@first-iraqi-bank/sdk 0.1.2 → 0.1.4

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 CHANGED
@@ -6,296 +6,4 @@ First Iraqi Bank allows you to create online payments in your application using
6
6
 
7
7
  This package helps you integrate the payment API easily on your JavaScript/TypeScript backend server with simple and typed set of functions.
8
8
 
9
- ## Table of Contents
10
-
11
- - [Installation](#installation)
12
- - [Technical notices](#technical-notices)
13
- - [Methods](#usage)
14
- - [authenticate](#authenticate)
15
- - [createPayment](#createpayment)
16
- - [getPaymentStatus](#getpaymentstatus)
17
- - [cancelPayment](#cancelpayment)
18
- - [refundPayment](#refundpayment)
19
- - [Types & Responses](#types)
20
- - [Error Handling](#error-handling)
21
- - [Contributing](#contributing)
22
-
23
- ## Installation
24
-
25
- ### npm
26
-
27
- ```sh
28
- npm i @first-iraqi-bank/sdk
29
- ```
30
-
31
- ### yarn
32
-
33
- ```sh
34
- yarn add @first-iraqi-bank/sdk
35
- ```
36
-
37
- ### pnpm
38
-
39
- ```sh
40
- pnpm add @first-iraqi-bank/sdk
41
- ```
42
-
43
- ### deno
44
-
45
- ```sh
46
- deno add npm:@first-iraqi-bank/sdk
47
- ```
48
-
49
- ### bun
50
-
51
- ```sh
52
- bun add @first-iraqi-bank/sdk
53
- ```
54
-
55
- ## Technical notices
56
-
57
- You need to register for the sandbox environment to get your `client_id` and `client_secret`. Once you are ready to move to production, contact <integration@fib.iq> to obtain your production credentials.
58
-
59
- 1. This package guarantees support for Maintenance and LTS versions of Node.js, starting from v18 of Node.js. if you encountered any issues in this regard, please [let us know](https://github.com/First-Iraqi-Bank/fib-nodejs-payment-sdk/issues/new).
60
-
61
- 2. This package guarantees support for ESM and CJS module formats, we prefer and recommend of using ESM everywhere if it works for you.
62
-
63
- 3. This package is built on top of the [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch) and all functions return a `Response` giving you maximum flexibility to parse or ignore the responses you get. Check out [Node.js docs - Fetch](https://nodejs.org/docs/latest/api/globals.html#fetch) section which is available since **v18.0.0**
64
-
65
- ## Usage
66
-
67
- You can import the SDK classes and types from the `payment` entrypoint:
68
-
69
- ```ts
70
- import { PaymentSDK } from "@first-iraqi-bank/sdk/payment"
71
- ```
72
-
73
- The `PaymentSDK` class has a static method that gives you an instance of the SDK configured with your API credentials:
74
-
75
- ```ts
76
- // fib.js
77
-
78
- import { PaymentSDK } from "@first-iraqi-bank/sdk/payment"
79
-
80
- const clientId = process.env.FIB_CLIENT_ID
81
- const clientSecret = process.env.FIB_CLIENT_SECRET
82
- const environment = process.env.FIB_ENV // 'dev', 'stage', or 'prod'
83
-
84
- export const FIB = PaymentSDK.getClient(clientId, clientSecret, environment)
85
- ```
86
-
87
- Now you can import `FIB` from anywhere in your project and call its methods to create payments, check payment status or canceling them.
88
-
89
- > [!TIP]
90
- > Checkout [FIB Web Payment](https://fib.iq/en/developers/web-payment) documentations for more info and how to obtain your credentials
91
-
92
- - `authenticate(signal?: AbortSignal)`: Authenticates the client and returns an access token.
93
- - `createPayment(paymentInput: PaymentInput, accessToken: string, signal?: AbortSignal)`: Creates a payment.
94
- - `getPaymentStatus(paymentId: string, accessToken: string, signal?: AbortSignal)`: Gets the status of a payment.
95
- - `cancelPayment(paymentId: string, accessToken: string, signal?: AbortSignal)`: Cancels a payment.
96
- - `refundPayment(paymentId: string, accessToken: string, signal?: AbortSignal)`: Refunds a payment.
97
-
98
- ### authenticate
99
-
100
- This method sends a request to the First Iraqi Bank's identity server, giving you necessary token and other related information to authenticate your next requests like creating or canceling a payment.
101
-
102
- ```ts
103
- import { FIB } from "./fib.js"
104
-
105
- const res = await FIB.authenticate()
106
- const { access_token, expires_in } = await res.json()
107
- ```
108
-
109
- `access_token` is the most important part of the response, since you need to pass it to the next request otherwise it'll fail with **Authentication** error!
110
-
111
- > [!IMPORTANT]
112
- > Access tokens are designed to be short-lived, `expires_in` will tell you how many seconds you have until the access token expires, make sure to fetch a new access token before your next API call by calling `authenticate` as described above.
113
-
114
- ---
115
-
116
- ### createPayment
117
-
118
- This method sends a request to the First Iraqi Bank's server, creating a payment based on the provided information, which are parameters to function:
119
-
120
- 1. `payment`: an object with below possible properties:
121
-
122
- - `amount`: a number, indicating the payment's amount in IQD. Must be bigger than `250`.
123
- - `description` _(optional)_: a string used as description and might be shown to the customer when they try to pay in the FIB app.
124
- - `expiresIn` _(optional)_: a Duration object indicating when the transaction expires, it must be:
125
-
126
- 1. Bigger than 5 Minutes
127
- 2. Smaller than 48 Hours
128
-
129
- - `refundableFor` _(optional)_: a Duration object indicating till when the transaction can be refunded after it was paid, it must be:
130
-
131
- 1. Bigger than 12 Hours
132
- 2. Smaller than 7 Days
133
-
134
- - `redirectUri` _(optional)_: an instance of [`URL`](https://developer.mozilla.org/en-US/docs/Web/API/URL_API) class, you can provide
135
- a URL of your app where the user should be redirected when the payment was authorized, for example if you want FIB app to redirect user
136
- back to some screen inside your app/website, this is used when you use **Pay with FIB** button in your.
137
- - `statusCallbackUrl` _(optional)_: an instance of [`URL`](https://developer.mozilla.org/en-US/docs/Web/API/URL_API) class, this must be the URL of your backend and specifically of an endpoint that can accept `POST` request, as FIB backend will call this endpoint when the status of the transaction changes. Omit it if you're not interested.
138
-
139
- 2. `accessToken`: a previously fetched access token from [`authenticate`](#authenticate) method.
140
- 3. `signal` _(optional)_: an AbortSignal that can use to abort the fetch request. Checkout [Canceling a request](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#canceling_a_request) on MDN for detailed explanation.
141
-
142
- Example:
143
-
144
- ```ts
145
- import { FIB } from "./fib.js"
146
-
147
- const paymentInput = {
148
- amount: 1000, // amount in IQD
149
- description: "Payment for Order #12345",
150
- redirectUri: new URL("https://example.com/payments"),
151
- statusCallbackUrl: new URL("https://example.com/api/callbacks/payment/status"),
152
- refundableFor: { days: 1 },
153
- expiresIn: { hours: 1 },
154
- }
155
-
156
- const authRes = await FIB.authenticate()
157
- const { access_token } = await authRes.json()
158
-
159
- const res = await FIB.createPayment(paymentInput, access_token)
160
- ```
161
-
162
- This method returns a JSON response, that is the details of transaction that you just created, represented by `Payment` type:
163
-
164
- - `paymentId`: a string indicating the id of the payment
165
- - `readableCode`: a 12-character alpha-numeric string used to generate the `qrCode` property.
166
- - `qrCode`: a URL-encoded PNG image that can be shown to the user to scan and pay the amount.
167
- - `validUntil`: a string indicating until when this payment is valid.
168
- - `personalAppLink`: a string representing the personal deep link that users can visit which automatically opens the payment details in the FIB app.
169
- - `businessAppLink`: a string representing the personal deep link that users can visit which automatically opens the payment details in the FIB app.
170
- - `corporateAppLink`: a string representing the personal deep link that users can visit which automatically opens the payment details in the FIB app.
171
-
172
- > [!TIP]
173
- > Users can pay the amount either by scanning the QRCode, manually typing the `readableCode` or visiting the deep-links like `personalAppLink`, we recommend showing all 3 options to the user to make it more convenient for your users to fulfill the payment
174
-
175
- Users might refresh your page, or close your application and come back, make sure you save the transaction details in your database as it contains information that can helpful to you or your customers later.
176
-
177
- ---
178
-
179
- ### getPaymentStatus
180
-
181
- When you generated a payment, you can use this method to retrieve information about the status of the payment, this provides details on when the payment is paid, or if its canceled then why and some other useful information:
182
-
183
- ```ts
184
- import { FIB } from "./fib.js"
185
-
186
- const authRes = await FIB.authenticate()
187
- const { access_token } = await authRes.json()
188
-
189
- const res = await FIB.getPaymentStatus(paymentId, accessToken)
190
- ```
191
-
192
- ---
193
-
194
- ### cancelPayment
195
-
196
- When a payment is created, you might want to cancel the payment for any reason, this can be done before he payment is fulfilled:
197
-
198
- ```ts
199
- import { FIB } from "./fib.js"
200
-
201
- const authRes = await FIB.authenticate()
202
- const { access_token } = await authRes.json()
203
-
204
- const res = await FIB.cancelPayment(paymentId, accessToken)
205
- ```
206
-
207
- ---
208
-
209
- ### refundPayment
210
-
211
- After a payment is fulfilled, it can be refunded depending on the `refundableFor` option you created the payment with:
212
-
213
- ```ts
214
- import { FIB } from "./fib.js"
215
-
216
- const authRes = await FIB.authenticate()
217
- const { access_token } = await authRes.json()
218
-
219
- const res = await FIB.refundPayment(paymentId, accessToken)
220
- ```
221
-
222
- ---
223
-
224
- ### Types
225
-
226
- #### PaymentInput
227
-
228
- ```typescript
229
- type PaymentInput = {
230
- amount: number
231
- description?: string
232
- redirectUri?: URL
233
- statusCallbackUrl?: URL
234
- expiresIn?: Duration
235
- refundableFor?: Duration
236
- }
237
- ```
238
-
239
- #### PaymentResponse
240
-
241
- ```typescript
242
- type PaymentResponse = {
243
- paymentId: string
244
- readableCode: string
245
- qrCode: string
246
- validUntil: string
247
- personalAppLink: string
248
- businessAppLink: string
249
- corporateAppLink: string
250
- }
251
- ```
252
-
253
- #### PaymentStatusResponse
254
-
255
- ```typescript
256
- type PaymentStatusResponse = {
257
- paymentId: string
258
- amount: MonetaryValue
259
- status: "UNPAID" | "DECLINED" | "PAID" | "REFUNDED" | "REFUND_REQUESTED"
260
- paidAt?: string
261
- decliningReason?: "PAYMENT_CANCELLATION" | "PAYMENT_EXPIRATION"
262
- declinedAt?: string
263
- paidBy?: { name: string; iban: string }
264
- }
265
- ```
266
-
267
- ## Error Handling
268
-
269
- There are two types of errors you might want to watch out for:
270
-
271
- 1. When the requests return a `Response`, but its not in `2xx` range, in this case
272
- FIB backend returns an error message and some traceId, that we can inspect the
273
- request for you if the error is not expected.
274
-
275
- ```javascript
276
- const res = await FIB.getPaymentStatus(paymentInput, accessToken)
277
- if(res.status !== 200){
278
- const { errors } = await res.json()
279
- }
280
- ```
281
-
282
- 2. When the request fails with an `Error`, which might happen for several reasons, for example
283
- a `NetworkError` or other runtime exceptions.
284
-
285
- ```javascript
286
- try{
287
- const res = await FIB.getPaymentStatus(paymentInput, accessToken)
288
- const { status } = await res.json()
289
-
290
- return status
291
- }catch(error){
292
- console.log("Something went wrong", error)
293
- return null
294
- }
295
- ```
296
-
297
- ## Contributing
298
-
299
- If you encounter any bugs or issues while using the SDK, we encourage you to report them by [filing an issue](https://github.com/First-Iraqi-Bank/fib-nodejs-payment-sdk/issues/new) on our GitHub repository. Your feedback helps us improve the SDK.
300
-
301
- Additionally, if during the discussion of an issue you feel that you can contribute a code change to resolve the problem, we warmly welcome your contributions. To do so, please submit a [pull request](https://github.com/First-Iraqi-Bank/fib-nodejs-payment-sdk/compare) with your proposed changes.
9
+ Please read our [Documentation](https://first-iraqi-bank.github.io/fib-nodejs-payment-sdk/) for a smooth integration.
package/dist/payment.cjs CHANGED
@@ -25,15 +25,24 @@ __export(payment_exports, {
25
25
  module.exports = __toCommonJS(payment_exports);
26
26
 
27
27
  // src/shared/net.ts
28
+ var MAP_ENVIRONMENT_TO_BASE_URL = {
29
+ dev: "https://fib-dev.fib.iq",
30
+ stage: "https://fib-stage.fib.iq",
31
+ prod: "https://fib.prod.fib.iq"
32
+ };
28
33
  var BaseHTTP = class {
29
34
  #baseUrl;
30
35
  #clientId;
31
36
  #clientSecret;
32
37
  #grantType = "client_credentials";
33
38
  constructor(clientId, clientSecret, env) {
39
+ const rawBaseURL = MAP_ENVIRONMENT_TO_BASE_URL[env];
40
+ if (!rawBaseURL) {
41
+ throw new Error(`Invalid environment: ${env}`);
42
+ }
34
43
  this.#clientId = clientId;
35
44
  this.#clientSecret = clientSecret;
36
- this.#baseUrl = new URL(`https://fib.${env}.fib.iq`);
45
+ this.#baseUrl = new URL(rawBaseURL);
37
46
  }
38
47
  getBaseUrl() {
39
48
  return this.#baseUrl;
@@ -65,16 +74,21 @@ var BaseHTTP = class {
65
74
 
66
75
  // src/shared/utils.ts
67
76
  function formatISODuration(duration) {
68
- const {
69
- years = 0,
70
- months = 0,
71
- days = 0,
72
- hours = 0,
73
- minutes = 0,
74
- seconds = 0
75
- } = duration;
76
- return `P${years}Y${months}M${days}DT${hours}H${minutes}M${seconds}S`;
77
+ const parts = ["P"];
78
+ if (duration.years) parts.push(`${duration.years}Y`);
79
+ if (duration.months) parts.push(`${duration.months}M`);
80
+ if (duration.weeks) parts.push(`${duration.weeks}W`);
81
+ if (duration.days) parts.push(`${duration.days}D`);
82
+ const hasTimeComponents = duration.hours || duration.minutes || duration.seconds;
83
+ if (hasTimeComponents) {
84
+ parts.push("T");
85
+ if (duration.hours) parts.push(`${duration.hours}H`);
86
+ if (duration.minutes) parts.push(`${duration.minutes}M`);
87
+ if (duration.seconds) parts.push(`${duration.seconds}S`);
88
+ }
89
+ return parts.length === 1 ? "P0D" : parts.join("");
77
90
  }
91
+ console.log(formatISODuration({ days: 1 }));
78
92
 
79
93
  // src/payment/net.ts
80
94
  var HTTP = class extends BaseHTTP {
package/dist/payment.js CHANGED
@@ -1,13 +1,22 @@
1
1
  // src/shared/net.ts
2
+ var MAP_ENVIRONMENT_TO_BASE_URL = {
3
+ dev: "https://fib-dev.fib.iq",
4
+ stage: "https://fib-stage.fib.iq",
5
+ prod: "https://fib.prod.fib.iq"
6
+ };
2
7
  var BaseHTTP = class {
3
8
  #baseUrl;
4
9
  #clientId;
5
10
  #clientSecret;
6
11
  #grantType = "client_credentials";
7
12
  constructor(clientId, clientSecret, env) {
13
+ const rawBaseURL = MAP_ENVIRONMENT_TO_BASE_URL[env];
14
+ if (!rawBaseURL) {
15
+ throw new Error(`Invalid environment: ${env}`);
16
+ }
8
17
  this.#clientId = clientId;
9
18
  this.#clientSecret = clientSecret;
10
- this.#baseUrl = new URL(`https://fib.${env}.fib.iq`);
19
+ this.#baseUrl = new URL(rawBaseURL);
11
20
  }
12
21
  getBaseUrl() {
13
22
  return this.#baseUrl;
@@ -39,16 +48,21 @@ var BaseHTTP = class {
39
48
 
40
49
  // src/shared/utils.ts
41
50
  function formatISODuration(duration) {
42
- const {
43
- years = 0,
44
- months = 0,
45
- days = 0,
46
- hours = 0,
47
- minutes = 0,
48
- seconds = 0
49
- } = duration;
50
- return `P${years}Y${months}M${days}DT${hours}H${minutes}M${seconds}S`;
51
+ const parts = ["P"];
52
+ if (duration.years) parts.push(`${duration.years}Y`);
53
+ if (duration.months) parts.push(`${duration.months}M`);
54
+ if (duration.weeks) parts.push(`${duration.weeks}W`);
55
+ if (duration.days) parts.push(`${duration.days}D`);
56
+ const hasTimeComponents = duration.hours || duration.minutes || duration.seconds;
57
+ if (hasTimeComponents) {
58
+ parts.push("T");
59
+ if (duration.hours) parts.push(`${duration.hours}H`);
60
+ if (duration.minutes) parts.push(`${duration.minutes}M`);
61
+ if (duration.seconds) parts.push(`${duration.seconds}S`);
62
+ }
63
+ return parts.length === 1 ? "P0D" : parts.join("");
51
64
  }
65
+ console.log(formatISODuration({ days: 1 }));
52
66
 
53
67
  // src/payment/net.ts
54
68
  var HTTP = class extends BaseHTTP {
package/dist/payout.cjs CHANGED
@@ -25,15 +25,24 @@ __export(payout_exports, {
25
25
  module.exports = __toCommonJS(payout_exports);
26
26
 
27
27
  // src/shared/net.ts
28
+ var MAP_ENVIRONMENT_TO_BASE_URL = {
29
+ dev: "https://fib-dev.fib.iq",
30
+ stage: "https://fib-stage.fib.iq",
31
+ prod: "https://fib.prod.fib.iq"
32
+ };
28
33
  var BaseHTTP = class {
29
34
  #baseUrl;
30
35
  #clientId;
31
36
  #clientSecret;
32
37
  #grantType = "client_credentials";
33
38
  constructor(clientId, clientSecret, env) {
39
+ const rawBaseURL = MAP_ENVIRONMENT_TO_BASE_URL[env];
40
+ if (!rawBaseURL) {
41
+ throw new Error(`Invalid environment: ${env}`);
42
+ }
34
43
  this.#clientId = clientId;
35
44
  this.#clientSecret = clientSecret;
36
- this.#baseUrl = new URL(`https://fib.${env}.fib.iq`);
45
+ this.#baseUrl = new URL(rawBaseURL);
37
46
  }
38
47
  getBaseUrl() {
39
48
  return this.#baseUrl;
package/dist/payout.js CHANGED
@@ -1,13 +1,22 @@
1
1
  // src/shared/net.ts
2
+ var MAP_ENVIRONMENT_TO_BASE_URL = {
3
+ dev: "https://fib-dev.fib.iq",
4
+ stage: "https://fib-stage.fib.iq",
5
+ prod: "https://fib.prod.fib.iq"
6
+ };
2
7
  var BaseHTTP = class {
3
8
  #baseUrl;
4
9
  #clientId;
5
10
  #clientSecret;
6
11
  #grantType = "client_credentials";
7
12
  constructor(clientId, clientSecret, env) {
13
+ const rawBaseURL = MAP_ENVIRONMENT_TO_BASE_URL[env];
14
+ if (!rawBaseURL) {
15
+ throw new Error(`Invalid environment: ${env}`);
16
+ }
8
17
  this.#clientId = clientId;
9
18
  this.#clientSecret = clientSecret;
10
- this.#baseUrl = new URL(`https://fib.${env}.fib.iq`);
19
+ this.#baseUrl = new URL(rawBaseURL);
11
20
  }
12
21
  getBaseUrl() {
13
22
  return this.#baseUrl;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@first-iraqi-bank/sdk",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Accept payment and send payout from and to First Iraqi Bank customers with ease!",
5
5
  "type": "module",
6
6
  "files": [
@@ -44,7 +44,7 @@
44
44
  "url": "git+https://github.com/First-Iraqi-Bank/fib-nodejs-payment-sdk.git"
45
45
  },
46
46
  "bugs": "https://github.com/First-Iraqi-Bank/fib-nodejs-payment-sdk/issues",
47
- "homepage": "https://github.com/First-Iraqi-Bank/fib-nodejs-payment-sdk#readme",
47
+ "homepage": "https://first-iraqi-bank.github.io/fib-nodejs-payment-sdk/",
48
48
  "keywords": [
49
49
  "api",
50
50
  "sdk",