本文将讲【解微信支付】“刷卡支付”、“被扫支付”开发JavaDemo
快速上手,使用SDK只需三步即可接入“被扫支付”
第一步,初始化SDK
1 | //-------------------------------------------------------------------- |
第二步,准备好提交给API的数据(scanPayReqData
)
1 | //-------------------------------------------------------------------- |
第三步,准备好一个用来处理各种结果分支的监听器(resultListener
)
1 | //-------------------------------------------------------------------- |
Demo简单说明
最佳实践
高级自定义
“被扫支付”高级知识
Demo包含的内容
Demo里面需要大家关注的主要有三个地方:
四个业务Demo,位于
src/main/java/com/tencent/business/
目录里面,这些demo将会教大家如何调用SDK里面封装好的业务逻辑。桥接器
bridge
,位于src/main/java/com/tencent/bridge/
目录里面。里面目前有4个bridge,分别对应4个业务demo。这个东西是用来对接商户系统逻辑,产生SDK请求所需要的特定参数用的,请大家按照API文档的说明实现这些参数的产生逻辑。监听器
listener
,位于src/main/java/com/tencent/listener/
目录里面,这几个listener
都是对业务逻辑各种可能返回事件的默认处理,商户需要自己实现更加具体的处理逻辑。
Demo依赖的配置项
- 打开demo工程里的
wxpay.properties
文件可以看到里面有6个配置项(该demo里面用的是一个mchid为10000097的测试号)
这些关键配置项的作用分别为:
- | 名称 | 用途 | 来源 |
---|---|---|---|
1 | KEY | 签名算法需要用到的秘钥 | 成功申请微信支付功能之后通过官方发出的邮件获得 |
2 | APPID | 公众账号ID | 成功申请公众账号后获得 |
3 | MCHID | 商户ID | 成功申请微信支付功能之后通过官方发出的邮件获得 |
4 | SUBMCHID | 子商户ID | 受理模式下必须要有的一个子商户ID |
5 | CERT_LOCAL_PATH | HTTP证书在服务器中的路径,用来加载证书用 | 成功申请微信支付功能之后通过官方发出的邮件获得“HTTPS证书”,这个配置项就是“HTTP证书”在服务器上所部署的路径(demo中需要的证书文件就是docs/https_cert_for_test/文件夹中的10000097.cert) |
6 | CERT_PASSWORD | HTTP证书的密码,默认等于MCHID | 成功申请微信支付功能之后通过官方发出的邮件获得 |
这些配置项用来对SDK进行一次初始化的时候使用。初始化方法见上面的“第一步,初始化SDK”
Demo需要商户自己实现的IBridge
从上图可见IBridge桥接器其实就是定义了请求API时需要提交的各种参数的产生接口,这些接口跟商户自己的系统是紧密结合的,商户自己需要根据具体业务系统的实际情况,按照API文档定义的格式来产生相应的参数给到调用API时使用。
举个例子,IBridge里面定义了一个非常关键的接口,叫getAuthCode(),这个接口的作用就是用来返回一个合法的“授权码”供调用API时用。
1 | /** |
以上只是简单的hardcode
(用来先简单手动输入“授权码”调试API是否能正常返回数据时用),实际上商户自己在实现这个接口的时候就需要根据自己实际系统来进行设计了,例如需要去监听“扫码枪”等具备一维码/二维码扫描功能的外设,当成功扫描到这串“授权码”的时候,将其保存下来,然后触发提交支付的API调用,调用时让IBridge
桥接器中的getAuthCode()
接口取得刚刚扫描到的授权码,作为参数传给支付API。
被扫支付业务流程最佳实践
被扫支付整个完成流程将会涉及到“查询”和“撤销”等请求,这里给出建议实现的流程供大家参考,SDK里面的ScanPayBusiness
就是按照这个流程来设计的:
从上图可见主要流程分为四种情况:
- 直接扣款成功:直接返回成功
- 扣款明确失败:走撤销流程,返回失败(建议提示具体的失败信息,指示用户进行下一步操作)
- 需输入密码:走查单流程,如果查询了一定时间还是没有成功则当失败处理,直接走撤销
- 扣款未知失败:先走查单流程,如果查询了一定时间还是没有成功则当失败处理,直接走撤销
两个关键流程解释:
- 有限次查询流程:这里会根据设定的“查询次数”(用户可以自定义)和“查询间隔”来进行轮询,超过了查询次数之后还是没有查询到“支付成功”的情况会自动转入“撤销流程”
- 撤销流程:这里会根据设定的“查询间隔”进行不停地轮询撤销API,API会通过recall字段来告诉商户侧需不需要继续轮询,如果“recall=Y”或是“撤销结果成功”都表示不需要再轮询了,然后到达“支付失败”的最终状态。
(以上最佳实践已经在SDK的ScanPayBusiness
里面封装好了)
支付业务逻辑分支处理最佳实践
ScanPayBusiness
里面的ResultListener
接口定义了支付流程中可能走到的8个分支,分别是:
1 | public interface ResultListener { |
Demo里面用到的DefaultScanPayBusinessResultListener
就是实现了以上这8个接口。
这里有几点处理建议:
onFailByReturnCodeError
、onFailByReturnCodeFail
、onFailBySignInvalid
这3种属于程序逻辑问题,建议商户自己做好日志监控,发现问题要及时让工程师进行定位处理;onFailByAuthCodeExpire
、onFailByAuthCodeInvalid
、onFailByMoneyNotEnough
这三种属于用户自身的问题,建议商户把具体出错信息提示给用户,指导用户进行下一步操作。(具体出错信息可以通过scanPayResData.getErr_code_des()
获取得到)
商户系统接入SDK最佳实践
- 生成一个新的订单
out_trade_no
- 输入订单金额
total_fee
- 启动扫码枪功能供用户进行扫码
- 扫码器获取授权码
auth_code
,并回传给SDK - SDK提交支付请求
- SDK处理API返回的数据
商户系统部署最佳实践
- 由于整套系统必须采用HTTPS来保证安全性,所以这里的支付请求必须由商户的后台系统来发起;
- 商户系统跟SDK的对接主要就是实现IBridge里面的接口;
- 从本demo里面有JUnit单元测试用例,商户开发者可以参考下这个示例;
高级自定义:1)自定义查询流程和撤销流程
商户可以根据自己的实际需要来配置支付业务流程中的“查询流程”的“查询次数”和“查询间隔”;“撤销流程”的“查询间隔”,例如:
1 | //自定义调用查询接口的间隔 |
高级自定义:2)使用自己的Https请求器
可能有些商户自己系统里面已经拥有自己封装得很完善的Https请求器了,想让SDK的服务统一都走自己的Https请求器来发起请求的话,这里提供了一个配置项可以实现这个功能:
1 | //自定义底层的HttpsRequest |
温馨提示:自己实现的Https请求器必须实现IServiceRequest这个接口,可以参考SDK里面的HttpRequest的实现。
调用被扫支付API的协议规则
序号||
:-:|-|-
1|传输方式|为保证交易安全性,采用HTTPS传输
2|提交方式|采用POST方法提交
3|数据格式|提交和返回数据都为XML格式,根节点名为xml
4|字符编码|统一采用UTF-8字符编码
5|签名算法|MD5
6|签名要求|请求和接收数据均需要校验签名,签名的方法在SDK里面已经封装好了
7|证书要求|调用申请退款、撤销订单接口需要商户证书
8|判断逻辑|先判断协议字段返回,再判断业务返回,最后判断交易状态
支付验证密码规则
- 支付金额>300元的交易需要验证用户支付密码;
- 用户账号每天最多有10笔交易可以免密,超过后需要验证密码;
- 微信支付后台判断用户支付行为有异常情况,符合免密规则的交易也会要求验证密码;