@vantagepay/vantagepay 0.17.3 → 0.18.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/README.md CHANGED
@@ -1,516 +1,356 @@
1
- # VantagePay API and Client SDK
1
+ # VantagePay SDK for TypeScript/JavaScript
2
2
 
3
- The VantagePay client SDK is intended to be used by web or mobile applications to integrate into the VantagePay payments, consumer and merchant API's.
3
+ `@vantagepay/vantagepay` is the official TypeScript/JavaScript SDK for integrating with VantagePay APIs.
4
4
 
5
- The library includes automatic retries for network failures and automatic token refresh on expiry. You can optionally subscribe to events published by the library to react appropriately from the client as well.
5
+ It provides:
6
+
7
+ - typed API modules backed by VantagePay model types
8
+ - automatic HTTP retries for transient failures
9
+ - automatic token refresh using `refreshToken`
10
+ - real-time payment status updates via SignalR
11
+ - event publishing for session and payment lifecycle signals
12
+
13
+ This package is client-focused. Administrative API-key capabilities are available in the .NET SDK ([VantagePay.SDK](https://www.nuget.org/packages/VantagePay.SDK)) and are not part of this package.
6
14
 
7
15
  ---
8
- # Installation
9
16
 
10
- Install the latest package into your project from NPM.
17
+ ## Table of Contents
18
+
19
+ - [Installation](#installation)
20
+ - [Client Types](#client-types)
21
+ - [Basic Usage](#basic-usage)
22
+ - [Configuration and Construction](#configuration-and-construction)
23
+ - [Authentication and Tokens](#authentication-and-tokens)
24
+ - [Error Handling](#error-handling)
25
+ - [Public API Surface](#public-api-surface)
26
+ - [Payments and Signals](#payments-and-signals)
27
+ - [Server-side Admin Usage](#server-side-admin-usage)
28
+ - [Additional Modules](#additional-modules)
11
29
 
12
- ```ps
13
- npm install @vantagepay/vantagepay --save
14
- ```
15
30
  ---
16
- # Basic Usage
17
- The library can be imported just like any other NPM package.
18
- ```js
19
- import { VantagePay, ApiTokens, ApiError } from '@vantagepay/vantagepay'
20
- ```
21
- Once imported you can create an instance with options specific to your environment.
22
- ```js
23
- const VantagePayClient = new VantagePay({ baseUrl: 'https://sandbox-api.vantagepay.dev/' })
24
- ```
25
- When you are done using the client or when the application exits, you can close the client to flush logs, unsubscribe to events and cancel active web requests.
26
- ```js
27
- await VantagePayClient.close()
31
+
32
+ ## Installation
33
+
34
+ ```sh
35
+ npm install @vantagepay/vantagepay
28
36
  ```
29
37
 
30
- The following options are available when creating an instance.
31
- ```js
32
- {
33
- // The partner URL you are integrating with, this will point to the local development server by default.
34
- baseUrl: 'https://sandbox-api.vantagepay.dev/',
38
+ ---
35
39
 
36
- // Optional extra headers (string key/value pairs) that you may want to send to the server with each call.
37
- headers: {
38
- 'X-EXAMPLE-HEADER': 'Test'
39
- },
40
+ ## Client Types
40
41
 
41
- // Optional language if you need to have response messages translated.
42
- language: 'en',
42
+ This package exposes one top-level client:
43
43
 
44
- // The number of automatic retries required for network failures, the default is 3.
45
- retries: 3,
44
+ - `VantagePay` for client-facing integrations (web/mobile/POS-style app integrations).
46
45
 
47
- // For additional request/response and signal logging which can be useful when debugging.
48
- consoleLogging: false,
46
+ Important:
49
47
 
50
- // The batch size limit when logs should immediately be sent to the server, the default is 100, use 0 to disable.
51
- logBatchSize: 100,
48
+ - there is no `VantagePayAdminClient` in TypeScript.
49
+ - for server-side admin API-key workflows, use the [.NET SDK](https://www.nuget.org/packages/VantagePay.SDK).
52
50
 
53
- // The interval in milliseconds to send any queued logs the server, the default is 60000, use 0 to disable.
54
- logBatchInterval: 60000,
55
- }
56
- ```
51
+ ---
57
52
 
58
- To flush any logs to the server you can call the `log.flush()` method manually or `close()` on the client instance when closing your application.
59
- ```js
60
- // Do this when the application close to push final logs to the server.
61
- VantagePayClient.log.flush()
53
+ ## Basic Usage
62
54
 
63
- // You can also just close the client when you are done using it.
64
- await VantagePayClient.close()
65
- ```
55
+ ```ts
56
+ import { VantagePay } from '@vantagepay/vantagepay'
66
57
 
67
- The instance will contain all the methods available for making API calls. All methods return a [`Promise`](https://javascript.info/async) so you can either use modern async/await syntax or promise-based chaining. The rest of the examples that follow use the async/await syntax.
58
+ const client = new VantagePay({
59
+ baseUrl: 'https://sandbox-api.vantagepay.dev/',
60
+ })
68
61
 
69
- ## Error Handling
70
- The API will respond with typical REST HTTP error status codes (4xx and 5xx) for errors that will trigger an exception. You can use the following generic error handling code for the typical exceptions that you may experience.
62
+ await client.auth.login('233548306110', 'Password123!')
71
63
 
72
- ```js
73
- try {
74
- // ... Call a method on the client library.
75
- } catch (error) {
76
- // First check if it's an API error.
77
- if (error instanceof ApiError) {
78
- // You can always display the `message` property to handle things generically.
79
- console.error('\n%s\n', error.message)
80
-
81
- // Or you can decide to handle things in a custom way depending on the status code.
82
- if (error.statusCode === 400 || error.statusCode === 422) { // 400/422 - Validation Errors
83
- if (Array.isArray(error.result)) {
84
- // Multiple errors.
85
- error.result.forEach(validationError => console.error(validationError))
86
- }
87
- else {
88
- // Single error message.
89
- console.error(error.message || error.result)
90
- }
91
- }
92
- else if (error.statusCode === 401 || error.statusCode === 403) { // 401/403 - Auth Errors
93
- // Login calls will contain extra information on failure (401).
94
- // No access will not have any specific details on why (403).
95
- }
96
- else if (error.statusCode === 429) { // 429 - Too Many Requests
97
- // Contains the limit.
98
- console.error(error.message)
99
- // This will also contain a standard 'Retry-After' header if you need to know how long to wait.
100
- }
101
- else if (error.statusCode === 500) { // 500 - Server Error
102
- // General error message.
103
- console.error(error.message)
104
- }
105
- else {
106
- console.error('Unknown status code from VantagePay client library: ' + error.statusCode)
107
- throw error
108
- }
109
- } else {
110
- // Not a client library error...
111
- throw error
112
- }
113
- }
64
+ const currencies = await client.lookups.getCurrencies()
65
+ const summary = await client.reports.getTransactionSummary('GHS')
66
+
67
+ await client.close()
114
68
  ```
115
69
 
116
70
  ---
117
- # Authentication
118
71
 
119
- ## Login
120
- Use credentials to login and retrieve access and refresh tokens.
121
- ```js
122
- try {
123
-
124
- const testLogin = await VantagePayClient.auth.login('test', 'test@#$123abCD')
72
+ ## Configuration and Construction
125
73
 
126
- // Store tokens in secure storage if you want to use biometrics etc.
127
- my_secure_storage.set('accessToken', testLogin.accessToken)
128
- my_secure_storage.set('refreshToken', testLogin.refreshToken)
74
+ Available `VantagePay` constructor options:
129
75
 
130
- // An alternative is to just use the static ApiTokens object where the tokens are stored after a login/refresh.
131
- my_secure_storage.set('accessToken', ApiTokens.accessToken)
132
- my_secure_storage.set('refreshToken', ApiTokens.refreshToken)
76
+ ```ts
77
+ import { VantagePay } from '@vantagepay/vantagepay'
133
78
 
134
- } catch (error) {
135
- if (error.statusCode === 401) {
136
- // Authentication error
137
- // {
138
- // invalidUsernameOrPassword: true,
139
- // mustChangePassword: false,
140
- // mustValidatePhoneNumber: false,
141
- // mustValidateEmailAddress: false,
142
- // registrationRequired: false,
143
- // lockedOut: false
144
- // }
145
-
146
- const authError = error.result
147
-
148
- if (authError.mustChangePassword) {
149
- console.log('Navigate to a change password page, the token is internally set to allow calls to auth.changePassword()')
150
-
151
- // A successful change will automatically log you in.
152
- await VantagePayClient.auth.changePassword('NewComplexP@55word!')
153
- }
79
+ const client = new VantagePay({
80
+ baseUrl: 'https://sandbox-api.vantagepay.dev/',
81
+ headers: { 'X-EXAMPLE-HEADER': 'Test' },
82
+ language: 'en',
83
+ retries: 3,
84
+ consoleLogging: false,
85
+ logBatchSize: 100,
86
+ logBatchInterval: 60000,
87
+ })
88
+ ```
154
89
 
155
- if (authError.mustValidatePhoneNumber || authError.mustValidateEmailAddress) {
156
- console.log('Navigate to the OTP page password page, the token is internally set to allow calls to auth.resendOtp() and auth.validateOtp()')
90
+ Notes:
157
91
 
158
- // A successful OTP verification will automatically log you in.
159
- await VantagePayClient.auth.validateOtp('1234')
160
- }
92
+ - `baseUrl` defaults to `http://localhost:5000`.
93
+ - `close()` flushes logs, stops payment status checks, unsubscribes events, and aborts in-flight requests.
161
94
 
162
- if (authError.deactivated) {
163
- console.log('User account has been deactivated')
164
- }
95
+ ---
165
96
 
166
- if (authError.lockedOut) {
167
- console.log('User is currently locked out')
168
- }
97
+ ## Authentication and Tokens
169
98
 
170
- if (authError.invalidUsernameOrPassword) {
171
- console.log('User credentials supplied are invalid')
172
- }
173
- }
99
+ ### Login and token storage
174
100
 
175
- if (error.statusCode === 429) {
176
- // Rate limited
177
- // Maximum number of requests exceeded. The maximum number of requests allowed is 3 per 30s. Please try again in 13 second(s).
178
- console.log(error.message)
179
- }
180
- }
101
+ ```ts
102
+ import { ApiTokens } from '@vantagepay/vantagepay'
103
+
104
+ const tokenResponse = await client.auth.login('233548306110', 'Password123!')
105
+
106
+ console.log(tokenResponse.accessToken)
107
+ console.log(ApiTokens.accessToken)
108
+ console.log(ApiTokens.refreshToken)
181
109
  ```
182
110
 
183
- ## Using Existing Tokens
184
- Tokens are kept in memory for the lifetime of the client instance and are used automatically to make authenticated calls and refresh when necessary.
185
- To avoid having to login each time your application starts, you can store access and refresh tokens (securely using biometrics for example) and re-use them when starting the application to "auto-login". You simply assign any tokens you have to the static instance of `ApiTokens`.
111
+ ### Restore existing tokens
112
+
113
+ ```ts
114
+ import { ApiTokens } from '@vantagepay/vantagepay'
186
115
 
187
- ```js
188
- ApiTokens.accessToken = my_secure_storage.get('accessToken') || null
189
- ApiTokens.refreshToken = my_secure_storage.get('refreshToken') || null
116
+ ApiTokens.accessToken = secureStore.get('accessToken') || null
117
+ ApiTokens.refreshToken = secureStore.get('refreshToken') || null
190
118
  ```
191
119
 
192
- It is usually not necessary to set the `accessToken`, if there is no access token then an automatic refresh will be triggered to retrieve one.
193
- You can also use this to clear out tokens manually which is also used internally when `logout` is called.
120
+ ### Session helpers
194
121
 
195
- ## Logout
196
- Logout of the system which revokes the refresh token as well. Use this when you need to forcibly log a user out due to multiple device unlock failures for example.
197
- ```js
198
- await VantagePayClient.auth.logout()
122
+ ```ts
123
+ const isLoggedIn = client.auth.isLoggedIn()
124
+ await client.auth.refresh()
125
+ await client.auth.logout()
199
126
  ```
200
127
 
201
- ## Refresh
202
- This is used internally to automatically refresh if the access token is no longer valid. If you need to refresh manually for any reason to start a new access session then you can call this as well to avoid expiry. This will use the current refresh token that has been set (`ApiKeys.refreshToken`).
203
- ```js
204
- await VantagePayClient.auth.refresh()
128
+ ### Token claim helpers
129
+
130
+ ```ts
131
+ client.auth.getCurrentUserReference()
132
+ client.auth.getCurrentConsumerReference()
133
+ client.auth.getCurrentMerchantReference()
134
+ client.auth.getCurrentBusinessReference()
135
+ client.auth.getCurrentTerminalReference()
136
+ client.auth.getCurrentUserName()
137
+ client.auth.getMobileNumber()
138
+ client.auth.getEmailAddress()
139
+ client.auth.getRedirectAction()
205
140
  ```
206
141
 
207
142
  ---
208
- # Lookups
209
- There are a number of lookup values that can be retrieved from the server. This is preferred over static client data because it allows for dynamic configuration and disabling of things from the server without redeploying the client.
210
143
 
211
- ## Currencies
212
- Get a list of configured currencies for the partner. The `isAvailable` flag can be used to disable items from selection, the text will also indicate if it is currently available. Other properties can be useful for displaying currency values.
213
- ```js
214
- var currencies = await VantagePayClient.lookups.getCurrencies()
215
- ```
144
+ ## Error Handling
216
145
 
217
- Example Output
218
- ```js
219
- [
220
- {
221
- isAvailable: true,
222
- currency: 'GHS',
223
- currencyName: 'Ghana Cedi',
224
- currencyCode: 'GHS',
225
- symbol: '¢',
226
- numericIsoCode: 936
227
- },
228
- {
229
- isAvailable: true,
230
- currency: 'NGN',
231
- currencyName: 'Nigeria Naira',
232
- currencyCode: 'NGN',
233
- symbol: '₦',
234
- numericIsoCode: 566
235
- },
236
- {
237
- isAvailable: true,
238
- currency: 'ZAR',
239
- currencyName: 'South Africa Rand',
240
- currencyCode: 'ZAR',
241
- symbol: 'R',
242
- numericIsoCode: 710
243
- }
244
- ]
245
- ```
146
+ All API methods throw `ApiError` for HTTP/API failures.
246
147
 
247
- ## Countries
248
- Get a list of configured countries for the partner. The `isAvailable` flag can be used to disable items from selection, the text will also indicate if it is currently available. Other values are useful for adding drop-downs to mobile numbers for example.
249
- ```js
250
- var countries = await VantagePayClient.lookups.getCountries()
251
- ```
148
+ ```ts
149
+ import { ApiError } from '@vantagepay/vantagepay'
252
150
 
253
- Example Output
254
- ```js
255
- [
256
- {
257
- isAvailable: true,
258
- country: 'GHA',
259
- countryName: 'Ghana',
260
- longIsoCode: 'GHA',
261
- shortIsoCode: 'GH',
262
- numericIsoCode: 288,
263
- diallingCode: '233'
264
- },
265
- {
266
- isAvailable: true,
267
- country: 'NGA',
268
- countryName: 'Nigeria',
269
- longIsoCode: 'NGA',
270
- shortIsoCode: 'NG',
271
- numericIsoCode: 566,
272
- diallingCode: '234'
273
- },
274
- {
275
- isAvailable: false,
276
- country: 'ZAF',
277
- countryName: 'South Africa (Currently Unavailable)',
278
- longIsoCode: 'ZAF',
279
- shortIsoCode: 'ZA',
280
- numericIsoCode: 710,
281
- diallingCode: '27'
282
- }
283
- ]
284
- ```
151
+ try {
152
+ await client.auth.login('user', 'wrong-password')
153
+ } catch (error) {
154
+ if (error instanceof ApiError) {
155
+ console.error(error.statusCode)
156
+ console.error(error.message)
157
+ console.error(error.result)
285
158
 
286
- ## Languages
287
- Get a list of configured languages for the partner. The `isAvailable` flag can be used to disable items from selection, the text will also indicate if it is currently available. This can be useful for apps that are translated to change the language header.
288
- ```js
289
- var languages = await VantagePayClient.lookups.getLanguages()
290
- ```
159
+ if (error.statusCode === 401 && error.result?.mustChangePassword) {
160
+ await client.auth.changePassword('OldPassword', 'NewPassword123!')
161
+ }
291
162
 
292
- Example Output
293
- ```js
294
- [ { isAvailable: true, languageCode: 'ENG', languageName: 'English' } ]
163
+ if (error.statusCode === 401 && (error.result?.mustValidatePhoneNumber || error.result?.mustValidateEmailAddress)) {
164
+ await client.auth.resendOtp()
165
+ await client.auth.validateOtp('123456')
166
+ }
167
+ } else {
168
+ throw error
169
+ }
170
+ }
295
171
  ```
296
172
 
297
- ## Mobile Wallet Operators
298
- Get a list of configured mobile wallet operators for the partner. The `isAvailable` flag can be used to disable items from selection, the text will also indicate if it is currently available. This can be used when setting up mobile wallets for example by limiting the types to only what the partner supports. The `operatorCode` is what can be passed into payment request packets for mobile wallet sources or destinations.
299
- ```js
300
- var mobileWalletOperators = await VantagePayClient.lookups.getMobileWalletOperators()
301
- ```
173
+ ---
302
174
 
303
- Example Output
304
- ```js
305
- [
306
- {
307
- isAvailable: false,
308
- operatorCode: 'ATG',
309
- operatorName: 'AirtelTigo (Currently Unavailable)'
310
- },
311
- { isAvailable: true, operatorCode: 'MTN', operatorName: 'MTN' },
312
- { isAvailable: true, operatorCode: 'VDF', operatorName: 'Vodafone' }
313
- ]
175
+ ## Public API Surface
176
+
177
+ `VantagePay` modules:
178
+
179
+ | Module | Purpose |
180
+ |---|---|
181
+ | `auth` | Login/logout, refresh, OTP, password, face/liveness checks, token claim helpers |
182
+ | `lookups` | Countries, currencies, languages, banks, wallet operators, categories, product types, address resolution |
183
+ | `consumers` | Consumer profile operations, files, limits, debit orders, feedback/support |
184
+ | `merchants` | Merchant profile operations, OTP verify, merchant user flows, product catalog and merchant product management, POS setup/config |
185
+ | `payments` | Payment initiation, status monitoring, tokenization, interactive payment submissions |
186
+ | `notifications` | In-app message retrieval and lifecycle |
187
+ | `qrCodes` | QR decode and QR image generation |
188
+ | `reports` | Recent transactions, summaries, daily and detailed transaction reporting |
189
+ | `system` | Health ping |
190
+ | `content` | Client content and contact-details retrieval (cached) |
191
+ | `log` | Structured application logging with batching |
192
+ | `events` | PubSub event bus for session and payment signals |
193
+
194
+ Example API calls:
195
+
196
+ ```ts
197
+ const banks = await client.lookups.getBanks()
198
+ const consumer = await client.consumers.getConsumer()
199
+ const merchant = await client.merchants.getMerchant()
200
+ const productTypes = await client.merchants.getActiveProductTypes()
201
+ const messages = await client.notifications.getMessages()
202
+ const recent = await client.reports.getRecentTransactions(10, true)
203
+ await client.system.ping()
314
204
  ```
315
205
 
316
- ## Banks
317
- Get a list of configured banks for the partner. The `isAvailable` flag can be used to disable items from selection, the text will also indicate if it is currently available. This can be used when setting up bank accounts for example by limiting the types to only what the partner supports. The `bankCode` is what can be passed into payment request packets for bank account sources or destinations.
318
- ```js
319
- var banks = await VantagePayClient.lookups.getBanks()
320
- ```
206
+ ---
321
207
 
322
- You can also optionally filter the banks returned for a specific country.
323
- ```js
324
- // Only return banks in Ghana.
325
- var banks = await VantagePayClient.lookups.getBanks('GHA')
326
- ```
208
+ ## Payments and Signals
209
+
210
+ ### Basic payment submission
327
211
 
328
- Example Output
329
- ```js
330
- [
331
- {
332
- isAvailable: true,
333
- bank: 'ABG',
334
- bankCode: 'ABG',
335
- bankName: 'ABSA Bank Ghana',
336
- country: 'GHA'
212
+ ```ts
213
+ const status = await client.payments.pay({
214
+ yourReference: 'ORDER-1001',
215
+ paymentSources: {
216
+ mobileWallets: [{
217
+ mobileWalletOperator: 'MTN',
218
+ msisdn: '233555666112',
219
+ amountInCents: 5000,
220
+ currency: 'GHS',
221
+ }],
337
222
  },
338
- {
339
- isAvailable: true,
340
- bank: 'ABL',
341
- bankCode: 'ABL',
342
- bankName: 'Access Bank Ghana',
343
- country: 'GHA'
223
+ paymentDestinations: {
224
+ merchants: [{
225
+ merchantReference: 'merchant-reference',
226
+ amountInCents: 5000,
227
+ currency: 'GHS',
228
+ paymentType: 'BuyingGoods',
229
+ }],
344
230
  },
345
- {
346
- isAvailable: false,
347
- bank: 'FNB',
348
- bankCode: 'FNB',
349
- bankName: 'First National Bank Ghana (Currently Unavailable)',
350
- country: 'GHA'
351
- }
352
- ]
231
+ })
353
232
  ```
354
233
 
355
- ## Card Issuer Country
356
- It is sometimes necessary to determine which country a card was issued in, you can use the card issuer country lookup with a card number to lookup the country.
357
- ```js
358
- var country = await VantagePayClient.lookups.getCardIssuerCountry('5200000000000114')
359
- ```
234
+ ### Subscribing to payment/session signals
360
235
 
361
- Partial numbers are also supported, 6 digits is usually sufficient, 8 digits is better.
362
- ```js
363
- var country = await VantagePayClient.lookups.getCardIssuerCountry('520001')
364
- ```
236
+ ```ts
237
+ import {
238
+ OnSessionStarted,
239
+ OnSessionExpired,
240
+ OnAutomaticRefresh,
241
+ OnApiRetry,
242
+ OnPaymentStatusUpdate,
243
+ OnPaymentComplete,
244
+ OnRequiresPin,
245
+ OnRequiresConfirmation,
246
+ OnRequires3DSecure,
247
+ OnComplete3DSecure,
248
+ OnRequiresAddress,
249
+ } from '@vantagepay/vantagepay'
365
250
 
366
- Example Output
367
- ```js
368
- {
369
- isAvailable: true,
370
- country: 'MYS',
371
- countryName: 'Malaysia',
372
- longIsoCode: 'MYS',
373
- shortIsoCode: 'MY',
374
- numericIsoCode: 458,
375
- diallingCode: '60'
376
- }
377
- ```
251
+ const sub1 = client.events.subscribe(OnPaymentStatusUpdate, (_, data) => {
252
+ console.log('status update', data)
253
+ })
378
254
 
379
- ---
380
- # Subscribing to Events
381
- The library uses [pubsub-js](https://www.npmjs.com/package/pubsub-js) to publish messages for subscribers. To subscribe to events you can use the `events` property on the client instance, which is a wrapper around PubSub so all the functions for the base library are available.
382
-
383
- These events can be useful if your application needs to react to certain things happening behind the scenes. It is especially useful when used to automatically receive payment status updates during payment processing.
384
- ```js
385
- import { VantagePay, OnApiRetry, OnAutomaticRefresh, OnSessionStarted, OnSessionExpired } from '@vantagepay/vantagepay'
386
- ...
387
- const onApiRetrySub = VantagePayClient.events.subscribe(OnApiRetry, (_, retryInfo) => console.log('API performed an automatic retry', retryInfo))
388
- const onAutoRefreshSub = VantagePayClient.events.subscribe(OnAutomaticRefresh, (_, tokenResponse) => console.log('Automatic refresh was triggered', tokenResponse))
389
- const onSessionStartedSub = VantagePayClient.events.subscribe(OnSessionStarted, () => console.log('Session started'))
390
- const onSessionExpiredSub = VantagePayClient.events.subscribe(OnSessionExpired, () => console.log('Session expired'))
391
- ...
392
- // Unsubscribe if you no longer want to receive events.
393
- VantagePayClient.events.unsubscribe(onApiRetrySub)
394
- VantagePayClient.events.unsubscribe(onAutoRefreshSub)
395
- VantagePayClient.events.unsubscribe(onSessionStartedSub)
396
- VantagePayClient.events.unsubscribe(onSessionExpiredSub)
397
- ```
255
+ const sub2 = client.events.subscribe(OnPaymentComplete, (_, data) => {
256
+ console.log('payment complete', data.paymentReference)
257
+ })
398
258
 
399
- ## OnSessionExpired ('login.session.expired')
400
- This will be fired when an automatic refresh fails or a refresh token is no longer available when making a call and you are now logged out. No data will be included with this event.
259
+ client.events.subscribe(OnRequiresPin, async (_, data) => {
260
+ await client.payments.submitPinCode(data.transactionReference, '1234')
261
+ })
401
262
 
402
- ## OnAutomaticRefresh ('login.session.refreshed')
403
- This will be fired when an automatic token refresh occurs. This is useful to know when new tokens are available that you may want to save in secure storage. The token response is included with the event, you can also use `ApiTokens.accessToken` and `ApiTokens.refreshToken` to read the new values.
263
+ client.events.subscribe(OnRequiresConfirmation, async (_, data) => {
264
+ await client.payments.submitConfirmation(data.transactionReference, true)
265
+ })
404
266
 
405
- ## OnApiRetry ('api.retry')
406
- This will be fired whenever there is an automatic API request retry. This is useful to indicate to application users that the network may be slow or they lack connectivity.
407
- The data included in the event indicates how many times the call has been retried.
408
- ```js
409
- { retryCount: 2 }
410
- ```
267
+ client.events.subscribe(OnRequiresAddress, async (_, data) => {
268
+ await client.payments.submitAddress(data.transactionReference, {
269
+ addressType: 'BILL',
270
+ addressLine1: '10 Main Road',
271
+ city: 'Johannesburg',
272
+ countryIsoCode: 'ZAF',
273
+ postalCode: '2196',
274
+ })
275
+ })
411
276
 
412
- ## OnPaymentStatusUpdate ('payment.status')
413
- During payment processing (call to `payments.pay()`) this will be fired for any status change to the payment. This is mainly due to transaction status changes that the client can display or react to. Certain status changes will also change the transaction amounts (adjustments, fees, failures and others). The recommendation here is to create a single view that renders the transaction status and on each event render the new state.
277
+ client.events.subscribe(OnRequires3DSecure, (_, data) => {
278
+ window.open(data.url)
279
+ })
414
280
 
415
- Transaction status data will be based on the request made. The source and destination data will be based on the source ans destinations provided in the request. All the possibilities will be documented separately.
281
+ client.events.subscribe(OnComplete3DSecure, () => {
282
+ console.log('3DS completed')
283
+ })
416
284
 
417
- ## OnPaymentComplete ('payment.complete')
418
- This will be fired when the payment processing is complete. In the most basic payment processing client you can ignore `OnPaymentStatusUpdate` if you do not want to show progress and simply go to the completion screen when this fires. The event will include full payment status data the same as `OnPaymentStatusUpdate` so the transaction statuses and final amounts can be displayed. Success or failure will be based on the various transaction statues in the final results.
285
+ client.events.subscribe(OnSessionStarted, () => console.log('session started'))
286
+ client.events.subscribe(OnSessionExpired, () => console.log('session expired'))
287
+ client.events.subscribe(OnAutomaticRefresh, (_, token) => console.log('refreshed', token))
288
+ client.events.subscribe(OnApiRetry, (_, data) => console.log('retry', data.retryCount))
419
289
 
420
- ## OnRequires3DSecure ('payment.wait.requires3dSecure')
421
- If card payment requires 3D Secure the client will need to launch a browser ot open an iFrame with the supplied URL and wait for `OnComplete3DSecure` to be fired before closing the browser or iFrame.
422
- The data will include the URL to launch.
423
- ```js
424
- { url: 'https://some_url_that_will_start-3ds' }
290
+ client.events.unsubscribe(sub1)
291
+ client.events.unsubscribe(sub2)
425
292
  ```
426
293
 
427
- ### Pseudo Code
428
- ```js
429
- async function handleRequires3DS(signalData) {
430
- // You are given a URL that you simply need to launch or set at the `src` on an iFrame.
431
- webBrowser = await open(signalData.url)
432
- }
294
+ ### Manual status-check control
295
+
296
+ ```ts
297
+ await client.payments.startPaymentStatusChecking() // external/incoming payment listener
298
+ await client.payments.stopPaymentStatusChecking('payment-ref') // one payment
299
+ await client.payments.stopPaymentStatusChecking() // all payments
433
300
  ```
434
301
 
435
- ## OnComplete3DSecure ('payment.complete3dSecure')
436
- This will fire once 3DS has completed as an indication that you can close the browser or iFrame that was launched when `OnRequires3DSecure` was fired. There is no additional data included in this event.
302
+ ### Tokenization and notifications
437
303
 
438
- ## OnRequiresPin ('payment.wait.requiresPin')
439
- This will be fired if a transaction requires a PIN/OTP. The event data will include the message to display to the user so they are aware of what to provide. The text field can generally be numbers only.
440
- ```js
441
- {
442
- message: 'Please enter you Vodafone PIN to complete this transaction.',
443
- transactionReference: '84125510-B042-417D-A532-47A7EBD47488',
444
- pinLength: 6
445
- }
304
+ ```ts
305
+ const cardToken = await client.payments.createCardToken({
306
+ cardNumber: '5200000000000114',
307
+ nameOnCard: 'John Doe',
308
+ expiryMonth: 9,
309
+ expiryYear: 2028,
310
+ })
311
+
312
+ await client.payments.sendEmailPaymentNotification('payment-reference', 'user@example.com')
313
+ await client.payments.sendSmsPaymentNotification('payment-reference', '233548306110')
446
314
  ```
447
315
 
448
- Once the PIN has been captured you can make a call to `payments.submitPinCode()` with the `transactionReference` that was sent in the event to continue payment processing.
316
+ ### Payment helpers
449
317
 
450
- ### Pseudo Code
451
- ```js
452
- function handleRequiresPin(signalData) {
453
- // You need to capture a PIN code and call `submitPinCode`.
454
- const pin = prompt(signalData.message)
455
- VantagePayClient.payments.submitPinCode(signalData.transactionReference, pin)
456
- }
318
+ ```ts
319
+ client.payments.getRequiredPinLength('VDF') // 6
320
+ client.payments.getRequiredPinLength('MTN') // 4
321
+ client.payments.luhnCheck('5200000000000114') // true
457
322
  ```
458
323
 
459
- ## OnRequiresConfirmation ('payment.wait.requiresConfirmation')
460
- This will be fired if a transaction requires confirmation such as additional fees or even to verify account information. The event data will include the message to display to the user so they are aware of what they are confirming. The dialog to display can just have Yes/No buttons.
461
- ```js
462
- {
463
- message: 'The transaction requires an additional e-levy fee of GHS 3.00. Do you want to continue?',
464
- transactionReference: '6FD502DE-20FF-4110-ABBE-8FE6D7733AAE',
465
- confirmationData: {
466
- amountInCents: 1025,
467
- sourceAccountHolder: 'Steve Rogers',
468
- destinationAccountHolder: 'Tony Stark',
469
- fees: []
470
- }
471
- }
472
- ```
324
+ ---
473
325
 
474
- Once the response has been captured you can make a call to `payments.submitConfirmation()` with the `transactionReference` that was sent in the event to continue payment processing.
326
+ ## Server-side Admin Usage
475
327
 
476
- ### Pseudo Code
477
- ```js
478
- function handleRequiresConfirmation(signalData) {
479
- // You need to ask the user for a Yes/No answer.
480
- const confirmation = prompt(signalData.message + ' -Y/N - ')
481
- VantagePayClient.payments.submitConfirmation(signalData.transactionReference, confirmation === 'Y' || confirmation === 'y')
482
- }
328
+ This TypeScript package does not expose admin API-key modules.
329
+
330
+ For administrative workflows (for example user administration, KYC/KYB administration, template management, and admin payment/refund orchestration), use the .NET SDK `VantagePay.SDK` with `VantagePayAdminClient`.
331
+
332
+ ---
333
+
334
+ ## Additional Modules
335
+
336
+ ### QR utilities
337
+
338
+ ```ts
339
+ const decoded = await client.qrCodes.decode('000201010211...')
340
+ const qrBase64 = await client.qrCodes.generate('https://example.com/pay', 500)
483
341
  ```
484
342
 
485
- ## OnRequiresAddress ('payment.wait.requiresAddress')
486
- This will be fired if address validation failed or an address is required but was not provided in the initial payment request. The event data will include the message to display to the user. The client should launch an address capture screen with the information provided (so it can corrected) a blank if no address information was provided.
487
- ```js
488
- {
489
- message: 'The address information provided does not appear to be valid. Please provide billing address information for this transaction.',
490
- transactionReference: '6F4F250E-BF64-4BC2-936C-02E5A2982969'
491
- }
343
+ ### Content
344
+
345
+ ```ts
346
+ const clientContent = await client.content.getClientContent()
347
+ const contactDetails = await client.content.getContactDetails()
492
348
  ```
493
349
 
494
- Once the address details have been captured you can make a call to `payments.submitAddress()` with the `transactionReference` that was sent in the event to continue payment processing.
495
-
496
- ### Pseudo Code
497
- ```js
498
- function handleRequiresAddress(signalData) {
499
- // Let the user know what is required.
500
- alert(signalData.message)
501
-
502
- // You need to capture a PIN code and call `submitPinCode`.
503
- const address = {
504
- addressType: prompt('Type: ') || 'BILL',
505
- addressLine1: prompt('Line 1: ') || '10 Whitley Road',
506
- addressLine2: prompt('Line 2: ') || null,
507
- addressLine3: prompt('Line 3: ') || null,
508
- countryIsoCode: prompt('Country: ') || 'ZAF',
509
- city: prompt('City: ') || 'Johannesburg',
510
- state: prompt('State: ') || null,
511
- postalCode: prompt('Postal Code: ') || '2196',
512
- }
350
+ ### Structured logging
513
351
 
514
- VantagePayClient.payments.submitAddress(signalData.transactionReference, address)
515
- }
352
+ ```ts
353
+ client.log.info('User {Username} logged in from {Country}', 'john', 'GHA')
354
+ client.log.warn('Payment {PaymentRef} is delayed', 'PAY-123')
355
+ await client.log.flush()
516
356
  ```