Files
frontend-app/utils/payUtils.js
T
2026-09-09 11:46:36 +08:00

392 lines
13 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { feedback } from "@/api/payment.js";
/**
* 微信支付
* @param {Object} alipay 微信支付的参数
* @param {Object} orderId 支付的订单ID
* @param {Object} orderNum 支付的订单编号
*/
export function appWxpayFun(alipay, orderId, orderNum) {
const type = alipay.type;
const orderStr = alipay.orderStr;
console.log("微信支付---", alipay, type);
if (type === "app") {
// app
const orderInfo = {
appid: alipay.appId, // 微信开放平台 - 应用 - AppId,注意和微信小程序、公众号 AppId 可能不一致
noncestr: alipay.nonceStr, // 随机字符串
package: "Sign=WXPay", // 固定值
partnerid: alipay.partnerId, // 微信支付商户号
prepayid: alipay.prepayId, // 统一下单订单号
timestamp: alipay.timeStamp, // 时间戳(单位:秒)
sign: alipay.sign, // 签名,这里用的 MD5/RSA 签名
};
uni.requestPayment({
provider: "wxpay",
orderInfo: orderInfo,
success: function (res) {
console.log("success:" + res);
payFeedbackFun(orderId, orderNum, 1);
jumpWayOk();
},
fail: function (err) {
console.log("fail:", err);
jumpWayError();
},
});
} else if (type === "wechatMiniProgram") {
const orderInfo = {
// "appid": alipay.appId, // 微信开放平台 - 应用 - AppId,注意和微信小程序、公众号 AppId 可能不一致
nonceStr: alipay.nonceStr, // 微信支付商户号
package: alipay.packageValue, // 统一下单订单号
timeStamp: alipay.timeStamp, // 时间戳(单位:秒)
signType: "RSA",
paySign: alipay.sign, // 签名,这里用的 MD5/RSA 签名
};
console.log("微信小程序支付---", orderInfo);
uni.requestPayment({
...orderInfo,
success: function (res) {
console.log("success:" + res);
payFeedbackFun(orderId, orderNum, 1);
jumpWayOk();
},
fail: function (err) {
console.log("fail:", err);
jumpWayError();
},
});
} else if (type === "h5") {
// h5
uni.navigateTo({
url:
`/pages/other_package/payment_processing/payment_processing?link=${encodeURIComponent(
orderStr
)}&orderNum=` + orderNum, // 假设有一个专门的支付页面来处理支付链接
});
}
}
/**
* 支付宝支付
* @param {Object} alipay 微信支付的参数
* @param {Object} orderId 支付的订单ID
* @param {Object} orderNum 支付的订单编号
*/
export function zfbPayFun(alipay, orderId, orderNum) {
console.log("alipay", alipay);
const type = alipay.type;
const orderStr = alipay.orderStr;
if (type === "h5") {
// h5
uni.navigateTo({
url:
`/pages/other_package/payment_processing/payment_processing?link=${encodeURIComponent(
orderStr
)}&orderNum=` + orderNum, // 假设有一个专门的支付页面来处理支付链接
});
} else if (type === "app") {
// app
uni.requestPayment({
provider: "alipay",
orderInfo: orderStr,
success: function (res) {
console.log("zfbPayFun res", res);
payFeedbackFun(orderId, orderNum, 1);
jumpWayOk();
},
fail: function (err) {
console.error("支付宝支付error", err);
jumpWayError();
},
});
}
// return new Promise((resolve, reject) => {
// resolve(res);
// // reject(err);
// });
}
/**
* 抖音支付(兼容 iOS、Android App 端)
* @param {Object|String} dyPay 抖音支付参数 (支持 orderStr, schema, url, payUrl, orderInfo 等)
* @param {Object|String|Number} orderId 支付的订单ID
* @param {Object|String} orderNum 支付的订单编号
*/
export function douyinPayFun(dyPay, orderId, orderNum) {
console.log("抖音支付---入参:", dyPay, orderId, orderNum);
return new Promise((resolve, reject) => {
if (!dyPay || (typeof dyPay === "object" && Object.keys(dyPay).length === 0)) {
uni.showToast({
title: "支付参数错误",
icon: "none",
});
jumpWayError();
return reject(new Error("支付参数为空"));
}
const d = typeof dyPay === "object" ? dyPay : {};
const sub = (typeof d.orderInfo === "object" && d.orderInfo) ? d.orderInfo : {};
const type = typeof dyPay === "object" ? (dyPay.type || "app") : "app";
// 1. 提取或生成 Scheme / URL (注意:排除 sign,避免将签名误认为 URL)
let orderStr = "";
if (typeof dyPay === "string") {
orderStr = dyPay;
} else if (typeof dyPay === "object") {
orderStr =
dyPay.orderStr ||
dyPay.schema ||
dyPay.scheme ||
dyPay.url ||
dyPay.payUrl ||
dyPay.link ||
sub.orderStr ||
sub.schema ||
sub.scheme ||
sub.url ||
"";
// 如果未配置直接链接,则尝试通过 prepayId / pay_token 自动生成抖音收银台 Scheme 备用
const token = d.prepayId || d.prepayid || sub.prepayid || sub.prepayId;
if (!orderStr && token) {
orderStr = `snssdk1128://pay?pay_token=${encodeURIComponent(token)}`;
}
}
console.log("抖音支付---提取到的 Scheme / orderStr:", orderStr);
// 2. 深度合并/映射原生支付所需的 orderInfo(融合根节点与 orderInfo 子节点,同时提供驼峰与小写命名)
const appId = d.appId || d.appid || sub.appId || sub.appid || "";
const mchId = d.mchId || d.partnerid || d.mchid || sub.mchId || sub.partnerid || sub.mchid || "";
const prepayId = d.prepayId || d.prepayid || sub.prepayId || sub.prepayid || "";
const callbackScheme = d.callbackScheme || sub.callbackScheme || "trustbridgeapp";
const packageValue = d.packageValue || d.package || sub.packageValue || sub.package || "Sign=DYPay";
const nonceStr = d.nonceStr || d.noncestr || sub.nonceStr || sub.noncestr || "";
const timeStamp = String(d.timeStamp || d.timestamp || sub.timeStamp || sub.timestamp || "");
const sign = d.sign || sub.sign || "";
const orderInfo = {
// 驼峰命名(标准 uni.requestPayment / 抖音 SDK)
appId,
mchId,
prepayId,
callbackScheme,
packageValue,
nonceStr,
timeStamp,
sign,
// 小写命名(部分原生桥接 SDK 兼容)
appid: appId,
partnerid: mchId,
mchid: mchId,
prepayid: prepayId,
package: packageValue,
noncestr: nonceStr,
timestamp: timeStamp,
service: 5,
};
// #ifdef APP-PLUS
// 情形 A:如果显式指定为 H5 方式
if (
type === "h5" &&
orderStr &&
(orderStr.startsWith("http://") || orderStr.startsWith("https://"))
) {
uni.navigateTo({
url:
`/pages/other_package/payment_processing/payment_processing?link=${encodeURIComponent(
orderStr
)}&orderNum=` + orderNum,
});
resolve({ status: "processing" });
return;
}
// 情形 B:如果后端直接传入了协议 Scheme 串(如以 snssdk1128://, douyin:// 开头)
if (
typeof dyPay === "string" ||
(dyPay.orderStr && (dyPay.orderStr.startsWith("snssdk") || dyPay.orderStr.startsWith("douyin")))
) {
let openSuccess = false;
// iOS Native.js 尝试
if (plus.os.name === "iOS") {
try {
const UIApplication = plus.ios.importClass("UIApplication");
const NSURL = plus.ios.importClass("NSURL");
const app = UIApplication.sharedApplication();
const nsUrl = NSURL.URLWithString(orderStr);
if (app && nsUrl && app.openURL(nsUrl)) {
openSuccess = true;
}
} catch (nativeErr) {
console.warn("iOS Native.js openURL 尝试:", nativeErr);
}
}
// Android Native.js 尝试
if (plus.os.name === "Android") {
try {
const Intent = plus.android.importClass("android.content.Intent");
const Uri = plus.android.importClass("android.net.Uri");
const main = plus.android.runtimeMainActivity();
const intent = new Intent(Intent.ACTION_VIEW, Uri.parse(orderStr));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
main.startActivity(intent);
openSuccess = true;
} catch (androidErr) {
console.warn("Android Native.js Intent 尝试:", androidErr);
}
}
if (!openSuccess) {
plus.runtime.openURL(
orderStr,
() => {
if (orderNum) {
uni.navigateTo({
url:
`/pages/other_package/payment_processing/payment_processing?orderNum=` +
orderNum,
});
}
resolve({ status: "invoked" });
},
(err) => {
console.error("拉起抖音客户端失败:", err);
const isSimulator =
plus.navigator && plus.navigator.isSimulator
? plus.navigator.isSimulator()
: false;
let tip = "未检测到抖音客户端或拉起失败,请确认是否已安装抖音客户端";
if (isSimulator) {
tip = "iOS模拟器无法打开第三方应用Scheme,请在安装了抖音的真机上测试";
} else if (err && err.code === -3) {
tip = "未检测到抖音应用或当前基座未配置Scheme白名单,请确认真机已安装抖音";
}
uni.showToast({
title: tip,
icon: "none",
duration: 3000,
});
jumpWayError();
reject(err);
}
);
} else {
if (orderNum) {
uni.navigateTo({
url:
`/pages/other_package/payment_processing/payment_processing?orderNum=` +
orderNum,
});
}
resolve({ status: "invoked" });
}
return;
}
// 情形 C:使用 uni.requestPayment 调起原生支付,失败时通过生成 Scheme 降级拉起
uni.requestPayment({
provider: "toutiao",
orderInfo: orderInfo,
service: 5,
success: function (res) {
console.log("抖音支付成功:", res);
payFeedbackFun(orderId, orderNum, 1);
jumpWayOk();
resolve(res);
},
fail: function (err) {
console.error("uni.requestPayment 抖音支付失败/不兼容,尝试 Scheme 降级拉起:", err);
if (orderStr) {
plus.runtime.openURL(
orderStr,
() => {
if (orderNum) {
uni.navigateTo({
url:
`/pages/other_package/payment_processing/payment_processing?orderNum=` +
orderNum,
});
}
resolve({ status: "invoked_fallback" });
},
(openErr) => {
console.error("openURL 降级失败:", openErr);
jumpWayError();
reject(err);
}
);
} else {
jumpWayError();
reject(err);
}
},
});
return;
// #endif
// 兜底处理 (H5 及非 App 环境)
if (orderStr) {
uni.navigateTo({
url:
`/pages/other_package/payment_processing/payment_processing?link=${encodeURIComponent(
orderStr
)}&orderNum=` + orderNum,
});
resolve({ status: "processing" });
} else {
uni.showToast({
title: "抖音支付暂仅支持在 App 端调用",
icon: "none",
});
jumpWayError();
reject(new Error("抖音支付暂仅支持在 App 端调用"));
}
});
}
// 导出别名方便不同调用习惯
export const dyPayFun = douyinPayFun;
export const appDyPayFun = douyinPayFun;
export const appDouyinPayFun = douyinPayFun;
// 跳转到支付成功页面
export function jumpWayOk() {
uni.navigateTo({
url: "/pages/order_package/order_submit_ok/order_submit_ok",
});
}
// 跳转到支付失败页面
export function jumpWayError() {
uni.navigateTo({
url: "/pages/order_package/order_submit_error/order_submit_error",
});
}
/**
* 支付结果回调
* @param {Object} orderId 支付订单ID
* @param {Object} orderNum 支付订单编号
* @param {Object} status 反馈结果【0:失败,1:成功】
*/
async function payFeedbackFun(orderId, orderNum, status) {
const params = {
orderId,
orderNum,
status,
};
console.log("params", params);
const response = await feedback(params);
console.log("payFeedbackFun response", response);
if (response && response.bizcode !== 100) {
console.error("反馈结果", response);
}
}