UPP Interface
Schema
This document describes how to perform transactions; it does not detail every field. The full schema is available at https://app.swaggerhub.com/apis-docs/quest-payment-system/upp/0.0.1.
Endpoints
Name | Url |
---|---|
Sandbox | https://payments.sandbox.upp.qps.io/v1/ |
Live | https://payments.upp.qps.io/v1/ |
Sandbox Credentials
To test against the UPP sandbox, you will require user credentials. Please email innovation@questps.com.au to request access (please include your external IP address).
Postman
Postman is an application that can send requests to the UPP server. Quest provides an import file that contains all the requests in this document. Postman gives you a simple and quick way to run through the UPP API and get an understanding of how the UPP system works before touching any code!
To use the Quest collection, in Postman:
- Click the button
Import
- Click on the
Link
tab - Enter the URL https://static.qps.io/upp/upp-v1.postman_collection.json
- Follow the prompts to finalise importing
Each request also contains a description explaining the request and the fields to customise. To show the description click on the request title as shown below.
Making a request
Authentication
All requests to UPP must be authenticated using HTTP bearer authorization header. You can do this by adding a HTTP header: Authorization: Bearer <token>
.
It is recommended that credentials to UPP are stored on a central system rather than on individual POS machines for easy key management.
Content-Type in header
All POST
requests must contain the HTTP header Content-Type
set to application/json
.
Idempotency
A key part of the API design is the concept of idempotency. Idempotency is the ability to try the same operation multiple times without changing the result. Idempotency is baked into each request in this API. If your client does not receive a response from the first request, retry the request again (without changing any fields) and be guaranteed that no more than one transaction is created.
Transactions
Payment workflow
- If the Merchant Backend does not receive a response, resend the entire message again. If resending does not resolve the issue refer to the result in the portal. Cashiers should be made aware that they are to trust the UPP result and not the result of a customer. A customer result may be forged or may not be indicative of the final result.
- Step 5 is required because not all purchases return an immediate result. It is important to implement a check to see if the purchase is pending and handle the payment appropriately.
Purchase
A transaction with a transactionType of "purchase" debits funds from the customer's account and transfers it in the merchant account.
To create a transaction perform a POST
to /v1/transactions
.
There are two types of saleType
:
merchantPresentedToken
- when the merchant presents a barcode for the customer andcustomerPresentedToken
- when the customer presents a barcode and the merchant.
Required parameters
The following parameters are required to initiate a refund:
Name | Type | Description |
---|---|---|
transactionType | string | Must be "purchase" |
transactionReference | string | Merchant reference for a transaction (can be any unique string) |
currency | string | 3 letter currency code ISO4217 (aud for Australian dollars and nzd for New Zealand dollars) |
amount | number | The dollar amount of the transaction (as a decimal value). |
provider | string | afterpay, alipay, financialcard, genoapay, humm, latitudepay, unionpay, wechat or zippay |
saleType | string | customerPresentedToken, merchantPresentedToken or website |
customerToken | string | Only required if saleType is customerPresentedToken. This item contains the contents from scanning the QR code |
items | array | |
items.type | string | sku, tax, shipping, discount or credit |
items.itemReference | string | Reference for the item |
items.name | string | Name of the item eg. Apple |
items.amount | number | The price of this item |
items.quantity | number | The number/quantity of this item being purchased |
For a more in-depth description refer to payment providers.
Note
If the customer wishes to change the payment method or cancel the payment after the request has been sent, it is important to send a cancel. A cancel ensures that the customer cannot complete the transaction.
If the transaction result contains approved
, then the transaction is complete. If approved
is true, then the transaction is approved. If approved
is false, then the transaction is declined. If approved
is missing, then the transaction is pending, use long polling to get the final transaction result.
Merchant presented token example
An example of an Alipay merchant presented QR code is shown below. The transaction is performed by submitting a POST
to /v1/transactions
:
{
"transactionType": "purchase",
"amount": 0.01,
"currency": "aud",
"transactionReference": "2e0e4f34-9461-4cdd-a9f9-5816171b70be",
"provider": "alipay",
"saleType": "merchantPresentedToken",
"items": [
{
"type": "sku",
"itemReference": "1",
"name": "Pen",
"amount": 0.01,
"quantity": 1
}
]
}
The response to this request:
{
"provider": "alipay",
"transactionType": "purchase",
"amount": 0.01,
"currency": "aud",
"transactionReference": "2e0e4f34-9461-4cdd-a9f9-5816171b70be",
"saleType": "merchantPresentedToken",
"items": [
{
"type": "sku",
"itemReference": "1",
"name": "Pen",
"amount": 0.01,
"quantity": 1
}
],
"outTradeNumber": "8010000005999702",
"modified": 1611886804060,
"cancelled": false,
"settlementAmount": 0,
"companyName": "Fred Ltd",
"merchantName": "Freds Bricks",
"created": 1611886803017,
"merchantId": "123456",
"terminalId": "1",
"clientIpAddress": "49.255.39.132",
"tags": [],
"amountCaptured": 0,
"canCaptureMore": false,
"merchantToken": "https://qr.alipay.com/bax02430n2uwj1zkewn580f3",
"discount": 0,
"discountTags": []
}
Display the merchantToken
to the customer and allow time for the customer to scan the QR code and perform a long poll to get the final result of the transaction.
{
"transactionReference": "69ac99d7-7b12-46a4-8a9d-38ee00495a1c",
"created": 1611887439088,
"providerReference": "2021012922001465741426433262",
"merchantId": "123456",
"companyName": "Fred Ltd",
"merchantName": "Freds Bricks",
"items": [
{
"amount": 0.01,
"itemReference": "1",
"type": "sku",
"quantity": 1,
"name": "Pen"
}
],
"merchantToken": "https://qr.alipay.com/bax08220ef9lxsyzvkdk00c9",
"approved": true,
"modified": 1611887439845,
"outTradeNumber": "8010000005498820",
"tags": [],
"transactionType": "purchase",
"paymentTime": 1611887462000,
"amount": 0.01,
"clientIpAddress": "49.255.39.132",
"canCaptureMore": false,
"settlementAmount": 0.01,
"discountTags": [],
"buyerIdentity": "alipay-2088722303265747",
"currency": "aud",
"saleType": "merchantPresentedToken",
"discount": 0,
"provider": "alipay",
"amountCaptured": 0.01,
"terminalId": "1",
"exchangeDetails": {
"purchaserBillingAmount": 0.05,
"purchaserBillingCurrency": "cny",
"exchangeRate": "4.96941400"
},
"cancelled": false,
"settlementBatch": "20210129"
}
Customer presented token example
An example of an Alipay customer presented QR code is shown below. The transaction is performed by submitting a POST
to /v1/transactions
:
{
"transactionType": "purchase",
"amount": 0.01,
"currency": "aud",
"customerToken": "289661544981076259",
"transactionReference": "45267dd6-aa0a-4352-9626-ad13e7bd053f",
"provider": "alipay",
"saleType": "customerPresentedToken",
"items": [
{
"type": "sku",
"itemReference": "1",
"name": "Pen",
"amount": 0.01,
"quantity": 1
}
]
}
The response to this request:
{
"provider": "alipay",
"transactionType": "purchase",
"amount": 0.01,
"currency": "aud",
"customerToken": "289661544981076259",
"transactionReference": "45267dd6-aa0a-4352-9626-ad13e7bd053f",
"saleType": "customerPresentedToken",
"items": [
{
"type": "sku",
"itemReference": "1",
"name": "Pen",
"amount": 0.01,
"quantity": 1
}
],
"approved": true,
"outTradeNumber": "8010000001198747",
"modified": 1611891559826,
"cancelled": false,
"settlementAmount": 0.01,
"companyName": "Fred Ltd",
"merchantName": "Freds Bricks",
"created": 1611891558022,
"merchantId": "123456",
"terminalId": "1",
"clientIpAddress": "49.255.39.132",
"tags": [],
"amountCaptured": 0.01,
"canCaptureMore": false,
"discountTags": [],
"buyerIdentity": "alipay-2088722303265747",
"paymentTime": 1611891559000,
"exchangeDetails": {
"exchangeRate": "4.96250000",
"purchaserBillingAmount": 0.05,
"purchaserBillingCurrency": "cny"
},
"providerReference": "2021012922001465741426514600",
"settlementBatch": "20210129"
}
In the example above the approved
field is true so the payment is approved. The approved
flag will be present on most customer presented barcode responses however not all. Long poll must be implemented to fetch the final result of the transaction in cases where the approved flag is missing.
Cancel
Cancel is used to stop a transaction that is in progress. An example of when to use a cancel is when the customer wants to change payment types. A cancellation should not be used when no response is received. On no response conditions, the same message should be sent to the UPP host.
Warning
Cancellations are only for purchases; refunds cannot be cancelled.
To cancel a purchase transaction perform a POST
to /api/v1/transactions/<transactionReference>/cancel
. The transaction is successfully cancelled if the response contains a successful HTTP status code. As long as you send a cancel to UPP within 24 hours of starting the transaction, UPP should not reject a cancellation request. If UPP returns a bad HTTP status code, refer to the failure
and failureDescription
fields for more information.
Refund
Required Parameters
The following parameters are required to initiate a refund:
Name | Type | Description |
---|---|---|
transactionType | string | Must be "refund" |
transactionReference | string | Merchant reference for a transaction (can be any string) |
currency | string | 3 letter currency code ISO4217 (aud for Australian dollars and nzd for New Zealand dollars) |
amount | number | The dollar amount to be refunded (as a decimal value) |
originalTransactionReference | string | The transactionReference used on the original purchase transaction |
refundReason | string | other, changeOfMind, faulty, notAsDescribed, wrongProduct, productNoLongerNeeded or didNotMeetExpectations |
Example Refund
To create a refund transaction perform a POST
to /v1/transactions
.
{
"transactionType": "refund",
"amount": 0.01,
"currency": "aud",
"transactionReference": "2e691372-77a1-4aca-9826-8a79c230d22e",
"originalTransactionReference": "17f7ca22-044d-4f9f-85e1-0091d77c36fd",
"refundReason": "other"
}
The response to this refund:
{
"transactionType": "refund",
"amount": 0.01,
"currency": "aud",
"transactionReference": "2e691372-77a1-4aca-9826-8a79c230d22e",
"originalTransactionReference": "17f7ca22-044d-4f9f-85e1-0091d77c36fd",
"refundReason": "other",
"approved": true,
"outTradeNumber": "8010000026101650",
"modified": 1611896048579,
"cancelled": false,
"settlementAmount": 0.01,
"companyName": "Fred Ltd",
"merchantName": "Freds Bricks",
"created": 1611896046820,
"merchantId": "123456",
"terminalId": "1",
"clientIpAddress": "49.255.39.132",
"tags": [],
"originalOutTradeNumber": "8010000010102383",
"saleType": "customerPresentedToken",
"provider": "alipay",
"amountCaptured": 0.01,
"canCaptureMore": false,
"discount": 0,
"discountTags": [],
"paymentTime": 1611896048580,
"providerReference": "2021012922001465741425855918",
"exchangeDetails": {
"exchangeRate": "4.96250000",
"purchaserBillingAmount": "0.05",
"purchaserBillingCurrency": "cny"
},
"settlementBatch": "20210129"
}
Fetch
There are two types of methods to fetch a transaction: immediate and long polling.
To fetch the current state of a transaction perform a GET
to /v1/transactions/<transactionReference>
.
Long polling keeps a connection alive until the transaction is complete or a timeout occurs. Upon receiving a 202 status code or a network error then resend the poll request. A poll can take up to 30 seconds so ensure the connection has a timeout beyond this period.
To perform long poll, perform a GET
on /api/v1/transactions/<transactionReference>?waitForCompletion=true
.