ghostguild-org/HELCIM_PAYMENT_FIX.md

4.4 KiB

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)
// 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

# 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

# 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:

# 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