不少朋友第一次作微信支付的时候都有蒙,但当你完整的作一次就会发现其实并无那么难php
业务流程和应用场景官网有详细的说明:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_4,我就不作具体介绍了,我主要介绍一下做为开发的咱们须要作的事情,微信官网要完成的部分咱们就先不要考虑了html
1.获取用户受权,有两种形式:java
一种是snsapi_base (不弹出受权页面,直接跳转,只能获取用户openid);另外一种是:snsapi_userinfo (弹出受权页面,可经过openid拿到昵称、性别、所在地。而且, 即便在未关注的状况下,只要用户受权,也能获取其信息 ) 算法
2.调用统一下单接口获取预支付ID;(重点)api
3.H5调起微信支付的内置JS安全
4.支付完成后,微信回调的处理,这里主要就是处理支付成功后本身项目的业务逻辑微信
所需参数去哪里找其实官方也有具体说明:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1app
appid:微信支付分配的公众帐号ID(企业号corpid即为此appId) 登录微信公众号后台==>开发==>基本配置微信公众平台
mch_id : 微信支付分配的商户号 ; 登录位置公众号支付后台就能够看到异步
device_info :设备号;能够为终端设备号(门店号或收银设备ID) PC网页或公众号内支付能够传"WEB"
nonce_str:随机字符串,长度要求在32位之内;本身随机生成就行
小科普一下:nonce=Number once 表示在密码学中Nonce是一个只被使用一次的任意或非重复的随机数值
sign:签名,官方详细描述:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3;
这是小白们常常栽跟头的地方,不过不用担忧,下面我会附上前面算法
sign_type:签名类型,默认为MD5,支持HMAC-SHA256和MD5。
body:商品简单描述信息,自定义便可
out_trade_no:商户系统内部订单号,要求32个字符内,只能是数字、大小写字母_-|* 且在同一个商户号下惟一;
total_fee:订单总金额,注意单位为分
spbill_create_ip:终端IP;APP和网页支付提交用户端ip
notify_url:回调函数的通知地址,异步接收微信支付结果通知的回调地址,通知url必须为外网可访问的url,不能携带参数,就是本身处理支付完业务的接口路径
trade_type:交易类型,JSAPI 公众号支付;NATIVE 扫码支付;APP APP支付
key :密钥,签名时用,key设置路径:微信商户平台(pay.weixin.qq.com)-->帐户设置-->API安全-->密钥设置
最方面的就是本身想了一个字符串,而后用MD5(其余加密方式也能够)加密成32位的字符串,从新设置。
所须要的参数签名已经都有具体介绍了,这里我就直接上代码了
SortedMap<Object,Object> packageParams = new TreeMap<Object,Object>(); packageParams.put("appid", appid); packageParams.put("mch_id", mch_id); packageParams.put("device_info", "WEB"); packageParams.put("body", "自定义描述信息"); packageParams.put("out_trade_no","商户系统内部订单号"); packageParams.put("total_fee","支付金额"); packageParams.put("spbill_create_ip", "终端IP"); packageParams.put("notify_url","回调地址url"); packageParams.put("trade_type","JSAPI"); packageParams.put("nonce_str", "随机字符串"); packageParams.put("sign","签名结果");
统一下单接口地址:https://api.mch.weixin.qq.com/pay/unifiedorder
准备好数据后,封装成XML,调起统一下单接口,会返回一个XML格式数据 return_code为SUCCESS时,请求成功,获取咱们须要的预支付id(prepay_id)这时就已经成功了一大半,能够稍做休息,犒劳一下本身了。
附上加密算法:传入上面准备的map数据
StringBuffer sb = new StringBuffer(); Set es = parameters.entrySet(); Iterator it = es.iterator(); while(it.hasNext()) { Map.Entry entry = (Map.Entry)it.next(); String k = (String)entry.getKey(); Object v = entry.getValue(); if(null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) { sb.append(k + "=" + v + "&"); } } sb.append("key=" +密钥key); String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();
此次的字段名和上次准备数据有所不同
appId:只是I大写,值仍是同样的
nonceStr:随机字符串,长度要求在32位之内;本身随机生成就行
package:统一下单接口返回的prepay_id参数值,提交格式如:prepay_id=***
timeStamp:时间戳
signType:签名方式,默认MD5
paySign:签名
SortedMap<Object,Object> packageParams = new TreeMap<Object,Object>(); packageParams.put("appId","商户号"); packageParams.put("timeStamp","时间戳"); packageParams.put("nonceStr","随机字符串"); packageParams.put("prepayid","前面获得的预支付id"); packageParams.put("package","prepay_id=前面获得的预支付id"); packageParams.put("signType","MD5"); packageParams.put("paySign","签名");
若是全部配置都OK,就会弹出请输入密码的界面,反之提示目录未受权,这时候你就应该想时候配置受权目录了
微信公众平台后台 ==> 微信支付 ==> 开发者配置,S API网页支付,而后添加系统后台的受权目录
其余微信支付配置参考:https://jingyan.baidu.com/article/77b8dc7fef360d6174eab690.html
1)解析传过来的流信息,经过从新签名的方式验证流中包含的信息的正确性。就是判断这个信息究竟是不是微信发的
2)return_code和result_code都是SUCCESS的话,处理商户本身的业务逻辑。就是订单的支付状态啊等一些信息。
3)告诉微信,我收到你的返回值了。不用在发了。