Files
xo_user_client/pages/buy/wu_you_status.vue
2025-05-19 09:56:28 +08:00

353 lines
9.6 KiB
Vue
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.
<template>
<view class="container">
<view class="loading">
<image class="icon" src="/static/icon_paying.svg" mode="aspectFit"></image>
<view class="t">
{{ status }}
</view>
</view>
</view>
</template>
<script>
import base64 from '../../common/js/lib/base64';
const app = getApp();
export default {
props: {
// 支付id
payment_id: 0,
// 订单下标 ---- 用于处理支付成功后前端修改成功状态
propTempPayIndex: {
type: [Number, String],
default: 0,
},
},
data() {
return {
status: '支付中...',
pay_url: '',
checkOrderTimer: null, // 存储定时器ID
isChecking: false, // 请求状态标记
checkTries: 0, // 当前尝试次数
};
},
onLoad(e) {
window.addEventListener('popstate', this.onPageBack);
console.log('wu_you_status.onLoad===', e);
this.pay_url = e;
let wuyou = uni.getStorageSync('wuyouPay');
if (this.pay_url.order_id && !wuyou.order_id) {
uni.setStorageSync('wuyouPay', {
order_id: this.pay_url.order_id,
check: false,
});
this.payHandle();
}
},
onHide() {
console.log('页面关闭');
if (this.checkOrderTimer) {
console.log('清除未完成的订单查询定时器');
clearTimeout(this.checkOrderTimer);
}
this.isChecking = false;
this.checkTries = 0;
},
onShow() {
let wuyou = uni.getStorageSync('wuyouPay');
if (wuyou && wuyou.check) {
this.checkOrderStatus();
}
},
methods: {
onPageBack() {
console.log('页面关闭');
if (this.checkOrderTimer) {
console.log('清除未完成的订单查询定时器');
clearTimeout(this.checkOrderTimer);
}
this.isChecking = false;
this.checkTries = 0;
},
// 开始支付
payHandle() {
console.log('开始支付00000');
uni.request({
url: app.globalData.get_request_url('wuYouPay', 'xo'),
method: 'POST',
data: {
ids: this.pay_url.order_id,
payment_id: this.pay_url.payment_id,
redirect_url: this.encodeAlipayCallbackUrl(window.location.href),
},
dataType: 'json',
success: (res) => {
console.log('开始支付===', res);
var data = res.data;
console.log(data);
if (data.code == 0) {
console.log(data.data.data.h5_url);
let wuyou2 = uni.getStorageSync('wuyouPay');
wuyou2.check = true;
uni.setStorageSync('wuyouPay', wuyou2);
window.location.href = data.data.data.h5_url;
} else {
uni.showToast({
title: msg.msg,
icon: 'none',
mask: true,
});
// setTimeout(() => {
// uni.redirectTo({
// url: '/pages/user-order/user-order',
// });
// }, 1500);
}
},
fail: (err) => {
console.log(err);
},
});
},
/**
* 处理支付宝回调 URL 编码
* @param {string} url - 原始回调 URL
* @returns {string} - 经过 URL 编码和 Base64 编码后的字符串
*/
encodeAlipayCallbackUrl(url) {
try {
// 解析URL并移除查询参数
const urlObj = new URL(url);
const cleanUrl = new URL(urlObj.origin + urlObj.pathname);
// 1. Base64 编码(仅编码路径部分,不含参数)
let base64Encoded;
if (typeof window !== 'undefined' && window.btoa) {
base64Encoded = window.btoa(cleanUrl.href);
} else if (typeof Buffer !== 'undefined') {
base64Encoded = Buffer.from(cleanUrl.href, 'utf8').toString('base64');
} else {
throw new Error('无法进行 Base64 编码');
}
// 2. URL 安全处理
const safeBase64 = base64Encoded
.replace(/\+/g, '-') // 替换 + 为 -
.replace(/\//g, '_') // 替换 / 为 _
.replace(/=+$/, ''); // 移除末尾的 =
// 3. 最终 URL 编码
return encodeURIComponent(safeBase64);
} catch (error) {
console.error('URL编码失败:', error);
throw new Error('无效的URL格式');
}
},
// 检测是否支付成功
checkOrderStatus() {
let wuyou = uni.getStorageSync('wuyouPay');
// 已达到最大尝试次数或正在请求中,则返回
if (this.checkTries >= 10 || this.isChecking) {
if (this.checkTries >= 10) {
console.log('checkOrderStatus.已达到最大查询次数');
this.payFail();
}
return;
}
this.status = `查询中,请勿操作(${this.checkTries + 1}/10...`;
this.checkTries++;
this.isChecking = true;
console.log(`checkOrderStatus.第${this.checkTries}次查询订单状态`);
uni.request({
url: app.globalData.get_request_url('queryOrder', 'xo'),
method: 'get',
data: {
id: wuyou.order_id,
},
dataType: 'json',
success: (res) => {
let data = res.data;
console.log(`checkOrderStatus.第${this.checkTries}次查询结果`, res.data);
if (data.code == 0) {
const status = data.data.status;
switch (status) {
case 0: // 支付中2秒后继续查询
console.log(`checkOrderStatus.订单状态:支付中,继续查询(${this.checkTries}/10`);
this.checkOrderTimer = setTimeout(() => {
this.checkOrderStatus();
}, 2000);
break;
case 1: // 支付成功,跳转到订单详情
console.log('checkOrderStatus.订单状态:支付成功');
uni.showToast({
title: '支付成功,即将跳转订单详情',
icon: 'none',
mask: true,
});
setTimeout(() => {
uni.reLaunch({
url: `/pages/user-order-detail/user-order-detail?id=${wuyou.order_id}`,
});
}, 1000);
break;
default: // 其他状态(如-1支付失败终止查询
console.log(`checkOrderStatus.订单状态异常:${status}`);
this.payFail();
}
} else {
// 请求成功但业务错误,终止查询
console.error('checkOrderStatus.业务错误:', data.message);
this.payFail();
}
},
fail: (err) => {
console.error(`checkOrderStatus.第${this.checkTries}次查询失败`, err);
// 请求失败2秒后继续尝试但不增加尝试次数
this.checkTries--; // 失败不计数
this.checkOrderTimer = setTimeout(() => {
this.checkOrderStatus();
}, 2000);
},
complete: () => {
// 请求完成,无论结果如何都重置状态
this.isChecking = false;
},
});
},
payFail() {
uni.showToast({
title: '支付失败',
icon: 'none',
mask: true,
});
setTimeout(() => {
uni.reLaunch({
url: '/pages/user-order/user-order',
});
}, 1500);
},
// 支付失败数据设置 data:后台返回的参数, order_id: 订单id, msg: 错误提示信息
order_item_pay_fail_handle(data, order_id, msg) {
let back_data = {
data: data,
order_id: order_id,
temp_pay_index: this.propTempPayIndex,
payment_id: this.payment_id,
};
this.$emit('pay-fail', back_data);
this.to_fail_page_event(msg);
},
// 失败跳转
to_fail_page_event(msg) {
let to_fail_page = this.propToFailPage || null;
if (to_fail_page != null) {
let join = to_fail_page.indexOf('?') == -1 ? '?' : '&';
to_fail_page += join + 'msg=' + msg;
if (this.propIsFailAlert) {
// 现金支付
uni.showModal({
content: msg,
showCancel: false,
confirmText: this.$t('common.confirm'),
success(res) {
if (res.confirm) {
// 跳转支付页面
app.globalData.url_open(to_fail_page, true);
}
},
});
} else {
// 跳转支付页面
app.globalData.url_open(to_fail_page, true);
}
} else {
if (msg) {
app.globalData.showToast(msg);
}
}
},
// 支付成功数据设置 data:后台返回的参数, order_id: 订单idis_to_page是否需要跳转页面的参数控制
order_item_pay_success_handle(data, order_id, is_to_page = true) {
let back_data = {
data: data,
order_id: order_id,
temp_pay_index: this.propTempPayIndex,
payment_id: this.payment_id,
is_to_page: is_to_page,
};
this.$emit('pay-success', back_data);
if (is_to_page) {
this.to_success_page_event();
}
},
// 支付成功数据设置 data:后台返回的参数, order_id: 订单idis_to_page是否需要跳转页面的参数控制
order_item_pay_success_handle(data, order_id, is_to_page = true) {
let back_data = {
data: data,
order_id: order_id,
temp_pay_index: this.propTempPayIndex,
payment_id: this.payment_id,
is_to_page: is_to_page,
};
this.$emit('pay-success', back_data);
if (is_to_page) {
this.to_success_page_event();
}
},
// 成功跳转
to_success_page_event() {
if (this.propToPage) {
// 跳转支付页面
app.globalData.url_open(this.propToPage, true);
} else {
let url_data = {
code: '9000',
};
url_data = Object.assign({}, url_data, this.propToPageBack);
// 跳转支付页面
app.globalData.url_open('/pages/paytips/paytips?params=' + encodeURIComponent(base64.encode(JSON.stringify(url_data))), this.propIsRedirectTo);
}
},
},
};
</script>
<style scoped lang="scss">
.container {
width: 100vw;
height: 100vh;
padding-bottom: 40%;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
.loading {
display: flex;
gap: 20upx;
flex-direction: column;
align-items: center;
justify-content: center;
.icon {
$size: 300upx;
width: $size;
height: $size;
}
.t {
font-size: 36upx;
color: #999;
}
}
}
</style>