Vue——H5微信内支付
业务场景介绍:
Vue2--------H5移动端微信支付 >>>微信内支付(JSAPI支付)
订单生成逻辑:前端判断设备获取code,根据code调用后端接口获取openId, 前端携带相关参数请求后端提交订单,后端去和微信对接生成订单,返回订单支付信息,拉取微信支付
开发前准备:
开通商户当然开通其他微信相关支付这个也是必不可少的比如这些
开通,进行商户和公众号关联绑定
其中还要配置相关,支付域名,回调域名等等一些域名的配置详见微信支付对应的开发文档(实际以开发文档为准),所以提前申请域名也必不可少
获取code,获取openId
参考获取code之后,通过code调用后端接口获取openId
插曲:获取code时页面会重定向,读取url获取code,调用openId接口,因为第一次本地是没有存的,所以首次点击可能是进入重定向页面第二次才生效然后进入拉起支付(想要避免根据实际需求进行修改获取openId,比如监听路由、根据携带参数)
其中 scope应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且, 即使在未关注的情况下,只要用户授权,也能获取其信息 )
export function getUrlCodeParam(name) {
const regex = new RegExp(`[\\?&]${name}=([^&#;]+)(?:&|#;|$)`);
const match = regex.exec(location.href);
if (match) {
const paramValue = decodeURIComponent(match[1].replace(/\+/g, "%20"));
return paramValue;
}
return null;
}
export const getOpenId = () => {
return new Promise(async (resolve, reject) => {
console.log("初始化");
let ua = navigator.userAgent.toLowerCase();
if (!/micromessenger/.test(ua)) {
console.log("不在微信环境内");
return resolve("");
}
console.log("微信内部环境");
let openid = sessionStorage.getItem("wx_Openid_2024");
if (openid) return resolve(openid);
const code = getUrlCodeParam("code");
if (code) {
console.log(code, "code");
try {
const res = await weixinH5Openid({ code, payProject: "icommission" });
console.log(res);
openid = res.body ? res.body.openid : "";
sessionStorage.setItem("wx_Openid_2024", openid);
resolve(openid);
} catch (error) {
console.error("获取openid失败", error);
reject(error);
}
} else {
let redirectUri = encodeURIComponent(window.location.href);
const appId = "wx99c163b3b6*****";
const url = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appId}&redirect_uri=${redirectUri}&forcePopup=true&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect`;
window.location.href = url;
return resolve("");
}
});
};
使用方法
import { getOpenId, wxpay } from '@/utils/common'
const isWechatBrowser = /micromessenger/i.test(navigator.userAgent);
if (isWechatBrowser) {
try {
let openid = await getOpenId();
if (openid) {
}else {
}
} catch (error) {
console.error('获取 openId 失败:', error);
}
}
提交订单,拉起微信支付
携带参数调取后端接口,生成订单,返回订单信息,然后根据订单信息拉起微信支付
可以先在index.html引用
<script src="http://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
common.js
import { weixinH5Openid } from "@/api/login";
export function wxpay(params, callback) {
if (typeof WeixinJSBridge == "undefined") {
if (document.addEventListener) {
document.addEventListener(
"WeixinJSBridgeReady",
onBridgeReady(params, callback),
false
);
} else if (document.attachEvent) {
document.attachEvent(
"WeixinJSBridgeReady",
onBridgeReady(params, callback)
);
document.attachEvent(
"onWeixinJSBridgeReady",
onBridgeReady(params, callback)
);
}
} else {
onBridgeReady(params, callback);
}
}
function onBridgeReady(params, callback) {
WeixinJSBridge.invoke(
"getBrandWCPayRequest",
{
appId: params.appId,
timeStamp: String(params.timeStamp),
nonceStr: params.nonceStr,
package: params.prepayId,
signType: params.signType,
paySign: params.sign,
},
function (res) {
callback(res);
}
);
}
在需要使用的地方引入调用
import { getOpenId, wxpay } from '@/utils/common'
wxpay(body, (payResult) => {
if (payResult.err_msg == "get_brand_wcpay_request:ok") {
console.log("支付成功");
this.$toast({ message: '支付成功', duration: 1000 });
this.payPopup = false
this.timer = setTimeout(() => {
this.$router.push({
path: '/',
})
clearTimeout(this.timer)
}, 1000)
} else if (payResult.err_msg == "get_brand_wcpay_request:cancel") {
this.payPopup = false
this.$toast({ message: '支付取消', duration: 1000 });
} else if (payResult.err_msg == "get_brand_wcpay_request:fail") {
this.payPopup = false
this.$toast({ message: '支付失败', duration: 1000 });
}else {
this.payPopup = false
this.$toast({ message: '未知错误', duration: 1000 });
}
})
beforeDestroy() {
clearTimeout(this.timer)
},
效果图
拉起微信支付也可以使用
安装依赖
npm install weixin-jsapi --save
在需要调起支付的页面引用
import wx from 'weixin-jsapi'
wxPayFc(body) {
let _this = this
wx.config({
debug: false,
"appId": body.appId,
"timeStamp": String(body.timeStamp),
nonceStr: body.nonceStr,
signature: sign,
jsApiList: ['chooseWXPay', 'checkJsApi']
})
wx.ready(() => {
wx.chooseWXPay({
"timeStamp": String(body.timeStamp),
nonceStr: body.nonceStr,
"nonceStr": body.nonceStr,
"package": body.prepayId,
"signType": body.signType,
"paySign": body.sign,
success: function (payRes) {
_this.$toast({ message: '支付成功', duration: 1000 });
},
cancel: function (payRes) {
_this.$toast({ message: '取消支付', duration: 1000 });
},
fail: function (payRes) {
_this.$toast({ message: '支付失败', duration: 1000 });
}
})
})
},