Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ adding additional type guards.

## Unreleased

### Added

- Added the `checkoutDomains` resource for listing, getting, deleting, and verifying payment methods for checkout domains. Checkout domain path arguments accept legacy IDs.

---

## 3.8.0 - 2026-04-20
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@paddle/paddle-node-sdk",
"version": "3.8.0",
"version": "3.9.0",
"description": "A Node.js SDK that you can use to integrate Paddle Billing with applications written in server-side JavaScript.",
"main": "dist/cjs/index.cjs.node.js",
"module": "dist/esm/index.esm.node.js",
Expand Down
50 changes: 50 additions & 0 deletions src/__tests__/mocks/resources/checkout-domains.mock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/**
* ! Autogenerated code !
* Do not make changes to this file.
* Changes may be overwritten as part of auto-generation.
*/

import { type VerifyCheckoutDomainPaymentMethodRequestBody } from '../../../resources/index.js';
import { type ICheckoutDomainResponse } from '../../../types/index.js';
import { type Response, type ResponsePaginated } from '../../../internal/index.js';

export const CheckoutDomainMock: ICheckoutDomainResponse = {
id: 'chedom_01j2abc3def4ghi5jkl6mno7pq',
domain: 'app.example.com',
status: 'action_required',
payment_method_verification: {
apple_pay: {
status: 'verified',
},
},
created_at: '2026-03-04T12:00:00.000Z',
updated_at: '2026-03-04T14:30:00.000Z',
};

export const CheckoutDomainMockResponse: Response<ICheckoutDomainResponse> = {
data: CheckoutDomainMock,
meta: {
request_id: '',
},
};

export const ListCheckoutDomainsMockResponse: ResponsePaginated<ICheckoutDomainResponse> = {
data: [CheckoutDomainMock],
meta: {
request_id: '',
pagination: {
estimated_total: 1,
has_more: true,
next: '/checkout-domains?after=1',
per_page: 10,
},
},
};

export const VerifyCheckoutDomainPaymentMethodMock: VerifyCheckoutDomainPaymentMethodRequestBody = {
paymentMethod: 'apple_pay',
};

export const VerifyCheckoutDomainPaymentMethodExpectation = {
payment_method: 'apple_pay',
};
79 changes: 79 additions & 0 deletions src/__tests__/resources/checkout-domains.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/**
* ! Autogenerated code !
* Do not make changes to this file.
* Changes may be overwritten as part of auto-generation.
*/

import { getPaddleTestClient } from '../helpers/test-client.js';
import {
CheckoutDomainMockResponse,
ListCheckoutDomainsMockResponse,
VerifyCheckoutDomainPaymentMethodExpectation,
VerifyCheckoutDomainPaymentMethodMock,
} from '../mocks/resources/checkout-domains.mock.js';
import { CheckoutDomainsResource } from '../../resources/index.js';
import { convertToSnakeCase } from '../../internal/index.js';

const legacyDomainId = '9b95b0b8-e10f-441a-862e-1936a6d818ab';

describe('CheckoutDomainsResource', () => {
test('should return a list of checkout domains', async () => {
const paddleInstance = getPaddleTestClient();
paddleInstance.get = jest.fn().mockResolvedValue(ListCheckoutDomainsMockResponse);

const checkoutDomainsResource = new CheckoutDomainsResource(paddleInstance);
const checkoutDomainCollection = checkoutDomainsResource.list();

let checkoutDomains = await checkoutDomainCollection.next();
expect(paddleInstance.get).toHaveBeenCalledWith('/checkout-domains?');
expect(checkoutDomains).toHaveLength(1);
expect(checkoutDomains[0]?.status).toBe('action_required');
expect(checkoutDomains[0]?.paymentMethodVerification.applePay.status).toBe('verified');

checkoutDomains = await checkoutDomainCollection.next();
expect(paddleInstance.get).toHaveBeenCalledWith('/checkout-domains?after=1');
expect(checkoutDomains).toHaveLength(1);
});

test('should get a checkout domain using a legacy domain ID', async () => {
const paddleInstance = getPaddleTestClient();
paddleInstance.get = jest.fn().mockResolvedValue(CheckoutDomainMockResponse);

const checkoutDomainsResource = new CheckoutDomainsResource(paddleInstance);
const checkoutDomain = await checkoutDomainsResource.get(legacyDomainId);

expect(paddleInstance.get).toHaveBeenCalledWith(`/checkout-domains/${legacyDomainId}`);
expect(checkoutDomain).toBeDefined();
});

test('should delete a checkout domain using a legacy domain ID', async () => {
const paddleInstance = getPaddleTestClient();
paddleInstance.delete = jest.fn().mockResolvedValue(undefined);

const checkoutDomainsResource = new CheckoutDomainsResource(paddleInstance);
const checkoutDomain = await checkoutDomainsResource.delete(legacyDomainId);

expect(paddleInstance.delete).toHaveBeenCalledWith(`/checkout-domains/${legacyDomainId}`);
expect(checkoutDomain).toBeUndefined();
});

test('should verify a payment method using a legacy domain ID', async () => {
const paddleInstance = getPaddleTestClient();
paddleInstance.post = jest.fn().mockResolvedValue(CheckoutDomainMockResponse);

const checkoutDomainsResource = new CheckoutDomainsResource(paddleInstance);
const checkoutDomain = await checkoutDomainsResource.verifyPaymentMethod(
legacyDomainId,
VerifyCheckoutDomainPaymentMethodMock,
);

expect(paddleInstance.post).toHaveBeenCalledWith(
`/checkout-domains/${legacyDomainId}/verify-payment-method`,
VerifyCheckoutDomainPaymentMethodMock,
);
expect(checkoutDomain).toBeDefined();
expect(convertToSnakeCase(VerifyCheckoutDomainPaymentMethodMock)).toEqual(
VerifyCheckoutDomainPaymentMethodExpectation,
);
});
});
15 changes: 15 additions & 0 deletions src/entities/checkout-domains/checkout-domain-collection.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* ! Autogenerated code !
* Do not make changes to this file.
* Changes may be overwritten as part of auto-generation.
*/

