mirror of
https://github.com/xtr-dev/payload-billing.git
synced 2025-12-10 19:03:23 +00:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f2ab50214b | |||
| 20030b435c | |||
| 1eb9d282b3 | |||
| 291ce255b4 |
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@xtr-dev/payload-billing",
|
"name": "@xtr-dev/payload-billing",
|
||||||
"version": "0.1.24",
|
"version": "0.1.28",
|
||||||
"description": "PayloadCMS plugin for billing and payment provider integrations with tracking and local testing",
|
"description": "PayloadCMS plugin for billing and payment provider integrations with tracking and local testing",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ export async function updatePaymentStatus(
|
|||||||
pluginConfig: BillingPluginConfig
|
pluginConfig: BillingPluginConfig
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
const paymentsCollection = extractSlug(pluginConfig.collections?.payments, defaults.paymentsCollection)
|
const paymentsCollection = extractSlug(pluginConfig.collections?.payments, defaults.paymentsCollection)
|
||||||
|
const logger = createContextLogger(payload, 'Payment Update')
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// First, fetch the current payment to get the current version
|
// First, fetch the current payment to get the current version
|
||||||
@@ -69,41 +70,65 @@ export async function updatePaymentStatus(
|
|||||||
}) as Payment
|
}) as Payment
|
||||||
|
|
||||||
if (!currentPayment) {
|
if (!currentPayment) {
|
||||||
const logger = createContextLogger(payload, 'Payment Update')
|
|
||||||
logger.error(`Payment ${paymentId} not found`)
|
logger.error(`Payment ${paymentId} not found`)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentVersion = currentPayment.version || 1
|
const currentVersion = currentPayment.version || 1
|
||||||
|
|
||||||
// Attempt to update with optimistic locking
|
// Try to use transactions if supported by the database adapter
|
||||||
// We'll use a transaction to ensure atomicity
|
let transactionID: string | number | null = null
|
||||||
const transactionID = await payload.db.beginTransaction()
|
try {
|
||||||
|
transactionID = await payload.db.beginTransaction()
|
||||||
if (!transactionID) {
|
} catch (error) {
|
||||||
const logger = createContextLogger(payload, 'Payment Update')
|
// Transaction support may not be available in all database adapters
|
||||||
logger.error('Failed to begin transaction')
|
logger.debug('Transactions not supported, falling back to direct update')
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
if (transactionID) {
|
||||||
// Re-fetch within transaction to ensure consistency
|
// Use transactional update with optimistic locking
|
||||||
const paymentInTransaction = await payload.findByID({
|
try {
|
||||||
collection: paymentsCollection,
|
// Re-fetch within transaction to ensure consistency
|
||||||
id: toPayloadId(paymentId),
|
const paymentInTransaction = await payload.findByID({
|
||||||
req: { transactionID }
|
collection: paymentsCollection,
|
||||||
}) as Payment
|
id: toPayloadId(paymentId),
|
||||||
|
req: { transactionID }
|
||||||
|
}) as Payment
|
||||||
|
|
||||||
// Check if version still matches
|
// Check if version still matches
|
||||||
if ((paymentInTransaction.version || 1) !== currentVersion) {
|
if ((paymentInTransaction.version || 1) !== currentVersion) {
|
||||||
// Version conflict detected - payment was modified by another process
|
// 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})`)
|
||||||
logger.warn(`Version conflict for payment ${paymentId} (expected version: ${currentVersion}, got: ${paymentInTransaction.version})`)
|
await payload.db.rollbackTransaction(transactionID)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update with new version
|
||||||
|
await payload.update({
|
||||||
|
collection: paymentsCollection,
|
||||||
|
id: toPayloadId(paymentId),
|
||||||
|
data: {
|
||||||
|
status,
|
||||||
|
providerData: {
|
||||||
|
...providerData,
|
||||||
|
webhookProcessedAt: new Date().toISOString()
|
||||||
|
},
|
||||||
|
version: currentVersion + 1
|
||||||
|
},
|
||||||
|
req: { transactionID }
|
||||||
|
})
|
||||||
|
|
||||||
|
await payload.db.commitTransaction(transactionID)
|
||||||
|
return true
|
||||||
|
} catch (error) {
|
||||||
await payload.db.rollbackTransaction(transactionID)
|
await payload.db.rollbackTransaction(transactionID)
|
||||||
return false
|
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')
|
||||||
|
|
||||||
// Update with new version
|
|
||||||
await payload.update({
|
await payload.update({
|
||||||
collection: paymentsCollection,
|
collection: paymentsCollection,
|
||||||
id: toPayloadId(paymentId),
|
id: toPayloadId(paymentId),
|
||||||
@@ -114,18 +139,12 @@ export async function updatePaymentStatus(
|
|||||||
webhookProcessedAt: new Date().toISOString()
|
webhookProcessedAt: new Date().toISOString()
|
||||||
},
|
},
|
||||||
version: currentVersion + 1
|
version: currentVersion + 1
|
||||||
},
|
}
|
||||||
req: { transactionID }
|
|
||||||
})
|
})
|
||||||
|
|
||||||
await payload.db.commitTransaction(transactionID)
|
|
||||||
return true
|
return true
|
||||||
} catch (error) {
|
|
||||||
await payload.db.rollbackTransaction(transactionID)
|
|
||||||
throw error
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const logger = createContextLogger(payload, 'Payment Update')
|
|
||||||
const errorMessage = error instanceof Error ? error.message : String(error)
|
const errorMessage = error instanceof Error ? error.message : String(error)
|
||||||
const errorStack = error instanceof Error ? error.stack : undefined
|
const errorStack = error instanceof Error ? error.stack : undefined
|
||||||
logger.error(`Failed to update payment ${paymentId}: ${errorMessage}`)
|
logger.error(`Failed to update payment ${paymentId}: ${errorMessage}`)
|
||||||
|
|||||||
Reference in New Issue
Block a user