微信小程序实现微信支付功能流程php
微信支付:css
https://pay.weixin.qq.com/wiki/doc/api/index.html
html
图片说明java
进行选择接入web
图片说明算法
图片说明json
步骤:小程序
小程序调用登陆接口,获取用户的openid
, wx.login(object)
, 经过调用接口获取登陆凭证code
进行获取登陆用户信息,包含用户的惟一标识(openid
)以及本次登陆的会话密钥(session_key
).微信小程序
用code
获取session_key
, 这是一个https
接口,开发者服务器使用登陆凭证code
获取session_key
和openid
.其中session_key
是对用户数据进行保密的密钥.为了安全,不能将session_key
在网络上传输.api
图片说明
获取的openid
商户在小程序中先调用该接口在微信支付服务后台生成预支付交易单,返回正确的预支付交易后调起支付。其实微信是提供java,net,php三种语言的封装包。
https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_1
图片说明
微信小程序-支付
http://www.cnblogs.com/jcscript/p/6126722.html
须要支付的
perpay_id
参数 | 类型 | 必填 | 说明 |
---|---|---|---|
timeStamp |
String |
是 | 时间戳从1970年1月1日00:00:00至今的秒数,即当前的时间 |
nonceStr |
String |
是 | 随机字符串。 |
package |
String |
是 | 统一下单接口返回的 prepay_id 参数值,提交格式如:prepay_id=*** |
signType |
String |
是 | 签名算法,暂支持 MD5 |
paySign |
String |
是 | 签名,具体签名方案参见小程序支付接口文档; |
wx.requestPayment({ "timeStamp": "", "nonceStr": "", "package": "", "signType": "MD5", "paySign": "", "success":function(res){ }, "fail":function(res){ } })
获取支付id
, res_pay
, 仅返回了perpay_id,还有随机字符串和签名
统一下单接口返回的 prepay_id 参数值,提交格式如:prepay_id=***
签名,具体签名方案参见小程序支付接口文档
踩坑:
图片说明
图片说明
小程序支付->小程序调用起支付API
图片说明
微信小程序
API
同理
图片说明
https://developers.weixin.qq.com/miniprogram/dev/api/wx.requestPayment.html
图片说明
// 调起支付签名 function MixedencryMD5(res_paydata,randomString,timeStamp) { return "appId=" + config.appid + "&nonceStr=" + randomString + "&package=prepay_id=" + res_paydata + "&signType=MD5" + "&timeStamp=" + timeStamp + "&key=" + config.key; }
// 时间戳 function timeStamp() { return parseInt(new Date().getTime() / 1000) + '' } /* 随机数 */ function randomString() { var chars = 'A2345678'; var maxPos = chars.length; var pwd = ''; for (var i = 0; i < 32; i++) { pwd += chars.charAt(Math.floor(Math.random() * maxPos)); } return pwd; }
图片说明
注意: 时间戳和随机字符串,保证生成一次
https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=1_1
图片说明
图片说明
开通微信支付和微信商户号,获取当前用户的openid
,经过调用wx.login
方法,能够获得用户的code
,而后开发者服务器使用登陆凭证code
获取openid
.而后在获取prepay_id
和支付签名验证paySign
`appid`: "", // 公众号名称,由商户传入 `timeStamp`: "", // 时间 `nonceStr`: "", // 随机串 'package': 'prepay_id=', 'signType`: 'MD5'; // 微信签名方式, 'paySign': ""; // 微信签名
小程序经过wx.requestPayment
方法调用起支付功能.prepay_id
的获取和签名paySign
的获取.
图片说明
在小程序后台,申请微信支付,认证之后,微信支付申请审核经过后,商户在申请资料填写的邮箱中收取到由微信支付小助手发送的邮件,此邮件包含开发时须要使用的支付帐户信息。
图片说明
图片说明
图片说明
图片说明
appid: wxd mch_id: 100 device_info: 10 body: test nonce_str: ibA
第一步:对参数按照key=value的格式
stringA="appid=wx&body=test&device_info=10&mch_id=10100&nonce_str=ibJA";
第二步:拼接API密钥
stringSignTemp=stringA+"&key=" //注:key为商户平台设置的密钥key sign=MD5(stringSignTemp).toUpperCase()="" //注:MD5签名方式 sign=hash_hmac("sha256",stringSignTemp,key).toUpperCase()="" //注:HMAC-SHA256签名方式
最终获得最终发送的数据
<xml> <appid>wx</appid> <mch_id>1000</mch_id> <device_info>1</device_info> <body>test</body> <nonce_str>ibuA</nonce_str> <sign>9A0A89CF3B7</sign> </xml>
开放模式介绍-
appid
和mch_id
成对使用
微信支付开放的能力分2大类:普通模式和服务商模式
微信支付基础帐号模型-普通模式
图片说明
普通服务商微信支付资金清算流程
图片说明
JSAPI 或 JSSDK 调起微信支付
图片说明
小程序支付模式
第一步开通微信支付功能,绑定微信支付商户号.
appid 小程序appid mch_id 所绑定的商户号中的 mch_id trade_type 请填写"JSAPI" openid 使用 "wx.login" 接口得到的 openid
帐号申请指引
进行微信认证
小程序申请微信认证
认证入口:登陆小程序—设置—基本设置—微信认证—详情
图片说明
小程序申请微信支付
图片说明
小程序绑定微信开放平台账号
绑定小程序流程说明:登陆微信开放平台(open.weixin.qq.com)—管理中心—公众账号—绑定公众账号
公众号关联小程序
关联流程:
登陆公众号后台-小程序-小程序管理-添加-关联小程序
开通微信支付后,申请或复用微信支付商户号,新申请微信支付商户号或绑定一个已有的微信支付商户号,开通指引:
http://kf.qq.com/faq/140225MveaUz161230yqiIby.html
图片说明
注意事项:
图片说明
小程序支付的流程图以下:
图片说明
图片说明
一、【[小程序登陆API](https://mp.weixin.qq.com/debug/wxadoc/dev/api/api-login.html?t=20161122)】
二、【[统一下单API](https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_1&index=1)】
三、【[再次签名](https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_7&index=3)】
四、【[支付结果通知API](https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_7)】
五、【[查询订单API](https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_2)】
开发步骤
图片说明
HTTPS服务器配置
https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=10_4
图片说明
小程序绑定已有商户号开通微信支付
http://kf.qq.com/faq/140225MveaUz161230yqiIby.html
https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_7&index=5
图片说明
示例代码:
wx.requestPayment( { 'timeStamp': '', 'nonceStr': '', 'package': '', 'signType': 'MD5', 'paySign': '', 'success':function(res){}, 'fail':function(res){}, 'complete':function(res){} })
图片说明
小程序
案例:
/* 微信支付 */ goWxPay: function () { var that = this; wx.login({ success: function (res) { console.log("获取login code",res.code); that.getOpenId(res.code); } }); }, /* 获取openId */ getOpenId: function (code) { var that = this; wx.request({ url: "" + code, method: 'GET', success: function (res) { that.unitedPayRequest(res.data.openid); }, fail: function () { }, complete: function () { } }); }, /*统一支付接口*/ unitedPayRequest: function(openid){ var that=this; //统一支付签名 var appid = '';//appid必填 var body = '';//商品名必填 var mch_id = '';//商户号必填 var nonce_str = util.randomString();//随机字符串,不长于32位。 var notify_url = '';//通知地址必填 var total_fee = parseInt(0.01 * 100); //价格,这是一分钱 var trade_type = "JSAPI"; var key = ''; //商户key必填,在商户后台得到 var out_trade_no = '';//自定义订单号必填 var unifiedPayment = 'appid=' + appid + '&body=' + body + '&mch_id=' + mch_id + '&nonce_str=' + nonce_str + '¬ify_url=' + notify_url + '&openid=' + openid + '&out_trade_no=' + out_trade_no + '&total_fee=' + total_fee + '™_type=' + trade_type + '&key=' + key; console.log("unifiedPayment", unifiedPayment); var sign = md5.md5(unifiedPayment).toUpperCase(); console.log("签名md5", sign); //封装统一支付xml参数 var formData = "<xml>"; formData += "<appid>" + appid + "</appid>"; formData += "<body>" + body + "</body>"; formData += "<mch_id>" + mch_id + "</mch_id>"; formData += "<nonce_str>" + nonce_str + "</nonce_str>"; formData += "<notify_url>" + notify_url + "</notify_url>"; formData += "<openid>" + openid + "</openid>"; formData += "<out_trade_no>" + that.data.ordernum + "</out_trade_no>"; formData += "<total_fee>" + total_fee + "</total_fee>"; formData += "<trade_type>" + trade_type + "</trade_type>"; formData += "<sign>" + sign + "</sign>"; formData += "</xml>"; console.log("formData", formData); //统一支付 wx.request({ url: '', method: 'POST', head: 'application/x-www-form-urlencoded', data: formData, //设置请求的 header success: function (res) { console.log("返回商户", res.data); var result_code = util.getXMLNodeValue('result_code', res.data.toString("utf-8")); var resultCode = result_code.split('[')[2].split(']')[0]; if (resultCode == 'FAIL') { var err_code_des = util.getXMLNodeValue('err_code_des', res.data.toString("utf-8")); var errDes = err_code_des.split('[')[2].split(']')[0]; wx.showToast({ title: errDes, icon: 'none', duration: 3000 }) } else { //发起支付 var prepay_id = util.getXMLNodeValue('prepay_id', res.data.toString("utf-8")); var tmp = prepay_id.split('['); var tmp1 = tmp[2].split(']'); //签名 var key = '';//商户key必填,在商户后台得到 var appId = '';//appid必填 var timeStamp = util.createTimeStamp(); var nonceStr = util.randomString(); var stringSignTemp = "appId=" + appId + "&nonceStr=" + nonceStr + "&package=prepay_id=" + tmp1[0] + "&signType=MD5&timeStamp=" + timeStamp + "&key=" + key; console.log("签名字符串", stringSignTemp); var sign = md5.md5(stringSignTemp).toUpperCase(); console.log("签名", sign); var param = { "timeStamp": timeStamp, "package": 'prepay_id=' + tmp1[0], "paySign": sign, "signType": "MD5", "nonceStr": nonceStr } console.log("param小程序支付接口参数", param); that.processPay(param); } }, }) }, /* 小程序支付 */ processPay: function (param) { wx.requestPayment({ timeStamp: param.timeStamp, nonceStr: param.nonceStr, package: param.package, signType: param.signType, paySign: param.paySign, success: function (res) { console.log("wx.requestPayment返回信息",res); wx.showModal({ title: '支付成功', content: '官方号中收到支付凭证', showCancel: false, success: function (res) { if (res.confirm) { } else if (res.cancel) { } } }) }, fail: function () { console.log("支付失败"); }, complete: function () { console.log("支付完成"); } }) }
客户端js
wx.request({ url:'', header:{ 'Content-Type':'application/x-www-form-urlencoded' }, method:'POST', success:function(res){ console.log(res.data); console.log('调起支付'); wx.requestPayment({ 'timeStamp': res.data.timeStamp, 'nonceStr': res.data.nonceStr, 'package': res.data.package, 'signType':'MD5', 'paySign': res.data.paySign, 'success':function(res){ console.log('success'); wx.showToast({ title:'支付成功', icon:'success', duration:3000 }); }, 'fail':function(res){ console.log('fail'); }, 'complete':function(res){ console.log('complete'); } }); }, fail:function(res){ console.log(res.data) } });
在小程序后台,点击微信支付,申请开通,选择新申请,
统一下单:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_1&index=1
接口连接URL
地址:https://api.mch.weixin.qq.com/pay/unifiedorder
图片说明
举例以下:
<xml> <appid>wx2421b1c4370ec43b</appid> <attach>支付测试</attach> <body>JSAPI支付测试</body> <mch_id>10000100</mch_id> <detail><![CDATA[{ "goods_detail":[ { "goods_id":"iphone6s_16G", "wxpay_goods_id":"1001", "goods_name":"iPhone6s 16G", "quantity":1, "price":528800, "goods_category":"123456", "body":"苹果手机" }, { "goods_id":"iphone6s_32G", "wxpay_goods_id":"1002", "goods_name":"iPhone6s 32G", "quantity":1, "price":608800, "goods_category":"123789", "body":"苹果手机" } ] }]]></detail> <nonce_str>1add1a30ac87aa2db72f57a2375d8fec</nonce_str> <notify_url>http://wxpay.wxutil.com/pub_v2/pay/notify.v2.php</notify_url> <openid>oUpF8uMuAJO_M2pxb1Q9zNjWeS6o</openid> <out_trade_no>1415659990</out_trade_no> <spbill_create_ip>14.23.150.211</spbill_create_ip> <total_fee>1</total_fee> <trade_type>JSAPI</trade_type> <sign>0CB01533B8C1EF103065174F50BCA001</sign> </xml>
微信支付的流程:
获取用户code
值
获取用户openid
服务器上请求微信的统一下单接口,获取prepay_id
值
微信支付的整个流程:
获取用户的code
值,请求用户的openid
.
//app.js App({ onLaunch: function() { wx.login({ success: function(res) { if (res.code) { //发起网络请求 wx.request({ url: 'https://test.com/onLogin', data: { code: res.code } }) } else { console.log('获取用户登陆态失败!' + res.errMsg) } } }); } })
接着服务端来请求微信的地址:(参考微信官方api
)
https://api.weixin.qq.com/sns/jscode2session
public Map<String,Object> onLogin(String code){ Map<String,Object>result=new HashMap<>(); String url=ConstantUtils.getSessionKeyUrl+"?appid="+ ConstantUtils.appId+ "&secret="+ConstantUtils.secret+"&js_code="+code+"&grant_type="+ConstantUtils.grantType; JSONObject httpResult=HttpUtils.httpGet(url); result.put("openid",httpResult.get("openid")); result.put("session_key",httpResult.get("session_key")); result.put("expires_in",httpResult.get("expires_in")); return result; }
统一下单的接口,获取prepay_id
字段值
https://api.mch.weixin.qq.com/pay/unifiedorder
public Map<String,Object> createOrder(String openId){ Map<String,Object>result=new HashMap<>(); result.put("status","1"); result.put("payType","weixin"); result.put("orderId","123456"); String formData=orderService.commitData(openId); String httpResult = HttpUtils.httpXMLPost(ConstantUtils.createOrderUrl,formData); try { Map<String, String> resultMap = WXPayUtil.xmlToMap(httpResult); result.put("package", "prepay_id=" + resultMap.get("prepay_id")); result.put("nonceStr",resultMap.get("nonce_str")); } catch (Exception e) { e.printStackTrace(); } String times= WXPayUtil.getCurrentTimestamp()+""; result.put("timeStamp",times); Map<String, String> packageParams = new HashMap<String ,String>(); packageParams.put("appId", ConstantUtils.appId); packageParams.put("signType", ConstantUtils.signType); packageParams.put("nonceStr",result.get("nonceStr")+""); packageParams.put("timeStamp",times); packageParams.put("package", result.get("package")+"");//商户订单号 String sign=""; try { sign= WXPayUtil.generateSignature(packageParams, ConstantUtils.key); } catch (Exception e) { e.printStackTrace(); } result.put("paySign",sign); return result; }
WXPayUtil
工具类是微信官方demo
中的工具类.
能够JAVA
后台实现小程序支付
图片说明
调用支付统一下单API
来获取prepay_id
小程序调支付数据须要签名的字段appId
,timeStamp
,nonceStr
,package
再次签名.
https://pay.weixin.qq.com/wiki/tools/signverify/
WXPayUtil.java
https://download.csdn.net/download/by965738071/10389430
开通微信支付功能,须要商户号,appid
,appsecret
, openid
小程序:
参考
https://blog.csdn.net/fredrik/article/details/79697963
pay:function(){ var that=this wx.getStorage({ key: 'openid', success: function(res) { wx.request({ url: url + 'Wx_Pay', data: { //用户的openid openid:res.data, fee: that.data.totalPrice, //支付金额 details: that.data.goodsList[0].goods_name,//支付商品的名称 }, success:function(result){ if(result.data){ wx.requestPayment({ timeStamp: result.data['timeStamp'], nonceStr: result.data['nonceStr'], package: result.data['package'], signType: 'MD5', paySign: result.data['paySign'], 'success':function(succe***et){ console.log('支付成功'); //获取支付用户的信息 wx.getStorage({ key: 'userInfo', success: function (getuser) { wx.request({ url: url + 'Wx_AddOrder', data: { uname: getuser.data.nickName, goods: that.data.goodsList[0].goods_name, price: that.data.totalPrice, openid:res.data, }, success: function (lastreturn) { console.log("存取成功"); } }) }, }) },'fail':function(res){ } }) } } }) }, }) },
支付实现
图片说明
图片说明
图片说明
图片说明
小程序端代码:
wx.requestPayment({ 'timeStamp': '', 'nonceStr': '', 'package': '', 'signType': 'MD5', 'paySign': '', 'success':function(res){ }, 'fail':function(res){ } })
小程序端代码以下:
pay:function(_payInfo,success,fail){ var payInfo = { body:'', total_fee:0, order_sn:'' } Object.assign(payInfo, _payInfo); if(payInfo.body.length==0){ wx.showToast({ title:'信息描述错误' }) return false; } if(payInfo.total_fee==0){ wx.showToast({ title:'金额不能0' }) return false; } if(payInfo.order_sn.length==0){ wx.showToast({ title:'订单号不能为空' }) return false; } var This = this; This.getOpenid(function(openid){ payInfo.openid=openid; This.request({ url:'api/pay/prepay', data:payInfo, success:function(res){ var data = res.data; console.log(data); if(!data.status){ wx.showToast({ title:data['errmsg'] }) return false; } This.request({ url:'api/pay/pay', data:{prepay_id:data.data.data.prepay_id}, success:function(_payResult){ var payResult = _payResult.data; console.log(payResult); wx.requestPayment({ 'timeStamp': payResult.timeStamp.toString(), 'nonceStr': payResult.nonceStr, 'package': payResult.package, 'signType': payResult.signType, 'paySign': payResult.paySign, 'success': function (succ) { success&&success(succ); }, 'fail': function (err) { fail&&fail(err); }, 'complete': function (comp) { } }) } }) } }) }) }
openid
wx.login({ success: function(res) { if (res.code) { wx.request({ url: 'https://yourwebsit/onLogin', method: 'POST', data: { code: res.code }, success: function(res) { var openid = res.data.openid; }, fail: function(err) { console.log(err) } }) } else { console.log('获取用户登陆态失败!' + res.errMsg) } } }); var code = req.param("code"); request({ url: "https://api.weixin.qq.com/sns/jscode2session?appid="+appid+"&secret="+secret+"&js_code="+code+"&grant_type=authorization_code", method: 'GET' }, function(err, response, body) { if (!err && response.statusCode == 200) { res.json(JSON.parse(body)); } });
prepay_id
和支付签名验证paySign
图片说明
经过
wx.requestPayment
方法来调起支付功能
图片说明
prepay_id
的获取和签名paySign
,是从小程序请求后台来的.
图片说明
第一步:调用wx.login(object)
获取用户的code
,code
换取session_key
,
微信的第三个接口,统一下单,获取prepay_id
,第四个接口,wx.requestPayment(object)
,成功后,请求支付后的结果.
先执行wx.login
小程序代码:
<view> <button bindtap='wxpay' class='css'>发起支付</button> </view>
// js var app=getApp(); Page({ wxpay: function(){ var code=app.code; wx.request({ url: SERVER_PATH+'wxpayapi/, data: { code: code }, header: { 'content-type': 'application/json' }, success: function (res) { console.log(res.data); var data=res.data; wx.requestPayment({ 'timeStamp': data.timeStamp, 'nonceStr': data.nonceStr, 'package': data.package, 'signType': 'MD5', 'paySign': data.paySign, 'success': function (res) { console.log("支付成功!") }, 'fail': function (res) { } }) } }) } })
https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1
图片说明
实例参考地址:
https://pan.baidu.com/s/1pKLgG8z
https://pan.baidu.com/s/1nuBH0EX
达叔小生:日后余生,惟独有你
You and me, we are family !
90后帅气小伙,良好的开发习惯;独立思考的能力;主动而且善于沟通
简书博客: 达叔小生
https://www.jianshu.com/u/c785ece603d1
下面我将继续对 其余知识 深刻讲解 ,有兴趣能够继续关注
小礼物走一走 or 点赞
这是一个有质量,有态度的公众号
喜欢本文的朋友们
欢迎长按下图关注订阅号
收看更多精彩内容