Skip to content

Commit 42e6ac3

Browse files
committed
feat: Add 3DS session support and update to cards endpoint
Includes card changes to use `multi_use` and new endpoint with /payments prefix. Add support for Create a 3DS session.
1 parent d241e4b commit 42e6ac3

File tree

10 files changed

+111
-6
lines changed

10 files changed

+111
-6
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@duffel/api",
3-
"version": "3.3.0",
3+
"version": "4.0.0",
44
"description": "Javascript client library for the Duffel API",
55
"main": "dist/index.js",
66
"module": "dist/index.es.js",

src/Vault/Cards/Cards.spec.ts renamed to src/Payments/Cards/Cards.spec.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ describe('Cards', () => {
1010
it('should create a card record when `create` is called', async () => {
1111
const MOCK_ID = 'tcd_00009hthhsUZ8W4LxQgkjb'
1212
nock(/(.*)/)
13-
.post('/vault/cards')
14-
.reply(200, { data: { id: MOCK_ID, liveMode: false } })
13+
.post('/payments/cards')
14+
.reply(200, { data: { id: MOCK_ID, liveMode: false, unavailableAt: '2024-01-01T00:00:00', brand: 'visa', multiUse: false, last4Digits: '4242' } })
1515

1616
const response = await duffel.cards.create({
1717
address_city: 'London',
@@ -25,6 +25,7 @@ describe('Cards', () => {
2525
name: 'Neil Armstrong',
2626
number: '4242424242424242',
2727
cvc: '123',
28+
multi_use: false,
2829
})
2930
expect(response.data.id).toBe(MOCK_ID)
3031
})

src/Vault/Cards/Cards.ts renamed to src/Payments/Cards/Cards.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,19 @@ interface CardParameters {
5656
* The card verification code
5757
*/
5858
cvc: string
59+
/**
60+
* Set to true to indicate that this card can be used multiple times
61+
*/
62+
multi_use: boolean
5963
}
6064

6165
interface CardRecord {
6266
id: string
6367
live_mode: boolean
68+
multi_use: boolean
69+
unavailble_at: string
70+
brand: string
71+
last_4_digits: string
6472
}
6573

6674
export class Cards extends Resource {
@@ -72,7 +80,7 @@ export class Cards extends Resource {
7280
// basePath must be 'https://api.duffel.cards'
7381
constructor(client: Client) {
7482
super(client)
75-
this.path = 'vault/cards'
83+
this.path = 'payments/cards'
7684
}
7785

7886
/**
File renamed without changes.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import nock from 'nock'
2+
import { Duffel } from '../../index'
3+
4+
const duffel = new Duffel({ token: 'mockToken' })
5+
describe('ThreeDSecureSessions', () => {
6+
afterEach(() => {
7+
nock.cleanAll()
8+
})
9+
10+
it('should create a 3DS session record when `create` is called', async () => {
11+
const MOCK_ID = '3ds_00009hthhsUZ8W4LxQgkjb'
12+
nock(/(.*)/)
13+
.post('/payments/three_d_secure_sessions')
14+
.reply(200, { data: { id: MOCK_ID, liveMode: false, expiresAt: '2024-01-01T00:00:00', status: 'ready_for_payment', resourceId: 'off_00009hthhsUZ8W4LxQgkjb', clientId: 'tds_57aa862f8bf7', cardID: 'tcd_00009hthhsUZ8W4LxQgkjb'} })
15+
16+
const response = await duffel.cards.create({
17+
resource_id: 'off_00009hthhsUZ8W4LxQgkjb',
18+
card_id: 'tcd_00009hthhsUZ8W4LxQgkjb'
19+
services: [{quantity: 1, id: 'ser_00009UhD4ongolulWd9123'}],
20+
exception: null,
21+
})
22+
expect(response.data.id).toBe(MOCK_ID)
23+
})
24+
})
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import { Client } from '../../Client'
2+
import { Resource } from '../../Resource'
3+
import { DuffelResponse } from '../../types'
4+
5+
interface Service {
6+
/**
7+
* The quantity of the service ID to pay for
8+
*/
9+
quantity: number
10+
/**
11+
* The ID of the service to pay for
12+
*/
13+
id: string
14+
}
15+
16+
interface ThreeDSecureSessionParameters {
17+
/**
18+
* The offer ID, order ID, order change ID or quote ID intended to pay
19+
*/
20+
resource_id: string
21+
22+
/**
23+
* The services inteded to pay
24+
*/
25+
services: Service[]
26+
27+
/**
28+
* The card ID
29+
*/
30+
card_id: string
31+
32+
/**
33+
* The exception name for the 3DS session
34+
*/
35+
exception: string
36+
}
37+
38+
interface ThreeDSecureSessionRecord {
39+
id: string
40+
resource_id: string
41+
card_id: string
42+
live_mode: boolean
43+
expires_at: string
44+
status: string
45+
client_id: string
46+
}
47+
48+
export class ThreeDSecureSession extends Resource {
49+
/**
50+
* Endpoint path
51+
*/
52+
path: string
53+
54+
constructor(args: any) {
55+
super(args)
56+
this.path = 'payments/three_d_secure_sessions'
57+
}
58+
59+
/**
60+
* Create a Duffel ThreeDSecureSession record
61+
*/
62+
public create = async (
63+
data: ThreeDSecureSessionParameters,
64+
): Promise<DuffelResponse<ThreeDSecureSessionRecord>> =>
65+
this.request({ method: 'POST', path: this.path, data })
66+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './ThreeDSecureSessions'

src/Payments/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './Cards'
2+
export * from './ThreeDSecureSessions'

src/Vault/index.ts

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ import { Refunds } from './DuffelPayments/Refunds'
1919
import { Sessions } from './Links'
2020
import { Webhooks } from './notifications'
2121
import { Stays } from './Stays/Stays'
22-
import { Cards } from './Vault/Cards'
22+
import { Cards } from './Payments/Cards'
23+
import { ThreeDSecureSessions } from './Payments/ThreeDSecureSessions'
2324

2425
export interface DuffelAPIClient {
2526
aircraft: Aircraft
@@ -34,6 +35,7 @@ export interface DuffelAPIClient {
3435
orderCancellations: OrderCancellations
3536
payments: Payments
3637
seatMaps: SeatMaps
38+
threeDSecureSessions: ThreeDSecureSessions
3739
}
3840

3941
export class Duffel {
@@ -58,6 +60,7 @@ export class Duffel {
5860
public refunds: Refunds
5961
public webhooks: Webhooks
6062
public stays: Stays
63+
public three_d_secure_sessions: ThreeDSecureSessions
6164

6265
private cardsClient: Client
6366
public cards: Cards
@@ -85,6 +88,7 @@ export class Duffel {
8588
this.refunds = new Refunds(this.client)
8689
this.webhooks = new Webhooks(this.client)
8790
this.stays = new Stays(this.client)
91+
this.three_d_secure_sessions = new ThreeDSecureSessions(this.client)
8892

8993
this.cardsClient = new Client({
9094
...config,

0 commit comments

Comments
 (0)