mirror of
https://github.com/xtr-dev/payload-billing.git
synced 2025-12-10 10:53:23 +00:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1eb9d282b3 | |||
| 291ce255b4 | |||
| 2904d30a5c | |||
| bf6f546371 |
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@xtr-dev/payload-billing",
|
"name": "@xtr-dev/payload-billing",
|
||||||
"version": "0.1.22",
|
"version": "0.1.26",
|
||||||
"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",
|
||||||
|
|||||||
@@ -17,6 +17,13 @@ import { createContextLogger } from '../utils/logger'
|
|||||||
const symbol = Symbol.for('@xtr-dev/payload-billing/mollie')
|
const symbol = Symbol.for('@xtr-dev/payload-billing/mollie')
|
||||||
export type MollieProviderConfig = Parameters<typeof createMollieClient>[0]
|
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
|
* Type-safe mapping of Mollie payment status to internal status
|
||||||
*/
|
*/
|
||||||
@@ -85,11 +92,15 @@ export const mollieProvider = (mollieConfig: MollieProviderConfig & {
|
|||||||
const status = mapMollieStatusToPaymentStatus(molliePayment.status)
|
const status = mapMollieStatusToPaymentStatus(molliePayment.status)
|
||||||
|
|
||||||
// Update the payment status and provider data
|
// Update the payment status and provider data
|
||||||
|
// Use toPlainObject if available, otherwise spread the object
|
||||||
|
const providerData = typeof molliePayment.toPlainObject === 'function'
|
||||||
|
? molliePayment.toPlainObject()
|
||||||
|
: { ...molliePayment }
|
||||||
const updateSuccess = await updatePaymentStatus(
|
const updateSuccess = await updatePaymentStatus(
|
||||||
payload,
|
payload,
|
||||||
payment.id,
|
payment.id,
|
||||||
status,
|
status,
|
||||||
molliePayment.toPlainObject(),
|
providerData,
|
||||||
pluginConfig
|
pluginConfig
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -157,6 +168,9 @@ export const mollieProvider = (mollieConfig: MollieProviderConfig & {
|
|||||||
validateProductionUrl(redirectUrl, 'Redirect')
|
validateProductionUrl(redirectUrl, 'Redirect')
|
||||||
validateProductionUrl(webhookUrl, 'Webhook')
|
validateProductionUrl(webhookUrl, 'Webhook')
|
||||||
|
|
||||||
|
// Determine testmode from API key (test_ prefix = true)
|
||||||
|
const testmode = isTestMode(mollieConfig.apiKey)
|
||||||
|
|
||||||
const molliePayment = await singleton.get(payload).payments.create({
|
const molliePayment = await singleton.get(payload).payments.create({
|
||||||
amount: {
|
amount: {
|
||||||
value: formatAmountForProvider(payment.amount, payment.currency),
|
value: formatAmountForProvider(payment.amount, payment.currency),
|
||||||
@@ -165,9 +179,13 @@ export const mollieProvider = (mollieConfig: MollieProviderConfig & {
|
|||||||
description: payment.description || '',
|
description: payment.description || '',
|
||||||
redirectUrl,
|
redirectUrl,
|
||||||
webhookUrl,
|
webhookUrl,
|
||||||
});
|
testmode,
|
||||||
|
} as any);
|
||||||
payment.providerId = molliePayment.id
|
payment.providerId = molliePayment.id
|
||||||
payment.providerData = molliePayment.toPlainObject()
|
// Use toPlainObject if available, otherwise spread the object (for compatibility with different Mollie client versions)
|
||||||
|
payment.providerData = typeof molliePayment.toPlainObject === 'function'
|
||||||
|
? molliePayment.toPlainObject()
|
||||||
|
: { ...molliePayment }
|
||||||
payment.checkoutUrl = molliePayment._links?.checkout?.href || null
|
payment.checkoutUrl = molliePayment._links?.checkout?.href || null
|
||||||
return payment
|
return payment
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -424,7 +424,8 @@ export const testProvider = (testConfig: TestProviderConfig) => {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
processTestPayment(payload, session, pluginConfig).catch(async (error) => {
|
processTestPayment(payload, session, pluginConfig).catch(async (error) => {
|
||||||
const logger = createContextLogger(payload, 'Test Provider')
|
const logger = createContextLogger(payload, 'Test Provider')
|
||||||
logger.error('Failed to process payment:', error)
|
const errorMessage = error instanceof Error ? error.message : String(error)
|
||||||
|
logger.error(`Failed to process payment: ${errorMessage}`)
|
||||||
|
|
||||||
// Ensure session status is updated consistently
|
// Ensure session status is updated consistently
|
||||||
session.status = 'failed'
|
session.status = 'failed'
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export const webhookResponses = {
|
|||||||
// Log error internally but don't expose details
|
// Log error internally but don't expose details
|
||||||
if (payload) {
|
if (payload) {
|
||||||
const logger = createContextLogger(payload, 'Webhook')
|
const logger = createContextLogger(payload, 'Webhook')
|
||||||
logger.error('Error:', message)
|
logger.error(`Error: ${message}`)
|
||||||
} else {
|
} else {
|
||||||
console.error('[Webhook] Error:', message)
|
console.error('[Webhook] Error:', message)
|
||||||
}
|
}
|
||||||
@@ -126,7 +126,12 @@ export async function updatePaymentStatus(
|
|||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const logger = createContextLogger(payload, 'Payment Update')
|
const logger = createContextLogger(payload, 'Payment Update')
|
||||||
logger.error(`Failed to update payment ${paymentId}:`, error)
|
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}`)
|
||||||
|
if (errorStack) {
|
||||||
|
logger.error(`Stack trace: ${errorStack}`)
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -165,15 +170,22 @@ export function handleWebhookError(
|
|||||||
context?: string,
|
context?: string,
|
||||||
payload?: Payload
|
payload?: Payload
|
||||||
): Response {
|
): Response {
|
||||||
const message = error instanceof Error ? error.message : 'Unknown error'
|
const message = error instanceof Error ? error.message : String(error)
|
||||||
|
const stack = error instanceof Error ? error.stack : undefined
|
||||||
const fullContext = context ? `${provider} Webhook - ${context}` : `${provider} Webhook`
|
const fullContext = context ? `${provider} Webhook - ${context}` : `${provider} Webhook`
|
||||||
|
|
||||||
// Log detailed error internally for debugging
|
// Log detailed error internally for debugging
|
||||||
if (payload) {
|
if (payload) {
|
||||||
const logger = createContextLogger(payload, fullContext)
|
const logger = createContextLogger(payload, fullContext)
|
||||||
logger.error('Error:', error)
|
logger.error(`Error: ${message}`)
|
||||||
|
if (stack) {
|
||||||
|
logger.error(`Stack trace: ${stack}`)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
console.error(`[${fullContext}] Error:`, error)
|
console.error(`[${fullContext}] Error: ${message}`)
|
||||||
|
if (stack) {
|
||||||
|
console.error(`[${fullContext}] Stack trace:`, stack)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return generic response to avoid information disclosure
|
// Return generic response to avoid information disclosure
|
||||||
|
|||||||
Reference in New Issue
Block a user