@vobs/payment 0.3.0 → 1.2.0

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.
Files changed (178) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +182 -0
  3. package/dist/alipay/client.cjs +112 -0
  4. package/dist/alipay/client.cjs.map +1 -0
  5. package/dist/alipay/client.d.cts +36 -0
  6. package/dist/alipay/client.d.ts +36 -0
  7. package/dist/alipay/client.js +110 -0
  8. package/dist/alipay/client.js.map +1 -0
  9. package/dist/alipay/config.cjs +67 -0
  10. package/dist/alipay/config.cjs.map +1 -0
  11. package/dist/alipay/config.d.cts +30 -0
  12. package/dist/alipay/config.d.ts +30 -0
  13. package/dist/alipay/config.js +65 -0
  14. package/dist/alipay/config.js.map +1 -0
  15. package/dist/alipay/index.cjs +592 -0
  16. package/dist/alipay/index.cjs.map +1 -0
  17. package/dist/alipay/index.d.cts +12 -0
  18. package/dist/alipay/index.d.ts +12 -0
  19. package/dist/alipay/index.js +580 -0
  20. package/dist/alipay/index.js.map +1 -0
  21. package/dist/alipay/notify.cjs +70 -0
  22. package/dist/alipay/notify.cjs.map +1 -0
  23. package/dist/alipay/notify.d.cts +52 -0
  24. package/dist/alipay/notify.d.ts +52 -0
  25. package/dist/alipay/notify.js +68 -0
  26. package/dist/alipay/notify.js.map +1 -0
  27. package/dist/alipay/payment.cjs +49 -0
  28. package/dist/alipay/payment.cjs.map +1 -0
  29. package/dist/alipay/payment.d.cts +24 -0
  30. package/dist/alipay/payment.d.ts +24 -0
  31. package/dist/alipay/payment.js +47 -0
  32. package/dist/alipay/payment.js.map +1 -0
  33. package/dist/alipay/plugin.cjs +300 -0
  34. package/dist/alipay/plugin.cjs.map +1 -0
  35. package/dist/alipay/plugin.d.cts +43 -0
  36. package/dist/alipay/plugin.d.ts +43 -0
  37. package/dist/alipay/plugin.js +296 -0
  38. package/dist/alipay/plugin.js.map +1 -0
  39. package/dist/alipay/query.cjs +80 -0
  40. package/dist/alipay/query.cjs.map +1 -0
  41. package/dist/alipay/query.d.cts +26 -0
  42. package/dist/alipay/query.d.ts +26 -0
  43. package/dist/alipay/query.js +78 -0
  44. package/dist/alipay/query.js.map +1 -0
  45. package/dist/alipay/refund.cjs +104 -0
  46. package/dist/alipay/refund.cjs.map +1 -0
  47. package/dist/alipay/refund.d.cts +32 -0
  48. package/dist/alipay/refund.d.ts +32 -0
  49. package/dist/alipay/refund.js +102 -0
  50. package/dist/alipay/refund.js.map +1 -0
  51. package/dist/alipay/response.cjs +38 -0
  52. package/dist/alipay/response.cjs.map +1 -0
  53. package/dist/alipay/response.d.cts +19 -0
  54. package/dist/alipay/response.d.ts +19 -0
  55. package/dist/alipay/response.js +35 -0
  56. package/dist/alipay/response.js.map +1 -0
  57. package/dist/alipay/types.cjs +4 -0
  58. package/dist/alipay/types.cjs.map +1 -0
  59. package/dist/alipay/types.d.cts +242 -0
  60. package/dist/alipay/types.d.ts +242 -0
  61. package/dist/alipay/types.js +3 -0
  62. package/dist/alipay/types.js.map +1 -0
  63. package/dist/alipay/wap.cjs +50 -0
  64. package/dist/alipay/wap.cjs.map +1 -0
  65. package/dist/alipay/wap.d.cts +24 -0
  66. package/dist/alipay/wap.d.ts +24 -0
  67. package/dist/alipay/wap.js +48 -0
  68. package/dist/alipay/wap.js.map +1 -0
  69. package/dist/index-B1aUR7Vt.d.ts +49 -0
  70. package/dist/index-B8pzZxGq.d.cts +44 -0
  71. package/dist/index-BWnIrwRi.d.ts +44 -0
  72. package/dist/index-Dyrkl86r.d.cts +49 -0
  73. package/dist/index.cjs +1071 -0
  74. package/dist/index.cjs.map +1 -0
  75. package/dist/index.d.cts +23 -0
  76. package/dist/index.d.ts +23 -37
  77. package/dist/index.js +1052 -37
  78. package/dist/index.js.map +1 -0
  79. package/dist/wechat/client.cjs +119 -0
  80. package/dist/wechat/client.cjs.map +1 -0
  81. package/dist/wechat/client.d.cts +39 -0
  82. package/dist/wechat/client.d.ts +39 -0
  83. package/dist/wechat/client.js +117 -0
  84. package/dist/wechat/client.js.map +1 -0
  85. package/dist/wechat/config.cjs +76 -0
  86. package/dist/wechat/config.cjs.map +1 -0
  87. package/dist/wechat/config.d.cts +29 -0
  88. package/dist/wechat/config.d.ts +29 -0
  89. package/dist/wechat/config.js +74 -0
  90. package/dist/wechat/config.js.map +1 -0
  91. package/dist/wechat/index.cjs +612 -0
  92. package/dist/wechat/index.cjs.map +1 -0
  93. package/dist/wechat/index.d.cts +10 -0
  94. package/dist/wechat/index.d.ts +10 -0
  95. package/dist/wechat/index.js +602 -0
  96. package/dist/wechat/index.js.map +1 -0
  97. package/dist/wechat/notify.cjs +73 -0
  98. package/dist/wechat/notify.cjs.map +1 -0
  99. package/dist/wechat/notify.d.cts +53 -0
  100. package/dist/wechat/notify.d.ts +53 -0
  101. package/dist/wechat/notify.js +71 -0
  102. package/dist/wechat/notify.js.map +1 -0
  103. package/dist/wechat/payment.cjs +186 -0
  104. package/dist/wechat/payment.cjs.map +1 -0
  105. package/dist/wechat/payment.d.cts +50 -0
  106. package/dist/wechat/payment.d.ts +50 -0
  107. package/dist/wechat/payment.js +184 -0
  108. package/dist/wechat/payment.js.map +1 -0
  109. package/dist/wechat/plugin.cjs +305 -0
  110. package/dist/wechat/plugin.cjs.map +1 -0
  111. package/dist/wechat/plugin.d.cts +40 -0
  112. package/dist/wechat/plugin.d.ts +40 -0
  113. package/dist/wechat/plugin.js +301 -0
  114. package/dist/wechat/plugin.js.map +1 -0
  115. package/dist/wechat/refund.cjs +112 -0
  116. package/dist/wechat/refund.cjs.map +1 -0
  117. package/dist/wechat/refund.d.cts +26 -0
  118. package/dist/wechat/refund.d.ts +26 -0
  119. package/dist/wechat/refund.js +110 -0
  120. package/dist/wechat/refund.js.map +1 -0
  121. package/dist/wechat/response.cjs +50 -0
  122. package/dist/wechat/response.cjs.map +1 -0
  123. package/dist/wechat/response.d.cts +20 -0
  124. package/dist/wechat/response.d.ts +20 -0
  125. package/dist/wechat/response.js +46 -0
  126. package/dist/wechat/response.js.map +1 -0
  127. package/dist/wechat/types.cjs +4 -0
  128. package/dist/wechat/types.cjs.map +1 -0
  129. package/dist/wechat/types.d.cts +200 -0
  130. package/dist/wechat/types.d.ts +200 -0
  131. package/dist/wechat/types.js +3 -0
  132. package/dist/wechat/types.js.map +1 -0
  133. package/package.json +37 -28
  134. package/src/alipay/alipay.test.ts +231 -0
  135. package/src/alipay/client.ts +67 -0
  136. package/src/alipay/config.ts +72 -0
  137. package/src/alipay/index.ts +32 -0
  138. package/src/alipay/notify.ts +92 -0
  139. package/src/alipay/payment.ts +60 -0
  140. package/src/alipay/plugin.ts +64 -0
  141. package/src/alipay/query.ts +52 -0
  142. package/src/alipay/refund.ts +85 -0
  143. package/src/alipay/response.ts +40 -0
  144. package/src/alipay/types.ts +271 -0
  145. package/src/alipay/wap.ts +55 -0
  146. package/src/index.ts +78 -0
  147. package/src/wechat/client.ts +68 -0
  148. package/src/wechat/config.ts +81 -0
  149. package/src/wechat/index.ts +30 -0
  150. package/src/wechat/notify.ts +93 -0
  151. package/src/wechat/payment.ts +177 -0
  152. package/src/wechat/plugin.ts +59 -0
  153. package/src/wechat/refund.ts +80 -0
  154. package/src/wechat/response.ts +54 -0
  155. package/src/wechat/types.ts +223 -0
  156. package/src/wechat/wechat.test.ts +393 -0
  157. package/dist/alipay-official.d.ts +0 -34
  158. package/dist/alipay-official.js +0 -206
  159. package/dist/handlers.d.ts +0 -45
  160. package/dist/handlers.js +0 -105
  161. package/dist/jeepay.d.ts +0 -39
  162. package/dist/jeepay.js +0 -206
  163. package/dist/lakala.d.ts +0 -41
  164. package/dist/lakala.js +0 -243
  165. package/dist/manager.d.ts +0 -67
  166. package/dist/manager.js +0 -538
  167. package/dist/mock-driver.d.ts +0 -22
  168. package/dist/mock-driver.js +0 -59
  169. package/dist/state-machine.d.ts +0 -41
  170. package/dist/state-machine.js +0 -60
  171. package/dist/store.d.ts +0 -33
  172. package/dist/store.js +0 -76
  173. package/dist/types.d.ts +0 -168
  174. package/dist/types.js +0 -11
  175. package/dist/verify.d.ts +0 -34
  176. package/dist/verify.js +0 -55
  177. package/dist/wechat-official.d.ts +0 -40
  178. package/dist/wechat-official.js +0 -208
