// Pure adapter: keeps merchant credentials and signing on the server. export function toSdkPayInfo(payment) { const data = payment?.douyin; if (!data) throw new Error('后端未返回抖音支付参数'); if (data.type && data.type !== 'app') throw new Error('当前仅支持抖音 App 支付'); let nested = data.orderInfo || {}; if (typeof nested === 'string') { try { nested = JSON.parse(nested); } catch (_) { throw new Error('抖音支付 orderInfo 格式错误'); } } const field = (camel, lower) => nested[lower] ?? nested[camel] ?? data[camel] ?? data[lower]; const info = { appid: field('appId', 'appid'), partnerid: field('mchId', 'partnerid'), prepayid: field('prepayId', 'prepayid'), package: field('packageValue', 'package'), noncestr: field('nonceStr', 'noncestr'), timestamp: field('timeStamp', 'timestamp'), sign: field('sign', 'sign') }; if (typeof info.timestamp === 'number' && Number.isSafeInteger(info.timestamp)) info.timestamp = String(info.timestamp); for (const [key, value] of Object.entries(info)) { if (typeof value !== 'string' || !value.trim()) { throw new Error(`缺少支付参数 ${key},请先部署后端 SDK 签名补丁`); } } if (info.package !== 'Sign=DYPay') throw new Error('抖音支付 package 不正确'); return info; } // request is the App's existing authenticated request wrapper, returning ApiResult.data. export async function queryUntilSettled(request, orderNum, { attempts = 5, pause = 1500 } = {}) { for (let i = 0; i < attempts; i++) { const result = await request({ url: '/payment/queryResult', method: 'GET', data: { orderNum } }); if (result?.state === 2) return { state: 'paid' }; if (result?.state === 3) return { state: 'failed' }; if (i + 1 < attempts) await new Promise(resolve => setTimeout(resolve, pause)); } return { state: 'pending' }; }