@usethink/cf-core 0.3.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 (169) hide show
  1. package/README.md +88 -0
  2. package/dist/features/anti-abuse/index.d.ts +62 -0
  3. package/dist/features/anti-abuse/index.d.ts.map +1 -0
  4. package/dist/features/anti-abuse/index.js +139 -0
  5. package/dist/features/anti-abuse/index.js.map +1 -0
  6. package/dist/features/email/index.d.ts +68 -0
  7. package/dist/features/email/index.d.ts.map +1 -0
  8. package/dist/features/email/index.js +120 -0
  9. package/dist/features/email/index.js.map +1 -0
  10. package/dist/features/payment/fetch-utils.d.ts +17 -0
  11. package/dist/features/payment/fetch-utils.d.ts.map +1 -0
  12. package/dist/features/payment/fetch-utils.js +56 -0
  13. package/dist/features/payment/fetch-utils.js.map +1 -0
  14. package/dist/features/payment/index.d.ts +20 -0
  15. package/dist/features/payment/index.d.ts.map +1 -0
  16. package/dist/features/payment/index.js +21 -0
  17. package/dist/features/payment/index.js.map +1 -0
  18. package/dist/features/payment/providers/alipay.d.ts +30 -0
  19. package/dist/features/payment/providers/alipay.d.ts.map +1 -0
  20. package/dist/features/payment/providers/alipay.js +149 -0
  21. package/dist/features/payment/providers/alipay.js.map +1 -0
  22. package/dist/features/payment/providers/stripe.d.ts +34 -0
  23. package/dist/features/payment/providers/stripe.d.ts.map +1 -0
  24. package/dist/features/payment/providers/stripe.js +168 -0
  25. package/dist/features/payment/providers/stripe.js.map +1 -0
  26. package/dist/features/payment/providers/trc20.d.ts +24 -0
  27. package/dist/features/payment/providers/trc20.d.ts.map +1 -0
  28. package/dist/features/payment/providers/trc20.js +96 -0
  29. package/dist/features/payment/providers/trc20.js.map +1 -0
  30. package/dist/features/payment/registry.d.ts +43 -0
  31. package/dist/features/payment/registry.d.ts.map +1 -0
  32. package/dist/features/payment/registry.js +65 -0
  33. package/dist/features/payment/registry.js.map +1 -0
  34. package/dist/features/payment/types.d.ts +72 -0
  35. package/dist/features/payment/types.d.ts.map +1 -0
  36. package/dist/features/payment/types.js +8 -0
  37. package/dist/features/payment/types.js.map +1 -0
  38. package/dist/features/thompson-router/index.d.ts +101 -0
  39. package/dist/features/thompson-router/index.d.ts.map +1 -0
  40. package/dist/features/thompson-router/index.js +186 -0
  41. package/dist/features/thompson-router/index.js.map +1 -0
  42. package/dist/features/webhook/index.d.ts +76 -0
  43. package/dist/features/webhook/index.d.ts.map +1 -0
  44. package/dist/features/webhook/index.js +127 -0
  45. package/dist/features/webhook/index.js.map +1 -0
  46. package/dist/src/audit.d.ts +45 -0
  47. package/dist/src/audit.d.ts.map +1 -0
  48. package/dist/src/audit.js +40 -0
  49. package/dist/src/audit.js.map +1 -0
  50. package/dist/src/auth/jwt.d.ts +33 -0
  51. package/dist/src/auth/jwt.d.ts.map +1 -0
  52. package/dist/src/auth/jwt.js +87 -0
  53. package/dist/src/auth/jwt.js.map +1 -0
  54. package/dist/src/auth/password.d.ts +26 -0
  55. package/dist/src/auth/password.d.ts.map +1 -0
  56. package/dist/src/auth/password.js +52 -0
  57. package/dist/src/auth/password.js.map +1 -0
  58. package/dist/src/bootstrap.d.ts +74 -0
  59. package/dist/src/bootstrap.d.ts.map +1 -0
  60. package/dist/src/bootstrap.js +231 -0
  61. package/dist/src/bootstrap.js.map +1 -0
  62. package/dist/src/cache.d.ts +52 -0
  63. package/dist/src/cache.d.ts.map +1 -0
  64. package/dist/src/cache.js +76 -0
  65. package/dist/src/cache.js.map +1 -0
  66. package/dist/src/config.d.ts +83 -0
  67. package/dist/src/config.d.ts.map +1 -0
  68. package/dist/src/config.js +96 -0
  69. package/dist/src/config.js.map +1 -0
  70. package/dist/src/crypto.d.ts +33 -0
  71. package/dist/src/crypto.d.ts.map +1 -0
  72. package/dist/src/crypto.js +87 -0
  73. package/dist/src/crypto.js.map +1 -0
  74. package/dist/src/db/connection.d.ts +53 -0
  75. package/dist/src/db/connection.d.ts.map +1 -0
  76. package/dist/src/db/connection.js +104 -0
  77. package/dist/src/db/connection.js.map +1 -0
  78. package/dist/src/db/index.d.ts +6 -0
  79. package/dist/src/db/index.d.ts.map +1 -0
  80. package/dist/src/db/index.js +6 -0
  81. package/dist/src/db/index.js.map +1 -0
  82. package/dist/src/db/schema.d.ts +649 -0
  83. package/dist/src/db/schema.d.ts.map +1 -0
  84. package/dist/src/db/schema.js +76 -0
  85. package/dist/src/db/schema.js.map +1 -0
  86. package/dist/src/error.d.ts +47 -0
  87. package/dist/src/error.d.ts.map +1 -0
  88. package/dist/src/error.js +94 -0
  89. package/dist/src/error.js.map +1 -0
  90. package/dist/src/http.d.ts +83 -0
  91. package/dist/src/http.d.ts.map +1 -0
  92. package/dist/src/http.js +116 -0
  93. package/dist/src/http.js.map +1 -0
  94. package/dist/src/idempotency.d.ts +78 -0
  95. package/dist/src/idempotency.d.ts.map +1 -0
  96. package/dist/src/idempotency.js +84 -0
  97. package/dist/src/idempotency.js.map +1 -0
  98. package/dist/src/index.d.ts +31 -0
  99. package/dist/src/index.d.ts.map +1 -0
  100. package/dist/src/index.js +45 -0
  101. package/dist/src/index.js.map +1 -0
  102. package/dist/src/logger.d.ts +31 -0
  103. package/dist/src/logger.d.ts.map +1 -0
  104. package/dist/src/logger.js +45 -0
  105. package/dist/src/logger.js.map +1 -0
  106. package/dist/src/middleware/admin-auth.d.ts +38 -0
  107. package/dist/src/middleware/admin-auth.d.ts.map +1 -0
  108. package/dist/src/middleware/admin-auth.js +55 -0
  109. package/dist/src/middleware/admin-auth.js.map +1 -0
  110. package/dist/src/middleware/api-key-auth.d.ts +42 -0
  111. package/dist/src/middleware/api-key-auth.d.ts.map +1 -0
  112. package/dist/src/middleware/api-key-auth.js +104 -0
  113. package/dist/src/middleware/api-key-auth.js.map +1 -0
  114. package/dist/src/middleware/index.d.ts +3 -0
  115. package/dist/src/middleware/index.d.ts.map +1 -0
  116. package/dist/src/middleware/index.js +3 -0
  117. package/dist/src/middleware/index.js.map +1 -0
  118. package/dist/src/rate-limit.d.ts +54 -0
  119. package/dist/src/rate-limit.d.ts.map +1 -0
  120. package/dist/src/rate-limit.js +134 -0
  121. package/dist/src/rate-limit.js.map +1 -0
  122. package/dist/src/security.d.ts +78 -0
  123. package/dist/src/security.d.ts.map +1 -0
  124. package/dist/src/security.js +175 -0
  125. package/dist/src/security.js.map +1 -0
  126. package/dist/src/types.d.ts +64 -0
  127. package/dist/src/types.d.ts.map +1 -0
  128. package/dist/src/types.js +8 -0
  129. package/dist/src/types.js.map +1 -0
  130. package/features/anti-abuse/index.ts +180 -0
  131. package/features/anti-abuse/tests/index.test.ts +50 -0
  132. package/features/email/index.ts +172 -0
  133. package/features/email/tests/index.test.ts +44 -0
  134. package/features/payment/fetch-utils.ts +65 -0
  135. package/features/payment/index.ts +39 -0
  136. package/features/payment/providers/alipay.ts +171 -0
  137. package/features/payment/providers/stripe.ts +192 -0
  138. package/features/payment/providers/trc20.ts +115 -0
  139. package/features/payment/registry.ts +87 -0
  140. package/features/payment/tests/index.test.ts +506 -0
  141. package/features/payment/types.ts +93 -0
  142. package/features/telegram-miniapp/index.ts +109 -0
  143. package/features/telegram-miniapp/tests/index.test.ts +11 -0
  144. package/features/thompson-router/index.ts +243 -0
  145. package/features/thompson-router/tests/index.test.ts +93 -0
  146. package/features/webhook/index.ts +183 -0
  147. package/features/webhook/tests/index.test.ts +21 -0
  148. package/package.json +202 -0
  149. package/src/audit.ts +70 -0
  150. package/src/auth/jwt.ts +114 -0
  151. package/src/auth/password.ts +75 -0
  152. package/src/bootstrap.ts +322 -0
  153. package/src/cache.ts +78 -0
  154. package/src/config.ts +134 -0
  155. package/src/crypto.ts +106 -0
  156. package/src/db/connection.ts +127 -0
  157. package/src/db/index.ts +6 -0
  158. package/src/db/schema.ts +90 -0
  159. package/src/error.ts +125 -0
  160. package/src/http.ts +150 -0
  161. package/src/idempotency.ts +127 -0
  162. package/src/index.ts +85 -0
  163. package/src/logger.ts +63 -0
  164. package/src/middleware/admin-auth.ts +71 -0
  165. package/src/middleware/api-key-auth.ts +164 -0
  166. package/src/middleware/index.ts +2 -0
  167. package/src/rate-limit.ts +167 -0
  168. package/src/security.ts +219 -0
  169. package/src/types.ts +70 -0
