telebirr-nodejs 1.0.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 +181 -0
- package/dist/index.cjs +489 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +104 -0
- package/dist/index.d.ts +104 -0
- package/dist/index.js +489 -0
- package/dist/index.js.map +1 -0
- package/package.json +39 -0
- package/tsconfig.json +21 -0
- package/tsup.config.ts +10 -0
package/README.md
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
telebirr-nodejs
|
|
2
|
+
|
|
3
|
+
A simple, opinionated Node.js SDK for integrating Telebirr C2B payments with automatic request signing, Fabric token handling, and checkout URL generation.
|
|
4
|
+
|
|
5
|
+
Installation
|
|
6
|
+
npm install telebirr-node
|
|
7
|
+
|
|
8
|
+
Required Configuration
|
|
9
|
+
|
|
10
|
+
Telebirr requires five credentials, plus callback URLs.
|
|
11
|
+
You should never hard-code secrets. Always load them from process.env.
|
|
12
|
+
|
|
13
|
+
Required Credentials
|
|
14
|
+
Name Description
|
|
15
|
+
FABRIC_APP_ID Fabric application ID
|
|
16
|
+
FABRIC_APP_SECRET Fabric application secret
|
|
17
|
+
MERCHANT_APP_ID Merchant application ID
|
|
18
|
+
MERCHANT_CODE Merchant code
|
|
19
|
+
MERCHANT_PRIVATE_KEY RSA private key (PEM string)
|
|
20
|
+
Required URLs
|
|
21
|
+
Name Description
|
|
22
|
+
TELEBIRR_NOTIFY_URL Server-to-server callback URL
|
|
23
|
+
TELEBIRR_REDIRECT_URL User redirect URL after payment
|
|
24
|
+
Basic Setup
|
|
25
|
+
import { TelebirrClient } from "telebirr-nodejs";
|
|
26
|
+
|
|
27
|
+
const client = new TelebirrClient({
|
|
28
|
+
mode: "sandbox", // "simulate" | "sandbox" | "production"
|
|
29
|
+
|
|
30
|
+
appId: process.env.FABRIC_APP_ID!,
|
|
31
|
+
appSecret: process.env.FABRIC_APP_SECRET!,
|
|
32
|
+
|
|
33
|
+
merchantAppId: process.env.MERCHANT_APP_ID!,
|
|
34
|
+
merchantCode: process.env.MERCHANT_CODE!,
|
|
35
|
+
privateKey: process.env.MERCHANT_PRIVATE_KEY!,
|
|
36
|
+
|
|
37
|
+
notifyUrl: process.env.TELEBIRR_NOTIFY_URL!,
|
|
38
|
+
redirectUrl: process.env.TELEBIRR_REDIRECT_URL!,
|
|
39
|
+
|
|
40
|
+
http: true, // allow HTTP in simulator mode
|
|
41
|
+
IntegrationOption: "C2B",
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
Important
|
|
45
|
+
|
|
46
|
+
MERCHANT_PRIVATE_KEY must be the full PEM string, including:
|
|
47
|
+
|
|
48
|
+
-----BEGIN RSA PRIVATE KEY-----
|
|
49
|
+
|
|
50
|
+
and
|
|
51
|
+
|
|
52
|
+
-----END RSA PRIVATE KEY-----
|
|
53
|
+
|
|
54
|
+
Example API Routes
|
|
55
|
+
|
|
56
|
+
Below is a complete demo using three routes:
|
|
57
|
+
|
|
58
|
+
POST /payment/initiate
|
|
59
|
+
|
|
60
|
+
GET /payment/status/:merchOrderId
|
|
61
|
+
|
|
62
|
+
POST /payment/refund
|
|
63
|
+
|
|
64
|
+
Initiate Payment
|
|
65
|
+
|
|
66
|
+
Creates an order and redirects the user to the Telebirr checkout page.
|
|
67
|
+
|
|
68
|
+
app.post("/payment/initiate", async (req, res) => {
|
|
69
|
+
const checkoutUrl = await client.preOrder({
|
|
70
|
+
merchOrderId: "order123",
|
|
71
|
+
title: "Phone",
|
|
72
|
+
amount: "12",
|
|
73
|
+
callbackInfo: "from web checkout",
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
res.redirect(checkoutUrl);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
What happens internally
|
|
80
|
+
|
|
81
|
+
Fabric token is fetched and cached
|
|
82
|
+
|
|
83
|
+
Order is signed and created
|
|
84
|
+
|
|
85
|
+
Checkout URL is generated
|
|
86
|
+
|
|
87
|
+
User is redirected to Telebirr
|
|
88
|
+
|
|
89
|
+
If you are using a frontend framework (e.g. React) and do not want to lose application state, return the checkout URL as JSON and let the frontend handle the redirection.
|
|
90
|
+
|
|
91
|
+
Query Payment Status
|
|
92
|
+
|
|
93
|
+
Used to check the payment result using the merchant order ID.
|
|
94
|
+
|
|
95
|
+
app.get("/payment/status/:merchOrderId", async (req, res) => {
|
|
96
|
+
const { merchOrderId } = req.params;
|
|
97
|
+
|
|
98
|
+
const info = await client.queryOrder(merchOrderId);
|
|
99
|
+
|
|
100
|
+
res.json(info);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
Typical Use Cases
|
|
104
|
+
|
|
105
|
+
Payment confirmation pages
|
|
106
|
+
|
|
107
|
+
Background reconciliation jobs
|
|
108
|
+
|
|
109
|
+
Admin dashboards
|
|
110
|
+
|
|
111
|
+
Refund Payment
|
|
112
|
+
|
|
113
|
+
Refunds a completed transaction.
|
|
114
|
+
|
|
115
|
+
app.post("/payment/refund", async (req, res) => {
|
|
116
|
+
const refundData = await client.refundOrder({
|
|
117
|
+
merchOrderId: "order123",
|
|
118
|
+
refundRequestNo: "original-transaction-id",
|
|
119
|
+
refundReason: "customer request",
|
|
120
|
+
amount: "12",
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
res.json(refundData);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
Notes
|
|
127
|
+
|
|
128
|
+
refundRequestNo must be unique
|
|
129
|
+
|
|
130
|
+
Refund amount must not exceed the original payment amount
|
|
131
|
+
|
|
132
|
+
Simulator Mode
|
|
133
|
+
|
|
134
|
+
To use the simulator provided by this package, set the mode to simulate.
|
|
135
|
+
|
|
136
|
+
import { TelebirrClient } from "telebirr-nodejs";
|
|
137
|
+
|
|
138
|
+
const client = new TelebirrClient({
|
|
139
|
+
mode: "simulate",
|
|
140
|
+
notifyUrl: "https://example.com/notify",
|
|
141
|
+
redirectUrl: "https://example.com/redirect",
|
|
142
|
+
http: true,
|
|
143
|
+
IntegrationOption: "C2B",
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
This simulator is for learning and development purposes only.
|
|
147
|
+
The simulation server is provided by this package, not by Telebirr.
|
|
148
|
+
|
|
149
|
+
For real testing, use Telebirr’s sandbox mode and whitelist your public IP address in the Telebirr portal.
|
|
150
|
+
|
|
151
|
+
Supported Features
|
|
152
|
+
|
|
153
|
+
Fabric token handling
|
|
154
|
+
|
|
155
|
+
RSA-SHA256 request signing
|
|
156
|
+
|
|
157
|
+
C2B checkout
|
|
158
|
+
|
|
159
|
+
Order query
|
|
160
|
+
|
|
161
|
+
Refunds
|
|
162
|
+
|
|
163
|
+
Simulator support
|
|
164
|
+
|
|
165
|
+
Notify URL Handling
|
|
166
|
+
|
|
167
|
+
Please refer to Telebirr’s official documentation to correctly handle notify callbacks:
|
|
168
|
+
|
|
169
|
+
https://developer.ethiotelecom.et/docs/H5%20C2B%20Web%20Payment%20Integration%20Quick%20Guide/Notify_Callback
|
|
170
|
+
|
|
171
|
+
you can generate private and public keys instantly
|
|
172
|
+
import { generateKeys } from "telebirr-nodejs";
|
|
173
|
+
|
|
174
|
+
generateKeys({
|
|
175
|
+
dir: process.cwd(),
|
|
176
|
+
privateKeyName: "telefy_private.pem",
|
|
177
|
+
publicKeyName: "telefy_public.pem",
|
|
178
|
+
overwrite: false,
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
this will add two files .pem in your rook directory you can configure them as u want but always remember the merchantPrivateKey option always accepts a string value so u have to read use fs module and pass the returned value to the option
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,489 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } var _class;// src/utils/credentials.ts
|
|
2
|
+
var _fs = require('fs'); var _fs2 = _interopRequireDefault(_fs);
|
|
3
|
+
var _crypto = require('crypto'); var _crypto2 = _interopRequireDefault(_crypto);
|
|
4
|
+
var _nanoid = require('nanoid');
|
|
5
|
+
|
|
6
|
+
// src/utils/keys.ts
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
var _path = require('path'); var _path2 = _interopRequireDefault(_path);
|
|
10
|
+
function generateKeys(options = {}) {
|
|
11
|
+
const {
|
|
12
|
+
dir = process.cwd(),
|
|
13
|
+
privateKeyName = "telebirr_private.pem",
|
|
14
|
+
publicKeyName = "telebirr_public.pem",
|
|
15
|
+
overwrite = false
|
|
16
|
+
} = options;
|
|
17
|
+
const privateKeyPath = _path2.default.join(dir, privateKeyName);
|
|
18
|
+
const publicKeyPath = _path2.default.join(dir, publicKeyName);
|
|
19
|
+
const exists = _fs2.default.existsSync(privateKeyPath) && _fs2.default.existsSync(publicKeyPath);
|
|
20
|
+
if (exists && !overwrite) {
|
|
21
|
+
return { privateKeyPath, publicKeyPath };
|
|
22
|
+
}
|
|
23
|
+
const { privateKey, publicKey } = _crypto.generateKeyPairSync.call(void 0, "rsa", {
|
|
24
|
+
modulusLength: 2048,
|
|
25
|
+
publicKeyEncoding: {
|
|
26
|
+
type: "pkcs1",
|
|
27
|
+
format: "pem"
|
|
28
|
+
},
|
|
29
|
+
privateKeyEncoding: {
|
|
30
|
+
type: "pkcs1",
|
|
31
|
+
format: "pem"
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
_fs2.default.writeFileSync(privateKeyPath, privateKey, { mode: 384 });
|
|
35
|
+
_fs2.default.writeFileSync(publicKeyPath, publicKey);
|
|
36
|
+
return { privateKeyPath, publicKeyPath };
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// src/utils/credentials.ts
|
|
40
|
+
var numeric16 = _nanoid.customAlphabet.call(void 0, "0123456789", 16);
|
|
41
|
+
var numeric6 = _nanoid.customAlphabet.call(void 0, "0123456789", 6);
|
|
42
|
+
function generateCredentials() {
|
|
43
|
+
const { privateKeyPath } = generateKeys();
|
|
44
|
+
const merchantPrivateKey = _fs2.default.readFileSync(privateKeyPath, "utf8");
|
|
45
|
+
return {
|
|
46
|
+
fabricAppId: _crypto.randomUUID.call(void 0, ),
|
|
47
|
+
fabricAppSecret: _crypto.randomBytes.call(void 0, 16).toString("hex"),
|
|
48
|
+
merchantAppId: numeric16(),
|
|
49
|
+
merchantCode: numeric6(),
|
|
50
|
+
merchantPrivateKey
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// src/services/requestToken.ts
|
|
55
|
+
var _http = require('http'); var _http2 = _interopRequireDefault(_http);
|
|
56
|
+
var _https = require('https'); var _https2 = _interopRequireDefault(_https);
|
|
57
|
+
|
|
58
|
+
// src/constants/urls.ts
|
|
59
|
+
var TELEBIRR_URLS = {
|
|
60
|
+
sandbox: {
|
|
61
|
+
apiBase: "https://developerportal.ethiotelebirr.et:38443/apiaccess/payment/gateway",
|
|
62
|
+
webBase: "https://developerportal.ethiotelebirr.et:38443/payment/web/paygate?"
|
|
63
|
+
},
|
|
64
|
+
production: {
|
|
65
|
+
apiBase: "https://telebirrappcube.ethiomobilemoney.et:38443/apiaccess/payment/gateway",
|
|
66
|
+
webBase: "https://telebirrappcube.ethiomobilemoney.et:38443/payment/web/paygate?"
|
|
67
|
+
},
|
|
68
|
+
simulate: {
|
|
69
|
+
apiBase: "http://localhost:3000",
|
|
70
|
+
webBase: "http://localhost:3000/web/?"
|
|
71
|
+
}
|
|
72
|
+
// simulate: {
|
|
73
|
+
// apiBase: "https://telebirr-node-simulator.onrender.com",
|
|
74
|
+
// webBase: "https://telebirr-node-simulator.onrender.com/web/?",
|
|
75
|
+
// },
|
|
76
|
+
};
|
|
77
|
+
var CHECKOUT_OTHER_PARAMS = "&version=1.0&trade_type=Checkout";
|
|
78
|
+
|
|
79
|
+
// src/services/requestToken.ts
|
|
80
|
+
function requestToken(config) {
|
|
81
|
+
const isHttps = TELEBIRR_URLS[config.mode].apiBase.startsWith("https://");
|
|
82
|
+
const client = isHttps ? _https2.default : _http2.default;
|
|
83
|
+
return new Promise((resolve, reject) => {
|
|
84
|
+
const req = client.request(
|
|
85
|
+
` ${TELEBIRR_URLS[config.mode].apiBase}/payment/v1/token`,
|
|
86
|
+
{
|
|
87
|
+
method: "POST",
|
|
88
|
+
headers: {
|
|
89
|
+
"Content-Type": "application/json",
|
|
90
|
+
"X-APP-Key": config.appId
|
|
91
|
+
},
|
|
92
|
+
...isHttps && { rejectUnauthorized: false }
|
|
93
|
+
},
|
|
94
|
+
(res) => {
|
|
95
|
+
let body = "";
|
|
96
|
+
res.on("data", (chunk) => body += chunk);
|
|
97
|
+
res.on("end", () => resolve(body));
|
|
98
|
+
}
|
|
99
|
+
);
|
|
100
|
+
req.on("error", reject);
|
|
101
|
+
req.write(JSON.stringify({ appSecret: config.appSecret }));
|
|
102
|
+
req.end();
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// src/services/requestCreateOrder.ts
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
// src/utils/nonce.ts
|
|
111
|
+
|
|
112
|
+
function createNonceStr() {
|
|
113
|
+
const bytes = Math.ceil(16);
|
|
114
|
+
return _crypto.randomBytes.call(void 0, bytes).toString("hex").slice(0, 32);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// src/utils/timestamp.ts
|
|
118
|
+
function createTimestamp() {
|
|
119
|
+
return Math.floor(Date.now() / 1e3).toString();
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// src/utils/signature.ts
|
|
123
|
+
|
|
124
|
+
function flattenParams(params) {
|
|
125
|
+
const flat = {};
|
|
126
|
+
for (const key in params) {
|
|
127
|
+
const value = params[key];
|
|
128
|
+
if (value === void 0 || value === null || value === "" || key === "sign" || key === "signType" || key === "sign_type") {
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
if (key === "biz_content" && typeof value === "object") {
|
|
132
|
+
for (const bizKey in value) {
|
|
133
|
+
const bizValue = value[bizKey];
|
|
134
|
+
if (bizValue !== void 0 && bizValue !== null && bizValue !== "") {
|
|
135
|
+
flat[bizKey] = String(bizValue);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
} else {
|
|
139
|
+
flat[key] = String(value);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return flat;
|
|
143
|
+
}
|
|
144
|
+
function buildSignString(params) {
|
|
145
|
+
const flat = flattenParams(params);
|
|
146
|
+
return Object.keys(flat).sort().map((key) => `${key}=${flat[key]}`).join("&");
|
|
147
|
+
}
|
|
148
|
+
function signRequest(data, privateKey) {
|
|
149
|
+
const signString = buildSignString(data);
|
|
150
|
+
return _crypto2.default.createSign("RSA-SHA256").update(signString, "utf8").sign(privateKey, "base64");
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// src/services/requestCreateOrder.ts
|
|
154
|
+
function requestCreateOrder(fabricToken, input, config) {
|
|
155
|
+
const reqBody = {
|
|
156
|
+
timestamp: createTimestamp(),
|
|
157
|
+
nonce_str: createNonceStr(),
|
|
158
|
+
method: "payment.preorder",
|
|
159
|
+
version: "1.0",
|
|
160
|
+
biz_content: {
|
|
161
|
+
appid: config.merchantAppId,
|
|
162
|
+
merch_code: config.merchantCode,
|
|
163
|
+
merch_order_id: input.merchOrderId,
|
|
164
|
+
notify_url: config.notifyUrl,
|
|
165
|
+
redirect_url: config.redirectUrl,
|
|
166
|
+
trade_type: "Checkout",
|
|
167
|
+
title: input.title,
|
|
168
|
+
total_amount: input.amount,
|
|
169
|
+
trans_currency: "ETB",
|
|
170
|
+
timeout_express: "120m",
|
|
171
|
+
business_type: "BuyGoods",
|
|
172
|
+
payee_type: "3000",
|
|
173
|
+
payee_identifier: config.merchantCode,
|
|
174
|
+
payee_identifier_type: "04",
|
|
175
|
+
callback_info: "From web"
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
reqBody.sign = signRequest(reqBody, config.privateKey);
|
|
179
|
+
reqBody.sign_type = "SHA256WithRSA";
|
|
180
|
+
const payload = JSON.stringify(reqBody);
|
|
181
|
+
const baseUrl = TELEBIRR_URLS[config.mode].apiBase;
|
|
182
|
+
const isHttps = baseUrl.startsWith("https://");
|
|
183
|
+
const client = isHttps ? _https2.default : _http2.default;
|
|
184
|
+
return new Promise((resolve, reject) => {
|
|
185
|
+
const req = client.request(
|
|
186
|
+
`${baseUrl}/payment/v1/merchant/preOrder`,
|
|
187
|
+
{
|
|
188
|
+
method: "POST",
|
|
189
|
+
headers: {
|
|
190
|
+
"Content-Type": "application/json",
|
|
191
|
+
"Content-Length": Buffer.byteLength(payload),
|
|
192
|
+
"X-APP-Key": config.appId,
|
|
193
|
+
Authorization: fabricToken
|
|
194
|
+
},
|
|
195
|
+
...isHttps && { rejectUnauthorized: false }
|
|
196
|
+
},
|
|
197
|
+
(res) => {
|
|
198
|
+
let raw = "";
|
|
199
|
+
res.on("data", (chunk) => {
|
|
200
|
+
raw += chunk;
|
|
201
|
+
});
|
|
202
|
+
res.on("end", () => {
|
|
203
|
+
const status = res.statusCode || 0;
|
|
204
|
+
let parsed = raw;
|
|
205
|
+
try {
|
|
206
|
+
parsed = JSON.parse(raw);
|
|
207
|
+
} catch (e) {
|
|
208
|
+
}
|
|
209
|
+
if (status < 200 || status >= 300) {
|
|
210
|
+
return reject({
|
|
211
|
+
message: "Telebirr preorder request failed",
|
|
212
|
+
status,
|
|
213
|
+
data: parsed,
|
|
214
|
+
headers: res.headers
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
resolve({
|
|
218
|
+
data: parsed,
|
|
219
|
+
status,
|
|
220
|
+
headers: res.headers
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
);
|
|
225
|
+
req.on("error", (err) => {
|
|
226
|
+
reject({
|
|
227
|
+
message: "Telebirr preorder network error",
|
|
228
|
+
cause: err,
|
|
229
|
+
code: err.code
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
req.write(payload);
|
|
233
|
+
req.end();
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// src/services/requestRefundOrder.ts
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
function requestRefund(fabricToken, input, config) {
|
|
241
|
+
const reqBody = {
|
|
242
|
+
timestamp: createTimestamp(),
|
|
243
|
+
nonce_str: createNonceStr(),
|
|
244
|
+
method: "payment.refund",
|
|
245
|
+
version: "1.0",
|
|
246
|
+
biz_content: {
|
|
247
|
+
appid: config.merchantAppId,
|
|
248
|
+
merch_code: config.merchantCode,
|
|
249
|
+
merch_order_id: input.merchOrderId,
|
|
250
|
+
trans_currency: "ETB",
|
|
251
|
+
actual_amount: input.amount,
|
|
252
|
+
refund_request_no: input.refundRequestNo,
|
|
253
|
+
refund_reason: input.refundReason
|
|
254
|
+
}
|
|
255
|
+
};
|
|
256
|
+
reqBody.sign = signRequest(reqBody, config.privateKey);
|
|
257
|
+
reqBody.sign_type = "SHA256WithRSA";
|
|
258
|
+
const payload = JSON.stringify(reqBody);
|
|
259
|
+
const baseUrl = TELEBIRR_URLS[config.mode].apiBase;
|
|
260
|
+
const isHttps = baseUrl.startsWith("https://");
|
|
261
|
+
const client = isHttps ? _https2.default : _http2.default;
|
|
262
|
+
return new Promise((resolve, reject) => {
|
|
263
|
+
const req = client.request(
|
|
264
|
+
`${baseUrl}/payment/v1/merchant/refund`,
|
|
265
|
+
{
|
|
266
|
+
method: "POST",
|
|
267
|
+
headers: {
|
|
268
|
+
"Content-Type": "application/json",
|
|
269
|
+
"Content-Length": Buffer.byteLength(payload),
|
|
270
|
+
"X-APP-Key": config.appId,
|
|
271
|
+
Authorization: fabricToken
|
|
272
|
+
},
|
|
273
|
+
...isHttps && { rejectUnauthorized: false }
|
|
274
|
+
},
|
|
275
|
+
(res) => {
|
|
276
|
+
let raw = "";
|
|
277
|
+
res.on("data", (chunk) => {
|
|
278
|
+
raw += chunk;
|
|
279
|
+
});
|
|
280
|
+
res.on("end", () => {
|
|
281
|
+
const status = res.statusCode || 0;
|
|
282
|
+
let parsed = raw;
|
|
283
|
+
try {
|
|
284
|
+
parsed = JSON.parse(raw);
|
|
285
|
+
} catch (e2) {
|
|
286
|
+
}
|
|
287
|
+
if (status < 200 || status >= 300) {
|
|
288
|
+
return reject({
|
|
289
|
+
message: "Telebirr refund request failed",
|
|
290
|
+
status,
|
|
291
|
+
data: parsed,
|
|
292
|
+
headers: res.headers
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
resolve({
|
|
296
|
+
data: parsed,
|
|
297
|
+
status,
|
|
298
|
+
headers: res.headers
|
|
299
|
+
});
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
);
|
|
303
|
+
req.on("error", (err) => {
|
|
304
|
+
reject({
|
|
305
|
+
message: "Telebirr refund network error",
|
|
306
|
+
cause: err,
|
|
307
|
+
code: err.code
|
|
308
|
+
});
|
|
309
|
+
});
|
|
310
|
+
req.write(payload);
|
|
311
|
+
req.end();
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// src/services/requestQueryOrder.ts
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
function requestQueryOrder(fabricToken, merchOrderId, config) {
|
|
319
|
+
const reqBody = {
|
|
320
|
+
timestamp: createTimestamp(),
|
|
321
|
+
nonce_str: createNonceStr(),
|
|
322
|
+
method: "payment.queryorder",
|
|
323
|
+
version: "1.0",
|
|
324
|
+
biz_content: {
|
|
325
|
+
appid: config.merchantAppId,
|
|
326
|
+
merch_code: config.merchantCode,
|
|
327
|
+
merch_order_id: merchOrderId
|
|
328
|
+
}
|
|
329
|
+
};
|
|
330
|
+
reqBody.sign = signRequest(reqBody, config.privateKey);
|
|
331
|
+
reqBody.sign_type = "SHA256WithRSA";
|
|
332
|
+
const payload = JSON.stringify(reqBody);
|
|
333
|
+
const baseUrl = TELEBIRR_URLS[config.mode].apiBase;
|
|
334
|
+
const isHttps = baseUrl.startsWith("https://");
|
|
335
|
+
const client = isHttps ? _https2.default : _http2.default;
|
|
336
|
+
return new Promise((resolve, reject) => {
|
|
337
|
+
const req = client.request(
|
|
338
|
+
`${baseUrl}/payment/v1/merchant/queryOrder`,
|
|
339
|
+
{
|
|
340
|
+
method: "POST",
|
|
341
|
+
headers: {
|
|
342
|
+
"Content-Type": "application/json",
|
|
343
|
+
"Content-Length": Buffer.byteLength(payload),
|
|
344
|
+
"X-APP-Key": config.appId,
|
|
345
|
+
Authorization: fabricToken
|
|
346
|
+
},
|
|
347
|
+
...isHttps && { rejectUnauthorized: false }
|
|
348
|
+
},
|
|
349
|
+
(res) => {
|
|
350
|
+
let raw = "";
|
|
351
|
+
res.on("data", (chunk) => {
|
|
352
|
+
raw += chunk;
|
|
353
|
+
});
|
|
354
|
+
res.on("end", () => {
|
|
355
|
+
const status = res.statusCode || 0;
|
|
356
|
+
let parsed = raw;
|
|
357
|
+
try {
|
|
358
|
+
parsed = JSON.parse(raw);
|
|
359
|
+
} catch (e3) {
|
|
360
|
+
}
|
|
361
|
+
if (status < 200 || status >= 300) {
|
|
362
|
+
return reject({
|
|
363
|
+
message: "Telebirr queryOrder request failed",
|
|
364
|
+
status,
|
|
365
|
+
data: parsed,
|
|
366
|
+
headers: res.headers
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
resolve({
|
|
370
|
+
data: parsed,
|
|
371
|
+
status,
|
|
372
|
+
headers: res.headers
|
|
373
|
+
});
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
);
|
|
377
|
+
req.on("error", (err) => {
|
|
378
|
+
reject({
|
|
379
|
+
message: "Telebirr queryOrder network error",
|
|
380
|
+
cause: err,
|
|
381
|
+
code: err.code
|
|
382
|
+
});
|
|
383
|
+
});
|
|
384
|
+
req.write(payload);
|
|
385
|
+
req.end();
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// src/client.ts
|
|
390
|
+
var TelebirrClient = (_class = class _TelebirrClient {
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
constructor(config) {
|
|
394
|
+
if (config.mode === "simulate") {
|
|
395
|
+
const creds = generateCredentials();
|
|
396
|
+
this.config = {
|
|
397
|
+
...config,
|
|
398
|
+
appId: _nullishCoalesce(config.appId, () => ( creds.fabricAppId)),
|
|
399
|
+
appSecret: _nullishCoalesce(config.appSecret, () => ( creds.fabricAppSecret)),
|
|
400
|
+
merchantAppId: _nullishCoalesce(config.merchantAppId, () => ( creds.merchantAppId)),
|
|
401
|
+
merchantCode: _nullishCoalesce(config.merchantCode, () => ( creds.merchantCode)),
|
|
402
|
+
privateKey: creds.merchantPrivateKey
|
|
403
|
+
};
|
|
404
|
+
} else {
|
|
405
|
+
this.config = config;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
async getFabricToken() {
|
|
409
|
+
if (this.token && !this.isTokenExpired(this.token)) {
|
|
410
|
+
return this.token;
|
|
411
|
+
}
|
|
412
|
+
let token = await requestToken(this.config);
|
|
413
|
+
token = JSON.parse(token);
|
|
414
|
+
if (!token) return;
|
|
415
|
+
this.token = token;
|
|
416
|
+
return token;
|
|
417
|
+
}
|
|
418
|
+
createCheckoutUrl(prepayId) {
|
|
419
|
+
const map = {
|
|
420
|
+
appid: this.config.merchantAppId,
|
|
421
|
+
merch_code: this.config.merchantCode,
|
|
422
|
+
nonce_str: createNonceStr(),
|
|
423
|
+
prepay_id: prepayId,
|
|
424
|
+
timestamp: createTimestamp()
|
|
425
|
+
};
|
|
426
|
+
const sign = signRequest(map, this.config.privateKey);
|
|
427
|
+
const rawRequest = [
|
|
428
|
+
`appid=${map.appid}`,
|
|
429
|
+
`merch_code=${map.merch_code}`,
|
|
430
|
+
`nonce_str=${map.nonce_str}`,
|
|
431
|
+
`prepay_id=${map.prepay_id}`,
|
|
432
|
+
`timestamp=${map.timestamp}`,
|
|
433
|
+
`sign=${sign}`,
|
|
434
|
+
`sign_type=SHA256WithRSA`
|
|
435
|
+
].join("&");
|
|
436
|
+
const webBase = TELEBIRR_URLS[this.config.mode].webBase;
|
|
437
|
+
return webBase + rawRequest + CHECKOUT_OTHER_PARAMS;
|
|
438
|
+
}
|
|
439
|
+
async preOrder(input) {
|
|
440
|
+
const token = await this.getFabricToken();
|
|
441
|
+
if (!token) return;
|
|
442
|
+
let response = await requestCreateOrder(
|
|
443
|
+
token.token,
|
|
444
|
+
input,
|
|
445
|
+
this.config
|
|
446
|
+
);
|
|
447
|
+
if (!response) return;
|
|
448
|
+
return this.createCheckoutUrl(response.data.biz_content.prepay_id);
|
|
449
|
+
}
|
|
450
|
+
async queryOrder(input) {
|
|
451
|
+
let token = await this.getFabricToken();
|
|
452
|
+
if (!token) return;
|
|
453
|
+
const response = await requestQueryOrder(
|
|
454
|
+
token.token,
|
|
455
|
+
input,
|
|
456
|
+
this.config
|
|
457
|
+
);
|
|
458
|
+
return response.data;
|
|
459
|
+
}
|
|
460
|
+
async refundOrder(input) {
|
|
461
|
+
const token = await this.getFabricToken();
|
|
462
|
+
if (!token) return;
|
|
463
|
+
const response = await requestRefund(token.token, input, this.config);
|
|
464
|
+
return response.data;
|
|
465
|
+
}
|
|
466
|
+
static __initStatic() {this.TOKEN_EXPIRY_SAFETY_WINDOW_MS = 5 * 60 * 1e3}
|
|
467
|
+
isTokenExpired(token) {
|
|
468
|
+
if (!token) {
|
|
469
|
+
return true;
|
|
470
|
+
}
|
|
471
|
+
const now = Date.now();
|
|
472
|
+
const expiry = this.parseTelebirrDate(token.expirationDate).getTime();
|
|
473
|
+
return now >= expiry - _TelebirrClient.TOKEN_EXPIRY_SAFETY_WINDOW_MS;
|
|
474
|
+
}
|
|
475
|
+
parseTelebirrDate(value) {
|
|
476
|
+
const year = Number(value.slice(0, 4));
|
|
477
|
+
const month = Number(value.slice(4, 6)) - 1;
|
|
478
|
+
const day = Number(value.slice(6, 8));
|
|
479
|
+
const hour = Number(value.slice(8, 10));
|
|
480
|
+
const minute = Number(value.slice(10, 12));
|
|
481
|
+
const second = Number(value.slice(12, 14));
|
|
482
|
+
return new Date(Date.UTC(year, month, day, hour, minute, second));
|
|
483
|
+
}
|
|
484
|
+
}, _class.__initStatic(), _class);
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
|
|
488
|
+
exports.TelebirrClient = TelebirrClient; exports.generateKeys = generateKeys;
|
|
489
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["c:\\Users\\Dell\\Desktop\\Projects\\telebirr-nodejs\\dist\\index.cjs"],"names":[],"mappings":"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;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,YAAA;AACA,cAAA;AACA,cAAA;AACA,cAAA;AACA,cAAA;AACA,YAAA;AACA,UAAA;AACA,UAAA;AACA,YAAA;AACA,YAAA;AACA,YAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,YAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,YAAA;AACA,cAAA;AACA,cAAA;AACA,cAAA;AACA,cAAA;AACA,YAAA;AACA,UAAA;AACA,UAAA;AACA,YAAA;AACA,YAAA;AACA,YAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,YAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,YAAA;AACA,cAAA;AACA,cAAA;AACA,cAAA;AACA,cAAA;AACA,YAAA;AACA,UAAA;AACA,UAAA;AACA,YAAA;AACA,YAAA;AACA,YAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA","file":"C:\\Users\\Dell\\Desktop\\Projects\\telebirr-nodejs\\dist\\index.cjs","sourcesContent":[null]}
|