Processing orders

Learn the basics of processing an order

Once customers are done checking out, how an order is created depends on whether you integrate with Prebuilt Checkout, Components, or Direct integrations.

If you're using Direct Integrations, first convert the checkout to an order and then handle the immediate response and/or key events that occur early in an order's lifecycle.

If you're using Prebuilt Checkout, then Digital River handles order creation. You should, however, configure a webhook(s) to listen for events with a type of checkout_session.order.created, order.accepted and order.cancelled.

However, no matter which integration option you select, make sure you're set up to process:

For a list of important webhook events that most integrations should subscribe to, refer to Key event types.

Converting a checkout to an order

With Direct Integrations, once the checkout's address and payment requirements are met and customers have reviewed and submitted their order, you should pass checkoutId in the body of a POST /orders.

curl --location --request POST 'https://api.digitalriver.com/orders' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <API_key>' \
--data-raw '{
    "checkoutId": "177452470336"    
}'

This request primarily serves to authorize payment. Once submitted, your integration should be set up to process the immediate response as well as respond to key events.

You can submit a POST /orders whose payload contains checkoutId plus additional parameters (provided they adhere to the request's data contract). But, when processing the request, Digital River ignores this additional data. So, if you'd like to update the checkout, you must do so prior to submitting a POST /orders.

For example, the following checkout's email address is johndoe@digitalriver.com.

{
    "id": "856adaff-0176-4bdb-91cb-7304dfd1e7a9",
    ...
    "email": "johndoe@digitalriver.com",
    ...
}

If you submit a POST /orders that contains the checkout's identifier, an updated email, and also adds an upstreamId that identifies the order in your system, then the response contains a 201 Created status code. However, email is not updated and upstreamId is not populated.

curl --location --request POST 'https://api.digitalriver.com/orders' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <API_key>' \
...
--data-raw '{
    "checkoutId": "856adaff-0176-4bdb-91cb-7304dfd1e7a9",
    "email": "janedoe@digitalriver.com",
    "upstreamId": "1J9F17710A6"
}'

Although not the preferred approach, you can omit checkoutId in a POST /orders and, instead, create an order with a registered customer's identifier.

Handling the POST /orders response

If you're using Direct Integrations, after you submit a POST/orders (assuming all upstream checkout requirements have been met), the response will contain a 409 Conflict or 201 Created status code.

When handling this immediate response, you need to capture specific data from its payload and use it to update the status of your commerce system. This ensures that downstream fulfillment operations are correctly handled.

409 Conflict

A 409 Conflict status code indicates that Digital River did not create an order, either due to a payment authorization failure or suspected fraud. The error's code and message contain more specific information about what triggered the failure.

Error
{
    "type": "conflict",
    "errors": [
        {
            "code": "failed-request",
            "message": "Failed to charge source."
        }
    ]
}

Use this error information to update the upstream order's overall status, payment status, and fraud status.

You can also use the error's message to inform end customers of the problem. Do not, however, share code. Doing so may aid parties that are attempting to carry out fraudulent or malicious activities.

For more details on how to process responses with a 409 Conflict status code, refer to the Handling rejected orders page.

201 Created

A 201 Created status code indicates an order's state is pending_payment, in_review, or accepted.

From the response's payload, retrieve the order's id, state, fraudState, and charges[].state, and use these values to update the corresponding attributes in the upstream commerce platform's order.

Pending payment

If an order's state is pending_payment, then the fraud review process has been successfully completed but the payment charge is not yet authorized. For more details, refer to handling pending payment orders.

In review

If an order's state is in_review, then this indicates that Digital River is conducting a secondary fraud review. For more information, refer to handling in review orders.

Accepted

If an order's state is accepted, then the transaction has successfully passed fraud review and the payment charge is authorized. For more information, refer to handling accepted orders.

Whether you're using Drop-in Checkout, Low-code components or Direct integrations, you'll need to configure webhooks to listen for some key events that occur early in an order's lifecycle.

These events notify you of:

Each time you're notified of one of these events, retrieve the order's state, fraudState, and charges[].state (if available) from its payload, and use this data to update the corresponding attributes in the upstream commerce system's order.

The charge authorization failure event

An asynchronous charge authorization failure triggers an order.charge.failed event.

If you receive this event, you can iterate over the order's payment.charges[] and inspect them for a failure code or message. The failureMessage however is not always available. But when it is, you can use it to provide more specific payment failure information to customers.

