引子:
以下的部分代码、思路来自于 CSDN的一位博客主 ,以及 后宫 —— 易水 的支持。
1.前期申请流程介绍:
在微信开放平台注册账户:
- 注册成功后在顶部菜单栏选择管理中心--移动应用--创建移动应用[业主需要准备应用的官网(没有可写域名或者www.baidu.com[有未知风险])、应用的logo2张,一张28*28,一张108*108]
应用创建完成之后申请开通微信支付接口:
- 在应用详情里,取得APPID;
- 开放平台需进行开发者资质认证后才可申请微信支付,认证费:300元/次;
- 认证后进行微信支付所需要的申请。[这里的申请需要提供APP应用的信息,一般情况下均提供APP页面截图,APP页面截图应该包含:APP首页、APP版权信息页、APP商品展示页、APP支付方式页。另外需要特别注意自己的应用是否涉及到了 网络文化经营许可证 的范畴,微信人工审核会判别这一点,如果是需要提供此证。如申请不下这个证,则会有一定的法律风险]
- 微信支付接口申请好之后,微信会向申请时填写的邮箱发送微信商户平台账户信息;[账户、密码、微信商户号等]
在微信商户平台设置32位密钥:
- [该网址的密码框控件不支持谷歌浏览器]
- 用邮箱里的账户信息登录,第一次登录微信会提示设置防钓鱼标志,请牢记此值;
- Key设置路径:微信商户平台--账户中心--API安全--API密钥--密钥设置[提供一个生成随机码的网页]
其他说明:
- 在商户平台扫描首页的二维码,关注支付提醒信息
- 微信提现有周期间隔,支付的金额不会实时转到业主银行账户上,需要人为转出
- 以上加粗标识的关键值均需业主提供给程序员,在代码抒写时有用到
2.支付流程示例:
商户APP-----向商户服务端发起请求--1--商户服务端--2--向微信服务端发起请求得到唯一标识--3--返回给商户APP;
商户APP根据返回值调起微信支付,消费人支付成功;
微信服务端-----4-----向商户服务端发起请求,商户服务端完成自身业务;
其他:数字标志的含义,1代表处理自身业务,2代表按照微信要求请求微信,3按照微信要求解析返回值并同样照要求返回APP,4代表按微信要求验证参数,完成自己业务。
3.代码结构以及使用说明:
下载:
包含了微信支付和支付宝支付,密码为phqa
结构:
使用说明:
- 操作者只需要填写Config所需的信息,根据自身业务抒写Controller、service层即可,其他结构无需修改;在service里调用WxPayCore进行微信必要的步骤即可。
- WxPayConfig配置参数概览:均为字符串
参数名 | 释义或固定值 | 取得方式或固定值 |
---|---|---|
appid | 应用id | 参考前期业主申请操作 |
mch_id | 微信商户号 | 同上 |
key | 密钥 | 同上 |
notify_url | 接收微信支付异步通知回调地址;通知url必须为直接可访问的url,不能携带参数 | 参考外网映射的配置方式https://www.ngrok.cc/ |
body | 商品描述交易字段 | APP名字-实际商品名称比如:天天爱消除-游戏充值 |
以下值为固定值 | --- | --- |
spbill_create_ip | 客户端ip地址 | 127.0.0.1[此值不影响] |
trade_type | 支付类型 | APP |
PACKAGE | --- | Sign=WXPay |
wxUrl | 微信统一下单接口请求地址 | https://api.mch.weixin.qq.com/pay/unifiedorder |
-
在Controller层抒写两个业务,处理APP调起支付和微信的回调;调起App的接口可以自定义参数,接收微信的回调参数无需修改。在Service里抒写自己的具体业务,然后调用固定方法进行处理。
-
eg:A用户要购买100元的衣服,提供给App的接口需要接收用户的id,衣服的id,在Service层里处理订单的业务之后,调用WxPayCore.createWxPayParam(out_trade_no,total_fee)方法,传入商户内部订单号和用户所要支付的金额,并将返回值返给前端即可;
前端接收到返回值调起微信SDK,用户支付完毕;
微信会异步通知在Config里配置的回调地址,在回调的Service层里,调用WxPayCore.checkWxPayParam(request)进行验证,判断是否是微信发送来的通知以及是否支付成功,返回值不为NULL即可进行商品发货或者填写快递订单号等业务。 -
两个核心方法使用介绍:
1.SortedMap<Object, Object> wxAppparameters = WxPayCore.createWxPayParam(String out_trade_no,String total_fee);
a)拼接微信支付必要参数,加签,并返回Map对象;
b)out_trade_no 传入商户内部订单号,必须唯一;total_fee 所要支付的金额,格式必须为0.00,单位为元;
c)返回App端调起支付所需要的参数。
2.SortedMap<Object, Object> parameters = WxPayCore.checkWxPayParam(request);
a)支付成功的回调:检测微信异步反馈是否真实,不为null为真实,null为校验失败。
b)返回的map中可以取得微信返回的参数,一般只取out_trade_no(商户内部订单号)、total_fee(充值的金额,单位为分)、transaction_id(微信支付订单号)。
c)判断parameters是否不为NULL,不为NULL拿商户内部订单号去查出充值的订单数据,完成自己的业务。
- 特别注意:在处理的回调里,处理成功后需要向微信反馈成功:
Eg:out.print(HttpXmlUtil.backWeixin("SUCCESS","OK")); *
如果处理失败则无需反馈;微信如果接收不到正确反馈,则会按照一定策略重复通知,代码中应该有去重处理[判断该订单是否已经处理过*]
注意事项:
- WxPayCore类里的方法均不需要修改,和业务无关,直接调用即可。
引用jar:
- dom4j-1.6.1.jar
- jdom.jar
- 微信不提供sdk,上述jar包无需修改。
4.备注以及拓展:
文档的第一步骤可以截取发给业主参考申请,让业主提供加粗的参数信息;
- 本着程序员应全身心在开发上,避免不必要的时间浪费。
对WxPayCore.createWxPayParam()方法的解释:
- 方法的作用就是按照微信的要求去请求微信并得到唯一的标识并返回给APP端;App端根据此返回值调起微信[微信所需要的是很多参数,不是字符串形式的];
- 返回的参数里包含着调起支付的唯一标识,[微信要扣多少钱、微信服务端给哪个地址发送支付成功的通知等信息都保存在 微信的服务端 了:通过服务端请求微信的那次请求,称作 统一下单接口];
- 请求微信的规则是[微信签名的规则]:
1.将参数的key值按照ascii码的顺序进行排序,并转化成key=value&key=value的形式;
2.拼接完所有的非sign参数后,字符串末尾拼入key=32位字符串[上面提及的key值]然后进行MD5加密并转为大写,得到sign值; - 微信以上的2步是为了确保这个通知是商户的自身发送出来的,拿key参与MD5运算,确保唯一性。[如果微信不这么做,订单信息被别人篡改了,对双方都将是最坏的结果];
- 微信请求以及返回值的形式都是xml形式,服务端请求微信前将map的值转为xml发送请求[发送了这个请求就意味着微信服务端存储了该订单的信息],得到返回值解析出来,得到预支付订单[唯一性的东西],再按照微信调起支付的参数要求继续拼接,并用MD5生成sign字段;
对WxPayCore.checkWxPayParam()方法的解释:
- 方法的作用就是检测是否是微信发送来的通知,根据此通知进行支付成功的业务;
- 微信是不会发送支付失败的通知的;
- 验证也有相应的规则:
1.将微信的参数都取出[这里有个拓展,requesr.getParameterMap()就可以取出Map形式的参数];
2.取出sign字段,将剩余参数变成按照ascii码排序的key=value&形式再次进行加签;
3.自己加签的签名和取出的sign字段进行比较,查看是否一致; - 同理,微信需要这样的验证步骤,也是为了确保该通知是微信发出的,以防别人冒发送请求;
- 为防止意外,对订单号、商户的基本信息做验证。
拓展:
- 关于数字签名这里有一篇文章介绍的很全面:
- 将参数拼接密钥进行加签,接收者根据参数同样进行加签,验证自己所加的签名与发送者的是否一致,来达到信息的准确性;
- 也推荐关注该文章的翻译者:阮一峰。
网友评论