Payments Overview

The Batchmates payment system processes donations through PayMongo — the sole active payment gateway — covering hosted checkout flows, direct charges against vaulted cards, and gateway-managed recurring subscriptions.


Stack

LayerTechnology
BackendLaravel 12
FrontendReact 19 + TypeScript
DatabasePostgreSQL
Payment gatewayPayMongo

Payment Paths

PathWhen used
Hosted CheckoutOne-time donations (card, GCash, Maya wallet, GrabPay, QR Ph)
Charge saved cardOne-time with a vaulted card
Recurring subscriptionAutomatic repeat billing against a vaulted card

Key Backend Services

FileResponsibility
app/Services/PayMongoService.phpRaw HTTP calls to PayMongo API
app/Services/PayMongoTransactionService.phpPayMongo business logic — initiate, charge, vault, webhook handling
app/Services/FeeCalculator.phpGateway-agnostic fee computation

Checkout Flow (High Level)

  1. User selects a campaign and donation amount on /donate
  2. Frontend calls POST /api/v1/donations/quote to display the exact fee for the chosen method
  3. Frontend posts to POST /api/v1/donations with payment_gateway: 'paymongo' and payment_method
  4. Backend creates a pending Donation record and calls PayMongo's checkout API
  5. Backend returns { redirectUrl } — frontend redirects the browser to the hosted payment page
  6. User completes payment
  7. PayMongo redirects back and fires a webhook
  8. Webhook handler marks the donation completed and increments campaign balances

See Donation Flow for the full step-by-step sequence.


Saved Card Flow (High Level)

  1. Frontend tokenizes the card directly against PayMongo's API (/payment_methods) using the public key — card data never touches Batchmates servers — producing a pm_... id
  2. Frontend sends the pm_... id to POST /api/v1/payment-methods/paymongo/link-card
  3. Backend creates a PayMongo customer (or reuses existing) and runs a ₱25 card verification charge with setup_future_usage to vault the card (PayMongo has no zero-amount setup intent)
  4. User donates via POST /api/v1/donations/charge-saved/paymongo with the saved payment method ID and the card CVC (PayMongo requires CVC re-entry on every charge)
  5. If 3DS is required, an action_url is returned — user authenticates, then the intent-return redirect finalises the donation

See PayMongo Saved Cards for the full vaulting flow.


API Endpoint Reference

MethodPathAuthDescription
POST/api/v1/donations/quoteOptional (public)Server-authoritative fee preview — creates nothing
POST/api/v1/donationsSanctumCreate donation + initiate PayMongo checkout
POST/api/v1/donations/charge-saved/paymongoSanctumCharge a vaulted PayMongo card (requires CVC)
POST/api/v1/donations/{id}/pay/paymongoSanctumRetry a failed/expired PayMongo donation
POST/api/v1/payment-methods/paymongo/link-cardSanctumVault a PayMongo card (via pm_... id)
GET/api/v1/payment-methodsSanctumList user's saved cards
DELETE/api/v1/payment-methods/{id}SanctumRemove a saved card
POST/api/v1/payment-methods/{id}/set-defaultSanctumSet default card
GET/api/v1/payments/paymongo/successPublicPayMongo post-checkout success redirect
GET/api/v1/payments/paymongo/cancelPublicPayMongo post-checkout cancel redirect — verifies with the gateway before cancelling
GET/api/v1/payments/paymongo/intent-returnPublicPayMongo saved-card 3DS return
GET/api/v1/payments/paymongo/vault-returnPublicPayMongo card-vaulting 3DS return
POST/api/v1/payments/paymongo/webhookWebhook sigPayMongo event webhook

Further Reading

Was this page helpful?