3. Put the order on hold and confirm it

Once the shopper has provided us with enough information and we are ready to move forward, two things may happen:

  • That the order is approved, ready for fullfillment. Then the shop must confirm the order is actually being placed, ready for shipment. This should be the most common scenario.
  • That the order needs review, and has to be put on hold. Then the shop must acknowledge the order is being placed but not ready for shipment, yet. Once the order is approved, the shop must confirm it's moving forward with fullfillment.

The main purposes of this action are:

  • To make sure the customer hasn't changed the contents of the cart during the checkout process. In case there's been any changes, the process must start again.
  • And ease the logistics of the shop: confirmed orders can move forward with fullfillment while orders on hold should wait for approval.

We strive to make the time between on hold and aproval as short as possible.

For the shop to know about on hold orders that get rejected, see the Webhooks API.

Overview

For the shop to know that an order has been approved or put under review, seQura sends a callback to the shop (the IPN, Instant Payment Notification), using a URL that was provided in the first API call.

To implement IPN the shop must expose an endpoint to which seQura can POST notifications once the order is approved or needs review.

When receiving a request to that endpoint, the shop must update the order through SeQura's API (placing it on hold or confirming it) before responding to the IPN with a success status code.

The interaction looks like this when the order is approved directly:


%%{init: {
    "theme": "base",
    "themeVariables": {
        "background": "#F0F0F0"
    }
}}%%
sequenceDiagram
  participant Shop
  participant SeQura

  SeQura->>+Shop: IPN request (approved)
  activate SeQura
  
  Shop->>+SeQura: Confirm order
  SeQura-->>-Shop: Order update response
  
  Shop-->>-SeQura: IPN response
  deactivate SeQura

Or like this when the order goes first through review:

sequenceDiagram
    participant Shop
    participant SeQura

    SeQura->>+Shop: IPN request (needs review)\
    activate SeQura

    Shop->>+SeQura: Place order on hold\
    SeQura-->>-Shop: Order update response

    Shop-->>-SeQura: IPN response\
    deactivate SeQura

    SeQura->>+Shop: IPN request (approved)\
    activate SeQura

    Shop->>+SeQura: Confirm order\
    SeQura-->>-Shop: Order update response

    Shop-->>-SeQura: IPN response\
    deactivate SeQura

Configuration

In order to use the IPN workflow you must include at least the notify_url field in the merchant section of the initial API call. We suggest including a return_url to which the shopper will be redirected once the checkout is finished.

The Notify URL: The notify_url must be included in the merchant section of the initial API call. Its value should be a URL to which seQura can make a POST request to trigger the confirmation and on hold processes.

When the shop receives a request to the notify_url it needs to find the order that needs confirming in its database. seQura will include the shop's order reference (if it is known) along with its own order reference in the request and the order state in seQura (see below, IPN Request Example). If these attributes are not sufficient to find the order, the shop must include identifying parameters either in the URL or in the optional notification_parameters structure.

If you are doing an integration for a shared shop platform, we recommend that you include a digital signature in the notification_parameters so that nobody can fake a real request. See Securing the IPN call for details.

The Return URL: The return_url can be included in the merchant section of the initial API call. Its value should be a URL to which seQura can redirect the shopper (with a GET request) after the confirmation or on hold step. This is typically the URL for a page that shows an order confirmation.

If the URL contains SQ_PRODUCT_CODE, that string will be replaced with SeQura's product code before it is sent to the shopper. For instance, if the shopper uses invoicing and return_url is http://shop.example.com/checkout/confirmed?payment_method=sq-SQ_PRODUCT_CODE, the shopper will be redirected to http://shop.example.com/checkout/confirmed?payment_method=sq-i1. This allows the shop to display slightly different messages depending on the credit product that the shopper used. (For invoicing it might be useful to tell the shopper that they will receive payment instructions after the order has been sent and that they should not pay anything now.)

Processing the IPN

When seQura sends the IPN (Instant Payment Notification) to the shop, the shop should understand this as a signal from seQura that seQura is willing to guarantee the payment of the order for which the credit was solicited and that it is now OK to go ahead and place the order.

In case the order can proceed to fullfillment, the IPN will include the parameter sq_state with value approved. This tells the shop to acknowledge the order is finalised with SeQura's payment method.

In case the order needs additional manual reviewing, the IPN will include the parameter sq_state with value needs_review. This tells the shop to place the order on hold, acknowledging the order is finalised with SeQura's payment method, but not ready for fullfillment yet. Once the order is approved, the shop will receive an additional IPN with sq_state set to approved.

There are several variations to this workflow. The main differentiator is if the shop is able to carry out the work implied by an IPN or not. The different cases are described in the subsections below:

The shop handles an IPN completely

