// #ifdef APP-PLUS import { initDypay, canOpenDypay, openDypay } from '@/uni_modules/tb-douyin-pay'; // #endif import request from './request.js'; import { BASE_URL } from './config.js'; import { TOKEN_NAME, USER_DATA } from './auth.js'; import { toSdkPayInfo, queryUntilSettled } from './douyin-pay-adapter.mjs'; let active = false; let resuming = false; function accountKey() { if (!uni.getStorageSync(TOKEN_NAME)) return ''; const user = uni.getStorageSync(USER_DATA) || {}; const id = user.userId || user.id; return id ? `tb-douyin:${BASE_URL}:${id}` : ''; } async function query(orderNum) { return queryUntilSettled(async options => { const response = await request({ ...options, isShowLoading: false }); if (response?.bizcode !== 100) throw new Error('查询支付结果失败'); return response.data; }, orderNum); } export function douyinPayTypes(types) { // #ifdef H5 return types.split(',').includes('6') ? types : `${types},6`; // #endif // #ifdef APP-PLUS return types.split(',').includes('6') ? types : `${types},6`; // #endif // #ifndef APP-PLUS return types; // #endif } export function filterDouyinPayWays(ways) { // #ifdef H5 return ways || []; // #endif // #ifdef APP-PLUS return ways || []; // #endif // #ifndef APP-PLUS return (ways || []).filter(item => item.type !== 'douyin'); // #endif } function showState(state, key, orderNum) { if (key !== accountKey()) return; if (state.state !== 'pending' && uni.getStorageSync(key) === orderNum) uni.removeStorageSync(key); uni.$emit('douyin-payment-result', { orderNum, state: state.state }); uni.showToast({ title: state.state === 'paid' ? '支付成功' : state.state === 'failed' ? '支付未成功,请查看订单' : '支付结果待确认,请稍后查看订单', icon: 'none', duration: 2500 }); } // Runs BEFORE creating an order. Never start another payment while an earlier result is unknown. export async function prepareDouyinPay(payway) { if (payway !== 'douyin') return true; try { // #ifndef APP-PLUS throw new Error('抖音支付仅支持 Android/iOS App'); // #endif // #ifdef APP-PLUS if (active || resuming) throw new Error('正在处理支付,请勿重复点击'); const key = accountKey(); if (!key) throw new Error('请先登录后再支付'); const previous = uni.getStorageSync(key); if (previous) { resuming = true; try { showState(await query(previous), key, previous); } finally { resuming = false; } return false; } if (!canOpenDypay()) throw new Error('请先安装或升级抖音客户端'); return true; // #endif } catch (error) { uni.showToast({ title: error.message || '暂时无法支付,请稍后重试', icon: 'none' }); return false; } } // Takes the existing settlement/recharge response; does NOT create a second order. export async function appDypayFun(payment) { // #ifndef APP-PLUS uni.showToast({ title: '抖音支付仅支持 Android/iOS App', icon: 'none' }); return; // #endif // #ifdef APP-PLUS if (active) return; active = true; const key = accountKey(); try { if (!key || !payment.orderNum) throw new Error('登录身份或支付订单编号缺失'); const payInfo = toSdkPayInfo(payment); const previous = uni.getStorageSync(key); if (previous) { const state = await query(previous); showState(state, key, previous); if (state.state === 'pending' || previous === payment.orderNum) return state; } uni.setStorageSync(key, payment.orderNum); if (!initDypay({ appId: payInfo.appid, callbackScheme: payment.douyin.callbackScheme || 'trustbridgeapp' })) { throw new Error('支付初始化失败,请先查询订单'); } await new Promise(resolve => openDypay({ payInfo, showLoading: true }, resolve)); const state = await query(payment.orderNum); showState(state, key, payment.orderNum); return state; } catch (error) { if (key === accountKey()) uni.showToast({ title: error.message || '支付结果待确认,请查看订单', icon: 'none' }); return { state: 'error', message: error.message || '支付结果待确认,请查看订单' }; } finally { active = false; } // #endif } export async function resumeDouyinPay() { // #ifdef APP-PLUS if (active || resuming) return; const key = accountKey(); const pending = key && uni.getStorageSync(key); if (!pending) return; resuming = true; try { showState(await query(pending), key, pending); } catch (_) { /* Keep the order for a later onShow. Never infer a payment failure. */ } finally { resuming = false; } // #endif }