微信支付,h5支付,jsapi支付

因业务需要,开发微信支付功能,涉及三种支付方式:

  • JSAPI 支付:微信内网页支付,需要开通微信服务号
  • 小程序支付:在小程序中支付,需要开通小程序
  • H5 支付:在手机浏览器(出微信内网爷)中网页支付

使用微信支付的前提必开通微信商户号,要使用到那种的支付方式要前需在商户平台开通(要审核)。

支付的钱最终都会到商户号里(一般由公司财务开通)。

开发微信支付的过程中大大小小坑还是踩了不少,终于做完了,整理下开发流程。

参考:

  • 微信支付-接入指引
  • 微信支付-开发文档

小程序支付

开发流程

  • 小程序端请求创建订单接口,后端统一下单获取 orderId 并返回
  • 小程序端获取通过wx.login()获取code
  • 小程序端拿这code和orderId请求后端接口,获取支付所需数据
  • 获取支付所需数据之后,小程序端调用wx.requestPayment()接口,直接调用起支付页面
  • 判断是否支付成功后的逻辑

伪代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
async function wxPay(goodId) {
// 1. 创建订单 获取orderId
let orderId = await ajax("POST", "/api/OrderProgram/CreateTheOrder", {
goodId, // 商品id
});
// 2. 获得 code
let code = await wxlogin(); // 基于pr封装的wx.login()方法
// 3. 获取支付的数据
let payData = await ajax("POST", "/api/OrderProgram/WxXcxPay", {
orderId,
code,
});
// 4. 发起支付
let res = await payment(payData); // 基于pr封装的wx.requestPayment()方法
// 5. 判断是否支付成功
let payResult = res.errMsg;
if (payResult == "requestPayment:ok") {
console.log("支付成功");
} else if (payResult == "requestPayment:fail cancel") {
console.log("用户取消支付");
} else {
console.log("支付失败");
}
}

注意事项

  1. 申请微信小程序账号

申请成功可拿到 AppID(小程序 id)和 AppSecret(小程序密钥)
申请类型为企业性质,否则无法接入微信支付

  1. 微信小程序认证

通过认证的小程序才能接入微信支付和绑定商户平台

  1. 申请商户平台账号

需要第一步申请的 AppID
申请成功可拿到 MchID(商户 id)和 MchKey(商户密钥)

  1. 信小程序关联商户号

微信和商户都认证成功后,在微信后台微信支付菜单中进行关联

  1. 接入微信支付

    在微信后台微信支付菜单中进行接入

参考

  • 小程序支付文档
  • 小程序开发文档

    H5 支付

    开发流程
  1. 前端端请求创建订单接口,后端统一下单获取 orderId 并返回
  2. 前端带着 orderId 请求支付接口,获得 mweb_url,
  3. 然后跳转 mweb_url 会跳转微信自动调用微信支付
  4. 支付后返回支付页,判断是否支付成功(需发送请求后端查询)

    刷新页面,获取最新的支付(订单)状态。

    设置一个的按钮”我已支付”,让用户点击自动查询状态。
    伪代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
async function wxH5Pay(goodId) {
// 1. 创建订单 获取orderId
let orderId = await ajax("POST", "/api/OrderProgram/CreateTheOrder", {
goodId, // 商品id
});
// 2. 获取支付跳转的URL
let mweb_url = await ajax("POST", "/api/OrderProgram/WxH5Pay", { orderId });
// 3. 跳转URL去微信支付
if (mweb_url) {
location.href = mweb_url;
} else {
console.log("回调地址出错");
}
// 4. 支付后返回支付页,判断是否支付成功
// 4.1 刷新页面,获取最新的订单(商品)状态。
// 4.2 设置一个"我已支付"的按钮,让用户点击之后查询状态。
}

注意事项

  • 在商户平台设置正确的支付域名
  • 调试需要在线上,如果嫌麻烦可以使用内网穿透(Ngrok 或花生壳)
  • 需对redirect_url进行urlencode处理
  • H5 支付不能直接在微信客户端内调起,请在外部浏览器调起。
    参考

  • 微信支付-H5 支付-开发步骤

    JSAPI 支付(微信内网页支付)

    开发流程