To handle an IPN completely, the shop needs to

  1. send the order data to seQura for verification,
  2. mark the order as completed or waiting for review in the shop's database,
  3. send the order reference to SeQura, if this has not been done already,
  4. respond to the IPN request with a 200 OK HTTP status.

In step 1, the merchant will make a PUT request to the URL returned in the Location header field of the initial solicitation. The merchant will send again all the order data and also will include the field state="confirmed" or state="on_hold", depending on the case.

If the order needs additional reviewing, the IPN will include the parameter sq_state="needs_review". The shop then needs to place the order on hold on their platform and include the field state="on_hold" in the PUT sent to SeQura.

If the order is ready for fullfillment, the IPN will include the parameter sq_state="approved". The shop then needs to confirm the order on their platform and include the field state="confirmed" in the PUT sent to SeQura.

SeQura will usually respond to the PUT request with a 200 OK status in which case the shop should proceed with steps 2-4. But if the order cart, delivery address, customer data or other details have changed in an unacceptable way, seQura will respond to the confirmation request with a 409 Conflict status and a JSON body detailing the problems. In this case, the shop must not complete the order in the shop's database or send the order reference to SeQura, but it must still respond to the IPN request with 200 OK.

Once the first IPN has been handled, i.e., when seQura has received the 200 OK, the shopper will be redirected to the return_url whether the order was successfully updated or not. For this reason, and because the order might be on hold or ready for fullfillment, the action handler at the return_url must check the status of the order in the shop before deciding what to display.

Problem: Order reference missing

Until the shop informs seQura of the order's order_ref_1, seQura will not be able to perform any work on the order and the merchant will not be paid for the order. seQura will follow up at least weekly on confirmed orders that don't have order_ref_1, but if the shop has recurring problems of this kind, seQura will consider this a broken integration and disconnect the service.

Problem: Order reference not unique

SeQura expects the combination (merchant.id, merchant_reference.order_ref_1) to be unique for confirmed orders. The merchant must be aware that errors in the shop might mean that an order reference is reused and that seQura will not process these orders. The error can occur in two places:

  • During step 1 above, when the shop requests seQura to confirm the order. If the shop provided the order_ref_1 at the beginning of the checkout, seQura will now check to see that the reference is unique among confirmed orders. If it isn't, seQura will respond with a 409 Conflict.
  • During step 3 above, when the shop updated the confirmed order with its order reference. Again, seQura will respond with 409 Conflict if the order_ref_1 is not unique. This case is more complicated than the former since (a) the order is confirmed in the shop with seQura as the payment method and (b) seQura is not able to process the order further.

Order should not be paid with seQura (410)

Between the start of the checkout and the IPN, the state of the shopping cart might have changed in ways that make it impossible to convert the cart to an order. For instance:

  • The shopper might have opened another browser tab and completed the order using another payment method.
  • An item in the cart might no longer be available (for the expected price, or at all).

In these cases, the shop should not confirm the order with SeQura, but instead respond to the IPN request with a 410 Gone. This will indicate to seQura that the approved credit will not be used and that any down payment should be refunded.

Once seQura has received the 410 Gone, the shopper will be redirected to the return_url.

Order cannot be found (404)

If the shop cannot find the order to be confirmed using the data in the notify_url or the request, it should respond with a 404 Not Found. seQura will assume the reason is one of the following:

  1. There has been a synchronisation delay between the storefront and the shop's backend.
  2. The shopper stayed too long in the checkout, and the unconfirmed order has been deleted from the shop.

SeQura will retry the IPN request a few times in case it is a synchronisation problem. If the 404 persists, seQura will act as if it were a 410.

Order has already been confirmed with seQura (409)

Due to communication or synchronisation errors, the shop might consider the order confirmed with seQura while SeQura's IPN service sees the order as needing confirmation. In this case, the shop should respond with a 409 Conflict which will serve as a signal to seQura to investigate.

Once seQura has received the 409 Conflict, the shopper will be redirected to an error page on SeQura's web site.

Temporary server problem (5xx)

If the shop encounters temporary server problems during IPN processing (DB unavailable, for instance), you should send a status code in the 500 series. This tells seQura to retry again later.​ seQura will retry for up to 24 hours, during which time it will not cancel the order or return the first instalment as long as the shop responds with a 5xx.​

Multi-request notification (30x)

If the shop responds with a 307 Temporary Redirect and a Location: header, seQura will make another POST call with the same data to the URL returned in the Location: header. This can be used to work around technical shortcomings in platforms like Prestashop but is not recommended if it is not necessary. In Prestashop, the call sequence becomes:

  1. seQura POSTs to the notify_url.
    • The shop PUTs the confirmation to SeQura, without order number.
    • seQura responds with 200.
    • The shop creates an order out of the shopping cart.
  2. The shop responds with 307 and a URL.
  3. seQura POSTs to the URL received in the previous step.
    • The shop PUTs the confirmation to SeQura, this time with the newly assigned order number.
    • seQura responds with 200.
  4. The shop responds with 200.

