- 基本条件:公众号需要开通h5支付权限,这个权限需要很长时间,要提前请求审核,而且必须是商户号才能开通,普通用户用不了的。如果支付权限要等很久,可以用支付沙箱先测试等待流程,我的上篇文章中写到过,可以参考。
https://blog.csdn.net/weixin_44500533/article/details/107005387
h5支付微信官方文档,参考文档:https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=15_1
- 所谓的h5, 就是手机端非微信浏览器,手机里的safari, qq浏览器之内的。
⏰h5支付很简单,不考虑权限的情况下,前期不需要后端开发接口,前端可以独立完成支付流程。但请注意:微信支付的接口完全可以请后端的同学来完成,前端同学业务代码很多的情况下,就让后端给一个支付接口就好啦!!至于他怎么请求的微信,就是后端同学需要学习的事啦!!!😄
- 官方的参考文档在 官方文档-开发步骤&常见问题 中:
⏰官方已经将操作流程写的非常清楚了,按照这个流程做就一定没问题哒👌🙆♂️,还是那句话,多看文档,多看官方文档!!!!到每一步都很清楚的程度!!!!!! ✅
第一步:
需要一个点击事件,唤起微信支付。也就是,写一个点击事件,调起后来的请求方法。
第二步:
由商户后台向微信支付发起下单请求(调用统一下单接口)注:交易类型trade_type=MWEB
https://api.mch.weixin.qq.com/pay/unifiedorder
这个接口是微信的。所以这个接口使用的时候,开发调试时可能会出现跨域,需要自己配置一下nginx代理。代理的配置我有空会写出来!!!如果不考虑业务分离的情况,可以直接让后端代为请求这个接口,你把xml传给后端即可的!这样解决的很快,后端不会跨域的🐔
我用的是uniapp的请求方式 , 但自己使用可以建议引入axios😁
uni.request({
url: '/prefix/pay/unifiedorder',
data: {
xml //这个xml就是唯一请求体,其中的签名、随机串和转码是关键
},
method: 'POST',
header: {
header: { 'content-type': 'application/x-www-form-urlencoded'}
},
success: (res) => {
console.log(res.data)
let ress = res.data
let resXml = this.$x2js.xml2js(ress)
let mweb_url = resXml.xml.mweb_url
// location.href = mweb_url 跳转到微信支付
},
fail: function(res) {
console.log(res.data);
}
});
## 这里需要注意的一点是,这里的post请求需要发送xml文件,这是一个难点,我当时也查了很久才知道怎么做。具体的内容请见下文。
## 这个接口的返回会拿到一个回调地址mweb_url,这个地址就是在浏览器唤起微信客户端微信支付的关键。拿到这个回调地址,这个微信支付过程就完成90%了。🎉你 😁
-------------------------------------------------------------
详细说明:请求体xml是什么?
准备工作:
- 引入需要的插件:
import md5 from ‘js-md5’ //签名需要的
mian.js
import x2js from ‘x2js’ //json和xml的互转插件
Vue.prototype.$x2js = new x2js()
前期测试的时候,可以多多借助在线son和xml的互转的网页 会很方便哟
https://www.sojson.com/json2xml/
- 跨域的解决
我是让后端代为请求的,引起跨域的接口让后端代为请求,我自己再请求的时候就不会出现跨域的问题了。 但较好的做法是使用nginx代理,后面有时间我会单独写一篇跨域代理的贴出来😁
this.getNum() //得到this.nums
let timestamp = Math.round(new Date() / 1000)
this.time = timestamp.toString() //得到this.time
let dataBeforeSign = {
"appid": "wxc8d81336736a6d43",
"body": "微信支付",
"mch_id": "1594545781",
"nonce_str": this.nums,
"notify_url": "http://121.196.178.39:8000/api/callBack/wx_pay_callBack",
"out_trade_no": this.time,
"spbill_create_ip": "121.196.178.39",
"total_fee": "1",
"trade_type": "MWEB"
}
## 需要签名的内容
let arr = [];
for (var key in dataBeforeSign) {
arr.push(key)
}
arr.sort();
## 参数名ASCII码从小到大排序(字典序)
let str = '';
for (var i in arr) {
str += arr[i] + "=" + dataBeforeSign[arr[i]] + "&"
}
let stringA = str.substr(0, str.length - 1)
## 对参数按照key=value的格式,并按照参数名ASCII字典序排序
let stringSignTemp=stringA+"&key=ecde02f1dc9bbed7bf39ea922952bdf4"
## 拼接API密钥
this.sign=md5(stringSignTemp).toUpperCase()
//得到md5的签名 **签名的生成算法**规则微信文档上写的很清楚,这里使用代码的形式展示了规则。关于签名,官方文档上有签名校验工具网页,前期不确定时可以多用用这个工具进行测试😁
let data = {
"appid": "wxc8d81336736a6d43",
"body": "微信支付",
"mch_id": "1594545781",
"nonce_str": this.nums,
"notify_url": "http://121.196.178.39:8000/api/callBack/wx_pay_callBack",
"out_trade_no": this.time,
"spbill_create_ip": "121.196.178.39",
"total_fee": "1",
"trade_type": "MWEB",
"sign": this.sign
}
let xmll = this.$x2js.js2xml(data)
let xmlq = `<root>`+ xmll+ `</root>`
let xml = "\`"+xmlq+"\`"
## 这里xml转好了之后,会遇到一个新难题哟 🈶️ 😯
怎么将xml像json一样,放在post请求体中进行请求呢???
我在网上找了很多,自己试了很多次,才发现:
**将xml作为Text类型传递就好啦 完美解决!也就是说,在xml外部,包裹''作为字符串传入post请求**
这样的话,就实现了
***每次使用变量得到新的xml,再将xml外层包裹引号成为Text字符串***
到此,我们就得到了传递给微信接口的xml啦!!!!!!😄
------------------------------
getNum(){
var chars = ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'];
var nums="";
for(var i=0;i<32;i++){
var id = parseInt(Math.random()*35);
nums+=chars[id];
}
this.nums = nums
return nums;
}
第三步:访问这个回调地址
location.href = mweb_url 获取到后直接跳转就行啦!!!
✅OK啦!!!完成
最后说明:开发过程中总会遇到🙅错误说明的,一步到位的情况比较少的,所以我们解决问题的方式就非常重要啦!!!
那么,当我们遇到了问题应该怎么办呢?
正确答案:看官方文档:
贴出地址:开发步骤&常见问题https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=15_4
还有,我最后开发都完成的时候,遇到了一个十分尴尬的问题:
文档上的一串红字,请注意⚠️
当我们查询时,一定要给一个弹框触法哟,不然结果可能不准确滴!!!!一定哟,不要怕麻烦!!!
查询的步骤和支付差不多滴,仔细就好!!!
注意⚠️ 查询的话建议让后端同学👩🎓进行,因为查询让后端做的话,方便后续的权限问题的解决哈