Hera 后端

Spring Boot 后端,提供微信小程序登录、手机号验证码绑定、用户资料、协议和关注我们接口。

命理计算使用 cn.6tail:lunar 根据公历生日和时辰生成四柱八字,再计算五行分布、日主、喜用和忌用。

元宝页提供今日卡牌和每日生活小贴士接口。

本地启动

export WECHAT_APP_ID=wxa76a2ef9e8ba612e
export WECHAT_APP_SECRET='set-via-environment'
export DB_URL='jdbc:mysql://101.43.139.56:3306/hera?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true'
export DB_USERNAME=hera_user
export DB_PASSWORD='请通过部署环境配置'
mvn spring-boot:run

默认地址:http://localhost:8080

本机敏感配置可放在仓库根目录的 .hera-local.yml,使用与 application.yml 相同的 YAML 层级。后端从项目根目录启动时会自动加载,此文件已加入 Git 忽略清单;服务器使用环境变量配置。

Redis

使用 Spring Data Redis 和 Lettuce,依赖版本由 Spring Boot 2.7.18 管理。 默认地址为 101.43.139.56:6379,逻辑库为 0,连接与命令超时均为 3 秒。 支持 REDIS_HOST、REDIS_PORT、REDIS_USERNAME、REDIS_PASSWORD、REDIS_DATABASE、 REDIS_SSL 环境变量;本机密码配置在被 Git 忽略的 .hera-local.yml 中。

业务代码可注入 StringRedisTemplate。Key、Value 和 Hash 均采用字符串序列化; 结构化数据使用现有 ObjectMapper 显式转换为 JSON。建议 Key 使用 hera:{业务}: 前缀, 缓存和临时数据写入时必须指定合理的 TTL。当前接入连接能力,登录会话、mock 短信验证码 仍由现有 MySQL 链路保存,未启用用户资料自动缓存。

mvn test 包含不访问真实 Redis 的配置测试。 mvn test -Dtest=RedisIntegrationTest -Dhera.redis.integration=true 显式验证真实连接、 认证、PING、字符串读写与 TTL,使用 hera:test:redis:{随机值} 测试键并在结束后删除, 不清空 Redis。该测试独立于 MySQL,不执行用户表迁移。

腾讯云 COS 文件存储

