Files
a_long/pages/tijiao/tijiao.js
2026-06-14 02:38:05 +08:00

313 lines
9.3 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.
// pages/tijiao/tijiao.js
const app = getApp()
import request from '../../utils/request.js'
import PopupService from '../../services/popupService.js'
Page({
data: {
ossImageUrl: '',
apiBaseUrl: '',
shangpinData: null,
shangpinId: '',
nicheng: '',
beizhu: '',
zhiding: '',
jine: 0,
isSubmitting: false,
canSubmit: false,
isPaying: false,
orderId: '',
payParams: null,
checkCount: 0,
maxCheckCount: 3
},
onLoad(options) {
this.setData({
ossImageUrl: app.globalData.ossImageUrl || '',
apiBaseUrl: app.globalData.apiBaseUrl || ''
})
wx.setNavigationBarTitle({ title: '提交订单' })
try {
if (options.data) {
const shangpinData = JSON.parse(decodeURIComponent(options.data))
if (shangpinData.image && !shangpinData.image.startsWith('http')) {
shangpinData.image = this.data.ossImageUrl + shangpinData.image
}
if (shangpinData.price) {
const price = parseFloat(shangpinData.price) || 0
const priceInteger = Math.floor(price)
let priceDecimal = '00'
const decimalPart = (price - priceInteger).toFixed(2)
if (decimalPart > 0) {
priceDecimal = decimalPart.toString().split('.')[1]
}
shangpinData.priceInteger = priceInteger
shangpinData.priceDecimal = priceDecimal
}
this.setData({
shangpinData: shangpinData,
shangpinId: shangpinData.id || '',
jine: parseFloat(shangpinData.price) || 0,
})
} else {
this.handleDataError('商品数据不完整')
}
} catch (error) {
this.handleDataError('解析商品数据失败')
}
PopupService.checkAndShow(this, 'tijiao');
},
onHide() {
const popupComp = this.selectComponent('#popupNotice');
if (popupComp && popupComp.cleanup) {
popupComp.cleanup();
}
},
onShow() {
this.registerNotificationComponent();
},
registerNotificationComponent() {
const app = getApp();
const notificationComp = this.selectComponent('#global-notification');
if (notificationComp && notificationComp.showNotification) {
app.globalData.globalNotification = {
show: (data) => notificationComp.showNotification(data),
hide: () => notificationComp.hideNotification()
};
}
},
handleDataError(errorMsg) {
wx.showToast({ title: errorMsg || '数据错误', icon: 'none' })
setTimeout(() => { wx.navigateBack() }, 1500)
},
onNicknameInput(e) {
this.setData({ nicheng: e.detail.value.trim() }, () => { this.checkFormValid() })
},
onRemarkInput(e) {
this.setData({ beizhu: e.detail.value.trim() })
},
onZhidingInput(e) {
this.setData({ zhiding: e.detail.value.trim() })
},
checkFormValid() {
const { nicheng } = this.data
this.setData({ canSubmit: nicheng && nicheng.length > 0 && nicheng.length <= 15 })
},
// 提交订单(生产版:已去掉所有调试日志,保留关键错误日志)
onSubmitOrder() {
const { nicheng, beizhu, zhiding, jine, shangpinId, canSubmit, isSubmitting } = this.data
if (!canSubmit) {
wx.showToast({ title: '请填写游戏昵称', icon: 'none' })
return
}
// 防重复提交
if (isSubmitting) return
this.setData({ isSubmitting: true, isPaying: false })
wx.showLoading({ title: '创建订单中...', mask: true })
// 10秒超时
const timeoutTimer = setTimeout(() => {
wx.hideLoading()
wx.showToast({ title: '网络超时,请检查您是否已登录', icon: 'none' })
this.setData({ isSubmitting: false, isPaying: false })
}, 10000)
// 获取登录 code虚拟支付必须每单刷新 session_key
wx.login({
success: (loginRes) => {
const orderData = {
shangpin_id: shangpinId,
nicheng: nicheng,
beizhu: beizhu || '',
zhiding: zhiding || '',
jine: jine,
code: loginRes.code
}
request({
url: '/dingdan/virtual_xiadan',
method: 'POST',
data: orderData
})
.then(res => {
clearTimeout(timeoutTimer)
wx.hideLoading()
if (res.statusCode === 200 && res.data && res.data.code === 0 && res.data.data) {
const payParams = res.data.data.payParams || {}
this.setData({
orderId: res.data.data.dingdanid,
payParams: payParams,
isSubmitting: false,
isPaying: true,
checkCount: 0
})
// 调起虚拟支付
this.triggerVirtualPayment(payParams)
} else {
const msg = (res.data && res.data.msg) || '创建订单失败'
wx.showToast({ title: msg, icon: 'none' })
this.setData({ isSubmitting: false, isPaying: false })
}
})
.catch(error => {
clearTimeout(timeoutTimer)
wx.hideLoading()
console.error('下单请求异常', error)
wx.showToast({ title: '创建订单失败', icon: 'none' })
this.setData({ isSubmitting: false, isPaying: false })
})
},
fail: () => {
clearTimeout(timeoutTimer)
wx.hideLoading()
wx.showToast({ title: '获取登录状态失败', icon: 'none' })
this.setData({ isSubmitting: false, isPaying: false })
}
})
},
// 调起虚拟支付(防抖已通过 isPaying 状态控制)
triggerVirtualPayment(payParams) {
// 参数完整性检查
if (!payParams || !payParams.signData || !payParams.paySig || !payParams.signature) {
console.error('支付参数不完整', payParams)
wx.showToast({ title: '支付参数异常', icon: 'none' })
this.setData({ isSubmitting: false, isPaying: false })
return
}
wx.requestVirtualPayment({
signData: payParams.signData,
paySig: payParams.paySig,
signature: payParams.signature,
mode: payParams.mode || 'short_series_coin',
success: (res) => {
// 支付成功,进入复查流程
this.onPaymentSuccess()
},
fail: (err) => {
console.error('支付失败', err)
if (err.errCode === -2 || (err.errMsg && err.errMsg.indexOf('cancel') !== -1)) {
this.handleUserCancel()
} else {
this.handlePaymentFail(err)
}
}
})
},
// 用户取消支付
handleUserCancel() {
wx.showToast({ title: '已取消支付', icon: 'none', duration: 1500 })
if (this.data.orderId) {
request({
url: '/dingdan/shibai',
method: 'POST',
data: { dingdanid: this.data.orderId }
}).catch(() => {})
}
this.setData({ isSubmitting: false, isPaying: false })
},
// 其他支付失败
handlePaymentFail(err) {
wx.showToast({ title: '支付失败', icon: 'none', duration: 1500 })
if (this.data.orderId) {
request({
url: '/dingdan/shibai',
method: 'POST',
data: {
dingdanid: this.data.orderId,
yuanyin: 'payment_fail'
}
}).catch(() => {})
}
this.setData({ isSubmitting: false, isPaying: false })
},
// 支付成功,开始双重确认
onPaymentSuccess() {
if (!this.data.orderId) {
wx.showToast({ title: '订单ID丢失', icon: 'none' })
this.setData({ isSubmitting: false, isPaying: false })
return
}
wx.showToast({ title: '支付成功,确认中...', icon: 'none', duration: 1500 })
this.checkOrderStatus()
},
// 复查订单状态最多重试3次
checkOrderStatus() {
const { orderId, checkCount, maxCheckCount } = this.data
wx.showLoading({
title: `确认支付状态${checkCount > 0 ? `(${checkCount + 1})` : ''}`,
mask: true
})
const timeoutTimer = setTimeout(() => {
wx.hideLoading()
this.handleConfirmError('网络超时')
}, 5000)
request({
url: '/dingdan/virtual_fucha',
method: 'POST',
data: { dingdanid: orderId }
})
.then(res => {
clearTimeout(timeoutTimer)
wx.hideLoading()
if ( res.data && res.data.code === 0) {
this.handleConfirmSuccess()
} else {
const msg = (res.data && res.data.msg) || '订单状态异常'
this.handleConfirmError(msg)
}
})
.catch(error => {
clearTimeout(timeoutTimer)
wx.hideLoading()
this.handleConfirmError('检查失败')
})
},
handleConfirmSuccess() {
wx.showToast({ title: '购买成功!', icon: 'success', duration: 1500 })
setTimeout(() => {
wx.switchTab({ url: '/pages/index/index' })
}, 1500)
this.setData({ isSubmitting: false, isPaying: false })
},
handleConfirmError(errorMsg) {
const { checkCount, maxCheckCount } = this.data
const newCheckCount = checkCount + 1
if (newCheckCount < maxCheckCount) {
this.setData({ checkCount: newCheckCount })
setTimeout(() => { this.checkOrderStatus() }, 1000)
} else {
wx.showModal({
title: '支付确认中',
content: '支付已成功,但订单状态确认异常。请稍后在订单列表查看,如有问题请联系客服。',
showCancel: false,
confirmText: '我知道了',
success: (res) => {
if (res.confirm) wx.switchTab({ url: '/pages/index/index' })
}
})
this.setData({ isSubmitting: false, isPaying: false })
}
}
})