开篇
连续包月-周期扣款-自动续费名字很多, 先简单解释这三个的意思:
- 支付宝官方定义的名称为-周期扣款
- 连续包月是这个模式常用的行为(也可以包天, 包季度),
- 自动续费是在用户的眼里行为, 可以不用手动付款
扣款场景
周期扣款有两种模式:
- 先签约后代扣场景
- 先跳转到签约页面
- 用户同意签约
- 支付宝签约异步回调 && 同步发起扣款
- 支付后签约场景
- 跳转到支付页面(用户可以手动关闭自动续费)
- 用户支付
- 收到两个异步通知, 支付通知 签约通知
- 支付后签约场景的模式虽然简单, 但是用户可以手动关闭续费, 所以很多时候我们选择先签约后代扣场景
申请信息
- 了解清楚基本逻辑之后, 就是要申请功能, 支付宝的可以参考此链接https://opendocs.alipay.com/open/20190319114403226822/intro
- 需要注意的是微信周期扣款申请比较复杂, 还需要申请一个额外的模板ID,
签约页面唤起逻辑
- 服务端根据
SDK
生成签名串(值的注意的https://github.com/go-pay/gopay这个包没有实现这个功能我提交了新功能并于2023-01-01
合并https://github.com/go-pay/gopay/pull/295)- 这个
SDK
虽然包含了client.UserAgreementPageSign()
方法, 但是这个方法实际上会请求支付宝返回一个H5
页面唤醒签约页面(但是这个只能给前端使用) - 如果是
APP
签约,我们不能请求支付宝, 必须本地签名 (这里很坑, 支付宝API
文档没写,需要在接入指南查看) - 官方提供
SDK
的代码示例如下(如果是PHP
,Java
,Node
可以直接用官方SDK
)
- 这个
AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do","app_id","your private_key","json","GBK","alipay_public_key","RSA2");
AlipayUserAgreementPageSignRequest request = new AlipayUserAgreementPageSignRequest();
request.setBizContent(参考上面的bizContent值);
//无线端唤起签约
//pageExecute get方式,生成url
AlipayUserAgreementPageSignResponse response = alipayClient.pageExecute(request,"get");
//生成的url地址去除http://openapi.alipay.com/gateway.do
signParams = response.replace("http://openapi.alipay.com/gateway.do?","");
//生成唤起客户端。把signParams使用 UTF-8 字符集整体做一次 encode
return 'alipays://platformapi/startapp?appId=60000157&appClearTop=false&startMultApp=YES&sign_params=' encode(signParams)
开发
- 由于我使用的是
Go
, 所以使用这个包 https://github.com/go-pay/gopay - 值的注意的是, 当前日期2022-12-29由于支付宝
V3
是还不支持周期扣款的, 所以我们需要用V2
- 首先基于表设计, 这边大致如下(省略部分)
id, no(订单号), tarde_no(商户订单号), user_id(用户), goods_id(商品), contract_code(自定义签约号), contract_id(商户签约号)
订单流程
- 用户下单连续包月产品时候, 创建订单, 订单包含一个随机的
contract_code
- 调用生成签约参数时, 把
contract_code
当做商户签约号参数生成唤醒签约页面链接签名 - 下发订单号
no
和支付宝唤醒签约页面链接给客户端, 客户端唤醒支付宝签约页面 - 签约成功之后,异步通知回调会把
contract_code
和contract_id
返回给我们(插入签约表) - 通过
contract_code
查找到订单, 然后调用支付接口alipay.trade.pay(同步调用),实时获取是否扣费成功 - 客户端返回的时候, 根据订单号
no
调用服务端, 如果订单未支付, 服务端再去主动扣款一次 - 增加定时任务, 定时查询签约表,找到五天内到期的调用同步支付接口
备注
- 微信连续包月提前两天扣款
- 比如
15
号签约, 那么应该13
号发起扣款,14
号是微信扣款等待期,15
号微信下发扣款通知(成功还是失败)
- 比如
- 支付宝连续包月提前五天扣款
- 比如
15
号签约, 那么可以10
号发起扣款
- 比如