PayUI Integration Guide
This page contains the detailed, step-by-step integration reference for server and client implementation, plus architecture diagrams, event payloads, and error handling guidance.
Steps: Payment Request → OTT → Initialise → Verify
Step 1: Create a Payment Request
Before initialising PayUI, create a Payment Request via the API.
Endpoint: POST /paymentrequests
For complete field documentation, see Create a Payment Request.
Example Request:
{ "reference": "INV-2026-001", "payment": { "amount": 3000, "currencyCode": "AUD", "description": "Payment for Order #12345" }, "paymentMethods": [ "card" ], "transactionRequest": { "category": { "frequency": "single", "captureType": "auto" } }}Note: Digital wallets are coming soon. When available, Apple Pay requires domain registration. For wallet setup details, see PayUI Digital Wallets.
Response (excerpt):
{ "id": "zWIEEs6BBU2A3GUQ8gD3Ag", "reference": "INV-2026-001", "createdDateTime": "2026-01-27T10:15:00Z", "paymentRequestStatus": "created"}Step 2: Generate a One-Time Token (OTT)
Request a one-time token with scope payui and the Payment Request ID from Step 1.
Endpoint: POST /tokens
Example Request:
{ "scope": "payui", "paymentRequestId": "zWIEEs6BBU2A3GUQ8gD3Ag"}Response (excerpt):
{ "token": "eyJhbGciOiJSUzI1NiIsInR5cCI6...", "tokenType": "onetimetoken", "scope": "payui", "expiryDateTime": "2026-01-27T11:15:00Z"}Important: tokens are single-use and short-lived. Use
expiryDateTimeand treat 1 hour as a typical TTL.
Step 3: Configure and Initialise PayUI
Create a minimal configuration object and initialise the PayUI instance on your payment page.
const config = { token: "your-one-time-token", containerId: "payment-container", version: "1.0.0"}
const payUI = GPAUNZ.PayUI.initialise(config);Optional UI customisation:
const config = { token: "your-one-time-token", containerId: "payment-container", version: "1.0.0", ui: { theme: "light", variables: { colorPrimary: "#007ACC", fontFamily: "Inter, system-ui, -apple-system, \"Segoe UI\", Roboto, Arial, sans-serif", borderRadius: "8px" } }}For supported UI options, see PayUI Customisation.
Create the container element in the page:
<div id="payment-container"></div>Use the initialise event to detect if the form loaded successfully and to present the UI to customers.
End-to-end Transaction Flow (Diagram)
This diagram shows the full PayUI flow from rendering the payment page through to server-side verification.
Note: The diagram uses shorthand
GPAUNZ.PayUI.initialise(OTT); in code, pass a config object that includestoken,containerId, andversion.
sequenceDiagram
autonumber
participant FrontEnd
participant Merchant Server
participant Single API
participant PayUI
FrontEnd->>Merchant Server: Request payment page
Merchant Server->>Single API: POST /paymentrequests
Single API-->>Merchant Server: Payment Request ID
Merchant Server->>Single API: POST /tokens (scope=payui and paymentrequestid)
Single API-->>Merchant Server: One-Time Token (OTT)
Merchant Server-->>FrontEnd: Render page with token
FrontEnd->>PayUI: Load payui.js
FrontEnd->>PayUI: GPAUNZ.PayUI.initialise(OTT)
PayUI-->>FrontEnd: Render iframe + emit 'initialise'
FrontEnd->>FrontEnd: User enters card details
PayUI-->>FrontEnd: Emit 'surchargeUpdate' (if enabled)
FrontEnd->>PayUI: User clicks Pay Now
PayUI->>Single API: Create transaction
Single API-->>PayUI: Transaction Result and <br/> PaymentRequest state change
Single API-->>FrontEnd: Emit 'process' event
FrontEnd->>FrontEnd: Display Processing Result
alt is recommended
Single API-->>Merchant Server: Transaction Webhook
Single API-->>Merchant Server: Payment Request Webhook
else is polling
Merchant Server-->>Single API: GET /paymentrequests/{paymentRequestId}
Single API-->>Merchant Server: paymentRequestStatus + transactionResult/transactionAttempts
Merchant Server-->>Single API: GET /transactions/{transactionId}
end
Events (Client-side)
PayUI uses an event-driven architecture. The initialise function returns a PayUIInstance object with on and off methods.
initialise
Fires when PayUI initialisation completes:
payUI.on('initialise', (payload) => { if (payload.result.status === 'ok') { console.log('PayUI ready'); } else { console.error('Initialisation failed:', payload.result.codes); }})surchargeUpdate
Fired when the user enters a valid card number (only if surcharges are enabled):
payUI.on('surchargeUpdate', (payload) => { if (payload.result.status === 'ok') { const surcharge = payload.surcharge / 100; console.log('Surcharge: $' + surcharge.toFixed(2)); }})process
Fired when payment processing completes:
payUI.on('process', (payload) => { if (payload.result.status === 'approved') { console.log('Transaction ID:', payload.transactionId); window.location.href = '/success?txn=' + payload.transactionId; } else { console.error('Payment failed:', payload.result.codes); }})Important: The
processevent is for UI feedback only. Always confirm the final outcome server-side (webhooks orGET /transactions/{id}) before fulfilment.
Error Handling
Payment Request Errors
Check result.codes for validation errors when POST /paymentrequests fails. Common issues include invalid amount/currency, missing required fields, or unsupported paymentMethods.
If you are using wallets, ensure your merchant configuration is enabled and the requested methods match what is supported.
Token Generation Errors
If POST /tokens fails, confirm paymentRequestId and that scope is payui. Tokens are single-use and expire at expiryDateTime.
If a token is rejected during initialisation, it may be expired or already used — generate a new token and re‑initialise.
Initialisation Errors
If the initialise event indicates failure:
- Confirm the PayUI script loaded (no 404s in the console).
- Confirm
containerIdmatches a real element on the page. - Regenerate the token and reload the page if it may be expired or reused.
Processing Errors
If processing fails:
- Use the
processpayload for immediate messaging. - Call
GET /paymentrequests/{id}to determine the outcome and locate the transaction. - Fetch the transaction via
GET /transactions/{id}for detailed failure codes and final status.
Server-side verification
Critical: The client-side
processevent is for UI feedback only. Always confirm the final outcome server-side (webhooks orGET /transactions/{id}) before fulfilment.
Transaction type and refunds
PayUI creates a standard purchase transaction.
Refunds follow the normal Transactions API flow using the verified transaction id:
POST /transactions/{id}/refundsGET /transactions/{id}/refunds/{refundId}
Option 1: Webhooks (Recommended)
Create webhook subscriptions via the REST API and listen for transaction and payment request events. Refer to Webhooks for the canonical event names and subscription payload shape.
For webhook creation, signing, and payload details, see: Webhooks.
Note: The sequence diagram below shows example event names for readability. Always follow the Webhooks page for canonical event names. Webhook flow:
sequenceDiagram
participant GP as GP Gateway
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 = 'paymentrequests'
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 feasible, poll from your server after the client receives the process event.
Polling checklist:
GET /paymentrequests/{paymentRequestId}— confirmpaymentRequestStatusand locate the related transactionGET /transactions/{transactionId}— verify final status and confirm amount/currency
How to locate the transaction to verify:
- Successful payment:
paymentRequestStatusiscompletedandtransactionResultis populated with the transactionidandlocation. - Failed payment:
paymentRequestStatusiscompleted,transactionResultis not populated, andtransactionAttemptsis populated with the failed transaction (use theid/locationfrom the attempt).
You can also retrieve transactions associated with a payment request via GET /transactions?paymentrequestid={paymentRequestId} and then confirm the final state via GET /paymentrequests/{paymentRequestId}.
Polling flow:
sequenceDiagram
participant Client as Client Browser
participant Server as Your Server
participant API as GP API
Client->>Server: Send paymentRequestId (and any observed transactionId)
Server->>API: GET /paymentrequests/{paymentRequestId}
API-->>Server: Payment Request
Server->>Server: Extract transactionId from transactionResult/transactionAttempts
Server->>API: GET /transactions/{transactionId}
API-->>Server: Transaction
Server->>Server: Verify payment request completed and amounts match
Server-->>Client: Return verified result
Testing & Sandbox
PayUI uses the same sandbox environment as the API.
Scenario Triggers
Sandbox scenarios are triggered by specific input values (for example, payment.amount) rather than test card numbers.
For the full list of scenarios and trigger values, see:
Surcharging
To test surcharging, ensure surcharging is enabled on your sandbox merchant account and use the scenario triggers applicable to your configuration.
Wallets
Wallet testing will be available when digital wallets launch. See PayUI Digital Wallets for preparation guidance.
Technical Architecture
Payment Request Lifecycle
stateDiagram-v2
[*] --> created: POST /paymentrequests
created --> completed: Transaction Approved
created --> completed: Transaction Declined
created --> expired: Expiry time reached
created --> cancelled: Merchant cancellation
completed --> [*]
expired --> [*]
cancelled --> [*]
Token Lifecycle
stateDiagram-v2
[*] --> created: POST /tokens
created --> initialised: PayUI.initialise()
initialised --> processed: Payment Submitted
processed --> [*]: Token Used
Note: Tokens expire at
expiryDateTimeregardless of state (typically 1 hour).
Concurrent Payment Protection
- Payment Requests are temporarily locked while a payment is processed to avoid duplicate payments.
- Duplicate idempotency errors return
V10018(header_idempotency_key_is_used).
Examples
For working examples, see: PayUI Examples.