@vulog/aima-payment 1.1.88 → 1.1.91

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,20 +1,321 @@
1
- # @vulog/aima-booking
1
+ # @vulog/aima-payment
2
+
3
+ Payment management module for the AIMA platform. This module provides functionality to handle payments, setup intents, payment methods, and trip payments.
4
+
5
+ ## Installation
2
6
 
3
7
  ```bash
4
- npm i @vulog/aima-client @vulog/aima-core @vulog/aima-payment
8
+ npm install @vulog/aima-client @vulog/aima-core @vulog/aima-payment
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### Initialize Client
14
+
15
+ ```javascript
16
+ import { getClient } from '@vulog/aima-client';
17
+ import {
18
+ getSetupIntent,
19
+ getPaymentMethodDetailsForUser,
20
+ getSynchronize,
21
+ payATrip
22
+ } from '@vulog/aima-payment';
23
+
24
+ const client = getClient({
25
+ apiKey: 'your-api-key',
26
+ baseUrl: 'https://your-api-base-url',
27
+ clientId: 'your-client-id',
28
+ clientSecret: 'your-client-secret',
29
+ fleetId: 'your-fleet-id',
30
+ });
31
+ ```
32
+
33
+ ## API Reference
34
+
35
+ ### Payment Setup
36
+
37
+ #### getSetupIntent
38
+
39
+ Create a setup intent for payment method configuration.
40
+
41
+ ```javascript
42
+ const setupIntent = await getSetupIntent(client, 'user-uuid-here');
43
+ ```
44
+
45
+ **Parameters:**
46
+ - `client`: AIMA client instance
47
+ - `entityId`: User UUID
48
+
49
+ **Returns:** Setup intent object for payment method configuration
50
+
51
+ #### getPaymentMethodDetailsForUser
52
+
53
+ Retrieve payment method details for a specific user.
54
+
55
+ ```javascript
56
+ const paymentMethods = await getPaymentMethodDetailsForUser(client, 'user-uuid-here');
57
+ ```
58
+
59
+ **Parameters:**
60
+ - `client`: AIMA client instance
61
+ - `entityId`: User UUID
62
+
63
+ **Returns:** Array of user's payment methods
64
+
65
+ ### Payment Processing
66
+
67
+ #### payATrip
68
+
69
+ Process payment for a trip.
70
+
71
+ ```javascript
72
+ const paymentResult = await payATrip(client, {
73
+ tripId: 'trip-uuid-here',
74
+ paymentMethodId: 'payment-method-id-here',
75
+ amount: 25.50,
76
+ currency: 'EUR'
77
+ });
78
+ ```
79
+
80
+ **Parameters:**
81
+ - `client`: AIMA client instance
82
+ - `paymentData`: Payment configuration object
83
+ - `tripId`: Trip identifier
84
+ - `paymentMethodId`: Payment method identifier
85
+ - `amount`: Payment amount
86
+ - `currency`: Currency code
87
+
88
+ **Returns:** Payment processing result
89
+
90
+ #### getSynchronize
91
+
92
+ Synchronize payment data.
93
+
94
+ ```javascript
95
+ const syncResult = await getSynchronize(client, {
96
+ entityId: 'user-uuid-here',
97
+ lastSyncDate: '2024-01-01T00:00:00Z'
98
+ });
99
+ ```
100
+
101
+ **Parameters:**
102
+ - `client`: AIMA client instance
103
+ - `syncData`: Synchronization configuration
104
+ - `entityId`: User UUID
105
+ - `lastSyncDate`: Last synchronization date
106
+
107
+ **Returns:** Synchronization result
108
+
109
+ ## Types
110
+
111
+ ### SetupIntent
112
+
113
+ ```typescript
114
+ interface SetupIntent {
115
+ id: string;
116
+ clientSecret: string;
117
+ status: 'requires_payment_method' | 'requires_confirmation' | 'requires_action' | 'processing' | 'succeeded' | 'canceled';
118
+ paymentMethodTypes: string[];
119
+ createdAt: string;
120
+ updatedAt: string;
121
+ }
5
122
  ```
6
123
 
124
+ ### PaymentMethod
125
+
126
+ ```typescript
127
+ interface PaymentMethod {
128
+ id: string;
129
+ type: 'card' | 'bank_account' | 'sepa_debit';
130
+ card?: {
131
+ brand: string;
132
+ last4: string;
133
+ expMonth: number;
134
+ expYear: number;
135
+ };
136
+ bankAccount?: {
137
+ bankName: string;
138
+ last4: string;
139
+ routingNumber: string;
140
+ };
141
+ isDefault: boolean;
142
+ createdAt: string;
143
+ updatedAt: string;
144
+ }
145
+ ```
146
+
147
+ ### PaymentResult
148
+
149
+ ```typescript
150
+ interface PaymentResult {
151
+ id: string;
152
+ status: 'succeeded' | 'failed' | 'pending' | 'canceled';
153
+ amount: number;
154
+ currency: string;
155
+ paymentMethodId: string;
156
+ tripId: string;
157
+ errorMessage?: string;
158
+ createdAt: string;
159
+ }
160
+ ```
161
+
162
+ ## Error Handling
163
+
164
+ All functions include validation and will throw appropriate errors if:
165
+ - Required parameters are missing
166
+ - Invalid user or trip IDs are provided
167
+ - Payment processing fails
168
+ - Network errors occur
169
+
170
+ ## Examples
171
+
172
+ ### Complete Payment Workflow
173
+
7
174
  ```javascript
