diff --git a/src/controller/checkout.controller.ts b/src/controller/checkout.controller.ts index ab46382f..08b70806 100644 --- a/src/controller/checkout.controller.ts +++ b/src/controller/checkout.controller.ts @@ -28,6 +28,7 @@ export function checkoutController(usersService: UsersService, paymentsService: postalCode: string; captchaToken: string; companyVatId?: string; + metadata?: Record; }; }>( '/customer', @@ -45,6 +46,10 @@ export function checkoutController(usersService: UsersService, paymentsService: postalCode: { type: 'string' }, captchaToken: { type: 'string' }, companyVatId: { type: 'string' }, + metadata: { + type: 'object', + additionalProperties: { type: 'string' }, + }, }, }, }, @@ -57,8 +62,17 @@ export function checkoutController(usersService: UsersService, paymentsService: }, async (req, res): Promise<{ customerId: string; token: string }> => { let customerId: Stripe.Customer['id']; - const { customerName, lineAddress1, lineAddress2, city, country, postalCode, companyVatId, captchaToken } = - req.body; + const { + customerName, + lineAddress1, + lineAddress2, + city, + country, + postalCode, + companyVatId, + captchaToken, + metadata, + } = req.body; const { uuid: userUuid, email } = req.user.payload; const verifiedCaptcha = await verifyRecaptcha(captchaToken); @@ -80,6 +94,7 @@ export function checkoutController(usersService: UsersService, paymentsService: postalCode, country, }, + metadata, }); customerId = userExists.customerId; } else { @@ -93,6 +108,7 @@ export function checkoutController(usersService: UsersService, paymentsService: postalCode, country, }, + metadata, }); await usersService.insertUser({ diff --git a/src/infrastructure/adapters/stripe.adapter.ts b/src/infrastructure/adapters/stripe.adapter.ts index e86a6a00..2983ef42 100644 --- a/src/infrastructure/adapters/stripe.adapter.ts +++ b/src/infrastructure/adapters/stripe.adapter.ts @@ -70,6 +70,7 @@ export class StripePaymentsAdapter implements PaymentsAdapter { postal_code: params.address.postalCode ?? undefined, }, }), + ...(params.metadata && { metadata: params.metadata }), }; } } diff --git a/src/infrastructure/domain/entities/customer.ts b/src/infrastructure/domain/entities/customer.ts index f12dda25..39daa8d8 100644 --- a/src/infrastructure/domain/entities/customer.ts +++ b/src/infrastructure/domain/entities/customer.ts @@ -7,6 +7,7 @@ export interface CreateCustomerParams { name: string; email: string; address: Partial
; + metadata?: Record; } export interface UpdateCustomerParams extends Partial { diff --git a/tests/src/infrastructure/adapters/stripe.adapter.test.ts b/tests/src/infrastructure/adapters/stripe.adapter.test.ts index 97e9bbaa..fa9c8998 100644 --- a/tests/src/infrastructure/adapters/stripe.adapter.test.ts +++ b/tests/src/infrastructure/adapters/stripe.adapter.test.ts @@ -14,6 +14,8 @@ describe('Stripe Adapter', () => { .spyOn(stripePaymentsAdapter.getInstance().customers, 'create') .mockResolvedValue(mockedCustomer as Stripe.Response); + const metadata = { referralCode: 'ABC123' }; + const createdCustomer = await stripePaymentsAdapter.createCustomer({ email: mockedCustomer.email as string, name: mockedCustomer.name as string, @@ -25,6 +27,7 @@ describe('Stripe Adapter', () => { country: mockedCustomer.address?.country ?? '', postalCode: mockedCustomer.address?.postal_code ?? '', }, + metadata, }); expect(createdCustomer).toStrictEqual(Customer.toDomain(mockedCustomer));