Callback mechanism: Difference between revisions

From Barion Documentation
Jump to navigation Jump to search
No edit summary
m (replaced reference to v2 GetPaymentState with v4 PaymentState)
 
(14 intermediate revisions by 6 users not shown)
Line 11: Line 11:
# The payment gets completed, cancelled, expired, refunded, taken under investigation, or released from investigation
# The payment gets completed, cancelled, expired, refunded, taken under investigation, or released from investigation
# The Barion system sends an '''HTTP POST''' request to the merchant's system to the URL defined by the merchant (in the <code>CallbackUrl</code> parameter of the [[Payment-Start-v2|/v2/Payment/Start]] API call) with the payment's unique identifier, indicating that something has just happened, so the merchant's system should check the payment now
# The Barion system sends an '''HTTP POST''' request to the merchant's system to the URL defined by the merchant (in the <code>CallbackUrl</code> parameter of the [[Payment-Start-v2|/v2/Payment/Start]] API call) with the payment's unique identifier, indicating that something has just happened, so the merchant's system should check the payment now
# The merchant's system sends a request to the [[Payment-GetPaymentState-v2|/v2/Payment/GetPaymentState]] API endpoint with its POSKey and the received payment identifier
# The merchant's system sends a request to the [[Payment-PaymentState-v4|/v4/Payment/<PaymentId>/PaymentState]] API endpoint with its POSKey and the received payment identifier
# Based on the response received, the merchant's system can determine what processing tasks should take place
# Based on the response received, the merchant's system can determine what processing tasks should take place
{{NotificationBox|title=IMPORTANT|text=Always process the entire response with all included transaction data, because different actions make different changes to the payment state object.|color=#FF7A3D}}


== Structure and processing of the callback request ==
== Structure and processing of the callback request ==
Line 26: Line 28:
So the total time window allocated for successful callback is roughly '''4 minutes'''. If the Barion system fails to get an HTTP 200 response after that, the callback is not sent and the merchant's system automatically gets an e-mail notification about the error.
So the total time window allocated for successful callback is roughly '''4 minutes'''. If the Barion system fails to get an HTTP 200 response after that, the callback is not sent and the merchant's system automatically gets an e-mail notification about the error.


Every time, when your system receives a callback request from the Barion you have to call the [[Payment-GetPaymentState-v2|/v2/Payment/GetPaymentState]] API endpoint to find out the change. First, your system should check the payment's status and after the list of the payment's transactions. For example, if you requested a payment refund or when the reserved payment's time limit has expired the list of payment’s transactions will contain new e-money transactions. It's your system's responsibility to handle changes.
Every time, when your system receives a callback request from the Barion you have to call the [[Payment-PaymentState-v4|/v4/Payment/<PaymentId>/PaymentState]] API endpoint to find out the change. First, your system should check the payment's status and after the list of the payment's transactions. For example, if you requested a payment refund or when the reserved payment's time limit has expired the list of payment’s transactions will contain new e-money transactions. It's your system's responsibility to handle changes.
 
== Actions initiating a callback, and how to detect them ==
 
Different actions result in different changes in the payment state object that you query on the [[Payment-PaymentState-v4|/v4/Payment/<PaymentId>/PaymentState]] API endpoint. Depending on what happened in the payment's life cycle, there are different things to look for. This section should help you choose what checks to perform based on your integration scenario. Please read these thoroughly and perform all applying checks in your business logic when processing a callback.
 
'''Successful payment'''
 
When the customer successfully completes the payment, the payment status will be set to different values depending on the type of the payment.
* <code>Successful</code> when using Immediate payments
* <code>Reserved</code> when using Reservation payments
 
'''Pending payment'''
 
In delayed capture type payments, when the payment amount is blocked on the payer's payment source, the transaction's payment status is set to <code>Authorized</code>.
{{NotificationBox|title=Note|text=An <code>Authorized</code>-status payment is very likely to succeed, but isn't in fact considered successful [[Payment-Capture-v2|until the payee shop captures it]].|color=#FF7A3D}}
 
'''Payment rejection'''
 
When the customer decides to reject payment, and return to the shop, the payment status will be set to <code>Canceled</code>. The payment can no longer be completed.
 
'''Finishing a Reservation payment'''
 
When the shop finishes a Reservation payment, the payment status will be set depending on the finish being partial or full.
* if there are multiple payment transactions, but only certain one of them are being finished, the payment status will NOT change (it will stay in <code>Reserved</code>)
* when every transaction in the payment has been finished, the payment status will be set to <code>Succeeded</code>
* transactions finished with a lower amount than the initial reserve will result in a partial refund to the user, which shows up as a new refund transaction in the Transactions[] array of the payment state object
 
'''Capturing a Delayed Capture payment'''
 
When the shop captures a Delayed Capture payment, the payment status will be set to <code>Succeeded</code>, regardless of whether the authorization and capture amounts match. No refund transaction is being created in this case, because the partial capture happens directly on the bank card.
 
'''Payment expiring'''
 
When a payment expires without being completed, the payment status will be set to <code>Expired</code>.
* If the payment was an ongoing Reservation payment that hasn't been finished in time, a refund will also be created, which shows up as a new refund transaction in the payment state object
 
'''Refund'''
 
When a refund is executed (via the website, or the [[Payment-Refund-v2|/v2/Payment/Refund]] API), a new refund transaction will be added to the Transactions[] array in the payment state object. Only <code>Succeeded</code> payments can be refunded, and the payment status will not change during a refund, it will stay <code>Succeeded</code>. Barion sends a callback for successful and unsuccessful refunds as well. You have to check the refund transaction in the Transactions[] array for the result.
 
{{NotificationBox|title=IMPORTANT|text=Different actions make different changes to the overall payment state. Never rely only on payment status changes! Always process the entire payment state object and execute your business logic accordingly.|color=#FF7A3D}}


== Security ==
== Security ==
Never rely on the callback function alone. When the callback URL is requested, your application must call the [[Payment-GetPaymentState-v2|/v2/Payment/GetPaymentState]] Barion API to get the proper payment state.
Never rely on the callback function alone. When the callback URL is requested, your application must call the [[Payment-PaymentState-v4|/v4/Payment/<PaymentId>/PaymentState]] Barion API to get the proper payment state.


Please refer to the [[Security Measures]] page for more information and a list of IP addresses.
Please refer to the [[Security Measures]] page for more information and a list of IP addresses.
Line 49: Line 92:


== Rate limiting ==
== Rate limiting ==
{{NotificationBox|title=IMPORTANT|text=Currently only live in the test environment, production go-live date will be announced soon|color=#FF7A3D}}
To prevent potential disruptions in our service caused by the abuse of the [[Payment-PaymentState-v4|/v4/Payment/<PaymentId>/PaymentState]] API endpoint, we have introduced a rate-limiting feature to throttle excessive requests. '''Generally, you should rely on the callback mechanism whenever possible unless you have a specific reason not to''', but if you want to manually get the details of a payment, here are a couple of things to bear in mind:
When a payment has started we send a callback message about any status change. Then a getpayment request can be sent then and query the status of the payment.
* Make sure you do not send continuous requests for the same payment even if you need to get its current state manually without waiting for the callback to happen
We experience some misuse about these getpaymentstate requests.
* Do not keep requesting for an indefinite time, even if your requests are throttled (e.g. if a problem occurs during the payment process, and the callback never happens, you shouldn't keep polling the API indefinitely) In this case the frequency is not the problem, but as time passes these orphan requests can cause a great load together
* After payment start, mass getpaymentstate requests are sent to the same paymentID about one request/sec or even more, and do not wait for the callback. This request burst cause a great overhead on our systems which is absolutely pointless.
* If a problem occurs during the payment and it does not finish successfully some getpaymentstate requests to that ID keeps going indefinitely with a 1, 2 or 5 minutes frequency. This frequency itself is not a problem, but as time passes there are more and more phantom requests which in sum can cause a great load.
<br/>                                                                                                     
Because of these two misuse of the getpaymentstate request we implemented rate limiting on calling getpaymentstate:
* Because of the first problem we accept only two getpaymentstate request (with the same paymentID) in every 5 seconds. So the first two request will be served then every additional request during the 5 seconds interval will be denied with http status code 429 "Too many request". Then two request will be served again, and so on, like that.
* Because of the second problem we start counting the getpaymentstate requests with the same paymentID. When this count reaches a certain limit during a well-defined time period the further requests with the same ID will be banned with the above http status code.
 
== What NOT to do ==


Never long-poll the [[Payment-GetPaymentState-v2|/v2/Payment/GetPaymentState]] API endpoint and wait for the payment status to suddenly change!
To avoid these situations, the following throttling logic is implemented on our API:
If you use a high interval between requests, user experience will deteriorate significantly. If you use a small interval, your requests will get throttled.
* During a 5 seconds window we only accept the first 2 [[Payment-PaymentState-v4|/v4/Payment/<PaymentId>/PaymentState]] requests with the same payment ID. This means that if you submit two requests less than 5 seconds apart, subsequent requests will be denied until 5 seconds pass after the initial successful request. These requests will return with an HTTP 429 "Too many requests" error.
* We keep track of requests, and if requests with the same payment ID reach a certain limit during a specific timeframe, all further requests will return HTTP 429. The exact timeframe and limits are not disclosed to the public.


If you are having difficulties implementing the proper callback flow, consult our developer support!
To reinforce the points above, we recommend using the callback mechanism described above, and calling the [[Payment-PaymentState-v4|/v4/Payment/<PaymentId>/PaymentState]] API endpoint only when there's a reason to do so.

Latest revision as of 10:11, 25 March 2024

Payment callback mechanism (aka. IPN)


Whenever a given payment's state changes, it is expected that the caller system and the Barion database are synchronized. This is accomplished by implementing the callback mechanism (referred to as "Instant Payment Notification" or "IPN" in some terminology) between the two systems.

The callback process

The event flow of the implemented callback mechanism is simple:

  1. The payment gets completed, cancelled, expired, refunded, taken under investigation, or released from investigation
  2. The Barion system sends an HTTP POST request to the merchant's system to the URL defined by the merchant (in the CallbackUrl parameter of the /v2/Payment/Start API call) with the payment's unique identifier, indicating that something has just happened, so the merchant's system should check the payment now
  3. The merchant's system sends a request to the /v4/Payment/<PaymentId>/PaymentState API endpoint with its POSKey and the received payment identifier
  4. Based on the response received, the merchant's system can determine what processing tasks should take place
IMPORTANT
Always process the entire response with all included transaction data, because different actions make different changes to the payment state object.

Structure and processing of the callback request

The callback request contains one parameter, the payment identifier. This is sent in the paymentId field of the POST request body. The merchant's system must send an HTTP 200 OK response (with any content) in order for the callback to be considered successful. The timeout period for answering a callback request is 15 seconds.

If the Barion system does not get an HTTP 200 response, it retries sending the callback for a maximum of 5 times, with exponential back-off timing delay between tries:

  • 2 seconds
  • 6 seconds
  • 18 seconds
  • 54 seconds
  • 2 minutes 42 seconds

So the total time window allocated for successful callback is roughly 4 minutes. If the Barion system fails to get an HTTP 200 response after that, the callback is not sent and the merchant's system automatically gets an e-mail notification about the error.

Every time, when your system receives a callback request from the Barion you have to call the /v4/Payment/<PaymentId>/PaymentState API endpoint to find out the change. First, your system should check the payment's status and after the list of the payment's transactions. For example, if you requested a payment refund or when the reserved payment's time limit has expired the list of payment’s transactions will contain new e-money transactions. It's your system's responsibility to handle changes.

Actions initiating a callback, and how to detect them

Different actions result in different changes in the payment state object that you query on the /v4/Payment/<PaymentId>/PaymentState API endpoint. Depending on what happened in the payment's life cycle, there are different things to look for. This section should help you choose what checks to perform based on your integration scenario. Please read these thoroughly and perform all applying checks in your business logic when processing a callback.

Successful payment

When the customer successfully completes the payment, the payment status will be set to different values depending on the type of the payment.

  • Successful when using Immediate payments
  • Reserved when using Reservation payments

Pending payment

In delayed capture type payments, when the payment amount is blocked on the payer's payment source, the transaction's payment status is set to Authorized.

Note
An Authorized-status payment is very likely to succeed, but isn't in fact considered successful until the payee shop captures it.

Payment rejection

When the customer decides to reject payment, and return to the shop, the payment status will be set to Canceled. The payment can no longer be completed.

Finishing a Reservation payment

When the shop finishes a Reservation payment, the payment status will be set depending on the finish being partial or full.

  • if there are multiple payment transactions, but only certain one of them are being finished, the payment status will NOT change (it will stay in Reserved)
  • when every transaction in the payment has been finished, the payment status will be set to Succeeded
  • transactions finished with a lower amount than the initial reserve will result in a partial refund to the user, which shows up as a new refund transaction in the Transactions[] array of the payment state object

Capturing a Delayed Capture payment

When the shop captures a Delayed Capture payment, the payment status will be set to Succeeded, regardless of whether the authorization and capture amounts match. No refund transaction is being created in this case, because the partial capture happens directly on the bank card.

Payment expiring

When a payment expires without being completed, the payment status will be set to Expired.

  • If the payment was an ongoing Reservation payment that hasn't been finished in time, a refund will also be created, which shows up as a new refund transaction in the payment state object

Refund

When a refund is executed (via the website, or the /v2/Payment/Refund API), a new refund transaction will be added to the Transactions[] array in the payment state object. Only Succeeded payments can be refunded, and the payment status will not change during a refund, it will stay Succeeded. Barion sends a callback for successful and unsuccessful refunds as well. You have to check the refund transaction in the Transactions[] array for the result.

IMPORTANT
Different actions make different changes to the overall payment state. Never rely only on payment status changes! Always process the entire payment state object and execute your business logic accordingly.

Security

Never rely on the callback function alone. When the callback URL is requested, your application must call the /v4/Payment/<PaymentId>/PaymentState Barion API to get the proper payment state.

Please refer to the Security Measures page for more information and a list of IP addresses.

IMPORTANT
The IP address of the callback request may change any time for security reasons.

Why you should use it

When a Barion Smart Gateway payment process takes place between the two systems, neither of them can rely purely on explicit user interaction to process things. In such situations, the Barion system must inform the merchant's system that the payment has changed in some way, without involving the user.

Here are some examples:

  • the payment is completed, but the user closed their browser or lose network connection, preventing them from returning to the webshop or application that redirected them to the Barion Smart Gateway
  • the user explicitly cancels the payment, but closes their browser instead of navigating back to the merchant
  • the payment is never completed and expires because of the time window limit
  • the payment is refunded

Implementing callback handling will save you time and pain tracking such "lost" payments. It also eases the troubleshooting with your customers, since you will always have valid data on your side.

Rate limiting

To prevent potential disruptions in our service caused by the abuse of the /v4/Payment/<PaymentId>/PaymentState API endpoint, we have introduced a rate-limiting feature to throttle excessive requests. Generally, you should rely on the callback mechanism whenever possible unless you have a specific reason not to, but if you want to manually get the details of a payment, here are a couple of things to bear in mind:

  • Make sure you do not send continuous requests for the same payment even if you need to get its current state manually without waiting for the callback to happen
  • Do not keep requesting for an indefinite time, even if your requests are throttled (e.g. if a problem occurs during the payment process, and the callback never happens, you shouldn't keep polling the API indefinitely) In this case the frequency is not the problem, but as time passes these orphan requests can cause a great load together

To avoid these situations, the following throttling logic is implemented on our API:

  • During a 5 seconds window we only accept the first 2 /v4/Payment/<PaymentId>/PaymentState requests with the same payment ID. This means that if you submit two requests less than 5 seconds apart, subsequent requests will be denied until 5 seconds pass after the initial successful request. These requests will return with an HTTP 429 "Too many requests" error.
  • We keep track of requests, and if requests with the same payment ID reach a certain limit during a specific timeframe, all further requests will return HTTP 429. The exact timeframe and limits are not disclosed to the public.

To reinforce the points above, we recommend using the callback mechanism described above, and calling the /v4/Payment/<PaymentId>/PaymentState API endpoint only when there's a reason to do so.