Files
Friendship-and-chat-uniapp/src/sheep/platform/pay.js
T
2026-07-31 13:56:18 +08:00

471 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 sheep from '@/sheep';
// #ifdef H5
import $wxsdk from '@/sheep/libs/sdk-h5-weixin';
// #endif
import { getRootUrl } from '@/sheep/helper';
import { h5Url } from '@/sheep/config';
import PayOrderApi from '@/sheep/api/pay/order';
import { openExternalUrl } from './h5-shell';
/**
* 支付
*
* @param {String} payment = ['wechat','alipay','wallet','mock'] - 支付方式
* @param {String} orderType = ['goods','recharge','groupon'] - 订单类型
* @param {String} id - 订单号
*/
export default class SheepPay {
constructor(payment, orderType, id, autoPay = true) {
this.payment = payment;
this.id = id;
this.orderType = orderType;
if (autoPay) {
this.payAction();
}
}
static payH5(payment, orderType, id) {
return new SheepPay(payment, orderType, id, false).h5PayAction();
}
payAction() {
const payAction = {
WechatOfficialAccount: {
wechat: () => {
this.wechatOfficialAccountPay();
},
alipay: () => {
this.redirectPay(); // 现在公众号可以直接跳转支付宝页面
},
wallet: () => {
this.walletPay();
},
mock: () => {
this.mockPay();
},
},
WechatMiniProgram: {
wechat: () => {
this.wechatMiniProgramPay();
},
alipay: () => {
this.copyPayLink();
},
wallet: () => {
this.walletPay();
},
mock: () => {
this.mockPay();
},
},
App: {
wechat: () => {
this.wechatAppPay();
},
alipay: () => {
this.alipay();
},
wallet: () => {
this.walletPay();
},
mock: () => {
this.mockPay();
},
},
H5: {
wechat: () => {
this.wechatWapPay();
},
alipay: () => {
this.redirectPay();
},
wallet: () => {
this.walletPay();
},
mock: () => {
this.mockPay();
},
},
};
return payAction[sheep.$platform.name][this.payment]();
}
h5PayAction() {
const payAction = {
wechat: () => this.wechatWapPay(),
alipay: () => this.redirectPay(),
};
const action = payAction[this.payment];
if (!action) {
return Promise.reject(new Error(`H5 支付不支持支付方式: ${this.payment}`));
}
return action().then((started) => {
if (!started) {
throw new Error('H5 支付调起失败');
}
return true;
});
}
// 预支付
async prepay(channel, returnUrl = '') {
const data = {
id: this.id,
channelCode: channel,
channelExtras: {},
};
if (returnUrl) {
data.returnUrl = returnUrl;
}
// 特殊逻辑:微信公众号、小程序支付时,必须传入 openid
if (['wx_pub', 'wx_lite'].includes(channel)) {
const openid = await sheep.$platform.useProvider('wechat').getOpenid(true);
// 如果获取不到 openid,微信无法发起支付,此时需要引导
if (!openid) {
this.bindWeixin();
return { code: -1, data: null };
}
data.channelExtras.openid = openid;
}
const res = await PayOrderApi.submitOrder(data);
const message = res.msg || '';
if (
res.code !== 0 &&
(message.includes('无效的openid') || message.includes('下单账号与支付账号不一致'))
) {
// https://developers.weixin.qq.com/community/develop/doc/00008c53c347804beec82aed051c00
this.bindWeixin();
}
return res;
}
// #ifdef H5
// 微信公众号 JSSDK 支付
async wechatOfficialAccountPay() {
let { code, data } = await this.prepay('wx_pub');
if (code !== 0) {
return;
}
const payConfig = JSON.parse(data.displayContent);
$wxsdk.wxpay(payConfig, {
success: () => {
this.payResult('success');
},
cancel: () => {
sheep.$helper.toast('支付已手动取消');
},
fail: (error) => {
if (error.errMsg.indexOf('chooseWXPay:没有此SDK或暂不支持此SDK模拟') >= 0) {
sheep.$helper.toast(
'发起微信支付失败,原因:可能是微信开发者工具不支持,建议使用微信打开网页后支付',
);
return;
}
this.payResult('fail');
},
});
}
// #endif
// 微信 H5 支付
async wechatWapPay() {
const returnUrl = this.getH5PayResultUrl();
const { code, data } = await this.prepay('wx_wap', returnUrl);
if (code !== 0 || !data?.displayContent) {
return false;
}
const separator = data.displayContent.includes('?') ? '&' : '?';
const payUrl = returnUrl
? `${data.displayContent}${separator}redirect_url=${encodeURIComponent(returnUrl)}`
: data.displayContent;
this.openH5PayUrl(payUrl, '微信支付');
return true;
}
// 支付链接(支付宝 wap 支付)
async redirectPay() {
const { code, data } = await this.prepay('alipay_wap', this.getH5PayResultUrl());
if (code !== 0 || !data?.displayContent) {
return false;
}
this.openH5PayUrl(data.displayContent, '支付宝支付');
return true;
}
getH5PayResultUrl() {
let rootUrl = getRootUrl();
if (!rootUrl && h5Url) {
rootUrl = `${String(h5Url).replace(/\/+$/, '')}/#/`;
}
if (!rootUrl) {
return '';
}
return `${rootUrl}pages/profile/pay-result?id=${encodeURIComponent(this.id)}&payment=${encodeURIComponent(
this.payment,
)}&orderType=${encodeURIComponent(this.orderType)}`;
}
openH5PayUrl(url, title) {
// #ifndef MP
openExternalUrl(url, `h5-pay:${title}`);
// #endif
// #ifdef MP
uni.showModal({
title,
content: '请复制链接到手机浏览器完成支付',
confirmText: '复制链接',
success: (res) => {
if (res.confirm) {
sheep.$helper.copyText(url);
}
},
});
// #endif
}
// 微信小程序支付
async wechatMiniProgramPay() {
// let that = this;
let { code, data } = await this.prepay('wx_lite');
if (code !== 0) {
return;
}
// 调用微信小程序支付
const payConfig = JSON.parse(data.displayContent);
uni.requestPayment({
provider: 'wxpay',
timeStamp: payConfig.timeStamp,
nonceStr: payConfig.nonceStr,
package: payConfig.packageValue,
signType: payConfig.signType,
paySign: payConfig.paySign,
success: (res) => {
this.payResult('success');
},
fail: (err) => {
if (err.errMsg === 'requestPayment:fail cancel') {
sheep.$helper.toast('支付已手动取消');
} else {
this.payResult('fail');
}
},
});
}
// 余额支付
async walletPay() {
const { code } = await this.prepay('wallet');
code === 0 && this.payResult('success');
}
// 模拟支付
async mockPay() {
const { code } = await this.prepay('mock');
code === 0 && this.payResult('success');
}
// 支付宝复制链接支付(通过支付宝 wap 支付实现)
async copyPayLink() {
let { code, data } = await this.prepay('alipay_wap');
if (code !== 0) {
return;
}
// 引入 showModal 点击确认:复制链接;
uni.showModal({
title: '支付宝支付',
content: '复制链接到外部浏览器',
confirmText: '复制链接',
success: (res) => {
if (res.confirm) {
sheep.$helper.copyText(data.displayContent);
// uni.navigateTo({ url: '/pages/profile/alipay-webview?url=' + encodeURIComponent(data.displayContent) })
}
},
});
}
// 支付宝支付(App)
async alipay() {
let that = this;
const { code, data } = await this.prepay('alipay_app');
if (code !== 0) {
return;
}
// TODO @芋艿:【可优化】如果是沙箱支付,EnvUtils.setEnv(EnvUtils.EnvEnum.SANDBOX),相关 https://t.zsxq.com/yjyJQ
uni.requestPayment({
provider: 'alipay',
orderInfo: data.displayContent, // 直接使用返回的支付参数
success: (res) => {
that.payResult('success');
},
fail: (err) => {
if (err.errMsg === 'requestPayment:fail [paymentAlipay:62001]user cancel') {
sheep.$helper.toast('支付已手动取消');
} else {
that.payResult('fail');
}
},
});
}
// 微信支付(App)
async wechatAppPay() {
let that = this;
// 获取预支付信息
let { code, data } = await this.prepay('wx_app');
if (code !== 0) {
sheep.$helper.toast('获取支付信息失败');
return;
}
// 解析支付参数
let payConfig = JSON.parse(data.displayContent);
if (typeof payConfig.appId === 'undefined') {
payConfig.appId = payConfig.appid;
}
if (typeof payConfig.nonceStr === 'undefined') {
payConfig.nonceStr = payConfig.noncestr;
}
if (typeof payConfig.timeStamp === 'undefined') {
payConfig.timeStamp = payConfig.timestamp;
}
// 调用微信支付
uni.requestPayment({
provider: 'wxpay',
timeStamp: payConfig.timeStamp,
nonceStr: payConfig.nonceStr,
package: payConfig.packageValue,
signType: payConfig.signType,
paySign: payConfig.paySign,
success: (res) => {
that.payResult('success');
},
fail: (err) => {
if (err.errMsg === 'requestPayment:fail cancel') {
sheep.$helper.toast('支付已手动取消');
} else {
sheep.$helper.toast('支付失败:' + err.errMsg);
that.payResult('fail');
}
},
});
}
// 支付结果跳转,success:成功,fail:失败
payResult(resultType) {
goPayResult(this.id, this.orderType, resultType);
}
// 引导绑定微信
bindWeixin() {
goBindWeixin();
}
}
export function getPayMethods(channels) {
const payMethods = [
{
icon: '/static/img/shop/pay/wechat.png',
title: '微信支付',
value: 'wechat',
disabled: true,
},
{
icon: '/static/img/shop/pay/alipay.png',
title: '支付宝支付',
value: 'alipay',
disabled: true,
},
{
icon: '/static/img/shop/pay/wallet.png',
title: '余额支付',
value: 'wallet',
disabled: true,
},
{
icon: '/static/img/shop/pay/apple.png',
title: 'Apple Pay',
value: 'apple',
disabled: true,
},
{
icon: '/static/img/shop/pay/wallet.png',
title: '模拟支付',
value: 'mock',
disabled: true,
},
];
const platform = sheep.$platform.name;
// 1. 处理【微信支付】
const wechatMethod = payMethods[0];
if (
(platform === 'WechatOfficialAccount' && channels.includes('wx_pub')) ||
(platform === 'WechatMiniProgram' && channels.includes('wx_lite')) ||
(platform === 'App' && channels.includes('wx_app'))
) {
wechatMethod.disabled = false;
}
// 2. 处理【支付宝支付】
const alipayMethod = payMethods[1];
if (
(platform === 'H5' && channels.includes('alipay_wap')) ||
(platform === 'WechatOfficialAccount' && channels.includes('alipay_wap')) ||
(platform === 'WechatMiniProgram' && channels.includes('alipay_wap')) ||
(platform === 'App' && channels.includes('alipay_app'))
) {
alipayMethod.disabled = false;
}
// 3. 处理【余额支付】
const walletMethod = payMethods[2];
if (channels.includes('wallet')) {
walletMethod.disabled = false;
}
// 4. 处理【苹果支付】TODO 芋艿:未来接入
// 5. 处理【模拟支付】
const mockMethod = payMethods[4];
if (channels.includes('mock')) {
mockMethod.disabled = false;
}
return payMethods;
}
// 支付结果跳转,success:成功,fail:失败
export function goPayResult(id, orderType, resultType) {
// const url = `/pages/pay/result?id=${id}&orderType=${orderType}&payState=${resultType}`;
const url = `/pages/profile/pay-result?id=${id}&orderType=${orderType}&payState=${resultType}`;
uni.redirectTo({ url: url })
}
export function goBindWeixin() {
uni.showModal({
title: '微信支付',
content: '请先绑定微信再使用微信支付',
success: function (res) {
if (res.confirm) {
sheep.$platform.useProvider('wechat').bind();
}
},
});
}
// 获取微信支付渠道码
export function getWeixinPayChannelCode() {
const platform = sheep.$platform.name;
switch (platform) {
case 'WechatOfficialAccount':
return 'wx_pub';
case 'WechatMiniProgram':
return 'wx_lite';
case 'App':
return 'wx_app';
case 'H5':
return 'wx_wap';
default:
return '';
}
}