Files
soul-yongping/miniprogram/pages/gift-pay/detail.js

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('&') : ''
}
}
})