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 Drop-in Checkout or Components.
If you're using Drop-in Checkout, then Digital River handles order creation. You do, however, need to listen for and respond to the checkout_session.order.created event.
With both integration paths, make sure you're set up to handle key events that occur early in an order's lifecycle.

Converting a checkout to an order

With Components, 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.
POST/orders
1
curl --location --request POST 'https://api.digitalriver.com/orders' \
2
--header 'Content-Type: application/json' \
3
--header 'Authorization: Bearer <API_key>' \
4
--data-raw '{
5
"checkoutId": "177452470336"
6
}'
Copied!
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 [email protected].
Checkout
1
{
2
"id": "856adaff-0176-4bdb-91cb-7304dfd1e7a9",
3
...
4
"email": "[email protected]",
5
...
6
}
Copied!
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.
POST/orders
Order
1
curl --location --request POST 'https://api.digitalriver.com/orders' \
2
--header 'Content-Type: application/json' \
3
--header 'Authorization: Bearer <API_key>' \
4
...
5
--data-raw '{
6
"checkoutId": "856adaff-0176-4bdb-91cb-7304dfd1e7a9",
7
"email": "[email protected]",
8
"upstreamId": "1J9F17710A6"
9
}'
Copied!
1
{
2
"id": "189917880336",
3
...
4
"email": "[email protected]",
5
...
6
"checkoutId": "856adaff-0176-4bdb-91cb-7304dfd1e7a9"
7
}
Copied!
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 Components, after you submit the 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
1
{
2
"type": "conflict",
3
"errors": [
4
{
5
"code": "failed-request",
6
"message": "Failed to charge source."
7
}
8
]
9
}
Copied!
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.

Events early in an order's lifecycle

With both Drop-in Checkout and Components, your integration should subscribe to 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.
For more information, refer to handling accepted orders.

The order cancelled event

When an order's state becomes cancelled, Digital River creates an order.cancelled event. The event’s data.object contains a cancelled order.
Since the event is not currently configured to provide a reason for the cancellation, cancelReason is not populated.

Event origins

Depending on how you build your integration, the order.cancelled event may have multiple origins. For example, if your site contains a cancel order button, then order.cancelled may originate with customers requesting to cancel their order.
If you're using Digital River's fulfillment service, this button’s click event handler should trigger a POST/fulfillment-cancellations that requests to fully cancel each of a fulfillment order's line items.
For more information, refer to cancelling physical fulfillments.
If your integration allows customers to submit line-item level cancellation requests (as opposed to the more standard full order cancellations), you can’t always use order.cancelled as the event that triggers a cancellation complete notification to customers. This is because, once an order is accepted, it doesn't become cancelled until the state of all of its payment.charges[] is also cancelled.
The order.cancelled event could also be triggered when customers fail to transfer payment by a designated date and time and, as a result, the source expires. This applies to wire transfers, Konibini payments, and other type(s) of sources with a payment flow of receiver.
For example, in checkouts whose primary source type is wireTransfer, once you successfully convert the checkout to an order, the order typically moves into a state of pending_payment. When handling this order state change event, you should provide instructions to customers on how to provide payment.
If customers don't push the funds within the allotted time, then the source expires, no charge authorization is created and the order.cancelled event is fired. In this scenario, since no charge is created, you won’t receive any order charge related events.

Handling the order.cancelled event

Upon receiving the order.cancelled event, 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

Handling order state changes

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

Handling pending payment orders

