大家好,感谢邀请,今天来为大家分享一下深入教程:循序渐进,掌握SpringBoot微信刷卡支付集成技巧的问题,以及和的一些困惑,大家要是还不太明白的话,也没有关系,因为接下来将为大家分享,希望可以帮助到大家,解决大家的问题,下面就开始吧!
申请服务号(企业)
开通微信支付
开发配置 具体准备工作请参考Spring Boot入门教程(三十九):微信支付集成-申请服务号和微信支付
二:支付方式
H5支付:H5支付是指商户在微信客户端外的移动端网页展示商品或服务,用户在前述页面确认使用微信支付时,商户发起本服务呼起微信客户端进行支付。主要用于触屏版的手机浏览器请求微信支付的场景。可以方便的从外部浏览器唤起微信支付。相当于支付宝的手机网站支付
App支付:APP支付又称移动端支付,是商户通过在移动端应用APP中集成开放SDK调起微信支付模块完成支付的模式。
小程序支付:在小程序中使用
三:刷卡支付场景介绍
1. 场景介绍
步骤1:用户选择刷卡支付付款并打开微信,进入“我”->“钱包”->“收付款”条码界面;
步骤2:收银员在商户系统操作生成支付订单,用户确认支付金额;
步骤4:微信支付后台系统收到支付请求,根据验证密码规则判断是否验证用户的支付密码,不需要验证密码的交易直接发起扣款,需要验证密码的交易会弹出密码输入框。支付成功后微信端会弹出成功页面,支付失败会弹出错误提示。
2. 验证密码规则:
支付金额>1000元的交易需要验证用户支付密码
用户账号每天最多有5笔交易可以免密,超过后需要验证密码
微信支付后台判断用户支付行为有异常情况,符合免密规则的交易也会要求验证密码
3. 免密支付流程:
(1)收银员在商户收银台生成支付订单,向用户展示支付金额;
(2)用户打开微信客户端,点击“我的钱包”,选择“刷卡”,进入条码界面;
(5)门店收银台得到支付信息后,向商户收银后台发起支付请求。
(6)商户后台对门店收银台的支付请求进行处理,生成签名后调用【提交刷卡支付API】向微信支付系统发起支付请求。
(7)微信支付系统得到商户侧的支付请求之后会对请求进行验证,验证通过之后会对请求数据进行处理,最后将处理后的支付结果返回给商户收银后台。如果支付成功,微信支付系统会将支付结果返回给商户,同时把支付结果通知给用户(以短信、微信消息的形式通知)。
(8)商户收银后台对得到的支付结果进行签名验证和处理,再将支付结果返回给门店收银台。
(9)收银员看到门店收银台的支付结果后给用户发货。
4. 验密支付流程
验密支付流程文档
在商户调用【提交刷卡支付API】发起支付请求之后,微信支付后台提示用户输入密码确认支付,接口同步返回USERPAYING状态,商户系统再轮询调用查询订单接口来确认当前用户是否已经支付成功。
以下时序图说明验密支付流程:
由于在商户收银后台向微信支付系统发起支付请求之前的流程是完全一样的,所以这里只介绍商户发起支付请求之后的逻辑。
(1)商户门店生成订单后,收银台向后台系统发起支付请求。
(2)后台调用微信支付【提交刷卡支付API】生成支付交易。
(3)微信支付系统对商户请求进行验证,验证通过后判断当前用户需要输入密码。
(4)微信支付系统返回USERPAYING状态,商户后台系统将应答结果返回给商户门店收银台。
(5)微信支付系统通知用户微信客户端输入密码。
(6)用户得到输入密码提示后,确认支付并输入密码。
(7)完成密码输入,提交微信支付。
(8)微信客户端在用户完成支付后提示微信支付后台系统返回的支付结果,而且微信支付系统会通过短信、微信消息给用户发送支付结果提醒。
(9)商户收银台得到USERPAYING状态后,经过商户后台系统调用【查询订单API】查询实际支付结果。
(10)如果支付结果仍为USERPAYING,则每隔5秒循环调用【查询订单API】判断实际支付结果,如果用户取消支付或累计30秒用户都未支付,商户收银台退出查询流程后继续调用【撤销订单API】撤销支付交易。
5. 异常处理
用户遇到支付异常,请按如下说明处理
(1)用户微信端弹出系统错误提示框,用户可在交易列表查看交易情况,如果未找到订单,需要商户重新发起支付交易;如果订单显示成功支付,商户收银系统再次调用【查询订单API】查询实际支付结果;
(2)用户微信端弹出支付失败提示,例如:余额不足,信用卡失效。需要重新发起支付;
(3)当交易超时或支付交易失败,商户收银系统必须调用【撤销订单API】,撤销此交易。
(4)由于银行系统异常、用户余额不足、不支持用户卡种等原因使当前支付交易失败,商户收银系统应该把错误提示明确展示给收银员。
(5)根据返回的错误码,判断是否需要撤销交易,具体详见API返回错误码列表
public Map
看Demo中的方法,整个方法也没有查询订单,也没有撤销订单的操作,而是不停的重复调用microPay,这和上面文档的(9)、(10)条逻辑不一样
注意:微信的刷卡支付并没有支付通知接口,只有退款通知接口;支付宝的条码支付是有支付通知接口的,两家是不一样的。
四:开发文档
在集成之前,一定要熟悉业务,熟悉文档
微信支付开发文档
刷卡文档,开发前请详细认证的看完该文档。
刷卡支付流程图 必须看
刷卡文档中有demo,SDK与DEMO下载,需要下载下来,熟悉一下项目结构,以及READEME.md
五:集成步骤
1. 引入SDK
wxpay-sdk 项目中的src就是要引入的sdk,可以直接将src的所有7个源文件拖入到自己项目中
wxpay-sdk 的READEME.md中说可以通过maven来引入sdk
现在有两种方式,选择其中一种,究竟选哪一种?
wxpay-sdk的src下面有7个java文件,通过maven引入可以看到的sdk中就4个java文件,两种方式文件个数不一致,多出来的3个文件是demo中用到的文件,并不是原始sdk中的文件,通过查看sdk中的源码可以看到,这4个文件其实就是使用httpclient来调用微信支付的支付接口,其中很多重要的逻辑并没有按照官方文档中说的那样缺少重要的逻辑实现,这个需要自己去完善一些逻辑
查看demo中的test发现竟然有一个类叫test,命名不清晰,语义太笼统,而且还是小写字母开头,不符合Java的基本命名规范,关于java中的测试的命名规则一般类名以Test作为后缀,而该demo以Test作为前缀,一般测试类方法的命名以test作为前缀,但是demo中的测试并没有什么test,一般测试类都要使用测试框架如Junit等,但是demo中的测试并没有使用测试框架,而是使用main方法来运行的。
对wxpay-sdk的评价:wxpay-sdk只是使用httpclient来调用微信支付的接口,只管调用微信支付接口,然后解析一下响应,并不处理支付中的业务逻辑,尽管一些和支付密切相关的重要逻辑也不会处理,甚至解密的工具方法都没有现成的,需要开发者自己去处理。看demo可以知道,写的不是一般的烂,没想到微信那么大的厂竟然sdk写的这么懒,demo写的这么low,真是丢人,和支付宝的sdk比一个地下一个天上。
骂完了,还是要集成的,这里我选择不相信demo的源文件,使用README.md中的maven来引入sdk,一个是demo写的太烂,多出来的文件也不是不要不行的,多出来的方法有重大逻辑缺陷,万一哪天微信哪天良心发现完善sdk了,更新了maven版本,自己只需要修改一下maven的版本号就行了。
2. application.yml
配置微信支付参数,其中appID、mchID、key、certPath是必须的,notifyUrl是可选的,sandboxKey和useSandbox是自己配置的,便于正式环境和沙箱环境的切换,关于参数的值去微信的开发配置中查看
useSandbox:true表示使用沙箱环境,如果为false为正式环境
sandboxKey: 沙箱环境API秘钥,需要通过下面的WXPayClient#getSignKey方法获取
pay: wxpay: appID: xxx mchID: xxx key: xxx sandboxKey: xxx certPath: /var/local/cert/apiclient_cert.p12 notifyUrl: http://65ta5j.natappfree.cc/wxpay/refund/notify useSandbox: false
3. MyWXPayConfig
配置微信参数,其实就是一种Properties类,需要实现WXPayConfig中的方法 注意:demo中的WXPayConfig是一种抽象类abstract class,可以看到maven与demo的不统一
/** * 微信支付的参数配置 * * @author mengday zhang */@Data@Slf4j@ConfigurationProperties(prefix = "pay.wxpay")public class MyWXPayConfig implements WXPayConfig { /** 公众账号ID */ private String appID; /** 商户号 */ private String mchID; /** API 密钥 */ private String key; /** API 沙箱环境密钥 */ private String sandboxKey; /** API证书绝对路径 */ private String certPath; /** 退款异步通知地址 */ private String notifyUrl; private Boolean useSandbox; /** HTTP(S) 连接超时时间,单位毫秒 */ private int httpConnectTimeoutMs = 8000; /** HTTP(S) 读数据超时时间,单位毫秒 */ private int httpReadTimeoutMs = 10000; /** * 获取商户证书内容 * * @return 商户证书内容 */ @Override public InputStream getCertStream() { File certFile = new File(certPath); InputStream inputStream = null; try { inputStream = new FileInputStream(certFile); } catch (FileNotFoundException e) { log.error("cert file not found, path={}, exception is:{}", certPath, e); } return inputStream; } @Override public String getKey(){ if (useSandbox) { return sandboxKey; } return key; }}
4. WXPayClient
WXPayClient 是对WXPay的一个封装,增加了microPayWithPOS方法,内部调用WXPay#microPay,但是sdk中的microPay并没有处理当微信支付时微信提示用户输入密码,这时sdk直接返回的错误,这里处理的逻辑就是在指定时间内去轮询支付结果,然后将轮询的结果返回出去,而不是就直接返回错误了,demo项目也有个microPayWithPOS实现,但是它的逻辑是当用户输入密码的情况会轮询的去下单去调用WXPay#microPay,这种做法是不符合微信的官方文档的。另外增加了获取沙箱环境API秘钥和解密退换通知的方法。
吐槽一下:感觉像这种解密方法WXPayUtil中竟然没有,这是必须的不可少的啊,怎么会没有呢,这也太烂了吧,这还称为sdk啊
/** * WXPayClient *
* 对WXPay的简单封装,处理支付密切相关的逻辑. * * @author Mengday Zhang * @version 1.0 * @since 2018/6/16 */@Slf4jpublic class WXPayClient extends WXPay { /** 密钥算法 */ private static final String ALGORITHM = "AES"; /** 加解密算法/工作模式/填充方式 */ private static final String ALGORITHM_MODE_PADDING = "AES/ECB/PKCS5Padding"; /** 用户支付中,需要输入密码 */ private static final String ERR_CODE_USERPAYING = "USERPAYING"; private static final String ERR_CODE_AUTHCODEEXPIRE = "AUTHCODEEXPIRE"; /** 交易状态: 未支付 */ private static final String TRADE_STATE_NOTPAY = "NOTPAY"; /** 用户输入密码,尝试30秒内去查询支付结果 */ private static Integer remainingTimeMs = 10000; private WXPayConfig config; public WXPayClient(WXPayConfig config, WXPayConstants.SignType signType, boolean useSandbox) { super(config, signType, useSandbox); this.config = config; } /** * * 刷卡支付 * * 对WXPay#microPay(Map)增加了当支付结果为USERPAYING时去轮询查询支付结果的逻辑处理 * * 注意:该方法没有处理return_code=FAIL的情况,暂时不考虑网络问题,这种情况直接返回错误 * * @param reqData * @return * @throws Exception */ public Map
5. WXPayConfiguration
/** * 微信支付配置 * * @author mengday zhang */@Configuration@EnableConfigurationProperties(MyWXPayConfig.class)public class WXPayConfiguration { @Autowired private MyWXPayConfig wxPayConfig; /** * useSandbox true为沙盒环境 * @return */ @Bean public WXPay wxPay() { return new WXPay(wxPayConfig, WXPayConstants.SignType.MD5, wxPayConfig.getUseSandbox() ); } @Bean public WXPayClient wxPayClient() { return new WXPayClient(wxPayConfig, WXPayConstants.SignType.MD5, wxPayConfig.getUseSandbox()); }}
6. WXPayMicroPayController
/** * 微信支付-刷卡支付. *
* detailed description * * @author Mengday Zhang * @version 1.0 * @since 2018/6/18 */@Slf4j@RestController@RequestMapping("/wxpay/microPay")public class WXPayMicroPayController { @Autowired private WXPayClient wxPayClient; /** * 刷卡支付(类似支付宝的条码支付) * * 和支付宝的好像不一样,支付宝有支付通知,但是微信好像没,微信有退款通知 * * 微信支付后台系统收到支付请求,根据验证密码规则判断是否验证用户的支付密码,不需要验证密码的交易直接发起扣款, * 需要验证密码的交易会弹出密码输入框。支付成功后微信端会弹出成功页面,支付失败会弹出错误提示 * 注意该接口有可能返回错误码为USERPAYING用户支付中 * * 验证密码规则 * ◆ 支付金额>1000元的交易需要验证用户支付密码 * ◆ 用户账号每天最多有5笔交易可以免密,超过后需要验证密码 * ◆ 微信支付后台判断用户支付行为有异常情况,符合免密规则的交易也会要求验证密码 * * 用户刷卡条形码规则:18位纯数字,以10、11、12、13、14、15开头 */ @PostMapping("") public Object microPay(String authCode) throws Exception { Map
7. WXPayController
/** * 微信支付 - 通用API. * *
* 类似支付宝中的条码支付. * * @author Mengday Zhang * @version 1.0 * @since 2018/6/15 */@Slf4j@RestController@RequestMapping("/wxpay")public class WXPayController { @Autowired private WXPay wxPay; @Autowired private WXPayClient wxPayClient; @Autowired private MyWXPayConfig wxPayConfig; /** * 订单查询 * @param orderNo * @return * @throws Exception */ @GetMapping("/orderQuery") public Object orderQuery(String orderNo) throws Exception { Map
获取源码
用户评论
一直想要学习微信刷卡支付!看到这个标题立马点进来看,好赞!感觉很详细实用
有19位网友表示赞同!
终于等到这篇文章了!之前一直在找关于SpringBoot和微信支付的教程,这篇文章讲得非常透彻,一步一步跟着做都能搞定。太赞了!
有7位网友表示赞同!
刚开始接触SpringBoot,这篇文章正好踩到我的痛点,希望能够详细介绍一下每一步骤的原理,这样就能更好地理解啊!
有15位网友表示赞同!
学习Spring Boot确实比较头疼,微信支付这一块更是难啃的骨头,你的文章能否加入一些实战案例和代码片段呢?那样更能帮助我快速上手.
有15位网友表示赞同!
这个标题简直太吸引人啦!终于不用再手动录入数据了,刷卡支付效率高多了。期待学习你提供的干货内容。
有13位网友表示赞同!
我已经用过很多类似的教程,但是你的文章看起来很独特,希望你能分享一些不一样的经验和方法,帮助我进一步提升我的技能水平!
有11位网友表示赞同!
学习成本很高的啊,希望你的文章能详细讲解一些基础知识点,不要太过于专业复杂的,否则我这个萌新就看不懂了!
有15位网友表示赞同!
期待看到你分享的步骤和代码规范,这样我就能更好地理解微信刷卡支付的流程和安全机制。多多的图解也挺好玩的.
有10位网友表示赞同!
终于有人来解决这一块难题!一直想自己实现微信刷卡支付功能,希望能按照你的教程一步步完成,搞定这个难题!
有10位网友表示赞同!
这篇文章真的太及时了!最近我正在开发一个项目,需要集成微信刷卡支付功能,你的教程刚好能够帮助我。一定要好好学习一下!
有11位网友表示赞同!
感觉这篇博文很有价值,希望能够解答一些我的疑问:比如如何处理异常情况和安全问题? 你能不能分享一些具体的经验?
有10位网友表示赞同!
这个标题太吸引人了!刚学习SpringBoot不久就遇到了微信刷卡支付的问题,希望能通过你的教程来解决。期待详细步骤!
有14位网友表示赞同!
看来你要把我们都带去成为开发高手啦!很期待学习你的干货内容,相信能够帮助我解决实际的项目问题!
有20位网友表示赞同!
我已经有一些SpringBoot基础了,想要进一步了解微信刷卡支付的功能实现,希望你能够从原理和实战结合的角度进行讲解!
有16位网友表示赞同!
这个主题太棒了!我一直想知道如何在SpringBoot中集成微信刷卡支付,你的文章能否分享一些调优技巧?例如如何提高效率、处理并发场景等?
有20位网友表示赞同!
学习Spring Boot确实很不错,这篇文章刚好让我能更深入地了解微信支付功能的实现。期待看到更多你的干货内容!
有14位网友表示赞同!