Appearance
安心支付技术链路与排障
本页面向开发和运维,记录支付宝安心生活、外部桥接服务、金刚后端、云平台和易宝之间的接口、数据、幂等与异常边界。接口密钥、企业微信机器人密钥、证书和数据库口令只保存在受控配置中,不进入知识库。
系统边界
text
支付宝安心生活
-> 外部桥接服务 orther_api.py
-> storeapi 外部需求接口
-> jingangdata 家政人广场和订单
-> storeui 员工履约
-> 外部桥接服务调用支付宝履约/核销/取消
-> 支付宝核销通知
-> storeapi 员工钱包
-> storeui 员工申请提现
-> yunui/yunapi 财务审核
-> storeapi 预检并调用易宝直接分账外部桥接服务还把支付宝原始通知写入 SQL Server;金刚业务数据和员工钱包位于 jingangdata MySQL。
接口清单
| 系统 | 方法与路径 | 作用 |
|---|---|---|
| 外部桥接 | POST /axzf | 接收支付宝预约、订单和核销扣款通知,验签后转发金刚 |
| 外部桥接 | POST /axzf_cancel | 调用支付宝预约同步,动作支持 fulfill 和 cancel |
| 外部桥接 | POST /axzf_hx | 调用支付宝核销使用接口 |
| 外部桥接 | POST /axzf_hx_cancel | 对已核销扣款单执行退款 |
storeapi | POST /api/v1/external/demand/publish | 接收预约,创建或取消安心需求 |
storeapi | POST /api/v1/external/demand/hx_notify | 保存核销扣款单并推进安心钱包入账 |
storeapi | POST /api/v1/demand-square/grab | 门店人工抢单并创建金刚订单 |
storeapi | POST /api/v1/order/cancelOrder | 金刚门店端取消,按核销事实分流渠道操作 |
storeapi | POST /api/v1/staff-order/startService | 状态 50 -> 60,事务提交后同步 fulfill |
storeapi | POST /api/v1/staff-order/endService | 状态 60 -> 80,判断钱包条件并在提交后发起核销 |
storeapi | GET/POST /api/v1/staff-wallet/* | 员工钱包总览、流水、提现记录和提现申请 |
yunapi | GET /merchant/standard-staff/withdrawals | 财务查询提现单及关联订单收入 |
yunapi | POST /merchant/standard-staff/withdrawals/{no}/review | 代理调用金刚内部审核和易宝打款 |
storeapi | POST /api/v1/internal/standard-order-ops/withdrawals/{no}/review | 余额预检、审核、提交易宝和返回结果 |
yunui 普通订单页使用的是 PUT /order/cancel/{ids}。该接口在 yunapi 中直接更新订单状态,不会调用上表中的安心渠道取消逻辑。
通知解析和 SQL Server 日志
orther_api.py 的 /axzf 支持:
| 支付宝消息方法 | 处理 |
|---|---|
| 预约或安心订单通知 | 解析预约信息并调用金刚放单 |
| 核销扣款单通知 | 提取 card_id、deduction_order_id、open_id 并调用金刚核销通知 |
| 其他消息 | 记录后返回成功,不进入放单 |
SQL Server dbo.AlipayAxzfNotifyLog 保存通知 ID、消息方法、预约单号、安心订单 ID、服务 ID、用户、支付宝门店、门店名称、预约状态、扣款状态、核销卡 ID、扣款单号、验签结果、处理状态、业务原文、表单原文、通知次数和时间。
幂等规则:
- 同一
NotifyId更新原记录并增加通知次数。 - 同一非空
OrderId已有日志时不再插入第二条日志。 shop_id通过 SQL Serveralipay_shop补shop_name。- 日志去重不替代金刚业务去重;重复请求仍由金刚按预约和安心订单 ID 返回幂等成功。
扩展属性脚本重复执行出现 MS_Description already exists 只表示备注已经存在。后续维护脚本应先判断扩展属性是否存在,存在时使用更新,不应反复无条件新增。
放单和建单幂等
storeapi 放单采用两层检查:
| 键 | 规则 |
|---|---|
booking_id + source_platform | 已存在即返回原需求 |
安心 order_id | 状态为待抢或已抢的有效需求只允许一条 |
预约确认只写 demand_square 和 demand_channel_data。created_order_number 为空时,订单列表查不到是预期行为。
人工抢单和 30 分钟自动接单都会:
- 锁定待抢需求,防止并发抢单。
- 更新需求的抢单门店和人员。
- 创建客户、地址、金刚订单、支付记录和订单日志。
- 回写
created_order_number。 - 提交事务后发送企业微信机器人消息。
机器人地址从 ANXIN_LIFE_ORDER_WEBHOOK_URL 读取。代码中不得保存默认密钥;部署时通过受控环境变量注入并定期轮换。
30 分钟自动接单
主路径使用 Redis 过期键:放单成功写入 30 分钟 TTL,监听到期后调用自动接单任务。服务启动时会扫描仍在待抢的安心需求并重建计时器,超过 30 分钟的记录立即触发。
定时任务 AnxinLifeAutoGrabTask.run 也能扫描超时需求作为补偿。当前目标配置为交付用户和全国交付门店。修改目标时必须同时核对用户、门店主键、UUID 和名称,避免订单归属不一致。
履约和核销时序
开始服务
员工开始服务先更新本地状态和开工资料,提交后调用预约同步 fulfill。渠道失败只记录,不回滚状态。
结束服务
员工结束服务的顺序:
text
更新订单为 80
-> 完成档期和派发记录
-> 调用结算入口识别安心渠道
-> 无 deduction_order_id 时返回 WAITING_DEDUCTION
-> 提交本地事务
-> 调用 /axzf_hx 发起支付宝核销
-> 支付宝异步通知 /axzf
-> 转发 /hx_notify
-> 保存 deduction_order_id 并尝试钱包入账支付宝先通知核销时,hx_notify 保存核销数据并返回 WAITING_SERVICE_COMPLETION。本地服务完成后,结算入口再次调用同一个钱包入账函数。
钱包入账
核心表:
| 表 | 作用 |
|---|---|
demand_square | 需求状态、承接门店和金刚订单号 |
demand_channel_data | 预约、安心订单、支付宝门店、核销扣款单和渠道结果 |
order | 金刚履约主订单 |
order_waiter | 实际服务员工和安心佣金 service_personal |
staff_wallet_account | 员工钱包可用、冻结、累计收入和已提现 |
staff_wallet_ledger | 安心佣金和提现账本 |
staff_withdrawal_application | 提现审核和易宝打款状态 |
standard_order_settlement_task | 全国标准单任务;用于阻止安心订单重复走标准单分账 |
安心佣金幂等键为“金刚订单号 + 员工”。入账前检查是否已有成功的全国标准单易宝分账;已有成功记录时转人工,未成功的标准单任务则改为 ANXIN_WALLET/CANCELLED。
提现审核和易宝打款
员工申请提现时:
- 校验最低金额和易宝个人入网。
- 锁定钱包账户并检查可用余额。
- 限制同一员工只有一笔处理中申请。
- 可用余额转冻结余额,创建提现单和提现流水。
财务点击通过时:
preflight_withdrawal检查真实模式、二级开关、出账商户配置和迁移字段。- 解析员工
micro_staff易宝商户并检查可用状态。 - 查询出账商户可用余额,余额小于提现金额直接失败,且不修改审核或钱包状态。
- 预检通过后把提现单改为
APPROVED,再复用YeepayDivideService.apply_divide_balance_direct提交单笔分账。 - 易宝同步成功或异步回调成功后,调用钱包完成逻辑扣减冻结余额并改为
COMPLETED。 - 明确失败时保留失败原因并进入
MANUAL_REVIEW;网络异常按 5、15、60 分钟重试。
部署变量:
| 变量 | 作用 |
|---|---|
STANDARD_WITHDRAWAL_PAYOUT_MODE | 钱包提现运行模式 |
STANDARD_WITHDRAWAL_PAYOUT_LIVE_ENABLED | 真实打款二级开关 |
STANDARD_WITHDRAWAL_SOURCE_MERCHANT_NO | 平台出账商户号 |
STANDARD_ORDER_SETTLEMENT_MODE | 全国标准单服务奖金运行模式 |
STANDARD_ORDER_SETTLEMENT_LIVE_ENABLED | 全国标准单真实分账二级开关 |
钱包提现和全国标准单服务奖金是两套独立开关。配置了钱包提现真实打款,不会自动开启全国标准单服务奖金分账。
取消链路
storeapi 取消订单会在本地提交后查询安心渠道数据:
| 条件 | 外部调用 |
|---|---|
无 deduction_order_id | 预约同步 cancel |
有 deduction_order_id | 核销扣款单 REFUND |
当前实现中第三方调用失败不影响本地取消,必须以 demand_channel_data.callback_response 和支付宝最终状态做补偿对账。
支付宝主动发送 status=canceled 时:
- 待抢需求改为过期;
- 已抢需求改为取消,并尝试取消未完成金刚订单;
- 已完成需求拒绝自动取消;
- 已取消或过期请求幂等返回。
已知技术风险
| 风险 | 代码事实 | 建议 |
|---|---|---|
| 放单金额被固定为 199 | 外部请求包含金额,但需求服务当前固定 commission_amount=199.00 | 改为校验后的请求金额或产品映射金额,并补非 199 用例 |
| 云平台取消绕过渠道 | yunapi 只批量更新 order_status=99 | 代理调用 storeapi 取消服务,或对安心订单禁用该按钮 |
| 本地取消先于渠道结果 | storeapi 提交本地事务后调用支付宝 | 增加补偿任务和醒目的渠道失败状态 |
| 渠道回调失败不阻断履约 | 开始、完成和机器人通知均是提交后调用 | 增加失败任务扫描、告警和手工重试入口 |
| 桥接日志使用拼接 SQL | 依赖手工转义 | 改为 SQL Server 参数化执行,并为 NotifyId、OrderId 建唯一或过滤索引 |
| 机器人密钥存在代码默认值 | 密钥轮换和泄露风险 | 删除默认值,只允许受控环境变量配置 |
排障顺序
有预约但无需求
- 查 SQL Server 通知日志的验签、消息方法和原始业务内容。
- 查桥接服务转发结果。
- 查
booking_id或安心order_id是否已命中幂等。 - 查产品映射或生产测试数据拦截。
有需求但无金刚订单
- 查需求是否仍为待抢。
- 查
created_order_number是否为空。 - 查人工抢单事务和 Redis 自动接单计时器。
- 超过 30 分钟时查自动接单任务、交付目标配置和数据库锁结果。
服务完成但未入钱包
- 查金刚订单是否为
80/90。 - 查
deduction_order_id。 - 查
order_waiter.service_personal和员工手机号。 - 查安心佣金幂等流水。
- 查是否已有全国标准单成功分账导致人工复核。
提现通过但未到账
- 查提现单状态和
payout_status。 - 查预检是否通过及出账余额查询结果。
- 查易宝分账记录、请求号和回调。
PROCESSING等回调或补偿;MANUAL_REVIEW按最后错误处理。- 禁止直接把状态改为完成,也不要创建新的请求号重复打款。
代码定位
| 逻辑 | 文件 |
|---|---|
| 支付宝通知和四个桥接接口 | D:/python/mypython/公司工具/家姐培训创建订单/orther_api.py |
| 放单、抢单和外部取消 | storeapi/module_admin/service/demand_square_service.py |
| 自动接单 | storeapi/module_task/anxin_life_auto_grab_task.py、storeapi/module_admin/service/anxin_life_auto_grab_listener.py |
| 建单群通知 | storeapi/module_admin/service/anxin_life_order_notify_service.py |
| 渠道履约、核销和取消 | storeapi/module_admin/service/channel_callback_service.py |
| 员工履约 | storeapi/module_admin/service/staff_order_service.py |
| 安心佣金和钱包 | storeapi/module_admin/service/staff_wallet_service.py |
| 提现打款 | storeapi/module_admin/service/staff_withdrawal_payout_service.py |
| 云平台提现代理 | yunapi/module_admin/controller/standard_staff_controller.py |
| 云平台普通取消 | yunapi/module_admin/service/order_service.py |