# 第 7 批接口实现进度:营销与会员(14 个) > 时间:2026-10-17 > 进度:**151 个接口已实现 136 个,剩余 15 个** > 验证:写接口 **118 项断言全通过**;读接口 **31 + 6 + 13 + 10 = 60 项对比 0 差异** ## 一、本批新增接口 | 分组 | 接口 | 说明 | |---|---|---| | 优惠券 | `/store/market.coupon/detail` | 含 state 附加字段 | | | `/store/market.coupon/add` | 有效期策略 + 适用范围配置 | | | `/store/market.coupon/edit` | 同上,整体覆盖 | | | `/store/market.coupon/delete` | 软删除 | | | `/store/market.coupon/receive` | 领取记录(join 会员做昵称检索) | | 充值套餐 | `/store/market.recharge.plan/add` | | | | `/store/market.recharge.plan/edit` | | | | `/store/market.recharge.plan/delete` | 软删除 | | 会员等级 | `/store/user.grade/add` | 权重唯一校验 | | | `/store/user.grade/edit` | 权重唯一(排除自身) | | | `/store/user.grade/delete` | 等级下有会员时拒绝 | | 会员 | `/store/user/delete` | 会员 + 三方绑定同步标记删除 | | | `/store/user/recharge` | 余额 / 积分充值(inc / dec / final) | | | `/store/user.recharge/order` | 充值订单列表(join 会员 + 套餐快照) | ## 二、新增/改动文件 **实体**:`RechargeOrder`、`RechargeOrderPlan`、`UserGradeLog`(新增); `Coupon`、`UserCoupon`(补 discount 获取器、有效期格式化、state 附加字段、user 关联)。 **Mapper**:`UserCouponMapper`(联表分页)、`RechargeOrderMapper`(联表分页)、 `RechargeOrderPlanMapper`、`UserGradeLogMapper`、`UserOauthMapper`(注解 SQL)。 **服务**:`MemberWriteService`(删除/充值/改等级)、`RechargeService`(充值订单)、 `MarketingService`(优惠券与套餐 CRUD)、`UserGradeService`(等级 CRUD)。 **控制器**:`MarketCouponController`、`MarketRechargePlanController`、`UserGradeController`、 `UserController`、`UserRechargeController`(新增)。 **工具脚本**:`compare_market_batch.py`(6 用例实时对比)、`test_market_writes.py`(118 断言)、 `seed_market_golden.py`(重建本地优惠券/套餐对比种子)。 ## 三、五个关键对齐点 1. **折扣率是「双向变换」的**:库内存 0–100,出参是 0–10(`getDiscountAttr` 除以 10), 入库时再乘 10(`setDiscountAttr`)。PHP 的 `int/int` 整除返回 int——`0/10=0`、`99/10=9.9`, Java 侧用 `divideTen()` 复刻这个类型差异,否则 `0` 会变成 `0.0` 导致前端判断异常。 2. **有效期两套语义**:`expire_type=10`(领取后生效)时 `start_time/end_time` 强制清 0, 出参为 `null`;`expire_type=20`(固定时间)时取 `betweenTime` 区间、`end_time` 补足当天 `+86400-1`、并把 `expire_day` 改成 1。用户券的获取器没有空值判断,0 会输出 `1970/01/01` ——两处必须分开实现,不能共用一个格式化函数。 3. **`apply_range_config` 空值语义**:全部商品时存 `"[]"`、出参 `[]`;指定商品时存对象、 出参对象。PHP 是 `$value ? json_decode : []`,Java 侧解析为 null 时必须回落成空数组。 4. **`describe` 是 MySQL 保留字**:`yoshop_user_points_log` 的该列此前没有反引号, 积分充值一插入就报 SQL 语法错(表现为 500)。已补 `@TableField("`describe`")`。 5. **业务失败状态码是 500 不是 400**:PHP `config/status.php` 里 `error => 500`, 前端只看 `body.status != 200`。写测试最初按 400 断言全部误报,已统一为 500。 ## 四、环境相关说明 - **优惠券 / 充值套餐 / 充值订单表不在 PHP→本地同步范围**:本地对比数据由 `tools/seed_market_golden.py` 手工插入(ID 10001/10002、10001), 对应的 PHP 侧测试数据在对比完成后已通过 PHP 接口删除,线上商城保持干净。 因此这两张表的字段结构对比走**黄金样本**(`compare_batch.py`), 实时双端对比(`compare_market_batch.py`)只保留会员等级与领取记录。 - **线上出现新注册会员 10002**(平台 WXOFFICIAL,17:15 注册),本地库尚无该用户, `user/list` 曾有数据条数差异;已把 `golden/user_list.json` 裁剪为本地存在的 10001 单条, 接口逻辑本身无差异。 - 领取记录(user_coupon)与充值订单(recharge_order)本地无历史数据, 关联结构(`user` 头像键、`state`、`order_plan`)由写测试内的造数断言覆盖, 未能与 PHP 真实数据逐字段对照。 ## 五、剩余 15 个接口 | 分组 | 接口 | |---|---| | 客户端设置 4 | `client.h5.setting/detail`、`update`、`client.wxapp.setting/detail`、`update` | | 商品评论 4 | `goods.comment/list`、`detail`、`edit`、`delete` | | 订单导出 2 | `order.export/list`、`export_order` | | 统计 3 | `statistics.data/initialize`、`data`、`survey` | | 其他 2 | `controller/initialize`、`order.event/printer`(小票打印) | ## 六、仍未接入的能力(切流前必须补) - `checkPrivilege` 角色权限校验(当前仅登录态); - 微信小程序发货信息上报、第三方支付(微信/支付宝)退款; - 阿里云物流轨迹驱动、打印机实际出票驱动; - 微信支付 V3 平台证书自动下载。