使用 uniapp 开发打包成h5 需要调用微信支付,分两种情况,一种是在浏览器的打开,后台返回一个链接跳转会打开微信来付款,如果是在微信中打开,环境是微信浏览器需要调用微信原后的支付。
支付步骤
- 创建订单
- 通过订单号拿到支付需要的参数
- 通过判断环境发起 web支付还是微信支付
环境判断工具
export const isWxBrowser = () => {
// 判断是否H5微信环境,true为微信浏览器
const ua = navigator.userAgent.toLowerCase();
return ua.includes("micromessenger");
};
export const isIos = () => {
// 是否IOS true为ios
let u = navigator.userAgent;
let isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
return isIOS ? true : false;
};
组装返回的url
const buildReturnUrl = (orderNum) => {
const baseUrl = window.location.origin;
const returnUrl = `${baseUrl}/pages/match/buyTicketDetail?orderNum=${orderNum}`;
return returnUrl;
};
支付判断
通过订单号发起相应的支付
import { isWxBrowser } from "@/utils/env";
const orderPayFn = async (orderNum) => {
let payParams = {
detailsId: "0001",
orderNum,
transactionType: !isWxBrowser() ? "WX_MWEB" : "WX_JSAPI",//后台规定的两种支付方式
openId: undefined,//微信原生支付才需要
};
if (isWxBrowser()) {
let currentOpenId = "";
try {
currentOpenId = uni.getStorageSync("openId") || "";
} catch (error) {
console.log("获取 openId 失败:", error);
}
if (!currentOpenId) {
currentOpenId = openId.value || "";
}
payParams.openId = currentOpenId;
} else {
payParams.openId = undefined;
}
console.log("支付参数:", payParams);
try {
let res = await orderPay(payParams);
if (res.status === 0) {
if (isWxBrowser()) {
let data = JSON.parse(res.data);
console.log("支付数据:", data);
await callWeixinPay(data, orderNum);
} else {
await handleWebPay(res.data, orderNum);
}
} else {
uni.showToast({
title: res.msg,
icon: "none",
});
}
} catch (error) {
console.log(error);
}
};
h5支付
const handleWebPay = async (payData, orderNum) => {
const returnUrl = buildReturnUrl(orderNum);
const redirectUrl = encodeURIComponent(returnUrl);
const separator = payData.includes("?") ? "&" : "?";
const payUrlWithRedirect = `${payData}${separator}redirect_url=${redirectUrl}`;
window.location.href = payUrlWithRedirect;
};
微信支付
支付官方文档:https://pay.weixin.qq.com/doc/v3/merchant/4012791857
获取openId
支付之前需要获取 openId
const getOpenId = async () => {
try {
let localOpenId = "";
try {
localOpenId = uni.getStorageSync("openId") || "";
} catch (error) {
console.log("获取本地 openId 失败:", error);
}
if (localOpenId) {
openId.value = localOpenId;
console.log("从本地获取到 openId:", localOpenId);
return localOpenId;
}
const urlParams = new URLSearchParams(window.location.search);
const code = urlParams.get("code");
if (code) {
const res = await openIdByWxCode({ code, tokenType: "gz-platform" });
if (res.status === 0) {
const newOpenId = res.data;
uni.setStorageSync("openId", newOpenId);
openId.value = newOpenId;
console.log("成功获取并存储 openId:", newOpenId);
return newOpenId;
}
} else if (isWxBrowser()) {
startWxAuth();
}
return null;
} catch (error) {
console.error("获取 openId 失败:", error);
return null;
}
};
获取授权
在通过 openId 获取静默授权
const startWxAuth = () => {
try {
const currentUrl = new URL(window.location.href);
const currentParams = currentUrl.searchParams;
const newParams = new URLSearchParams();
for (const [key, value] of currentParams) {
if (key !== "code" && key !== "state") {
newParams.append(key, value);
}
}
const baseUrl = window.location.origin + window.location.pathname;
const redirectUrl = newParams.toString()
? `${baseUrl}?${newParams.toString()}`
: baseUrl;
const redirectUri = encodeURIComponent(redirectUrl);
const appId = WECHAT_APPID;
const authUrl = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appId}&redirect_uri=${redirectUri}&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect`;
window.location.href = authUrl;
} catch (error) {
console.error("微信授权失败:", error);
uni.showToast({
title: "授权失败",
icon: "none",
});
}
};
获取需要在页面加载 的时候 就获取到
onLoad(async (options) => {
if (isWxBrowser()) {
await getOpenId();
}
})
获取订单号
const poserbuyTicket = async () => {
isBuying.value = true;
orderParams.value.layoutId = detail.value.layoutId;
try {
let res = await buyTicket(orderParams.value);
if (res.status === 0) {
await orderPayFn(res.data);
} else {
uni.showToast({
title: res.msg,
icon: "none",
});
}
} catch (error) {
console.log(error);
} finally {
setTimeout(() => {
isBuying.value = false;
}, 2000);
}
};
微信支付
const callWeixinPay = (payData, orderNum) => {
const onBridgeReady = () => {
WeixinJSBridge.invoke(
"getBrandWCPayRequest",
{
appId: payData.appId,
timeStamp: payData.timeStamp,
nonceStr: payData.nonceStr,
package: payData.package,
signType: payData.signType || "RSA",
paySign: payData.paySign,
},
function (res) {
console.log("微信支付结果:", res);
if (res.err_msg == "get_brand_wcpay_request:ok") {
uni.showToast({
title: "支付成功",
icon: "success",
});
setTimeout(() => {
uni.reLaunch({
url: `/pages/match/buyTicketDetail?orderNum=${orderNum}`,
});
}, 1500);
} else if (res.err_msg == "get_brand_wcpay_request:cancel") {
uni.showToast({
title: "支付已取消",
icon: "none",
});
postcancelPay(orderNum);
} else {
uni.showToast({
title: "支付失败",
icon: "none",
});
postcancelPay(orderNum);
}
}
);
};
if (typeof WeixinJSBridge == "undefined") {
if (document.addEventListener) {
document.addEventListener("WeixinJSBridgeReady", onBridgeReady, false);
} else if (document.attachEvent) {
document.attachEvent("WeixinJSBridgeReady", onBridgeReady);
document.attachEvent("onWeixinJSBridgeReady", onBridgeReady);
}
} else {
onBridgeReady();
}
};
取消订单
const postcancelPay = async (orderNum) => {
try {
let res = await cancelPay(orderNum);
if (res.status === 0) {
console.log("取消订单成功");
}
} catch (error) {
console.log("postcancelPay", error);
}
};
参考文档
CSDN:https://blog.csdn.net/qq_73617452/article/details/147431223