rpay-sdk 0.0.0-stage → 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 RPAY (https://rpay.vn)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,331 @@
1
- # Temporary Holding Version
1
+ # rpay-sdk — Thư viện Tích hợp Thanh toán Tự động RPAY (Bank VietQR VNĐ & Crypto USDT/USDC)
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ SDK chính thức cho hệ sinh thái **RPAY (`https://api.rpay.vn` & hệ thống Web con / Multi-Domain)** dành cho **Node.js, TypeScript, Next.js, Express.js, NestJS**.
4
+
5
+ Thiết kế theo triết lý **Zero-Config (Tự đọc `.env`)** và **Hợp nhất 1 Hàm Duy Nhất** cho cả **Ngân hàng (15 cổng VietQR VNĐ)** lẫn **Crypto (USDT/USDC trên 18 mạng lưới)**.
6
+
7
+ ---
8
+
9
+ ## Mục lục
10
+
11
+ 1. [Cài đặt & Cấu hình `.env` trong 30 giây (Zero-Config)](#1-cài-đặt--cấu-hình-env-trong-30-giây-zero-config)
12
+ 2. [4 Hàm Cốt lõi Dễ Dùng Nhất (`pay`, `check`, `lsgd`, `qr`)](#2-4-hàm-cốt-lõi-dễ-dùng-nhất-pay-check-lsgd-qr)
13
+ 3. [Tích hợp Nhận Webhook Tự động Cộng tiền (Next.js & Express.js)](#3-tích-hợp-nhận-webhook-tự-động-cộng-tiền-nextjs--expressjs)
14
+ 4. [Tích hợp Cronjob Lấy Lịch sử Giao dịch (LSGD) & Đối soát Chống Trùng](#4-tích-hợp-cronjob-lấy-lịch-sử-giao-dịch-lsgd--đối-soát-chống-trùng)
15
+ 5. [Cách dùng trên Nhiều Tên Miền (Multi-Domain / Web Con / Nhiều Shop)](#5-cách-dùng-trên-nhiều-tên-miền-multi-domain--web-con--nhiều-shop)
16
+ 6. [Quantum Router Hub (`rpay.route`) & Lịch sử V2 / V3 / POS Chi tiết](#6-quantum-router-hub-rpayroute--lịch-sử-v2--v3--pos-chi-tiết)
17
+ 7. [Bảng Mã 15 Ngân hàng & 18 Mạng lưới USDT/USDC](#7-bảng-mã-15-ngân-hàng--18-mạng-lưới-usdtusdc)
18
+ 8. [Hướng dẫn Đẩy gói lên NPM (`npm publish`)](#8-hướng-dẫn-đẩy-gói-lên-npm-npm-publish)
19
+
20
+ ---
21
+
22
+ ## 1. Cài đặt & Cấu hình `.env` trong 30 giây (Zero-Config)
23
+
24
+ ### Bước 1: Cài đặt thư viện
25
+
26
+ ```bash
27
+ npm install rpay-sdk
28
+ # hoặc
29
+ pnpm add rpay-sdk
30
+ # hoặc
31
+ yarn add rpay-sdk
32
+ ```
33
+
34
+ ### Bước 2: Khai báo biến môi trường trong file `.env`
35
+
36
+ SDK **tự động đọc các biến môi trường `RPAY_*`** ngay khi `import rpay from "rpay-sdk"` mà không bắt buộc phải viết code khởi tạo:
37
+
38
+ ```env
39
+ # Tên miền cổng thanh toán (Mặc định: https://api.rpay.vn hoặc điền domain Web con của bạn)
40
+ RPAY_DOMAIN=https://api.rpay.vn
41
+
42
+ # Token Ngân hàng (dùng cho tạo hóa đơn Bank & lấy LSGD POS/V1/V2/V3)
43
+ RPAY_BANK_TOKEN=rpay_vcb_live_123456_abcdef123456
44
+
45
+ # Thông tin Cửa hàng Crypto USDT/USDC (nếu tích hợp cổng Crypto)
46
+ RPAY_MERCHANT_ID=MRCH-0001
47
+ RPAY_USDT_API_KEY=ukey_live_xxxxxxxxxxxxxxxx
48
+
49
+ # Khóa bí mật xác thực chữ ký Webhook HMAC-SHA256
50
+ RPAY_WEBHOOK_SECRET=whsec_xxxxxxxxxxxxxxxx
51
+ ```
52
+
53
+ *(Hoặc nếu không dùng `.env`, bạn có thể gọi `rpay.init({ domain, bankToken, merchantId, usdtKey, secret })` ở đầu ứng dụng).*
54
+
55
+ ---
56
+
57
+ ## 2. 4 Hàm Cốt lõi Dễ Dùng Nhất (`pay`, `check`, `lsgd`, `qr`)
58
+
59
+ Mọi thao tác thanh toán đều nằm ngay trên đối tượng `rpay` và **tương thích đồng thời cả Bank (VNĐ) lẫn Crypto (USDT/USDC)**:
60
+
61
+ ### 2.1. `rpay.pay(...)` — Tạo Hóa đơn Thanh toán (Bank VNĐ hoặc Crypto USDT/USDC)
62
+
63
+ ```ts
64
+ import rpay from "rpay-sdk";
65
+
66
+ // TH1: Tạo hóa đơn Ngân hàng (VietQR VNĐ)
67
+ const bankOrder = await rpay.pay({
68
+ channel: "bank", // Hoặc truyền currency: "VND"
69
+ amount: 250000, // 250.000 VNĐ
70
+ orderId: "DH1001", // Mã đơn hàng trên hệ thống của bạn
71
+ description: "Nạp tiền tài khoản",
72
+ callbackUrl: "https://webcuaban.com/api/webhooks/rpay",
73
+ });
74
+
75
+ // TH2: Tạo hóa đơn Crypto (USDT hoặc USDC trên 18 mạng lưới)
76
+ const cryptoOrder = await rpay.pay({
77
+ channel: "usdt", // Hoặc truyền currency: "USDT" | "USDC"
78
+ network: "TRC20", // TRC20, BEP20, ERC20, SOLANA, TON, POLYGON, ARBITRUM, BASE...
79
+ token: "USDT",
80
+ amount: 50, // 50 USDT
81
+ orderId: "DH1002",
82
+ callbackUrl: "https://webcuaban.com/api/webhooks/rpay",
83
+ });
84
+
85
+ // Cả 2 đều trả về CÙNG MỘT CẤU TRÚC chuẩn để bạn hiển thị lên giao diện hoặc chuyển hướng:
86
+ console.log({
87
+ invoiceCode: bankOrder.invoiceCode, // "RPINV..." (Bank) hoặc "USINV..." (USDT)
88
+ paymentUrl: bankOrder.paymentUrl, // Link trang Checkout Hosted của RPAY
89
+ qrImageUrl: bankOrder.qrImageUrl, // Link ảnh QR để gắn vào <img src="..." />
90
+ recipientAddress: bankOrder.recipientAddress, // Số tài khoản NH hoặc Địa chỉ ví USDT
91
+ recipientName: bankOrder.recipientName, // Tên chủ TK hoặc Tên mạng lưới
92
+ transferContent: bankOrder.transferContent, // Nội dung chuyển khoản bắt buộc
93
+ amount: bankOrder.amount, // Số tiền cần thanh toán
94
+ currency: bankOrder.currency, // "VND" | "USDT" | "USDC"
95
+ });
96
+ ```
97
+
98
+ ### 2.2. `rpay.check(code)` — Kiểm tra & Đối soát Hóa đơn Tức thì ("Tôi đã chuyển khoản")
99
+
100
+ Hàm tự động phân biệt mã hóa đơn Ngân hàng (`RPINV...`) và mã hóa đơn Crypto (`USINV...` / `USTX...`):
101
+
102
+ ```ts
103
+ const status = await rpay.check(bankOrder.invoiceCode);
104
+
105
+ if (status.isPaid) {
106
+ console.log("Khách đã thanh toán thành công!", status.paidAmount, status.currency);
107
+ }
108
+ ```
109
+
110
+ ### 2.3. `rpay.qr(...)` — Tạo nhanh Mã VietQR Động (Không cần tạo Invoice)
111
+
112
+ ```ts
113
+ const qr = await rpay.qr({
114
+ bank: "MB", // Mã NH (VCB, MB, ACB, TCB, BIDV, ICB, VPB, TPB...) hoặc BIN (970422)
115
+ account: "0123456789", // Số tài khoản nhận
116
+ amount: 150000, // Số tiền VNĐ
117
+ memo: "NAPTIEN DH1001", // Nội dung chuyển khoản
118
+ });
119
+
120
+ console.log(qr.qrDataUrl); // Chuỗi ảnh base64: "data:image/png;base64,..."
121
+ console.log(qr.qrImageUrl); // Link ảnh PNG trực tiếp: "https://api.rpay.vn/api/qr/vietqr.png?..."
122
+ ```
123
+
124
+ ### 2.4. `rpay.lsgd(...)` — Lấy Lịch sử Giao dịch (Bank, USDT hoặc Cả hai cùng lúc)
125
+
126
+ ```ts
127
+ // Lấy đồng thời cả LSGD Ngân hàng + LSGD USDT trong 1 lệnh duy nhất:
128
+ const history = await rpay.lsgd({
129
+ channel: "all", // "bank" | "usdt" | "all"
130
+ bank: "VCB",
131
+ limit: 50,
132
+ });
133
+
134
+ console.log(history.transactions); // Mảng giao dịch đã chuẩn hóa chung cho cả Bank & USDT
135
+ ```
136
+
137
+ ---
138
+
139
+ ## 3. Tích hợp Nhận Webhook Tự động Cộng tiền (Next.js & Express.js)
140
+
141
+ SDK cung cấp sẵn handler tự động kiểm tra chữ ký bảo mật `HMAC-SHA256` (chống giả mạo 100%) và gộp chung sự kiện thanh toán của **Bank Invoice (`bank.invoice.paid`)**, **USDT Store (`crypto.invoice.paid`)** và **Biến động số dư (`bank.transactions`)** vào callback `onPaid`:
142
+
143
+ ### 3.1. Tích hợp vào Next.js App Router (`app/api/webhooks/rpay/route.ts`)
144
+
145
+ ```ts
146
+ import rpay from "rpay-sdk";
147
+
148
+ export const POST = rpay.webhooks.nextAppRouterHandler({
149
+ // Tự động đọc RPAY_WEBHOOK_SECRET từ .env (hoặc truyền secret: "..." tại đây)
150
+ onPaid: async (event) => {
151
+ // event.channel: "bank" | "usdt"
152
+ // event.orderId: Mã đơn hàng của bạn (VD: "DH1001")
153
+ // event.invoiceCode: Mã hóa đơn RPAY ("RPINV..." hoặc "USINV...")
154
+ // event.paidAmount: Số tiền thực nhận (VNĐ hoặc USDT)
155
+ // event.currency: "VND" | "USDT" | "USDC"
156
+ // event.transactionId: Mã FT ngân hàng hoặc TxHash Blockchain
157
+
158
+ console.log(`[RPAY Webhook] Đơn ${event.orderId} đã thanh toán ${event.paidAmount} ${event.currency}`);
159
+ // TODO: Kiểm tra đơn hàng chưa cộng tiền trong DB -> Cộng tiền & đánh dấu hoàn tất
160
+ },
161
+ onTransactions: async (event) => {
162
+ // Nhận mảng giao dịch biến động số dư trực tiếp (STC / SePay mode)
163
+ console.log("Biến động số dư mới:", event.networkOrBank, event.transactions);
164
+ },
165
+ });
166
+ ```
167
+
168
+ ### 3.2. Tích hợp vào Express.js / Node.js (`server.js`)
169
+
170
+ ```ts
171
+ import express from "express";
172
+ import rpay from "rpay-sdk";
173
+
174
+ const app = express();
175
+ app.use(express.json());
176
+
177
+ app.post(
178
+ "/api/webhooks/rpay",
179
+ rpay.webhooks.expressHandler({
180
+ onPaid: async (event) => {
181
+ console.log(`Đơn ${event.orderId} (${event.channel}) đã thanh toán:`, event.paidAmount, event.currency);
182
+ // Cộng tiền cho khách tại đây
183
+ },
184
+ })
185
+ );
186
+ ```
187
+
188
+ ---
189
+
190
+ ## 4. Tích hợp Cronjob Lấy Lịch sử Giao dịch (LSGD) & Đối soát Chống Trùng
191
+
192
+ Nếu hệ thống của bạn dùng cơ chế **Cronjob quét LSGD định kỳ** (mỗi 10–30 giây) thay vì Webhook, sử dụng cặp `rpay.lsgd(...)` + `rpay.matchPayment(...)`:
193
+
194
+ ```ts
195
+ import rpay from "rpay-sdk";
196
+
197
+ // Tập hợp lưu các mã giao dịch đã xử lý (Trong thực tế lưu vào bảng database unique transactionID)
198
+ const processedTxIds = new Set<string>();
199
+
200
+ async function cronCheckPayments(pendingOrders: Array<{ orderCode: string; amount: number }>) {
201
+ // 1. Lấy lịch sử giao dịch của cả Bank (V2) và USDT
202
+ const { transactions } = await rpay.lsgd({
203
+ channel: "all", // Hoặc "bank" nếu chỉ dùng ngân hàng, "usdt" nếu chỉ dùng crypto
204
+ bank: "VCB",
205
+ limit: 50,
206
+ });
207
+
208
+ // 2. Duyệt từng đơn hàng đang chờ và so khớp tự động
209
+ for (const order of pendingOrders) {
210
+ const matches = rpay.matchPayment(transactions, {
211
+ orderCode: order.orderCode, // Tự động khớp nội dung CK (kể cả khách gõ cách chữ "DH 1001")
212
+ expectedAmount: order.amount, // Số tiền nhận >= số tiền đơn hàng
213
+ processedIds: processedTxIds, // Chống cộng tiền trùng tuyệt đối
214
+ mutateProcessedIds: true, // Tự động thêm transactionID vào processedTxIds sau khi khớp
215
+ });
216
+
217
+ if (matches.length > 0) {
218
+ const tx = matches[0];
219
+ console.log(`Đã khớp đơn ${order.orderCode} qua kênh ${tx.channel}: +${tx.amount} ${tx.currency} (Mã GD: ${tx.transactionID})`);
220
+ // Cập nhật đơn hàng thành công trong Database
221
+ }
222
+ }
223
+ }
224
+ ```
225
+
226
+ ---
227
+
228
+ ## 5. Cách dùng trên Nhiều Tên Miền (Multi-Domain / Web Con / Nhiều Shop)
229
+
230
+ Khi bạn vận hành nhiều website con (White-label) hoặc nhiều cửa hàng trên cùng 1 mã nguồn:
231
+
232
+ ```ts
233
+ import rpay from "rpay-sdk";
234
+
235
+ // Cách A: Tạo instance riêng cho từng domain bằng `rpay.forDomain(...)`
236
+ const site1 = rpay.forDomain("pay.daily1.vn", {
237
+ bankToken: "rpay_vcb_live_site1...",
238
+ usdtKey: "ukey_site1...",
239
+ });
240
+
241
+ const site2 = rpay.forDomain("pay.daily2.com", {
242
+ bankToken: "rpay_acb_live_site2...",
243
+ usdtKey: "ukey_site2...",
244
+ });
245
+
246
+ const inv1 = await site1.pay({ amount: 100000, orderId: "S1-001" });
247
+ const inv2 = await site2.pay({ amount: 50, currency: "USDT", network: "BEP20", orderId: "S2-001" });
248
+
249
+ // Cách B: Truyền trực tiếp `domain` vào từng lệnh gọi
250
+ const historySite2 = await rpay.lsgd({
251
+ domain: "pay.daily2.com",
252
+ channel: "bank",
253
+ bank: "ACB",
254
+ });
255
+ ```
256
+
257
+ ---
258
+
259
+ ## 6. Quantum Router Hub (`rpay.route`) & Lịch sử V2 / V3 / POS Chi tiết
260
+
261
+ ```ts
262
+ // 6.1. Quantum Router Hub
263
+ const routerStatus = await rpay.route({
264
+ provider: "9ROUTER",
265
+ security: "HMAC_256",
266
+ coalesced: "498.310 req",
267
+ });
268
+
269
+ // 6.2. Gọi trực tiếp chuẩn V2 / POS / V3 của từng ngân hàng
270
+ const v2 = await rpay.banks.v2({ bank: "VCB", limit: 30 });
271
+ const pos = await rpay.banks.pos({ fromDate: "01/11/2026", toDate: "05/11/2026" });
272
+
273
+ // 6.3. Chuẩn V3 (Xác thực 3FA mật khẩu + số tài khoản + token, tự mã hóa ký tự # thành %23)
274
+ const v3 = await rpay.banks.v3({
275
+ bank: "ACB",
276
+ password: "MatKhau#2026",
277
+ accountNumber: "0123456789",
278
+ });
279
+
280
+ // Với Viettel Money (vtm / vtp), V3 tự động nhận { phone, pin, token }:
281
+ const vtm = await rpay.banks.v3({
282
+ bank: "viettelpay",
283
+ phone: "0988123456",
284
+ pin: "123456",
285
+ });
286
+ ```
287
+
288
+ ---
289
+
290
+ ## 7. Bảng Mã 15 Ngân hàng & 18 Mạng lưới USDT/USDC
291
+
292
+ ### 7.1. 15 Ngân hàng & Ví điện tử Việt Nam (`RPAY_BANKS`)
293
+
294
+ | Ngân hàng | Mã `bank` (`code`) | Slug API (`primarySlug`) | Mã BIN VietQR | Ghi chú V3 |
295
+ | :--- | :--- | :--- | :--- | :--- |
296
+ | **Vietcombank** | `VCB` | `vcb` | `970436` | `password` + `accountNumber` + `token` |
297
+ | **ACB** | `ACB` | `acb` | `970416` | `password` + `accountNumber` + `token` |
298
+ | **MBBank** | `MB` | `mb` | `970422` | `password` + `accountNumber` + `token` |
299
+ | **Techcombank** | `TCB` | `tcb` | `970407` | `password` + `accountNumber` + `token` |
300
+ | **BIDV** | `BIDV` | `bidv` | `970418` | `password` + `accountNumber` + `token` |
301
+ | **VietinBank** | `ICB` | `icb` | `970415` | `password` + `accountNumber` + `token` |
302
+ | **VPBank** | `VPB` | `vpb` | `970432` | `password` + `accountNumber` + `token` |
303
+ | **TPBank** | `TPB` | `tpb` | `970423` | `password` + `accountNumber` + `token` |
304
+ | **Agribank** | `VBA` | `vba` | `970405` | `password` + `accountNumber` + `token` |
305
+ | **MSB** | `MSB` | `msb` | `970426` | `password` + `accountNumber` + `token` |
306
+ | **OCB** | `OCB` | `ocb` | `970448` | `password` + `accountNumber` + `token` |
307
+ | **SeABank** | `SEAB` | `seabank` | `970440` | `password` + `accountNumber` + `token` |
308
+ | **Eximbank** | `EIB` | `eib` | `970431` | `password` + `accountNumber` + `token` |
309
+ | **BVBank** | `BVB` | `bvb` | `970454` | `password` + `accountNumber` + `token` |
310
+ | **Viettel Money** | `VTP` | `vtm` | `971005` | Dùng `phone` + `pin` (6 số) + `token` |
311
+
312
+ ### 7.2. 18 Mạng lưới Blockchain USDT / USDC (`RPAY_USDT_NETWORKS`)
313
+
314
+ `TRC20` (TRON), `BEP20` (BNB Smart Chain), `ERC20` (Ethereum), `POLYGON`, `ARBITRUM`, `OPTIMISM`, `SOLANA`, `TON`, `BASE`, `AVALANCHE`, `APTOS`, `SUI`, `OPBNB`, `CELO`, `SCROLL`, `KAVA`, `POLKADOT`, `OSMOSIS`.
315
+
316
+ ---
317
+
318
+ ## 8. Hướng dẫn Đẩy gói lên NPM (`npm publish`)
319
+
320
+ ```powershell
321
+ cd C:\Users\kotin\Desktop\rpayv2\plugin\npmjs
322
+
323
+ # 1. Chạy bộ kiểm thử tự động
324
+ npm test
325
+
326
+ # 2. Đăng nhập tài khoản npmjs.com
327
+ npm login
328
+
329
+ # 3. Xuất bản lên npm
330
+ npm publish --access public
331
+ ```
package/index.cjs ADDED
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+
3
+ const esmModule = require("./src/index.mjs");
4
+ const rpayInstance = esmModule.rpay;
5
+
6
+ Object.assign(rpayInstance, esmModule, {
7
+ default: rpayInstance,
8
+ });
9
+
10
+ module.exports = rpayInstance;