DocHub
Payment methods, processing flows, service fees, and refunds

Payments System

Ricoya supports three payment methods: card (CyberSource), PayPal, and cash on delivery.

Payment Methods

Method Provider Flow Service Fee
Card CyberSource 3DS authentication + tokenization 2.5% of subtotal + delivery
PayPal PayPal OAuth redirect → capture 2.5% of subtotal + delivery
Cash Manual Driver collects at door 0%

Service fee percentages are configurable via the config table keys: payment-fee-card, payment-fee-paypal, payment-fee-cash.

Order Total Calculation

total = subtotal + tax + delivery_fee + service_fee + tip - discount
  • subtotal: Sum of (item price × quantity) for all order items
  • tax: Calculated per item from category tax mappings or direct tax_id
  • delivery_fee: Distance-based ($3 base + $0.50/km beyond 1km, converted to HNL)
  • service_fee: Percentage of (subtotal + delivery_fee), varies by payment method
  • tip: User-selected (preset 10/15/20% or custom amount)
  • discount: From discount code if applied

Server recalculates total before processing payment. If client total differs by more than 50 cents, payment is rejected (AmountMismatchError).

CyberSource Card Payment (3DS Flow)

Four-step process:

Step 1: Setup — POST /api/payments/setup

  • Detects card type from BIN (Visa, Mastercard, AMEX)
  • Calls CyberSource /risk/v1/authentication-setups
  • Returns accessToken for device data collection (DDC)

Step 2: Device Data Collection (client-side)

  • Hidden iframe posts JWT to CyberSource DDC URL
  • Waits for profile.completed message (10s timeout)
  • Collects device fingerprint for fraud detection

Step 3: Payment — POST /api/payments

  • Sends card details + device info + 3DS reference
  • CyberSource processes with TOKEN_CREATE + CONSUMER_AUTHENTICATION
  • If 3DS challenge required: returns stepUpUrl for bank redirect
  • If no challenge: returns AUTHORIZED with payment ID

Step 4: Verification — POST /api/payments/verify

  • Called after bank 3DS redirect
  • Validates authentication with VALIDATE_CONSUMER_AUTHENTICATION
  • Completes payment, returns final status

Card tokenization creates a saved_cards entry for future 1-click payments.

PayPal Flow

Create — POST /api/payments/paypal/create

  • Converts HNL to USD using exchange rate from config
  • Creates PayPal order with intent: CAPTURE
  • Returns approvalUrl — user redirected to PayPal

Capture — POST /api/payments/paypal/capture

  • Called after user approves on PayPal
  • Captures payment, extracts capture ID
  • Updates order: payment_status: "paid", status: "placed"
  • Sends push notification to restaurant staff

Cancel — POST /api/payments/paypal/cancel

  • Marks order payment_status: "failed" locally
  • No PayPal API call needed

Cash on Delivery

  1. Customer selects cash, enters expected amount (cash_payment_amount_cents)
  2. Order created with payment_status: "pending", payment_method: "cash"
  3. Driver collects cash on delivery
  4. Staff marks payment_status: "cash_completed" via admin panel

Refunds — POST /api/payments/refund

Tries reversal first (faster, full amount), falls back to refund (partial OK):

  1. Reversal: POST /pts/v2/payments/{id}/reversals — cancels original transaction
  2. Refund: POST /pts/v2/payments/{id}/refunds — returns funds (partial or full)

Payment Status Flow

(new) → pending → authorized → paid → refunded
                              ↗
         pending → paid ------
                              ↘
         pending → cash_completed

         pending/authorized → failed

Key Files

File Purpose
src/app/api/payments/route.ts CyberSource card payment
src/app/api/payments/setup/route.ts 3DS setup
src/app/api/payments/verify/route.ts Post-3DS verification
src/app/api/payments/refund/route.ts Refund/reversal
src/app/api/payments/paypal/create/route.ts Create PayPal order
src/app/api/payments/paypal/capture/route.ts Capture PayPal payment
src/app/api/payments/paypal/cancel/route.ts Cancel PayPal order
src/app/api/saved-cards/route.ts Saved card CRUD
src/app/api/orders/[orderId]/payment-status/route.ts Update payment status
src/lib/cybersource.ts CyberSource signature builder
src/lib/orderTotalCalculator.ts Server-side total recalculation
src/services/paymentApi.ts Client-side payment API wrapper
src/services/paypalApi.ts Client-side PayPal API wrapper

Environment Variables

Variable Purpose
CYBERSOURCE_MERCHANT_ID CyberSource account ID
CYBERSOURCE_KEY_ID API key ID
CYBERSOURCE_SECRET_KEY Base64-encoded signing key
CYBERSOURCE_API_BASE_URL API endpoint (prod vs test)
CYBERSOURCE_3DS_REQUESTOR_ID 3DS processing ID
PAYPAL_CLIENT_ID PayPal OAuth client
PAYPAL_CLIENT_SECRET PayPal OAuth secret
PAYPAL_API_BASE_URL PayPal endpoint