商品页

  1. 前端商品页创建订单,在后端统一下单后获取 orderId
  2. 前端带着 orderId 跳转到支付页,

    支付页

  3. 获取 code
  • 第一次进入页面,判断是否路径中有 code
  • 没有 code,请求数据跳转授权页面,code 会通过回调地址一起返回回来
  • 拿到 code,发送给后端,后端解析到 openid,保存好。
  1. 点击确定支付按钮,触发 wxPay() 方法

  2. 发送 orderId 给后端,获取 wxData

  3. wxData 中包含 wx.config 和 wx.chooseWXPay 两个接口的数据。
  4. 先调用 wx.config()然后在调用 wx.chooseWXPay(),如果一切正常,支付页面就会弹出。

  5. 支付状态通过后端去查询
    伪代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
商品页
// 1. 创建订单 获取orderId
let orderId = await ajax("POST", "/api/OrderProgram/CreateTheOrder", {
goodId, // 商品id
});
// 2. 携带id 跳转到支付页
this.$router.push({ name: "wx_pay_page", params: { orderId: id } });
入口文件(main.js)
// main.js 引入 js-sdk
import wx from "weixin-js-sdk";
支付页 HTML
<template>
<div>
<button @click="wxPay">点击支付button>
div>
template>
支付页 JS

// Vue
data(){
return {
orderId: this.$route.params.orderId, // 订单id
url: '',// 获取code的url
wxData: null,// js-sdk接口所需的数据
}
},
mounted(){
// 判断是否有code
this.getCode()
}
methods: {
getCode() {
var code = this.getUrlPram("code");
if (code != null) {
this.code = code;
// 拿到 code 发给 后端
this.sendCode(code);
} else {
// 去拿code
this.getUrl();
}
},
getUrl() {
// 请求后端拿到url所需数据,然后跳转页面在通过回调地址返回,获取code.
this.axios
.post("/api/OrderProgram/GetOpenidAndAccessToken", {
orderId: this.orderId,
})
.then((data) => {
this.url = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${data.appId}&redirect_uri=${data.redirect_uri}&response_type=${data.response_type}&scope=${data.scope}&state=${data.state}`;
window.location.href = this.url;
})
.catch((err) => {
console.log(err);
});
},
sendCode(code) {
// 发送code给后端 后端解析出openid
this.axios
.post("/api/OrderProgram/GetOpenidAndAccessTokenFromCode", {
code: code,
})
.then((res) => {
console.log(res);
})
.catch((err) => {
console.log(err);
});
},
wxPay: async function() {
// 发送orderid,获取wx.chooseWXPay和wx.config所需的参数
this.wxData = await this.axios.post(
"/api/OrderProgram/WxJSAPIPay",
{ orderId: this.orderId }
);
let wxConfigData = this.wxData.wxConfigData // 获取wx.chooseWXPay()所需数据
let wxPayData = this.wxData.wxPayData;// 获取wx.config()所需数据
this.$wx.config({
debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: wxConfigData.appId, // 必填,公众号的唯一标识
timestamp: wxConfigData.timeStamp, // 必填,生成签名的时间戳
nonceStr: wxConfigData.nonceStr, // 必填,生成签名的随机串
signature: wxConfigData.paySign, // 必填,签名
jsApiList: [
"chooseWXPay",
],
});
// 执行支付
this.$wx.chooseWXPay({
timestamp: wxPayData.timeStamp, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
nonceStr: wxPayData.nonceStr, // 支付签名随机串,不长于 32 位
package: wxPayData.package, // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=\*\*\*)
signType: wxPayData.signType, // 签名方式,默认为'SHA1',使用新版支付需传入'MD5'
paySign: wxPayData.paySign, // 支付签名
success: (res) => {
this.$toast("支付成功");
},
fail: (err) => {
this.$toast("支付失败");
},
});
},
}

同时支持 H5 支付和 JSAPI 支付

1
2
3
4
5
6
7
8
9
10
11
// 在创建订单之后,就判断环境使用哪种方法支付。
if (isWx()) {
this.WXPay(orderId); // 带着orderId跳转到支付页逻辑
} else {
this.H5Pay(orderId); // 执行上面H5支付中的创建订单之后的逻辑
}
// 判断是否是微信浏览器
function isWx() {
let uAgent = navigator.userAgent.toLowerCase();
reutrn(/micromessenger/.test(uAgent)) ? true : false;
}

注意事项
开通微信商户号 - 设置支付目录(如果是 Vue 这类 SPA 页面,到根目录即可,也就是#号之前的地址)

Buy me a cup of coffee,thanks!