From 4fde492e0f210a1dbade8cff78da6493af9c3ffe Mon Sep 17 00:00:00 2001 From: Bas van den Aakster Date: Tue, 18 Nov 2025 23:01:43 +0100 Subject: [PATCH] feat: add checkoutUrl field to payment collection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add checkoutUrl field to Payment type and collection - Mollie provider now sets checkoutUrl from _links.checkout.href - Test provider sets checkoutUrl to interactive payment UI - Stripe provider doesn't use checkoutUrl (uses client_secret instead) - Update README with checkoutUrl examples and clarifications - Make it easier to redirect users to payment pages 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- README.md | 11 +++++++---- package.json | 2 +- src/collections/payments.ts | 8 ++++++++ src/plugin/types/payments.ts | 4 ++++ src/providers/mollie.ts | 1 + src/providers/test.ts | 4 +++- 6 files changed, 24 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 54fb0d8..ac3be6d 100644 --- a/README.md +++ b/README.md @@ -111,9 +111,9 @@ const payment = await payload.create({ **What you get back:** -- **Stripe**: `providerId` = PaymentIntent ID, `providerData.raw.client_secret` for Stripe.js -- **Mollie**: `providerId` = Transaction ID, `providerData.raw._links.checkout.href` for redirect URL -- **Test**: `providerId` = Test payment ID, `providerData.raw.paymentUrl` for interactive test UI +- **Stripe**: `providerId` = PaymentIntent ID, use `providerData.raw.client_secret` with Stripe.js on frontend +- **Mollie**: `providerId` = Transaction ID, redirect user to `checkoutUrl` to complete payment +- **Test**: `providerId` = Test payment ID, navigate to `checkoutUrl` for interactive test UI ## Payment Providers @@ -407,6 +407,7 @@ Tracks payment transactions with provider integration. amount: number // Amount in cents currency: string // ISO 4217 currency code description?: string + checkoutUrl?: string // Checkout URL (if applicable) invoice?: Invoice | string // Linked invoice metadata?: Record // Custom metadata providerData?: ProviderData // Raw provider response (read-only) @@ -639,12 +640,14 @@ const payment = await payload.create({ } }) -// Get client secret for Stripe.js +// Get client secret for Stripe.js (Stripe doesn't use checkoutUrl) const clientSecret = payment.providerData.raw.client_secret // Frontend: Confirm payment with Stripe.js // const stripe = Stripe('pk_...') // await stripe.confirmCardPayment(clientSecret, { ... }) + +// For Mollie/Test: redirect to payment.checkoutUrl instead ``` ### Creating an Invoice with Line Items diff --git a/package.json b/package.json index 223c3bf..67c162a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@xtr-dev/payload-billing", - "version": "0.1.15", + "version": "0.1.16", "description": "PayloadCMS plugin for billing and payment provider integrations with tracking and local testing", "license": "MIT", "type": "module", diff --git a/src/collections/payments.ts b/src/collections/payments.ts index 942c005..103e9c7 100644 --- a/src/collections/payments.ts +++ b/src/collections/payments.ts @@ -78,6 +78,14 @@ export function createPaymentsCollection(pluginConfig: BillingPluginConfig): Col description: 'Payment description', }, }, + { + name: 'checkoutUrl', + type: 'text', + admin: { + description: 'Checkout URL where user can complete payment (if applicable)', + readOnly: true, + }, + }, { name: 'invoice', type: 'relationship', diff --git a/src/plugin/types/payments.ts b/src/plugin/types/payments.ts index 0164514..ada717f 100644 --- a/src/plugin/types/payments.ts +++ b/src/plugin/types/payments.ts @@ -22,6 +22,10 @@ export interface Payment { * Payment description */ description?: string | null; + /** + * Checkout URL where user can complete payment (if applicable) + */ + checkoutUrl?: string | null; invoice?: (Id | null) | Invoice; /** * Additional metadata for the payment diff --git a/src/providers/mollie.ts b/src/providers/mollie.ts index c2ab492..23ecc80 100644 --- a/src/providers/mollie.ts +++ b/src/providers/mollie.ts @@ -155,6 +155,7 @@ export const mollieProvider = (mollieConfig: MollieProviderConfig & { }); payment.providerId = molliePayment.id payment.providerData = molliePayment.toPlainObject() + payment.checkoutUrl = molliePayment._links?.checkout?.href || null return payment }, } satisfies PaymentProvider diff --git a/src/providers/test.ts b/src/providers/test.ts index cc44525..bb5105b 100644 --- a/src/providers/test.ts +++ b/src/providers/test.ts @@ -492,6 +492,7 @@ export const testProvider = (testConfig: TestProviderConfig) => { // Set provider ID and data payment.providerId = testPaymentId + const paymentUrl = `${baseUrl}/api/payload-billing/test/payment/${testPaymentId}` const providerData: ProviderData = { raw: { id: testPaymentId, @@ -500,7 +501,7 @@ export const testProvider = (testConfig: TestProviderConfig) => { description: payment.description, status: 'pending', testMode: true, - paymentUrl: `${baseUrl}/api/payload-billing/test/payment/${testPaymentId}`, + paymentUrl, scenarios: scenarios.map(s => ({ id: s.id, name: s.name, description: s.description })), methods: Object.entries(PAYMENT_METHODS).map(([key, value]) => ({ id: key, @@ -512,6 +513,7 @@ export const testProvider = (testConfig: TestProviderConfig) => { provider: 'test' } payment.providerData = providerData + payment.checkoutUrl = paymentUrl return payment },