Payments Overview

The Batchmates payment system processes donations through Maya — the primary gateway — with PayMongo support alongside it, covering hosted checkout flows as well as direct charges against vaulted cards.


Stack

LayerTechnology
BackendLaravel 12
FrontendReact 19 + TypeScript
DatabasePostgreSQL
Payment gatewaysMaya (PayMaya), PayMongo

Two Payment Paths

PathWhen usedGateways
Hosted CheckoutOne-time donations (GCash, Maya wallet, card)Maya, PayMongo
Charge saved cardOne-time with a vaulted cardMaya, PayMongo

Key Backend Services

FileResponsibility
app/Services/MayaService.phpRaw HTTP calls to Maya API
app/Services/MayaTransactionService.phpMaya business logic — initiate, charge, webhook handling
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 posts to POST /api/v1/donations with payment_gateway: 'maya' (or 'paymongo')
  3. Backend creates a pending Donation record and calls the selected gateway's checkout API
  4. Backend returns { redirectUrl } — frontend redirects the browser to the hosted payment page
  5. User completes payment
  6. Gateway redirects back and fires a webhook
  7. 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)

Maya

  1. Frontend tokenizes the card directly against Maya's API (/payments/v1/payment-tokens) using the public key — card data never touches Batchmates servers
  2. Frontend sends the resulting paymentTokenId to POST /api/v1/payment-methods/maya/link-card
  3. Backend creates a Maya customer (or reuses existing) and vaults the card token
  4. User donates via POST /api/v1/donations/charge-saved/maya with the saved payment method ID
  5. If 3DS is required, an action_url is returned — user completes authentication, then the success redirect finalises the donation

PayMongo

  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 Maya Saved Cards for Maya vaulting, and PayMongo Saved Cards for PayMongo.


API Endpoint Reference

MethodPathAuthDescription
POST/api/v1/donationsSanctumCreate donation + initiate Maya or PayMongo checkout
POST/api/v1/donations/charge-saved/mayaSanctumCharge a vaulted Maya card
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/maya/link-cardSanctumVault a Maya payment token
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/maya/successPublicMaya post-checkout / post-3DS success redirect
GET/api/v1/payments/maya/failurePublicMaya post-checkout failure redirect
GET/api/v1/payments/maya/cancelPublicMaya post-checkout cancel redirect
POST/api/v1/payments/maya/webhookIP allowlistMaya event webhook
GET/api/v1/payments/paymongo/successPublicPayMongo post-checkout success redirect
GET/api/v1/payments/paymongo/cancelPublicPayMongo post-checkout cancel redirect
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?