Payments - In Store

This guide describes how the online payment flow works in detail.

1 - Get access token

Pass your client id and secret to the Waave token API to obtain an access token. The access token returned by this logic will be required to make subsequent calls to Waave APIs.

The host should cache the access token until its expiry.

Token API end point URIs:

Sample Request

{
    "client_id":MERCHANT_CLIENT_ID,
    "client_secret":MERCHANT_CLIENT_SECRET,
    "scope":"payment-sessions:create payment-sessions.status:read"
}

Sample Response

{
    "access_token": "eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiIxYjg3MGNkNy1lODdjLTRkZTYtYTExNS05Y2I1NzBkZDk5NTIiLCJhdXRoIjoiUk9MRV9XU19VU0VSIiwic2NvcGUiOiJwYXltZW50LXNlc3Npb25zOmNyZWF0ZSBwYXltZW50LXNlc3Npb25zLnN0YXR1czpyZWFkIiwiZXhwIjoxNjU0ODI1OTgwfQ.nOZNzpHicZkFtmsK4LJNRD44QuGlja8UBoyv_1JiUlTdGYTadq0Qe_yK8LV9e_RMgKeusb6xTk0ZbMzj6bgbZn7h9ZC6g942gjhFyIIQwY0tpLaFcU5cC5wfdcIIwdKDHcQNnXz1J6mNHnJlmgbmRijYdR21q-CxFZJ3j3TScYUDAyoz9_8usI8UeLjWrzveU1DZvGd1jKJFmnqDJntuBtDjW107rADZaaGrAmidC-QXrLJx90z7YxVu8N5B0lQTd67mQILWpONAVLLeFTCDEtQEMXLb1O_ENlYw6ZdyF8RzukfW0Nz91OMml86VlrRKG1IaiSKg1WhyI9YvhiTiuQ",
    "expires": 86400
}

2 - Create a Payment

If the customer selects Waave as payment method, call Create Payment API (In Store) to create a Payment using the access token obtained in the previous step.

Sample Request

{
    "customerReference": "orderRef-20220610123125",  
    "totalAmount": 900,
    "currency": "AUD",
    "effectiveFromAt": null,
    "effectiveToAt": "2022-07-11T04:40:42.500126870Z",
    "notificationUrl": "https://your_notification_url", 
    "businessCode": "your_business_code",
    "tillId": "Till-1234",
    "orderItems": [
        {
            "name": "bournvita health drink",
            "quantity": 1,
            "amount": 900,
            "currency": "AUD"
        }
    ]
}
FieldDescription / Notes
customerReferenceOptionalMerchant specified reference for the order / payment.
totalAmountMandatoryTotal payment amount in cents (e.g. $120.50 should be passed as 12050)
currencyOptionalIf not specified, defaults to AUD.
effectiveFromAtOptionalIf specified, Waave will reject payment authorisation attempts by the shopper prior to the time specified.
effectiveToAtOptionalIf specified, Waave will reject payment authorisation attempts by the shopper after the time specified.
notificationUrlOptionalWebhook URL to which Waave will post the status updates for this payment. Leave blank if web hooks are not required.
businessCodeMandatoryProvided by the Waave team during onboarding.
tillIdOptionalTill / terminal ID
orderItemsMandatoryArray of line items in the cart.

This API supports idempotency. See this section for more detail.

Sample Response

{
    "paymentSessionId": "1fd302b1-5876-4629-bd1a-77eba6a1e647",
    "customerReference": "orderRef-20220610123125",
    "totalAmount": 900,
    "currency": "AUD",
    "businessCode": "your_business_code",
    "tillId": "Till-123445",
    "createdAt": "2023-04-26T12:23:48.329412315Z",
    "expiresAt": "2023-04-26T13:23:48.306020434Z",
    "status": "AWAITING_AUTHORISATION",
    "payUrl": "https://link.app.waavetest.com/pay/w/1fd302b1-5876-4629-bd1a-77eba6a1e647?r=true",
    "orderItems": [
        {
            "id": 204302,
            "name": "bournvita health drink",
            "sku": null,
            "quantity": 1,
            "amount": 900,
            "currency": "AUD"
        }
    ],
    "notificationUrl": "https://your_notification_url",
    "effectiveFromAt": null,
    "effectiveToAt": "2022-07-11T04:40:42.500126870Z"
}

