@h-ai/payment 0.1.0-alpha.18 → 0.1.0-alpha.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -86,12 +86,17 @@ await payment.init({
|
|
|
86
86
|
stripe: {
|
|
87
87
|
secretKey: 'sk_xxx',
|
|
88
88
|
webhookSecret: 'whsec_xxx',
|
|
89
|
+
webhookToleranceSeconds: 300, // 可选,默认 300 秒
|
|
89
90
|
},
|
|
90
91
|
})
|
|
91
92
|
```
|
|
92
93
|
|
|
93
94
|
只配置需要的 Provider 即可,未配置的 Provider 不会注册。
|
|
94
95
|
|
|
96
|
+
金额字段统一使用“分”为单位,且必须为正整数。模块会在调用具体 Provider 之前先校验 `amount` / `totalAmount`,避免把非法金额继续传给下游支付平台。
|
|
97
|
+
|
|
98
|
+
所有内置 Provider 的 HTTP 请求默认附带 15 秒超时,避免网络异常时长时间挂起。
|
|
99
|
+
|
|
95
100
|
## 审计日志
|
|
96
101
|
|
|
97
102
|
关键支付操作执行成功后会自动写入审计日志(依赖 `@h-ai/audit`),无需额外配置。审计写入失败仅输出 warn 日志,不影响支付操作。
|
|
@@ -111,6 +116,9 @@ await payment.init({
|
|
|
111
116
|
const result = await payment.createOrder('wechat', orderInput)
|
|
112
117
|
if (!result.success) {
|
|
113
118
|
switch (result.error.code) {
|
|
119
|
+
case HaiPaymentError.INVALID_AMOUNT:
|
|
120
|
+
// 金额不是正整数,或 refund.totalAmount < amount
|
|
121
|
+
break
|
|
114
122
|
case HaiPaymentError.PROVIDER_NOT_FOUND:
|
|
115
123
|
// Provider 未注册
|
|
116
124
|
break
|
|
@@ -128,7 +136,9 @@ if (!result.success) {
|
|
|
128
136
|
| `HaiPaymentError.CREATE_ORDER_FAILED` | `hai:payment:001` | 创建订单失败 |
|
|
129
137
|
| `HaiPaymentError.NOT_INITIALIZED` | `hai:payment:010` | 模块未初始化 |
|
|
130
138
|
| `HaiPaymentError.PROVIDER_NOT_FOUND` | `hai:payment:030` | Provider 未注册 |
|
|
139
|
+
| `HaiPaymentError.INVALID_AMOUNT` | `hai:payment:040` | 金额无效 |
|
|
131
140
|
| `HaiPaymentError.NOTIFY_VERIFY_FAILED` | `hai:payment:050` | 回调验签失败 |
|
|
141
|
+
| `HaiPaymentError.NOTIFY_PARSE_FAILED` | `hai:payment:051` | 回调解析失败 |
|
|
132
142
|
| `HaiPaymentError.CONFIG_ERROR` | `hai:payment:070` | 配置无效 |
|
|
133
143
|
|
|
134
144
|
## 测试
|
package/dist/client/index.d.ts
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { P as PaymentFunctions } from './payment-types-
|
|
2
|
-
export { A as AlipayConfig, a as AlipayConfigSchema, C as CreateOrderInput, H as HaiPaymentError, O as OrderStatus, b as OrderStatusValue, c as PaymentConfig, d as PaymentConfigInput, e as PaymentConfigSchema, f as PaymentNotifyRequest, g as PaymentNotifyResult, h as PaymentOrder, i as PaymentProvider, R as RefundInput, j as RefundResult, S as StripeConfig, k as StripeConfigSchema, T as TradeType, W as WechatPayConfig, l as WechatPayConfigSchema } from './payment-types-
|
|
1
|
+
import { P as PaymentFunctions } from './payment-types-oKsJbCSZ.js';
|
|
2
|
+
export { A as AlipayConfig, a as AlipayConfigSchema, C as CreateOrderInput, H as HaiPaymentError, O as OrderStatus, b as OrderStatusValue, c as PaymentConfig, d as PaymentConfigInput, e as PaymentConfigSchema, f as PaymentNotifyRequest, g as PaymentNotifyResult, h as PaymentOrder, i as PaymentProvider, R as RefundInput, j as RefundResult, S as StripeConfig, k as StripeConfigSchema, T as TradeType, W as WechatPayConfig, l as WechatPayConfigSchema } from './payment-types-oKsJbCSZ.js';
|
|
3
3
|
import '@h-ai/core';
|
|
4
4
|
import 'zod';
|
|
5
5
|
|
package/dist/index.js
CHANGED
|
@@ -23,7 +23,8 @@ var AlipayConfigSchema = z.object({
|
|
|
23
23
|
});
|
|
24
24
|
var StripeConfigSchema = z.object({
|
|
25
25
|
secretKey: z.string().min(1, paymentM("payment_configFieldRequired")),
|
|
26
|
-
webhookSecret: z.string().min(1, paymentM("payment_configFieldRequired"))
|
|
26
|
+
webhookSecret: z.string().min(1, paymentM("payment_configFieldRequired")),
|
|
27
|
+
webhookToleranceSeconds: z.number().int().positive().default(300)
|
|
27
28
|
});
|
|
28
29
|
var PaymentConfigSchema = z.object({
|
|
29
30
|
wechat: WechatPayConfigSchema.optional(),
|
|
@@ -38,6 +39,35 @@ async function auditLog(input) {
|
|
|
38
39
|
logger.warn("Failed to write payment audit log", { action: input.action, error: result.error.message });
|
|
39
40
|
}
|
|
40
41
|
}
|
|
42
|
+
function isValidAmount(amount) {
|
|
43
|
+
return Number.isSafeInteger(amount) && amount > 0;
|
|
44
|
+
}
|
|
45
|
+
function validateCreateOrderInput(input) {
|
|
46
|
+
if (!isValidAmount(input.amount)) {
|
|
47
|
+
return err(
|
|
48
|
+
HaiPaymentError.INVALID_AMOUNT,
|
|
49
|
+
paymentM("payment_invalidAmount")
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
return ok(void 0);
|
|
53
|
+
}
|
|
54
|
+
function validateRefundInput(input) {
|
|
55
|
+
if (!isValidAmount(input.amount)) {
|
|
56
|
+
return err(
|
|
57
|
+
HaiPaymentError.INVALID_AMOUNT,
|
|
58
|
+
paymentM("payment_invalidAmount")
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
if (input.totalAmount !== void 0) {
|
|
62
|
+
if (!isValidAmount(input.totalAmount) || input.totalAmount < input.amount) {
|
|
63
|
+
return err(
|
|
64
|
+
HaiPaymentError.INVALID_AMOUNT,
|
|
65
|
+
paymentM("payment_invalidAmount")
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return ok(void 0);
|
|
70
|
+
}
|
|
41
71
|
function registerProvider(provider) {
|
|
42
72
|
providers.set(provider.name, provider);
|
|
43
73
|
}
|
|
@@ -58,6 +88,9 @@ async function createOrder(providerName, input) {
|
|
|
58
88
|
const result = requireProvider(providerName);
|
|
59
89
|
if (!result.success)
|
|
60
90
|
return result;
|
|
91
|
+
const validateResult = validateCreateOrderInput(input);
|
|
92
|
+
if (!validateResult.success)
|
|
93
|
+
return validateResult;
|
|
61
94
|
const orderResult = await result.data.createOrder(input);
|
|
62
95
|
if (orderResult.success) {
|
|
63
96
|
await auditLog({
|
|
@@ -94,6 +127,9 @@ async function refund(providerName, input) {
|
|
|
94
127
|
const result = requireProvider(providerName);
|
|
95
128
|
if (!result.success)
|
|
96
129
|
return result;
|
|
130
|
+
const validateResult = validateRefundInput(input);
|
|
131
|
+
if (!validateResult.success)
|
|
132
|
+
return validateResult;
|
|
97
133
|
const refundResult = await result.data.refund(input);
|
|
98
134
|
if (refundResult.success) {
|
|
99
135
|
await auditLog({
|
|
@@ -123,6 +159,15 @@ async function closeOrder(providerName, orderNo) {
|
|
|
123
159
|
function clearProviders() {
|
|
124
160
|
providers.clear();
|
|
125
161
|
}
|
|
162
|
+
|
|
163
|
+
// src/providers/payment-provider-http.ts
|
|
164
|
+
var DEFAULT_PROVIDER_TIMEOUT_MS = 15e3;
|
|
165
|
+
async function fetchWithTimeout(input, init, timeoutMs = DEFAULT_PROVIDER_TIMEOUT_MS) {
|
|
166
|
+
return fetch(input, {
|
|
167
|
+
...init,
|
|
168
|
+
signal: init.signal ? AbortSignal.any([init.signal, AbortSignal.timeout(timeoutMs)]) : AbortSignal.timeout(timeoutMs)
|
|
169
|
+
});
|
|
170
|
+
}
|
|
126
171
|
function signAlipayParams(params, privateKey, signType = "RSA2") {
|
|
127
172
|
const sorted = Object.keys(params).filter((k) => params[k] !== void 0 && params[k] !== "").sort().map((k) => `${k}=${params[k]}`).join("&");
|
|
128
173
|
const algorithm = signType === "RSA2" ? "RSA-SHA256" : "RSA-SHA1";
|
|
@@ -139,10 +184,37 @@ function verifyAlipayNotify(params, alipayPublicKey) {
|
|
|
139
184
|
verify.update(sorted);
|
|
140
185
|
return verify.verify(alipayPublicKey, sign, "base64");
|
|
141
186
|
}
|
|
187
|
+
var AlipayNotifyParamsSchema = z.object({
|
|
188
|
+
out_trade_no: z.string().min(1),
|
|
189
|
+
trade_no: z.string().min(1),
|
|
190
|
+
trade_status: z.string().min(1),
|
|
191
|
+
total_amount: z.string().min(1),
|
|
192
|
+
gmt_payment: z.string().optional()
|
|
193
|
+
}).catchall(z.string());
|
|
142
194
|
|
|
143
195
|
// src/providers/alipay/alipay-provider.ts
|
|
144
196
|
var ALIPAY_GATEWAY = "https://openapi.alipay.com/gateway.do";
|
|
145
197
|
var ALIPAY_SANDBOX_GATEWAY = "https://openapi-sandbox.dl.alipaydev.com/gateway.do";
|
|
198
|
+
function formatFenAmount(amount) {
|
|
199
|
+
const yuan = Math.floor(amount / 100);
|
|
200
|
+
const cents = String(amount % 100).padStart(2, "0");
|
|
201
|
+
return `${yuan}.${cents}`;
|
|
202
|
+
}
|
|
203
|
+
function parseAlipayAmount(value) {
|
|
204
|
+
const trimmedValue = value.trim();
|
|
205
|
+
if (!/^\d+(?:\.\d{1,2})?$/.test(trimmedValue)) {
|
|
206
|
+
throw new Error(`Invalid Alipay amount: ${value}`);
|
|
207
|
+
}
|
|
208
|
+
const [yuanPart, centsPart = ""] = trimmedValue.split(".");
|
|
209
|
+
return Number.parseInt(yuanPart, 10) * 100 + Number.parseInt(centsPart.padEnd(2, "0"), 10);
|
|
210
|
+
}
|
|
211
|
+
function parseAlipayNotifyParams(body) {
|
|
212
|
+
const parseResult = AlipayNotifyParamsSchema.safeParse(Object.fromEntries(new URLSearchParams(body).entries()));
|
|
213
|
+
if (!parseResult.success) {
|
|
214
|
+
throw parseResult.error;
|
|
215
|
+
}
|
|
216
|
+
return parseResult.data;
|
|
217
|
+
}
|
|
146
218
|
function createAlipayProvider(config) {
|
|
147
219
|
const gateway = config.sandbox ? ALIPAY_SANDBOX_GATEWAY : ALIPAY_GATEWAY;
|
|
148
220
|
const signType = config.signType ?? "RSA2";
|
|
@@ -170,14 +242,14 @@ function createAlipayProvider(config) {
|
|
|
170
242
|
const sign = signAlipayParams(params, config.privateKey, signType);
|
|
171
243
|
const allParams = { ...params, sign };
|
|
172
244
|
const queryString = Object.entries(allParams).map(([k, v]) => `${k}=${encodeURIComponent(v)}`).join("&");
|
|
173
|
-
const
|
|
245
|
+
const timedResponse = await fetchWithTimeout(`${gateway}?${queryString}`, {
|
|
174
246
|
method: "POST",
|
|
175
247
|
headers: { "Content-Type": "application/x-www-form-urlencoded" }
|
|
176
248
|
});
|
|
177
|
-
if (!
|
|
178
|
-
throw new Error(`Alipay API failed: ${
|
|
249
|
+
if (!timedResponse.ok) {
|
|
250
|
+
throw new Error(`Alipay API failed: ${timedResponse.status}`);
|
|
179
251
|
}
|
|
180
|
-
return
|
|
252
|
+
return timedResponse.json();
|
|
181
253
|
}
|
|
182
254
|
return {
|
|
183
255
|
name: "alipay",
|
|
@@ -186,8 +258,7 @@ function createAlipayProvider(config) {
|
|
|
186
258
|
const { method, productCode } = getTradeConfig(input.tradeType);
|
|
187
259
|
const bizContent = JSON.stringify({
|
|
188
260
|
out_trade_no: input.orderNo,
|
|
189
|
-
total_amount: (input.amount
|
|
190
|
-
// 分 → 元
|
|
261
|
+
total_amount: formatFenAmount(input.amount),
|
|
191
262
|
subject: input.description,
|
|
192
263
|
product_code: productCode,
|
|
193
264
|
passback_params: input.metadata ? JSON.stringify(input.metadata) : void 0
|
|
@@ -215,12 +286,7 @@ function createAlipayProvider(config) {
|
|
|
215
286
|
},
|
|
216
287
|
async handleNotify(request) {
|
|
217
288
|
try {
|
|
218
|
-
const params =
|
|
219
|
-
const pairs = request.body.split("&");
|
|
220
|
-
for (const pair of pairs) {
|
|
221
|
-
const [key, ...rest] = pair.split("=");
|
|
222
|
-
params[decodeURIComponent(key)] = decodeURIComponent(rest.join("="));
|
|
223
|
-
}
|
|
289
|
+
const params = parseAlipayNotifyParams(request.body);
|
|
224
290
|
const valid = verifyAlipayNotify(params, config.alipayPublicKey);
|
|
225
291
|
if (!valid) {
|
|
226
292
|
return err(
|
|
@@ -237,8 +303,7 @@ function createAlipayProvider(config) {
|
|
|
237
303
|
return ok({
|
|
238
304
|
orderNo: params.out_trade_no,
|
|
239
305
|
transactionId: params.trade_no,
|
|
240
|
-
amount:
|
|
241
|
-
// 元 → 分
|
|
306
|
+
amount: parseAlipayAmount(params.total_amount),
|
|
242
307
|
status: statusMap[params.trade_status] ?? "pending",
|
|
243
308
|
paidAt: params.gmt_payment ? new Date(params.gmt_payment) : void 0,
|
|
244
309
|
// 支付宝回调原始 params 的强类型为 AlipayNotifyParams,此处统一以 Record 暴露给上层做调试/审计
|
|
@@ -271,7 +336,7 @@ function createAlipayProvider(config) {
|
|
|
271
336
|
orderNo,
|
|
272
337
|
transactionId: data?.trade_no,
|
|
273
338
|
status: statusMap[data?.trade_status] ?? "pending",
|
|
274
|
-
amount:
|
|
339
|
+
amount: parseAlipayAmount(data?.total_amount ?? "0"),
|
|
275
340
|
paidAt: data?.send_pay_date ? new Date(data.send_pay_date) : void 0
|
|
276
341
|
});
|
|
277
342
|
} catch (cause) {
|
|
@@ -290,7 +355,7 @@ function createAlipayProvider(config) {
|
|
|
290
355
|
biz_content: JSON.stringify({
|
|
291
356
|
out_trade_no: input.orderNo,
|
|
292
357
|
out_request_no: input.refundNo,
|
|
293
|
-
refund_amount: (input.amount
|
|
358
|
+
refund_amount: formatFenAmount(input.amount),
|
|
294
359
|
refund_reason: input.reason
|
|
295
360
|
})
|
|
296
361
|
};
|
|
@@ -331,7 +396,7 @@ function createAlipayProvider(config) {
|
|
|
331
396
|
var STRIPE_API_BASE = "https://api.stripe.com/v1";
|
|
332
397
|
function createStripeProvider(config) {
|
|
333
398
|
async function stripeRequest(method, path, body) {
|
|
334
|
-
const response = await
|
|
399
|
+
const response = await fetchWithTimeout(`${STRIPE_API_BASE}${path}`, {
|
|
335
400
|
method,
|
|
336
401
|
headers: {
|
|
337
402
|
"Authorization": `Bearer ${config.secretKey}`,
|
|
@@ -345,7 +410,7 @@ function createStripeProvider(config) {
|
|
|
345
410
|
}
|
|
346
411
|
return response.json();
|
|
347
412
|
}
|
|
348
|
-
const TIMESTAMP_TOLERANCE = 300;
|
|
413
|
+
const TIMESTAMP_TOLERANCE = config.webhookToleranceSeconds ?? 300;
|
|
349
414
|
function verifyWebhookSignature(payload, signature) {
|
|
350
415
|
const parts = signature.split(",");
|
|
351
416
|
const timestamp = parts.find((p) => p.startsWith("t="))?.slice(2) ?? "";
|
|
@@ -549,7 +614,7 @@ function createWechatPayProvider(config) {
|
|
|
549
614
|
const bodyStr = body ? JSON.stringify(body) : "";
|
|
550
615
|
const signature = signRequest(method, path, timestamp, nonce, bodyStr, config.privateKey);
|
|
551
616
|
const authorization = `WECHATPAY2-SHA256-RSA2048 mchid="${config.mchId}",nonce_str="${nonce}",timestamp="${timestamp}",serial_no="${config.serialNo}",signature="${signature}"`;
|
|
552
|
-
const response = await
|
|
617
|
+
const response = await fetchWithTimeout(`${WECHAT_API_BASE}${path}`, {
|
|
553
618
|
method,
|
|
554
619
|
headers: {
|
|
555
620
|
"Content-Type": "application/json",
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/payment-config.ts","../src/payment-functions.ts","../src/providers/alipay/alipay-sign.ts","../src/providers/alipay/alipay-provider.ts","../src/providers/stripe/stripe-provider.ts","../src/providers/wechat/wechat-pay-sign.ts","../src/providers/wechat/wechat-pay-provider.ts","../src/payment-main.ts"],"names":["ok","err","core","refund","createSign","createVerify","logger"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * @h-ai/payment — 错误码 + 配置 Schema\n *\n * 支付模块的错误码、Zod 配置 Schema 与配置类型。\n * @module payment-config\n */\n\nimport { z } from 'zod'\nimport { paymentM } from './payment-i18n.js'\n\n// ─── 配置 Schema ───\n\n/** 微信支付配置 Schema */\nexport const WechatPayConfigSchema = z.object({\n mchId: z.string().min(1, paymentM('payment_configFieldRequired')),\n apiV3Key: z.string().min(1, paymentM('payment_configFieldRequired')),\n serialNo: z.string().min(1, paymentM('payment_configFieldRequired')),\n privateKey: z.string().min(1, paymentM('payment_configFieldRequired')),\n platformCert: z.string().optional(),\n appId: z.string().min(1, paymentM('payment_configFieldRequired')),\n})\n\n/** 支付宝配置 Schema */\nexport const AlipayConfigSchema = z.object({\n appId: z.string().min(1, paymentM('payment_configFieldRequired')),\n privateKey: z.string().min(1, paymentM('payment_configFieldRequired')),\n alipayPublicKey: z.string().min(1, paymentM('payment_configFieldRequired')),\n signType: z.enum(['RSA2', 'RSA']).default('RSA2'),\n sandbox: z.boolean().default(false),\n})\n\n/** Stripe 配置 Schema */\nexport const StripeConfigSchema = z.object({\n secretKey: z.string().min(1, paymentM('payment_configFieldRequired')),\n webhookSecret: z.string().min(1, paymentM('payment_configFieldRequired')),\n})\n\n/** 支付模块配置 Schema */\nexport const PaymentConfigSchema = z.object({\n wechat: WechatPayConfigSchema.optional(),\n alipay: AlipayConfigSchema.optional(),\n stripe: StripeConfigSchema.optional(),\n})\n\nexport type PaymentConfig = z.infer<typeof PaymentConfigSchema>\nexport type PaymentConfigInput = z.input<typeof PaymentConfigSchema>\nexport type WechatPayConfig = z.infer<typeof WechatPayConfigSchema>\nexport type AlipayConfig = z.infer<typeof AlipayConfigSchema>\nexport type StripeConfig = z.infer<typeof StripeConfigSchema>\n","/**\n * @h-ai/payment — 业务逻辑编排\n *\n * 统一路由到对应 Provider 的支付操作。\n * @module payment-functions\n */\n\nimport type { CreateAuditLogInput } from '@h-ai/audit'\nimport type { HaiResult } from '@h-ai/core'\nimport type { CreateOrderInput, OrderStatus, PaymentNotifyRequest, PaymentNotifyResult, PaymentOrder, PaymentProvider, RefundInput, RefundResult } from './payment-types.js'\nimport { audit } from '@h-ai/audit'\nimport { core, err, ok } from '@h-ai/core'\nimport { paymentM } from './payment-i18n.js'\nimport {\n\n HaiPaymentError,\n\n} from './payment-types.js'\n\nconst logger = core.logger.child({ module: 'payment', scope: 'functions' })\n\n/** Provider 注册表 */\nconst providers = new Map<string, PaymentProvider>()\n\n/**\n * 写审计日志(失败仅 warn,不影响支付操作)\n */\nasync function auditLog(input: CreateAuditLogInput): Promise<void> {\n const result = await audit.log(input)\n if (!result.success) {\n logger.warn('Failed to write payment audit log', { action: input.action, error: result.error.message })\n }\n}\n\n/**\n * 注册支付 Provider\n *\n * @param provider - PaymentProvider 实例\n */\nexport function registerProvider(provider: PaymentProvider): void {\n providers.set(provider.name, provider)\n}\n\n/**\n * 获取已注册的 Provider\n *\n * @param name - Provider 名称\n * @returns Provider 实例(不存在返回 undefined)\n */\nexport function getProvider(name: string): PaymentProvider | undefined {\n return providers.get(name)\n}\n\n/**\n * 获取 Provider(不存在则返回 err)\n */\nfunction requireProvider(name: string): HaiResult<PaymentProvider> {\n const provider = providers.get(name)\n if (!provider) {\n return err(\n HaiPaymentError.PROVIDER_NOT_FOUND,\n paymentM('payment_providerNotFound'),\n )\n }\n return ok(provider)\n}\n\n/**\n * 通过指定 Provider 创建订单\n *\n * @param providerName - Provider 名称('wechat' | 'alipay' | 'stripe')\n * @param input - 创建订单入参\n */\nexport async function createOrder(\n providerName: string,\n input: CreateOrderInput,\n): Promise<HaiResult<PaymentOrder>> {\n const result = requireProvider(providerName)\n if (!result.success)\n return result\n const orderResult = await result.data.createOrder(input)\n if (orderResult.success) {\n await auditLog({\n action: 'create_order',\n resource: 'payment',\n resourceId: input.orderNo,\n details: { provider: providerName, amount: input.amount, tradeType: input.tradeType },\n })\n }\n return orderResult\n}\n\n/**\n * 处理支付回调通知\n *\n * @param providerName - Provider 名称\n * @param request - 原始 HTTP 请求数据\n */\nexport async function handleNotify(\n providerName: string,\n request: PaymentNotifyRequest,\n): Promise<HaiResult<PaymentNotifyResult>> {\n const result = requireProvider(providerName)\n if (!result.success)\n return result\n const notifyResult = await result.data.handleNotify(request)\n if (notifyResult.success) {\n await auditLog({\n action: 'payment_notify',\n resource: 'payment',\n resourceId: notifyResult.data.orderNo,\n details: { provider: providerName, transactionId: notifyResult.data.transactionId, status: notifyResult.data.status, amount: notifyResult.data.amount },\n })\n }\n return notifyResult\n}\n\n/**\n * 查询订单状态\n *\n * @param providerName - Provider 名称\n * @param orderNo - 商户订单号\n */\nexport async function queryOrder(\n providerName: string,\n orderNo: string,\n): Promise<HaiResult<OrderStatus>> {\n const result = requireProvider(providerName)\n if (!result.success)\n return result\n return result.data.queryOrder(orderNo)\n}\n\n/**\n * 发起退款\n *\n * @param providerName - Provider 名称\n * @param input - 退款入参\n */\nexport async function refund(\n providerName: string,\n input: RefundInput,\n): Promise<HaiResult<RefundResult>> {\n const result = requireProvider(providerName)\n if (!result.success)\n return result\n const refundResult = await result.data.refund(input)\n if (refundResult.success) {\n await auditLog({\n action: 'refund',\n resource: 'payment',\n resourceId: input.orderNo,\n details: { provider: providerName, refundNo: input.refundNo, amount: input.amount },\n })\n }\n return refundResult\n}\n\n/**\n * 关闭订单\n *\n * @param providerName - Provider 名称\n * @param orderNo - 商户订单号\n */\nexport async function closeOrder(\n providerName: string,\n orderNo: string,\n): Promise<HaiResult<void>> {\n const result = requireProvider(providerName)\n if (!result.success)\n return result\n const closeResult = await result.data.closeOrder(orderNo)\n if (closeResult.success) {\n await auditLog({\n action: 'close_order',\n resource: 'payment',\n resourceId: orderNo,\n details: { provider: providerName },\n })\n }\n return closeResult\n}\n\n/**\n * 清空所有已注册 Provider(测试用)\n */\nexport function clearProviders(): void {\n providers.clear()\n}\n","/**\n * @h-ai/payment — 支付宝签名\n *\n * 支付宝 RSA2/RSA 签名与验签工具。\n * @module alipay-sign\n */\n\nimport { createSign, createVerify } from 'node:crypto'\n\n/**\n * 支付宝参数签名\n *\n * @param params - 待签名参数(已排除 sign)\n * @param privateKey - 应用私钥 PEM\n * @param signType - 签名类型(默认 RSA2)\n * @returns Base64 编码的签名\n */\nexport function signAlipayParams(\n params: Record<string, string>,\n privateKey: string,\n signType: 'RSA2' | 'RSA' = 'RSA2',\n): string {\n // 按 key 字典排序,拼接为 query string\n const sorted = Object.keys(params)\n .filter(k => params[k] !== undefined && params[k] !== '')\n .sort()\n .map(k => `${k}=${params[k]}`)\n .join('&')\n\n const algorithm = signType === 'RSA2' ? 'RSA-SHA256' : 'RSA-SHA1'\n const sign = createSign(algorithm)\n sign.update(sorted)\n return sign.sign(privateKey, 'base64')\n}\n\n/**\n * 验证支付宝回调签名\n *\n * @param params - 回调参数(含 sign 和 sign_type)\n * @param alipayPublicKey - 支付宝公钥 PEM\n * @returns 验签是否通过\n */\nexport function verifyAlipayNotify(\n params: Record<string, string>,\n alipayPublicKey: string,\n): boolean {\n const sign = params.sign ?? ''\n const signType = params.sign_type ?? 'RSA2'\n\n // 排除 sign 和 sign_type,按 key 排序拼接\n const sorted = Object.keys(params)\n .filter(k => k !== 'sign' && k !== 'sign_type' && params[k] !== undefined && params[k] !== '')\n .sort()\n .map(k => `${k}=${params[k]}`)\n .join('&')\n\n const algorithm = signType === 'RSA2' ? 'RSA-SHA256' : 'RSA-SHA1'\n const verify = createVerify(algorithm)\n verify.update(sorted)\n return verify.verify(alipayPublicKey, sign, 'base64')\n}\n","/**\n * @h-ai/payment — 支付宝 Provider\n *\n * 实现 PaymentProvider 接口,对接支付宝 Open API。\n * @module alipay-provider\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { AlipayConfig } from '../../payment-config.js'\nimport type { CreateOrderInput, OrderStatus, PaymentNotifyRequest, PaymentNotifyResult, PaymentOrder, PaymentProvider, RefundInput, RefundResult } from '../../payment-types.js'\nimport type { AlipayNotifyParams } from './alipay-types.js'\nimport { err, ok } from '@h-ai/core'\nimport { paymentM } from '../../payment-i18n.js'\nimport {\n\n HaiPaymentError,\n\n} from '../../payment-types.js'\nimport { signAlipayParams, verifyAlipayNotify } from './alipay-sign.js'\n\n/** 支付宝网关地址 */\nconst ALIPAY_GATEWAY = 'https://openapi.alipay.com/gateway.do'\nconst ALIPAY_SANDBOX_GATEWAY = 'https://openapi-sandbox.dl.alipaydev.com/gateway.do'\n\n/**\n * 创建支付宝 Provider\n *\n * @param config - 支付宝配置\n * @returns PaymentProvider 实例\n */\nexport function createAlipayProvider(config: AlipayConfig): PaymentProvider {\n const gateway = config.sandbox ? ALIPAY_SANDBOX_GATEWAY : ALIPAY_GATEWAY\n const signType = config.signType ?? 'RSA2'\n\n /** 构建公共参数 */\n function buildCommonParams(method: string, notifyUrl: string): Record<string, string> {\n return {\n app_id: config.appId,\n method,\n charset: 'utf-8',\n sign_type: signType,\n timestamp: new Date().toISOString().replace('T', ' ').slice(0, 19),\n version: '1.0',\n notify_url: notifyUrl,\n }\n }\n\n /** 根据 tradeType 映射到产品码和 API */\n function getTradeConfig(tradeType: string): { method: string, productCode: string } {\n const map: Record<string, { method: string, productCode: string }> = {\n jsapi: { method: 'alipay.trade.create', productCode: 'JSAPI_PAY' },\n h5: { method: 'alipay.trade.wap.pay', productCode: 'QUICK_WAP_WAY' },\n app: { method: 'alipay.trade.app.pay', productCode: 'QUICK_MSECURITY_PAY' },\n native: { method: 'alipay.trade.precreate', productCode: 'FACE_TO_FACE_PAYMENT' },\n }\n return map[tradeType] ?? map.h5\n }\n\n /** 发送支付宝 API 请求 */\n async function alipayRequest<T>(params: Record<string, string>): Promise<T> {\n const sign = signAlipayParams(params, config.privateKey, signType)\n const allParams = { ...params, sign }\n\n const queryString = Object.entries(allParams)\n .map(([k, v]) => `${k}=${encodeURIComponent(v)}`)\n .join('&')\n\n const response = await fetch(`${gateway}?${queryString}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n })\n\n if (!response.ok) {\n throw new Error(`Alipay API failed: ${response.status}`)\n }\n\n return response.json() as T\n }\n\n return {\n name: 'alipay',\n\n async createOrder(input: CreateOrderInput): Promise<HaiResult<PaymentOrder>> {\n try {\n const { method, productCode } = getTradeConfig(input.tradeType)\n\n const bizContent = JSON.stringify({\n out_trade_no: input.orderNo,\n total_amount: (input.amount / 100).toFixed(2), // 分 → 元\n subject: input.description,\n product_code: productCode,\n passback_params: input.metadata ? JSON.stringify(input.metadata) : undefined,\n })\n\n const params = {\n ...buildCommonParams(method, input.notifyUrl),\n biz_content: bizContent,\n }\n\n const response = await alipayRequest<Record<string, unknown>>(params)\n const key = `${method.replace(/\\./g, '_')}_response`\n const data = response[key] as Record<string, unknown> | undefined\n\n return ok({\n provider: 'alipay',\n tradeType: input.tradeType,\n clientParams: data ?? {},\n prepayId: data?.trade_no as string | undefined,\n })\n }\n catch (cause) {\n return err(\n HaiPaymentError.CREATE_ORDER_FAILED,\n paymentM('payment_createOrderFailed'),\n cause,\n )\n }\n },\n\n async handleNotify(request: PaymentNotifyRequest): Promise<HaiResult<PaymentNotifyResult>> {\n try {\n // 解析 form-urlencoded body\n const params: AlipayNotifyParams = {} as AlipayNotifyParams\n const pairs = request.body.split('&')\n for (const pair of pairs) {\n const [key, ...rest] = pair.split('=')\n params[decodeURIComponent(key)] = decodeURIComponent(rest.join('='))\n }\n\n // 验签\n const valid = verifyAlipayNotify(params as Record<string, string>, config.alipayPublicKey)\n if (!valid) {\n return err(\n HaiPaymentError.NOTIFY_VERIFY_FAILED,\n paymentM('payment_notifyVerifyFailed'),\n )\n }\n\n const statusMap: Record<string, PaymentNotifyResult['status']> = {\n TRADE_SUCCESS: 'paid',\n TRADE_CLOSED: 'closed',\n TRADE_FINISHED: 'paid',\n WAIT_BUYER_PAY: 'pending',\n }\n\n return ok({\n orderNo: params.out_trade_no,\n transactionId: params.trade_no,\n amount: Math.round(Number.parseFloat(params.total_amount) * 100), // 元 → 分\n status: statusMap[params.trade_status] ?? 'pending',\n paidAt: params.gmt_payment ? new Date(params.gmt_payment) : undefined,\n // 支付宝回调原始 params 的强类型为 AlipayNotifyParams,此处统一以 Record 暴露给上层做调试/审计\n raw: params as unknown as Record<string, unknown>,\n })\n }\n catch (cause) {\n return err(\n HaiPaymentError.NOTIFY_PARSE_FAILED,\n paymentM('payment_notifyParseFailed'),\n cause,\n )\n }\n },\n\n async queryOrder(orderNo: string): Promise<HaiResult<OrderStatus>> {\n try {\n const method = 'alipay.trade.query'\n const params = {\n ...buildCommonParams(method, ''),\n biz_content: JSON.stringify({ out_trade_no: orderNo }),\n }\n\n const response = await alipayRequest<Record<string, unknown>>(params)\n const data = response.alipay_trade_query_response as Record<string, unknown> | undefined\n\n const statusMap: Record<string, OrderStatus['status']> = {\n TRADE_SUCCESS: 'paid',\n TRADE_CLOSED: 'closed',\n TRADE_FINISHED: 'paid',\n WAIT_BUYER_PAY: 'pending',\n }\n\n return ok({\n orderNo,\n transactionId: data?.trade_no as string | undefined,\n status: statusMap[data?.trade_status as string] ?? 'pending',\n amount: Math.round(Number.parseFloat(data?.total_amount as string ?? '0') * 100),\n paidAt: data?.send_pay_date ? new Date(data.send_pay_date as string) : undefined,\n })\n }\n catch (cause) {\n return err(\n HaiPaymentError.QUERY_ORDER_FAILED,\n paymentM('payment_queryOrderFailed'),\n cause,\n )\n }\n },\n\n async refund(input: RefundInput): Promise<HaiResult<RefundResult>> {\n try {\n const method = 'alipay.trade.refund'\n const params = {\n ...buildCommonParams(method, ''),\n biz_content: JSON.stringify({\n out_trade_no: input.orderNo,\n out_request_no: input.refundNo,\n refund_amount: (input.amount / 100).toFixed(2),\n refund_reason: input.reason,\n }),\n }\n\n const response = await alipayRequest<Record<string, unknown>>(params)\n const data = response.alipay_trade_refund_response as Record<string, unknown> | undefined\n\n return ok({\n refundNo: input.refundNo,\n refundId: data?.trade_no as string ?? '',\n status: data?.fund_change === 'Y' ? 'success' : 'processing',\n })\n }\n catch (cause) {\n return err(\n HaiPaymentError.REFUND_FAILED,\n paymentM('payment_refundFailed'),\n cause,\n )\n }\n },\n\n async closeOrder(orderNo: string): Promise<HaiResult<void>> {\n try {\n const method = 'alipay.trade.close'\n const params = {\n ...buildCommonParams(method, ''),\n biz_content: JSON.stringify({ out_trade_no: orderNo }),\n }\n\n await alipayRequest(params)\n return ok(undefined)\n }\n catch (cause) {\n return err(\n HaiPaymentError.CLOSE_ORDER_FAILED,\n paymentM('payment_closeOrderFailed'),\n cause,\n )\n }\n },\n }\n}\n","/**\n * @h-ai/payment — Stripe Provider\n *\n * 实现 PaymentProvider 接口,对接 Stripe API。\n * 使用 Stripe Checkout Session 模式。\n * @module stripe-provider\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { StripeConfig } from '../../payment-config.js'\nimport type { CreateOrderInput, OrderStatus, PaymentNotifyRequest, PaymentNotifyResult, PaymentOrder, PaymentProvider, RefundInput, RefundResult } from '../../payment-types.js'\nimport { createHmac } from 'node:crypto'\nimport { core, err, ok } from '@h-ai/core'\nimport { paymentM } from '../../payment-i18n.js'\nimport {\n\n HaiPaymentError,\n\n} from '../../payment-types.js'\n\n/** Stripe API 基地址 */\nconst STRIPE_API_BASE = 'https://api.stripe.com/v1'\n\n/**\n * 创建 Stripe Provider\n *\n * @param config - Stripe 配置\n * @returns PaymentProvider 实例\n */\nexport function createStripeProvider(config: StripeConfig): PaymentProvider {\n /** Stripe API 请求 */\n async function stripeRequest<T>(method: string, path: string, body?: Record<string, string>): Promise<T> {\n const response = await fetch(`${STRIPE_API_BASE}${path}`, {\n method,\n headers: {\n 'Authorization': `Bearer ${config.secretKey}`,\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: body\n ? Object.entries(body).map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`).join('&')\n : undefined,\n })\n\n if (!response.ok) {\n const errorText = await response.text()\n throw new Error(`Stripe API ${method} ${path} failed: ${response.status} ${errorText}`)\n }\n\n return response.json() as T\n }\n\n /** Stripe Webhook 签名容忍时间窗口(秒) */\n const TIMESTAMP_TOLERANCE = 300\n\n /** 验证 Stripe Webhook 签名 */\n function verifyWebhookSignature(payload: string, signature: string): boolean {\n const parts = signature.split(',')\n const timestamp = parts.find(p => p.startsWith('t='))?.slice(2) ?? ''\n const v1 = parts.find(p => p.startsWith('v1='))?.slice(3) ?? ''\n\n // 时间戳重放保护\n const ts = Number.parseInt(timestamp, 10)\n if (Number.isNaN(ts) || Math.abs(Math.floor(Date.now() / 1000) - ts) > TIMESTAMP_TOLERANCE) {\n return false\n }\n\n const signedPayload = `${timestamp}.${payload}`\n const expected = createHmac('sha256', config.webhookSecret)\n .update(signedPayload)\n .digest('hex')\n\n try {\n return core.string.constantTimeEqual(v1, expected)\n }\n catch {\n return false\n }\n }\n\n return {\n name: 'stripe',\n\n async createOrder(input: CreateOrderInput): Promise<HaiResult<PaymentOrder>> {\n try {\n // 使用 Stripe Checkout Session\n const params: Record<string, string> = {\n 'mode': 'payment',\n 'line_items[0][price_data][currency]': input.currency?.toLowerCase() ?? 'usd',\n 'line_items[0][price_data][product_data][name]': input.description,\n 'line_items[0][price_data][unit_amount]': input.amount.toString(),\n 'line_items[0][quantity]': '1',\n }\n\n // metadata 传递订单号\n params['metadata[orderNo]'] = input.orderNo\n if (input.metadata) {\n for (const [k, v] of Object.entries(input.metadata)) {\n params[`metadata[${k}]`] = v\n }\n }\n\n const session = await stripeRequest<{\n id: string\n url: string\n payment_intent: string\n }>('POST', '/checkout/sessions', params)\n\n return ok({\n provider: 'stripe',\n tradeType: input.tradeType,\n clientParams: {\n sessionId: session.id,\n checkoutUrl: session.url,\n },\n })\n }\n catch (cause) {\n return err(\n HaiPaymentError.CREATE_ORDER_FAILED,\n paymentM('payment_createOrderFailed'),\n cause,\n )\n }\n },\n\n async handleNotify(request: PaymentNotifyRequest): Promise<HaiResult<PaymentNotifyResult>> {\n try {\n const signature = request.headers['stripe-signature'] ?? ''\n\n // 验签\n const valid = verifyWebhookSignature(request.body, signature)\n if (!valid) {\n return err(\n HaiPaymentError.NOTIFY_VERIFY_FAILED,\n paymentM('payment_notifyVerifyFailed'),\n )\n }\n\n const event = JSON.parse(request.body) as {\n type: string\n data: {\n object: {\n id: string\n metadata?: Record<string, string>\n amount_total?: number\n payment_status?: string\n }\n }\n }\n\n const obj = event.data.object\n const orderNo = obj.metadata?.orderNo ?? ''\n\n const statusMap: Record<string, PaymentNotifyResult['status']> = {\n 'checkout.session.completed': 'paid',\n 'payment_intent.payment_failed': 'failed',\n }\n\n return ok({\n orderNo,\n transactionId: obj.id,\n amount: obj.amount_total ?? 0,\n status: statusMap[event.type] ?? 'pending',\n paidAt: new Date(),\n // Stripe SDK 的 Event 是强类型对象,此处统一以 Record 暴露给上层做调试/审计\n raw: event as unknown as Record<string, unknown>,\n })\n }\n catch (cause) {\n return err(\n HaiPaymentError.NOTIFY_PARSE_FAILED,\n paymentM('payment_notifyParseFailed'),\n cause,\n )\n }\n },\n\n async queryOrder(orderNo: string): Promise<HaiResult<OrderStatus>> {\n try {\n // 搜索 checkout sessions by metadata\n const sessions = await stripeRequest<{\n data: Array<{\n id: string\n payment_status: string\n amount_total: number\n }>\n }>('GET', `/checkout/sessions?limit=1&metadata[orderNo]=${encodeURIComponent(orderNo)}`)\n\n const session = sessions.data[0]\n if (!session) {\n return ok({\n orderNo,\n status: 'pending',\n amount: 0,\n })\n }\n\n const statusMap: Record<string, OrderStatus['status']> = {\n paid: 'paid',\n unpaid: 'pending',\n no_payment_required: 'paid',\n }\n\n return ok({\n orderNo,\n transactionId: session.id,\n status: statusMap[session.payment_status] ?? 'pending',\n amount: session.amount_total,\n })\n }\n catch (cause) {\n return err(\n HaiPaymentError.QUERY_ORDER_FAILED,\n paymentM('payment_queryOrderFailed'),\n cause,\n )\n }\n },\n\n async refund(input: RefundInput): Promise<HaiResult<RefundResult>> {\n try {\n // Stripe 退款需要 payment_intent ID,这里简化为根据 orderNo 查询\n const sessions = await stripeRequest<{\n data: Array<{ payment_intent: string }>\n }>('GET', `/checkout/sessions?limit=1&metadata[orderNo]=${encodeURIComponent(input.orderNo)}`)\n\n const paymentIntent = sessions.data[0]?.payment_intent\n if (!paymentIntent) {\n return err(\n HaiPaymentError.REFUND_FAILED,\n paymentM('payment_refundFailed'),\n )\n }\n\n const refund = await stripeRequest<{\n id: string\n status: string\n }>('POST', '/refunds', {\n payment_intent: paymentIntent,\n amount: input.amount.toString(),\n reason: input.reason ?? 'requested_by_customer',\n })\n\n return ok({\n refundNo: input.refundNo,\n refundId: refund.id,\n status: refund.status === 'succeeded' ? 'success' : 'processing',\n })\n }\n catch (cause) {\n return err(\n HaiPaymentError.REFUND_FAILED,\n paymentM('payment_refundFailed'),\n cause,\n )\n }\n },\n\n async closeOrder(_orderNo: string): Promise<HaiResult<void>> {\n // Stripe Checkout Sessions 会自动过期,无需主动关闭\n return ok(undefined)\n },\n }\n}\n","/**\n * @h-ai/payment — 微信支付签名\n *\n * 微信支付 API v3 签名生成与验签工具。\n * @module wechat-pay-sign\n */\n\nimport { Buffer } from 'node:buffer'\nimport { createDecipheriv, createSign, createVerify, randomBytes } from 'node:crypto'\n\n/**\n * 生成随机字符串\n *\n * @param length - 字符串长度(默认 32)\n */\nexport function generateNonce(length = 32): string {\n return randomBytes(length).toString('hex').slice(0, length)\n}\n\n/**\n * 获取当前时间戳(秒)\n */\nexport function getTimestamp(): string {\n return Math.floor(Date.now() / 1000).toString()\n}\n\n/**\n * 微信 API v3 请求签名\n *\n * @param method - HTTP 方法\n * @param url - 请求路径(不含域名)\n * @param timestamp - 时间戳\n * @param nonce - 随机串\n * @param body - 请求体(空则为空字符串)\n * @param privateKey - 商户私钥 PEM\n * @returns SHA256-RSA2048 签名(Base64)\n */\nexport function signRequest(\n method: string,\n url: string,\n timestamp: string,\n nonce: string,\n body: string,\n privateKey: string,\n): string {\n const message = `${method}\\n${url}\\n${timestamp}\\n${nonce}\\n${body}\\n`\n const sign = createSign('RSA-SHA256')\n sign.update(message)\n return sign.sign(privateKey, 'base64')\n}\n\n/**\n * 微信 JSAPI 支付签名\n *\n * @param appId - 应用 ID\n * @param timestamp - 时间戳\n * @param nonce - 随机串\n * @param prepayId - 预支付 ID\n * @param privateKey - 商户私钥 PEM\n * @returns 签名\n */\nexport function signJsapi(\n appId: string,\n timestamp: string,\n nonce: string,\n prepayId: string,\n privateKey: string,\n): string {\n const message = `${appId}\\n${timestamp}\\n${nonce}\\nprepay_id=${prepayId}\\n`\n const sign = createSign('RSA-SHA256')\n sign.update(message)\n return sign.sign(privateKey, 'base64')\n}\n\n/**\n * 验证微信支付回调签名\n *\n * @param timestamp - 回调 header 中的时间戳\n * @param nonce - 回调 header 中的随机串\n * @param body - 回调原始 body\n * @param signature - 回调签名\n * @param platformCert - 微信支付平台证书 PEM\n * @returns 是否验签通过\n */\nexport function verifyNotifySignature(\n timestamp: string,\n nonce: string,\n body: string,\n signature: string,\n platformCert: string,\n): boolean {\n const message = `${timestamp}\\n${nonce}\\n${body}\\n`\n const verify = createVerify('RSA-SHA256')\n verify.update(message)\n return verify.verify(platformCert, signature, 'base64')\n}\n\n/**\n * AES-256-GCM 解密(微信支付回调资源解密)\n *\n * @param ciphertext - 密文(Base64)\n * @param nonce - 随机串\n * @param associatedData - 附加数据\n * @param apiV3Key - API v3 密钥\n * @returns 解密后的 JSON 字符串\n */\nexport function decryptResource(\n ciphertext: string,\n nonce: string,\n associatedData: string,\n apiV3Key: string,\n): string {\n const buf = Buffer.from(ciphertext, 'base64')\n const authTag = buf.subarray(buf.length - 16)\n const data = buf.subarray(0, buf.length - 16)\n\n const decipher = createDecipheriv('aes-256-gcm', apiV3Key, nonce)\n decipher.setAuthTag(authTag)\n decipher.setAAD(Buffer.from(associatedData))\n\n const decrypted = Buffer.concat([decipher.update(data), decipher.final()])\n return decrypted.toString('utf-8')\n}\n","/**\n * @h-ai/payment — 微信支付 Provider\n *\n * 实现 PaymentProvider 接口,对接微信支付 API v3。\n * @module wechat-pay-provider\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { WechatPayConfig } from '../../payment-config.js'\nimport type { CreateOrderInput, OrderStatus, PaymentNotifyRequest, PaymentNotifyResult, PaymentOrder, PaymentProvider, RefundInput, RefundResult } from '../../payment-types.js'\nimport type { WechatNotifyResource, WechatOrderRequest } from './wechat-pay-types.js'\nimport { err, ok } from '@h-ai/core'\nimport { paymentM } from '../../payment-i18n.js'\nimport {\n\n HaiPaymentError,\n\n} from '../../payment-types.js'\nimport {\n decryptResource,\n generateNonce,\n getTimestamp,\n signJsapi,\n signRequest,\n verifyNotifySignature,\n} from './wechat-pay-sign.js'\n\n/** 微信支付 API 基地址 */\nconst WECHAT_API_BASE = 'https://api.mch.weixin.qq.com'\n\n/**\n * 创建微信支付 Provider\n *\n * @param config - 微信支付配置\n * @returns PaymentProvider 实例\n *\n * @example\n * ```ts\n * const wechatPay = createWechatPayProvider({\n * mchId: 'your-mch-id',\n * apiV3Key: 'your-api-v3-key',\n * serialNo: 'your-serial-no',\n * privateKey: fs.readFileSync('apiclient_key.pem', 'utf-8'),\n * appId: 'your-app-id',\n * })\n *\n * const result = await wechatPay.createOrder({\n * orderNo: 'ORD20240101001',\n * amount: 100, // 1 元\n * description: '测试商品',\n * tradeType: 'jsapi',\n * userId: 'openid-xxx',\n * notifyUrl: 'https://api.example.com/payment/notify/wechat',\n * })\n * ```\n */\nexport function createWechatPayProvider(config: WechatPayConfig): PaymentProvider {\n /**\n * 发送微信支付 API 请求\n */\n async function wechatRequest<T>(method: string, path: string, body?: unknown): Promise<T> {\n const timestamp = getTimestamp()\n const nonce = generateNonce()\n const bodyStr = body ? JSON.stringify(body) : ''\n\n const signature = signRequest(method, path, timestamp, nonce, bodyStr, config.privateKey)\n\n const authorization = `WECHATPAY2-SHA256-RSA2048 mchid=\"${config.mchId}\",nonce_str=\"${nonce}\",timestamp=\"${timestamp}\",serial_no=\"${config.serialNo}\",signature=\"${signature}\"`\n\n const response = await fetch(`${WECHAT_API_BASE}${path}`, {\n method,\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': authorization,\n 'Accept': 'application/json',\n },\n body: bodyStr || undefined,\n })\n\n if (!response.ok) {\n const errorText = await response.text()\n throw new Error(`Wechat API ${method} ${path} failed: ${response.status} ${errorText}`)\n }\n\n return response.json() as T\n }\n\n /** 根据 tradeType 映射到微信 API 路径 */\n function getOrderPath(tradeType: string): string {\n const map: Record<string, string> = {\n jsapi: '/v3/pay/transactions/jsapi',\n h5: '/v3/pay/transactions/h5',\n app: '/v3/pay/transactions/app',\n native: '/v3/pay/transactions/native',\n }\n return map[tradeType] ?? '/v3/pay/transactions/jsapi'\n }\n\n return {\n name: 'wechat',\n\n async createOrder(input: CreateOrderInput): Promise<HaiResult<PaymentOrder>> {\n try {\n const requestBody: WechatOrderRequest = {\n appid: config.appId,\n mchid: config.mchId,\n description: input.description,\n out_trade_no: input.orderNo,\n notify_url: input.notifyUrl,\n amount: {\n total: input.amount,\n currency: input.currency ?? 'CNY',\n },\n }\n\n // JSAPI 需要 payer.openid\n if (input.tradeType === 'jsapi' && input.userId) {\n requestBody.payer = { openid: input.userId }\n }\n\n if (input.metadata) {\n requestBody.attach = JSON.stringify(input.metadata)\n }\n\n const path = getOrderPath(input.tradeType)\n const response = await wechatRequest<{ prepay_id?: string, h5_url?: string, code_url?: string }>('POST', path, requestBody)\n\n // 构建客户端调起参数\n let clientParams: Record<string, unknown> = {}\n\n if (input.tradeType === 'jsapi') {\n const timestamp = getTimestamp()\n const nonce = generateNonce()\n const paySign = signJsapi(config.appId, timestamp, nonce, response.prepay_id!, config.privateKey)\n\n clientParams = {\n appId: config.appId,\n timeStamp: timestamp,\n nonceStr: nonce,\n package: `prepay_id=${response.prepay_id}`,\n signType: 'RSA',\n paySign,\n }\n }\n else if (input.tradeType === 'h5') {\n clientParams = { h5Url: response.h5_url }\n }\n else if (input.tradeType === 'native') {\n clientParams = { codeUrl: response.code_url }\n }\n\n return ok({\n provider: 'wechat',\n tradeType: input.tradeType,\n clientParams,\n prepayId: response.prepay_id,\n })\n }\n catch (cause) {\n return err(\n HaiPaymentError.CREATE_ORDER_FAILED,\n paymentM('payment_createOrderFailed'),\n cause,\n )\n }\n },\n\n async handleNotify(request: PaymentNotifyRequest): Promise<HaiResult<PaymentNotifyResult>> {\n try {\n const timestamp = request.headers['wechatpay-timestamp'] ?? ''\n const nonce = request.headers['wechatpay-nonce'] ?? ''\n const signature = request.headers['wechatpay-signature'] ?? ''\n\n // 验签(必须提供平台证书)\n if (!config.platformCert) {\n return err(\n HaiPaymentError.NOTIFY_VERIFY_FAILED,\n paymentM('payment_notifyVerifyFailed'),\n )\n }\n const valid = verifyNotifySignature(timestamp, nonce, request.body, signature, config.platformCert)\n if (!valid) {\n return err(\n HaiPaymentError.NOTIFY_VERIFY_FAILED,\n paymentM('payment_notifyVerifyFailed'),\n )\n }\n\n // 解密资源\n const body = JSON.parse(request.body) as {\n resource: { ciphertext: string, nonce: string, associated_data: string }\n }\n const decrypted = decryptResource(\n body.resource.ciphertext,\n body.resource.nonce,\n body.resource.associated_data,\n config.apiV3Key,\n )\n const resource = JSON.parse(decrypted) as WechatNotifyResource\n\n return ok({\n orderNo: resource.out_trade_no,\n transactionId: resource.transaction_id,\n amount: resource.amount.total,\n status: resource.trade_state === 'SUCCESS' ? 'paid' : 'failed',\n paidAt: resource.success_time ? new Date(resource.success_time) : undefined,\n // 微信回调原始 payload 的强类型为 WechatNotifyResource,此处统一以 Record 暴露给上层做调试/审计\n raw: resource as unknown as Record<string, unknown>,\n })\n }\n catch (cause) {\n return err(\n HaiPaymentError.NOTIFY_PARSE_FAILED,\n paymentM('payment_notifyParseFailed'),\n cause,\n )\n }\n },\n\n async queryOrder(orderNo: string): Promise<HaiResult<OrderStatus>> {\n try {\n const path = `/v3/pay/transactions/out-trade-no/${encodeURIComponent(orderNo)}?mchid=${encodeURIComponent(config.mchId)}`\n const response = await wechatRequest<{\n out_trade_no: string\n transaction_id: string\n trade_state: string\n amount: { total: number }\n success_time?: string\n }>('GET', path)\n\n const statusMap: Record<string, OrderStatus['status']> = {\n SUCCESS: 'paid',\n CLOSED: 'closed',\n REFUND: 'refunded',\n NOTPAY: 'pending',\n PAYERROR: 'failed',\n }\n\n return ok({\n orderNo: response.out_trade_no,\n transactionId: response.transaction_id,\n status: statusMap[response.trade_state] ?? 'pending',\n amount: response.amount.total,\n paidAt: response.success_time ? new Date(response.success_time) : undefined,\n })\n }\n catch (cause) {\n return err(\n HaiPaymentError.QUERY_ORDER_FAILED,\n paymentM('payment_queryOrderFailed'),\n cause,\n )\n }\n },\n\n async refund(input: RefundInput): Promise<HaiResult<RefundResult>> {\n try {\n const response = await wechatRequest<{\n refund_id: string\n status: string\n }>('POST', '/v3/refund/domestic/refunds', {\n out_trade_no: input.orderNo,\n out_refund_no: input.refundNo,\n amount: {\n refund: input.amount,\n total: input.totalAmount ?? input.amount,\n currency: 'CNY',\n },\n reason: input.reason,\n })\n\n const statusMap: Record<string, RefundResult['status']> = {\n SUCCESS: 'success',\n PROCESSING: 'processing',\n ABNORMAL: 'failed',\n }\n\n return ok({\n refundNo: input.refundNo,\n refundId: response.refund_id,\n status: statusMap[response.status] ?? 'processing',\n })\n }\n catch (cause) {\n return err(\n HaiPaymentError.REFUND_FAILED,\n paymentM('payment_refundFailed'),\n cause,\n )\n }\n },\n\n async closeOrder(orderNo: string): Promise<HaiResult<void>> {\n try {\n await wechatRequest('POST', `/v3/pay/transactions/out-trade-no/${encodeURIComponent(orderNo)}/close`, {\n mchid: config.mchId,\n })\n return ok(undefined)\n }\n catch (cause) {\n return err(\n HaiPaymentError.CLOSE_ORDER_FAILED,\n paymentM('payment_closeOrderFailed'),\n cause,\n )\n }\n },\n }\n}\n","/**\n * @h-ai/payment — 模块入口(生命周期管理)\n *\n * 提供支付模块的初始化、Provider 注册与统一支付操作 API。\n * `payment.init(config)` 负责根据配置自动注册可用的 Provider。\n *\n * @module payment-main\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { PaymentConfig, PaymentConfigInput } from './payment-config.js'\nimport type {\n OrderStatus,\n PaymentFunctions,\n PaymentNotifyResult,\n PaymentOrder,\n RefundResult,\n} from './payment-types.js'\nimport { core, err, ok } from '@h-ai/core'\nimport { PaymentConfigSchema } from './payment-config.js'\nimport {\n clearProviders,\n closeOrder,\n createOrder,\n getProvider,\n handleNotify,\n queryOrder,\n refund,\n registerProvider,\n} from './payment-functions.js'\nimport { paymentM } from './payment-i18n.js'\nimport { HaiPaymentError } from './payment-types.js'\nimport { createAlipayProvider } from './providers/alipay/alipay-provider.js'\nimport { createStripeProvider } from './providers/stripe/stripe-provider.js'\nimport { createWechatPayProvider } from './providers/wechat/wechat-pay-provider.js'\n\nconst logger = core.logger.child({ module: 'payment', scope: 'main' })\n\n// ─── 内部状态 ───\n\nlet currentConfig: PaymentConfig | null = null\nlet initInProgress = false\n\n// ─── 未初始化占位 ───\n\nconst notInitialized = core.module.createNotInitializedKit(\n HaiPaymentError.NOT_INITIALIZED,\n () => paymentM('payment_notInitialized'),\n)\n\n// ─── 服务对象 ───\n\n/**\n * 支付模块服务对象\n *\n * @example\n * ```ts\n * import { payment } from '@h-ai/payment'\n *\n * await payment.init({\n * wechat: { mchId: '...', apiV3Key: '...', ... },\n * alipay: { appId: '...', privateKey: '...' , ... },\n * })\n *\n * const result = await payment.createOrder('wechat', {\n * orderNo: 'ORD001',\n * amount: 100,\n * description: '测试商品',\n * tradeType: 'jsapi',\n * userId: 'openid-xxx',\n * notifyUrl: 'https://api.example.com/payment/notify/wechat',\n * })\n * ```\n */\nexport const payment: PaymentFunctions = {\n /**\n * 初始化支付模块\n *\n * 根据提供的配置自动注册对应的 Provider。\n *\n * @param config - 支付配置\n */\n async init(config: PaymentConfigInput): Promise<HaiResult<void>> {\n if (initInProgress) {\n logger.warn('Payment module init already in progress, skipping')\n return err(\n HaiPaymentError.CONFIG_ERROR,\n paymentM('payment_configError', { params: { error: 'init already in progress' } }),\n )\n }\n\n initInProgress = true\n\n try {\n if (currentConfig !== null) {\n logger.warn('Payment module is already initialized, reinitializing')\n await payment.close()\n }\n\n logger.info('Initializing payment module')\n const parseResult = PaymentConfigSchema.safeParse(config)\n if (!parseResult.success) {\n logger.error('Payment config validation failed', { error: parseResult.error.message })\n return err(\n HaiPaymentError.CONFIG_ERROR,\n paymentM('payment_configError', { params: { error: parseResult.error.message } }),\n parseResult.error,\n )\n }\n const parsed = parseResult.data\n\n // 清除旧注册\n clearProviders()\n\n // 按配置自动注册 Provider\n if (parsed.wechat) {\n registerProvider(createWechatPayProvider(parsed.wechat))\n }\n if (parsed.alipay) {\n registerProvider(createAlipayProvider(parsed.alipay))\n }\n if (parsed.stripe) {\n registerProvider(createStripeProvider(parsed.stripe))\n }\n\n currentConfig = parsed\n logger.info('Payment module initialized', {\n providers: [\n parsed.wechat ? 'wechat' : null,\n parsed.alipay ? 'alipay' : null,\n parsed.stripe ? 'stripe' : null,\n ].filter(Boolean),\n })\n return ok(undefined)\n }\n catch (error) {\n logger.error('Payment module initialization failed', { error })\n return err(\n HaiPaymentError.CONFIG_ERROR,\n paymentM('payment_initFailed', {\n params: { error: error instanceof Error ? error.message : String(error) },\n }),\n error,\n )\n }\n finally {\n initInProgress = false\n }\n },\n\n /**\n * 关闭模块、清除所有 Provider\n */\n async close(): Promise<void> {\n if (!currentConfig) {\n logger.info('Payment module already closed, skipping')\n return\n }\n logger.info('Closing payment module')\n clearProviders()\n currentConfig = null\n logger.info('Payment module closed')\n },\n\n get config() { return currentConfig },\n get isInitialized() { return currentConfig !== null },\n\n /** 创建支付订单 */\n createOrder: (...args: Parameters<typeof createOrder>) =>\n currentConfig ? createOrder(...args) : Promise.resolve(notInitialized.result<PaymentOrder>()),\n\n /** 处理异步回调通知 */\n handleNotify: (...args: Parameters<typeof handleNotify>) =>\n currentConfig ? handleNotify(...args) : Promise.resolve(notInitialized.result<PaymentNotifyResult>()),\n\n /** 查询订单状态 */\n queryOrder: (...args: Parameters<typeof queryOrder>) =>\n currentConfig ? queryOrder(...args) : Promise.resolve(notInitialized.result<OrderStatus>()),\n\n /** 发起退款 */\n refund: (...args: Parameters<typeof refund>) =>\n currentConfig ? refund(...args) : Promise.resolve(notInitialized.result<RefundResult>()),\n\n /** 关闭订单 */\n closeOrder: (...args: Parameters<typeof closeOrder>) =>\n currentConfig ? closeOrder(...args) : Promise.resolve(notInitialized.result<void>()),\n\n /** 获取已注册的 Provider */\n getProvider,\n\n /** 手动注册 Provider(自定义渠道) */\n registerProvider,\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/payment-config.ts","../src/payment-functions.ts","../src/providers/payment-provider-http.ts","../src/providers/alipay/alipay-sign.ts","../src/providers/alipay/alipay-types.ts","../src/providers/alipay/alipay-provider.ts","../src/providers/stripe/stripe-provider.ts","../src/providers/wechat/wechat-pay-sign.ts","../src/providers/wechat/wechat-pay-provider.ts","../src/payment-main.ts"],"names":["z","ok","err","core","refund","createSign","createVerify","logger"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * @h-ai/payment — 错误码 + 配置 Schema\n *\n * 支付模块的错误码、Zod 配置 Schema 与配置类型。\n * @module payment-config\n */\n\nimport { z } from 'zod'\nimport { paymentM } from './payment-i18n.js'\n\n// ─── 配置 Schema ───\n\n/** 微信支付配置 Schema */\nexport const WechatPayConfigSchema = z.object({\n mchId: z.string().min(1, paymentM('payment_configFieldRequired')),\n apiV3Key: z.string().min(1, paymentM('payment_configFieldRequired')),\n serialNo: z.string().min(1, paymentM('payment_configFieldRequired')),\n privateKey: z.string().min(1, paymentM('payment_configFieldRequired')),\n platformCert: z.string().optional(),\n appId: z.string().min(1, paymentM('payment_configFieldRequired')),\n})\n\n/** 支付宝配置 Schema */\nexport const AlipayConfigSchema = z.object({\n appId: z.string().min(1, paymentM('payment_configFieldRequired')),\n privateKey: z.string().min(1, paymentM('payment_configFieldRequired')),\n alipayPublicKey: z.string().min(1, paymentM('payment_configFieldRequired')),\n signType: z.enum(['RSA2', 'RSA']).default('RSA2'),\n sandbox: z.boolean().default(false),\n})\n\n/** Stripe 配置 Schema */\nexport const StripeConfigSchema = z.object({\n secretKey: z.string().min(1, paymentM('payment_configFieldRequired')),\n webhookSecret: z.string().min(1, paymentM('payment_configFieldRequired')),\n webhookToleranceSeconds: z.number().int().positive().default(300),\n})\n\n/** 支付模块配置 Schema */\nexport const PaymentConfigSchema = z.object({\n wechat: WechatPayConfigSchema.optional(),\n alipay: AlipayConfigSchema.optional(),\n stripe: StripeConfigSchema.optional(),\n})\n\nexport type PaymentConfig = z.infer<typeof PaymentConfigSchema>\nexport type PaymentConfigInput = z.input<typeof PaymentConfigSchema>\nexport type WechatPayConfig = z.infer<typeof WechatPayConfigSchema>\nexport type AlipayConfig = z.infer<typeof AlipayConfigSchema>\nexport type StripeConfig = z.infer<typeof StripeConfigSchema>\n","/**\n * @h-ai/payment — 业务逻辑编排\n *\n * 统一路由到对应 Provider 的支付操作。\n * @module payment-functions\n */\n\nimport type { CreateAuditLogInput } from '@h-ai/audit'\nimport type { HaiResult } from '@h-ai/core'\nimport type { CreateOrderInput, OrderStatus, PaymentNotifyRequest, PaymentNotifyResult, PaymentOrder, PaymentProvider, RefundInput, RefundResult } from './payment-types.js'\nimport { audit } from '@h-ai/audit'\nimport { core, err, ok } from '@h-ai/core'\nimport { paymentM } from './payment-i18n.js'\nimport { HaiPaymentError } from './payment-types.js'\n\nconst logger = core.logger.child({ module: 'payment', scope: 'functions' })\n\n/** Provider 注册表 */\nconst providers = new Map<string, PaymentProvider>()\n\n/**\n * 写审计日志(失败仅 warn,不影响支付操作)\n */\nasync function auditLog(input: CreateAuditLogInput): Promise<void> {\n const result = await audit.log(input)\n if (!result.success) {\n logger.warn('Failed to write payment audit log', { action: input.action, error: result.error.message })\n }\n}\n\nfunction isValidAmount(amount: number): boolean {\n return Number.isSafeInteger(amount) && amount > 0\n}\n\nfunction validateCreateOrderInput(input: CreateOrderInput): HaiResult<void> {\n if (!isValidAmount(input.amount)) {\n return err(\n HaiPaymentError.INVALID_AMOUNT,\n paymentM('payment_invalidAmount'),\n )\n }\n\n return ok(undefined)\n}\n\nfunction validateRefundInput(input: RefundInput): HaiResult<void> {\n if (!isValidAmount(input.amount)) {\n return err(\n HaiPaymentError.INVALID_AMOUNT,\n paymentM('payment_invalidAmount'),\n )\n }\n\n if (input.totalAmount !== undefined) {\n if (!isValidAmount(input.totalAmount) || input.totalAmount < input.amount) {\n return err(\n HaiPaymentError.INVALID_AMOUNT,\n paymentM('payment_invalidAmount'),\n )\n }\n }\n\n return ok(undefined)\n}\n\n/**\n * 注册支付 Provider\n *\n * @param provider - PaymentProvider 实例\n */\nexport function registerProvider(provider: PaymentProvider): void {\n providers.set(provider.name, provider)\n}\n\n/**\n * 获取已注册的 Provider\n *\n * @param name - Provider 名称\n * @returns Provider 实例(不存在返回 undefined)\n */\nexport function getProvider(name: string): PaymentProvider | undefined {\n return providers.get(name)\n}\n\n/**\n * 获取 Provider(不存在则返回 err)\n */\nfunction requireProvider(name: string): HaiResult<PaymentProvider> {\n const provider = providers.get(name)\n if (!provider) {\n return err(\n HaiPaymentError.PROVIDER_NOT_FOUND,\n paymentM('payment_providerNotFound'),\n )\n }\n return ok(provider)\n}\n\n/**\n * 通过指定 Provider 创建订单\n *\n * @param providerName - Provider 名称('wechat' | 'alipay' | 'stripe')\n * @param input - 创建订单入参\n */\nexport async function createOrder(\n providerName: string,\n input: CreateOrderInput,\n): Promise<HaiResult<PaymentOrder>> {\n const result = requireProvider(providerName)\n if (!result.success)\n return result\n\n const validateResult = validateCreateOrderInput(input)\n if (!validateResult.success)\n return validateResult as HaiResult<PaymentOrder>\n\n const orderResult = await result.data.createOrder(input)\n if (orderResult.success) {\n await auditLog({\n action: 'create_order',\n resource: 'payment',\n resourceId: input.orderNo,\n details: { provider: providerName, amount: input.amount, tradeType: input.tradeType },\n })\n }\n return orderResult\n}\n\n/**\n * 处理支付回调通知\n *\n * @param providerName - Provider 名称\n * @param request - 原始 HTTP 请求数据\n */\nexport async function handleNotify(\n providerName: string,\n request: PaymentNotifyRequest,\n): Promise<HaiResult<PaymentNotifyResult>> {\n const result = requireProvider(providerName)\n if (!result.success)\n return result\n const notifyResult = await result.data.handleNotify(request)\n if (notifyResult.success) {\n await auditLog({\n action: 'payment_notify',\n resource: 'payment',\n resourceId: notifyResult.data.orderNo,\n details: { provider: providerName, transactionId: notifyResult.data.transactionId, status: notifyResult.data.status, amount: notifyResult.data.amount },\n })\n }\n return notifyResult\n}\n\n/**\n * 查询订单状态\n *\n * @param providerName - Provider 名称\n * @param orderNo - 商户订单号\n */\nexport async function queryOrder(\n providerName: string,\n orderNo: string,\n): Promise<HaiResult<OrderStatus>> {\n const result = requireProvider(providerName)\n if (!result.success)\n return result\n return result.data.queryOrder(orderNo)\n}\n\n/**\n * 发起退款\n *\n * @param providerName - Provider 名称\n * @param input - 退款入参\n */\nexport async function refund(\n providerName: string,\n input: RefundInput,\n): Promise<HaiResult<RefundResult>> {\n const result = requireProvider(providerName)\n if (!result.success)\n return result\n\n const validateResult = validateRefundInput(input)\n if (!validateResult.success)\n return validateResult as HaiResult<RefundResult>\n\n const refundResult = await result.data.refund(input)\n if (refundResult.success) {\n await auditLog({\n action: 'refund',\n resource: 'payment',\n resourceId: input.orderNo,\n details: { provider: providerName, refundNo: input.refundNo, amount: input.amount },\n })\n }\n return refundResult\n}\n\n/**\n * 关闭订单\n *\n * @param providerName - Provider 名称\n * @param orderNo - 商户订单号\n */\nexport async function closeOrder(\n providerName: string,\n orderNo: string,\n): Promise<HaiResult<void>> {\n const result = requireProvider(providerName)\n if (!result.success)\n return result\n const closeResult = await result.data.closeOrder(orderNo)\n if (closeResult.success) {\n await auditLog({\n action: 'close_order',\n resource: 'payment',\n resourceId: orderNo,\n details: { provider: providerName },\n })\n }\n return closeResult\n}\n\n/**\n * 清空所有已注册 Provider(测试用)\n */\nexport function clearProviders(): void {\n providers.clear()\n}\n","/**\n * @h-ai/payment — Provider HTTP 辅助\n *\n * 为各支付 Provider 的 fetch 请求统一附加超时控制。\n * @module payment-provider-http\n */\n\nconst DEFAULT_PROVIDER_TIMEOUT_MS = 15_000\n\nexport async function fetchWithTimeout(input: string, init: RequestInit, timeoutMs = DEFAULT_PROVIDER_TIMEOUT_MS): Promise<Response> {\n return fetch(input, {\n ...init,\n signal: init.signal\n ? AbortSignal.any([init.signal, AbortSignal.timeout(timeoutMs)])\n : AbortSignal.timeout(timeoutMs),\n })\n}\n","/**\n * @h-ai/payment — 支付宝签名\n *\n * 支付宝 RSA2/RSA 签名与验签工具。\n * @module alipay-sign\n */\n\nimport { createSign, createVerify } from 'node:crypto'\n\n/**\n * 支付宝参数签名\n *\n * @param params - 待签名参数(已排除 sign)\n * @param privateKey - 应用私钥 PEM\n * @param signType - 签名类型(默认 RSA2)\n * @returns Base64 编码的签名\n */\nexport function signAlipayParams(\n params: Record<string, string>,\n privateKey: string,\n signType: 'RSA2' | 'RSA' = 'RSA2',\n): string {\n // 按 key 字典排序,拼接为 query string\n const sorted = Object.keys(params)\n .filter(k => params[k] !== undefined && params[k] !== '')\n .sort()\n .map(k => `${k}=${params[k]}`)\n .join('&')\n\n const algorithm = signType === 'RSA2' ? 'RSA-SHA256' : 'RSA-SHA1'\n const sign = createSign(algorithm)\n sign.update(sorted)\n return sign.sign(privateKey, 'base64')\n}\n\n/**\n * 验证支付宝回调签名\n *\n * @param params - 回调参数(含 sign 和 sign_type)\n * @param alipayPublicKey - 支付宝公钥 PEM\n * @returns 验签是否通过\n */\nexport function verifyAlipayNotify(\n params: Record<string, string>,\n alipayPublicKey: string,\n): boolean {\n const sign = params.sign ?? ''\n const signType = params.sign_type ?? 'RSA2'\n\n // 排除 sign 和 sign_type,按 key 排序拼接\n const sorted = Object.keys(params)\n .filter(k => k !== 'sign' && k !== 'sign_type' && params[k] !== undefined && params[k] !== '')\n .sort()\n .map(k => `${k}=${params[k]}`)\n .join('&')\n\n const algorithm = signType === 'RSA2' ? 'RSA-SHA256' : 'RSA-SHA1'\n const verify = createVerify(algorithm)\n verify.update(sorted)\n return verify.verify(alipayPublicKey, sign, 'base64')\n}\n","/**\n * @h-ai/payment — 支付宝类型\n *\n * 支付宝 Open API 的内部请求/响应类型。\n * @module alipay-types\n */\n\nimport { z } from 'zod'\n\n/** 支付宝回调参数 */\nexport const AlipayNotifyParamsSchema = z.object({\n out_trade_no: z.string().min(1),\n trade_no: z.string().min(1),\n trade_status: z.string().min(1),\n total_amount: z.string().min(1),\n gmt_payment: z.string().optional(),\n}).catchall(z.string())\n\nexport type AlipayNotifyParams = z.infer<typeof AlipayNotifyParamsSchema>\n","/**\n * @h-ai/payment — 支付宝 Provider\n *\n * 实现 PaymentProvider 接口,对接支付宝 Open API。\n * @module alipay-provider\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { AlipayConfig } from '../../payment-config.js'\nimport type { CreateOrderInput, OrderStatus, PaymentNotifyRequest, PaymentNotifyResult, PaymentOrder, PaymentProvider, RefundInput, RefundResult } from '../../payment-types.js'\nimport type { AlipayNotifyParams } from './alipay-types.js'\nimport { err, ok } from '@h-ai/core'\nimport { paymentM } from '../../payment-i18n.js'\nimport { HaiPaymentError } from '../../payment-types.js'\nimport { fetchWithTimeout } from '../payment-provider-http.js'\nimport { signAlipayParams, verifyAlipayNotify } from './alipay-sign.js'\nimport { AlipayNotifyParamsSchema } from './alipay-types.js'\n\n/** 支付宝网关地址 */\nconst ALIPAY_GATEWAY = 'https://openapi.alipay.com/gateway.do'\nconst ALIPAY_SANDBOX_GATEWAY = 'https://openapi-sandbox.dl.alipaydev.com/gateway.do'\n\nfunction formatFenAmount(amount: number): string {\n const yuan = Math.floor(amount / 100)\n const cents = String(amount % 100).padStart(2, '0')\n return `${yuan}.${cents}`\n}\n\nfunction parseAlipayAmount(value: string): number {\n const trimmedValue = value.trim()\n if (!/^\\d+(?:\\.\\d{1,2})?$/.test(trimmedValue)) {\n throw new Error(`Invalid Alipay amount: ${value}`)\n }\n\n const [yuanPart, centsPart = ''] = trimmedValue.split('.')\n return Number.parseInt(yuanPart, 10) * 100 + Number.parseInt(centsPart.padEnd(2, '0'), 10)\n}\n\nfunction parseAlipayNotifyParams(body: string): AlipayNotifyParams {\n const parseResult = AlipayNotifyParamsSchema.safeParse(Object.fromEntries(new URLSearchParams(body).entries()))\n if (!parseResult.success) {\n throw parseResult.error\n }\n\n return parseResult.data\n}\n\n/**\n * 创建支付宝 Provider\n *\n * @param config - 支付宝配置\n * @returns PaymentProvider 实例\n */\nexport function createAlipayProvider(config: AlipayConfig): PaymentProvider {\n const gateway = config.sandbox ? ALIPAY_SANDBOX_GATEWAY : ALIPAY_GATEWAY\n const signType = config.signType ?? 'RSA2'\n\n /** 构建公共参数 */\n function buildCommonParams(method: string, notifyUrl: string): Record<string, string> {\n return {\n app_id: config.appId,\n method,\n charset: 'utf-8',\n sign_type: signType,\n timestamp: new Date().toISOString().replace('T', ' ').slice(0, 19),\n version: '1.0',\n notify_url: notifyUrl,\n }\n }\n\n /** 根据 tradeType 映射到产品码和 API */\n function getTradeConfig(tradeType: string): { method: string, productCode: string } {\n const map: Record<string, { method: string, productCode: string }> = {\n jsapi: { method: 'alipay.trade.create', productCode: 'JSAPI_PAY' },\n h5: { method: 'alipay.trade.wap.pay', productCode: 'QUICK_WAP_WAY' },\n app: { method: 'alipay.trade.app.pay', productCode: 'QUICK_MSECURITY_PAY' },\n native: { method: 'alipay.trade.precreate', productCode: 'FACE_TO_FACE_PAYMENT' },\n }\n return map[tradeType] ?? map.h5\n }\n\n /** 发送支付宝 API 请求 */\n async function alipayRequest<T>(params: Record<string, string>): Promise<T> {\n const sign = signAlipayParams(params, config.privateKey, signType)\n const allParams = { ...params, sign }\n\n const queryString = Object.entries(allParams)\n .map(([k, v]) => `${k}=${encodeURIComponent(v)}`)\n .join('&')\n\n const timedResponse = await fetchWithTimeout(`${gateway}?${queryString}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n })\n\n if (!timedResponse.ok) {\n throw new Error(`Alipay API failed: ${timedResponse.status}`)\n }\n\n return timedResponse.json() as T\n }\n\n return {\n name: 'alipay',\n\n async createOrder(input: CreateOrderInput): Promise<HaiResult<PaymentOrder>> {\n try {\n const { method, productCode } = getTradeConfig(input.tradeType)\n\n const bizContent = JSON.stringify({\n out_trade_no: input.orderNo,\n total_amount: formatFenAmount(input.amount),\n subject: input.description,\n product_code: productCode,\n passback_params: input.metadata ? JSON.stringify(input.metadata) : undefined,\n })\n\n const params = {\n ...buildCommonParams(method, input.notifyUrl),\n biz_content: bizContent,\n }\n\n const response = await alipayRequest<Record<string, unknown>>(params)\n const key = `${method.replace(/\\./g, '_')}_response`\n const data = response[key] as Record<string, unknown> | undefined\n\n return ok({\n provider: 'alipay',\n tradeType: input.tradeType,\n clientParams: data ?? {},\n prepayId: data?.trade_no as string | undefined,\n })\n }\n catch (cause) {\n return err(\n HaiPaymentError.CREATE_ORDER_FAILED,\n paymentM('payment_createOrderFailed'),\n cause,\n )\n }\n },\n\n async handleNotify(request: PaymentNotifyRequest): Promise<HaiResult<PaymentNotifyResult>> {\n try {\n const params = parseAlipayNotifyParams(request.body)\n\n // 验签\n const valid = verifyAlipayNotify(params as Record<string, string>, config.alipayPublicKey)\n if (!valid) {\n return err(\n HaiPaymentError.NOTIFY_VERIFY_FAILED,\n paymentM('payment_notifyVerifyFailed'),\n )\n }\n\n const statusMap: Record<string, PaymentNotifyResult['status']> = {\n TRADE_SUCCESS: 'paid',\n TRADE_CLOSED: 'closed',\n TRADE_FINISHED: 'paid',\n WAIT_BUYER_PAY: 'pending',\n }\n\n return ok({\n orderNo: params.out_trade_no,\n transactionId: params.trade_no,\n amount: parseAlipayAmount(params.total_amount),\n status: statusMap[params.trade_status] ?? 'pending',\n paidAt: params.gmt_payment ? new Date(params.gmt_payment) : undefined,\n // 支付宝回调原始 params 的强类型为 AlipayNotifyParams,此处统一以 Record 暴露给上层做调试/审计\n raw: params as unknown as Record<string, unknown>,\n })\n }\n catch (cause) {\n return err(\n HaiPaymentError.NOTIFY_PARSE_FAILED,\n paymentM('payment_notifyParseFailed'),\n cause,\n )\n }\n },\n\n async queryOrder(orderNo: string): Promise<HaiResult<OrderStatus>> {\n try {\n const method = 'alipay.trade.query'\n const params = {\n ...buildCommonParams(method, ''),\n biz_content: JSON.stringify({ out_trade_no: orderNo }),\n }\n\n const response = await alipayRequest<Record<string, unknown>>(params)\n const data = response.alipay_trade_query_response as Record<string, unknown> | undefined\n\n const statusMap: Record<string, OrderStatus['status']> = {\n TRADE_SUCCESS: 'paid',\n TRADE_CLOSED: 'closed',\n TRADE_FINISHED: 'paid',\n WAIT_BUYER_PAY: 'pending',\n }\n\n return ok({\n orderNo,\n transactionId: data?.trade_no as string | undefined,\n status: statusMap[data?.trade_status as string] ?? 'pending',\n amount: parseAlipayAmount(data?.total_amount as string ?? '0'),\n paidAt: data?.send_pay_date ? new Date(data.send_pay_date as string) : undefined,\n })\n }\n catch (cause) {\n return err(\n HaiPaymentError.QUERY_ORDER_FAILED,\n paymentM('payment_queryOrderFailed'),\n cause,\n )\n }\n },\n\n async refund(input: RefundInput): Promise<HaiResult<RefundResult>> {\n try {\n const method = 'alipay.trade.refund'\n const params = {\n ...buildCommonParams(method, ''),\n biz_content: JSON.stringify({\n out_trade_no: input.orderNo,\n out_request_no: input.refundNo,\n refund_amount: formatFenAmount(input.amount),\n refund_reason: input.reason,\n }),\n }\n\n const response = await alipayRequest<Record<string, unknown>>(params)\n const data = response.alipay_trade_refund_response as Record<string, unknown> | undefined\n\n return ok({\n refundNo: input.refundNo,\n refundId: data?.trade_no as string ?? '',\n status: data?.fund_change === 'Y' ? 'success' : 'processing',\n })\n }\n catch (cause) {\n return err(\n HaiPaymentError.REFUND_FAILED,\n paymentM('payment_refundFailed'),\n cause,\n )\n }\n },\n\n async closeOrder(orderNo: string): Promise<HaiResult<void>> {\n try {\n const method = 'alipay.trade.close'\n const params = {\n ...buildCommonParams(method, ''),\n biz_content: JSON.stringify({ out_trade_no: orderNo }),\n }\n\n await alipayRequest(params)\n return ok(undefined)\n }\n catch (cause) {\n return err(\n HaiPaymentError.CLOSE_ORDER_FAILED,\n paymentM('payment_closeOrderFailed'),\n cause,\n )\n }\n },\n }\n}\n","/**\n * @h-ai/payment — Stripe Provider\n *\n * 实现 PaymentProvider 接口,对接 Stripe API。\n * 使用 Stripe Checkout Session 模式。\n * @module stripe-provider\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { StripeConfig } from '../../payment-config.js'\nimport type { CreateOrderInput, OrderStatus, PaymentNotifyRequest, PaymentNotifyResult, PaymentOrder, PaymentProvider, RefundInput, RefundResult } from '../../payment-types.js'\nimport { createHmac } from 'node:crypto'\nimport { core, err, ok } from '@h-ai/core'\nimport { paymentM } from '../../payment-i18n.js'\nimport { HaiPaymentError } from '../../payment-types.js'\nimport { fetchWithTimeout } from '../payment-provider-http.js'\n\n/** Stripe API 基地址 */\nconst STRIPE_API_BASE = 'https://api.stripe.com/v1'\n\n/**\n * 创建 Stripe Provider\n *\n * @param config - Stripe 配置\n * @returns PaymentProvider 实例\n */\nexport function createStripeProvider(config: StripeConfig): PaymentProvider {\n /** Stripe API 请求 */\n async function stripeRequest<T>(method: string, path: string, body?: Record<string, string>): Promise<T> {\n const response = await fetchWithTimeout(`${STRIPE_API_BASE}${path}`, {\n method,\n headers: {\n 'Authorization': `Bearer ${config.secretKey}`,\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: body\n ? Object.entries(body).map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`).join('&')\n : undefined,\n })\n\n if (!response.ok) {\n const errorText = await response.text()\n throw new Error(`Stripe API ${method} ${path} failed: ${response.status} ${errorText}`)\n }\n\n return response.json() as T\n }\n\n /** Stripe Webhook 签名容忍时间窗口(秒) */\n const TIMESTAMP_TOLERANCE = config.webhookToleranceSeconds ?? 300\n\n /** 验证 Stripe Webhook 签名 */\n function verifyWebhookSignature(payload: string, signature: string): boolean {\n const parts = signature.split(',')\n const timestamp = parts.find(p => p.startsWith('t='))?.slice(2) ?? ''\n const v1 = parts.find(p => p.startsWith('v1='))?.slice(3) ?? ''\n\n // 时间戳重放保护\n const ts = Number.parseInt(timestamp, 10)\n if (Number.isNaN(ts) || Math.abs(Math.floor(Date.now() / 1000) - ts) > TIMESTAMP_TOLERANCE) {\n return false\n }\n\n const signedPayload = `${timestamp}.${payload}`\n const expected = createHmac('sha256', config.webhookSecret)\n .update(signedPayload)\n .digest('hex')\n\n try {\n return core.string.constantTimeEqual(v1, expected)\n }\n catch {\n return false\n }\n }\n\n return {\n name: 'stripe',\n\n async createOrder(input: CreateOrderInput): Promise<HaiResult<PaymentOrder>> {\n try {\n // 使用 Stripe Checkout Session\n const params: Record<string, string> = {\n 'mode': 'payment',\n 'line_items[0][price_data][currency]': input.currency?.toLowerCase() ?? 'usd',\n 'line_items[0][price_data][product_data][name]': input.description,\n 'line_items[0][price_data][unit_amount]': input.amount.toString(),\n 'line_items[0][quantity]': '1',\n }\n\n // metadata 传递订单号\n params['metadata[orderNo]'] = input.orderNo\n if (input.metadata) {\n for (const [k, v] of Object.entries(input.metadata)) {\n params[`metadata[${k}]`] = v\n }\n }\n\n const session = await stripeRequest<{\n id: string\n url: string\n payment_intent: string\n }>('POST', '/checkout/sessions', params)\n\n return ok({\n provider: 'stripe',\n tradeType: input.tradeType,\n clientParams: {\n sessionId: session.id,\n checkoutUrl: session.url,\n },\n })\n }\n catch (cause) {\n return err(\n HaiPaymentError.CREATE_ORDER_FAILED,\n paymentM('payment_createOrderFailed'),\n cause,\n )\n }\n },\n\n async handleNotify(request: PaymentNotifyRequest): Promise<HaiResult<PaymentNotifyResult>> {\n try {\n const signature = request.headers['stripe-signature'] ?? ''\n\n // 验签\n const valid = verifyWebhookSignature(request.body, signature)\n if (!valid) {\n return err(\n HaiPaymentError.NOTIFY_VERIFY_FAILED,\n paymentM('payment_notifyVerifyFailed'),\n )\n }\n\n const event = JSON.parse(request.body) as {\n type: string\n data: {\n object: {\n id: string\n metadata?: Record<string, string>\n amount_total?: number\n payment_status?: string\n }\n }\n }\n\n const obj = event.data.object\n const orderNo = obj.metadata?.orderNo ?? ''\n\n const statusMap: Record<string, PaymentNotifyResult['status']> = {\n 'checkout.session.completed': 'paid',\n 'payment_intent.payment_failed': 'failed',\n }\n\n return ok({\n orderNo,\n transactionId: obj.id,\n amount: obj.amount_total ?? 0,\n status: statusMap[event.type] ?? 'pending',\n paidAt: new Date(),\n // Stripe SDK 的 Event 是强类型对象,此处统一以 Record 暴露给上层做调试/审计\n raw: event as unknown as Record<string, unknown>,\n })\n }\n catch (cause) {\n return err(\n HaiPaymentError.NOTIFY_PARSE_FAILED,\n paymentM('payment_notifyParseFailed'),\n cause,\n )\n }\n },\n\n async queryOrder(orderNo: string): Promise<HaiResult<OrderStatus>> {\n try {\n // 搜索 checkout sessions by metadata\n const sessions = await stripeRequest<{\n data: Array<{\n id: string\n payment_status: string\n amount_total: number\n }>\n }>('GET', `/checkout/sessions?limit=1&metadata[orderNo]=${encodeURIComponent(orderNo)}`)\n\n const session = sessions.data[0]\n if (!session) {\n return ok({\n orderNo,\n status: 'pending',\n amount: 0,\n })\n }\n\n const statusMap: Record<string, OrderStatus['status']> = {\n paid: 'paid',\n unpaid: 'pending',\n no_payment_required: 'paid',\n }\n\n return ok({\n orderNo,\n transactionId: session.id,\n status: statusMap[session.payment_status] ?? 'pending',\n amount: session.amount_total,\n })\n }\n catch (cause) {\n return err(\n HaiPaymentError.QUERY_ORDER_FAILED,\n paymentM('payment_queryOrderFailed'),\n cause,\n )\n }\n },\n\n async refund(input: RefundInput): Promise<HaiResult<RefundResult>> {\n try {\n // Stripe 退款需要 payment_intent ID,这里简化为根据 orderNo 查询\n const sessions = await stripeRequest<{\n data: Array<{ payment_intent: string }>\n }>('GET', `/checkout/sessions?limit=1&metadata[orderNo]=${encodeURIComponent(input.orderNo)}`)\n\n const paymentIntent = sessions.data[0]?.payment_intent\n if (!paymentIntent) {\n return err(\n HaiPaymentError.REFUND_FAILED,\n paymentM('payment_refundFailed'),\n )\n }\n\n const refund = await stripeRequest<{\n id: string\n status: string\n }>('POST', '/refunds', {\n payment_intent: paymentIntent,\n amount: input.amount.toString(),\n reason: input.reason ?? 'requested_by_customer',\n })\n\n return ok({\n refundNo: input.refundNo,\n refundId: refund.id,\n status: refund.status === 'succeeded' ? 'success' : 'processing',\n })\n }\n catch (cause) {\n return err(\n HaiPaymentError.REFUND_FAILED,\n paymentM('payment_refundFailed'),\n cause,\n )\n }\n },\n\n async closeOrder(_orderNo: string): Promise<HaiResult<void>> {\n // Stripe Checkout Sessions 会自动过期,无需主动关闭\n return ok(undefined)\n },\n }\n}\n","/**\n * @h-ai/payment — 微信支付签名\n *\n * 微信支付 API v3 签名生成与验签工具。\n * @module wechat-pay-sign\n */\n\nimport { Buffer } from 'node:buffer'\nimport { createDecipheriv, createSign, createVerify, randomBytes } from 'node:crypto'\n\n/**\n * 生成随机字符串\n *\n * @param length - 字符串长度(默认 32)\n */\nexport function generateNonce(length = 32): string {\n return randomBytes(length).toString('hex').slice(0, length)\n}\n\n/**\n * 获取当前时间戳(秒)\n */\nexport function getTimestamp(): string {\n return Math.floor(Date.now() / 1000).toString()\n}\n\n/**\n * 微信 API v3 请求签名\n *\n * @param method - HTTP 方法\n * @param url - 请求路径(不含域名)\n * @param timestamp - 时间戳\n * @param nonce - 随机串\n * @param body - 请求体(空则为空字符串)\n * @param privateKey - 商户私钥 PEM\n * @returns SHA256-RSA2048 签名(Base64)\n */\nexport function signRequest(\n method: string,\n url: string,\n timestamp: string,\n nonce: string,\n body: string,\n privateKey: string,\n): string {\n const message = `${method}\\n${url}\\n${timestamp}\\n${nonce}\\n${body}\\n`\n const sign = createSign('RSA-SHA256')\n sign.update(message)\n return sign.sign(privateKey, 'base64')\n}\n\n/**\n * 微信 JSAPI 支付签名\n *\n * @param appId - 应用 ID\n * @param timestamp - 时间戳\n * @param nonce - 随机串\n * @param prepayId - 预支付 ID\n * @param privateKey - 商户私钥 PEM\n * @returns 签名\n */\nexport function signJsapi(\n appId: string,\n timestamp: string,\n nonce: string,\n prepayId: string,\n privateKey: string,\n): string {\n const message = `${appId}\\n${timestamp}\\n${nonce}\\nprepay_id=${prepayId}\\n`\n const sign = createSign('RSA-SHA256')\n sign.update(message)\n return sign.sign(privateKey, 'base64')\n}\n\n/**\n * 验证微信支付回调签名\n *\n * @param timestamp - 回调 header 中的时间戳\n * @param nonce - 回调 header 中的随机串\n * @param body - 回调原始 body\n * @param signature - 回调签名\n * @param platformCert - 微信支付平台证书 PEM\n * @returns 是否验签通过\n */\nexport function verifyNotifySignature(\n timestamp: string,\n nonce: string,\n body: string,\n signature: string,\n platformCert: string,\n): boolean {\n const message = `${timestamp}\\n${nonce}\\n${body}\\n`\n const verify = createVerify('RSA-SHA256')\n verify.update(message)\n return verify.verify(platformCert, signature, 'base64')\n}\n\n/**\n * AES-256-GCM 解密(微信支付回调资源解密)\n *\n * @param ciphertext - 密文(Base64)\n * @param nonce - 随机串\n * @param associatedData - 附加数据\n * @param apiV3Key - API v3 密钥\n * @returns 解密后的 JSON 字符串\n */\nexport function decryptResource(\n ciphertext: string,\n nonce: string,\n associatedData: string,\n apiV3Key: string,\n): string {\n const buf = Buffer.from(ciphertext, 'base64')\n const authTag = buf.subarray(buf.length - 16)\n const data = buf.subarray(0, buf.length - 16)\n\n const decipher = createDecipheriv('aes-256-gcm', apiV3Key, nonce)\n decipher.setAuthTag(authTag)\n decipher.setAAD(Buffer.from(associatedData))\n\n const decrypted = Buffer.concat([decipher.update(data), decipher.final()])\n return decrypted.toString('utf-8')\n}\n","/**\n * @h-ai/payment — 微信支付 Provider\n *\n * 实现 PaymentProvider 接口,对接微信支付 API v3。\n * @module wechat-pay-provider\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { WechatPayConfig } from '../../payment-config.js'\nimport type { CreateOrderInput, OrderStatus, PaymentNotifyRequest, PaymentNotifyResult, PaymentOrder, PaymentProvider, RefundInput, RefundResult } from '../../payment-types.js'\nimport type { WechatNotifyResource, WechatOrderRequest } from './wechat-pay-types.js'\nimport { err, ok } from '@h-ai/core'\nimport { paymentM } from '../../payment-i18n.js'\nimport { HaiPaymentError } from '../../payment-types.js'\nimport { fetchWithTimeout } from '../payment-provider-http.js'\nimport {\n decryptResource,\n generateNonce,\n getTimestamp,\n signJsapi,\n signRequest,\n verifyNotifySignature,\n} from './wechat-pay-sign.js'\n\n/** 微信支付 API 基地址 */\nconst WECHAT_API_BASE = 'https://api.mch.weixin.qq.com'\n\n/**\n * 创建微信支付 Provider\n *\n * @param config - 微信支付配置\n * @returns PaymentProvider 实例\n *\n * @example\n * ```ts\n * const wechatPay = createWechatPayProvider({\n * mchId: 'your-mch-id',\n * apiV3Key: 'your-api-v3-key',\n * serialNo: 'your-serial-no',\n * privateKey: fs.readFileSync('apiclient_key.pem', 'utf-8'),\n * appId: 'your-app-id',\n * })\n *\n * const result = await wechatPay.createOrder({\n * orderNo: 'ORD20240101001',\n * amount: 100, // 1 元\n * description: '测试商品',\n * tradeType: 'jsapi',\n * userId: 'openid-xxx',\n * notifyUrl: 'https://api.example.com/payment/notify/wechat',\n * })\n * ```\n */\nexport function createWechatPayProvider(config: WechatPayConfig): PaymentProvider {\n /**\n * 发送微信支付 API 请求\n */\n async function wechatRequest<T>(method: string, path: string, body?: unknown): Promise<T> {\n const timestamp = getTimestamp()\n const nonce = generateNonce()\n const bodyStr = body ? JSON.stringify(body) : ''\n\n const signature = signRequest(method, path, timestamp, nonce, bodyStr, config.privateKey)\n\n const authorization = `WECHATPAY2-SHA256-RSA2048 mchid=\"${config.mchId}\",nonce_str=\"${nonce}\",timestamp=\"${timestamp}\",serial_no=\"${config.serialNo}\",signature=\"${signature}\"`\n\n const response = await fetchWithTimeout(`${WECHAT_API_BASE}${path}`, {\n method,\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': authorization,\n 'Accept': 'application/json',\n },\n body: bodyStr || undefined,\n })\n\n if (!response.ok) {\n const errorText = await response.text()\n throw new Error(`Wechat API ${method} ${path} failed: ${response.status} ${errorText}`)\n }\n\n return response.json() as T\n }\n\n /** 根据 tradeType 映射到微信 API 路径 */\n function getOrderPath(tradeType: string): string {\n const map: Record<string, string> = {\n jsapi: '/v3/pay/transactions/jsapi',\n h5: '/v3/pay/transactions/h5',\n app: '/v3/pay/transactions/app',\n native: '/v3/pay/transactions/native',\n }\n return map[tradeType] ?? '/v3/pay/transactions/jsapi'\n }\n\n return {\n name: 'wechat',\n\n async createOrder(input: CreateOrderInput): Promise<HaiResult<PaymentOrder>> {\n try {\n const requestBody: WechatOrderRequest = {\n appid: config.appId,\n mchid: config.mchId,\n description: input.description,\n out_trade_no: input.orderNo,\n notify_url: input.notifyUrl,\n amount: {\n total: input.amount,\n currency: input.currency ?? 'CNY',\n },\n }\n\n // JSAPI 需要 payer.openid\n if (input.tradeType === 'jsapi' && input.userId) {\n requestBody.payer = { openid: input.userId }\n }\n\n if (input.metadata) {\n requestBody.attach = JSON.stringify(input.metadata)\n }\n\n const path = getOrderPath(input.tradeType)\n const response = await wechatRequest<{ prepay_id?: string, h5_url?: string, code_url?: string }>('POST', path, requestBody)\n\n // 构建客户端调起参数\n let clientParams: Record<string, unknown> = {}\n\n if (input.tradeType === 'jsapi') {\n const timestamp = getTimestamp()\n const nonce = generateNonce()\n const paySign = signJsapi(config.appId, timestamp, nonce, response.prepay_id!, config.privateKey)\n\n clientParams = {\n appId: config.appId,\n timeStamp: timestamp,\n nonceStr: nonce,\n package: `prepay_id=${response.prepay_id}`,\n signType: 'RSA',\n paySign,\n }\n }\n else if (input.tradeType === 'h5') {\n clientParams = { h5Url: response.h5_url }\n }\n else if (input.tradeType === 'native') {\n clientParams = { codeUrl: response.code_url }\n }\n\n return ok({\n provider: 'wechat',\n tradeType: input.tradeType,\n clientParams,\n prepayId: response.prepay_id,\n })\n }\n catch (cause) {\n return err(\n HaiPaymentError.CREATE_ORDER_FAILED,\n paymentM('payment_createOrderFailed'),\n cause,\n )\n }\n },\n\n async handleNotify(request: PaymentNotifyRequest): Promise<HaiResult<PaymentNotifyResult>> {\n try {\n const timestamp = request.headers['wechatpay-timestamp'] ?? ''\n const nonce = request.headers['wechatpay-nonce'] ?? ''\n const signature = request.headers['wechatpay-signature'] ?? ''\n\n // 验签(必须提供平台证书)\n if (!config.platformCert) {\n return err(\n HaiPaymentError.NOTIFY_VERIFY_FAILED,\n paymentM('payment_notifyVerifyFailed'),\n )\n }\n const valid = verifyNotifySignature(timestamp, nonce, request.body, signature, config.platformCert)\n if (!valid) {\n return err(\n HaiPaymentError.NOTIFY_VERIFY_FAILED,\n paymentM('payment_notifyVerifyFailed'),\n )\n }\n\n // 解密资源\n const body = JSON.parse(request.body) as {\n resource: { ciphertext: string, nonce: string, associated_data: string }\n }\n const decrypted = decryptResource(\n body.resource.ciphertext,\n body.resource.nonce,\n body.resource.associated_data,\n config.apiV3Key,\n )\n const resource = JSON.parse(decrypted) as WechatNotifyResource\n\n return ok({\n orderNo: resource.out_trade_no,\n transactionId: resource.transaction_id,\n amount: resource.amount.total,\n status: resource.trade_state === 'SUCCESS' ? 'paid' : 'failed',\n paidAt: resource.success_time ? new Date(resource.success_time) : undefined,\n // 微信回调原始 payload 的强类型为 WechatNotifyResource,此处统一以 Record 暴露给上层做调试/审计\n raw: resource as unknown as Record<string, unknown>,\n })\n }\n catch (cause) {\n return err(\n HaiPaymentError.NOTIFY_PARSE_FAILED,\n paymentM('payment_notifyParseFailed'),\n cause,\n )\n }\n },\n\n async queryOrder(orderNo: string): Promise<HaiResult<OrderStatus>> {\n try {\n const path = `/v3/pay/transactions/out-trade-no/${encodeURIComponent(orderNo)}?mchid=${encodeURIComponent(config.mchId)}`\n const response = await wechatRequest<{\n out_trade_no: string\n transaction_id: string\n trade_state: string\n amount: { total: number }\n success_time?: string\n }>('GET', path)\n\n const statusMap: Record<string, OrderStatus['status']> = {\n SUCCESS: 'paid',\n CLOSED: 'closed',\n REFUND: 'refunded',\n NOTPAY: 'pending',\n PAYERROR: 'failed',\n }\n\n return ok({\n orderNo: response.out_trade_no,\n transactionId: response.transaction_id,\n status: statusMap[response.trade_state] ?? 'pending',\n amount: response.amount.total,\n paidAt: response.success_time ? new Date(response.success_time) : undefined,\n })\n }\n catch (cause) {\n return err(\n HaiPaymentError.QUERY_ORDER_FAILED,\n paymentM('payment_queryOrderFailed'),\n cause,\n )\n }\n },\n\n async refund(input: RefundInput): Promise<HaiResult<RefundResult>> {\n try {\n const response = await wechatRequest<{\n refund_id: string\n status: string\n }>('POST', '/v3/refund/domestic/refunds', {\n out_trade_no: input.orderNo,\n out_refund_no: input.refundNo,\n amount: {\n refund: input.amount,\n total: input.totalAmount ?? input.amount,\n currency: 'CNY',\n },\n reason: input.reason,\n })\n\n const statusMap: Record<string, RefundResult['status']> = {\n SUCCESS: 'success',\n PROCESSING: 'processing',\n ABNORMAL: 'failed',\n }\n\n return ok({\n refundNo: input.refundNo,\n refundId: response.refund_id,\n status: statusMap[response.status] ?? 'processing',\n })\n }\n catch (cause) {\n return err(\n HaiPaymentError.REFUND_FAILED,\n paymentM('payment_refundFailed'),\n cause,\n )\n }\n },\n\n async closeOrder(orderNo: string): Promise<HaiResult<void>> {\n try {\n await wechatRequest('POST', `/v3/pay/transactions/out-trade-no/${encodeURIComponent(orderNo)}/close`, {\n mchid: config.mchId,\n })\n return ok(undefined)\n }\n catch (cause) {\n return err(\n HaiPaymentError.CLOSE_ORDER_FAILED,\n paymentM('payment_closeOrderFailed'),\n cause,\n )\n }\n },\n }\n}\n","/**\n * @h-ai/payment — 模块入口(生命周期管理)\n *\n * 提供支付模块的初始化、Provider 注册与统一支付操作 API。\n * `payment.init(config)` 负责根据配置自动注册可用的 Provider。\n *\n * @module payment-main\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { PaymentConfig, PaymentConfigInput } from './payment-config.js'\nimport type {\n OrderStatus,\n PaymentFunctions,\n PaymentNotifyResult,\n PaymentOrder,\n RefundResult,\n} from './payment-types.js'\nimport { core, err, ok } from '@h-ai/core'\nimport { PaymentConfigSchema } from './payment-config.js'\nimport {\n clearProviders,\n closeOrder,\n createOrder,\n getProvider,\n handleNotify,\n queryOrder,\n refund,\n registerProvider,\n} from './payment-functions.js'\nimport { paymentM } from './payment-i18n.js'\nimport { HaiPaymentError } from './payment-types.js'\nimport { createAlipayProvider } from './providers/alipay/alipay-provider.js'\nimport { createStripeProvider } from './providers/stripe/stripe-provider.js'\nimport { createWechatPayProvider } from './providers/wechat/wechat-pay-provider.js'\n\nconst logger = core.logger.child({ module: 'payment', scope: 'main' })\n\n// ─── 内部状态 ───\n\nlet currentConfig: PaymentConfig | null = null\nlet initInProgress = false\n\n// ─── 未初始化占位 ───\n\nconst notInitialized = core.module.createNotInitializedKit(\n HaiPaymentError.NOT_INITIALIZED,\n () => paymentM('payment_notInitialized'),\n)\n\n// ─── 服务对象 ───\n\n/**\n * 支付模块服务对象\n *\n * @example\n * ```ts\n * import { payment } from '@h-ai/payment'\n *\n * await payment.init({\n * wechat: { mchId: '...', apiV3Key: '...', ... },\n * alipay: { appId: '...', privateKey: '...' , ... },\n * })\n *\n * const result = await payment.createOrder('wechat', {\n * orderNo: 'ORD001',\n * amount: 100,\n * description: '测试商品',\n * tradeType: 'jsapi',\n * userId: 'openid-xxx',\n * notifyUrl: 'https://api.example.com/payment/notify/wechat',\n * })\n * ```\n */\nexport const payment: PaymentFunctions = {\n /**\n * 初始化支付模块\n *\n * 根据提供的配置自动注册对应的 Provider。\n *\n * @param config - 支付配置\n */\n async init(config: PaymentConfigInput): Promise<HaiResult<void>> {\n if (initInProgress) {\n logger.warn('Payment module init already in progress, skipping')\n return err(\n HaiPaymentError.CONFIG_ERROR,\n paymentM('payment_configError', { params: { error: 'init already in progress' } }),\n )\n }\n\n initInProgress = true\n\n try {\n if (currentConfig !== null) {\n logger.warn('Payment module is already initialized, reinitializing')\n await payment.close()\n }\n\n logger.info('Initializing payment module')\n const parseResult = PaymentConfigSchema.safeParse(config)\n if (!parseResult.success) {\n logger.error('Payment config validation failed', { error: parseResult.error.message })\n return err(\n HaiPaymentError.CONFIG_ERROR,\n paymentM('payment_configError', { params: { error: parseResult.error.message } }),\n parseResult.error,\n )\n }\n const parsed = parseResult.data\n\n // 清除旧注册\n clearProviders()\n\n // 按配置自动注册 Provider\n if (parsed.wechat) {\n registerProvider(createWechatPayProvider(parsed.wechat))\n }\n if (parsed.alipay) {\n registerProvider(createAlipayProvider(parsed.alipay))\n }\n if (parsed.stripe) {\n registerProvider(createStripeProvider(parsed.stripe))\n }\n\n currentConfig = parsed\n logger.info('Payment module initialized', {\n providers: [\n parsed.wechat ? 'wechat' : null,\n parsed.alipay ? 'alipay' : null,\n parsed.stripe ? 'stripe' : null,\n ].filter(Boolean),\n })\n return ok(undefined)\n }\n catch (error) {\n logger.error('Payment module initialization failed', { error })\n return err(\n HaiPaymentError.CONFIG_ERROR,\n paymentM('payment_initFailed', {\n params: { error: error instanceof Error ? error.message : String(error) },\n }),\n error,\n )\n }\n finally {\n initInProgress = false\n }\n },\n\n /**\n * 关闭模块、清除所有 Provider\n */\n async close(): Promise<void> {\n if (!currentConfig) {\n logger.info('Payment module already closed, skipping')\n return\n }\n logger.info('Closing payment module')\n clearProviders()\n currentConfig = null\n logger.info('Payment module closed')\n },\n\n get config() { return currentConfig },\n get isInitialized() { return currentConfig !== null },\n\n /** 创建支付订单 */\n createOrder: (...args: Parameters<typeof createOrder>) =>\n currentConfig ? createOrder(...args) : Promise.resolve(notInitialized.result<PaymentOrder>()),\n\n /** 处理异步回调通知 */\n handleNotify: (...args: Parameters<typeof handleNotify>) =>\n currentConfig ? handleNotify(...args) : Promise.resolve(notInitialized.result<PaymentNotifyResult>()),\n\n /** 查询订单状态 */\n queryOrder: (...args: Parameters<typeof queryOrder>) =>\n currentConfig ? queryOrder(...args) : Promise.resolve(notInitialized.result<OrderStatus>()),\n\n /** 发起退款 */\n refund: (...args: Parameters<typeof refund>) =>\n currentConfig ? refund(...args) : Promise.resolve(notInitialized.result<RefundResult>()),\n\n /** 关闭订单 */\n closeOrder: (...args: Parameters<typeof closeOrder>) =>\n currentConfig ? closeOrder(...args) : Promise.resolve(notInitialized.result<void>()),\n\n /** 获取已注册的 Provider */\n getProvider,\n\n /** 手动注册 Provider(自定义渠道) */\n registerProvider,\n}\n"]}
|
|
@@ -33,6 +33,7 @@ declare const AlipayConfigSchema: z.ZodObject<{
|
|
|
33
33
|
declare const StripeConfigSchema: z.ZodObject<{
|
|
34
34
|
secretKey: z.ZodString;
|
|
35
35
|
webhookSecret: z.ZodString;
|
|
36
|
+
webhookToleranceSeconds: z.ZodDefault<z.ZodNumber>;
|
|
36
37
|
}, z.core.$strip>;
|
|
37
38
|
/** 支付模块配置 Schema */
|
|
38
39
|
declare const PaymentConfigSchema: z.ZodObject<{
|
|
@@ -57,6 +58,7 @@ declare const PaymentConfigSchema: z.ZodObject<{
|
|
|
57
58
|
stripe: z.ZodOptional<z.ZodObject<{
|
|
58
59
|
secretKey: z.ZodString;
|
|
59
60
|
webhookSecret: z.ZodString;
|
|
61
|
+
webhookToleranceSeconds: z.ZodDefault<z.ZodNumber>;
|
|
60
62
|
}, z.core.$strip>>;
|
|
61
63
|
}, z.core.$strip>;
|
|
62
64
|
type PaymentConfig = z.infer<typeof PaymentConfigSchema>;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@h-ai/payment",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.1.0-alpha.
|
|
4
|
+
"version": "0.1.0-alpha.20",
|
|
5
5
|
"description": "Hai Framework payment module for WeChat Pay, Alipay, and Stripe.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"exports": {
|
|
@@ -24,8 +24,8 @@
|
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"zod": "^4.4.3",
|
|
27
|
-
"@h-ai/audit": "0.1.0-alpha.
|
|
28
|
-
"@h-ai/core": "0.1.0-alpha.
|
|
27
|
+
"@h-ai/audit": "0.1.0-alpha.20",
|
|
28
|
+
"@h-ai/core": "0.1.0-alpha.20"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@types/node": "^25.9.1",
|