Files
break ba0855d9eb feat(退款): AUG26-006 退款方式选择与原路退款
按 PRD 2.3/2.4/2.5 落地套餐退款的方式矩阵与原路渠道退款:

- 退款申请派生并冻结权威实收金额(线上取原成功支付记录,钱包/线下取订单实际收款),
  提交人不可填写或修改;按来源支付方式生成可选方式矩阵并在创建、提交、执行前重复校验。
- 审批切换为「每次提交一条不可变审批尝试记录 + 独立企业微信审批实例」,业务标识取尝试
  记录主键;终态消费按尝试记录优先、退款申请兜底双读,兼容存量无实例与已关联实例申请。
  新增活动退款部分唯一索引 (order_id) WHERE status IN (1,5,6)。
- 本地人工终审保持既有开关,补齐通过入口的 approval_instance_id IS NULL 守卫,使三个
  入口一致拒绝已关联审批实例的申请;重提按尝试模式重写(仅已拒绝/已退回/原路失败且无异常)。
- 权益时点:企微通过事务写退款终态、按方式确定的订单态、钱包回款、员工账单冲销与可靠
  失效事实;套餐失效/接续/停机仍由既有可靠机制最终一致执行,不把外部调用放入资金事务。
  订单支付状态按方式置位:凭证退款与退回原钱包在企微通过时置已退款,原路须渠道明确成功。
- 按官方契约实现微信直连 v3、微信 v2(双向证书)、富友(/commonRefund 与 /refundQuery)、
  支付宝四类原路退款;能力只由服务商类型与退款必需凭证完整性决定,无人工开关。
  渠道请求号在提交时冻结到尝试记录,并以 channel_submitted_at 条件认领保证资金动作至多
  提交一次(重复投递只查询不二次提交);不向任何渠道传递退款结果通知地址。
- 新增 refund:channel:recovery 恢复任务只查询回填;本地查询窗口超期(富友 72 小时、
  微信 v2 7 天)转原路退款失败、渠道状态已失败、分类超时未知并置异常转人工,不放行自动
  重提以避免重复退款。
- 同步退款 DTO/导出/审计资源与审计查询关联、商户凭证文档,并修正 fuiou 集成契约文档。

迁移 000218(退款尝试与渠道退款事实)、000219(微信 v2 客户端证书凭证)成对提供,
未修改既有迁移;测试库 junhong_cmp_test 完成 up/down/up 与行为核对,未调用真实渠道。
2026-09-14 11:55:16 +08:00
..

富友接入契约

元数据

  • Owner支付适配维护人
  • 实现:pkg/fuiou/
  • 核验日期2026-08-07
  • 来源:当前代码和商户接口约定;仓库未保存可公开的版本号

当前实际使用范围

系统使用微信预下单 POST <ApiURL>/wxPreCreate、主扫统一下单 POST <ApiURL>/preCreate 与支付通知;代理在线充值恢复流程另有本地 CommonQuery 调用,用于主动查询支付订单状态。交易类型为 JSAPI(公众号)或 LETPAY(小程序),主扫下单的订单类型为 WECHATALIPAY;本地 CommonQuery 代码保持现有请求格式、签名算法、状态映射和恢复语义不变。该源码事实仅表示本地候选实现及后续双读配置来源改造接缝,不证明真实富友渠道契约,也不证明验签、状态解释或恢复核验已通过。

原路退款

退款申请 POST <ApiURL>/commonRefund,必填 versionins_cdmchnt_cdterm_idmchnt_order_norandom_strsignorder_typerefund_order_nototal_amtrefund_amt;选填 operator_idreserved_fy_term_idreserved_origi_dtreserved_addn_infreserved_refund_desc。响应 result_code=000000 表示渠道受理成功,此时取 refund_id(富友退款流水号)、transaction_idreserved_refund_amt(退款金额,分)、reserved_fy_settle_dt(清算日期)。reserved 开头字段随报文发出但不参与签名。

退款查询 POST <ApiURL>/refundQuery,入参为 refund_order_no;响应 trans_stat 取值为 SUCCESS(退款成功)或 PAYERROR(退款失败),未返回该字段表示仍在办理中。

全局约束:mchnt_order_norefund_order_no 均为全局永久唯一,重复提交会被直接拒绝;商户退款单号格式为「机构码(4 位) + 日期(yyyyMMdd) + 随机段(818 位字母数字)」,本系统按该规则生成,三渠道共用同一生成器;接口支持全额退款与多次部分退款。

原交易日期决定可退时限:不传 reserved_origi_dt 仅支持 30 天内的原交易,传了可退 360 天内的原交易。本系统始终回传原支付成功时间,因此按 360 天判定可退性,超出该时限的申请在选择退款方式阶段即禁用原路。

退款查询接口只支持查询 3 日内的退款交易。超出该窗口且结果仍未知时,系统保留原路退款处理中状态、标记审批异常并转人工核对,绝不重复发起退款。

配置、认证与传输

运行配置包含 API 地址、机构号、商户号、终端号、RSA 私钥、公钥及通知地址。请求先生成 XML再转换为 GBK并对请求参数做双重 URL 编码;请求和响应使用 RSA 签名/验签。除 reserved 外的请求字段即使为空也参与 XML 与签名。

关键支付请求字段包括 mchnt_order_noorder_amt(分)、txn_begin_tsnotify_urltrade_typesub_openidsub_appid。响应 result_code=000000 表示渠道成功,并返回富友流水号和 JSAPI 支付字段。

幂等、失败与重试

mchnt_order_no 是渠道业务幂等键,退款侧对应 refund_order_no;通知处理还需校验签名、商户订单号、金额及当前支付状态。非 000000、验签失败、解码失败或字段不匹配均不得推进支付状态。客户端未实现自动重试,调用方只有在可确认沿用同一商户订单号时才可重试。

退款调用以冻结在审批尝试记录上的渠道退款请求号作为幂等标识:同一次尝试的渠道重试复用同一请求号,重提会生成新请求号。结果未知时只由查询恢复回填,不得重复发起资金动作。

安全与验证

RSA 私钥、公钥、机构和商户凭证不得进入文档或普通日志;通知日志必须脱敏。可复现静态证据:pkg/fuiou/client.gopkg/fuiou/wxprecreate.gopkg/fuiou/scan.gopkg/fuiou/refund.gopkg/fuiou/types.gointernal/handler/callback/payment.gointernal/infrastructure/payment/fuiou_scan.gointernal/infrastructure/payment/refund_adapter.go

本文按官方契约记录退款接口,未做真实渠道实测:未实测只作记录,不作为阻塞、未完成任务或上线前置;真实渠道可退款性由维护者后续手工验证。真实验收需使用隔离商户验证两种交易类型、签名失败、金额不符、重复通知、退款受理与退款查询;本次不调用真实渠道。

端点、编码、签名字段、成功码、退款字段或通知语义变化时更新本文。