Payment Flow 🔁
High-level Overview
- The merchant creates a payment and redirects a customer to pay.o2pay.co/... (exact link is provided in the payment object)
- The customer specifies payment options and pays with crypto
- OxygenPay receives "in progress" transaction
- The customer receives "payment successful" in the UI. Right after that "back to site" button is enabled and it points to "success url" that was provided when creating a payment
- OxygenPay sends "inProgress" webhook to the merchant's backend
- OxygenPay receives transaction confirmation and marks the payment as successful
- OxygenPay sends "success" webhook to the merchant's backend
Detailed Flow
This diagram illustrates the process of a payment lifecycle
At step 11 customer can click "back to site" and proceed to $payment.redirectUrl, but at this moment transaction is not confirmed yet
Payment creation
You can create a payment with several ways:
- By creating a payment link
- Using API (e.g. from your backend) using
createPayment
- Manually via Merchant Dashboard (Payments > New Payment). Minimal payment entity consists of ID, fiat currency (USD / EUR), and price
To prevent duplicate requests and keep the flow idempotent, ID generation is led by the merchant side i.e. you should provide a unique id in the request
curl -X POST 'https://api.o2pay.co/api/merchant/v1/merchant/{merchantId}/payment' \
-H 'X-O2PAY-TOKEN: {token}' \
-H 'Content-Type: application/json' \
--data '{
"id": "8263313B-08C8-4855-8FAC-3A4CCBA7EAC2",
"currency": "USD",
"price": 30,
"redirectUrl": "https://my-store.com/success",
"description": "Sample Payment"
}'
The response would be:
{
"createdAt": "2023-04-25T21:19:29.358Z",
"currency": "USD",
"description": "Sample Payment",
"id": "8263313b-08c8-4855-8fac-3a4ccba7eac2",
"isTest": false,
"orderId": null,
"paymentUrl": "https://pay.o2pay.co/pay/<uuid>",
"price": "30",
"redirectUrl": "https://my-store.com/success",
"status": "pending",
"type": "payment"
}
Right after that you should redirect a customer to the $.paymentURL
:
Payment status lifecycle
Notes on expiration
- When a customer selects a currency, the payment is locked for 20 minutes.
After that period it expires and payment is marked as Failed - Created and untouched payment link expires automatically after 6 hours
Test payments
It's possible to create test payments, in that case, we will process transactions on testnets (e.g. Ethereum Goerli)
and top-up test balances as well. To create a test payment, simply specify "isTest": true
.
Not all ERC20/TRC20 tokens are supported, see supported currencies section.