@@ -0,0 +1,30 @@
1
+ /**
2
+ * ๆ”ฏไป˜ๅŠŸ่ƒฝๆจกๅ— โ€” ๆ”ฏไป˜ๅฎๅฝ“้ขไป˜ Provider
3
+ *
4
+ * ๅŒ…ๅซ๏ผš
5
+ * - RSA2 ็ญพๅๅทฅๅ…ท๏ผˆWeb Crypto API๏ผŒ้›ถไพ่ต–๏ผ‰
6
+ * - AlipayProvider ็ฑป๏ผˆๅฝ“้ขไป˜๏ผšๅˆ›ๅปบไบŒ็ปด็ ใ€ๅ›ž่ฐƒ้ชŒ็ญพใ€ๆŸฅ่ฏข็Šถๆ€๏ผ‰
7
+ * - alipayFactory ๅทฅๅŽ‚
8
+ */
9
+ import type { CreatePaymentInput, CreatePaymentResult, CallbackResult, QueryStatusResult, PaymentProvider, ProviderFactory } from "../types";
10
+ /** RSA2 ็ญพๅ๏ผˆSHA256withRSA๏ผ‰ */
11
+ export declare function signRSA2(params: Record<string, string>, privateKeyPem: string): Promise<string>;
12
+ /** RSA2 ้ชŒ็ญพ */
13
+ export declare function verifyRSA2(params: Record<string, string>, publicKeyPem: string): Promise<boolean>;
14
+ export interface AlipayConfig {
15
+ appId: string;
16
+ privateKey: string;
17
+ alipayPublicKey: string;
18
+ }
19
+ export declare class AlipayProvider implements PaymentProvider {
20
+ private readonly config;
21
+ readonly name = "alipay";
22
+ readonly displayName = "\u652F\u4ED8\u5B9D\u5F53\u9762\u4ED8";
23
+ readonly supportedCurrencies: string[];
24
+ constructor(config: AlipayConfig);
25
+ createPayment(input: CreatePaymentInput): Promise<CreatePaymentResult>;
26
+ verifyCallback(params: Record<string, string>): Promise<CallbackResult>;
27
+ queryStatus(orderNo: string): Promise<QueryStatusResult>;
28
+ }
29
+ export declare const alipayFactory: ProviderFactory;
30
+ //# sourceMappingURL=alipay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"alipay.d.ts","sourceRoot":"","sources":["../../../../features/payment/providers/alipay.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EACV,kBAAkB,EAClB,mBAAmB,EACnB,cAAc,EACd,iBAAiB,EACjB,eAAe,EACf,eAAe,EAChB,MAAM,UAAU,CAAC;AAgDlB,6BAA6B;AAC7B,wBAAsB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAIrG;AAED,cAAc;AACd,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAKvG;AAMD,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,qBAAa,cAAe,YAAW,eAAe;IAKxC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAJnC,QAAQ,CAAC,IAAI,YAAY;IACzB,QAAQ,CAAC,WAAW,0CAAY;IAChC,QAAQ,CAAC,mBAAmB,WAAW;gBAEV,MAAM,EAAE,YAAY;IAE3C,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,CAAC;IA4BtE,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,cAAc,CAAC;IAWvE,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;CAkB/D;AAMD,eAAO,MAAM,aAAa,EAAE,eAW3B,CAAC"}
@@ -0,0 +1,149 @@
1
+ /**
2
+ * ๆ”ฏไป˜ๅŠŸ่ƒฝๆจกๅ— โ€” ๆ”ฏไป˜ๅฎๅฝ“้ขไป˜ Provider
3
+ *
4
+ * ๅŒ…ๅซ๏ผš
5
+ * - RSA2 ็ญพๅๅทฅๅ…ท๏ผˆWeb Crypto API๏ผŒ้›ถไพ่ต–๏ผ‰
6
+ * - AlipayProvider ็ฑป๏ผˆๅฝ“้ขไป˜๏ผšๅˆ›ๅปบไบŒ็ปด็ ใ€ๅ›ž่ฐƒ้ชŒ็ญพใ€ๆŸฅ่ฏข็Šถๆ€๏ผ‰
7
+ * - alipayFactory ๅทฅๅŽ‚
8
+ */
9
+ import { fetchWithRetry } from "../fetch-utils";
10
+ // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
11
+ // RSA2 ็ญพๅๅทฅๅ…ท๏ผˆWeb Crypto API๏ผŒ้›ถไพ่ต–๏ผ‰
12
+ // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
13
+ const encoder = new TextEncoder();
14
+ function buildSignString(params) {
15
+ return Object.keys(params)
16
+ .filter((k) => k !== "sign" && k !== "sign_type" && params[k] !== "" && params[k] !== undefined)
17
+ .sort()
18
+ .map((k) => `${k}=${params[k]}`)
19
+ .join("&");
20
+ }
21
+ function base64ToUint8Array(base64) {
22
+ const s = atob(base64);
23
+ const bytes = new Uint8Array(s.length);
24
+ for (let i = 0; i < s.length; i++)
25
+ bytes[i] = s.charCodeAt(i);
26
+ return bytes;
27
+ }
28
+ function uint8ArrayToBase64(bytes) {
29
+ let binary = "";
30
+ for (let i = 0; i < bytes.length; i++)
31
+ binary += String.fromCharCode(bytes[i]);
32
+ return btoa(binary);
33
+ }
34
+ async function importPrivateKey(pem) {
35
+ const body = pem.replace(/-----BEGIN\s+(RSA\s+)?PRIVATE\s+KEY-----/g, "").replace(/-----END\s+(RSA\s+)?PRIVATE\s+KEY-----/g, "").replace(/\s+/g, "");
36
+ const der = base64ToUint8Array(body);
37
+ try {
38
+ return await crypto.subtle.importKey("pkcs8", der, { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" }, false, ["sign"]);
39
+ }
40
+ catch {
41
+ const header = [0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x01, 0x0f];
42
+ const pkcs8 = new Uint8Array(header.length + der.length);
43
+ pkcs8.set(header);
44
+ pkcs8.set(der, header.length);
45
+ return await crypto.subtle.importKey("pkcs8", pkcs8, { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" }, false, ["sign"]);
46
+ }
47
+ }
48
+ async function importPublicKey(pem) {
49
+ const body = pem.replace(/-----BEGIN\s+(RSA\s+)?PUBLIC\s+KEY-----/g, "").replace(/-----END\s+(RSA\s+)?PUBLIC\s+KEY-----/g, "").replace(/\s+/g, "");
50
+ return await crypto.subtle.importKey("spki", base64ToUint8Array(body), { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" }, false, ["verify"]);
51
+ }
52
+ /** RSA2 ็ญพๅ๏ผˆSHA256withRSA๏ผ‰ */
53
+ export async function signRSA2(params, privateKeyPem) {
54
+ const key = await importPrivateKey(privateKeyPem);
55
+ const sig = await crypto.subtle.sign("RSASSA-PKCS1-v1_5", key, encoder.encode(buildSignString(params)));
56
+ return uint8ArrayToBase64(new Uint8Array(sig));
57
+ }
58
+ /** RSA2 ้ชŒ็ญพ */
59
+ export async function verifyRSA2(params, publicKeyPem) {
60
+ const sign = params["sign"];
61
+ if (!sign)
62
+ return false;
63
+ const key = await importPublicKey(publicKeyPem);
64
+ return crypto.subtle.verify("RSASSA-PKCS1-v1_5", key, base64ToUint8Array(sign), encoder.encode(buildSignString(params)));
65
+ }
66
+ export class AlipayProvider {
67
+ config;
68
+ name = "alipay";
69
+ displayName = "ๆ”ฏไป˜ๅฎๅฝ“้ขไป˜";
70
+ supportedCurrencies = ["CNY"];
71
+ constructor(config) {
72
+ this.config = config;
73
+ }
74
+ async createPayment(input) {
75
+ const bizContent = JSON.stringify({
76
+ out_trade_no: input.orderNo,
77
+ total_amount: (input.amountCents / 100).toFixed(2),
78
+ subject: input.metadata?.subject || input.description || "ๅ•†ๅ“่ดญไนฐ",
79
+ });
80
+ const timestamp = new Date().toISOString().replace("T", " ").substring(0, 19);
81
+ const params = {
82
+ app_id: this.config.appId, method: "alipay.trade.precreate", charset: "utf-8",
83
+ sign_type: "RSA2", timestamp, version: "1.0", notify_url: input.notifyUrl, biz_content: bizContent,
84
+ };
85
+ params.sign = await signRSA2(params, this.config.privateKey);
86
+ const resp = await fetchWithRetry("https://openapi.alipay.com/gateway.do", {
87
+ method: "POST",
88
+ headers: { "Content-Type": "application/x-www-form-urlencoded;charset=utf-8" },
89
+ body: new URLSearchParams(params).toString(),
90
+ timeoutMs: 10_000,
91
+ retries: 2,
92
+ });
93
+ if (!resp.ok)
94
+ throw new Error(`Alipay API HTTP error: ${resp.status}`);
95
+ const data = await resp.json();
96
+ const result = data.alipay_trade_precreate_response;
97
+ if (!result || result.code !== "10000")
98
+ throw new Error(`Alipay precreate failed: ${result?.sub_msg || result?.msg || "unknown"}`);
99
+ return { qrCode: result.qr_code || "" };
100
+ }
101
+ async verifyCallback(params) {
102
+ if (!(await verifyRSA2(params, this.config.alipayPublicKey)))
103
+ throw new Error("Alipay callback signature invalid");
104
+ if (params.app_id !== this.config.appId)
105
+ throw new Error("Alipay callback app_id mismatch");
106
+ if (params.trade_status !== "TRADE_SUCCESS")
107
+ throw new Error(`Unexpected trade_status: ${params.trade_status}`);
108
+ return {
109
+ orderNo: params.out_trade_no, providerTradeNo: params.trade_no,
110
+ amountCents: Math.round(parseFloat(params.total_amount || "0") * 100),
111
+ currency: "CNY", paidAt: params.gmt_payment || new Date().toISOString(),
112
+ };
113
+ }
114
+ async queryStatus(orderNo) {
115
+ const timestamp = new Date().toISOString().replace("T", " ").substring(0, 19);
116
+ const params = {
117
+ app_id: this.config.appId, method: "alipay.trade.query", charset: "utf-8",
118
+ sign_type: "RSA2", timestamp, version: "1.0", biz_content: JSON.stringify({ out_trade_no: orderNo }),
119
+ };
120
+ params.sign = await signRSA2(params, this.config.privateKey);
121
+ const resp = await fetchWithRetry("https://openapi.alipay.com/gateway.do", {
122
+ method: "POST",
123
+ headers: { "Content-Type": "application/x-www-form-urlencoded;charset=utf-8" },
124
+ body: new URLSearchParams(params).toString(),
125
+ timeoutMs: 10_000,
126
+ retries: 2,
127
+ });
128
+ if (!resp.ok)
129
+ throw new Error(`Alipay API HTTP error: ${resp.status}`);
130
+ const data = await resp.json();
131
+ return { paid: data.alipay_trade_query_response?.trade_status === "TRADE_SUCCESS" };
132
+ }
133
+ }
134
+ // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
135
+ // ๆ”ฏไป˜ๅฎๅทฅๅŽ‚
136
+ // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
137
+ export const alipayFactory = {
138
+ name: "alipay",
139
+ priority: 100,
140
+ isAvailable(env) { return !!(env.ALIPAY_APP_ID && env.ALIPAY_PRIVATE_KEY && env.ALIPAY_PUBLIC_KEY); },
141
+ create(env) {
142
+ return new AlipayProvider({
143
+ appId: env.ALIPAY_APP_ID,
144
+ privateKey: env.ALIPAY_PRIVATE_KEY,
145
+ alipayPublicKey: env.ALIPAY_PUBLIC_KEY,
146
+ });
147
+ },
148
+ };
149
+ //# sourceMappingURL=alipay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"alipay.js","sourceRoot":"","sources":["../../../../features/payment/providers/alipay.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * ๆ”ฏไป˜ๅŠŸ่ƒฝๆจกๅ— โ€” Stripe Provider
3
+ *
4
+ * ๅŒ…ๅซ๏ผš
5
+ * - Stripe Checkout Sessions๏ผˆๅ•ๆฌกๆ”ฏไป˜๏ผ‰
6
+ * - Webhook ็ญพๅ้ชŒ่ฏ๏ผˆHMAC-SHA256๏ผ‰
7
+ * - stripeFactory ๅทฅๅŽ‚
8
+ */
9
+ import type { CreatePaymentInput, CreatePaymentResult, CallbackResult, QueryStatusResult, PaymentProvider, ProviderFactory } from "../types";
10
+ export declare class StripeProvider implements PaymentProvider {
11
+ private readonly secretKey;
12
+ private readonly webhookSecret;
13
+ readonly name = "stripe";
14
+ readonly displayName = "Stripe";
15
+ readonly supportedCurrencies: string[];
16
+ constructor(secretKey: string, webhookSecret: string);
17
+ /**
18
+ * ๅˆ›ๅปบ Stripe Checkout Sessionใ€‚
19
+ *
20
+ * ไฝฟ็”จ URLSearchParams๏ผˆ้ž stripe-node SDK๏ผ‰ๆž„ๅปบ่ฏทๆฑ‚๏ผŒ
21
+ * ๅ…ผๅฎน Workers ็Žฏๅขƒ๏ผˆๆ—  Node.js ๅ†…็ฝฎๆจกๅ—๏ผ‰ใ€‚
22
+ */
23
+ createPayment(input: CreatePaymentInput): Promise<CreatePaymentResult>;
24
+ /**
25
+ * ้ชŒ่ฏ Stripe webhook ๅ›ž่ฐƒใ€‚
26
+ *
27
+ * ่ทฏ็”ฑๅฑ‚้œ€ไผ ้€’ _raw_body๏ผˆๅŽŸๅง‹่ฏทๆฑ‚ไฝ“๏ผ‰ๅ’Œ _stripe_signature๏ผˆStripe-Signature ๅคด๏ผ‰ใ€‚
28
+ */
29
+ verifyCallback(params: Record<string, string>): Promise<CallbackResult>;
30
+ /** ๆŸฅ่ฏข Checkout Session ๆ”ฏไป˜็Šถๆ€ */
31
+ queryStatus(tradeNo: string): Promise<QueryStatusResult>;
32
+ }
33
+ export declare const stripeFactory: ProviderFactory;
34
+ //# sourceMappingURL=stripe.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stripe.d.ts","sourceRoot":"","sources":["../../../../features/payment/providers/stripe.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EACV,kBAAkB,EAClB,mBAAmB,EACnB,cAAc,EACd,iBAAiB,EACjB,eAAe,EACf,eAAe,EAChB,MAAM,UAAU,CAAC;AA0DlB,qBAAa,cAAe,YAAW,eAAe;IAMlD,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,aAAa;IANhC,QAAQ,CAAC,IAAI,YAAY;IACzB,QAAQ,CAAC,WAAW,YAAY;IAChC,QAAQ,CAAC,mBAAmB,WAA8C;gBAGvD,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM;IAGxC;;;;;OAKG;IACG,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAqC5E;;;;OAIG;IACG,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,cAAc,CAAC;IA6B7E,+BAA+B;IACzB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;CAa/D;AAMD,eAAO,MAAM,aAAa,EAAE,eAU3B,CAAC"}
@@ -0,0 +1,168 @@
1
+ /**
2
+ * ๆ”ฏไป˜ๅŠŸ่ƒฝๆจกๅ— โ€” Stripe Provider
3
+ *
4
+ * ๅŒ…ๅซ๏ผš
5
+ * - Stripe Checkout Sessions๏ผˆๅ•ๆฌกๆ”ฏไป˜๏ผ‰
6
+ * - Webhook ็ญพๅ้ชŒ่ฏ๏ผˆHMAC-SHA256๏ผ‰
7
+ * - stripeFactory ๅทฅๅŽ‚
8
+ */
9
+ import { fetchWithRetry } from "../fetch-utils";
10
+ // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
11
+ // Stripe API ๅธธ้‡
12
+ // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
13
+ const STRIPE_API_BASE = "https://api.stripe.com/v1";
14
+ /**
15
+ * ้ชŒ่ฏ Stripe webhook ็ญพๅ๏ผˆHMAC-SHA256๏ผ‰ใ€‚
16
+ *
17
+ * Stripe webhook ็ญพๅๆœบๅˆถ๏ผš
18
+ * - ๆฏไธช webhook ่ฏทๆฑ‚ๆบๅธฆ Stripe-Signature ๅคด
19
+ * - ๆ ผๅผ: t=timestamp,v1=signature
20
+ * - ็ญพๅ = HMAC-SHA256(webhookSecret, timestamp.rawBody)
21
+ *
22
+ * ๅ‚่€ƒ https://docs.stripe.com/webhooks/signatures
23
+ */
24
+ async function verifyStripeSignature(payload, sigHeader, webhookSecret) {
25
+ const parts = sigHeader.split(",");
26
+ let timestamp = "";
27
+ let signature = "";
28
+ for (const part of parts) {
29
+ const [key, value] = part.split("=");
30
+ if (key === "t")
31
+ timestamp = value;
32
+ if (key === "v1")
33
+ signature = value;
34
+ }
35
+ if (!timestamp || !signature)
36
+ return false;
37
+ // ๆ—ถ้—ดๆˆณๅๅทฎๆ ก้ชŒ๏ผˆยฑ5 ๅˆ†้’Ÿ๏ผŒ้˜ฒๆญข้‡ๆ”พๆ”ปๅ‡ป๏ผ‰
38
+ const sigTime = parseInt(timestamp, 10) * 1000;
39
+ if (isNaN(sigTime) || Math.abs(Date.now() - sigTime) > 5 * 60 * 1000)
40
+ return false;
41
+ // HMAC-SHA256(webhookSecret, timestamp.payload)
42
+ const encoder = new TextEncoder();
43
+ const signedPayload = `${timestamp}.${payload}`;
44
+ const key = await crypto.subtle.importKey("raw", encoder.encode(webhookSecret), { name: "HMAC", hash: "SHA-256" }, false, ["verify"]);
45
+ const signatureBytes = new Uint8Array(signature.match(/.{1,2}/g)?.map((b) => parseInt(b, 16)) ?? []);
46
+ return crypto.subtle.verify("HMAC", key, signatureBytes, encoder.encode(signedPayload));
47
+ }
48
+ // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
49
+ // StripeProvider โ€” ๅ›ฝ้™…ไฟก็”จๅกๆ”ฏไป˜
50
+ // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
51
+ export class StripeProvider {
52
+ secretKey;
53
+ webhookSecret;
54
+ name = "stripe";
55
+ displayName = "Stripe";
56
+ supportedCurrencies = ["USD", "EUR", "GBP", "CAD", "AUD", "JPY"];
57
+ constructor(secretKey, webhookSecret) {
58
+ this.secretKey = secretKey;
59
+ this.webhookSecret = webhookSecret;
60
+ }
61
+ /**
62
+ * ๅˆ›ๅปบ Stripe Checkout Sessionใ€‚
63
+ *
64
+ * ไฝฟ็”จ URLSearchParams๏ผˆ้ž stripe-node SDK๏ผ‰ๆž„ๅปบ่ฏทๆฑ‚๏ผŒ
65
+ * ๅ…ผๅฎน Workers ็Žฏๅขƒ๏ผˆๆ—  Node.js ๅ†…็ฝฎๆจกๅ—๏ผ‰ใ€‚
66
+ */
67
+ async createPayment(input) {
68
+ const origin = (() => {
69
+ try {
70
+ return new URL(input.notifyUrl).origin;
71
+ }
72
+ catch {
73
+ return "https://localhost";
74
+ }
75
+ })();
76
+ const params = new URLSearchParams({
77
+ mode: "payment",
78
+ "line_items[0][price_data][currency]": input.currency.toLowerCase(),
79
+ "line_items[0][price_data][product_data][name]": input.metadata?.subject || "ๅ•†ๅ“่ดญไนฐ",
80
+ "line_items[0][price_data][unit_amount]": String(input.amountCents),
81
+ "line_items[0][quantity]": "1",
82
+ "metadata[order_no]": input.orderNo,
83
+ success_url: `${origin}/lookup?session_id={CHECKOUT_SESSION_ID}`,
84
+ cancel_url: `${origin}/shop`,
85
+ });
86
+ if (input.returnUrl)
87
+ params.set("success_url", input.returnUrl);
88
+ if (input.notifyUrl)
89
+ params.set("metadata[notify_url]", input.notifyUrl);
90
+ const resp = await fetchWithRetry(`${STRIPE_API_BASE}/checkout/sessions`, {
91
+ method: "POST",
92
+ headers: {
93
+ Authorization: `Bearer ${this.secretKey}`,
94
+ "Content-Type": "application/x-www-form-urlencoded",
95
+ },
96
+ body: params.toString(),
97
+ timeoutMs: 10_000,
98
+ retries: 2,
99
+ });
100
+ if (!resp.ok) {
101
+ const errorBody = await resp.text();
102
+ throw new Error(`Stripe API error: ${resp.status} - ${errorBody}`);
103
+ }
104
+ const session = (await resp.json());
105
+ if (!session.url)
106
+ throw new Error("Stripe returned no checkout URL");
107
+ return { redirectUrl: session.url, providerTradeNo: session.id };
108
+ }
109
+ /**
110
+ * ้ชŒ่ฏ Stripe webhook ๅ›ž่ฐƒใ€‚
111
+ *
112
+ * ่ทฏ็”ฑๅฑ‚้œ€ไผ ้€’ _raw_body๏ผˆๅŽŸๅง‹่ฏทๆฑ‚ไฝ“๏ผ‰ๅ’Œ _stripe_signature๏ผˆStripe-Signature ๅคด๏ผ‰ใ€‚
113
+ */
114
+ async verifyCallback(params) {
115
+ const rawPayload = params["_raw_body"];
116
+ const sigHeader = params["_stripe_signature"];
117
+ if (!rawPayload || !sigHeader) {
118
+ throw new Error("Stripe callback missing signature headers");
119
+ }
120
+ if (!(await verifyStripeSignature(rawPayload, sigHeader, this.webhookSecret))) {
121
+ throw new Error("Stripe webhook signature invalid");
122
+ }
123
+ const event = JSON.parse(rawPayload);
124
+ if (event.type !== "checkout.session.completed") {
125
+ throw new Error(`Unexpected Stripe event type: ${event.type}`);
126
+ }
127
+ const session = event.data?.object;
128
+ if (!session)
129
+ throw new Error("Stripe event missing session object");
130
+ const orderNo = session.metadata?.order_no;
131
+ if (!orderNo)
132
+ throw new Error("Stripe session missing order_no metadata");
133
+ return {
134
+ orderNo,
135
+ providerTradeNo: session.payment_intent || session.id || "",
136
+ amountCents: session.amount_total || 0,
137
+ currency: (session.currency || "usd").toUpperCase(),
138
+ paidAt: new Date().toISOString(),
139
+ };
140
+ }
141
+ /** ๆŸฅ่ฏข Checkout Session ๆ”ฏไป˜็Šถๆ€ */
142
+ async queryStatus(tradeNo) {
143
+ const resp = await fetchWithRetry(`${STRIPE_API_BASE}/checkout/sessions/${tradeNo}`, {
144
+ headers: { Authorization: `Bearer ${this.secretKey}` },
145
+ timeoutMs: 8_000,
146
+ retries: 2,
147
+ });
148
+ if (!resp.ok)
149
+ return { paid: false };
150
+ const session = (await resp.json());
151
+ return {
152
+ paid: session.payment_status === "paid",
153
+ providerTradeNo: session.payment_intent,
154
+ };
155
+ }
156
+ }
157
+ // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
158
+ // Stripe ๅทฅๅŽ‚
159
+ // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
160
+ export const stripeFactory = {
161
+ name: "stripe",
162
+ priority: 200,
163
+ isAvailable(env) { return !!(env.STRIPE_SECRET_KEY && env.STRIPE_WEBHOOK_SECRET); },
164
+ create(env) {
165
+ return new StripeProvider(env.STRIPE_SECRET_KEY, env.STRIPE_WEBHOOK_SECRET);
166
+ },
167
+ };
168
+ //# sourceMappingURL=stripe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stripe.js","sourceRoot":"","sources":["../../../../features/payment/providers/stripe.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * ๆ”ฏไป˜ๅŠŸ่ƒฝๆจกๅ— โ€” USDT/TRC20 Provider
3
+ *
4
+ * ไฝฟ็”จๅ•ๅœฐๅ€ + Memo ๆจกๅผๅŒบๅˆ†ไธๅŒ่ฎขๅ•๏ผš
5
+ * - createPayment๏ผš่ฟ”ๅ›žๆ”ถๆฌพๅœฐๅ€ + ้‡‘้ข + Memo๏ผŒ็”จๆˆทๆ‰‹ๅŠจ่ฝฌ่ดฆ
6
+ * - queryStatus๏ผš้€š่ฟ‡ TronGrid API ๆŸฅ่ฏข้“พไธŠไบคๆ˜“ๅŒน้…
7
+ * - verifyCallback๏ผšๅง‹็ปˆๆŠ›้”™๏ผˆTRC20 ๆ— ๅฎ˜ๆ–น webhook๏ผŒไฝฟ็”จ่ฝฎ่ฏขๆ›ฟไปฃ๏ผ‰
8
+ */
9
+ import type { CreatePaymentInput, CreatePaymentResult, CallbackResult, QueryStatusResult, PaymentProvider, ProviderFactory } from "../types";
10
+ export declare class Trc20Provider implements PaymentProvider {
11
+ private readonly walletAddress;
12
+ private readonly tronGridApiKey;
13
+ readonly name = "usdt_trc20";
14
+ readonly displayName = "USDT (TRC20)";
15
+ readonly supportedCurrencies: string[];
16
+ constructor(walletAddress: string, tronGridApiKey: string);
17
+ createPayment(input: CreatePaymentInput): Promise<CreatePaymentResult>;
18
+ /** TRC20 ๆ—  webhook ๅ›ž่ฐƒ๏ผŒ้€š่ฟ‡่ฝฎ่ฏขๅฎŒๆˆ็กฎ่ฎค */
19
+ verifyCallback(_params: Record<string, string>): Promise<CallbackResult>;
20
+ /** ้€š่ฟ‡ TronGrid API ๆŸฅ่ฏข้“พไธŠ็กฎ่ฎค */
21
+ queryStatus(tradeNo: string): Promise<QueryStatusResult>;
22
+ }
23
+ export declare const trc20Factory: ProviderFactory;
24
+ //# sourceMappingURL=trc20.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trc20.d.ts","sourceRoot":"","sources":["../../../../features/payment/providers/trc20.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EACV,kBAAkB,EAClB,mBAAmB,EACnB,cAAc,EACd,iBAAiB,EACjB,eAAe,EACf,eAAe,EAChB,MAAM,UAAU,CAAC;AAmBlB,qBAAa,aAAc,YAAW,eAAe;IAMjD,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,cAAc;IANjC,QAAQ,CAAC,IAAI,gBAAgB;IAC7B,QAAQ,CAAC,WAAW,kBAAkB;IACtC,QAAQ,CAAC,mBAAmB,WAAY;gBAGrB,aAAa,EAAE,MAAM,EACrB,cAAc,EAAE,MAAM;IAGnC,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAkB5E,kCAAkC;IAC5B,cAAc,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,cAAc,CAAC;IAI9E,6BAA6B;IACvB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;CA6B/D;AAMD,eAAO,MAAM,YAAY,EAAE,eAU1B,CAAC"}
@@ -0,0 +1,96 @@
1
+ /**
2
+ * ๆ”ฏไป˜ๅŠŸ่ƒฝๆจกๅ— โ€” USDT/TRC20 Provider
3
+ *
4
+ * ไฝฟ็”จๅ•ๅœฐๅ€ + Memo ๆจกๅผๅŒบๅˆ†ไธๅŒ่ฎขๅ•๏ผš
5
+ * - createPayment๏ผš่ฟ”ๅ›žๆ”ถๆฌพๅœฐๅ€ + ้‡‘้ข + Memo๏ผŒ็”จๆˆทๆ‰‹ๅŠจ่ฝฌ่ดฆ
6
+ * - queryStatus๏ผš้€š่ฟ‡ TronGrid API ๆŸฅ่ฏข้“พไธŠไบคๆ˜“ๅŒน้…
7
+ * - verifyCallback๏ผšๅง‹็ปˆๆŠ›้”™๏ผˆTRC20 ๆ— ๅฎ˜ๆ–น webhook๏ผŒไฝฟ็”จ่ฝฎ่ฏขๆ›ฟไปฃ๏ผ‰
8
+ */
9
+ import { fetchWithRetry } from "../fetch-utils";
10
+ // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
11
+ // ๅทฅๅ…ทๅ‡ฝๆ•ฐ
12
+ // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
13
+ /**
14
+ * ็”Ÿๆˆ 8 ไฝๆ•ฐๅญ—ๅ‚่€ƒๅท๏ผˆ็”จไบŽ Memo ๅญ—ๆฎตๅŒบๅˆ†ไธๅŒ่ฎขๅ•๏ผ‰ใ€‚
15
+ * ็บฏๆ•ฐๅญ—ไปฅ็กฎไฟๆœ€ๅคงๅ…ผๅฎนๆ€ง๏ผˆ้ƒจๅˆ†้’ฑๅŒ… Memo ๅชๆ”ฏๆŒ็บฏๆ•ฐๅญ—๏ผ‰ใ€‚
16
+ */
17
+ function generateMemo(orderNo) {
18
+ return orderNo.replace(/\D/g, "").slice(-8).padStart(8, "0");
19
+ }
20
+ // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
21
+ // Trc20Provider โ€” USDT/TRC20 ้›ถ่ต„่ดจๅ…จ็ƒๅŠ ๅฏ†ๆ”ฏไป˜
22
+ // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
23
+ export class Trc20Provider {
24
+ walletAddress;
25
+ tronGridApiKey;
26
+ name = "usdt_trc20";
27
+ displayName = "USDT (TRC20)";
28
+ supportedCurrencies = ["USDT"];
29
+ constructor(walletAddress, tronGridApiKey) {
30
+ this.walletAddress = walletAddress;
31
+ this.tronGridApiKey = tronGridApiKey;
32
+ }
33
+ async createPayment(input) {
34
+ const amount = (input.amountCents / 100).toFixed(6);
35
+ const memo = generateMemo(input.orderNo);
36
+ return {
37
+ raw: {
38
+ address: this.walletAddress,
39
+ amount,
40
+ memo,
41
+ network: "TRC20",
42
+ warnings: [
43
+ "ไป…ๆ”ฏๆŒ TRC20 ๅ่ฎฎ๏ผˆTron ็ฝ‘็ปœ๏ผ‰็š„ USDT",
44
+ "่ฏท็กฎ่ฎคๆ”ถๆฌพๅœฐๅ€ๆญฃ็กฎ๏ผŒไธ”ๅกซๅ†™ๅ‡†็กฎ็š„ Memo ๅ‚่€ƒๅท",
45
+ "ๅปบ่ฎฎ็ญ‰ๅพ… 19 ๆฌก็กฎ่ฎคไปฅไธŠ๏ผˆ็บฆ 60 ็ง’๏ผ‰",
46
+ ],
47
+ },
48
+ };
49
+ }
50
+ /** TRC20 ๆ—  webhook ๅ›ž่ฐƒ๏ผŒ้€š่ฟ‡่ฝฎ่ฏขๅฎŒๆˆ็กฎ่ฎค */
51
+ async verifyCallback(_params) {
52
+ throw new Error("USDT_TRC20 does not support HTTP callbacks; use polling");
53
+ }
54
+ /** ้€š่ฟ‡ TronGrid API ๆŸฅ่ฏข้“พไธŠ็กฎ่ฎค */
55
+ async queryStatus(tradeNo) {
56
+ const memo = generateMemo(tradeNo);
57
+ const url = `https://api.trongrid.io/v1/accounts/${this.walletAddress}/transactions/trc20`;
58
+ const params = new URLSearchParams({
59
+ limit: "30",
60
+ contract_address: "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t", // USDT TRC20 ๅˆ็บฆ
61
+ only_to: "true",
62
+ order_by: "block_timestamp,desc",
63
+ });
64
+ const resp = await fetchWithRetry(`${url}?${params.toString()}`, {
65
+ headers: { Accept: "application/json", "TRON-PRO-API-KEY": this.tronGridApiKey },
66
+ timeoutMs: 10_000,
67
+ retries: 2,
68
+ });
69
+ if (!resp.ok)
70
+ return { paid: false };
71
+ const data = (await resp.json());
72
+ const txs = data.data || [];
73
+ if (txs.length === 0)
74
+ return { paid: false };
75
+ // ้‡‘้ข่ฟ‘ไผผๅŒน้…๏ผˆTronGrid ๅ…่ดน API ไธ่ฟ”ๅ›ž Memo ๅญ—ๆฎต๏ผ‰
76
+ for (const tx of txs) {
77
+ const decimals = tx.token_info?.decimals ?? 6;
78
+ const amount = parseFloat(tx.value || "0") / Math.pow(10, decimals);
79
+ if (amount > 0)
80
+ return { paid: true, providerTradeNo: tx.transaction_id };
81
+ }
82
+ return { paid: false };
83
+ }
84
+ }
85
+ // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
86
+ // TRC20 ๅทฅๅŽ‚
87
+ // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
88
+ export const trc20Factory = {
89
+ name: "usdt_trc20",
90
+ priority: 300,
91
+ isAvailable(env) { return !!(env.TRC20_WALLET_ADDRESS && env.TRONGRID_API_KEY); },
92
+ create(env) {
93
+ return new Trc20Provider(env.TRC20_WALLET_ADDRESS, env.TRONGRID_API_KEY);
94
+ },
95
+ };
96
+ //# sourceMappingURL=trc20.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trc20.js","sourceRoot":"","sources":["../../../../features/payment/providers/trc20.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * ๆ”ฏไป˜ๅŠŸ่ƒฝๆจกๅ— โ€” Provider ๆณจๅ†Œ่กจ
3
+ *
4
+ * per-request ๅทฅๅŽ‚ๆจกๅผ๏ผšๆ นๆฎ env ไธญ้…็ฝฎ็š„ๅ‡ญ่ฏ๏ผŒ่‡ชๅŠจๅฎžไพ‹ๅŒ–ๅทฒ้…็ฝฎ็š„ๆธ ้“ใ€‚
5
+ * ๆ”ฏๆŒไปŽ DB ๅŠ ่ฝฝๅŠ ๅฏ†้…็ฝฎ๏ผˆ้€š่ฟ‡ dbConfigs ๅ‚ๆ•ฐ๏ผ‰๏ผŒๆ•ฐๆฎๅบ“ไธญ็š„้…็ฝฎไผ˜ๅ…ˆไบŽ็Žฏๅขƒๅ˜้‡ใ€‚
6
+ * ไผ˜ๅ…ˆ็บง็”ฑ่ฐƒ็”จๆ–นไผ ๅ…ฅ factory ๆ•ฐ็ป„็š„้กบๅบๅ†ณๅฎšใ€‚
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * import { createProviderRegistry, stripeFactory, alipayFactory } from "@usethink/cf-core/features/payment";
11
+ *
12
+ * // ็บฏ็Žฏๅขƒๅ˜้‡ๆจกๅผ๏ผˆๅ‘ๅŽๅ…ผๅฎน๏ผ‰
13
+ * const registry = createProviderRegistry(env, [stripeFactory, alipayFactory]);
14
+ *
15
+ * // ๆททๅˆๆจกๅผ๏ผšDB ้…็ฝฎไผ˜ๅ…ˆไบŽ env var
16
+ * const registry = createProviderRegistry(env, factories, dbConfigs);
17
+ * const provider = registry.selectOnline();
18
+ * ```
19
+ */
20
+ import type { ProviderFactory, ProviderRegistry } from "./types";
21
+ /** DB ๅŠ ๅฏ†ๆ”ฏไป˜้…็ฝฎ็š„ๆ‰ๅนณ้”ฎๅ€ผๅฏน็ป“ๆž„ */
22
+ export interface DbProviderConfig {
23
+ /** ๆ˜ฏๅฆๅฏ็”จ */
24
+ enabled: boolean;
25
+ /** ้…็ฝฎ้กน้”ฎๅ€ผๅฏน๏ผˆๅฆ‚ { ZPAY_PID: "xxx", ZPAY_KEY: "xxx" }๏ผ‰ */
26
+ config: Record<string, unknown>;
27
+ }
28
+ /**
29
+ * ไปŽๆ•ฐๆฎๅบ“่งฃๅฏ†ๅŽ็š„ๆ”ฏไป˜้…็ฝฎๆ˜ ๅฐ„ใ€‚
30
+ * key = provider ๅ็งฐ๏ผˆๅฆ‚ "zpay", "alipay"๏ผ‰๏ผŒvalue = ่งฃๅฏ†ๅŽ็š„ๅฎŒๆ•ด้…็ฝฎ
31
+ */
32
+ export type DbProviderConfigMap = Record<string, DbProviderConfig>;
33
+ /**
34
+ * ๅˆ›ๅปบ per-request ็š„ Provider ๆณจๅ†Œ่กจใ€‚
35
+ *
36
+ * ้…็ฝฎๅŠ ่ฝฝไผ˜ๅ…ˆ็บง๏ผˆ้ซ˜ๅˆฐไฝŽ๏ผ‰๏ผš
37
+ * 1. dbConfigs[factory.name].config โ€” ๆ•ฐๆฎๅบ“ไธญ็š„ๆ”ฏไป˜้…็ฝฎ๏ผˆ่งฃๅฏ†ๅŽ๏ผ‰
38
+ * 2. env โ€” ็Žฏๅขƒๅ˜้‡๏ผˆๅ…œๅบ•๏ผ‰
39
+ *
40
+ * ๅฝ“ dbConfigs ๅญ˜ๅœจไธ” enabled=true ๆ—ถ๏ผŒDB ้…็ฝฎ่ฆ†็›– env ไธญๅŒๅ็š„้”ฎใ€‚
41
+ */
42
+ export declare function createProviderRegistry(env: Record<string, unknown>, factories: ProviderFactory[], dbConfigs?: DbProviderConfigMap): ProviderRegistry;
43
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../features/payment/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAmB,eAAe,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAElF,wBAAwB;AACxB,MAAM,WAAW,gBAAgB;IAC/B,WAAW;IACX,OAAO,EAAE,OAAO,CAAC;IACjB,qDAAqD;IACrD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED;;;GAGG;AACH,MAAM,MAAM,mBAAmB,GAAG,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;AAEnE;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,SAAS,EAAE,eAAe,EAAE,EAC5B,SAAS,CAAC,EAAE,mBAAmB,GAC9B,gBAAgB,CAqClB"}