Bind refunds to a refundable payment

Require a captured or otherwise refundable original payment under the provider’s rules, remaining refundable amount, currency match, and approved destination. Bank settlement is a separate state; do not assume it must precede a refund. The server must calculate the refundable amount from trusted records. A support agent should not supply a larger value through a hidden field or API request.

Split high impact actions

Give staff roles narrow rights: one can request a refund; another can approve and release it. The same person must not approve their own request. OWASP transaction authorization guidance supports explicit review of transaction details before execution.

Test the full permission matrix

Try approval with the requestor account, a read only account, an expired session, and a newly promoted account. Submit two partial refunds at once. Record the actor, approver, reason, original payment, and provider result without putting sensitive card data in logs.

Treat an off-route refund as an exception

The original payment reference proves a charge happened, not that a new recipient is entitled to its funds. When the provider supports an alternate refund route, collect the reason, verified recipient, amount, and independent approval in a separate case. If the provider only supports refunding the original method, follow its exception process; do not send a payout and label it a refund. Bind that approval to the exact destination and original charge. A changed destination after approval invalidates the decision. Limit who can request, approve, and release the exception. The provider request and journal must carry the exception ID so finance can reconcile it later.

Show the reviewer the exact refund

Use a synthetic ₦10,000 captured payment. A support worker requests a ₦4,000 refund to the original payment route and gives a reason. The reviewer sees that amount, the payment reference, the remaining refundable amount, and the requester’s identity. The approval records a digest of those exact fields. If an API client changes the amount to ₦6,000 or swaps the payment reference, the release service must reject the old approval and ask for a new decision.

Run the case through the staff screen, direct API, and scheduled refund job. A policy that only disables the button on the screen fails the direct API test. Check that one staff identity cannot request and approve the same refund through two roles. Record the request version, approval version, provider refund ID, and resulting ledger entry. OWASP’s transaction authorization guide says the server must enforce the sequence and protect significant transaction data from change during approval. The test passes when a changed request never reaches the provider under an earlier approval.

Reserve the refund before release

For a captured ₦10,000 payment with no refunds, submit two separate ₦6,000 refund requests at once. Reserve refundable value inside the approval or release transaction. One reserves ₦6,000; the other is denied because only ₦4,000 remains. Two ₦3,000 requests can both pass if the roles, policy, and remaining amount permit them. The control is the funded total, not a fixed rule that only one request wins.

Keep the reservation while the provider result is unknown. A lost response cannot release it safely: the refund might already exist. Use the provider refund ID and documented lookup or retry method to resolve the existing request. Release the reservation once after a final failed result; convert it once after success. For a policy denial, check that no refund job, provider refund, or financial journal followed. A denied-action audit event is still expected.

Case PAY-04 changes the amount after approval. Save the before and after request versions, the independent staff identities, and the provider call count. Approval must match the exact version at release. Partial refund tests cover the remaining-amount race separately.

Evidence to retain

Keep the original charge, refund request, remaining refundable amount, requester, approver, approved version, and provider result. The review must show two distinct actors.

Sources

Put this into practice

Map each refund route and its roles, then test partial refunds under parallel load. Lock down destination exceptions with a separate approval step. See our payment gateway testing and payment gateway testing service. To check a live flow, request a security review.