fix: 接入抖音原生支付并修复App支付服务缺失
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
// #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
|
||||
}
|
||||
Reference in New Issue
Block a user