Do not display the failureCode to end customers. Doing so potentially aids malicious and fraudulent actors.

The fraud block event

When Digital River detects an anomaly during its fraud review, or we determine that the customer is on the Denied Persons List, we create an order.blocked event. The payload of this event consists of an order whose state is blocked. The order's fraudState is also blocked. Since these are both terminal states, you should inform end customers that the transaction has failed.

The pending charge authorization event

An order.pending_payment event indicates that Digital River detected no fraudulent activity during its fraud review. However, don't use this event as a trigger to initiate fulfillment operations. This is because the order's payment.charges[] are not yet fully authorized.

For more information, refer to handling pending payment orders.

The in-process fraud review event

An order.review_opened event indicates that Digital River is conducting a secondary fraud review and has moved the order's state to in_review. Since the fraud review process is not yet complete, don't use this event as a trigger to initiate fulfillment operations.

For more information, refer to handling in review orders.

The order accepted event

When all of an order's payment.charges[] are authorized and no irregularities are detected during the fraud review, Digital River creates an order.accepted event. Respond to this event by moving the commerce platform's order into a ready to fulfill state.

Unless you synchronously receive an order in an accepted state, your integration should wait until it receives order.accepted before initiating fulfillment operations. Doing so reduces the risk of fraud and the frequency of disputes and chargebacks.

In the data.object of the expanded version of order.accepted, you can use physical in each items[].productDetails to determine whether that product is classified as physical or digital. If physical is true, then the product needs to be shipped to the customer. As a result, you should pass its details in an ship request to your fulfillment service. Otherwise, if false, then the product is a digital item and should be delivered to the customer via email or some other digital channel.

For more information, refer to handling accepted orders.

The order cancelled event

When an order's state moves to cancelled, Digital River creates an event whose type is order.cancelled and whose data.object contains that order.

If you decide to build your integration so that customers can submit line-item level cancellation requests (as opposed to the more standard full order cancellations), then you can’t always use order.cancelled to trigger notifications that inform customers their request was successfully processed. This is due to the fact that an order's state doesn't move to cancelled until the state of all of its payment.charges[] is also cancelled.

You should also be aware that order.cancelled is often created when customers fail to transfer payment by a designated date and time. This applies to wire transfers, Konibini, and other type(s) of sources that have a flow of receiver.

For example, after an order with a primary source type of wireTransfer is created, that order's state typically becomes pending_payment. As a result, customers are provided instructions on how to authorize payment. For details, refer to Handling pending payments.

If these instructions aren't followed (i.e., the funds aren't pushed within the allotted time), then the source expires, no charge authorization is created, and Digital River creates order.cancelled.

For more details, refer to Handling cancelled orders.

Handling order state changes

The following provides information on how to handle pending payment, in review, accepted, cancelled orders.

Handling pending payment orders

If an order's state is pending_payment, then the charge on the primary payment sources[] is not yet authorized and the order's goods should not be fulfilled.

To handle this state change event, determine the value of the order's payment.session.nextAction.action.

Handling in review orders

Orders that are in_review should not be fulfilled. After an order transitions out of this state, Digital River creates either order.accepted or order.blocked. So make sure your integration is set up to handle both of these events.

Handling accepted orders

When an order's state becomes accepted, move the order in your system into a ready to fulfill state.

Depending on whether the order is synchronously or asynchronously accepted, you should also redirect customers to an order confirmation page and/or send them an order confirmation notification.

At this point, fulfillment operations can be initiated.

Handling the order.cancelled event

Upon receiving the event with a type of order.cancelled, we recommend that you:

  • Update the master order record in your system

  • Notify customers (typically by email) that their order has been successfully cancelled and no payment was collected. In the email, we suggest you provide:

    • The order number

    • The order cancellation date (you can retrieve this information from the order's stateTransitions.cancelled attribute)

    • An itemization of the cancelled goods

    • The payment method used by the customer

    • The total amount cancelled

    • The customer’s billing address

    • Your contact information

Reusing the checkout identifier

If you attempt to pass a checkoutId in a POST /orders request, and that Checkout has already been consumed by a different POST /orders request, you'll get back a response with a 404 Not Found status:

{
    "type": "not_found",
    "errors": [
        {
            "code": "not_found",
            "parameter": "orderId",
            "message": "Order 180139250336 not found"
        }
    ]
}

Last updated