mirror of
https://github.com/xtr-dev/payload-billing.git
synced 2025-12-10 10:53:23 +00:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6de405d07f | |||
| 7c0b42e35d | |||
| 25b340d818 | |||
| 46bec6bd2e | |||
| 4fde492e0f |
11
README.md
11
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<string, any> // 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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@xtr-dev/payload-billing",
|
||||
"version": "0.1.15",
|
||||
"version": "0.1.18",
|
||||
"description": "PayloadCMS plugin for billing and payment provider integrations with tracking and local testing",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
|
||||
@@ -7,7 +7,8 @@ export const initProviderPayment = async (payload: Payload, payment: Partial<Pay
|
||||
|
||||
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.'
|
||||
'Billing plugin not initialized. Make sure the billingPlugin is properly configured in your Payload config and that Payload has finished initializing. ' +
|
||||
'If you are calling this from a Next.js API route or Server Component, ensure you are using getPayload() with the same config instance used in your Payload configuration.'
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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',
|
||||
@@ -136,6 +144,18 @@ export function createPaymentsCollection(pluginConfig: BillingPluginConfig): Col
|
||||
useAsTitle: 'id',
|
||||
},
|
||||
fields,
|
||||
defaultPopulate: {
|
||||
id: true,
|
||||
provider: true,
|
||||
status: true,
|
||||
amount: true,
|
||||
currency: true,
|
||||
description: true,
|
||||
checkoutUrl: true,
|
||||
providerId: true,
|
||||
metadata: true,
|
||||
providerData: true,
|
||||
},
|
||||
hooks: {
|
||||
afterChange: [
|
||||
async ({ doc, operation, req, previousDoc }) => {
|
||||
|
||||
@@ -4,7 +4,7 @@ import type { Config, Payload } from 'payload'
|
||||
import { createSingleton } from './singleton'
|
||||
import type { PaymentProvider } from '../providers/index'
|
||||
|
||||
const singleton = createSingleton(Symbol('billingPlugin'))
|
||||
const singleton = createSingleton(Symbol.for('@xtr-dev/payload-billing'))
|
||||
|
||||
type BillingPlugin = {
|
||||
config: BillingPluginConfig
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
import { formatAmountForProvider, isValidAmount, isValidCurrencyCode } from './currency'
|
||||
import { createContextLogger } from '../utils/logger'
|
||||
|
||||
const symbol = Symbol('mollie')
|
||||
const symbol = Symbol.for('@xtr-dev/payload-billing/mollie')
|
||||
export type MollieProviderConfig = Parameters<typeof createMollieClient>[0]
|
||||
|
||||
/**
|
||||
@@ -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
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
import { isValidAmount, isValidCurrencyCode } from './currency'
|
||||
import { createContextLogger } from '../utils/logger'
|
||||
|
||||
const symbol = Symbol('stripe')
|
||||
const symbol = Symbol.for('@xtr-dev/payload-billing/stripe')
|
||||
|
||||
export interface StripeProviderConfig {
|
||||
secretKey: string
|
||||
|
||||
@@ -6,7 +6,7 @@ import { handleWebhookError, logWebhookEvent } from './utils'
|
||||
import { isValidAmount, isValidCurrencyCode } from './currency'
|
||||
import { createContextLogger } from '../utils/logger'
|
||||
|
||||
const TestModeWarningSymbol = Symbol('TestModeWarning')
|
||||
const TestModeWarningSymbol = Symbol.for('@xtr-dev/payload-billing/test-mode-warning')
|
||||
const hasGivenTestModeWarning = () => TestModeWarningSymbol in globalThis
|
||||
const setTestModeWarning = () => ((<any>globalThis)[TestModeWarningSymbol] = true)
|
||||
|
||||
@@ -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
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user