Payment Test Cases
♻️ Reconciled against current code — 2026-07-01. This section was flagged KNOWN STALE on 2026-06-10 with a "do not execute" warning; that blanket warning is now lifted. Confirmed still-valid drift from the original audit: TraxionPay is fully removed (Paynamics is the sole gateway); channel codes are not BDO/BPI/CASH (admin-recorded channels are
MANUAL_CASH / MANUAL_BANK / MANUAL_OTHER / SIMULATED; member-selectable gateway channels are GCASH / MAYA / CREDITCARD / OTC_*); approve/reject on a manual payment sets SUCCEEDED/FAILED (not "APPROVED"/"REJECTED"); Credits admin UI is still thin (TC-PAY-007 largely aspirational — spot-check before trusting it). Newly testable since the 2026-06-15 accounting milestone (!136): manual/record payments, proof of payment, treasury reconciliation, and bulk (multi-invoice) payments are all live on stage. "Simulate Payment" as a user-facing button is REMOVED (2026-06-26, MR saas!242) — use Record Payment for manual/offline payments instead; the SIMULATED payment-method enum and the simulated gateway are kept only as a non-prod test harness, not a UI affordance. TC-PAY-001 through 004 still reference the old flow in places — trust this page and the code over stale wording in those child pages until they get their own rewrite pass. See the green banner below for what's new since Jun 19.
🆕 New on stage — 2026-07-09 (#528). Treasury verify/dispute maker-checker separation of duties: verifying/disputing a treasury reconciliation entry now requires
FINANCE:VERIFY:treasury — a permission key distinct from FINANCE:EDIT:payments (billing payment approve/reject). A new PermissionAction.VERIFY backs it, and the admin Roles/Permissions matrix has a new VERIFY column so a tenant can split maker and checker onto separate custom roles. Default ADMIN and FINANCE_MANAGER hold both grants out of the box — no behavior change until an admin deliberately splits a custom role. See TC-PAY-009 — Treasury Verify/Dispute — Maker-Checker SoD for full coverage.
🆕 New on stage — 2026-07-08 (payments sweep, !283 & !285). See the Jul 8 release note for full test steps.
- Member proof upload no longer 401s (#641, !285, was blocking): the XHR upload double-set the
Authorizationheader, so every proof-of-payment upload was rejected. Uploading proof on a manual payment now succeeds. - Bank-account controls gate on finance permission (#643, !285): finance-capable users can add/edit bank accounts; others get a single friendly 403 message. Unblocks the whole "admin adds bank account → member pays with proof → admin approves" path.
- Paid-event payment submit fixed (#625): the submit-payment Authorization payload was mis-structured; paying for a paid event now works.
- Paid-event registration emails a payment link (#626); manual payment survives session-expiry (#628 — amount + proof preserved for retry after re-login).
- Delete-payment-method confirm modal (#631); reference/invoice-number column in the admin Payments list (#632); "Set default" payment-method action (#634, single-default invariant); approval-notes input on payment approval (#635); sidebar no longer double-active on Payment Channels (#633).
🆕 New on stage — 2026-06-19 → 2026-07-01.
- Payment proof stored as bare S3 key, served via a proxy/presign route (#451, Jun 25 release):
Payment.proofUrlis now a bare storage key, not a full URL. Retrieval goes throughGET /api/billing/admin/payments/:paymentId/proof, which streams the file from storage (or, for legacy absolute-URL proofs, redirects only to an allow-listed host). A proof uploaded via bank-transfer submission should still render after a hard refresh — if it 404s, that's a real bug. memberOnlyticket flag on paid registration (#448, Jun 25 release): a ticket type withmemberOnly: truerejects aSELFregistration unless the registering member's status isACTIVE— enforced server-side inregisterForEvent.ts(closes the old honour-system gap, OQ-ENG-04). GUEST registrations invited by an active member are exempt.- Paid walk-in creates real Invoice + Payment records (#424/#425, Jun 25 release): event check-in's Walk-in tab, for a paid event with "payment collected offline" confirmed, creates a shell guest member, a real
Invoice, and aMANUAL_OTHER/SUCCEEDEDPayment— records only, the gateway is never called. A best-effort welcome email is queued async (failure doesn't block the 201). - Rejected manual payment keeps invoice visible + reverts balance (#469, Jun 29 release): rejecting a manual payment no longer hides the invoice or leaves it at a stale partial balance —
recomputeAndPersistInvoiceStatusre-runs after rejection so the invoice stays listed with its balance restored to the full pre-payment amount. - Payment rows show payment ref + gateway ref (#490, Jun 29 release):
components/invoices/tabs/PaymentsTab.tsxnow renders bothpayment.reference("Ref: …") andpayment.externalReference("Gateway: …") when present, not just one collapsing into the other. - Removed misleading "Skip" on bank-transfer proof (#467, Jun 29 release):
SubmitPaymentProofModal.tsxhas no Skip button — proof is labeled "Proof of Payment (Screenshot) *" (required) and the submit action reads "Submit for Approval".
Payment gateway is INERT on stage (Paynamics). Every "paid" path in this section — including the walk-in path above — creates Invoice/Payment records only; there is never a live charge. Say so explicitly whenever you file a bug against a paid flow.
💳 Paynamics Sandbox — Test Accounts
When these apply. Use the accounts below only when the Paynamics gateway is configured in sandbox mode (
PAYNAMICS_ENVIRONMENT=sandbox). As noted in the red box above, live/online payment is currently PARKED / INERT on stage (no prod credentials) — so on today's staging build the gateway steps are N/A and you exercise paid flows only up to REGISTERED_UNPAID / ISSUED via Record Payment. Keep this table for when sandbox is switched on.
- Hosted checkout. Card / wallet details are entered on the Paynamics-hosted page after redirect — MemberVu never stores card data (no PAN/CVV in our DB, logs, or audit rows). You will leave the app to a
*.payserv.netpage and return to/invoices/:id?payment=processing. - Merchant credentials are NOT in this guide. The sandbox merchant ID / keys are configured server-side by DevOps (from the Paynamics merchant portal) — they are secrets and are intentionally omitted here. Only the buyer-side sandbox test accounts below are safe to publish.
Credit / Debit Cards (Processor MIGS)
| Card Type | Number | CVV | Expiry | 3DS | Expected Result |
|---|---|---|---|---|---|
| VISA (Non-3DS) | 4434260000000008 | 123 | 01/2039 | No | Approved |
| JCB (Non-3DS) | 3528249999991755 | 123 | 01/2039 | No | Approved |
| MasterCard (3DS) | 5123450000000008 | 123 | 01/2039 | Yes | 3DS OTP page shown (enter an OTP below) |
| AMEX | 345678901234564 | 1234 | 01/2039 | No | Approved |
3DS OTP Codes (Metrobank processor)
On the 3D-Secure OTP page for the MasterCard above, enter one of these to drive the outcome — assert the invoice/payment lands in the matching state:
| OTP | Drives | Assert |
|---|---|---|
123456 | Success | Payment SUCCEEDED, invoice → PAID |
111111 | Failed | Payment FAILED, invoice stays ISSUED |
333333 | Card Issuer Declined | Red "card was declined" banner; invoice unchanged (ISSUED) |
444444 | Incorrect OTP | OTP rejected on the bank page; no settlement |
E-Wallets
| Wallet | Test Account | Notes |
|---|---|---|
| Maya | Username 09193890579 · Password Password@1 · OTP 123456 | Choose "Express Pay out" on the Maya page. |
| GCash | No sandbox test account — uses a real GCash wallet | ⚠️ Real money. There is no fake GCash sandbox login; if you must exercise GCash, use a real wallet with a PHP 1.00 invoice, or skip and use a card/Maya instead. |
Notes. Sandbox initiate returns a
redirectUrl on *.payserv.net (e.g. https://testpti.payserv.net/…). Settlement is confirmed by a webhook, so the invoice flips to PAID a moment after you return (watch the processing → success banner). Full click-by-click gateway flows (GCash/card/Maya happy paths, decline, cancel, replaced-payment, timeout, gateway-not-ready) live in the source test file tester-files/01_TEST_CASES/payments/TC_PAY_005_PAYMENT_GATEWAY.md — these accounts are lifted verbatim from there. Assert on the data (payment status, invoice status, no double-charge), not just "it redirected".