Payment charge basics
Understand how charges are created and the role they play in the order process.
A charge object represents the amount to charge a payment source.
At the time of order creation, Digital River must request authorization from the payment provider to create a charge for the amount indicated. For credit cards, once an authorization has been approved, the charge typically remains valid for seven days.
During a charge's lifecycle, one or more capture, cancel, and refund objects can be created. When aggregated, the total amount captured, cancelled, and refunded determines how much the customer's payment method is credited or debited.
The charges contained in an order are an enduring record of all the captures cancels, and refunds that occur during an order's lifecycle.

How a charge is created

A charge object is created from a payment source. When you submit a create order request, Digital River uses sources to create one or more charges.
For example, in many checkouts, customers provide credit card information which you then use to create a primary source. Once you convert the checkout to an order, Digital River's payment services routes a charge authorization request to the appropriate payment processor. Since credit cards are synchronous payment method, the charge is typically approved immediately and returned in a capturable state.
For asynchronous payment methods that require additional customer action, the charge is typically returned in a pending state.
We recommend you listen for events that notify you when the state of a charge changes.
The charge's amount contains an initial, authorized amount charged to the customer's payment method. However, all the captures, cancellations, and refunds that are processed during an order's lifecycle ultimately determine the actual amount debited from the customer.
Order
1
{
2
"id": "178727320336",
3
...
4
"state": "accepted",
5
...
6
"charges": [
7
{
8
"id": "b469adb4-d9d1-4baa-80b1-e55c26feb4e8",
9
"createdTime": "2020-07-02T20:10:47Z",
10
"currency": "USD",
11
"amount": 145.16,
12
"state": "capturable",
13
"captured": false,
14
"refunded": false,
15
"sourceId": "9d9cff59-2b43-4b0a-a171-f49a243e5ea8"
16
}
17
],
18
...
19
}
Copied!

How captures, cancels, and refunds work

A capture object indicates that Digital River is in the process of settling an authorization. In other words, it represents how much the customer's payment source is likely to be debited. Some payment sources require that the full amount of the charge be captured at once, while others allow multiple captures.
A cancel reduces the amount available to be captured. In these cases, the customer's payment source is neither debited or credited. Whether full or partial cancellation is available depends on the underlying payment method.
And finally, a refund represents funds returned to the customer. Once funds have been captured, all or part of the captured amount can be refunded.
All three of these objects start in a pending state and then either transition to complete or failed. For each of these state transitions, a corresponding event is created.
For example, when a cancel is created by Digital River, an order.charge.cancel.pending event is emitted, eventually followed either by an order.charge.cancel.complete event or an order.charge.cancel.failed event.

Captures

Once a charge moves into a capturable state, it can be used by Digital River to create a capture. Digital River cannot capture a charge until it's in this state.
When you create a fulfillment with a specified quantity in the payload, Digital River creates a capture. We never attempt to capture the cost of an order's items until you send a POST/fulfillments with a fulfilled quantity.
The following POST/fulfillments request partially fulfills an order. Once it's submitted, you can be notified that the capture process has begun by listening for the relevant order.charge.capture.pending event.
POST/fulfillments
1
curl --location --request POST 'https://api.digitalriver.com/fulfillments' \
2
--header 'Content-Type: application/json' \
3
--header 'Authorization: Bearer <API_key>' \
4
"orderId": "178728710336",
5
"items": [
6
{
7
"itemId": "98014170336",
8
"quantity": 1
9
},
10
{
11
"itemId": "98014180336",
12
"quantity": 2
13
}
14
]
15
}'
Copied!
In this example, two separate line items were fulfilled, so the response will contain one or more captures, each with a unique identifier and captured amount.
As more of the order's goods are fulfilled, the capturedAmount provides a running total of the amount collected.
In this example, since the payment source used to create the charge is a credit card (a synchronous source) the captures briefly have a state of pending before transitioning to complete. Once a capture transitions to this state, Digital River triggers an order.charge.capture.complete event.
In this example, the charge is only partially captured, so captured is true but the order remains in an accepted state.
Order
1
{
2
"id": "178728710336",
3
...
4
"totalAmount": 145.16,
5
...
6
"state": "accepted",
7
...
8
"charges": [
9
{
10
"id": "c23d5317-3410-4abb-af86-8c8570b9dc90",
11
"createdTime": "2020-07-02T21:43:30Z",
12
"currency": "USD",
13
"amount": 145.16,
14
"state": "capturable",
15
"captured": true,
16
"captures": [
17
{
18
"id": "075224cd-0d07-440f-9c16-a17f16cb9692",
19
"createdTime": "2020-07-02T21:50:35Z",
20
"amount": 64.52,
21
"state": "complete"
22
},
23
{
24
"id": "966387d3-3693-4d35-bf8e-9f190b58e2a8",
25
"createdTime": "2020-07-02T21:50:35Z",
26
"amount": 24.2,
27
"state": "complete"
28
}
29
],
30
"refunded": false,
31
"sourceId": "9d9cff59-2b43-4b0a-a171-f49a243e5ea8"
32
}
33
],
34
...
35
"capturedAmount": 88.72,
36
"cancelledAmount": 0.0,
37
...
38
}
Copied!

