订单配置

This commit is contained in:
tianmo committed 2026-09-30 11:02:58 +08:00
1 parent e81481623c
commit c7f43e30a9
11 files changed
+492 -19

No files matched your search

+42
View File
@@ -0,0 +1,42 @@
import { createDecipheriv, createHash, timingSafeEqual } from 'node:crypto';
/**
* 微信「消息推送」服务器地址相关的两个协议细节。
*
* 小程序后台填了 URL 之后,微信会先发一个 GET 来验签,验不过就一直显示
* 「服务器地址验证失败」,也就配不上发货推送。虚拟支付文档说的「发货推送 URL」
* 指的就是这个地址。
*/
/** 签名 = sha1(Token 与 URL 参数按字典序排序后拼接)。安全模式下把 Encrypt 也算进去。 */
export function wechatSignature(token: string, ...parts: string[]): string {
return createHash('sha1').update([token, ...parts].sort().join('')).digest('hex');
}
export function sameHex(a: string, b: string): boolean {
const x = Buffer.from(a);
const y = Buffer.from(b);
return x.length > 0 && x.length === y.length && timingSafeEqual(x, y);
}
/** 取 XML 标签文本(兼容 CDATA)。 */
export function xmlField(xml: string, field: string): string {
const match = new RegExp(`<${field}>(?:<!\\[CDATA\\[)?([\\s\\S]*?)(?:\\]\\]>)?</${field}>`).exec(xml);
return match ? match[1]!.trim() : '';
}
/**
* 安全模式:AES-256-CBC。
* 密钥 = Base64(EncodingAESKey + '='),IV 取密钥前 16 字节。
* 明文 = 16 字节随机数 + 4 字节长度 + msg + appId,填充是 PKCS#7(块长 32)。
* 填充长度可能是 17~32,OpenSSL 的自动去填充只认 ≤16,所以关掉自己剥。
*/
export function decryptWechatMessage(encodingAesKey: string, base64: string): string {
const key = Buffer.from(encodingAesKey + '=', 'base64');
const decipher = createDecipheriv('aes-256-cbc', key, key.subarray(0, 16));
decipher.setAutoPadding(false);
const raw = Buffer.concat([decipher.update(Buffer.from(base64, 'base64')), decipher.final()]);
const pad = raw[raw.length - 1]!;
const body = pad >= 1 && pad <= 32 ? raw.subarray(0, raw.length - pad) : raw;
return body.subarray(20, 20 + body.readUInt32BE(16)).toString('utf8');
}