import { Collection } from '../../internal/base/index.js';
import { type ICheckoutDomainResponse } from '../../types/index.js';
import { CheckoutDomain } from './checkout-domain.js';

export class CheckoutDomainCollection extends Collection<ICheckoutDomainResponse, CheckoutDomain> {
override fromJson(data: ICheckoutDomainResponse): CheckoutDomain {
return new CheckoutDomain(data);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* ! Autogenerated code !
* Do not make changes to this file.
* Changes may be overwritten as part of auto-generation.
*/

import { type CheckoutDomainPaymentMethodVerificationStatus } from '../../enums/index.js';
import { type ICheckoutDomainPaymentMethodVerificationResponse } from '../../types/index.js';

export class CheckoutDomainApplePayVerification {
public readonly status: CheckoutDomainPaymentMethodVerificationStatus;

constructor(status: CheckoutDomainPaymentMethodVerificationStatus) {
this.status = status;
}
}

export class CheckoutDomainPaymentMethodVerification {
public readonly applePay: CheckoutDomainApplePayVerification;

constructor(paymentMethodVerification: ICheckoutDomainPaymentMethodVerificationResponse) {
this.applePay = new CheckoutDomainApplePayVerification(paymentMethodVerification.apple_pay.status);
}
}
29 changes: 29 additions & 0 deletions src/entities/checkout-domains/checkout-domain.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
* ! Autogenerated code !
* Do not make changes to this file.
* Changes may be overwritten as part of auto-generation.
*/

import { type CheckoutDomainApprovalStatus } from '../../enums/index.js';
import { type ICheckoutDomainResponse } from '../../types/index.js';
import { CheckoutDomainPaymentMethodVerification } from './checkout-domain-payment-method-verification.js';

export class CheckoutDomain {
public readonly id: string;
public readonly domain: string;
public readonly status: CheckoutDomainApprovalStatus;
public readonly paymentMethodVerification: CheckoutDomainPaymentMethodVerification;
public readonly createdAt: string;
public readonly updatedAt: string;

constructor(checkoutDomain: ICheckoutDomainResponse) {
this.id = checkoutDomain.id;
this.domain = checkoutDomain.domain;
this.status = checkoutDomain.status;
this.paymentMethodVerification = new CheckoutDomainPaymentMethodVerification(
checkoutDomain.payment_method_verification,
);
this.createdAt = checkoutDomain.created_at;
this.updatedAt = checkoutDomain.updated_at;
}
}
9 changes: 9 additions & 0 deletions src/entities/checkout-domains/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* ! Autogenerated code !
* Do not make changes to this file.
* Changes may be overwritten as part of auto-generation.
*/

export * from './checkout-domain.js';
export * from './checkout-domain-collection.js';
export * from './checkout-domain-payment-method-verification.js';
1 change: 1 addition & 0 deletions src/entities/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export * from './subscription/index.js';
export * from './address/index.js';
export * from './discount/index.js';
export * from './discount-group/index.js';
export * from './checkout-domains/index.js';
export * from './events/index.js';
export * from './payment-method/index.js';
export * from './payout/index.js';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/**
* ! Autogenerated code !
* Do not make changes to this file.
* Changes may be overwritten as part of auto-generation.
*/

export type CheckoutDomainApprovalStatus = 'pending_review' | 'approved' | 'rejected' | 'in_review' | 'action_required';
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/**
* ! Autogenerated code !
* Do not make changes to this file.
* Changes may be overwritten as part of auto-generation.
*/

export type CheckoutDomainPaymentMethodVerificationStatus = 'verified' | 'unverified';
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/**
* ! Autogenerated code !
* Do not make changes to this file.
* Changes may be overwritten as part of auto-generation.
*/

export type CheckoutDomainPaymentMethod = 'apple_pay';
9 changes: 9 additions & 0 deletions src/enums/checkout-domains/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* ! Autogenerated code !
* Do not make changes to this file.
* Changes may be overwritten as part of auto-generation.
*/

export * from './checkout-domain-approval-status.js';
export * from './checkout-domain-payment-method.js';
export * from './checkout-domain-payment-method-verification-status.js';
1 change: 1 addition & 0 deletions src/enums/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*/

export * from './shared/index.js';
export * from './checkout-domains/index.js';
export * from './metrics/index.js';
export * from './subscription/index.js';
export * from './discount/index.js';
Expand Down
3 changes: 3 additions & 0 deletions src/paddle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
AddressesResource,
AdjustmentsResource,
BusinessesResource,
CheckoutDomainsResource,
CustomerPortalSessionsResource,
CustomersResource,
DiscountGroupsResource,
Expand Down Expand Up @@ -43,6 +44,7 @@ export class Paddle {
public customerPortalSessions: CustomerPortalSessionsResource;
public addresses: AddressesResource;
public businesses: BusinessesResource;
public checkoutDomains: CheckoutDomainsResource;
public discounts: DiscountsResource;
public discountGroups: DiscountGroupsResource;
public subscriptions: SubscriptionsResource;
Expand Down Expand Up @@ -75,6 +77,7 @@ export class Paddle {
this.customerPortalSessions = new CustomerPortalSessionsResource(this.client);
this.addresses = new AddressesResource(this.client);
this.businesses = new BusinessesResource(this.client);
this.checkoutDomains = new CheckoutDomainsResource(this.client);
this.discounts = new DiscountsResource(this.client);
this.discountGroups = new DiscountGroupsResource(this.client);
this.subscriptions = new SubscriptionsResource(this.client);
Expand Down
74 changes: 74 additions & 0 deletions src/resources/checkout-domains/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/**
* ! Autogenerated code !
* Do not make changes to this file.
* Changes may be overwritten as part of auto-generation.
*/

import { BaseResource, PathParameters, QueryParameters } from '../../internal/base/index.js';
import { type ErrorResponse, type Response } from '../../internal/index.js';
import { CheckoutDomain, CheckoutDomainCollection } from '../../entities/index.js';
import { type ICheckoutDomainResponse } from '../../types/index.js';
import {
type ListCheckoutDomainsQueryParameters,
type VerifyCheckoutDomainPaymentMethodRequestBody,
} from './operations/index.js';

const CheckoutDomainPaths = {
list: '/checkout-domains',
get: '/checkout-domains/{domain_id}',
delete: '/checkout-domains/{domain_id}',
verifyPaymentMethod: '/checkout-domains/{domain_id}/verify-payment-method',
} as const;

export * from './operations/index.js';

export class CheckoutDomainsResource extends BaseResource {
public list(queryParams?: ListCheckoutDomainsQueryParameters): CheckoutDomainCollection {
const queryParameters = new QueryParameters(queryParams);
return new CheckoutDomainCollection(this.client, CheckoutDomainPaths.list + queryParameters.toQueryString());
}

public async get(domainId: string): Promise<CheckoutDomain> {
const urlWithPathParams = new PathParameters(CheckoutDomainPaths.get, {
domain_id: domainId,
}).deriveUrl();

const response = await this.client.get<undefined, Response<ICheckoutDomainResponse> | ErrorResponse>(
urlWithPathParams,
);

const data = this.handleResponse<ICheckoutDomainResponse>(response);

return new CheckoutDomain(data);
}

public async delete(domainId: string): Promise<undefined> {
const urlWithPathParams = new PathParameters(CheckoutDomainPaths.delete, {
domain_id: domainId,
}).deriveUrl();

const response = await this.client.delete(urlWithPathParams);

if (response) {
this.handleResponse<undefined>(response);
}
}

public async verifyPaymentMethod(
domainId: string,
requestBody: VerifyCheckoutDomainPaymentMethodRequestBody,
): Promise<CheckoutDomain> {
const urlWithPathParams = new PathParameters(CheckoutDomainPaths.verifyPaymentMethod, {
domain_id: domainId,
}).deriveUrl();

const response = await this.client.post<
VerifyCheckoutDomainPaymentMethodRequestBody,
Response<ICheckoutDomainResponse> | ErrorResponse
>(urlWithPathParams, requestBody);

const data = this.handleResponse<ICheckoutDomainResponse>(response);

return new CheckoutDomain(data);
}
}
8 changes: 8 additions & 0 deletions src/resources/checkout-domains/operations/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/**
* ! Autogenerated code !
* Do not make changes to this file.
* Changes may be overwritten as part of auto-generation.
*/

export * from './list-checkout-domains-query-parameters.js';
export * from './verify-checkout-domain-payment-method-request-body.js';
Loading
Loading