Created
October 1, 2025 09:37
-
-
Save mmikhan/9ae8ee511b309a3c1615e4830bb4961c to your computer and use it in GitHub Desktop.
Payload CMS form builder plugin configuration
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| export default formBuilderPlugin({ | |
| fields: { | |
| payment: true, | |
| }, | |
| handlePayment: async ({ data, req }) => { | |
| console.log('Payment handler called with hook data:', { | |
| formId: data?.form, | |
| submissionData: data?.submissionData, | |
| payment: data?.payment, | |
| }) | |
| const formId = data.form | |
| const submissionData = data.submissionData || [] | |
| // Ensure the form ID is valid | |
| if (!formId) { | |
| throw new Error('No form ID provided in submission data') | |
| } | |
| // Get the form document to access price conditions | |
| const formDoc = await req.payload.findByID({ | |
| collection: 'forms', | |
| id: formId, | |
| }) | |
| // console.log('Form document:', formDoc) | |
| // Define a type for submission data items | |
| type SubmissionDataItem = { | |
| field: string | |
| value: string | number | boolean | null | undefined | |
| // Add other properties if needed | |
| } | |
| // Extract field values from submission data | |
| const fieldValues: Record<string, string | number | boolean | null | undefined> = {} | |
| submissionData.forEach((item: SubmissionDataItem) => { | |
| if (item.field && item.value !== undefined) { | |
| fieldValues[item.field] = item.value | |
| } | |
| }) | |
| // Find the payment field to get basePrice and priceConditions | |
| const paymentField = formDoc.fields.find((field: any) => field.blockType === 'payment') | |
| // console.log('Payment field:', paymentField) | |
| if (!paymentField) { | |
| throw new Error('No payment field found in form') | |
| } | |
| // Calculate the total payment amount using the built-in function | |
| const price = getPaymentTotal({ | |
| basePrice: paymentField.basePrice || 0, | |
| priceConditions: paymentField.priceConditions || [], | |
| fieldValues, | |
| }) | |
| // console.log('Calculated payment amount:', price) | |
| if (price <= 0) { | |
| throw new Error(`Payment amount must be greater than 0. Calculated: ${price}`) | |
| } | |
| try { | |
| // Create a payment intent with Stripe | |
| const paymentIntent = await stripe.paymentIntents.create({ | |
| amount: Math.round(price * 100), // Convert to cents | |
| currency: 'usd', | |
| automatic_payment_methods: { | |
| enabled: true, | |
| }, | |
| metadata: { | |
| formId: formId?.toString() || 'unknown', | |
| formTitle: formDoc?.title || 'Form Submission', | |
| calculatedAmount: price.toString(), | |
| }, | |
| description: `Payment for ${formDoc?.title || 'Form Submission'} - Amount: $${price}`, | |
| }) | |
| console.log('Payment intent created successfully:', { | |
| id: paymentIntent.id, | |
| amount: price, | |
| currency: 'usd', | |
| }) | |
| // Update the payment data in the submission | |
| data.payment = { | |
| ...data.payment, | |
| status: 'succeeded', | |
| amount: price, | |
| paymentProcessor: 'stripe', | |
| transactionId: paymentIntent.id, | |
| } | |
| // Return the payment result | |
| return { | |
| paid: true, | |
| amount: price, | |
| transactionId: paymentIntent.id, | |
| } | |
| } catch (error) { | |
| console.error('Payment processing failed:', error) | |
| // Update payment status to failed | |
| data.payment = { | |
| ...data.payment, | |
| status: 'failed', | |
| amount: price, | |
| paymentProcessor: 'stripe', | |
| } | |
| throw new Error(`Payment failed: ${error instanceof Error ? error.message : 'Unknown error'}`) | |
| } | |
| } | |
| }) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment