322 lines
11 KiB
JavaScript
322 lines
11 KiB
JavaScript
/**
|
|
* 卡若创业派对 - 代付详情页
|
|
* 改造后:发起人支付,好友领取。支持单页模式引导、登录检测。
|
|
*/
|
|
const app = getApp()
|
|
|
|
Page({
|
|
data: {
|
|
statusBarHeight: 44,
|
|
requestSn: '',
|
|
sectionId: '',
|
|
detail: null,
|
|
loading: true,
|
|
paying: false,
|
|
redeeming: false,
|
|
isInitiator: false,
|
|
requesterMsg: '',
|
|
amountDisplay: '0.00',
|
|
isSinglePageMode: false,
|
|
showLoginModal: false,
|
|
showPrivacyModal: false,
|
|
// 创建态
|
|
isCreateMode: false,
|
|
giftQuantity: 1,
|
|
unitPrice: 0
|
|
},
|
|
|
|
onLoad(options) {
|
|
wx.showShareMenu({ menus: ['shareAppMessage', 'shareTimeline'] })
|
|
this.setData({ statusBarHeight: app.globalData.statusBarHeight || 44 })
|
|
if (options?.ref || options?.referralCode) {
|
|
app.handleReferralCode({ query: { ref: options.ref || options.referralCode } })
|
|
}
|
|
const requestSn = (options.requestSn || '').trim()
|
|
const sectionId = (options.sectionId || '').trim()
|
|
const isSinglePage = (wx.getSystemInfoSync?.()?.mode === 'singlePage') || app.globalData.isSinglePageMode
|
|
this.setData({ requestSn, sectionId, isSinglePageMode: !!isSinglePage })
|
|
if (requestSn || sectionId) {
|
|
this.loadDetail()
|
|
} else {
|
|
wx.showToast({ title: '链接无效', icon: 'none' })
|
|
setTimeout(() => wx.switchTab({ url: '/pages/index/index' }), 1500)
|
|
}
|
|
},
|
|
|
|
async loadDetail() {
|
|
const { requestSn, sectionId } = this.data
|
|
this.setData({ loading: true })
|
|
const userId = app.globalData.userInfo?.id || ''
|
|
let url = ''
|
|
if (requestSn) {
|
|
url = `/api/miniprogram/gift-pay/detail?requestSn=${encodeURIComponent(requestSn)}${userId ? '&userId=' + encodeURIComponent(userId) : ''}`
|
|
} else if (sectionId && userId) {
|
|
url = `/api/miniprogram/gift-pay/detail?sectionId=${encodeURIComponent(sectionId)}&userId=${encodeURIComponent(userId)}`
|
|
} else if (sectionId) {
|
|
this.setData({ loading: false })
|
|
wx.showToast({ title: '请先登录', icon: 'none' })
|
|
return
|
|
} else {
|
|
this.setData({ loading: false })
|
|
return
|
|
}
|
|
try {
|
|
const res = await app.request(url)
|
|
if (res && res.success) {
|
|
const isCreateMode = res.mode === 'create' || res.action === 'create'
|
|
const isInitiator = res.isInitiator === true
|
|
let requesterMsg = ''
|
|
let amountDisplay = '0.00'
|
|
if (isCreateMode) {
|
|
requesterMsg = '输入发放数量,支付后分享给好友免费领取'
|
|
amountDisplay = (res.unitPrice != null ? Number(res.unitPrice) * (this.data.giftQuantity || 1) : 0).toFixed(2)
|
|
} else {
|
|
requesterMsg = isInitiator
|
|
? (res.action === 'pay' ? '支付后分享给好友,好友打开即可免费领取。' : '分享给好友,好友打开即可免费领取。')
|
|
: res.initiatorMsg || `" 请帮我代付「${res.sectionTitle || res.description || '该商品'}」,非常感谢! "`
|
|
amountDisplay = (res.amount != null && res.amount !== '') ? Number(res.amount).toFixed(2) : '0.00'
|
|
}
|
|
this.setData({
|
|
detail: res,
|
|
loading: false,
|
|
isInitiator,
|
|
isCreateMode,
|
|
requesterMsg,
|
|
amountDisplay,
|
|
unitPrice: res.unitPrice != null ? res.unitPrice : 0
|
|
})
|
|
if (isCreateMode) this._updateAmountDisplay()
|
|
} else {
|
|
this.setData({ loading: false })
|
|
wx.showToast({ title: res?.error || '加载失败', icon: 'none' })
|
|
}
|
|
} catch (e) {
|
|
this.setData({ loading: false })
|
|
wx.showToast({ title: '加载失败', icon: 'none' })
|
|
}
|
|
},
|
|
|
|
onGiftQuantityInput(e) {
|
|
const raw = (e.detail.value || '').trim()
|
|
const v = parseInt(raw, 10)
|
|
this.setData({ giftQuantity: isNaN(v) ? (raw === '' ? '' : this.data.giftQuantity) : v })
|
|
this._updateAmountDisplay()
|
|
},
|
|
_updateAmountDisplay() {
|
|
const { unitPrice, giftQuantity } = this.data
|
|
const q = Math.max(0, parseInt(giftQuantity, 10) || 0)
|
|
const amount = (unitPrice || 0) * q
|
|
this.setData({ amountDisplay: amount.toFixed(2) })
|
|
},
|
|
|
|
// 发起人支付(改造后:我帮别人付款)
|
|
async doInitiatorPay() {
|
|
if (this.data.isSinglePageMode) {
|
|
wx.showModal({
|
|
title: '朋友圈单页',
|
|
content: '当前为朋友圈单页,无法支付。请点击底部「前往小程序」进入完整版后再支付。',
|
|
showCancel: false
|
|
})
|
|
return
|
|
}
|
|
const userId = app.globalData.userInfo?.id || ''
|
|
if (!userId) {
|
|
wx.showToast({ title: '请先登录后再支付', icon: 'none' })
|
|
return
|
|
}
|
|
let openId = app.globalData.openId || wx.getStorageSync('openId')
|
|
if (!openId) {
|
|
wx.showLoading({ title: '获取支付凭证...', mask: true })
|
|
openId = await app.getOpenId()
|
|
wx.hideLoading()
|
|
}
|
|
if (!openId) {
|
|
wx.showToast({ title: '请先登录', icon: 'none' })
|
|
return
|
|
}
|
|
let { requestSn, sectionId, detail, giftQuantity, isCreateMode } = this.data
|
|
if (!requestSn && isCreateMode && sectionId) {
|
|
const q = parseInt(giftQuantity, 10)
|
|
if (isNaN(q) || q !== Math.floor(q) || q < 1) {
|
|
wx.showToast({ title: '发放份数须为正整数', icon: 'none' })
|
|
return
|
|
}
|
|
const quantity = q
|
|
wx.showLoading({ title: '创建中...', mask: true })
|
|
try {
|
|
const createRes = await app.request({
|
|
url: '/api/miniprogram/gift-pay/create',
|
|
method: 'POST',
|
|
data: { userId, productType: 'section', productId: sectionId, quantity }
|
|
})
|
|
if (!createRes?.success || !createRes.requestSn) {
|
|
throw new Error(createRes?.error || '创建失败')
|
|
}
|
|
requestSn = createRes.requestSn
|
|
this.setData({ requestSn, isCreateMode: false })
|
|
} catch (e) {
|
|
wx.hideLoading()
|
|
wx.showToast({ title: e.message || e.error || '创建失败', icon: 'none' })
|
|
return
|
|
}
|
|
}
|
|
if (!requestSn) return
|
|
|
|
this.setData({ paying: true })
|
|
wx.showLoading({ title: '创建订单中...', mask: true })
|
|
try {
|
|
const res = await app.request({
|
|
url: '/api/miniprogram/gift-pay/initiator-pay',
|
|
method: 'POST',
|
|
data: {
|
|
requestSn,
|
|
openId,
|
|
userId
|
|
}
|
|
})
|
|
wx.hideLoading()
|
|
if (!res || !res.success || !res.data?.payParams) {
|
|
throw new Error(res?.error || '创建订单失败')
|
|
}
|
|
const payParams = res.data.payParams
|
|
const orderSn = res.data.orderSn
|
|
// 与正常章节支付一致:只传 5 个必需参数,不传 appId 等多余字段
|
|
await new Promise((resolve, reject) => {
|
|
wx.requestPayment({
|
|
timeStamp: payParams.timeStamp,
|
|
nonceStr: payParams.nonceStr,
|
|
package: payParams.package,
|
|
signType: payParams.signType || 'RSA',
|
|
paySign: payParams.paySign,
|
|
success: resolve,
|
|
fail: reject
|
|
})
|
|
})
|
|
wx.showToast({ title: '支付成功', icon: 'success' })
|
|
this.setData({ paying: false })
|
|
// 主动同步订单状态(与 read 页一致)
|
|
if (orderSn) {
|
|
try {
|
|
await app.request(`/api/miniprogram/pay?orderSn=${encodeURIComponent(orderSn)}`, { silent: true })
|
|
} catch (e) {
|
|
console.warn('[GiftPay] 主动同步订单失败:', e)
|
|
}
|
|
}
|
|
this.loadDetail()
|
|
} catch (e) {
|
|
this.setData({ paying: false })
|
|
const msg = e.message || e.error || e.errMsg || '支付失败'
|
|
if (e.errMsg && e.errMsg.includes('cancel')) {
|
|
wx.showToast({ title: '已取消支付', icon: 'none' })
|
|
} else {
|
|
wx.showToast({ title: msg, icon: 'none', duration: 2500 })
|
|
}
|
|
}
|
|
},
|
|
|
|
// 好友领取(改造后:免费获得章节)
|
|
async doRedeem() {
|
|
if (this.data.isSinglePageMode) {
|
|
wx.showModal({
|
|
title: '朋友圈单页',
|
|
content: '当前为朋友圈单页,无法登录领取。请点击底部「前往小程序」进入完整版后再领取。',
|
|
showCancel: false
|
|
})
|
|
return
|
|
}
|
|
const userId = app.globalData.userInfo?.id
|
|
if (!userId) {
|
|
this.setData({ showLoginModal: true })
|
|
return
|
|
}
|
|
await this._doRedeem()
|
|
},
|
|
|
|
async _doRedeem() {
|
|
const { requestSn } = this.data
|
|
const userId = app.globalData.userInfo?.id
|
|
if (!requestSn || !userId) return
|
|
|
|
this.setData({ redeeming: true })
|
|
wx.showLoading({ title: '领取中...', mask: true })
|
|
try {
|
|
const res = await app.request({
|
|
url: '/api/miniprogram/gift-pay/redeem',
|
|
method: 'POST',
|
|
data: { requestSn, userId }
|
|
})
|
|
wx.hideLoading()
|
|
this.setData({ redeeming: false })
|
|
if (res && res.success) {
|
|
wx.showToast({ title: '领取成功', icon: 'success' })
|
|
const mid = res.sectionMid || res.sectionId
|
|
const q = mid ? `mid=${mid}` : `id=${res.sectionId || ''}`
|
|
setTimeout(() => {
|
|
wx.navigateTo({ url: `/pages/read/read?${q}` })
|
|
}, 800)
|
|
} else {
|
|
wx.showToast({ title: res?.error || '领取失败', icon: 'none' })
|
|
}
|
|
} catch (e) {
|
|
this.setData({ redeeming: false })
|
|
wx.hideLoading()
|
|
wx.showToast({ title: e.message || e.error || '领取失败', icon: 'none' })
|
|
}
|
|
},
|
|
|
|
onLoginModalClose() {
|
|
this.setData({ showLoginModal: false, showPrivacyModal: false })
|
|
},
|
|
onLoginModalPrivacyAgree() {
|
|
this.setData({ showPrivacyModal: false })
|
|
},
|
|
async onLoginModalSuccess() {
|
|
this.setData({ showLoginModal: false })
|
|
await this._doRedeem()
|
|
},
|
|
|
|
goBack() {
|
|
app.goBackOrToHome()
|
|
},
|
|
|
|
goToInitiatorProfile() {
|
|
const { detail } = this.data
|
|
if (!detail?.initiatorUserId) return
|
|
wx.navigateTo({ url: `/pages/member-detail/member-detail?id=${detail.initiatorUserId}` })
|
|
},
|
|
|
|
goToArticle() {
|
|
const { detail } = this.data
|
|
if (!detail || detail.productType !== 'section' || !detail.productId) return
|
|
const mid = detail.productMid
|
|
const q = mid ? `mid=${mid}` : `id=${detail.productId}`
|
|
wx.navigateTo({ url: `/pages/read/read?${q}` })
|
|
},
|
|
|
|
onShareAppMessage() {
|
|
const { requestSn } = this.data
|
|
const ref = app.getMyReferralCode?.() || app.globalData.userInfo?.referralCode || ''
|
|
let path = '/pages/gift-pay/detail'
|
|
const params = []
|
|
if (requestSn) params.push(`requestSn=${encodeURIComponent(requestSn)}`)
|
|
if (ref) params.push(`ref=${encodeURIComponent(ref)}`)
|
|
if (params.length) path += '?' + params.join('&')
|
|
return {
|
|
title: '好友送你一篇好文 - 卡若创业派对',
|
|
path
|
|
}
|
|
},
|
|
|
|
onShareTimeline() {
|
|
const { requestSn } = this.data
|
|
const ref = app.getMyReferralCode?.() || app.globalData.userInfo?.referralCode || ''
|
|
const params = []
|
|
if (requestSn) params.push(`requestSn=${encodeURIComponent(requestSn)}`)
|
|
if (ref) params.push(`ref=${encodeURIComponent(ref)}`)
|
|
return {
|
|
title: '好友送你一篇好文 - 卡若创业派对',
|
|
query: params.length ? params.join('&') : ''
|
|
}
|
|
}
|
|
})
|