Cancels

When you send a POST/fulfillments that specifies a cancelQuantity in the payload, we generate one or more cancel objects.
POST/fulfillments
1
curl --location --request POST 'https://api.digitalriver.com/fulfillments' \
2
--header 'Content-Type: application/json' \
3
--header 'Authorization: Bearer sk_test_68c0e36d7917474ca077f4c98d26050e' \
4
--header 'Cookie: visid_incap_1638494=62Z4/PTETRmkZkZ3SlxVTDpHtF4AAAAAQUIPAAAAAACGQO0FdnZ7zb8/xIqdgyAa; nlbi_1638494_1914372=Z42yObNSoGk6L2yCgd4GMQAAAABWUIZqfIBfEeL9zXoXYItv; nlbi_1638494=snJkNq6qmm2pgVfVgd4GMQAAAABsawcrSY0/mGfpdpB3gDvN; incap_ses_513_1638494=cBdber641kLOZDB65ooeB/dU/l4AAAAAYoHk9U3rNL+slY8gybF0Fg==' \
5
--data-raw '{
6
"orderId": "178728710336",
7
"items": [
8
{
9
"itemId": "98014170336",
10
"cancelQuantity": 1
11
},
12
{
13
"itemId": "98014180336",
14
"cancelQuantity": 1
15
}
16
]
17
}'
Copied!
Once the request is submitted, you can be notified that the cancel process has begun by listening for the relevant order.charge.cancel.pending event.
This example order now contains two cancel objects in the cancels array. Since the order is completely fulfilled and all possible charges have either been captured or cancelled, the order state moves to complete.
Order
1
{
2
"id": "178728710336",
3
...
4
"totalAmount": 145.16,
5
...
6
"state": "complete",
7
...
8
"charges": [
9
{
10
"id": "c23d5317-3410-4abb-af86-8c8570b9dc90",
11
"createdTime": "2020-07-02T21:43:30Z",
12
"currency": "USD",
13
"amount": 145.16,
14
"state": "processing",
15
"captured": true,
16
"captures": [
17
...
18
],
19
"refunded": false,
20
"cancels": [
21
{
22
"id": "5c13a17a-8c30-4550-be27-ddd84894b45e",
23
"createdTime": "2020-07-02T21:54:51Z",
24
"amount": 32.26,
25
"state": "complete"
26
},
27
{
28
"id": "58d9ff72-d043-4e00-9552-fb6dd8144a6c",
29
"createdTime": "2020-07-02T21:54:51Z",
30
"amount": 24.18,
31
"state": "complete"
32
}
33
],
34
"sourceId": "9d9cff59-2b43-4b0a-a171-f49a243e5ea8"
35
}
36
],
37
...
38
"capturedAmount": 88.72,
39
"cancelledAmount": 56.44,
40
"availableToRefundAmount": 88.71,
41
...
42
}
Copied!

Refunds