存储桶为 hera-1319913268,地域为 ap-beijing,桶权限保持私有读。 运行环境必须配置 TENCENT_COS_SECRET_ID、TENCENT_COS_SECRET_KEY。 推荐仅授权该桶 hera/avatar/*、hera/files/* 路径的 cos:PutObject、cos:GetObject 权限。 密钥不写入配置文件或 Git。未配置密钥时允许服务启动,文件操作会返回配置错误。

  • POST /api/user/avatar:上传 JPG、PNG、WebP 头像,最大 5MB。
  • POST /api/files:通过 multipart 字段 file 上传普通文件,最大 5MB。
  • GET /api/files/url?reference=cos%3A%2F%2Fhera%2Ffiles%2F...:为本人文件续签。

所有上述接口需要 Bearer JWT。对象分别存储在 hera/avatar/{userId}/、 hera/files/{userId}/,数据库保存 cos:// 对象标识;不要保存临时签名 URL。 资料查询返回的头像 URL 和文件上传返回的 URL 有效期为 900 秒;过期后重新获取。 历史 /uploads/avatars/ 路径继续按原有本地静态资源配置访问,旧文件没有自动迁移。

访问入口默认使用 http://101.43.139.56/file/access?token=...,Nginx 保留路径和查询参数 转发至后端;参考 deploy/nginx-file.conf.example。后端校验文件专用短期凭证后, 302 跳转至 COS 官方 HTTPS 签名 URL。入口不要求登录头,必须携带有效文件凭证。 文件链接属于临时访问凭据,不应写入日志或分享给无权访问的人。 部署时通过 HERA_JWT_SECRET 配置随机签名密钥,并通过 TENCENT_COS_PUBLIC_BASE_URL 配置生产 HTTPS 域名下的 /file/ 地址。小程序需配置入口和跳转目标的 HTTPS 合法域名。 当前 HTTP IP 地址供联调使用,不满足正式小程序的 HTTPS 域名要求。

COS 验证

mvn test 执行本地签名、目录归属和模拟上传测试,不访问真实 COS。 mvn test -Dhera.cos.integration=true 额外启用真实 COS 联调:从运行配置读取密钥, 在 hera/avatar/9223372036854775807/ 和 hera/files/9223372036854775807/ 创建本次随机命名的测试对象,校验匿名访问为 403、签名下载内容一致,以及后端文件入口的跳转。 测试结束后删除本次创建的对象,因此联调账号还需要这两个测试目录的 cos:DeleteObject 权限。 此测试不会操作数据库,也不会验证远端 Nginx 是否已部署。

开发说明

  • 当前已默认关闭微信 mock,并接入微信 jscode2session。
  • 数据持久层使用 MyBatis Mapper XML,首次启动会执行 schema.sql 创建缺失的数据表。
  • 数据库连接默认指向 101.43.139.56:3306/hera,生产部署建议通过 DB_URL、DB_USERNAME、DB_PASSWORD 覆盖。
  • WECHAT_APP_SECRET 请优先使用服务器环境变量配置,不建议提交到公开仓库。
  • /api/auth/sms 开发阶段返回 mockCode,接入短信厂商后移除返回值。
  • 正式上线前需要替换 hera.jwt-secret、短信服务实现和协议正文。

数据表 CRUD

小程序用户业务已统一到 user_account 与 user_profile:微信身份、昵称和手机号 保存在账号表;性别、生日、出生时辰、头像、现居住地区与资料修改额度保存在资料表。 User 仅作为联合查询模型;业务接口不再读写 hera_user。

当前系统尚未上线,以当前数据库与 schema.sql 为准,不执行历史用户迁移、 启动时补列或修改旧表结构,也不读取或维护历史迁移版本表。 schema.sql 仅通过 CREATE TABLE IF NOT EXISTS 初始化缺失的当前业务表; 已有表结构若发生变化,应先更新代码与建表定义,不自动兼容历史结构。 纯微信账号的 password_hash 可空;资料修改周期为首次修改起六个月,最多五次。 历史迁移源码与对应测试已移除,但本次清理不会删除数据库中已有的表或记录。

POST /api/auth/wx-login 对已绑定手机号的用户额外返回 token 和 user;未绑定时, 继续通过 sessionKey 和 mock 短信验证码调用 /api/auth/bind-phone 完成注册或绑定。 绑定成功会核销会话与验证码。禁用账号不能登录或使用个人资料接口。 个人资料接口的字段名保持不变;资料尚未填写时,生日、时辰及五行报告可能为空,不填充虚构资料。

原 /api/data/** 通用 CRUD 控制器已撤下,避免普通登录用户改写设备归属、资产、 账号状态或他人资料。Mapper 与内部 CRUD Service 保留,不作为小程序 HTTP 接口。 账号注册和资料修改继续使用 /api/auth/** 与 /api/user/profile,尚未提供管理员接口。

NFC 与虚拟物

全部接口需要 Authorization: Bearer <token>,用户身份取 JWT,不接收操作者用户 ID。 列表接受 offset=0&limit=20,单页最大 100。芯片和虚拟物字典由可信后台或数据库预先入库, 不允许小程序自行注册硬件、指定设备奖励或修改流水。

代码以现库结构为准:绑定流水通过 nfc_uid 关联设备,芯片不再使用 last_login_at。 nfc_chip.sn 为设备序列号,按现库定义使用 VARCHAR(64) NOT NULL,无默认值、无唯一索引。 硬件入库和更新时必须提供 SN;扫描、绑定及本人设备列表返回 sn,客户端不能通过绑定请求修改它。 设备归属和绑定历史仍以唯一 UID 关联,不将 SN 当作唯一标识或绑定凭证。 新库由 schema.sql 创建该字段;旧库若尚未新增,应使用真实序列号补录已有设备后再设置非空约束, 不自动生成序列号或用 UID 代填,本服务不在启动时自动修改已有表。 旧库如缺少芯片归属、解绑额度或绑定流水表,可先备份,再手工执行 src/main/resources/db/nfc-schema-update.sql;该脚本不由应用自动执行。新库由 schema.sql 建表。 若已有同名表但字段结构不同,部署前应核对,不会通过删表自动适配。

  • POST /api/nfc/scan:{"uid":"设备UID"},查看绑定状态,不返回他人身份或 NDEF。
  • POST /api/nfc/bind:同上,绑定设备、写绑定流水、激活预置虚拟物,整体事务提交。
  • POST /api/nfc/unbind:同上,解绑本人设备并写解绑时间。
  • GET /api/nfc/devices:本人当前设备。
  • GET /api/nfc/bindings:本人绑定与解绑历史。
  • GET /api/virtual-items:启用的虚拟物字典,按字典排序。
  • GET /api/user/virtual-items:本人资产,含失效与送神状态。
  • GET /api/user/virtual-items/{id}:本人持有关系详情。
  • PUT /api/user/virtual-items/sort:{"ids":[持有关系ID,...]},按提交顺序设置排序值。
  • POST /api/user/virtual-items/offerings:{"userVirtualItemId":1,"offeringType":3,"content":"祈愿"}。
  • GET /api/user/virtual-items/offerings?holdingId=1:本人供奉记录,holdingId 可省略。
  • POST /api/user/virtual-items/transfers:{"userVirtualItemId":1,"toUserId":2,"content":"祝福"}。
  • GET /api/user/virtual-items/transfers:本人发出或收到的回向记录。

一个芯片仅允许一个当前用户,一个微信用户可以绑定多个芯片;要求有效账号已绑定微信和手机号。 重复绑定本人设备只刷新更新时间,不增加绑定次数,也不重复发放资产。 每台芯片按北京时间自然年最多解绑两次,次数跟随芯片,不因换用户而重置,跨年重新计算。

同类虚拟物在一个用户下只有一条资产记录,保留首次获得的 nfc_uid 和获得时间。 绑定新设备可恢复该类失效资产。解绑最后一台提供该类虚拟物的设备后,资产状态置为 3(失效), 不删除供奉和回向历史;仍有同类设备时保留资产。失效资产不能互动或直接请神,必须重新绑定。 供奉类型 1 请神、2 上香、3 祈愿、4 功德、5 送神。绑定激活自动记录请神; 送神置状态 0,保有对应设备时可通过请神恢复为 1。重复请神、重复送神会拒绝。 只有功德请求可填写 meritValue,要求 1 至 1000000,仅作互动记录,不代表积分、支付或余额。

回向只写记录,不创建接收方资产、不扣除发起方资产,也不把发起方状态改为已回向。 昵称快照从账号表生成;接收方原本有同类资产时保存其关系 ID,没有则为 null。 记录不开放通用修改和删除。UID 校验仅确认已入库设备,不具备防复制能力; 若产品需要防克隆,须增加硬件挑战响应或服务端签发的激活凭证,不能将普通 UID 当作秘密。

NfcWorkflowTest 在独立 H2 MySQL 模式测试库验证真实 Mapper XML、HTTP、事务与并发抢绑, 覆盖解绑上限、跨年、同类多设备、失效恢复、越权、供奉和只记账回向,不访问线上业务数据。 mvn test -Dtest=NfcMySqlIntegrationTest -Dhera.nfc.mysql.integration=true 显式检查现库列名, 通过只读、零行查询验证 XML 与现表兼容,再在七张连接级临时表中验证读写与回滚。 临时表创建成功并全部覆盖后才允许测试写入;结束时回滚并关闭连接自动清理, 不修改正式表结构和业务记录。测试账号需有 CREATE TEMPORARY TABLES 权限。

S
Description
No description provided
Readme
365 KiB
0 Stars 2 Watchers 0 Forks
Languages
Java 100%