An order that is pending_payment indicates that a payment charge has not yet been authorized. Orders in this state should not be fulfilled.
Instead, from the payload of either the POST/orders response or the order.pending_payment event, retrieve the payment.sources[].id of the order's primary payment source.
order.pending_payment
1
{
2
"id": "65beb271-e660-444d-8919-69c991d63d6d",
3
"type": "order.pending_payment",
4
"data": {
5
"object": {
6
"id": "196623140336",
7
...
8
"payment": {
9
"sources": [
10
{
11
"id": "f853f415-7f85-4695-bd93-7f479efdc4a8",
12
"type": "wireTransfer",
13
"amount": 11.33,
14
...
15
"wireTransfer": {
16
"accountHolder": "Global Collect BV",
17
"bankName": "Rabobank N.A.",
18
"city": "Ontario",
19
"country": "US",
20
"referenceId": "890701505439",
21
"accountNumber": "0487369908",
22
"swiftCode": "RABOUS66XXX"
23
}
24
}
25
],
26
"session": {
27
"id": "affcead4-92b4-425d-b995-3ebb3fc046f8",
28
"amountContributed": 11.33,
29
"amountRemainingToBeContributed": 0.0,
30
"state": "pending_funds",
31
"clientSecret": "affcead4-92b4-425d-b995-3ebb3fc046f8_1773afaa-5bb3-4668-b466-b5a49b63653b"
32
}
33
},
34
"state": "pending_payment",
35
...
36
"checkoutId": "ab3b00eb-5f32-4c84-8ef3-dc659016d502"
37
}
38
},
39
...
40
"digitalriverVersion": "2021-03-23"
41
}
Copied!
Send this value as a path parameter in a GET/sources/{id} request. From the response, retrieve the source's clientSecret.
Source
1
{
2
"id": "f853f415-7f85-4695-bd93-7f479efdc4a8",
3
"createdTime": "2021-08-23T02:24:02Z",
4
"type": "wireTransfer",
5
...
6
"clientSecret": "f853f415-7f85-4695-bd93-7f479efdc4a8_abec5143-4f72-486c-b377-34d31ddb3c13",
7
"wireTransfer": {
8
"accountHolder": "Global Collect BV",
9
"bankName": "Rabobank N.A.",
10
"city": "Ontario",
11
"country": "US",
12
"referenceId": "74243814931",
13
"accountNumber": "5215726630",
14
"swiftCode": "RABOUS29XXX"
15
},
16
"liveMode": false
17
}
Copied!
Then use both the source's id and clientSecret to configure the delayed payment instructions element on your front end.
1
let options = {
2
"sourceId": "f853f415-7f85-4695-bd93-7f479efdc4a8",
3
"sourceClientSecret": "f853f415-7f85-4695-bd93-7f479efdc4a8_abec5143-4f72-486c-b377-34d31ddb3c13"
4
}
5
6
let delayedPaymentInstructions = digitalRiver.createElement('delayedpaymentinstructions', options);
Copied!
Ensure that the element is mounted on an appropriate page on your site.
1
<div id="delayed-payment-container"></div>
2
...
3
delayedPaymentInstructions.mount("delayed-payment-container");
Copied!
You can optionally configure the element to listen for the ready event. This event signifies that the delayed payment instructions have been loaded in the specified container.
1
delayedPaymentInstructions.on('ready', function(event) {
2
//delayed payment instructions element is ready
3
});
Copied!
You can then direct customers to the page that contains the element with the populated instructions.
These instructions usually inform customers of the number of days that they have to push payment.
1
<div id="delayed-payment-container">
2
<div id="delayedpaymentinstructions-c4906e5d-bcc4-482d-aa23-24775f73f035" class="DR-delayed-payment-instructions-container">
3
<p>Thank you for your order. Please pay at a local branch of the store that you selected.<br><br>The payment will be processed by Digital River, K.K. on our behalf.<br><br>Your order will not be available or shipped until payment has been received and processed.</p>
4
<p id="DR-konbiniAmountAndReferenceId">
5
<strong>Amount:</strong> 30.00 USD
6
<br>
7
<strong>Reference Number:</strong> 100001
8
<br>
9
<strong>Store:</strong> セブン‐イレブン
10
<br>
11
</p><p>Please verify your order, and complete payment within 7 days after your order date. <br><br>As soon as the payment is received and confirmed, the product will be made available or shipped. <br><br></p>
12
<p></p>
13
14
</div></div>
Copied!
If customers follow the instructions and the charge on the payment source is authorized, your integration will receive the order.accepted event. If they don't make payment within the allotted time, you receive order.cancelled.

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 is accepted, move the commerce platform's order into a ready to fulfill state.
Depending on whether the order is synchronously or asynchronously accepted, you should also either direct customers to an order confirmation page or inform them (typically by email) that their order has been accepted.
At this point, fulfillment operations can be initiated.

The order object

The following looks at some of the key attributes in an order and how you might use them in downstream requests. For a complete list, refer to the Orders API reference documentation.

Unique identifier