The response contains a unique payUrl which is required in the next step.


3 - Display QR code for the customer to scan & pay

Once the Payment object has been created, you need to encode the payUrl in the response message into a QR code and display it on the terminal display or a customer facing POS display.

The shopper will scan the QR code with the Waave mobile app and authorise the payment.


4 - Verify Payment Status

Once the QR code is displayed, the host must verify the payment status by polling the Get Payment Status API with the paymentSessionId.

Based on the status being returned, you must take different actions:

  • INSTRUCTION_SENT - the shopper has authorised the payment in the Waave app and the payment has been submitted. This is the only status that indicates successful payment authorisation.
  • AWAITING_AUTHORISATION - the shopper is yet to authorise the payment in the Waave app. The host must continue to poll.
  • EXPIRED - The payment session has expired.
  • DECLINED - Waave have declined the payment.
  • CANCELLED - The payment session has been cancelled by the merchant or the shopper.
  • ERROR - There was an error while processing the payment session.

There are other statuses that this API can return, such as AWAITING_AUTHORISATION. If it does, you need to keep polling the API until one of the final statuses mentioned above is returned. See Statuses for a complete list of statuses.

Sample Response

{
    "status": "INSTRUCTION_SENT", 
    "resultCode": null,
    "resultUrl": null
}

The host can also subscribe to payment notification webhooks. Refer to Webhooks - Payment Notifications for more details.


5 - Cancel a Payment

The host can explicitly cancel / void a payment by calling the Cancel Payment API. If the shopper attempts to authorise a cancelled payment, they recieve an error.

Once a payment session is authorised it cannot be cancelled. You will need to initiate a refund instead. See Refunds for more details.

First, implement logic to pass your client id and secret to the Waave token API to obtain an access token with the scope 'payment-sessions:cancel'.

Sample Request

{
    "client_id":MERCHANT_CLIENT_ID,
    "client_secret":MERCHANT_CLIENT_SECRET,
    "scope":"payment-sessions:cancel"
}

Sample Response

{
    "access_token": "eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiIxYjg3MGNkNy1lODdjLTRkZTYtYTExNS05Y2I1NzBkZDk5NTIiLCJhdXRoIjoiUk9MRV9XU19VU0VSIiwic2NvcGUiOiJwYXltZW50LXNlc3Npb25zOmNyZWF0ZSBwYXltZW50LXNlc3Npb25zLnN0YXR1czpyZWFkIiwiZXhwIjoxNjU0ODI1OTgwfQ.nOZNzpHicZkFtmsK4LJNRD44QuGlja8UBoyv_1JiUlTdGYTadq0Qe_yK8LV9e_RMgKeusb6xTk0ZbMzj6bgbZn7h9ZC6g942gjhFyIIQwY0tpLaFcU5cC5wfdcIIwdKDHcQNnXz1J6mNHnJlmgbmRijYdR21q-CxFZJ3j3TScYUDAyoz9_8usI8UeLjWrzveU1DZvGd1jKJFmnqDJntuBtDjW107rADZaaGrAmidC-QXrLJx90z7YxVu8N5B0lQTd67mQILWpONAVLLeFTCDEtQEMXLb1O_ENlYw6ZdyF8RzukfW0Nz91OMml86VlrRKG1IaiSKg1WhyI9YvhiTiuQ",
    "expires": 86400
}

Then call the the Cancel Payment API with the token provided. The API will return a 200 response indicating that the payment session has been invalidated. If the shopper attempts to authorise this payment session, they will receive an error.

If you receive the following error, the payment session has already been authorised by the customer and it cannot be cancelled.

{
    "entityName": "paymentSession",
    "errorKey": "cancel-not-allowed",
    "type": "https://www.waave.com/problem/problem-with-message",
    "title": "Cannot perform cancel on payment session already having status INSTRUCTION_SENT",
    "status": 400,
    "message": "error.cancel-not-allowed",
    "params": "paymentSession"
}

What’s Next