2025-10-22 23:06:43 +08:00

542 lines
15 KiB
JavaScript
Raw Permalink 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 CcbLifePlatform from './provider/ccblife/index';
import ccbApi from './provider/ccblife/api';
/**
* 支付
*
* @param {String} payment = ['wechat','alipay','wallet','offline'] - 支付方式
* @param {String} orderType = ['goods','recharge','groupon'] - 订单类型
* @param {String} orderSN - 订单号
*/
export default class SheepPay {
constructor(payment, orderType, orderSN) {
this.payment = payment;
this.orderSN = orderSN;
this.orderType = orderType;
this.payAction();
}
payAction() {
// 调试日志:打印当前平台和支付方式
console.log('[支付调试] 当前平台:', sheep.$platform.name, '支付方式:', this.payment);
const payAction = {
WechatOfficialAccount: {
wechat: () => {
this.wechatOfficialAccountPay();
},
alipay: () => {
this.redirectPay(); // 现在公众号可以直接跳转支付宝页面
},
ccb: () => {
this.ccbPay(); // 建行支付
},
money: () => {
this.moneyPay();
},
offline: () => {
this.offlinePay();
}
},
WechatMiniProgram: {
wechat: () => {
this.wechatMiniProgramPay();
},
alipay: () => {
this.copyPayLink();
},
ccb: () => {
sheep.$helper.toast('小程序暂不支持建行支付');
},
money: () => {
this.moneyPay();
},
offline: () => {
this.offlinePay();
}
},
App: {
wechat: () => {
this.wechatAppPay();
},
alipay: () => {
this.alipay();
},
ccb: () => {
this.ccbPay(); // 建行支付
},
money: () => {
this.moneyPay();
},
offline: () => {
this.offlinePay();
}
},
H5: {
wechat: () => {
// 如果在建行App内使用建行支付
if (CcbLifePlatform.isInCcbApp) {
this.ccbPay();
} else {
this.wechatWapPay();
}
},
alipay: () => {
this.redirectPay();
},
ccb: () => {
this.ccbPay(); // 建行支付
},
money: () => {
this.moneyPay();
},
offline: () => {
this.offlinePay();
}
},
// ⭐ 建行生活平台CcbLife
CcbLife: {
wechat: () => {
this.ccbPay(); // 在建行生活内使用建行支付
},
alipay: () => {
sheep.$helper.toast('请使用建行支付');
},
ccb: () => {
this.ccbPay(); // 建行支付
},
money: () => {
this.moneyPay();
},
offline: () => {
this.offlinePay();
}
},
};
// 防御性检查:确保平台配置存在
if (!payAction[sheep.$platform.name]) {
console.error('[支付错误] 未知平台:', sheep.$platform.name);
sheep.$helper.toast('当前平台不支持该支付方式');
return;
}
// 防御性检查:确保支付方式存在
if (!payAction[sheep.$platform.name][this.payment]) {
console.error('[支付错误] 平台不支持该支付方式:', {
platform: sheep.$platform.name,
payment: this.payment
});
sheep.$helper.toast(`当前平台不支持${this.payment}支付`);
return;
}
return payAction[sheep.$platform.name][this.payment]();
}
// 预支付
prepay() {
return new Promise((resolve, reject) => {
let data = {
order_sn: this.orderSN,
payment: this.payment,
};
if (uni.getStorageSync('openid')) {
data.openid = uni.getStorageSync('openid');
}
sheep.$api.pay.prepay(data).then((res) => {
res.code === 1 && resolve(res);
if (res.data === -1 && res.msg === 'miss_openid') {
uni.showModal({
title: '微信支付',
content: '请先绑定微信再使用微信支付',
success: function (res) {
if (res.confirm) {
sheep.$platform.useProvider('wechat').bind();
}
},
});
}
});
});
}
// #ifdef H5
// 微信公众号JSSDK支付
async wechatOfficialAccountPay() {
let that = this;
let {
code,
data,
msg
} = await this.prepay();
if (code !== 1) {
console.log('支付错误', msg);
return;
}
$wxsdk.wxpay(data.pay_data, {
success: () => {
that.payResult('success');
},
cancel: () => {
sheep.$helper.toast('支付已手动取消');
},
fail: () => {
that.payResult('fail');
},
});
}
//浏览器微信H5支付
async wechatWapPay() {
const {
code,
data
} = await this.prepay();
if (code === 1) {
const redirect_url = `${getRootUrl()}pages/pay/result?orderSN=${this.orderSN}&payment=${this.payment
}&orderType=${this.orderType}`;
location.href = `${data.pay_data.h5_url}&redirect_url=${encodeURIComponent(redirect_url)}`;
}
}
// 支付链接
async redirectPay() {
let {
code,
data
} = await this.prepay();
if (code === 1) {
const redirect_url = `${getRootUrl()}pages/pay/result?orderSN=${this.orderSN}&payment=${this.payment
}&orderType=${this.orderType}`;
location.href = data.pay_data + encodeURIComponent(redirect_url);
}
}
// #endif
// 微信小程序支付
async wechatMiniProgramPay() {
let that = this;
let result = await this.prepay();
uni.requestPayment({
provider: 'wxpay',
...result.data.pay_data,
success: (res) => {
that.payResult('success');
},
fail: (err) => {
if (err.errMsg === 'requestPayment:fail cancel') {
sheep.$helper.toast('支付已手动取消');
} else {
that.payResult('fail');
}
},
});
}
// 余额支付
async moneyPay() {
const {
code
} = await this.prepay();
code === 1 && this.payResult('success');
}
// 货到付款
async offlinePay() {
const {
code
} = await this.prepay();
code === 1 && this.payResult('success');
}
// 支付宝复制链接支付
async copyPayLink() {
let that = this;
let {
code,
data
} = await this.prepay();
if (code === 1) {
// 引入showModal 点击确认 复制链接;
uni.showModal({
title: '支付宝支付',
content: '复制链接到外部浏览器',
confirmText: '复制链接',
success: (res) => {
if (res.confirm) {
sheep.$helper.copyText(data.pay_data);
}
},
});
}
}
// 支付宝支付
async alipay() {
let that = this;
const {
code,
data
} = await this.prepay();
if (code === 1) {
uni.requestPayment({
provider: 'alipay',
orderInfo: data.pay_data, //支付宝订单数据
success: (res) => {
that.payResult('success');
},
fail: (err) => {
if (err.errMsg === 'requestPayment:fail [paymentAlipay:62001]user cancel') {
sheep.$helper.toast('支付已手动取消');
} else {
that.payResult('fail');
}
},
});
}
}
// 微信支付
async wechatAppPay() {
let that = this;
let {
code,
data
} = await this.prepay();
if (code === 1) {
uni.requestPayment({
provider: 'wxpay',
orderInfo: data.pay_data, //微信订单数据(官方说是string。实测为object)
success: (res) => {
that.payResult('success');
},
fail: (err) => {
err.errMsg !== 'requestPayment:fail cancel' && that.payResult('fail');
},
});
}
}
// 建行生活支付
async ccbPay() {
let that = this;
console.log('[建行支付] ========== 开始建行支付流程 ==========');
console.log('[建行支付] 订单号:', this.orderSN);
console.log('[建行支付] 订单类型:', this.orderType);
// 检查是否在建行App内
console.log('[建行支付] 检查建行App环境...');
console.log('[建行支付] isInCcbApp:', CcbLifePlatform.isInCcbApp);
console.log('[建行支付] User Agent:', navigator.userAgent);
console.log('[建行支付] URL参数:', location.search);
if (!CcbLifePlatform.isInCcbApp) {
console.error('[建行支付] ❌ 不在建行App内');
sheep.$helper.toast('请在建行生活App内使用建行支付');
return;
}
console.log('[建行支付] ✅ 确认在建行App内');
// 获取订单ID从订单号查询
console.log('[建行支付] 步骤1: 查询订单信息...');
let orderId;
let paymentResult;
try {
const orderInfo = await sheep.$api.order.detail(this.orderSN);
console.log('[建行支付] 订单查询结果:', orderInfo);
if (!orderInfo || orderInfo.code !== 1 || !orderInfo.data) {
console.error('[建行支付] ❌ 获取订单信息失败:', orderInfo);
sheep.$helper.toast('获取订单信息失败');
return;
}
orderId = orderInfo.data.id;
console.log('[建行支付] ✅ 订单ID:', orderId);
console.log('[建行支付] 订单金额:', orderInfo.data.pay_fee);
console.log('[建行支付] 订单状态:', orderInfo.data.status);
// 调用后端生成支付串
console.log('[建行支付] 步骤2: 调用后端生成支付串...');
console.log('[建行支付] 请求参数:', { order_id: orderId });
paymentResult = await ccbApi.createPayment(orderId);
console.log('[建行支付] 支付串生成结果:', paymentResult);
if (!paymentResult || paymentResult.code !== 1 || !paymentResult.data) {
console.error('[建行支付] ❌ 生成支付串失败:', paymentResult);
console.error('[建行支付] 错误信息:', paymentResult?.msg);
console.error('[建行支付] 完整响应:', JSON.stringify(paymentResult));
sheep.$helper.toast(paymentResult?.msg || '生成支付串失败');
return;
}
console.log('[建行支付] ✅ 支付串生成成功');
console.log('[建行支付] 支付串长度:', paymentResult.data?.payment_string?.length);
console.log('[建行支付] 支付流水号:', paymentResult.data?.pay_flow_id);
console.log('[建行支付] 支付金额:', paymentResult.data?.amount);
// 验证支付串是否存在
if (!paymentResult.data.payment_string) {
console.error('[建行支付] ❌ 支付串为空');
sheep.$helper.toast('支付串生成失败');
return;
}
} catch (error) {
console.error('[建行支付] ❌ 异常:', error);
console.error('[建行支付] 错误堆栈:', error.stack);
sheep.$helper.toast('支付准备失败: ' + error.message);
return;
}
// 调起建行支付
console.log('[建行支付] 步骤3: 调起建行收银台...');
try {
const paymentParams = {
payment_string: paymentResult.data.payment_string,
order_id: orderId,
order_sn: this.orderSN
};
console.log('[建行支付] 调起参数:', {
order_id: paymentParams.order_id,
order_sn: paymentParams.order_sn,
payment_string_length: paymentParams.payment_string?.length
});
const result = await CcbLifePlatform.payment(paymentParams);
console.log('[建行支付] 收银台调起结果:', result);
if (result && result.code === 0) {
// ✅ 支付调起成功,开始轮询查询订单状态
console.log('[建行支付] ✅ 支付调起成功,开始轮询查询订单状态');
// 显示加载提示
uni.showLoading({
title: '支付确认中...',
mask: true
});
// 轮询查询订单状态(最多30次,每次间隔2秒,总共60秒)
let pollCount = 0;
const MAX_POLL_COUNT = 30;
const POLL_INTERVAL = 2000; // 2秒
const pollPaymentStatus = async () => {
pollCount++;
console.log(`[建行支付] 轮询查询 ${pollCount}/${MAX_POLL_COUNT} 次...`);
try {
const statusResult = await ccbApi.queryPaymentStatus(orderId);
console.log('[建行支付] 查询结果:', statusResult);
if (statusResult && statusResult.code === 1 && statusResult.data && statusResult.data.is_paid) {
// ✅ 支付成功
uni.hideLoading();
console.log('[建行支付] ✅ 订单已支付 order_id:' + orderId);
console.log('[建行支付] 支付时间:', statusResult.data.paid_time);
that.payResult('success');
return;
}
console.log('[建行支付] 订单状态:', statusResult?.data?.status);
console.log('[建行支付] 是否已支付:', statusResult?.data?.is_paid);
// 未支付,继续轮询
if (pollCount < MAX_POLL_COUNT) {
console.log(`[建行支付] ${POLL_INTERVAL/1000}秒后继续查询...`);
setTimeout(pollPaymentStatus, POLL_INTERVAL);
} else {
// 超时
console.warn('[建行支付] ⚠️ 轮询超时,可能支付未完成');
uni.hideLoading();
uni.showModal({
title: '提示',
content: '支付确认超时,请稍后在订单列表中查看支付状态',
showCancel: false,
confirmText: '知道了',
success: () => {
// 跳转到订单列表
sheep.$router.redirect('/pages/order/list');
}
});
}
} catch (error) {
console.error('[建行支付] ❌ 查询状态失败:', error);
console.error('[建行支付] 错误详情:', error.message);
// 继续轮询(网络错误不中断)
if (pollCount < MAX_POLL_COUNT) {
setTimeout(pollPaymentStatus, POLL_INTERVAL);
} else {
uni.hideLoading();
sheep.$helper.toast('支付状态查询失败,请稍后在订单列表中查看');
that.payResult('fail');
}
}
};
// 延迟1秒后开始轮询(给建行异步通知留点时间)
setTimeout(pollPaymentStatus, 1000);
} else {
// 支付失败或取消
console.error('[建行支付] ❌ 支付未成功:', result);
// 确保关闭可能存在的loading
uni.hideLoading();
if (result && result.msg && result.msg.includes('取消')) {
console.log('[建行支付] 用户取消支付');
sheep.$helper.toast('支付已取消');
// ⭐ 用户取消支付,返回支付页面(而不是跳转到失败页面)
setTimeout(() => {
uni.navigateBack({
delta: 1,
fail: () => {
// 如果返回失败,跳转到订单列表
sheep.$router.redirect('/pages/order/list');
}
});
}, 1500);
} else {
console.error('[建行支付] 支付失败原因:', result?.msg);
sheep.$helper.toast(result?.msg || '支付失败');
that.payResult('fail');
}
}
} catch (error) {
console.error('[建行支付] ❌ 异常错误:', error);
console.error('[建行支付] 错误类型:', error.name);
console.error('[建行支付] 错误信息:', error.message);
console.error('[建行支付] 错误堆栈:', error.stack);
// 确保关闭loading
uni.hideLoading();
sheep.$helper.toast('支付失败: ' + error.message);
that.payResult('fail');
}
console.log('[建行支付] ========== 建行支付流程结束 ==========');
}
// 支付结果跳转,success:成功fail:失败
payResult(resultType) {
sheep.$router.redirect('/pages/pay/result', {
orderSN: this.orderSN,
payment: this.payment, //重新支付的时候使用
payState: resultType,
orderType: this.orderType,
});
}
}