Order
1
{
2
"id": "177452480336",
3
...
Copied!

Ship to values

An order's shipTo values are displayed on invoices and credit memos.
1
...
2
"customerId": "987654321",
3
...
4
"shipTo": {
5
"address": {
6
"line1": "10380 Bren Rd W",
7
"line2": "string",
8
"city": "Minnetonka",
9
"postalCode": "55129",
10
"state": "MN",
11
"country": "US"
12
},
13
"name": "Jane Doe",
14
"phone": "952-111-1111",
15
"email": "[email protected]",
16
"organization": "Digital River"
17
},
Copied!

Amounts, fees, and taxes

The order's total amount, fees, taxes, and other costs are the same as those presented to customers when they confirmed the purchase. You can retrieve these values and display them to customers on their order confirmation page.
1
...
2
"totalAmount": 177.67,
3
"subtotal": 172.5,
4
"totalFees": 0.0,
5
"totalTax": 5.17,
6
"totalDuty": 0.0,
7
"totalDiscount": 7.5,
8
"totalShipping": 5.0,
9
...
Copied!

Line items

Digital River assigns each of an order's items[] a unique id. You need this identifier when capturing and cancelling payments, handling third-party returns, and issuing refunds.
Depending on how you send product data in checkouts, each of an order's items[] also contains either a skuId or a productDetails object.
In addition, these items[] store detailed price, tax, and quantity information that you can display to customers on order confirmation and order detail pages.
For more information on subscriptionInfo, refer to the Subscription information page.
1
...
2
"items": [
3
{
4
"id": "96415480336",
5
"skuId": "08141946",
6
"amount": 100.0,
7
"quantity": 1,
8
"state": "created",
9
"stateTransitions": {
10
"created": "2020-05-21T17:26:34Z"
11
},
12
"tax": {
13
"rate": 0.0,
14
"amount": 0.0
15
},
16
"subscriptionInfo": {
17
"billingAgreementId": "cfeba2ac-d532-49e4-99f4-7a433507facf",
18
"terms": "Insert terms here",
19
"autoRenewal": true,
20
"freeTrial": false
21
}
22
},
23
{
24
"id": "96415490336",
25
"skuId": "05081978",
26
"amount": 67.5,
27
"quantity": 1,
28
"discount": {
29
"percentOff": 10.0,
30
"quantity": 1
31
},
32
"state": "created",
33
"stateTransitions": {
34
"created": "2020-05-21T17:26:34Z"
35
},
36
"tax": {
37
"rate": 0.07125,
38
"amount": 4.81
39
}
40
}
41
],
42
...
Copied!

Tax invoices and credit memos

In most cases, Digital River populates an order's invoicePDFs and creditMemoPDFs with information that you can use to access and share tax invoice and credit memo files.
1
...
2
"invoicePDFs": [
3
{
4
"url": "https://api.digitalriver.com/files/23c7e1a5-25e4-41a9-b935-eda98dfa238b/content",
5
"id": "23c7e1a5-25e4-41a9-b935-eda98dfa238b"
6
}
7
],
8
"creditMemoPDFs": [
9
{
10
"url": "https://api.digitalriver.com/files/5cec4a32-853f-485a-90a0-15ea0a614355/content",
11
"id": "5cec4a32-853f-485a-90a0-15ea0a614355"
12
}
13
],
14
...
Copied!

State and fraud state

For more information about an order's state and fraudState, refer to the Order lifecycle page.

Tax identifiers

Orders with applied tax identifiers contain an array of tax identifier objects.
JSON
1
...
2
"taxIdentifiers": [{
3
"id": "a6809a63-e6a9-4016-abbc-f33d19fccb5b",
4
"customerId": "5774321009",
5
"type": "uk",
6
"value": "GB000283536",
7
"state": "verified",
8
"stateTransitions":
9
{"pending": "2020-05-13T11:00:00.000Z", "verified": "2020-05-15T16:00:00.000Z"},
10
"verified_name": "Descon Ltd",
11
"verified_address": "Design House, 18b Tromode, Isle of Man",
12
"createdTime": "2020-08-01T02:25:53Z",
13
"updatedTime": "2020-08-01T05:47:21Z"
14
}],
15
...
Copied!

Charges

An order's charges array contains one or more elements, each representing a charge created from a primary or secondary payment source. Each charge contains a unique identifier, an amount, a state, and the identifier of the payment source used to create the charge.
1
...
2
"charges": [
3
{
4
"id": "d3a02b03-1378-431e-81a5-9cb6dd54d90b",
5
"createdTime": "2020-05-21T17:26:37Z",
6
"currency": "USD",
7
"amount": 177.67,
8
"state": "capturable",
9
"captured": false,
10
"refunded": false,
11
"sourceId": "deabb3a4-14e4-4702-a13b-ddaac23277d3"
12
}
13
],
14
...
Copied!

Request to be forgotten

An order's requestToBeForgotten indicates whether an order's data is scheduled for deletion. This is the only attribute (other than metadata) that can be modified in an update order request.
1
...
2
"requestToBeForgotten": false,
3
...
4
}
Copied!

Updating an order

Besides metadata, the only order attribute that you can update is requestToBeForgotten.
To update an order, submit a POST/orders/{id} request and pass in the order identifier as a path parameter. If the customer has requested that the order be forgotten, then set the requestToBeForgotten parameter to true.

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:
JSON
1
{
2
"type": "not_found",
3
"errors": [
4
{
5
"code": "not_found",
6
"parameter": "orderId",
7
"message": "Order 180139250336 not found"
8
}
9
]
10
}
Copied!

Using a registered customer to create an order

We strongly recommend that your integration convert checkouts to orders.
You do, however, have the ability to submit a POST/orders that omits checkoutId, thereby bypassing the Checkouts API. In this case, the request should contain a registered customer and a reusable payment source saved to that customer's account. The POST/orders must also meet all currency, address, shipping method, product, and payment session requirements.
POST/orders
1
curl --location --request POST 'https://api.digitalriver.com/orders' \
2
--header 'Content-Type: application/json' \
3
--header 'Authorization: Bearer <API_key>' \
4
...
5
--data-raw '{
6
"customerId": "534313260336",
7
"currency": "USD",
8
"taxInclusive": false,
9
"email": "[email protected]",
10
"shipTo": {
11
"address": {
12
"line1": "10380 Bren Road W",
13
"city": "Minnetonka",
14
"postalCode": "55343",
15
"state": "MN",
16
"country": "US"
17
},
18
"name": "John Doe"
19
},
20
"shipFrom": {
21
"address": {
22
"country": "US"
23
}
24
},
25
"shippingChoice": {
26
"amount": 5,
27
"description": "standard",
28
"serviceLevel": "SG"
29
},
30
"items": [
31
{
32
"skuId": "aa4dbf0c-2336-4b9c-8cff-5d12664b8266",
33
"quantity": 2,
34
"price": 10
35
}
36
]
37
}'
Copied!