支付相关
This commit is contained in:
+60
-22
@@ -47,15 +47,16 @@ provider,因此渠道族仍然是九个,而不是把微信重复计算成两
|
||||
|
||||
| GoPay 渠道族 | 本地 provider | 当前适配的 GoPay 能力 | 回调/退款边界 |
|
||||
| --- | --- | --- | --- |
|
||||
| Alipay | `alipay` | `TradeCreate`、`TradePrecreate`、`TradeAppPay`、`TradePagePay`、`TradeWapPay`、查单、退款、通知验签 | 支持服务端验签后主动查单 |
|
||||
| WeChat | `wechat-v2`、`wechat-v3` | v2 `UnifiedOrder`/`QueryOrder`/`Refund`;v3 JSAPI、App、Native、H5 下单、查单、退款、通知验签/解密 | v2 使用商户密钥;v3 使用平台证书和 API v3 key |
|
||||
| Alipay(旧网关协议) | `alipay` | `TradeCreate`、`TradePay`、`TradePrecreate`、`TradeAppPay`、`TradePagePay`、`TradeWapPay`、查单、退款、通知验签 | 支持服务端验签后主动查单 |
|
||||
| Alipay V3 | `alipay-v3` | GoPay V3 `TradeCreate`、`TradePay`、`TradePrecreate`、`TradeAppPay`、`TradePagePay`、`TradeWapPay`、查单、退款、证书响应验签、通知证书验签 | 必须配置应用公钥证书、支付宝根证书和支付宝公钥证书;确认仍以主动查单为准 |
|
||||
| WeChat | `wechat-v2`、`wechat-v3` | v2 `UnifiedOrder`/`Micropay`/`QueryOrder`/`Refund`;v3 JSAPI、App、Native、H5、CodePay 付款码下单、查单、退款、通知验签/解密 | v2 使用商户密钥;v3 使用平台证书和 API v3 key |
|
||||
| Apple | `apple-iap` | App Store Server API 交易查询、JWS/证书链处理 | 下单由客户端 StoreKit 驱动;服务端不提供主动退款 |
|
||||
| PayPal | `paypal` | `CreateOrder`、`OrderDetail`、`PaymentCaptureRefund`、Webhook 验签 | 退款需要已持久化的 capture ID |
|
||||
| PayPal | `paypal` | `CreateOrder`、`OrderDetail`、`OrderCapture`、`PaymentCaptureRefund`、Webhook 验签 | 买家批准后由查单链路捕获;退款需要已持久化的 capture ID |
|
||||
| Douyin | `douyin` | App、JSAPI、H5、Native 下单,按商户订单号查单、退款、通知验签和解密 | 平台证书必须配置 |
|
||||
| QQ | `qq` | `UnifiedOrder`、`OrderQuery`、`Refund`、通知解析和验签 | 退款需要商户证书、私钥或 PKCS#12 |
|
||||
| AllinPay | `allinpay` | `Pay`、`Query`、`Refund` | 当前不接收通知;使用主动查单/对账确认 |
|
||||
| Lakala | `lakala` | `Pay`、`OrderStatus`、`Refund`、通知解析和验签 | 回调字段以 GoPay 返回模型为准 |
|
||||
| Saobei | `saobei` | `Pay`、`Query`、`Refund` | 当前不接收通知;使用主动查单/对账确认 |
|
||||
| AllinPay | `allinpay` | `Pay`、`ScanPay`、`NativePay`、`Query`、`Refund` | 当前不接收通知;使用主动查单/对账确认 |
|
||||
| Lakala | `lakala` | JSAPI、H5、小程序、Native/二维码、Native JSAPI、SDK、Web Gateway、线下条码/二维码下单,`OrderStatus`、`Refund`、通知解析和验签 | 回调字段以 GoPay 返回模型为准 |
|
||||
| Saobei | `saobei` | `MiniPay`、`BarcodePay`、`Query`、`Refund` | 当前不接收通知;使用主动查单/对账确认 |
|
||||
|
||||
`CMB`(招商银行)不在固定的 v1.5.122 模块中,不能作为本分支已接入渠道;
|
||||
上游未发布版本中的目录或提交不构成稳定依赖,故这里明确排除。
|
||||
@@ -68,11 +69,16 @@ AllinPay 和 Saobei 的 adapter 会拒绝回调入口,因为固定版本没有
|
||||
当前仓库仅做单元测试和本地 mock/HTTP 响应验证;上线前仍须使用实际商户凭证、
|
||||
证书、平台回调和退款报文逐项联调。
|
||||
|
||||
统一 adapter 面向普通商户的核心下单、查单、退款和回调流程。微信服务商/合单、
|
||||
PayPal `AUTHORIZE` 意图后的授权捕获,以及账单、分账、转账等能力需要不同的业务
|
||||
状态机和持久化字段,不能仅靠透传 `extra` 安全接入;这些扩展应按实际业务合同
|
||||
单独建模,不属于“稳定渠道族已接入”的含义。
|
||||
|
||||
## 其他已保留渠道
|
||||
|
||||
| Provider | 实现方式 |
|
||||
| --- | --- |
|
||||
| `alipay`、`wechat-v2`、`wechat-v3`、`apple-iap`、`paypal`、`douyin`、`qq`、`allinpay`、`lakala`、`saobei` | 统一走上面的 GoPay v1.5.122 adapter;业务层只接收 `biz.PaymentResult` |
|
||||
| `alipay`、`alipay-v3`、`wechat-v2`、`wechat-v3`、`apple-iap`、`paypal`、`douyin`、`qq`、`allinpay`、`lakala`、`saobei` | 统一走上面的 GoPay v1.5.122 adapter;业务层只接收 `biz.PaymentResult` |
|
||||
| `chinaums` | 配置驱动的银联商务 JSON 签名适配器 |
|
||||
| `sft` | 配置驱动的商福通 JSON/MD5 适配器 |
|
||||
| `supper-pay` | 配置驱动的 Supper Pay HMAC 适配器 |
|
||||
@@ -181,7 +187,7 @@ if err := paymentUsecase.RegisterBusinessModule(GameItemPayment{orders: gameOrde
|
||||
- 平台确认:只有验签后的主动查单结果可以把订单推进到 `paid`,状态不会从已支付回退到待支付或失败。
|
||||
- 多实例发货:数据库行锁、处理令牌和租约保证同一时刻只有一个实例执行发货。
|
||||
- 最终发货幂等:业务模块必须在自己的事务中对 `confirmation_id` 建唯一约束。
|
||||
- 退款:一次只允许一个在途退款;每次退款都有持久化 `refund_no`,网络超时会复用同一个退款号重试,平台接受退款后状态为 `pending`,只有携带匹配 `refund_no` 的退款通知或对账任务调用 `ConfirmRefund` 后才增加 `refunded_amount`。
|
||||
- 退款:一次只允许一个在途退款;每次退款都有持久化 `refund_no`,网络超时会复用同一个退款号重试。渠道响应提供退款号回显时,adapter 必须校验其与本地 `refund_no` 一致,并要求独立的平台退款号非空;平台接受退款后状态为 `pending`,只有携带匹配 `refund_no` 的退款通知或对账任务调用 `ConfirmRefund` 后才增加 `refunded_amount`。
|
||||
- 退款授权:业务模块必须实现 `AuthorizeRefund`,支付模块不会仅凭渠道、订单号和金额执行退款。
|
||||
- 外部平台调用和本地数据库无法组成单个 ACID 事务,因此采用“本地先落单、平台接口幂等重试、主动查单、数据库状态机、业务最终幂等”的组合保证最终一致性。
|
||||
|
||||
@@ -193,8 +199,24 @@ if err := paymentUsecase.RegisterBusinessModule(GameItemPayment{orders: gameOrde
|
||||
{"app_id":"","private_key":"PEM","public_key":"PEM","environment":"production","sign_type":"RSA2","gateway_url":"https://openapi.alipay.com/gateway.do","method":"alipay.trade.create"}
|
||||
```
|
||||
|
||||
`method` 可选 `alipay.trade.create`、`alipay.trade.precreate`、
|
||||
`method` 可选 `alipay.trade.create`、`alipay.trade.pay`、`alipay.trade.precreate`、
|
||||
`alipay.trade.app.pay`、`alipay.trade.page.pay` 或 `alipay.trade.wap.pay`。
|
||||
付款码支付可使用 `barcode` / `micropay` 别名,并在订单 `extra.auth_code` 中传入付款码。
|
||||
|
||||
支付宝 V3:
|
||||
|
||||
```json
|
||||
{"app_id":"","private_key":"PEM","app_cert":"PEM 或文件路径","root_cert":"PEM 或文件路径","public_cert":"PEM 或文件路径","environment":"production","api_base_url":"https://openapi.alipay.com","gateway_url":"https://openapi.alipay.com/gateway.do","method":"alipay.trade.create"}
|
||||
```
|
||||
|
||||
`alipay-v3` 独立于旧 `alipay` provider。`app_cert`、`root_cert` 和 `public_cert`
|
||||
分别对应 GoPay `ClientV3.SetCert` 的应用公钥证书、支付宝根证书和支付宝公钥证书;
|
||||
也可使用 `*_content` / `*_path` 以及 `alipay_root_cert*`、`alipay_public_cert*`
|
||||
兼容别名。V3 HTTP 接口使用 `api_base_url`(测试代理可指向本地 mock),页面/APP
|
||||
调起参数使用 GoPay 已封装的 `TradeAppPay`、`TradePagePay` 和 `TradeWapPay`;
|
||||
`method` 支持 `alipay.trade.create`、`alipay.trade.pay`、`alipay.trade.precreate`、
|
||||
`alipay.trade.app.pay`、`alipay.trade.page.pay` 和 `alipay.trade.wap.pay`。V3 的
|
||||
REST 响应只有在证书验签通过后才会进入业务层,通知回调同样使用 GoPay 的证书验签。
|
||||
|
||||
微信支付 v2:
|
||||
|
||||
@@ -204,7 +226,10 @@ if err := paymentUsecase.RegisterBusinessModule(GameItemPayment{orders: gameOrde
|
||||
|
||||
`client_cert` / `client_key` 在退款等双向 TLS 请求中使用;也接受
|
||||
`appid`、`mch_id`、`api_key` 等兼容别名。自定义测试端点可分别配置
|
||||
`create_url`、`query_url` 和 `refund_url`。
|
||||
`create_url`、`query_url` 和 `refund_url`。`trade_type` 支持 `JSAPI`、`APP`、
|
||||
`NATIVE`、`MWEB`;付款码支付可使用 `micropay` / `barcode` 别名,并在订单
|
||||
`extra.auth_code`(或渠道配置同名字段)传入付款码。未知下单方式会直接拒绝;
|
||||
付款码下单返回的平台交易号和金额会校验,客户端调起数据只保存在 `Payload`。
|
||||
|
||||
微信支付 v3:
|
||||
|
||||
@@ -212,8 +237,9 @@ if err := paymentUsecase.RegisterBusinessModule(GameItemPayment{orders: gameOrde
|
||||
{"app_id":"","merchant_id":"","serial_no":"","private_key":"PEM","api_v3_key":"32-byte key","platform_cert":"PEM","platform_serial_no":"","trade_type":"jsapi"}
|
||||
```
|
||||
|
||||
`trade_type` 支持 `jsapi`、`app`、`native` 和 `h5`;JSAPI/小程序下单还需
|
||||
在订单 `extra.openid` 中传入用户标识。
|
||||
`trade_type` 支持 `jsapi`、`app`、`native`、`h5` 和 `codepay` / `micropay`;
|
||||
JSAPI/小程序下单还需在订单 `extra.openid` 中传入用户标识,付款码支付则需在
|
||||
订单 `extra.auth_code` 中传入用户付款码(兼容 `authcode` / `barcode` 字段名)。
|
||||
|
||||
Apple 内购:
|
||||
|
||||
@@ -225,7 +251,8 @@ Apple Server API 的交易 `price` 使用平台返回的单位;`price_divisor`
|
||||
|
||||
Apple 多币种可使用 `price_divisors` 对不同 `currency` 分别配置比例;服务端不会把 Apple 的价格字段默认当作人民币分。
|
||||
|
||||
Apple 没有传统服务端“预下单”。创建接口要求 `tradeNo` 是 UUID,并把它作为 `appAccountToken` 返回给客户端;客户端发起 StoreKit 购买时必须原样传入。回调使用 `appAccountToken` 关联本地订单,使用 `transactionId` 调 Apple Server API 主动查单,两者不会混用。缺少 `appAccountToken`、Bundle ID 或环境不一致、JWS 算法不是 ES256、证书链校验失败时均拒绝确认。
|
||||
Apple 没有传统服务端“预下单”。创建接口要求 `tradeNo` 是 UUID,并把它作为 `appAccountToken` 返回给客户端;客户端发起 StoreKit 购买时必须原样传入。回调使用 `appAccountToken` 关联本地订单,使用 `transactionId` 调 Apple Server API 主动查单,两者不会混用。最终确认还会把签名载荷的 `productId` 与业务订单持久化的 `extra.product_id` 精确匹配;缺少 `appAccountToken`、Bundle ID、商品 ID 或环境不一致、JWS 算法不是 ES256、证书链校验失败时均拒绝确认。
|
||||
adapter 在调用 GoPay 解码前还会绑定 `x5c[0]` 叶子到 `x5c[1]`/`x5c[2]`,并检查 Apple App Store 签名证书扩展,避免仅凭叶子公钥验签。
|
||||
|
||||
Apple IAP 的购买流程由客户端发起,退款/撤销由 App Store 管理。本项目的
|
||||
`apple-iap` adapter 不提供商户服务端主动退款,业务侧应通过 Apple 的退款流程和
|
||||
@@ -237,8 +264,11 @@ PayPal:
|
||||
{"client_id":"","client_secret":"","webhook_id":"","environment":"sandbox","return_url":"https://merchant.example/paypal/return","cancel_url":"https://merchant.example/paypal/cancel","amount_scales":{"USD":"100","JPY":"1"}}
|
||||
```
|
||||
|
||||
生产回调验签必须配置 `webhook_id`。默认金额比例按 PayPal 币种处理,也可使用
|
||||
`amount_scales`/`currency_scales` 覆盖;退款需要订单状态中已持久化的 capture ID。
|
||||
启用 PayPal 配置必须提供 `webhook_id`,回调验签会将其传给 GoPay;默认金额比例按
|
||||
PayPal 币种处理,也可使用 `amount_scales`/`currency_scales` 覆盖。`CAPTURE` 意图的
|
||||
订单在买家批准后会由查单流程调用 GoPay `OrderCapture` 完成捕获,只有捕获成功才会
|
||||
进入支付成功和发货;可显式配置 `auto_capture=false` 关闭。退款需要订单状态中已
|
||||
持久化的 capture ID。
|
||||
|
||||
抖音支付:
|
||||
|
||||
@@ -247,7 +277,8 @@ PayPal:
|
||||
```
|
||||
|
||||
当前 adapter 支持 `app`、`jsapi`、`h5`、`native`;固定版本的抖音客户端按
|
||||
生产接口工作,`environment` 只能使用 `production`/`prod`。
|
||||
生产接口工作,`environment` 只能使用 `production`/`prod`。平台证书序列号也接受
|
||||
GoPay 模型使用的兼容字段 `platform_cert_serial`。
|
||||
|
||||
QQ 支付:
|
||||
|
||||
@@ -261,19 +292,25 @@ QQ 支付:
|
||||
通联支付(AllinPay):
|
||||
|
||||
```json
|
||||
{"cus_id":"","app_id":"","private_key":"PEM","public_key":"PEM","org_id":"","pay_type":"W02","currency":"CNY","environment":"production"}
|
||||
{"cus_id":"","app_id":"","private_key":"PEM","public_key":"PEM","org_id":"","pay_type":"W02","query_order_type":"reqsn","currency":"CNY","environment":"production"}
|
||||
```
|
||||
|
||||
该 provider 只接入下单、查单和退款,不接收通知;支付确认由主动查单/对账触发。
|
||||
`query_order_type` 只允许 `reqsn` 或 `trxid`,默认使用商户订单号 `reqsn`。
|
||||
选择 `trxid` 时,下单响应必须返回交易号并将其持久化为后续查单、退款标识;
|
||||
Native 下单不会返回该标识,因此不能与 `trxid` 模式组合。该 provider 只接入
|
||||
下单、查单和退款,不接收通知;支付确认由主动查单/对账触发。
|
||||
|
||||
拉卡拉(Lakala):
|
||||
|
||||
```json
|
||||
{"partner_code":"","credential_code":"","channel":"Wechat","currency":"JPY","environment":"production"}
|
||||
{"partner_code":"","credential_code":"","channel":"Wechat","method":"jsapi","currency":"JPY","environment":"production"}
|
||||
```
|
||||
|
||||
支持 JSAPI/H5 下单、查单、退款和 GoPay 通知验签。当前固定版本客户端只允许
|
||||
生产环境配置。
|
||||
`method` 支持 `jsapi`、`h5`、`mini`、`native`、`qrcode`、`native_jsapi`、
|
||||
`sdk`、`web`、`retail` 和 `retail_qrcode`,并映射到 GoPay v1.5.122 对应的
|
||||
创建方法;未知值会直接拒绝。下单响应中的 `order_id` 是持久化查单键,二维码、
|
||||
跳转 URL 和 SDK 参数只放在创建结果 `Payload`。支持查单、退款和 GoPay 通知验签。
|
||||
当前固定版本客户端只允许生产环境配置。
|
||||
|
||||
扫呗(Saobei):
|
||||
|
||||
@@ -282,7 +319,8 @@ QQ 支付:
|
||||
```
|
||||
|
||||
该 provider 只接入条码/小程序下单、查单和退款,不接收通知;支付确认由主动
|
||||
查单/对账触发。
|
||||
查单/对账触发。条码支付在订单 `extra.auth_no` 中传入付款码,也兼容
|
||||
`auth_code`、`authcode`、`barcode` 和 `pay_code` 字段名。
|
||||
|
||||
非 GoPay 的配置驱动聚合/小游戏渠道最少需要:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user