Skip to content

HPP Outcomes

This page describes how to determine the final payment outcome after a customer completes (or abandons) the HPP flow.

Result Page Behaviour

After the transaction is processed, the result page behaviour depends on the resultPage value set in your Payment Request:

  • resultPage: "show" (default): HPP displays a hosted result page. The page shows transaction details on approval, or a decline/failure message with the option to retry (if attempts remain). When redirectUrl is provided, the result page includes a link back to the merchant site.
  • resultPage: "redirect": On approved transactions, the customer is automatically redirected to the merchant’s redirectUrl. On declined or failed transactions, the hosted result page is displayed.
  • resultPage: "none": Accepted API value.

Server-Side Reconciliation

Critical: Do not rely on the customer reaching your redirect URL to confirm payment. Always verify the outcome server-side using webhooks or polling.

Subscribe to transactions and payment_requests webhook events. When a payment completes via HPP, you will receive:

  1. A transaction webhook with the transaction outcome.
  2. A payment request webhook with the updated paymentRequestStatus.

For webhook setup, signing verification, and payload structure, see Webhooks.

Webhook flow:

sequenceDiagram
    participant GP as Single API
    participant Webhook as Your Webhook Endpoint
    participant DB as Your Database

    GP->>Webhook: POST callbackUrl (X-Signature + JSON payload)
    Webhook->>Webhook: Verify X-Signature (HMAC-SHA256)
    alt signature valid
        Webhook->>Webhook: Parse event and payload
        alt event = 'transactions'
            Webhook->>DB: Persist transaction state
        else event = 'payment_requests'
            Webhook->>DB: Persist payment request state
        end
        Webhook->>GP: HTTP 200 OK
    else signature invalid
        Webhook->>GP: HTTP 401/403
    end

Option 2: Polling (Fallback)

If webhooks are not available, poll the Payment Request after a reasonable delay:

  1. GET /paymentrequests/{paymentRequestId} — check paymentRequestStatus and locate the transaction.
  2. GET /transactions/{transactionId} — verify final status, amount, and currency.

How to locate the transaction:

  • Successful payment: paymentRequestStatus is completed and transactionResult contains the transaction id and location.
  • Failed payment: paymentRequestStatus is completed, transactionResult is not populated, and transactionAttempts contains the failed transaction details.

You can also retrieve transactions via GET /transactions?paymentrequestid={paymentRequestId}.

Polling flow:

sequenceDiagram
    participant Server as Your Server
    participant API as Single API

    Server->>API: GET /paymentrequests/{paymentRequestId}
    API-->>Server: Payment Request (status + transactionResult)
    Server->>Server: Extract transactionId
    Server->>API: GET /transactions/{transactionId}
    API-->>Server: Transaction (final status, amount, codes)
    Server->>Server: Verify outcome and update database

Payment Request Lifecycle

stateDiagram-v2
    [*] --> created: POST /paymentrequests
    created --> completed: Transaction approved or declined
    created --> cancelled: Merchant cancellation
    completed --> [*]
    cancelled --> [*]

HPP-Specific Status Scenarios

ScenarioWhat the customer seesPayment Request status
Payment approvedResult page or redirect (depends on resultPage)completed
Payment declined (retries remaining)Hosted result page with retry optionRemains created
Payment declined (no retries)Hosted result page — attempts exhaustedcompleted
Payment request cancelledHosted page indicating the request has been cancelledcancelled
Payment request already completedRedirects to the transaction result pagecompleted