@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.
- package/README.md +88 -0
- package/dist/features/anti-abuse/index.d.ts +62 -0
- package/dist/features/anti-abuse/index.d.ts.map +1 -0
- package/dist/features/anti-abuse/index.js +139 -0
- package/dist/features/anti-abuse/index.js.map +1 -0
- package/dist/features/email/index.d.ts +68 -0
- package/dist/features/email/index.d.ts.map +1 -0
- package/dist/features/email/index.js +120 -0
- package/dist/features/email/index.js.map +1 -0
- package/dist/features/payment/fetch-utils.d.ts +17 -0
- package/dist/features/payment/fetch-utils.d.ts.map +1 -0
- package/dist/features/payment/fetch-utils.js +56 -0
- package/dist/features/payment/fetch-utils.js.map +1 -0
- package/dist/features/payment/index.d.ts +20 -0
- package/dist/features/payment/index.d.ts.map +1 -0
- package/dist/features/payment/index.js +21 -0
- package/dist/features/payment/index.js.map +1 -0
- package/dist/features/payment/providers/alipay.d.ts +30 -0
- package/dist/features/payment/providers/alipay.d.ts.map +1 -0
- package/dist/features/payment/providers/alipay.js +149 -0
- package/dist/features/payment/providers/alipay.js.map +1 -0
- package/dist/features/payment/providers/stripe.d.ts +34 -0
- package/dist/features/payment/providers/stripe.d.ts.map +1 -0
- package/dist/features/payment/providers/stripe.js +168 -0
- package/dist/features/payment/providers/stripe.js.map +1 -0
- package/dist/features/payment/providers/trc20.d.ts +24 -0
- package/dist/features/payment/providers/trc20.d.ts.map +1 -0
- package/dist/features/payment/providers/trc20.js +96 -0
- package/dist/features/payment/providers/trc20.js.map +1 -0
- package/dist/features/payment/registry.d.ts +43 -0
- package/dist/features/payment/registry.d.ts.map +1 -0
- package/dist/features/payment/registry.js +65 -0
- package/dist/features/payment/registry.js.map +1 -0
- package/dist/features/payment/types.d.ts +72 -0
- package/dist/features/payment/types.d.ts.map +1 -0
- package/dist/features/payment/types.js +8 -0
- package/dist/features/payment/types.js.map +1 -0
- package/dist/features/thompson-router/index.d.ts +101 -0
- package/dist/features/thompson-router/index.d.ts.map +1 -0
- package/dist/features/thompson-router/index.js +186 -0
- package/dist/features/thompson-router/index.js.map +1 -0
- package/dist/features/webhook/index.d.ts +76 -0
- package/dist/features/webhook/index.d.ts.map +1 -0
- package/dist/features/webhook/index.js +127 -0
- package/dist/features/webhook/index.js.map +1 -0
- package/dist/src/audit.d.ts +45 -0
- package/dist/src/audit.d.ts.map +1 -0
- package/dist/src/audit.js +40 -0
- package/dist/src/audit.js.map +1 -0
- package/dist/src/auth/jwt.d.ts +33 -0
- package/dist/src/auth/jwt.d.ts.map +1 -0
- package/dist/src/auth/jwt.js +87 -0
- package/dist/src/auth/jwt.js.map +1 -0
- package/dist/src/auth/password.d.ts +26 -0
- package/dist/src/auth/password.d.ts.map +1 -0
- package/dist/src/auth/password.js +52 -0
- package/dist/src/auth/password.js.map +1 -0
- package/dist/src/bootstrap.d.ts +74 -0
- package/dist/src/bootstrap.d.ts.map +1 -0
- package/dist/src/bootstrap.js +231 -0
- package/dist/src/bootstrap.js.map +1 -0
- package/dist/src/cache.d.ts +52 -0
- package/dist/src/cache.d.ts.map +1 -0
- package/dist/src/cache.js +76 -0
- package/dist/src/cache.js.map +1 -0
- package/dist/src/config.d.ts +83 -0
- package/dist/src/config.d.ts.map +1 -0
- package/dist/src/config.js +96 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/crypto.d.ts +33 -0
- package/dist/src/crypto.d.ts.map +1 -0
- package/dist/src/crypto.js +87 -0
- package/dist/src/crypto.js.map +1 -0
- package/dist/src/db/connection.d.ts +53 -0
- package/dist/src/db/connection.d.ts.map +1 -0
- package/dist/src/db/connection.js +104 -0
- package/dist/src/db/connection.js.map +1 -0
- package/dist/src/db/index.d.ts +6 -0
- package/dist/src/db/index.d.ts.map +1 -0
- package/dist/src/db/index.js +6 -0
- package/dist/src/db/index.js.map +1 -0
- package/dist/src/db/schema.d.ts +649 -0
- package/dist/src/db/schema.d.ts.map +1 -0
- package/dist/src/db/schema.js +76 -0
- package/dist/src/db/schema.js.map +1 -0
- package/dist/src/error.d.ts +47 -0
- package/dist/src/error.d.ts.map +1 -0
- package/dist/src/error.js +94 -0
- package/dist/src/error.js.map +1 -0
- package/dist/src/http.d.ts +83 -0
- package/dist/src/http.d.ts.map +1 -0
- package/dist/src/http.js +116 -0
- package/dist/src/http.js.map +1 -0
- package/dist/src/idempotency.d.ts +78 -0
- package/dist/src/idempotency.d.ts.map +1 -0
- package/dist/src/idempotency.js +84 -0
- package/dist/src/idempotency.js.map +1 -0
- package/dist/src/index.d.ts +31 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +45 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/logger.d.ts +31 -0
- package/dist/src/logger.d.ts.map +1 -0
- package/dist/src/logger.js +45 -0
- package/dist/src/logger.js.map +1 -0
- package/dist/src/middleware/admin-auth.d.ts +38 -0
- package/dist/src/middleware/admin-auth.d.ts.map +1 -0
- package/dist/src/middleware/admin-auth.js +55 -0
- package/dist/src/middleware/admin-auth.js.map +1 -0
- package/dist/src/middleware/api-key-auth.d.ts +42 -0
- package/dist/src/middleware/api-key-auth.d.ts.map +1 -0
- package/dist/src/middleware/api-key-auth.js +104 -0
- package/dist/src/middleware/api-key-auth.js.map +1 -0
- package/dist/src/middleware/index.d.ts +3 -0
- package/dist/src/middleware/index.d.ts.map +1 -0
- package/dist/src/middleware/index.js +3 -0
- package/dist/src/middleware/index.js.map +1 -0
- package/dist/src/rate-limit.d.ts +54 -0
- package/dist/src/rate-limit.d.ts.map +1 -0
- package/dist/src/rate-limit.js +134 -0
- package/dist/src/rate-limit.js.map +1 -0
- package/dist/src/security.d.ts +78 -0
- package/dist/src/security.d.ts.map +1 -0
- package/dist/src/security.js +175 -0
- package/dist/src/security.js.map +1 -0
- package/dist/src/types.d.ts +64 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +8 -0
- package/dist/src/types.js.map +1 -0
- package/features/anti-abuse/index.ts +180 -0
- package/features/anti-abuse/tests/index.test.ts +50 -0
- package/features/email/index.ts +172 -0
- package/features/email/tests/index.test.ts +44 -0
- package/features/payment/fetch-utils.ts +65 -0
- package/features/payment/index.ts +39 -0
- package/features/payment/providers/alipay.ts +171 -0
- package/features/payment/providers/stripe.ts +192 -0
- package/features/payment/providers/trc20.ts +115 -0
- package/features/payment/registry.ts +87 -0
- package/features/payment/tests/index.test.ts +506 -0
- package/features/payment/types.ts +93 -0
- package/features/telegram-miniapp/index.ts +109 -0
- package/features/telegram-miniapp/tests/index.test.ts +11 -0
- package/features/thompson-router/index.ts +243 -0
- package/features/thompson-router/tests/index.test.ts +93 -0
- package/features/webhook/index.ts +183 -0
- package/features/webhook/tests/index.test.ts +21 -0
- package/package.json +202 -0
- package/src/audit.ts +70 -0
- package/src/auth/jwt.ts +114 -0
- package/src/auth/password.ts +75 -0
- package/src/bootstrap.ts +322 -0
- package/src/cache.ts +78 -0
- package/src/config.ts +134 -0
- package/src/crypto.ts +106 -0
- package/src/db/connection.ts +127 -0
- package/src/db/index.ts +6 -0
- package/src/db/schema.ts +90 -0
- package/src/error.ts +125 -0
- package/src/http.ts +150 -0
- package/src/idempotency.ts +127 -0
- package/src/index.ts +85 -0
- package/src/logger.ts +63 -0
- package/src/middleware/admin-auth.ts +71 -0
- package/src/middleware/api-key-auth.ts +164 -0
- package/src/middleware/index.ts +2 -0
- package/src/rate-limit.ts +167 -0
- package/src/security.ts +219 -0
- 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":"AAAA;;;;;;;GAOG;AAUH,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEhD,kFAAkF;AAClF,OAAO;AACP,kFAAkF;AAElF;;;GAGG;AACH,SAAS,YAAY,CAAC,OAAe;IACnC,OAAO,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AAC/D,CAAC;AAED,kFAAkF;AAClF,uCAAuC;AACvC,kFAAkF;AAElF,MAAM,OAAO,aAAa;IAML;IACA;IANV,IAAI,GAAG,YAAY,CAAC;IACpB,WAAW,GAAG,cAAc,CAAC;IAC7B,mBAAmB,GAAG,CAAC,MAAM,CAAC,CAAC;IAExC,YACmB,aAAqB,EACrB,cAAsB;QADtB,kBAAa,GAAb,aAAa,CAAQ;QACrB,mBAAc,GAAd,cAAc,CAAQ;IACtC,CAAC;IAEJ,KAAK,CAAC,aAAa,CAAC,KAAyB;QAC3C,MAAM,MAAM,GAAG,CAAC,KAAK,CAAC,WAAW,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QACpD,MAAM,IAAI,GAAG,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACzC,OAAO;YACL,GAAG,EAAE;gBACH,OAAO,EAAE,IAAI,CAAC,aAAa;gBAC3B,MAAM;gBACN,IAAI;gBACJ,OAAO,EAAE,OAAO;gBAChB,QAAQ,EAAE;oBACR,6BAA6B;oBAC7B,2BAA2B;oBAC3B,uBAAuB;iBACxB;aACF;SACF,CAAC;IACJ,CAAC;IAED,kCAAkC;IAClC,KAAK,CAAC,cAAc,CAAC,OAA+B;QAClD,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;IAC7E,CAAC;IAED,6BAA6B;IAC7B,KAAK,CAAC,WAAW,CAAC,OAAe;QAC/B,MAAM,IAAI,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;QACnC,MAAM,GAAG,GAAG,uCAAuC,IAAI,CAAC,aAAa,qBAAqB,CAAC;QAC3F,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC;YACjC,KAAK,EAAE,IAAI;YACX,gBAAgB,EAAE,oCAAoC,EAAE,gBAAgB;YACxE,OAAO,EAAE,MAAM;YACf,QAAQ,EAAE,sBAAsB;SACjC,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,cAAc,CAAC,GAAG,GAAG,IAAI,MAAM,CAAC,QAAQ,EAAE,EAAE,EAAE;YAC/D,OAAO,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,IAAI,CAAC,cAAc,EAAE;YAChF,SAAS,EAAE,MAAM;YACjB,OAAO,EAAE,CAAC;SACX,CAAC,CAAC;QACH,IAAI,CAAC,IAAI,CAAC,EAAE;YAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;QACrC,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,CAE9B,CAAC;QACF,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;QAC5B,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;QAE7C,sCAAsC;QACtC,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;YACrB,MAAM,QAAQ,GAAG,EAAE,CAAC,UAAU,EAAE,QAAQ,IAAI,CAAC,CAAC;YAC9C,MAAM,MAAM,GAAG,UAAU,CAAC,EAAE,CAAC,KAAK,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;YACpE,IAAI,MAAM,GAAG,CAAC;gBAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,eAAe,EAAE,EAAE,CAAC,cAAc,EAAE,CAAC;QAC5E,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IACzB,CAAC;CACF;AAED,kFAAkF;AAClF,WAAW;AACX,kFAAkF;AAElF,MAAM,CAAC,MAAM,YAAY,GAAoB;IAC3C,IAAI,EAAE,YAAY;IAClB,QAAQ,EAAE,GAAG;IACb,WAAW,CAAC,GAAG,IAAI,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,oBAAoB,IAAI,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC;IACjF,MAAM,CAAC,GAAG;QACR,OAAO,IAAI,aAAa,CACtB,GAAG,CAAC,oBAA8B,EAClC,GAAG,CAAC,gBAA0B,CAC/B,CAAC;IACJ,CAAC;CACF,CAAC"}
|
|
@@ -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"}
|