# Helcim Payment Flow Fix ## Issue The initial implementation had a mismatch in the payment flow: - **Error**: "Customer ID is required" when attempting to purchase event tickets - **Cause**: The payment initialization endpoint required a `customerId`, but event tickets are one-time purchases that don't need customer accounts ## Solution ### 1. Updated Payment Initialization (`server/api/helcim/initialize-payment.post.js`) **Changed from:** - Always requiring `customerId` - Always using `verify` payment type (for card verification) - Amount fixed at 0 **Changed to:** - `customerId` is now optional - Detects event ticket purchases via `metadata.type === 'event_ticket'` - Uses `purchase` type for event tickets with amount > 0 - Uses `verify` type for subscription setup (card verification) ```javascript // For event tickets: HelcimPay.js completes the purchase immediately const paymentType = isEventTicket && amount > 0 ? 'purchase' : 'verify' ``` ### 2. Updated Ticket Purchase Endpoint (`server/api/events/[id]/tickets/purchase.post.js`) **Changed from:** - Expecting `paymentToken` from client - Calling `processHelcimPayment()` to process the payment - Payment happens server-side after modal closes **Changed to:** - Expecting `transactionId` from client - Payment already completed by HelcimPay.js modal - Server just records the transaction **Why?** When using HelcimPay.js with `purchase` type, the payment is processed inside the modal and we get a completed transaction back. We don't need to make a second API call to charge the card. ### 3. Updated Frontend Component (`app/components/EventTicketPurchase.vue`) **Changed from:** - Getting `cardToken` from payment modal - Sending `paymentToken` to purchase endpoint **Changed to:** - Getting `transactionId` from payment modal - Sending `transactionId` to purchase endpoint - Added validation to ensure transaction ID exists ## Payment Flow Comparison ### Old Flow (Subscriptions) ``` 1. Initialize payment session (verify mode, amount: 0) 2. User enters card in modal 3. Modal returns cardToken 4. Send cardToken to server 5. Server calls Helcim API to charge card 6. Create registration ``` ### New Flow (Event Tickets) ``` 1. Initialize payment session (purchase mode, amount: actual price) 2. User enters card in modal 3. Helcim charges card immediately 4. Modal returns transactionId 5. Send transactionId to server 6. Server records transaction and creates registration ``` ## Benefits 1. **Simpler**: One API call instead of two 2. **Faster**: Payment completes in the modal 3. **More Secure**: No need to handle card tokens server-side 4. **PCI Compliant**: Card data never touches our server 5. **Better UX**: User sees immediate payment confirmation ## Testing ### Free Member Tickets ```bash # Should work without payment modal 1. Member logs in 2. Views event with member.isFree: true 3. Fills name/email 4. Clicks "Complete Registration" 5. ✓ Registers immediately (no payment) ``` ### Paid Public Tickets ```bash # Should trigger Helcim modal 1. Non-member views event 2. Sees public ticket price 3. Fills name/email 4. Clicks "Pay $XX.XX" 5. Helcim modal opens 6. Enters test card: 4242 4242 4242 4242 7. Payment processes 8. ✓ Modal closes with success 9. ✓ Registration created with transaction ID ``` ## Environment Variables Ensure these are set in `.env`: ```bash # Public (client-side) NUXT_PUBLIC_HELCIM_TOKEN=your_helcim_api_token NUXT_PUBLIC_HELCIM_ACCOUNT_ID=your_account_id # Private (server-side) HELCIM_API_TOKEN=your_helcim_api_token ``` ## Common Issues ### "Customer ID is required" - ✅ **Fixed** - This error should no longer occur for event tickets - If you still see it, check that `metadata.type: 'event_ticket'` is being passed ### "No transaction ID received" - Check browser console for HelcimPay.js errors - Verify Helcim credentials are correct - Ensure test mode is enabled for testing ### Payment modal doesn't open - Check that HelcimPay.js script loaded (see console) - Verify `NUXT_PUBLIC_HELCIM_TOKEN` is set - Check browser console for initialization errors ## Files Changed 1. `server/api/helcim/initialize-payment.post.js` - Smart payment type detection 2. `server/api/events/[id]/tickets/purchase.post.js` - Accept transactionId instead of token 3. `app/components/EventTicketPurchase.vue` - Pass transactionId instead of cardToken --- **Status**: ✅ Fixed **Date**: 2025-10-14 **Impact**: Event ticket purchases now work correctly with Helcim