Refunds on the charge are contained in the refunds array. However, you should be aware that no one-to-one relationship exists between charge-level refunds and order-level refunds. This is because, for batch processing purposes, charge-level refunds are often aggregated.
The following demonstrates the distinction between charge-level refunds and order-level refunds:
Refund
Order
Charge
This GET/refunds request queries refunds by orderId.
1
curl --location --request GET 'https://api.digitalriver.com/refunds?orderId=178728710336' \
2
--header 'Authorization: Bearer <API_key>' \
Copied!
In the data array, the response returns all the order-level refunds. In this example, only a single POST/refunds request has been submitted for the order.
1
{
2
"hasMore": false,
3
"data": [
4
{
5
"id": "re_40af9cbd-0f38-4362-9e24-c6338f3795c4",
6
...
7
"items": [
8
{
9
"amount": 21.51,
10
"quantity": 1,
11
"refundedAmount": 21.51,
12
...
13
},
14
{
15
"amount": 32.26,
16
"quantity": 1,
17
"refundedAmount": 32.26,
18
...
19
}
20
],
21
"orderId": "178728710336",
22
...
23
"refundedAmount": 53.769999999999996,
24
...
25
}
26
]
27
}
Copied!
This GET/orders/{id} request retrieves the order by using its unique identifier.
1
curl --location --request GET 'https://api.digitalriver.com/orders/178728710336' \
2
--header 'Authorization: Bearer <API_key>' \
Copied!
The charges[].refunds array contains only a single element. However, despite being associated with the same order and being for nearly the same amount, this charge-level refund does not reference the same object as the order-level refund.
1
{
2
"id": "178728710336",
3
...
4
"charges": [
5
{
6
"id": "c23d5317-3410-4abb-af86-8c8570b9dc90",
7
...
8
"refunded": true,
9
"refunds": [
10
{
11
"createdTime": "2020-07-02T22:39:00Z",
12
"amount": 53.77,
13
"state": "complete"
14
}
15
],
16
...
17
}
18
...
19
}
Copied!
This GET/charges/{id} request uses the charge identifier from the order to retrieve charge details.
1
curl --location --request GET 'https://api.digitalriver.com/charges/c23d5317-3410-4abb-af86-8c8570b9dc90' \
2
--header 'Authorization: Bearer <API_key>' \
Copied!
In the response, an array of charge-level refunds is returned, each with a unique id. Note that the id of the charge-level refund is not the same as the id of the order-level refund.
1
{
2
"id": "c23d5317-3410-4abb-af86-8c8570b9dc90",
3
...
4
"orderId": "178728710336",
5
...
6
"refunded": true,
7
"refunds": [
8
{
9
"id": "5e32af54-aff5-49a8-b72e-37aa8e3d03af",
10
"createdTime": "2020-07-02T22:39:00Z",
11
"amount": 53.77,
12
"state": "complete"
13
}
14
],
15
...
16
}
Copied!
During the order lifecycle, the totalAmount of the order and the amount of the charge remain unchanged. The actual amount the payment source is debited or credited is reflected by the capturedAmount and refundedAmount, respectively.
1
{
2
"id": "178728710336",
3
...
4
"totalAmount": 145.16,
5
...
6
"refundedAmount": 53.77,
7
"state": "complete",
8
...
9
"charges": [
10
{
11
"id": "c23d5317-3410-4abb-af86-8c8570b9dc90",
12
"createdTime": "2020-07-02T21:43:30Z",
13
"currency": "USD",
14
"amount": 145.16,
15
"state": "processing",
16
"captured": true,
17
"captures": [
18
...
19
],
20
"refunded": true,
21
"refunds": [
22
{
23
"createdTime": "2020-07-02T22:39:00Z",
24
"amount": 53.77,
25
"state": "complete"
26
}
27
],
28
"cancels": [
29
...
30
],
31
"sourceId": "9d9cff59-2b43-4b0a-a171-f49a243e5ea8"
32
}
33
],
34
...
35
"capturedAmount": 88.72,
36
"cancelledAmount": 56.44,
37
"availableToRefundAmount": 34.94,
38
...
39
}
Copied!

Handling failures

When a charge authorization request fails, the object moves into a failed state. The same is true for failed capture, cancel, and refund attempts.
You can use failureMessage and failureCode to determine a reason for the failure.
For more information, refer to authorization declines and handling rejected orders.

The charge lifecycle

A charge has a defined lifecycle and can be in any one of the following states: pending, capturable, processing, complete, cancelled, or failed.
When the charge's state changes, an event is usually emitted. For example, when the charge's state changes from pending to capturable an order.charge.capturable event is emitted.
The state values for a successful charge (i.e. the happy path) are pending > capturable > processing > complete .
The following table lists the possible states of a charge and their corresponding events:
1) When the charge...
(2) the state transitions to...
(3) and an...event is emitted.
...is awaiting authorization, typically because additional customer action is required
pending
order.charge.pending
...is authorized by the payment provider
capturable
order.charge.capturable
...is being processed by the payment provider
processing
order.charge.processing
...is captured in full or captured in part with the remainder cancelled and there are no pending charge operations.
complete
order.charge.complete
...is cancelled in full and there are no pending charge operations.
cancelled
order.charge.cancelled
fails
failed
order.charge.failed
For different success and error scenarios, you can create tests to determine whether your integration returns the expected state value.
Last modified 1mo ago