@xmz-ai/coin 0.1.1

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 ADDED
@@ -0,0 +1,66 @@
1
+ # coin merchant sdk (typescript)
2
+
3
+ 面向商户 App 的 TypeScript SDK,封装 coin HTTP API 的商户业务能力。
4
+
5
+ ## Scope (v1)
6
+
7
+ 支持:
8
+ - `GET /api/v1/merchants/me`
9
+ - `POST /api/v1/transactions/credit`
10
+ - `POST /api/v1/transactions/debit`
11
+ - `POST /api/v1/transactions/transfer`
12
+ - `POST /api/v1/transactions/refund`
13
+ - `GET /api/v1/transactions/{txn_no}`
14
+ - `GET /api/v1/transactions/by-out-trade-no/{out_trade_no}`
15
+ - `GET /api/v1/transactions`
16
+
17
+ 不支持(平台后台能力):
18
+ - `POST /api/v1/merchants`
19
+ - `POST /api/v1/merchants/{merchant_no}/secret:rotate`
20
+ - `PUT /api/v1/webhooks/config`
21
+
22
+ ## Install
23
+
24
+ ```bash
25
+ npm install @xmz-ai/coin
26
+ ```
27
+
28
+ ## Quick Start
29
+
30
+ ```typescript
31
+ import { CoinClient, CoinAPIError } from "@xmz-ai/coin";
32
+
33
+ const client = new CoinClient({
34
+ baseURL: "https://api.example.com",
35
+ merchantNo: "1000123456789012",
36
+ merchantSecret: "msk_xxx",
37
+ });
38
+
39
+ const resp = await client.transactions.credit({
40
+ out_trade_no: "ord_issue_001",
41
+ user_id: "u_90001",
42
+ amount: 1000,
43
+ });
44
+
45
+ console.log(`txn=${resp.txn_no} status=${resp.status}`);
46
+ ```
47
+
48
+ ## Error Handling
49
+
50
+ ```typescript
51
+ try {
52
+ await client.transactions.credit({ ... });
53
+ } catch (err) {
54
+ if (err instanceof CoinAPIError) {
55
+ console.error(`api failed: code=${err.code} request_id=${err.requestId}`);
56
+ }
57
+ throw err;
58
+ }
59
+ ```
60
+
61
+ ## Notes
62
+
63
+ - SDK 只提供原子接口,不内置自动轮询或业务重试。
64
+ - 所有请求自动签名(HMAC-SHA256),签名串和服务端一致。
65
+ - 错误统一返回 `CoinAPIError`(包含 HTTP 状态、业务错误码、request_id)。
66
+ - 需要 Node.js >= 18(使用 `node:crypto` 和全局 `fetch`)。
package/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.1
@@ -0,0 +1,22 @@
1
+ import { CustomersAPI } from "./customers.js";
2
+ import { MerchantAPI } from "./merchant.js";
3
+ import { TransactionsAPI } from "./transactions.js";
4
+ import type { ClientOptions } from "./types.js";
5
+ export declare class CoinClient {
6
+ /** @internal */ readonly _baseURL: URL;
7
+ /** @internal */ readonly _merchantNo: string;
8
+ /** @internal */ readonly _merchantSecret: string;
9
+ /** @internal */ readonly _fetch: typeof globalThis.fetch;
10
+ /** @internal */ readonly _timeout: number;
11
+ /** @internal */ readonly _now: () => Date;
12
+ /** @internal */ readonly _nonce: () => string;
13
+ /** @internal */ readonly _userAgent: string;
14
+ readonly customers: CustomersAPI;
15
+ readonly merchant: MerchantAPI;
16
+ readonly transactions: TransactionsAPI;
17
+ constructor(opts: ClientOptions);
18
+ /** @internal */
19
+ _do<T>(method: string, path: string, query?: Record<string, string>, payload?: unknown): Promise<T>;
20
+ }
21
+ export declare function signature(method: string, path: string, merchantNo: string, timestamp: string, nonce: string, body: Uint8Array, secret: string): string;
22
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAYhD,qBAAa,UAAU;IACrB,gBAAgB,CAAC,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC;IACxC,gBAAgB,CAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC9C,gBAAgB,CAAC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IAClD,gBAAgB,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IAC1D,gBAAgB,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC3C,gBAAgB,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,IAAI,CAAC;IAC3C,gBAAgB,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,MAAM,CAAC;IAC/C,gBAAgB,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAE7C,QAAQ,CAAC,SAAS,EAAE,YAAY,CAAC;IACjC,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IAC/B,QAAQ,CAAC,YAAY,EAAE,eAAe,CAAC;gBAE3B,IAAI,EAAE,aAAa;IAgC/B,gBAAgB;IACV,GAAG,CAAC,CAAC,EACT,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC9B,OAAO,CAAC,EAAE,OAAO,GAChB,OAAO,CAAC,CAAC,CAAC;CAqFd;AAED,wBAAgB,SAAS,CACvB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,MAAM,GACb,MAAM,CAWR"}
package/dist/client.js ADDED
@@ -0,0 +1,152 @@
1
+ import { createHmac, createHash, randomBytes } from "node:crypto";
2
+ import { CoinAPIError } from "./error.js";
3
+ import { CustomersAPI } from "./customers.js";
4
+ import { MerchantAPI } from "./merchant.js";
5
+ import { TransactionsAPI } from "./transactions.js";
6
+ const SUCCESS_CODE = "SUCCESS";
7
+ const MAX_RESPONSE_BODY_BYTES = 4 * 1024 * 1024;
8
+ export class CoinClient {
9
+ /** @internal */ _baseURL;
10
+ /** @internal */ _merchantNo;
11
+ /** @internal */ _merchantSecret;
12
+ /** @internal */ _fetch;
13
+ /** @internal */ _timeout;
14
+ /** @internal */ _now;
15
+ /** @internal */ _nonce;
16
+ /** @internal */ _userAgent;
17
+ customers;
18
+ merchant;
19
+ transactions;
20
+ constructor(opts) {
21
+ const base = (opts.baseURL ?? "").trim();
22
+ if (!base)
23
+ throw new Error("base_url is required");
24
+ let parsed;
25
+ try {
26
+ parsed = new URL(base);
27
+ }
28
+ catch {
29
+ throw new Error(`parse base_url: invalid URL: ${base}`);
30
+ }
31
+ if (!parsed.protocol || !parsed.host) {
32
+ throw new Error("base_url must include scheme and host");
33
+ }
34
+ const merchantNo = (opts.merchantNo ?? "").trim();
35
+ if (!merchantNo)
36
+ throw new Error("merchant_no is required");
37
+ if (!(opts.merchantSecret ?? "").trim())
38
+ throw new Error("merchant_secret is required");
39
+ this._baseURL = parsed;
40
+ this._merchantNo = merchantNo;
41
+ this._merchantSecret = opts.merchantSecret;
42
+ this._fetch = opts.fetch ?? globalThis.fetch;
43
+ this._timeout = opts.timeout && opts.timeout > 0 ? opts.timeout : 10_000;
44
+ this._now = opts.now ?? (() => new Date());
45
+ this._nonce = opts.nonceGenerator ?? (() => randomBytes(16).toString("hex"));
46
+ this._userAgent = (opts.userAgent ?? "").trim();
47
+ this.customers = new CustomersAPI(this);
48
+ this.merchant = new MerchantAPI(this);
49
+ this.transactions = new TransactionsAPI(this);
50
+ }
51
+ /** @internal */
52
+ async _do(method, path, query, payload) {
53
+ if (!path || path[0] !== "/") {
54
+ throw new Error("path must start with /");
55
+ }
56
+ const body = payload != null ? JSON.stringify(payload) : "";
57
+ const bodyBytes = new TextEncoder().encode(body);
58
+ const fullPath = joinURLPath(this._baseURL.pathname, path);
59
+ const url = new URL(fullPath, this._baseURL);
60
+ if (query) {
61
+ for (const [k, v] of Object.entries(query)) {
62
+ url.searchParams.set(k, v);
63
+ }
64
+ }
65
+ const timestamp = String(this._now().getTime());
66
+ const nonce = this._nonce().trim();
67
+ if (!nonce)
68
+ throw new Error("nonce generator returned empty value");
69
+ const sig = signature(method, fullPath, this._merchantNo, timestamp, nonce, bodyBytes, this._merchantSecret);
70
+ const headers = {
71
+ "X-Merchant-No": this._merchantNo,
72
+ "X-Timestamp": timestamp,
73
+ "X-Nonce": nonce,
74
+ "X-Signature": sig,
75
+ };
76
+ if (payload != null) {
77
+ headers["Content-Type"] = "application/json";
78
+ }
79
+ if (this._userAgent) {
80
+ headers["User-Agent"] = this._userAgent;
81
+ }
82
+ const controller = new AbortController();
83
+ const timer = setTimeout(() => controller.abort(), this._timeout);
84
+ let resp;
85
+ try {
86
+ resp = await this._fetch(url.toString(), {
87
+ method: method.toUpperCase(),
88
+ headers,
89
+ body: payload != null ? body : undefined,
90
+ signal: controller.signal,
91
+ });
92
+ }
93
+ finally {
94
+ clearTimeout(timer);
95
+ }
96
+ const respBody = await resp.text();
97
+ if (new TextEncoder().encode(respBody).byteLength > MAX_RESPONSE_BODY_BYTES) {
98
+ throw new CoinAPIError({
99
+ httpStatus: resp.status,
100
+ code: "RESPONSE_TOO_LARGE",
101
+ message: `response body exceeds ${MAX_RESPONSE_BODY_BYTES} bytes`,
102
+ rawBody: respBody.slice(0, MAX_RESPONSE_BODY_BYTES),
103
+ });
104
+ }
105
+ let env;
106
+ try {
107
+ env = JSON.parse(respBody);
108
+ }
109
+ catch {
110
+ throw new CoinAPIError({
111
+ httpStatus: resp.status,
112
+ code: "INVALID_RESPONSE",
113
+ message: respBody,
114
+ rawBody: respBody,
115
+ });
116
+ }
117
+ if (!env.code)
118
+ env.code = "INVALID_RESPONSE";
119
+ if (env.code !== SUCCESS_CODE || resp.status >= 400) {
120
+ throw new CoinAPIError({
121
+ httpStatus: resp.status,
122
+ code: env.code,
123
+ message: env.message,
124
+ requestId: env.request_id,
125
+ rawBody: respBody,
126
+ });
127
+ }
128
+ return (env.data ?? null);
129
+ }
130
+ }
131
+ export function signature(method, path, merchantNo, timestamp, nonce, body, secret) {
132
+ const bodyHash = createHash("sha256").update(body).digest("hex");
133
+ const signingString = [
134
+ method.toUpperCase().trim(),
135
+ path,
136
+ merchantNo,
137
+ timestamp,
138
+ nonce,
139
+ bodyHash,
140
+ ].join("\n");
141
+ return createHmac("sha256", secret).update(signingString).digest("hex");
142
+ }
143
+ function joinURLPath(basePath, p) {
144
+ let left = (basePath ?? "").trim().replace(/\/+$/, "");
145
+ const right = (p ?? "").trim().replace(/^\/+/, "");
146
+ if (!left)
147
+ return "/" + right;
148
+ if (!left.startsWith("/"))
149
+ left = "/" + left;
150
+ return left + "/" + right;
151
+ }
152
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { CoinClient } from "./client.js";
2
+ import type { CustomerBalance } from "./types.js";
3
+ export declare class CustomersAPI {
4
+ /** @internal */
5
+ private readonly client;
6
+ /** @internal */
7
+ constructor(client: CoinClient);
8
+ getBalance(outUserID: string): Promise<CustomerBalance>;
9
+ }
10
+ //# sourceMappingURL=customers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"customers.d.ts","sourceRoot":"","sources":["../src/customers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,qBAAa,YAAY;IACvB,gBAAgB;IAChB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAa;IAEpC,gBAAgB;gBACJ,MAAM,EAAE,UAAU;IAIxB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;CAS9D"}
@@ -0,0 +1,15 @@
1
+ export class CustomersAPI {
2
+ /** @internal */
3
+ client;
4
+ /** @internal */
5
+ constructor(client) {
6
+ this.client = client;
7
+ }
8
+ async getBalance(outUserID) {
9
+ outUserID = (outUserID ?? "").trim();
10
+ if (!outUserID)
11
+ throw new Error("out_user_id is required");
12
+ return this.client._do("GET", "/api/v1/customers/balance", { out_user_id: outUserID });
13
+ }
14
+ }
15
+ //# sourceMappingURL=customers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"customers.js","sourceRoot":"","sources":["../src/customers.ts"],"names":[],"mappings":"AAGA,MAAM,OAAO,YAAY;IACvB,gBAAgB;IACC,MAAM,CAAa;IAEpC,gBAAgB;IAChB,YAAY,MAAkB;QAC5B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,SAAiB;QAChC,SAAS,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACrC,IAAI,CAAC,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;QAC3D,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CACpB,KAAK,EACL,2BAA2B,EAC3B,EAAE,WAAW,EAAE,SAAS,EAAE,CAC3B,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,14 @@
1
+ export declare class CoinAPIError extends Error {
2
+ readonly httpStatus: number;
3
+ readonly code: string;
4
+ readonly requestId: string;
5
+ readonly rawBody: string;
6
+ constructor(opts: {
7
+ httpStatus: number;
8
+ code: string;
9
+ message: string;
10
+ requestId?: string;
11
+ rawBody?: string;
12
+ });
13
+ }
14
+ //# sourceMappingURL=error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"AAAA,qBAAa,YAAa,SAAQ,KAAK;IACrC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;gBAEb,IAAI,EAAE;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB;CAYF"}
package/dist/error.js ADDED
@@ -0,0 +1,19 @@
1
+ export class CoinAPIError extends Error {
2
+ httpStatus;
3
+ code;
4
+ requestId;
5
+ rawBody;
6
+ constructor(opts) {
7
+ const parts = [`api error: http=${opts.httpStatus} code=${opts.code} message=${opts.message}`];
8
+ if (opts.requestId) {
9
+ parts.push(`request_id=${opts.requestId}`);
10
+ }
11
+ super(parts.join(" "));
12
+ this.name = "CoinAPIError";
13
+ this.httpStatus = opts.httpStatus;
14
+ this.code = opts.code;
15
+ this.requestId = opts.requestId ?? "";
16
+ this.rawBody = opts.rawBody ?? "";
17
+ }
18
+ }
19
+ //# sourceMappingURL=error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error.js","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,YAAa,SAAQ,KAAK;IAC5B,UAAU,CAAS;IACnB,IAAI,CAAS;IACb,SAAS,CAAS;IAClB,OAAO,CAAS;IAEzB,YAAY,IAMX;QACC,MAAM,KAAK,GAAG,CAAC,mBAAmB,IAAI,CAAC,UAAU,SAAS,IAAI,CAAC,IAAI,YAAY,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QAC/F,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,KAAK,CAAC,IAAI,CAAC,cAAc,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;QAC7C,CAAC;QACD,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;QAC3B,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;QAClC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACtB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC;QACtC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC;IACpC,CAAC;CACF"}
@@ -0,0 +1,7 @@
1
+ export { CoinClient, signature } from "./client.js";
2
+ export { CustomersAPI } from "./customers.js";
3
+ export { CoinAPIError } from "./error.js";
4
+ export { MerchantAPI } from "./merchant.js";
5
+ export { TransactionsAPI } from "./transactions.js";
6
+ export type { ClientOptions, CreditRequest, CustomerBalance, DebitRequest, TransferRequest, RefundRequest, ListTransactionsRequest, TxnSubmitResponse, Txn, ListTransactionsResponse, MerchantProfile, } from "./types.js";
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,YAAY,EACV,aAAa,EACb,aAAa,EACb,eAAe,EACf,YAAY,EACZ,eAAe,EACf,aAAa,EACb,uBAAuB,EACvB,iBAAiB,EACjB,GAAG,EACH,wBAAwB,EACxB,eAAe,GAChB,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ export { CoinClient, signature } from "./client.js";
2
+ export { CustomersAPI } from "./customers.js";
3
+ export { CoinAPIError } from "./error.js";
4
+ export { MerchantAPI } from "./merchant.js";
5
+ export { TransactionsAPI } from "./transactions.js";
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { CoinClient } from "./client.js";
2
+ import type { MerchantProfile } from "./types.js";
3
+ export declare class MerchantAPI {
4
+ /** @internal */
5
+ private readonly client;
6
+ /** @internal */
7
+ constructor(client: CoinClient);
8
+ me(): Promise<MerchantProfile>;
9
+ }
10
+ //# sourceMappingURL=merchant.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merchant.d.ts","sourceRoot":"","sources":["../src/merchant.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,qBAAa,WAAW;IACtB,gBAAgB;IAChB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAa;IAEpC,gBAAgB;gBACJ,MAAM,EAAE,UAAU;IAIxB,EAAE,IAAI,OAAO,CAAC,eAAe,CAAC;CAGrC"}
@@ -0,0 +1,12 @@
1
+ export class MerchantAPI {
2
+ /** @internal */
3
+ client;
4
+ /** @internal */
5
+ constructor(client) {
6
+ this.client = client;
7
+ }
8
+ async me() {
9
+ return this.client._do("GET", "/api/v1/merchants/me");
10
+ }
11
+ }
12
+ //# sourceMappingURL=merchant.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merchant.js","sourceRoot":"","sources":["../src/merchant.ts"],"names":[],"mappings":"AAGA,MAAM,OAAO,WAAW;IACtB,gBAAgB;IACC,MAAM,CAAa;IAEpC,gBAAgB;IAChB,YAAY,MAAkB;QAC5B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,EAAE;QACN,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAkB,KAAK,EAAE,sBAAsB,CAAC,CAAC;IACzE,CAAC;CACF"}
@@ -0,0 +1,16 @@
1
+ import type { CoinClient } from "./client.js";
2
+ import type { CreditRequest, DebitRequest, TransferRequest, RefundRequest, ListTransactionsRequest, TxnSubmitResponse, Txn, ListTransactionsResponse } from "./types.js";
3
+ export declare class TransactionsAPI {
4
+ /** @internal */
5
+ private readonly client;
6
+ /** @internal */
7
+ constructor(client: CoinClient);
8
+ credit(req: CreditRequest): Promise<TxnSubmitResponse>;
9
+ debit(req: DebitRequest): Promise<TxnSubmitResponse>;
10
+ transfer(req: TransferRequest): Promise<TxnSubmitResponse>;
11
+ refund(req: RefundRequest): Promise<TxnSubmitResponse>;
12
+ getByTxnNo(txnNo: string): Promise<Txn>;
13
+ getByOutTradeNo(outTradeNo: string): Promise<Txn>;
14
+ list(req: ListTransactionsRequest): Promise<ListTransactionsResponse>;
15
+ }
16
+ //# sourceMappingURL=transactions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transactions.d.ts","sourceRoot":"","sources":["../src/transactions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EACV,aAAa,EACb,YAAY,EACZ,eAAe,EACf,aAAa,EACb,uBAAuB,EACvB,iBAAiB,EACjB,GAAG,EACH,wBAAwB,EACzB,MAAM,YAAY,CAAC;AAIpB,qBAAa,eAAe;IAC1B,gBAAgB;IAChB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAa;IAEpC,gBAAgB;gBACJ,MAAM,EAAE,UAAU;IAIxB,MAAM,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAWtD,KAAK,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAQpD,QAAQ,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAc1D,MAAM,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAQtD,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAMvC,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAMjD,IAAI,CAAC,GAAG,EAAE,uBAAuB,GAAG,OAAO,CAAC,wBAAwB,CAAC;CAiB5E"}
@@ -0,0 +1,89 @@
1
+ const OUT_TRADE_NO_PATTERN = /^[A-Za-z0-9_-]{1,64}$/;
2
+ export class TransactionsAPI {
3
+ /** @internal */
4
+ client;
5
+ /** @internal */
6
+ constructor(client) {
7
+ this.client = client;
8
+ }
9
+ async credit(req) {
10
+ req = { ...req, out_trade_no: validateOutTradeNoAndAmount(req.out_trade_no, req.amount) };
11
+ if (!(req.credit_account_no ?? "").trim() && !(req.user_id ?? "").trim()) {
12
+ throw new Error("credit_account_no or user_id is required");
13
+ }
14
+ if ((req.expire_in_days ?? 0) < 0) {
15
+ throw new Error("expire_in_days must be >= 0");
16
+ }
17
+ return this.client._do("POST", "/api/v1/transactions/credit", undefined, req);
18
+ }
19
+ async debit(req) {
20
+ req = { ...req, out_trade_no: validateOutTradeNoAndAmount(req.out_trade_no, req.amount) };
21
+ if (!(req.debit_account_no ?? "").trim() && !(req.debit_out_user_id ?? "").trim()) {
22
+ throw new Error("debit_account_no or debit_out_user_id is required");
23
+ }
24
+ return this.client._do("POST", "/api/v1/transactions/debit", undefined, req);
25
+ }
26
+ async transfer(req) {
27
+ req = { ...req, out_trade_no: validateOutTradeNoAndAmount(req.out_trade_no, req.amount) };
28
+ if (!(req.from_account_no ?? "").trim() && !(req.from_out_user_id ?? "").trim()) {
29
+ throw new Error("from_account_no or from_out_user_id is required");
30
+ }
31
+ if (!(req.to_account_no ?? "").trim() && !(req.to_out_user_id ?? "").trim()) {
32
+ throw new Error("to_account_no or to_out_user_id is required");
33
+ }
34
+ if ((req.to_expire_in_days ?? 0) < 0) {
35
+ throw new Error("to_expire_in_days must be >= 0");
36
+ }
37
+ return this.client._do("POST", "/api/v1/transactions/transfer", undefined, req);
38
+ }
39
+ async refund(req) {
40
+ req = { ...req, out_trade_no: validateOutTradeNoAndAmount(req.out_trade_no, req.amount) };
41
+ const refundOfTxnNo = (req.refund_of_txn_no ?? "").trim();
42
+ if (!refundOfTxnNo)
43
+ throw new Error("refund_of_txn_no is required");
44
+ req = { ...req, refund_of_txn_no: refundOfTxnNo };
45
+ return this.client._do("POST", "/api/v1/transactions/refund", undefined, req);
46
+ }
47
+ async getByTxnNo(txnNo) {
48
+ txnNo = (txnNo ?? "").trim();
49
+ if (!txnNo)
50
+ throw new Error("txn_no is required");
51
+ return this.client._do("GET", `/api/v1/transactions/${encodeURIComponent(txnNo)}`);
52
+ }
53
+ async getByOutTradeNo(outTradeNo) {
54
+ outTradeNo = (outTradeNo ?? "").trim();
55
+ if (!outTradeNo)
56
+ throw new Error("out_trade_no is required");
57
+ return this.client._do("GET", `/api/v1/transactions/by-out-trade-no/${encodeURIComponent(outTradeNo)}`);
58
+ }
59
+ async list(req) {
60
+ const query = {};
61
+ if (req.startTime)
62
+ query.start_time = req.startTime.toISOString();
63
+ if (req.endTime)
64
+ query.end_time = req.endTime.toISOString();
65
+ if ((req.status ?? "").trim())
66
+ query.status = req.status.trim().toUpperCase();
67
+ if ((req.transferScene ?? "").trim())
68
+ query.transfer_scene = req.transferScene.trim().toUpperCase();
69
+ if ((req.outUserID ?? "").trim())
70
+ query.out_user_id = req.outUserID.trim();
71
+ if (req.pageSize && req.pageSize > 0)
72
+ query.page_size = String(req.pageSize);
73
+ if ((req.pageToken ?? "").trim())
74
+ query.page_token = req.pageToken.trim();
75
+ const resp = await this.client._do("GET", "/api/v1/transactions", Object.keys(query).length > 0 ? query : undefined);
76
+ return { ...resp, items: resp.items ?? [] };
77
+ }
78
+ }
79
+ function validateOutTradeNoAndAmount(outTradeNo, amount) {
80
+ const trimmed = (outTradeNo ?? "").trim();
81
+ if (!trimmed)
82
+ throw new Error("out_trade_no is required");
83
+ if (!OUT_TRADE_NO_PATTERN.test(trimmed))
84
+ throw new Error("invalid out_trade_no");
85
+ if (!amount || amount <= 0)
86
+ throw new Error("amount must be > 0");
87
+ return trimmed;
88
+ }
89
+ //# sourceMappingURL=transactions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transactions.js","sourceRoot":"","sources":["../src/transactions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,94 @@
1
+ export interface ClientOptions {
2
+ baseURL: string;
3
+ merchantNo: string;
4
+ merchantSecret: string;
5
+ timeout?: number;
6
+ fetch?: typeof globalThis.fetch;
7
+ userAgent?: string;
8
+ /** Injected for testing. Returns current UTC time. */
9
+ now?: () => Date;
10
+ /** Injected for testing. Returns a nonce string. */
11
+ nonceGenerator?: () => string;
12
+ }
13
+ export interface CreditRequest {
14
+ out_trade_no: string;
15
+ debit_account_no?: string;
16
+ credit_account_no?: string;
17
+ user_id?: string;
18
+ expire_in_days?: number;
19
+ amount: number;
20
+ }
21
+ export interface DebitRequest {
22
+ out_trade_no: string;
23
+ biz_type?: string;
24
+ transfer_scene?: string;
25
+ debit_account_no?: string;
26
+ debit_out_user_id?: string;
27
+ credit_account_no?: string;
28
+ credit_out_user_id?: string;
29
+ amount: number;
30
+ }
31
+ export interface TransferRequest {
32
+ out_trade_no: string;
33
+ biz_type?: string;
34
+ transfer_scene?: string;
35
+ from_account_no?: string;
36
+ from_out_user_id?: string;
37
+ to_account_no?: string;
38
+ to_out_user_id?: string;
39
+ to_expire_in_days?: number;
40
+ amount: number;
41
+ }
42
+ export interface RefundRequest {
43
+ out_trade_no: string;
44
+ biz_type?: string;
45
+ refund_of_txn_no: string;
46
+ amount: number;
47
+ }
48
+ export interface ListTransactionsRequest {
49
+ startTime?: Date;
50
+ endTime?: Date;
51
+ status?: string;
52
+ transferScene?: string;
53
+ outUserID?: string;
54
+ pageSize?: number;
55
+ pageToken?: string;
56
+ }
57
+ export interface TxnSubmitResponse {
58
+ txn_no: string;
59
+ status: string;
60
+ }
61
+ export interface Txn {
62
+ txn_no: string;
63
+ out_trade_no: string;
64
+ transfer_scene: string;
65
+ status: string;
66
+ amount: number;
67
+ refundable_amount: number;
68
+ debit_account_no: string;
69
+ credit_account_no: string;
70
+ error_code: string;
71
+ error_msg: string;
72
+ created_at: string;
73
+ }
74
+ export interface ListTransactionsResponse {
75
+ items: Txn[];
76
+ next_page_token: string;
77
+ }
78
+ export interface CustomerBalance {
79
+ out_user_id: string;
80
+ account_no: string;
81
+ balance: number;
82
+ book_enabled: boolean;
83
+ }
84
+ export interface MerchantProfile {
85
+ merchant_no: string;
86
+ name: string;
87
+ status: string;
88
+ budget_account_no: string;
89
+ receivable_account_no: string;
90
+ secret_version: number;
91
+ auto_create_account_on_customer_create: boolean;
92
+ auto_create_customer_on_credit: boolean;
93
+ }
94
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "@xmz-ai/coin",
3
+ "version": "0.1.1",
4
+ "description": "Coin merchant SDK for Node.js / TypeScript",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "files": [
9
+ "dist",
10
+ "VERSION",
11
+ "README.md"
12
+ ],
13
+ "scripts": {
14
+ "build": "tsc",
15
+ "test": "vitest run",
16
+ "prepublishOnly": "npm run build"
17
+ },
18
+ "engines": {
19
+ "node": ">=18"
20
+ },
21
+ "devDependencies": {
22
+ "@types/node": "^25.5.0",
23
+ "typescript": "^5.4.0",
24
+ "vitest": "^3.0.0"
25
+ },
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "https://github.com/xmz-ai/coin.git",
29
+ "directory": "sdk/ts/coin"
30
+ },
31
+ "license": "MIT"
32
+ }