313 lines
9.3 KiB
JavaScript
313 lines
9.3 KiB
JavaScript
// 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 })
|
||
}
|
||
}
|
||
}) |