Files
soul-yongping/miniprogram/utils/soulBridge.js

164 lines
6.0 KiB
JavaScript
Raw Normal View History

2026-03-24 15:44:08 +08:00
/**
* 分销 / 微信支付 / 代付链路 / 存客宝留资 小程序侧统一桥接
* 阅读页 @mention会员详情点头像章节与代付支付等共用
*/
/**
* 支付订单携带的推荐码优先落地页写入的 storage否则当前用户自己的码便于自购归因一致
*/
function getReferralCodeForPay(app) {
try {
const s = wx.getStorageSync('referral_code')
if (s != null && String(s).trim() !== '') return String(s).trim()
} catch (e) {}
if (app && typeof app.getMyReferralCode === 'function') {
const c = app.getMyReferralCode()
if (c) return String(c).trim()
}
return ''
}
/** 章节 / 全书支付描述(与 read 页原逻辑一致) */
function buildSectionPayDescription(productType, sectionId, sectionTitle) {
if (productType === 'fullbook') return '《一场Soul的创业实验》全书'
if (productType === 'section') {
const t = sectionTitle || sectionId || ''
const short = t.length > 20 ? t.slice(0, 20) + '...' : t
return `章节${sectionId}-${short}`
}
return ''
}
/**
* 调起微信 JSAPI 支付字段与 soul-api GetJSAPIPayParams 一致 spread 全对象以免带入多余字段
*/
function requestWxJsapiPayment(payParams) {
return new Promise((resolve, reject) => {
if (!payParams || payParams.timeStamp == null) {
reject(new Error('支付参数异常'))
return
}
wx.requestPayment({
timeStamp: String(payParams.timeStamp),
nonceStr: payParams.nonceStr,
package: payParams.package,
signType: payParams.signType || 'RSA',
paySign: payParams.paySign,
success: resolve,
fail: reject
})
})
}
/** 支付成功后主动查单,缓解回调延迟导致订单长期 created */
function syncOrderStatusQuery(app, orderSn) {
if (!app || !orderSn) return Promise.resolve()
return app.request(`/api/miniprogram/pay?orderSn=${encodeURIComponent(orderSn)}`, { silent: true }).catch(() => null)
}
/**
* 提交存客宝 lead与阅读页 @会员详情点头像同接口
* @param {object} app getApp()
2026-03-24 18:45:32 +08:00
* @param {{ targetUserId?: string, targetNickname?: string, targetMemberId?: string, targetMemberName?: string, source: string, phoneModalContent?: string }} opts
2026-03-24 15:44:08 +08:00
* @returns {Promise<boolean>} 是否提交成功
*/
async function submitCkbLead(app, opts) {
2026-03-24 18:45:32 +08:00
const targetUserId = ((opts && opts.targetUserId) || '').trim()
const targetMemberId = ((opts && opts.targetMemberId) || '').trim()
let targetNickname = (opts && opts.targetNickname != null) ? String(opts.targetNickname).trim() : ''
if (targetUserId && !targetNickname) targetNickname = 'TA'
const targetMemberName = ((opts && opts.targetMemberName) || '').trim()
2026-03-24 15:44:08 +08:00
const source = (opts && opts.source) || 'article_mention'
const phoneModalContent = (opts && opts.phoneModalContent) || '请先填写手机号(必填),以便对方联系您'
2026-03-24 18:45:32 +08:00
// 文章 @ 为 token会员详情无 token 时用 targetMemberId 走全局获客计划(与后端 CKBLead 一致)
if (!targetUserId && !targetMemberId) return false
2026-03-24 15:44:08 +08:00
if (!app.globalData.isLoggedIn || !app.globalData.userInfo) {
return await new Promise((resolve) => {
wx.showModal({
title: '提示',
content: '请先登录后再添加好友',
confirmText: '去登录',
cancelText: '取消',
success: (res) => {
if (res.confirm) wx.switchTab({ url: '/pages/my/my' })
resolve(false)
}
})
})
}
const myUserId = app.globalData.userInfo.id
let phone = (app.globalData.userInfo.phone || wx.getStorageSync('user_phone') || '').trim().replace(/\s/g, '')
let wechatId = (app.globalData.userInfo.wechatId || app.globalData.userInfo.wechat_id || wx.getStorageSync('user_wechat') || '').trim()
if (!phone || !/^1[3-9]\d{9}$/.test(phone)) {
try {
const profileRes = await app.request({ url: `/api/miniprogram/user/profile?userId=${myUserId}`, silent: true })
if (profileRes && profileRes.success && profileRes.data) {
phone = (profileRes.data.phone || wx.getStorageSync('user_phone') || '').trim().replace(/\s/g, '')
wechatId = (profileRes.data.wechatId || profileRes.data.wechat_id || wx.getStorageSync('user_wechat') || '').trim()
}
} catch (e) {}
}
if (!phone || !/^1[3-9]\d{9}$/.test(phone)) {
return await new Promise((resolve) => {
wx.showModal({
title: '完善资料',
content: phoneModalContent,
confirmText: '去填写',
cancelText: '取消',
success: (res) => {
if (res.confirm) wx.navigateTo({ url: '/pages/profile-edit/profile-edit' })
resolve(false)
}
})
})
}
wx.showLoading({ title: '提交中...', mask: true })
try {
const res = await app.request({
url: '/api/miniprogram/ckb/lead',
method: 'POST',
data: {
userId: myUserId,
phone: phone || undefined,
wechatId: wechatId || undefined,
name: (app.globalData.userInfo.nickname || '').trim() || undefined,
2026-03-24 18:45:32 +08:00
targetUserId: targetUserId || undefined,
targetNickname: targetNickname !== '' ? targetNickname : undefined,
targetMemberId: targetMemberId || undefined,
targetMemberName: targetMemberName || undefined,
2026-03-24 15:44:08 +08:00
source
}
})
wx.hideLoading()
if (res && res.success) {
try {
wx.setStorageSync('lead_last_submit_ts', Date.now())
} catch (e) {}
wx.showToast({ title: res.message || '提交成功,对方会尽快联系您', icon: 'success' })
return true
}
wx.showToast({ title: (res && res.message) || '提交失败', icon: 'none' })
return false
} catch (e) {
wx.hideLoading()
2026-03-24 18:45:32 +08:00
const resp = e && e.response
const hint = (resp && (resp.message || resp.error)) || (e && e.message) || '提交失败'
wx.showToast({ title: String(hint), icon: 'none' })
2026-03-24 15:44:08 +08:00
return false
}
}
module.exports = {
getReferralCodeForPay,
buildSectionPayDescription,
requestWxJsapiPayment,
syncOrderStatusQuery,
submitCkbLead
}