telebirr-nodejs 1.0.3 → 1.0.5
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 +66 -82
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,11 +8,15 @@ A simple, opinionated Node.js SDK for integrating **Telebirr C2B payments** with
|
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
10
|
npm install telebirr-nodejs
|
|
11
|
-
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Required Configuration
|
|
14
|
+
|
|
12
15
|
Telebirr requires credentials and callback URLs.
|
|
13
16
|
You should never hard-code secrets. Always load them from process.env.
|
|
14
17
|
|
|
15
|
-
Required Credentials
|
|
18
|
+
### Required Credentials
|
|
19
|
+
|
|
16
20
|
| Name | Description |
|
|
17
21
|
| ---------------------- | ---------------------------- |
|
|
18
22
|
| `FABRIC_APP_ID` | Fabric application ID |
|
|
@@ -21,171 +25,151 @@ Required Credentials
|
|
|
21
25
|
| `MERCHANT_CODE` | Merchant code |
|
|
22
26
|
| `MERCHANT_PRIVATE_KEY` | RSA private key (PEM string) |
|
|
23
27
|
|
|
28
|
+
### Required URLs
|
|
24
29
|
|
|
25
|
-
Required URLs
|
|
26
30
|
| Name | Description |
|
|
27
31
|
| ----------------------- | ------------------------------- |
|
|
28
32
|
| `TELEBIRR_NOTIFY_URL` | Server-to-server callback URL |
|
|
29
33
|
| `TELEBIRR_REDIRECT_URL` | User redirect URL after payment |
|
|
30
34
|
|
|
35
|
+
### Basic Setup
|
|
31
36
|
|
|
32
|
-
|
|
37
|
+
```bash
|
|
33
38
|
import { TelebirrClient } from "telebirr-nodejs";
|
|
34
39
|
|
|
35
40
|
const client = new TelebirrClient({
|
|
36
41
|
mode: "sandbox", // "simulate" | "sandbox" | "production"
|
|
37
|
-
|
|
38
42
|
appId: process.env.FABRIC_APP_ID!,
|
|
39
43
|
appSecret: process.env.FABRIC_APP_SECRET!,
|
|
40
|
-
|
|
41
44
|
merchantAppId: process.env.MERCHANT_APP_ID!,
|
|
42
45
|
merchantCode: process.env.MERCHANT_CODE!,
|
|
43
46
|
privateKey: process.env.MERCHANT_PRIVATE_KEY!,
|
|
44
|
-
|
|
45
47
|
notifyUrl: process.env.TELEBIRR_NOTIFY_URL!,
|
|
46
48
|
redirectUrl: process.env.TELEBIRR_REDIRECT_URL!,
|
|
47
|
-
|
|
48
49
|
http: true, // allow HTTP in simulator mode
|
|
49
50
|
IntegrationOption: "C2B",
|
|
50
51
|
});
|
|
52
|
+
```
|
|
51
53
|
|
|
54
|
+
### Important
|
|
52
55
|
|
|
53
|
-
|
|
54
|
-
Important
|
|
55
56
|
MERCHANT_PRIVATE_KEY must be the full PEM string, including:
|
|
56
57
|
|
|
58
|
+
```bash
|
|
57
59
|
-----BEGIN RSA PRIVATE KEY-----
|
|
58
60
|
...
|
|
59
61
|
-----END RSA PRIVATE KEY-----
|
|
62
|
+
```
|
|
60
63
|
|
|
61
|
-
|
|
62
|
-
Example API Routes
|
|
64
|
+
### Example API Routes
|
|
63
65
|
|
|
64
66
|
Below is a complete demo using three routes:
|
|
65
67
|
|
|
66
68
|
POST /payment/initiate
|
|
67
|
-
|
|
68
69
|
GET /payment/status/:merchOrderId
|
|
69
|
-
|
|
70
70
|
POST /payment/refund
|
|
71
71
|
|
|
72
|
-
Initiate Payment
|
|
72
|
+
### 1 Initiate Payment
|
|
73
|
+
|
|
73
74
|
Creates an order and redirects the user to the Telebirr checkout page.
|
|
74
75
|
|
|
76
|
+
```bash
|
|
75
77
|
app.post("/payment/initiate", async (req, res) => {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
78
|
+
const checkoutUrl = await client.preOrder({
|
|
79
|
+
merchOrderId: "order123",
|
|
80
|
+
title: "Phone",
|
|
81
|
+
amount: "12",
|
|
82
|
+
callbackInfo: "from web checkout",
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
res.redirect(checkoutUrl);
|
|
84
86
|
});
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
What happens internally
|
|
88
|
-
|
|
89
|
-
Fabric token is fetched and cached
|
|
90
|
-
|
|
91
|
-
Order is signed and created
|
|
92
|
-
|
|
93
|
-
Checkout URL is generated
|
|
94
|
-
|
|
95
|
-
User is redirected to Telebirr
|
|
87
|
+
```
|
|
96
88
|
|
|
97
89
|
If you are using a frontend framework (for example React) and do not want to lose application state, return the checkout URL as JSON and let the frontend handle the redirection.
|
|
98
90
|
|
|
99
|
-
Query Payment Status
|
|
91
|
+
### 2 Query Payment Status
|
|
92
|
+
|
|
100
93
|
Used to check the payment result using the merchant order ID.
|
|
101
94
|
|
|
95
|
+
```bash
|
|
102
96
|
app.get("/payment/status/:merchOrderId", async (req, res) => {
|
|
103
|
-
|
|
97
|
+
const { merchOrderId } = req.body;
|
|
104
98
|
|
|
105
|
-
|
|
99
|
+
const info = await client.queryOrder(merchOrderId);
|
|
106
100
|
|
|
107
|
-
|
|
101
|
+
res.json(info);
|
|
108
102
|
});
|
|
103
|
+
```
|
|
109
104
|
|
|
105
|
+
### 3 Refund Payment
|
|
110
106
|
|
|
111
|
-
Typical Use Cases
|
|
112
|
-
Payment confirmation pages
|
|
113
|
-
|
|
114
|
-
Background reconciliation jobs
|
|
115
|
-
|
|
116
|
-
Admin dashboards
|
|
117
|
-
|
|
118
|
-
Refund Payment
|
|
119
107
|
Refunds a completed transaction.
|
|
120
108
|
|
|
109
|
+
```bash
|
|
121
110
|
app.post("/payment/refund", async (req, res) => {
|
|
122
|
-
const refundData = await client.refundOrder({
|
|
123
|
-
merchOrderId: "order123",
|
|
124
|
-
refundRequestNo: "original-transaction-id",
|
|
125
|
-
refundReason: "customer request",
|
|
126
|
-
amount: "12",
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
res.json(refundData);
|
|
130
|
-
});
|
|
131
111
|
|
|
132
|
-
|
|
133
|
-
|
|
112
|
+
const refundData = await client.refundOrder({
|
|
113
|
+
merchOrderId: "order123",
|
|
114
|
+
refundRequestNo: "original-transaction-id",
|
|
115
|
+
refundReason: "customer request",
|
|
116
|
+
amount: "12",
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
res.json(refundData);
|
|
120
|
+
});
|
|
121
|
+
```
|
|
134
122
|
|
|
135
123
|
Refund amount must not exceed the original payment amount
|
|
136
124
|
|
|
137
|
-
Simulator Mode
|
|
125
|
+
### Simulator Mode
|
|
138
126
|
|
|
139
127
|
To use the simulator provided by this package, set the mode to simulate.
|
|
140
128
|
|
|
129
|
+
```bash
|
|
141
130
|
import { TelebirrClient } from "telebirr-nodejs";
|
|
142
131
|
|
|
143
|
-
const client = new TelebirrClient({
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
});
|
|
150
|
-
|
|
132
|
+
const client = new TelebirrClient({
|
|
133
|
+
mode: "simulate",
|
|
134
|
+
notifyUrl: "https://example.com/notify",
|
|
135
|
+
redirectUrl: "https://example.com/redirect",
|
|
136
|
+
http: true,
|
|
137
|
+
IntegrationOption: "C2B",
|
|
138
|
+
});
|
|
139
|
+
```
|
|
151
140
|
|
|
152
141
|
This simulator is for learning and development purposes only.
|
|
153
|
-
The simulation server is provided by this package, not by Telebirr.
|
|
142
|
+
The simulation server is provided by this package, not by Telebirr. For real testing, use Telebirr’s sandbox mode and whitelist your public IP address in the Telebirr portal.
|
|
154
143
|
|
|
155
|
-
|
|
144
|
+
### Supported Features
|
|
156
145
|
|
|
157
|
-
Supported Features
|
|
158
146
|
Fabric token handling
|
|
159
|
-
|
|
160
147
|
RSA-SHA256 request signing
|
|
161
|
-
|
|
162
148
|
C2B checkout
|
|
163
|
-
|
|
164
149
|
Order query
|
|
165
|
-
|
|
166
150
|
Refunds
|
|
167
|
-
|
|
168
151
|
Simulator support
|
|
169
|
-
|
|
170
152
|
Notify URL Handling
|
|
153
|
+
|
|
171
154
|
Please refer to Telebirr’s official documentation to correctly handle notify callbacks:
|
|
172
155
|
|
|
173
156
|
https://developer.ethiotelecom.et/docs/H5%20C2B%20Web%20Payment%20Integration%20Quick%20Guide/Notify_Callback
|
|
174
157
|
|
|
175
|
-
RSA Key Generation
|
|
158
|
+
### RSA Key Generation
|
|
159
|
+
|
|
176
160
|
You can generate private and public keys instantly.
|
|
177
161
|
|
|
162
|
+
```bash
|
|
178
163
|
import { generateKeys } from "telebirr-nodejs";
|
|
179
164
|
|
|
180
165
|
generateKeys({
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
166
|
+
dir: process.cwd(),
|
|
167
|
+
privateKeyName: "telefy_private.pem",
|
|
168
|
+
publicKeyName: "telefy_public.pem",
|
|
169
|
+
overwrite: false,
|
|
185
170
|
});
|
|
186
|
-
|
|
171
|
+
```
|
|
187
172
|
|
|
188
173
|
This will generate two .pem files in your root directory.
|
|
189
174
|
|
|
190
175
|
The merchantPrivateKey option always accepts a string, so you must read the private key file using Node.js fs and pass the value to the client configuration.
|
|
191
|
-
```
|