@@ -0,0 +1,602 @@
1
+ import { Wechatpay, Formatter, Rsa, Aes } from 'wechatpay-axios-plugin';
2
+
3
+ var __defProp = Object.defineProperty;
4
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
5
+
6
+ // packages/payment/src/wechat/config.ts
7
+ var _WechatConfig = class _WechatConfig {
8
+ constructor(options) {
9
+ this.validate(options);
10
+ this._options = { ...options };
11
+ }
12
+ /** 获取完整配置 */
13
+ get options() {
14
+ return this._options;
15
+ }
16
+ /** 商户号 */
17
+ get mchid() {
18
+ return this._options.mchid;
19
+ }
20
+ /** 应用 ID(公众号 / 小程序 / APP) */
21
+ get appid() {
22
+ return this._options.appid;
23
+ }
24
+ /** 商户 API 证书序列号 */
25
+ get serial() {
26
+ return this._options.serial;
27
+ }
28
+ /** APIv3 密钥(回调解密用) */
29
+ get apiv3Key() {
30
+ return this._options.apiv3Key;
31
+ }
32
+ /** 异步通知地址 */
33
+ get notifyUrl() {
34
+ return this._options.notifyUrl;
35
+ }
36
+ /** 更新配置(部分更新) */
37
+ update(patch) {
38
+ const merged = { ...this._options, ...patch };
39
+ this.validate(merged);
40
+ this._options = merged;
41
+ }
42
+ /** 替换配置 */
43
+ replace(options) {
44
+ this.validate(options);
45
+ this._options = { ...options };
46
+ }
47
+ validate(options) {
48
+ if (!options.mchid) {
49
+ throw new Error("WechatConfig: mchid \u4E0D\u80FD\u4E3A\u7A7A");
50
+ }
51
+ if (!options.serial) {
52
+ throw new Error("WechatConfig: serial\uFF08\u5546\u6237 API \u8BC1\u4E66\u5E8F\u5217\u53F7\uFF09\u4E0D\u80FD\u4E3A\u7A7A");
53
+ }
54
+ if (!options.privateKey) {
55
+ throw new Error("WechatConfig: privateKey\uFF08\u5546\u6237 API \u79C1\u94A5 PEM\uFF09\u4E0D\u80FD\u4E3A\u7A7A");
56
+ }
57
+ if (!options.certs || Object.keys(options.certs).length === 0) {
58
+ throw new Error("WechatConfig: certs\uFF08\u5E73\u53F0\u8BC1\u4E66/\u5FAE\u4FE1\u652F\u4ED8\u516C\u94A5 {\u5E8F\u5217\u53F7: PEM}\uFF09\u4E0D\u80FD\u4E3A\u7A7A");
59
+ }
60
+ if (!options.appid) {
61
+ throw new Error("WechatConfig: appid \u4E0D\u80FD\u4E3A\u7A7A");
62
+ }
63
+ if (!options.apiv3Key) {
64
+ throw new Error("WechatConfig: apiv3Key \u4E0D\u80FD\u4E3A\u7A7A");
65
+ }
66
+ if (options.apiv3Key.length !== 32) {
67
+ throw new Error("WechatConfig: apiv3Key \u5FC5\u987B\u4E3A 32 \u5B57\u8282\u5B57\u7B26\u4E32");
68
+ }
69
+ }
70
+ };
71
+ __name(_WechatConfig, "WechatConfig");
72
+ var WechatConfig = _WechatConfig;
73
+
74
+ // packages/payment/src/wechat/client.ts
75
+ var _WechatClient = class _WechatClient {
76
+ constructor(options) {
77
+ this._disposed = false;
78
+ this.config = new WechatConfig(options);
79
+ this._sdk = this.createSdk(options);
80
+ }
81
+ /** 获取底层 Wechatpay 实例(链式 API:client.sdk.v3.pay.transactions.jsapi.post(...)) */
82
+ get sdk() {
83
+ this.ensureActive();
84
+ return this._sdk;
85
+ }
86
+ /** 更新配置并重建 SDK 实例 */
87
+ updateConfig(patch) {
88
+ this.ensureActive();
89
+ this.config.update(patch);
90
+ this._sdk = this.createSdk(this.config.options);
91
+ }
92
+ /** 销毁客户端 */
93
+ dispose() {
94
+ this._disposed = true;
95
+ this._sdk = null;
96
+ }
97
+ createSdk(options) {
98
+ return new Wechatpay({
99
+ mchid: options.mchid,
100
+ serial: options.serial,
101
+ privateKey: options.privateKey,
102
+ certs: options.certs,
103
+ timeout: options.timeout ?? 5e3
104
+ });
105
+ }
106
+ ensureActive() {
107
+ if (this._disposed) {
108
+ throw new Error("WechatClient: \u5BA2\u6237\u7AEF\u5DF2\u9500\u6BC1");
109
+ }
110
+ }
111
+ };
112
+ __name(_WechatClient, "WechatClient");
113
+ var WechatClient = _WechatClient;
114
+
115
+ // packages/payment/src/wechat/response.ts
116
+ var _WechatApiError = class _WechatApiError extends Error {
117
+ constructor(message, status, code) {
118
+ super(message);
119
+ this.name = "WechatApiError";
120
+ this.status = status;
121
+ this.code = code;
122
+ }
123
+ };
124
+ __name(_WechatApiError, "WechatApiError");
125
+ var WechatApiError = _WechatApiError;
126
+ function toWechatApiError(error) {
127
+ if (error instanceof WechatApiError) return error;
128
+ const axiosError = error;
129
+ const status = axiosError?.response?.status;
130
+ const bizCode = axiosError?.response?.data?.code;
131
+ const bizMessage = axiosError?.response?.data?.message;
132
+ if (status !== void 0) {
133
+ return new WechatApiError(
134
+ `\u5FAE\u4FE1\u652F\u4ED8\u63A5\u53E3\u8C03\u7528\u5931\u8D25: ${bizMessage ?? axiosError?.message ?? "\u672A\u77E5\u9519\u8BEF"} (${status}${bizCode ? `, ${bizCode}` : ""})`,
135
+ status,
136
+ bizCode ?? String(status)
137
+ );
138
+ }
139
+ return new WechatApiError(
140
+ `\u5FAE\u4FE1\u652F\u4ED8\u8BF7\u6C42\u5931\u8D25: ${axiosError?.message ?? "\u672A\u77E5\u9519\u8BEF"}${axiosError?.code ? ` (${axiosError.code})` : ""}`,
141
+ void 0,
142
+ axiosError?.code ?? "NETWORK_ERROR"
143
+ );
144
+ }
145
+ __name(toWechatApiError, "toWechatApiError");
146
+ async function unwrapV3(promise) {
147
+ try {
148
+ return await promise;
149
+ } catch (error) {
150
+ throw toWechatApiError(error);
151
+ }
152
+ }
153
+ __name(unwrapV3, "unwrapV3");
154
+ function createPayment(client) {
155
+ return {
156
+ /**
157
+ * 公众号 / 小程序支付下单(POST /v3/pay/transactions/jsapi)
158
+ * @param params 下单参数,openid 必填
159
+ * @returns 调起 wx.requestPayment 所需的签名参数
160
+ */
161
+ async jsapiPay(params) {
162
+ const { data } = await postTransaction(client, "jsapi", params);
163
+ return buildInvokeParams(client, data.prepay_id ?? "");
164
+ },
165
+ /**
166
+ * APP 支付下单(POST /v3/pay/transactions/app)
167
+ * @param params 下单参数
168
+ * @returns 传给客户端 SDK 调起微信支付的签名参数
169
+ */
170
+ async appPay(params) {
171
+ const { data } = await postTransaction(client, "app", params);
172
+ return buildInvokeParams(client, data.prepay_id ?? "");
173
+ },
174
+ /**
175
+ * Native 扫码支付下单(POST /v3/pay/transactions/native)
176
+ * @returns 二维码链接(前端渲染二维码,用户扫码支付)
177
+ */
178
+ async nativePay(params) {
179
+ const { data } = await postTransaction(client, "native", params);
180
+ if (!data.code_url) {
181
+ throw new Error("WechatClient: \u4E0B\u5355\u54CD\u5E94\u7F3A\u5C11 code_url");
182
+ }
183
+ return { codeUrl: data.code_url };
184
+ },
185
+ /**
186
+ * H5 支付下单(POST /v3/pay/transactions/h5)
187
+ * @param params 下单参数,payerClientIp 必填
188
+ * @returns 收银台跳转链接(302 重定向即可拉起微信支付)
189
+ */
190
+ async h5Pay(params) {
191
+ const body = buildTransactionBody(client, params);
192
+ body.scene_info = {
193
+ payer_client_ip: params.payerClientIp,
194
+ ...params.sceneInfo?.deviceType ? { device_type: params.sceneInfo.deviceType } : {}
195
+ };
196
+ const { data } = await unwrapV3(client.sdk.v3.pay.transactions.h5.post(body));
197
+ return { h5Url: data.h5_url };
198
+ },
199
+ /**
200
+ * 交易查询(GET /v3/pay/transactions/out-trade-no/{no} 或 .../id/{id})
201
+ * @throws {WechatApiError} 订单不存在等失败(RESOURCE_NOT_EXISTS)
202
+ */
203
+ async query(params) {
204
+ const mchid = client.config.mchid;
205
+ const response = params.transactionId ? await unwrapV3(
206
+ client.sdk.client.request(
207
+ `/v3/pay/transactions/id/${encodeURIComponent(params.transactionId)}`,
208
+ "GET",
209
+ void 0,
210
+ { params: { mchid } }
211
+ )
212
+ ) : await unwrapV3(
213
+ client.sdk.client.request(
214
+ `/v3/pay/transactions/out-trade-no/${encodeURIComponent(params.outTradeNo ?? "")}`,
215
+ "GET",
216
+ void 0,
217
+ { params: { mchid } }
218
+ )
219
+ );
220
+ return mapTransaction(response.data);
221
+ }
222
+ };
223
+ }
224
+ __name(createPayment, "createPayment");
225
+ async function postTransaction(client, chain, params) {
226
+ const body = buildTransactionBody(client, params);
227
+ return unwrapV3(client.sdk.v3.pay.transactions[chain].post(body));
228
+ }
229
+ __name(postTransaction, "postTransaction");
230
+ function buildTransactionBody(client, params) {
231
+ const body = {
232
+ appid: client.config.appid,
233
+ mchid: client.config.mchid,
234
+ description: params.description,
235
+ out_trade_no: params.outTradeNo,
236
+ time_expire: params.timeExpire,
237
+ attach: params.attach,
238
+ goods_tag: params.goodsTag,
239
+ notify_url: client.config.notifyUrl,
240
+ amount: {
241
+ total: params.amount.total,
242
+ currency: params.amount.currency ?? "CNY"
243
+ }
244
+ };
245
+ if (params.openid) {
246
+ body.payer = { openid: params.openid };
247
+ }
248
+ for (const key of Object.keys(body)) {
249
+ if (body[key] === void 0) delete body[key];
250
+ }
251
+ return body;
252
+ }
253
+ __name(buildTransactionBody, "buildTransactionBody");
254
+ function buildInvokeParams(client, prepayId) {
255
+ if (!prepayId) {
256
+ throw new Error("WechatClient: \u4E0B\u5355\u54CD\u5E94\u7F3A\u5C11 prepay_id");
257
+ }
258
+ const appId = client.config.appid;
259
+ const timeStamp = `${Formatter.timestamp()}`;
260
+ const nonceStr = Formatter.nonce(32);
261
+ const pkg = `prepay_id=${prepayId}`;
262
+ const message = `${appId}
263
+ ${timeStamp}
264
+ ${nonceStr}
265
+ ${pkg}
266
+ `;
267
+ const paySign = Rsa.sign(message, client.config.options.privateKey);
268
+ return { appId, timeStamp, nonceStr, package: pkg, signType: "RSA", paySign };
269
+ }
270
+ __name(buildInvokeParams, "buildInvokeParams");
271
+ function mapTransaction(data) {
272
+ return {
273
+ appid: data.appid,
274
+ mchid: data.mchid,
275
+ outTradeNo: data.out_trade_no,
276
+ transactionId: data.transaction_id,
277
+ tradeType: data.trade_type,
278
+ tradeState: data.trade_state,
279
+ tradeStateDesc: data.trade_state_desc,
280
+ bankType: data.bank_type,
281
+ attach: data.attach,
282
+ successTime: data.success_time,
283
+ total: data.amount?.total,
284
+ payerTotal: data.amount?.payer_total
285
+ };
286
+ }
287
+ __name(mapTransaction, "mapTransaction");
288
+ function createNotifyHandler(client) {
289
+ return {
290
+ /**
291
+ * 验签异步通知
292
+ * @param headers 微信支付回调的 Wechatpay-* 系列 HTTP 头
293
+ * @param body 原始请求体字符串(必须是未解析的原文,不可先 JSON.parse 再序列化)
294
+ * @returns 验签是否通过
295
+ */
296
+ verify(headers, body) {
297
+ const publicKey = client.config.options.certs[headers.serial];
298
+ if (!publicKey) {
299
+ return false;
300
+ }
301
+ try {
302
+ const message = Formatter.response(headers.timestamp, headers.nonce, body);
303
+ return Rsa.verify(message, headers.signature, publicKey);
304
+ } catch {
305
+ return false;
306
+ }
307
+ },
308
+ /**
309
+ * 解密通知 resource 字段(AES-256-GCM,apiv3Key)
310
+ * @param resource 回调 JSON 中的 resource 字段
311
+ */
312
+ decrypt(resource) {
313
+ const plaintext = Aes.AesGcm.decrypt(
314
+ resource.ciphertext,
315
+ client.config.apiv3Key,
316
+ resource.nonce,
317
+ resource.associatedData ?? ""
318
+ );
319
+ return JSON.parse(plaintext);
320
+ },
321
+ /**
322
+ * 校验解密后的通知与商户侧订单是否一致。
323
+ * 验签只保证通知来自微信支付,不保证与你的订单一致。
324
+ * @param payload 解密后的通知数据
325
+ * @param expected 商户侧期望值:outTradeNo 订单号、total 订单金额(分)
326
+ */
327
+ validate(payload, expected) {
328
+ const errors = [];
329
+ if (payload.mchid !== client.config.mchid) {
330
+ errors.push(`mchid \u4E0D\u5339\u914D: \u671F\u671B ${client.config.mchid}\uFF0C\u6536\u5230 ${payload.mchid}`);
331
+ }
332
+ if (expected?.outTradeNo && payload.outTradeNo !== expected.outTradeNo) {
333
+ errors.push(`out_trade_no \u4E0D\u5339\u914D: \u671F\u671B ${expected.outTradeNo}\uFF0C\u6536\u5230 ${payload.outTradeNo}`);
334
+ }
335
+ if (expected?.total !== void 0 && payload.amount?.total !== expected.total) {
336
+ errors.push(`amount.total \u4E0D\u5339\u914D: \u671F\u671B ${expected.total}\uFF0C\u6536\u5230 ${payload.amount?.total}`);
337
+ }
338
+ return { valid: errors.length === 0, errors };
339
+ },
340
+ /** 通知处理成功应答(HTTP 200/201,body 恰为 {"code":"SUCCESS"}) */
341
+ successResponse() {
342
+ return { code: "SUCCESS" };
343
+ },
344
+ /** 通知处理失败应答(微信会按衰减频率重发通知) */
345
+ failResponse(message) {
346
+ return { code: "FAIL", message: message ?? "\u5904\u7406\u5931\u8D25" };
347
+ }
348
+ };
349
+ }
350
+ __name(createNotifyHandler, "createNotifyHandler");
351
+
352
+ // packages/payment/src/wechat/refund.ts
353
+ function createRefund(client) {
354
+ return {
355
+ /**
356
+ * 申请退款(POST /v3/refund/domestic/refunds)
357
+ * @param params 退款参数(outTradeNo 与 transactionId 二选一)
358
+ * @throws {WechatApiError} 参数错误、余额不足、订单不可退等失败
359
+ */
360
+ async refund(params) {
361
+ const body = {
362
+ out_trade_no: params.outTradeNo,
363
+ transaction_id: params.transactionId,
364
+ out_refund_no: params.outRefundNo,
365
+ reason: params.reason,
366
+ notify_url: params.notifyUrl ?? client.config.notifyUrl,
367
+ funds_account: params.fundsAccount,
368
+ amount: {
369
+ refund: params.amount.refund,
370
+ total: params.amount.total,
371
+ currency: params.amount.currency ?? "CNY"
372
+ }
373
+ };
374
+ for (const key of Object.keys(body)) {
375
+ if (body[key] === void 0) delete body[key];
376
+ }
377
+ for (const key of Object.keys(body.amount)) {
378
+ if (body.amount[key] === void 0) delete body.amount[key];
379
+ }
380
+ const { data } = await unwrapV3(client.sdk.v3.refund.domestic.refunds.post(body));
381
+ return mapRefund(data);
382
+ },
383
+ /**
384
+ * 查询退款(GET /v3/refund/domestic/refunds/{out_refund_no | refund_id})
385
+ * @throws {WechatApiError} 退款单不存在等失败
386
+ */
387
+ async queryRefund(params) {
388
+ const id = params.refundId ?? params.outRefundNo;
389
+ if (!id) {
390
+ throw new Error("WechatClient: queryRefund \u9700\u8981 outRefundNo \u6216 refundId");
391
+ }
392
+ const { data } = await unwrapV3(
393
+ client.sdk.client.request(`/v3/refund/domestic/refunds/${encodeURIComponent(id)}`, "GET")
394
+ );
395
+ return mapRefund(data);
396
+ }
397
+ };
398
+ }
399
+ __name(createRefund, "createRefund");
400
+ function mapRefund(data) {
401
+ return {
402
+ refundId: data.refund_id,
403
+ outRefundNo: data.out_refund_no,
404
+ outTradeNo: data.out_trade_no,
405
+ transactionId: data.transaction_id,
406
+ status: data.status,
407
+ refundAmount: data.amount?.refund,
408
+ total: data.amount?.total,
409
+ userReceivedAmount: data.amount?.user_received_amount,
410
+ successTime: data.success_time,
411
+ reason: data.reason
412
+ };
413
+ }
414
+ __name(mapRefund, "mapRefund");
415
+
416
+ // packages/reactivity/src/debug.ts
417
+ var activeDebugHooks = null;
418
+ function hasDebugHooks() {
419
+ return activeDebugHooks !== null;
420
+ }
421
+ __name(hasDebugHooks, "hasDebugHooks");
422
+ function invokeDebug(name, ...args) {
423
+ return;
424
+ }
425
+ __name(invokeDebug, "invokeDebug");
426
+
427
+ // packages/reactivity/src/owner.ts
428
+ var currentOwner = null;
429
+ function getCurrentOwner() {
430
+ return currentOwner;
431
+ }
432
+ __name(getCurrentOwner, "getCurrentOwner");
433
+
434
+ // packages/reactivity/src/scheduler.ts
435
+ var _Scheduler = class _Scheduler {
436
+ constructor() {
437
+ this.dirtyEffects = /* @__PURE__ */ new Set();
438
+ this.lowPriorityEffects = /* @__PURE__ */ new Set();
439
+ // flush 不可重入(flushing 标志保证),缓冲数组可在轮次间安全复用,避免每轮分配。
440
+ this.normalBuffer = [];
441
+ this.lowBuffer = [];
442
+ this.flushing = false;
443
+ this.scheduled = false;
444
+ this.batchDepth = 0;
445
+ }
446
+ schedule(effect2) {
447
+ if (effect2.disposed) return;
448
+ this.dirtyEffects.add(effect2);
449
+ this.lowPriorityEffects.delete(effect2);
450
+ this.ensureScheduled();
451
+ }
452
+ /** Queue an effect behind normal updates while preserving deterministic order. */
453
+ scheduleLow(effect2) {
454
+ if (effect2.disposed) return;
455
+ if (!this.dirtyEffects.has(effect2)) this.lowPriorityEffects.add(effect2);
456
+ this.ensureScheduled();
457
+ }
458
+ ensureScheduled() {
459
+ if (this.batchDepth === 0 && !this.flushing && !this.scheduled) {
460
+ this.scheduled = true;
461
+ queueMicrotask(() => {
462
+ this.scheduled = false;
463
+ this.flush();
464
+ });
465
+ }
466
+ }
467
+ remove(effect2) {
468
+ this.dirtyEffects.delete(effect2);
469
+ this.lowPriorityEffects.delete(effect2);
470
+ }
471
+ batch(fn) {
472
+ this.batchDepth++;
473
+ try {
474
+ return fn();
475
+ } finally {
476
+ this.batchDepth--;
477
+ if (this.batchDepth === 0) this.flush();
478
+ }
479
+ }
480
+ flush() {
481
+ if (this.flushing || this.batchDepth > 0) return;
482
+ this.flushing = true;
483
+ let rounds = 0;
484
+ let firstError;
485
+ let hasError = false;
486
+ try {
487
+ while (this.dirtyEffects.size > 0 || this.lowPriorityEffects.size > 0) {
488
+ if (++rounds > 100) {
489
+ this.dirtyEffects.clear();
490
+ this.lowPriorityEffects.clear();
491
+ throw new Error("Vobs: \u54CD\u5E94\u5F0F\u66F4\u65B0\u8D85\u8FC7 100 \u8F6E\uFF0C\u53EF\u80FD\u5B58\u5728\u5FAA\u73AF\u4F9D\u8D56");
492
+ }
493
+ this.collectRunnable(this.dirtyEffects, this.normalBuffer);
494
+ this.collectRunnable(this.lowPriorityEffects, this.lowBuffer);
495
+ sortEffects(this.normalBuffer);
496
+ sortEffects(this.lowBuffer);
497
+ for (const effect2 of this.normalBuffer) {
498
+ try {
499
+ effect2.run();
500
+ } catch (error) {
501
+ if (!hasError) {
502
+ firstError = error;
503
+ hasError = true;
504
+ }
505
+ }
506
+ }
507
+ for (const effect2 of this.lowBuffer) {
508
+ try {
509
+ effect2.run();
510
+ } catch (error) {
511
+ if (!hasError) {
512
+ firstError = error;
513
+ hasError = true;
514
+ }
515
+ }
516
+ }
517
+ this.normalBuffer.length = 0;
518
+ this.lowBuffer.length = 0;
519
+ }
520
+ } finally {
521
+ this.normalBuffer.length = 0;
522
+ this.lowBuffer.length = 0;
523
+ this.flushing = false;
524
+ }
525
+ if (hasError) throw firstError;
526
+ }
527
+ /** 收集未 disposed 的 effect 并清空源集合;run() 期间新调度的 effect 留给下一轮。 */
528
+ collectRunnable(source, target) {
529
+ for (const effect2 of source) {
530
+ if (!effect2.disposed) target.push(effect2);
531
+ }
532
+ source.clear();
533
+ }
534
+ };
535
+ __name(_Scheduler, "Scheduler");
536
+ function sortEffects(effects) {
537
+ if (effects.length > 1) {
538
+ effects.sort((a, b) => b.depth - a.depth || a.order - b.order);
539
+ }
540
+ }
541
+ __name(sortEffects, "sortEffects");
542
+
543
+ // packages/runtime/src/hmr.ts
544
+ var globalTarget = globalThis;
545
+ var hmrGlobal = globalTarget.__VOBS_HMR__ ?? { modules: /* @__PURE__ */ new Map() };
546
+ globalTarget.__VOBS_HMR__ = hmrGlobal;
547
+
548
+ // packages/vobs/src/context.ts
549
+ var ownerProviders = /* @__PURE__ */ new WeakMap();
550
+ function inject(key, fallback) {
551
+ const owner = getCurrentOwner();
552
+ const value = owner ? injectFromOwner(owner, key) : void 0;
553
+ return value === void 0 ? fallback : value;
554
+ }
555
+ __name(inject, "inject");
556
+ function injectFromOwner(owner, key) {
557
+ let current = owner;
558
+ while (current) {
559
+ const providers = ownerProviders.get(current);
560
+ if (providers?.has(key)) return providers.get(key);
561
+ current = current.parent;
562
+ }
563
+ return void 0;
564
+ }
565
+ __name(injectFromOwner, "injectFromOwner");
566
+
567
+ // packages/vobs/src/app.ts
568
+ function createInjectionKey(description) {
569
+ return Symbol(description);
570
+ }
571
+ __name(createInjectionKey, "createInjectionKey");
572
+
573
+ // packages/payment/src/wechat/plugin.ts
574
+ var WECHAT_KEY = createInjectionKey("vobs.payment.wechat");
575
+ function useWechat() {
576
+ const client = inject(WECHAT_KEY);
577
+ if (!client) {
578
+ throw new Error("Vobs Payment: \u627E\u4E0D\u5230 WechatClient\uFF0C\u8BF7\u5B89\u88C5 wechatPlugin");
579
+ }
580
+ return client;
581
+ }
582
+ __name(useWechat, "useWechat");
583
+ function wechatPlugin(options) {
584
+ return {
585
+ name: "@vobs/payment/wechat",
586
+ version: "0.1.0",
587
+ install(context) {
588
+ if (!options.client && !options.config) {
589
+ throw new Error("Vobs Payment: wechatPlugin \u9700\u8981\u63D0\u4F9B config \u6216 client \u4E4B\u4E00");
590
+ }
591
+ const ownClient = !options.client;
592
+ const client = options.client ?? new WechatClient(options.config);
593
+ context.provide(WECHAT_KEY, client);
594
+ return ownClient ? () => client.dispose() : void 0;
595
+ }
596
+ };
597
+ }
598
+ __name(wechatPlugin, "wechatPlugin");
599
+
600
+ export { WECHAT_KEY, WechatApiError, WechatClient, WechatConfig, createNotifyHandler, createPayment, createRefund, useWechat, wechatPlugin };
601
+ //# sourceMappingURL=index.js.map
602
+ //# sourceMappingURL=index.js.map