Handle Payment In Exceptions
The final step is to build in handling for exceptions that may occur in the payment flow. We have discussed the types of webhooks in a previous page for these scenarios, but the following pages explain the scenarios in greater detail.
As cryptocurrency payments are push payments rather than pull payments, we cannot control when and how much cryptocurrency will be received to complete the end user's payment.
Generally, exception scenarios are caused either by end user error, hidden or unpredictable fee amounts from the sending exchange, or slow blockchain processing speeds.
There are three payment exception scenarios that need to be considered and handled by merchants, and all three can be handles from the webhook data sent:
- Overpayments: the amount received exceeds the invoice.
- Underpayments: the amount received falls short of invoice.
- Late payments: funds arrive after the payment has expired or been finalised.
Overpayments
When a customer sends more crypto than the invoice specifies (for example, 0.1 ETH instead of 0.01 ETH), the payment still moves to a COMPLETE
status, but the excess must be accounted for.
To see the actual received amount, on the transactionConfirmed webhook, compare the fields:
paidCurrency.actual
indicates the amount you actually received.paidCurrency.amount
indicates the original expected amount.
To ensure the best customer experience when managing overpayments, it is advisable to adjust the final payment made by the end user to reflect the higher total amount received.
This method eliminates the need to return minor excess amounts of cryptocurrency. Instead, the complete sum will be credited to the end user's account. The total amount sent will be deposited into the MID wallet associated with the transaction.
The sent amount is indicated in the .actual
fields, which can then be referenced to update the end user's total payment amount in your system, in relation to the requested .amount
field.
Underpayments
Underpayments occur when end users do not transfer enough cryptocurrency to fulfil their payment obligation. This can occur if the end user is charged a network fee by their exchange platform that exceeds what they anticipated from their payment amount. Furthermore, the end user might unintentionally send less than intended (e.g. they mean to send 0.1 ETH but send 0.01 ETH instead). In this situation, the payment will still transition to an UNDERPAID
status.
To see the actual received amount, on the transactionConfirmed webhook, compare the fields:
paidCurrency.actual
indicates the amount you actually received.paidCurrency.amount
indicates the original expected amount.
Adjust the end user's final payment to reflect the lower total amount received. This approach prevents the need to return the entire sum of crypto, which may be slightly less than expected due to fees or rounding errors, and instead, credits the revised amount to the end user's account.
The full amount sent will be deposited into the MID wallet associated with the transaction.
The sent amount is indicated in the .actual
fields referenced in the preceding section, which can then be utilised to modify the end user's total payment amount in your system, aligning with the .amount
field.
Late Payments
Late payments occur when cryptocurrency arrives after a payment has already expired or been marked as COMPLETE
or UNDERPAID
. This situation can arise if:
- The blockchain confirmation is delayed
- The user sends funds late, or
- They attempt to top up an already finalised payment
When this happens, you’ll receive a transactionLate webhook indicating that funds have been received for a payment with status of EXPIRED
, COMPLETE
, or UNDERPAID
. The walletCurrency.actual
field will show the amount credited to your wallet in the settlement currency.
Why and when payments expire
We don’t want to leave payments in a PENDING
state indefinitely if a user never sends any funds. Therefore, each payment has an expiry window:
- If you specify
expiryMinutes
and the payment is still in apending
orprocessing
state after that time, it will expire once that many minutes elapse without reaching aCOMPLETE
orUNDERPAID
status. - If you don’t specify
expiryMinutes
, your merchant account’s default expiry setting applies. - If a payment requires FX conversion between the currency being paid and the ond of your MID wallet but
expiryMinutes
and a default expiry are not configured, it will expire after 180 minutes by default.
Once a payment expires, you receive a statusChanged
webhook showing "status": "EXPIRED"
.
Heads up
In most cases, the payment’s status remains
EXPIRED
after funds have been received. If an additional payment is received for aCOMPLETE
orUNDERPAID
payment, this is still categorised as 'late', and the payments will remain in those states as they are considered final.
The webhook payload includes:
walletCurrency.actual
: the converted amount credited to your wallet at the new spot rate (because the original locked rate no longer applies).- Original exchange rate and total amount sent: in case you need to reconcile or report.
From this information, you can see exactly how much was received, how it was converted, and update your records accordingly.
Updated about 2 hours ago