3 Commits

Author SHA1 Message Date
4fde492e0f feat: add checkoutUrl field to payment collection
- 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 <noreply@anthropic.com>
2025-11-18 23:01:43 +01:00
a37757ffa1 fix: add better error handling for uninitialized billing plugin
- Fix TypeError when accessing providerConfig on undefined billing plugin
- Add proper type safety: useBillingPlugin now returns BillingPlugin | undefined
- Add clear error message when plugin hasn't been initialized
- Update README quickstart with concise provider response examples

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 22:31:51 +01:00
1867bb2f96 docs: restructure and update README for clarity
- Revise features list for precision and enhanced readability
- Expand and reorganize table of contents for better navigation
- Add detailed configurations and examples for Stripe, Mollie, and test providers
- Include new sections like customer management, payment flows, and webhook setup
- Refine descriptions of automatic behaviors and status synchronization
- Fix minor grammar inconsistencies and improve overall formatting

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 21:43:47 +01:00
8 changed files with 1084 additions and 311 deletions

1367
README.md

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "@xtr-dev/payload-billing",
"version": "0.1.14",
"version": "0.1.16",
"description": "PayloadCMS plugin for billing and payment provider integrations with tracking and local testing",
"license": "MIT",
"type": "module",

View File

@@ -4,6 +4,13 @@ import { useBillingPlugin } from '../plugin/index'
export const initProviderPayment = async (payload: Payload, payment: Partial<Payment>): Promise<Partial<Payment>> => {
const billing = useBillingPlugin(payload)
if (!billing) {
throw new Error(
'Billing plugin not initialized. Make sure the billingPlugin is properly configured in your Payload config and that Payload has finished initializing.'
)
}
if (!payment.provider || !billing.providerConfig[payment.provider]) {
throw new Error(`Provider ${payment.provider} not found.`)
}

View File

@@ -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',

View File

@@ -13,7 +13,7 @@ type BillingPlugin = {
}
}
export const useBillingPlugin = (payload: Payload) => singleton.get(payload) as BillingPlugin
export const useBillingPlugin = (payload: Payload) => singleton.get(payload) as BillingPlugin | undefined
export const billingPlugin = (pluginConfig: BillingPluginConfig = {}) => (config: Config): Config => {
if (pluginConfig.disabled) {

View File

@@ -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

View File

@@ -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

View File

@@ -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
},