mirror of
https://github.com/xtr-dev/payload-billing.git
synced 2025-12-10 19:03:23 +00:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f2ab50214b | |||
| 20030b435c |
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@xtr-dev/payload-billing",
|
||||
"version": "0.1.26",
|
||||
"version": "0.1.28",
|
||||
"description": "PayloadCMS plugin for billing and payment provider integrations with tracking and local testing",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
|
||||
@@ -17,13 +17,6 @@ import { createContextLogger } from '../utils/logger'
|
||||
const symbol = Symbol.for('@xtr-dev/payload-billing/mollie')
|
||||
export type MollieProviderConfig = Parameters<typeof createMollieClient>[0]
|
||||
|
||||
/**
|
||||
* Determine if testmode should be enabled based on API key prefix
|
||||
*/
|
||||
function isTestMode(apiKey: string): boolean {
|
||||
return apiKey.startsWith('test_')
|
||||
}
|
||||
|
||||
/**
|
||||
* Type-safe mapping of Mollie payment status to internal status
|
||||
*/
|
||||
@@ -168,9 +161,6 @@ export const mollieProvider = (mollieConfig: MollieProviderConfig & {
|
||||
validateProductionUrl(redirectUrl, 'Redirect')
|
||||
validateProductionUrl(webhookUrl, 'Webhook')
|
||||
|
||||
// Determine testmode from API key (test_ prefix = true)
|
||||
const testmode = isTestMode(mollieConfig.apiKey)
|
||||
|
||||
const molliePayment = await singleton.get(payload).payments.create({
|
||||
amount: {
|
||||
value: formatAmountForProvider(payment.amount, payment.currency),
|
||||
@@ -179,8 +169,7 @@ export const mollieProvider = (mollieConfig: MollieProviderConfig & {
|
||||
description: payment.description || '',
|
||||
redirectUrl,
|
||||
webhookUrl,
|
||||
testmode,
|
||||
} as any);
|
||||
});
|
||||
payment.providerId = molliePayment.id
|
||||
// Use toPlainObject if available, otherwise spread the object (for compatibility with different Mollie client versions)
|
||||
payment.providerData = typeof molliePayment.toPlainObject === 'function'
|
||||
|
||||
@@ -60,6 +60,7 @@ export async function updatePaymentStatus(
|
||||
pluginConfig: BillingPluginConfig
|
||||
): Promise<boolean> {
|
||||
const paymentsCollection = extractSlug(pluginConfig.collections?.payments, defaults.paymentsCollection)
|
||||
const logger = createContextLogger(payload, 'Payment Update')
|
||||
|
||||
try {
|
||||
// First, fetch the current payment to get the current version
|
||||
@@ -69,23 +70,23 @@ export async function updatePaymentStatus(
|
||||
}) as Payment
|
||||
|
||||
if (!currentPayment) {
|
||||
const logger = createContextLogger(payload, 'Payment Update')
|
||||
logger.error(`Payment ${paymentId} not found`)
|
||||
return false
|
||||
}
|
||||
|
||||
const currentVersion = currentPayment.version || 1
|
||||
|
||||
// Attempt to update with optimistic locking
|
||||
// We'll use a transaction to ensure atomicity
|
||||
const transactionID = await payload.db.beginTransaction()
|
||||
|
||||
if (!transactionID) {
|
||||
const logger = createContextLogger(payload, 'Payment Update')
|
||||
logger.error('Failed to begin transaction')
|
||||
return false
|
||||
// Try to use transactions if supported by the database adapter
|
||||
let transactionID: string | number | null = null
|
||||
try {
|
||||
transactionID = await payload.db.beginTransaction()
|
||||
} catch (error) {
|
||||
// Transaction support may not be available in all database adapters
|
||||
logger.debug('Transactions not supported, falling back to direct update')
|
||||
}
|
||||
|
||||
if (transactionID) {
|
||||
// Use transactional update with optimistic locking
|
||||
try {
|
||||
// Re-fetch within transaction to ensure consistency
|
||||
const paymentInTransaction = await payload.findByID({
|
||||
@@ -97,7 +98,6 @@ export async function updatePaymentStatus(
|
||||
// Check if version still matches
|
||||
if ((paymentInTransaction.version || 1) !== currentVersion) {
|
||||
// Version conflict detected - payment was modified by another process
|
||||
const logger = createContextLogger(payload, 'Payment Update')
|
||||
logger.warn(`Version conflict for payment ${paymentId} (expected version: ${currentVersion}, got: ${paymentInTransaction.version})`)
|
||||
await payload.db.rollbackTransaction(transactionID)
|
||||
return false
|
||||
@@ -124,8 +124,27 @@ export async function updatePaymentStatus(
|
||||
await payload.db.rollbackTransaction(transactionID)
|
||||
throw error
|
||||
}
|
||||
} else {
|
||||
// Fallback: Direct update without transaction support
|
||||
// This is less safe but allows payment updates on databases without transaction support
|
||||
logger.debug('Using direct update without transaction')
|
||||
|
||||
await payload.update({
|
||||
collection: paymentsCollection,
|
||||
id: toPayloadId(paymentId),
|
||||
data: {
|
||||
status,
|
||||
providerData: {
|
||||
...providerData,
|
||||
webhookProcessedAt: new Date().toISOString()
|
||||
},
|
||||
version: currentVersion + 1
|
||||
}
|
||||
})
|
||||
|
||||
return true
|
||||
}
|
||||
} catch (error) {
|
||||
const logger = createContextLogger(payload, 'Payment Update')
|
||||
const errorMessage = error instanceof Error ? error.message : String(error)
|
||||
const errorStack = error instanceof Error ? error.stack : undefined
|
||||
logger.error(`Failed to update payment ${paymentId}: ${errorMessage}`)
|
||||
|
||||
Reference in New Issue
Block a user