8
175
  import { getClient } from '@vulog/aima-client';
9
- import { getModelById } from '@vulog/aima-payment';
176
+ import {
177
+ getSetupIntent,
178
+ getPaymentMethodDetailsForUser,
179
+ payATrip
180
+ } from '@vulog/aima-payment';
10
181
 
11
182
  const client = getClient({
12
- apiKey: '...',
13
- baseUrl: '...',
14
- clientId: '...',
15
- clientSecret: '...',
16
- fleetId: '...',
183
+ apiKey: 'your-api-key',
184
+ baseUrl: 'https://your-api-base-url',
185
+ clientId: 'your-client-id',
186
+ clientSecret: 'your-client-secret',
187
+ fleetId: 'your-fleet-id',
17
188
  });
18
189
 
19
- const response = await getSetupIntent(client, 'entityId');
190
+ async function paymentWorkflow() {
191
+ try {
192
+ const userId = 'user-uuid-here';
193
+
194
+ // Create setup intent for new payment method
195
+ const setupIntent = await getSetupIntent(client, userId);
196
+ console.log('Setup intent created:', setupIntent);
197
+
198
+ // Get user's existing payment methods
199
+ const paymentMethods = await getPaymentMethodDetailsForUser(client, userId);
200
+ console.log(`User has ${paymentMethods.length} payment methods`);
201
+
202
+ // Process trip payment
203
+ const paymentResult = await payATrip(client, {
204
+ tripId: 'trip-uuid-here',
205
+ paymentMethodId: paymentMethods[0].id,
206
+ amount: 25.50,
207
+ currency: 'EUR'
208
+ });
209
+
210
+ console.log('Payment processed:', paymentResult);
211
+
212
+ return { setupIntent, paymentMethods, paymentResult };
213
+ } catch (error) {
214
+ console.error('Payment workflow error:', error);
215
+ throw error;
216
+ }
217
+ }
218
+ ```
219
+
220
+ ### Payment Method Management
221
+
222
+ ```javascript
223
+ async function managePaymentMethods(client, userId) {
224
+ try {
225
+ const paymentMethods = await getPaymentMethodDetailsForUser(client, userId);
226
+
227
+ const analysis = {
228
+ totalMethods: paymentMethods.length,
229
+ defaultMethod: paymentMethods.find(pm => pm.isDefault),
230
+ cardMethods: paymentMethods.filter(pm => pm.type === 'card'),
231
+ bankMethods: paymentMethods.filter(pm => pm.type === 'bank_account'),
232
+ sepaMethods: paymentMethods.filter(pm => pm.type === 'sepa_debit')
233
+ };
234
+
235
+ console.log('Payment Method Analysis:');
236
+ console.log(`Total Methods: ${analysis.totalMethods}`);
237
+ console.log(`Default Method: ${analysis.defaultMethod?.id || 'None'}`);
238
+ console.log(`Card Methods: ${analysis.cardMethods.length}`);
239
+ console.log(`Bank Methods: ${analysis.bankMethods.length}`);
240
+ console.log(`SEPA Methods: ${analysis.sepaMethods.length}`);
241
+
242
+ return analysis;
243
+ } catch (error) {
244
+ console.error('Payment method management error:', error);
245
+ throw error;
246
+ }
247
+ }
248
+ ```
249
+
250
+ ### Trip Payment Processing
251
+
252
+ ```javascript
253
+ async function processTripPayment(client, tripId, userId, amount, currency = 'EUR') {
254
+ try {
255
+ // Get user's payment methods
256
+ const paymentMethods = await getPaymentMethodDetailsForUser(client, userId);
257
+
258
+ if (paymentMethods.length === 0) {
259
+ throw new Error('No payment methods found for user');
260
+ }
261
+
262
+ // Use default payment method or first available
263
+ const paymentMethod = paymentMethods.find(pm => pm.isDefault) || paymentMethods[0];
264
+
265
+ // Process payment
266
+ const paymentResult = await payATrip(client, {
267
+ tripId,
268
+ paymentMethodId: paymentMethod.id,
269
+ amount,
270
+ currency
271
+ });
272
+
273
+ if (paymentResult.status === 'succeeded') {
274
+ console.log(`Payment successful: ${amount} ${currency} for trip ${tripId}`);
275
+ } else {
276
+ console.log(`Payment failed: ${paymentResult.errorMessage}`);
277
+ }
278
+
279
+ return paymentResult;
280
+ } catch (error) {
281
+ console.error('Trip payment processing error:', error);
282
+ throw error;
283
+ }
284
+ }
285
+ ```
286
+
287
+ ### Payment History and Analytics
288
+
289
+ ```javascript
290
+ async function analyzePayments(client, userId) {
291
+ try {
292
+ // This would require additional API endpoints for payment history
293
+ // For now, we'll demonstrate with payment methods
294
+ const paymentMethods = await getPaymentMethodDetailsForUser(client, userId);
295
+
296
+ const analysis = {
297
+ userPaymentMethods: paymentMethods.length,
298
+ hasDefaultMethod: paymentMethods.some(pm => pm.isDefault),
299
+ supportedTypes: [...new Set(paymentMethods.map(pm => pm.type))],
300
+ cardBrands: paymentMethods
301
+ .filter(pm => pm.card)
302
+ .map(pm => pm.card.brand),
303
+ recentMethods: paymentMethods
304
+ .sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt))
305
+ .slice(0, 3)
306
+ };
307
+
308
+ console.log('Payment Analysis:');
309
+ console.log(`Payment Methods: ${analysis.userPaymentMethods}`);
310
+ console.log(`Has Default: ${analysis.hasDefaultMethod}`);
311
+ console.log(`Supported Types: ${analysis.supportedTypes.join(', ')}`);
312
+ console.log(`Card Brands: ${analysis.cardBrands.join(', ')}`);
313
+ console.log('Recent Methods:', analysis.recentMethods);
314
+
315
+ return analysis;
316
+ } catch (error) {
317
+ console.error('Payment analysis error:', error);
318
+ throw error;
319
+ }
320
+ }
20
321
  ```
package/dist/index.d.mts CHANGED
@@ -33,9 +33,32 @@ type PaymentDetail = {
33
33
  paymentMethod: 'SEPA' | 'IDEAL' | 'PAYPAL' | 'CREDIT_CARD' | 'WIRE_TRANSFER' | 'EXTERNAL';
34
34
  mopStatus: 'MOP_VALID' | 'MOP_MISSING' | 'MOP_EXPIRED' | 'MOP_INVALID' | 'MOP_UPDATING' | 'MOP_UPDATE_FAILED' | 'MOP_UNKNOWN';
35
35
  paymentCurrency: string;
36
- paymentType: 'CARD' | 'BANK' | 'PAYPAL' | 'SEPA' | 'EXTERNAL';
37
36
  cardFunding: 'credit' | 'debit' | 'prepaid' | 'unknown';
38
- };
37
+ } & ({
38
+ paymentType: 'CARD';
39
+ cardSummary?: string;
40
+ cardType?: string;
41
+ expiryDate?: number;
42
+ expiryMonth?: string;
43
+ expiryYear?: string;
44
+ } | {
45
+ paymentType: 'SEPA';
46
+ bankCode: string;
47
+ branchCode: string;
48
+ country: string;
49
+ fingerprint: string;
50
+ last4: string;
51
+ } | {
52
+ paymentType: 'BANK';
53
+ bankName: string;
54
+ bankAccountNumber: string;
55
+ iban: string;
56
+ bic: string;
57
+ } | {
58
+ paymentType: 'PAYPAL';
59
+ } | {
60
+ paymentType: 'EXTERNAL';
61
+ });
39
62
  type SynchronizeResponse = {
40
63
  status: 'SUCCEEDED' | 'REQUIRES_CAPTURE' | 'FAILED';
41
64
  };
package/dist/index.d.ts CHANGED
@@ -33,9 +33,32 @@ type PaymentDetail = {
33
33
  paymentMethod: 'SEPA' | 'IDEAL' | 'PAYPAL' | 'CREDIT_CARD' | 'WIRE_TRANSFER' | 'EXTERNAL';
34
34
  mopStatus: 'MOP_VALID' | 'MOP_MISSING' | 'MOP_EXPIRED' | 'MOP_INVALID' | 'MOP_UPDATING' | 'MOP_UPDATE_FAILED' | 'MOP_UNKNOWN';
35
35
  paymentCurrency: string;
36
- paymentType: 'CARD' | 'BANK' | 'PAYPAL' | 'SEPA' | 'EXTERNAL';
37
36
  cardFunding: 'credit' | 'debit' | 'prepaid' | 'unknown';
38
- };
37
+ } & ({
38
+ paymentType: 'CARD';
39
+ cardSummary?: string;
40
+ cardType?: string;
41
+ expiryDate?: number;
42
+ expiryMonth?: string;
43
+ expiryYear?: string;
44
+ } | {
45
+ paymentType: 'SEPA';
46
+ bankCode: string;
47
+ branchCode: string;
48
+ country: string;
49
+ fingerprint: string;
50
+ last4: string;
51
+ } | {
52
+ paymentType: 'BANK';
53
+ bankName: string;
54
+ bankAccountNumber: string;
55
+ iban: string;
56
+ bic: string;
57
+ } | {
58
+ paymentType: 'PAYPAL';
59
+ } | {
60
+ paymentType: 'EXTERNAL';
61
+ });
39
62
  type SynchronizeResponse = {
40
63
  status: 'SUCCEEDED' | 'REQUIRES_CAPTURE' | 'FAILED';
41
64
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vulog/aima-payment",
3
- "version": "1.1.88",
3
+ "version": "1.1.91",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/index.mjs",
6
6
  "types": "dist/index.d.ts",
@@ -19,8 +19,8 @@
19
19
  "author": "Vulog",
20
20
  "license": "MIT",
21
21
  "dependencies": {
22
- "@vulog/aima-client": "1.1.88",
23
- "@vulog/aima-core": "1.1.88"
22
+ "@vulog/aima-client": "1.1.91",
23
+ "@vulog/aima-core": "1.1.91"
24
24
  },
25
25
  "peerDependencies": {
26
26
  "zod": "^3.25.76"
@@ -0,0 +1,253 @@
1
+ import { describe, test, expect, vi, beforeEach, afterEach } from 'vitest';
2
+ import { Client } from '@vulog/aima-client';
3
+ import { getPaymentMethodDetailsForUser } from './getPaymentMethodDetailsForUser';
4
+ import { randomUUID } from 'crypto';
5
+
6
+ describe('getPaymentMethodDetailsForUser', () => {
7
+ const userId = randomUUID();
8
+ const getMock = vi.fn();
9
+ const client = {
10
+ get: getMock,
11
+ clientOptions: {
12
+ fleetId: 'FLEET_ID',
13
+ },
14
+ } as unknown as Client;
15
+ beforeEach(() => {
16
+ getMock.mockReset();
17
+ vi.useFakeTimers({ now: new Date('2025-01-12T13:35:50.123Z') });
18
+ });
19
+
20
+ afterEach(() => {
21
+ vi.useRealTimers();
22
+ });
23
+
24
+ test('call OK visa', async () => {
25
+ const mockData = {
26
+ token: 'pm_1RqA47HGgb8lFOFDpTeFe16C',
27
+ holderName: 'John Doe',
28
+ fleetId: client.clientOptions.fleetId,
29
+ entityId: '2f16423b-2b75-4a6e-a82e-5087f98a4df8',
30
+ pspName: 'STRIPE',
31
+ customerPspReference: 'cus_ScgfSAgJ6rmaNo',
32
+ entityStatus: 'APPROVED',
33
+ profileId: '7ca3b51c-3ada-4fe0-8e36-0030940dfde1',
34
+ profileName: 'default',
35
+ profileType: 'Single',
36
+ paymentMethod: 'CREDIT_CARD',
37
+ mopStatus: 'MOP_VALID',
38
+ cardSummary: '0817',
39
+ cardType: 'visa',
40
+ cardFunding: 'credit',
41
+ expiryDate: 1856563200000,
42
+ expiryMonth: '10',
43
+ expiryYear: '2028',
44
+ paymentType: 'CARD',
45
+ };
46
+ getMock.mockResolvedValueOnce({ data: [
47
+ mockData,
48
+ ]});
49
+
50
+ const result = await getPaymentMethodDetailsForUser(client, userId);
51
+
52
+ expect(getMock).toBeCalled();
53
+ expect(getMock).toBeCalledWith(`/boapi/proxy/user/fleets/FLEET_ID/users/${userId}/paymentMethodDetails`);
54
+ expect(result).toBeTruthy();
55
+ expect(result?.token).toEqual(mockData.token);
56
+ expect(result?.holderName).toEqual(mockData.holderName);
57
+ expect(result?.fleetId).toEqual(mockData.fleetId);
58
+ expect(result?.entityId).toEqual(mockData.entityId);
59
+ expect(result?.pspName).toEqual(mockData.pspName);
60
+ expect(result?.customerPspReference).toEqual(mockData.customerPspReference);
61
+ expect(result?.entityStatus).toEqual(mockData.entityStatus);
62
+ expect(result?.profileId).toEqual(mockData.profileId);
63
+ expect(result?.profileName).toEqual(mockData.profileName);
64
+ expect(result?.profileType).toEqual(mockData.profileType);
65
+ expect(result?.paymentMethod).toEqual(mockData.paymentMethod);
66
+ expect(result?.mopStatus).toEqual(mockData.mopStatus);
67
+ expect(result?.paymentCurrency).toBeUndefined();
68
+ expect(result?.paymentType).toEqual(mockData.paymentType);
69
+ expect(result?.cardFunding).toEqual(mockData.cardFunding);
70
+ expect(result?.paymentType).toEqual('CARD');
71
+ if (result?.paymentType === 'CARD') {
72
+ expect(result?.cardSummary).toEqual(mockData.cardSummary);
73
+ expect(result?.cardType).toEqual(mockData.cardType);
74
+ expect(result?.expiryDate).toEqual(mockData.expiryDate);
75
+ expect(result?.expiryMonth).toEqual(mockData.expiryMonth);
76
+ expect(result?.expiryYear).toEqual(mockData.expiryYear);
77
+ }
78
+ });
79
+
80
+ test('call OK SEPA', async () => {
81
+ const mockData = {
82
+ token: 'pm_1Kb5WdCOd50lRjiu9tPH3r5i',
83
+ holderName: 'Thomas Durant',
84
+ fleetId: client.clientOptions.fleetId,
85
+ entityId: '2330f5d0-91a3-49fb-8f85-4133384bc02c',
86
+ pspName: 'STRIPE',
87
+ customerPspReference: 'cus_LHcyYpiF7A2he3',
88
+ entityStatus: 'PENDING',
89
+ profileId: 'ec94adb1-98e8-48ec-952a-dddc6cba8464',
90
+ profileName: 'default',
91
+ profileType: 'Single',
92
+ paymentMethod: 'SEPA',
93
+ mopStatus: 'MOP_INVALID',
94
+ bankCode: '20041',
95
+ branchCode: '01005',
96
+ country: 'FR',
97
+ fingerprint: 'SPFArCDNSB9TvZuS',
98
+ last4: '2606',
99
+ paymentType: 'SEPA',
100
+ };
101
+ getMock.mockResolvedValueOnce({ data: [
102
+ mockData,
103
+ ]});
104
+
105
+ const result = await getPaymentMethodDetailsForUser(client, userId);
106
+
107
+ expect(getMock).toBeCalled();
108
+ expect(getMock).toBeCalledWith(`/boapi/proxy/user/fleets/FLEET_ID/users/${userId}/paymentMethodDetails`);
109
+ expect(result).toBeTruthy();
110
+ expect(result?.token).toEqual(mockData.token);
111
+ expect(result?.holderName).toEqual(mockData.holderName);
112
+ expect(result?.fleetId).toEqual(mockData.fleetId);
113
+ expect(result?.entityId).toEqual(mockData.entityId);
114
+ expect(result?.pspName).toEqual(mockData.pspName);
115
+ expect(result?.customerPspReference).toEqual(mockData.customerPspReference);
116
+ expect(result?.entityStatus).toEqual(mockData.entityStatus);
117
+ expect(result?.profileId).toEqual(mockData.profileId);
118
+ expect(result?.profileName).toEqual(mockData.profileName);
119
+ expect(result?.profileType).toEqual(mockData.profileType);
120
+ expect(result?.paymentMethod).toEqual(mockData.paymentMethod);
121
+ expect(result?.mopStatus).toEqual(mockData.mopStatus);
122
+ expect(result?.paymentCurrency).toBeUndefined();
123
+ expect(result?.paymentType).toEqual(mockData.paymentType);
124
+ expect(result?.cardFunding).toBeUndefined;
125
+ expect(result?.paymentType).toEqual('SEPA');
126
+ if (result?.paymentType === 'SEPA') {
127
+ expect(result?.bankCode).toEqual(mockData.bankCode);
128
+ expect(result?.branchCode).toEqual(mockData.branchCode);
129
+ expect(result?.country).toEqual(mockData.country);
130
+ expect(result?.fingerprint).toEqual(mockData.fingerprint);
131
+ expect(result?.last4).toEqual(mockData.last4);
132
+ }
133
+ });
134
+
135
+ test('call OK BANK', async () => {
136
+ const mockData = {
137
+ token: '8416227869543125',
138
+ holderName: 'Jack Dalton',
139
+ fleetId: client.clientOptions.fleetId,
140
+ entityId: '2330f5d0-91a3-49fb-8f85-4133384bc02d',
141
+ pspName: null,
142
+ customerPspReference: null,
143
+ entityStatus: 'APPROVED',
144
+ profileId: 'ec94adb1-98e8-48ec-952a-dddc6cba8465',
145
+ profileName: 'default',
146
+ profileType: 'Single',
147
+ paymentMethod: 'IDEAL',
148
+ mopStatus: 'MOP_INVALID',
149
+ paymentCurrency: null,
150
+ bankName: 'Test Issuer',
151
+ bankAccountNumber: '951',
152
+ iban: 'NL13TEST0123456789',
153
+ bic: 'TESTNL01',
154
+ paymentType: 'BANK',
155
+ };
156
+ getMock.mockResolvedValueOnce({ data: [
157
+ mockData,
158
+ ]});
159
+
160
+ const result = await getPaymentMethodDetailsForUser(client, userId);
161
+
162
+ expect(getMock).toBeCalled();
163
+ expect(getMock).toBeCalledWith(`/boapi/proxy/user/fleets/FLEET_ID/users/${userId}/paymentMethodDetails`);
164
+ expect(result).toBeTruthy();
165
+ expect(result?.token).toEqual(mockData.token);
166
+ expect(result?.holderName).toEqual(mockData.holderName);
167
+ expect(result?.fleetId).toEqual(mockData.fleetId);
168
+ expect(result?.entityId).toEqual(mockData.entityId);
169
+ expect(result?.pspName).toEqual(mockData.pspName);
170
+ expect(result?.customerPspReference).toEqual(mockData.customerPspReference);
171
+ expect(result?.entityStatus).toEqual(mockData.entityStatus);
172
+ expect(result?.profileId).toEqual(mockData.profileId);
173
+ expect(result?.profileName).toEqual(mockData.profileName);
174
+ expect(result?.profileType).toEqual(mockData.profileType);
175
+ expect(result?.paymentMethod).toEqual(mockData.paymentMethod);
176
+ expect(result?.mopStatus).toEqual(mockData.mopStatus);
177
+ expect(result?.paymentCurrency).toBeFalsy();
178
+ expect(result?.paymentType).toEqual(mockData.paymentType);
179
+ expect(result?.cardFunding).toBeUndefined;
180
+ expect(result?.paymentType).toEqual('BANK');
181
+ if (result?.paymentType === 'BANK') {
182
+ expect(result?.bankName).toEqual(mockData.bankName);
183
+ expect(result?.bankAccountNumber).toEqual(mockData.bankAccountNumber);
184
+ expect(result?.iban).toEqual(mockData.iban);
185
+ expect(result?.bic).toEqual(mockData.bic);
186
+ }
187
+ });
188
+
189
+ test('call OK missing + business', async () => {
190
+ const mockData = [
191
+ {
192
+ token: null,
193
+ holderName: null,
194
+ fleetId: 'KINTOEU-ESSHARE',
195
+ entityId: 'cc42a4ca-2881-4ea3-af0e-1d8b15599243',
196
+ pspName: null,
197
+ customerPspReference: null,
198
+ entityStatus: 'APPROVED',
199
+ profileId: '2dfd07c3-cb97-4df0-a496-48a1c6c7eed4',
200
+ profileName: 'default',
201
+ profileType: 'Business',
202
+ paymentMethod: 'WIRE_TRANSFER',
203
+ mopStatus: 'MOP_VALID',
204
+ paymentCurrency: null,
205
+ bankName: null,
206
+ bankAccountNumber: null,
207
+ iban: 'FR0000000000000000',
208
+ bic: null,
209
+ paymentType: 'BANK',
210
+ },
211
+ {
212
+ entityStatus: 'APPROVED',
213
+ profileId: 'd392469a-484e-4b86-b9f7-498c2e27e3e0',
214
+ profileName: 'default',
215
+ profileType: 'Single',
216
+ paymentMethod: 'CREDIT_CARD',
217
+ mopStatus: 'MOP_MISSING',
218
+ paymentType: 'CARD',
219
+ }
220
+ ];
221
+ getMock.mockResolvedValueOnce({ data: mockData });
222
+
223
+ const result = await getPaymentMethodDetailsForUser(client, userId);
224
+
225
+ expect(getMock).toBeCalled();
226
+ expect(getMock).toBeCalledWith(`/boapi/proxy/user/fleets/FLEET_ID/users/${userId}/paymentMethodDetails`);
227
+ expect(result).toBeTruthy();
228
+ expect(result?.token).toBeUndefined();
229
+ expect(result?.holderName).toBeUndefined();
230
+ expect(result?.fleetId).toBeUndefined();
231
+ expect(result?.entityId).toBeUndefined();
232
+ expect(result?.pspName).toBeUndefined();
233
+ expect(result?.customerPspReference).toBeUndefined();
234
+ expect(result?.entityStatus).toEqual(mockData[1].entityStatus);
235
+ expect(result?.profileId).toEqual(mockData[1].profileId);
236
+ expect(result?.profileName).toEqual(mockData[1].profileName);
237
+ expect(result?.profileType).toEqual(mockData[1].profileType);
238
+ expect(result?.paymentMethod).toEqual(mockData[1].paymentMethod);
239
+ expect(result?.mopStatus).toEqual(mockData[1].mopStatus);
240
+ expect(result?.paymentCurrency).toBeUndefined();
241
+ expect(result?.paymentType).toEqual(mockData[1].paymentType);
242
+ expect(result?.cardFunding).toBeUndefined;
243
+ expect(result?.paymentType).toEqual('CARD');
244
+ expect(result?.mopStatus).toEqual('MOP_MISSING');
245
+ if (result?.paymentType === 'CARD') {
246
+ expect(result?.cardSummary).toBeUndefined();
247
+ expect(result?.cardType).toBeUndefined();
248
+ expect(result?.expiryDate).toBeUndefined();
249
+ expect(result?.expiryMonth).toBeUndefined();
250
+ expect(result?.expiryYear).toBeUndefined();
251
+ }
252
+ });
253
+ });
package/src/types.ts CHANGED
@@ -38,9 +38,40 @@ export type PaymentDetail = {
38
38
  | 'MOP_UPDATE_FAILED'
39
39
  | 'MOP_UNKNOWN';
40
40
  paymentCurrency: string;
41
- paymentType: 'CARD' | 'BANK' | 'PAYPAL' | 'SEPA' | 'EXTERNAL';
42
41
  cardFunding: 'credit' | 'debit' | 'prepaid' | 'unknown';
43
- };
42
+ } & (
43
+ | {
44
+ paymentType: 'CARD'; // CARD is also the type used when there is no MoP ... hence all are optional.
45
+ cardSummary?: string;
46
+ cardType?: string;
47
+ expiryDate?: number;
48
+ expiryMonth?: string;
49
+ expiryYear?: string;
50
+ }
51
+ | {
52
+ paymentType: 'SEPA';
53
+ bankCode: string;
54
+ branchCode: string;
55
+ country: string;
56
+ fingerprint: string;
57
+ last4: string;
58
+ }
59
+ | {
60
+ paymentType: 'BANK';
61
+ bankName: string;
62
+ bankAccountNumber: string;
63
+ iban: string;
64
+ bic: string;
65
+ }
66
+ | {
67
+ paymentType: 'PAYPAL';
68
+ // ??
69
+ }
70
+ | {
71
+ paymentType: 'EXTERNAL';
72
+ // nothing more
73
+ }
74
+ );
44
75
 
45
76
  export type SynchronizeResponse = {
46
77
  status: 'SUCCEEDED' | 'REQUIRES_CAPTURE' | 'FAILED';