Some notes about this method:

  • The IPN accepts up to 2 redirects, i.e., it will make a maximum of 3 POST requests.
  • The URL returned in the Location: header can be the same as a previously visited URL and specifically, it can be the same as the notify_url .
  • Currently, a 302 Found can be used instead of the 307 Temporary Redirect. The use of302 is deprecated and will not be allowed in new integrations. The problem is that 302 is customarily used by web servers to signal "I want you to GET this URL", and the use of 302 sometimes creates hard-to-track bugs.
  • Other 30x codes are not accepted and will result in a failed IPN.

IPN request examples

As mentioned above, seQura includes the available order references in the IPN request. Assuming that the original API request sent by the shop contained

{
  "order": {
    "merchant": {
      "id": "...",
      "notify_url": "http://shop.example.com/ipn-me",
      "return_url": "http://shop.example.com/checkout/confirmed?payment_method=sq-SQ_PRODUCT_CODE",
    },
    "merchant_reference": {"order_ref_1": "MHPULMKOE"},
    ...

and that seQura returned a URL ending in /9201b602-94b3-4804-8ef2-080c518378ee in the Location header, the IPN request will look like this:

POST /ipn-me HTTP/1.1
User-Agent: SeQura-IPN/1.0
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 164
Host: shop.example.com

order_ref=9201b602-94b3-4804-8ef2-080c518378ee&order_ref_1=MHPULMKOE&product_code=pp3&sq_state=approved&approved_since=0

If the order needs to be put on hold, it will look like this:

POST /ipn-me HTTP?1.1
User-Agent: SeQura-IPN/1.0
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 172
Host: shop.example.com

order_ref=9201b602-94b3-4804-8ef2-080c518378ee&order_ref_1=MHPULMKOE&product_code=pp3&sq_state=needs_review&needs_review_since=0

The variable approved_since is equal to the number of seconds since seQura approved the order. It is included to facilitate debugging in cases where shops return 5xx and it is recommended that the shop log this value. It is only present once the order has been approved.

The variable needs_review_since is equal to the number of seconds since seQura requested the order to be put on hold for review. Like approved_since, it is included to facilitate debugging in cases where shops return 5xx and it is recommended that the shop log this value. It is only present if the order needs to be put on hold.

The variable product_code is included for use with our platform plugins for Magento, Prestashop, etc, and should be ignored by other integrators.
notification_parameters` key.

Securing the IPN call

Secure the IPN call by including a secure token, a short string that is hard to guess, easy to verify and only used once.

Creating a secure token: The simplest way to create a secure token is to use a cryptographic hash function and a secret salt (string which should not be known outside your application). In this example the token is the SHA1 digest of 1234:sUpErSeCrEtSaLt, i.e. the cart id, a colon and a salt.

{
  "order": {
    "merchant": {
      "notify_url": "https://my.shop.tld/checkout/sequra-ipn",
      "notification_parameters": {
        "cart": "1234",
        "token": "4207e9302d31d4fa2dbcaf9dfb45249d2581b9f8"
      },

IPs used in the IPN request

SeQura uses 3 static IPs for both sandbox and production environments, from where a request can arrive:

  • 34.253.159.179
  • 34.252.147.155
  • 52.211.243.177

Please remember that when receiving the IPN you won’t have access to the session and in case you need some data from it you will need to send it in notification_parameters.

Tips for working with the IPN in development environments

Using tunnels

If you want to integrate the IPN workflow in a development environment behind a firewall our servers won't be able to lookup your notify_url unless you expose it to the net. We recommend using ngrok to expose a specific port or sub domain.

For example you could expose port 3000 with:

$ ngrok http 3000

Ngrok will generate a unique url in order to expose the desired port. For example, if ngrok assigns you http://12345678.ngrok.io your notify_url could be http://12345678.ngrok.io/checkout/sequra-ipn.

The development / staging server doesn't have an up to date SSL certificate

The IPN expects to notify to a HTTPS url. The notify_url must be HTTPS. If the server doesn't have an up to date SSL certificate, the IPN won't proceed.
However, there is a way to bypass this limitation in the sandbox environment. Important: This won't work in production / live environment.

To use a non secure url in the notify_url field, you can prefix the url with the protocol "unverified-https://". For instance: unverified-https://my.shop.tld/checkout/sequra-ipn/8765432

How to test that an order needs to be put on hold

Checkout out the FAQ for some
options to test what may happen when an order needs to be put on hold.