支付通路

This commit is contained in:
tianmo committed 2026-09-30 15:08:16 +08:00
1 parent c7f43e30a9
commit 85b0e70907
26 files changed
+1324 -74

No files matched your search

+40
View File
@@ -25,6 +25,46 @@ export function xmlField(xml: string, field: string): string {
return match ? match[1]!.trim() : '';
}
/**
* 取推送的事件名。发货/退款推送是 XML,iOS 退款问询是 JSON,两种都要认。
* 认不出来就返回空串——调用方据此记「无 Event」。
*/
export function eventOf(body: string): string {
const fromXml = xmlField(body, 'Event');
if (fromXml) return fromXml;
try {
const parsed = JSON.parse(body) as { Event?: unknown; event?: unknown };
const value = parsed.Event ?? parsed.event;
return typeof value === 'string' ? value : '';
} catch {
return '';
}
}
/**
* 取推送里的任意字段,XML 和 JSON 都认。
*
* 为什么需要:文档把 iOS 退款问询的报文体写成了 JSON 对象,但实际推过来的是
* 明文模式的标准 XML 信封(`<pay_order_id><![CDATA[...]]></pay_order_id>`)。
* 只按 JSON 解析会抛异常,整个问询处理直接掉进兜底分支。
*/
export function fieldOf(body: string, field: string): string {
const fromXml = xmlField(body, field);
if (fromXml) return fromXml;
try {
const parsed = JSON.parse(body) as Record<string, unknown>;
const value = parsed[field];
return value === undefined || value === null ? '' : String(value);
} catch {
return '';
}
}
/** 把值塞进 CDATA 安全地用于回包。 */
export function cdata(value: string): string {
return `<![CDATA[${value.replace(/]]>/g, ']] >')}]]>`;
}
/**
* 安全模式:AES-256-CBC。
* 密钥 = Base64(EncodingAESKey + '='),IV 取密钥前 16 字节。