Payment sessions

Learn the basics of payment sessions

A payment session tracks a transaction's payment. On this page, you'll find information on:

Why use payment sessions?

Payment sessions allow you to gain access to Drop-in payments. This solution lessens your front-end development burden. To take just one example, Drop-in payments automatically retrieves a transaction's applicable payment methods and then presents them to customers during the payment collection stage of a checkout.

Additionally, payment sessions simplify source creation. Without them, you'll need to retrieve numerous data points from the checkout and ensure they're properly formatted before passing them to createSource(). With payment sessions however you simply retrieve the checkout's payment.session.id and then pass that value to the appropriate source creation method, thereby minimizing your data transfer requirements

Payment sessions also allow you to comply with PSD2 and SCA regulations. If you reference this object when creating credit card sources, Digital River, when necessary, automatically collects a customer's authentication data.

When to use payment sessions

You can use payment sessions to:

Configure elements

The following elements all can be configured with a payment session identifier:

Retrieve available payment methods

If you're using DigitalRiver.js with elements to collect payment, you can call retrieveAvailablePaymentMethods() to get a transaction's applicable payment methods and then present them as options during checkouts.

To configure this method, retrieve the checkout's payment.session.id and pass it to sessionId.

digitalriver.retrieveAvailablePaymentMethods({
    "sessionId": "ea03bf6f-84ef-4993-b1e7-b7d5ecf71d1f"
}).then(function(result) {
    //do something with the data
});

Create sources

Both of Digital River's source creation methods can be configured with the checkout's payment.session.id. The data our payment service needs to create the source is then retrieved from that referenced object.

let configuration = {
    "sessionId": "172deb0f-de6f-4d2c-9555-53f3894b6318",
    "options": {
        "flow": "checkout",
        "showComplianceSection": true
    }, 
    onSuccess: function(data) {}, 
    onError: function(data) {}, 
    onReady: function(data) {}, 
    onCancel: function(data) {}
}
                                    
let dropin = digitalriverpayments.createDropin(configuration);
dropin.mount("drop-in");

Determine when to create orders

Before creating an order, a checkout's payment.session should be in a state of requires_confirmation and its amountRemainingToBeContributed should be 0.

Checkout
{
    "id": "8f349290-a6ec-438a-8623-ca0c6e6f65fa",
    ...
    "payment": {
        ...
        "session": {
            "id": "1403a59f-37a8-4d9e-8e13-838cf6f2a0cc",
            "amountContributed": 27.01,
            "amountRemainingToBeContributed": 0.0,
            "state": "requires_confirmation",
            "clientSecret": "1403a59f-37a8-4d9e-8e13-838cf6f2a0cc_a2a14087-2aa7-4876-b4f9-d16b5ae6817b"
        }
    }
}

Determine next action

If you create an order and its state is pending_payment, then this indicates that the charge on the primary payment sources[] isn't authorized and the goods shouldn't be fulfilled yet.

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

The payment session object

The attributes described in this section are only contained in versions 2021-03-23 and higher.

The following section provides information on a payment session object's:

Session state

A payment session has a defined lifecycle. Each stage of that lifecycle is represented by a state. When building your integration, we recommend you pay close attention to:

For a complete list of payment session state values, refer to the checkouts, orders, or invoices API reference documentation.

requires_source

If a checkout's payment.session.state is requires_source, then this indicates that either:

In both cases, Digital River won't be able to generate an aggregated amount of charges[] large enough to cover the checkout's totalAmount. As a result, the amountRemainingToContribute remains greater than 0.0 and any attempt to create an order is blocked.

requires_confirmation

When the payment session's state is requires_confirmation, then one or more sources[] have been applied to the checkout and their aggregated amount is sufficient to fund the transaction.

The checkout's payment.session.state must be requires_confirmation before you create the order.

For example, if you attach a primary source to a checkout, then the amountRemainingToContribute drops to 0.0 and the payment session's state transitions to requires_confirmation.

pending_redirect

A payment session in a state of pending_redirect indicates that customers were successfully redirected to the payment provider's portal but have yet to complete the actions necessary to authorize payment.

This state only occurs when customers choose a payment method whose resulting source has a redirect authentication flow.

If an order's payment.session.state persists as pending_redirect, then customers either selected the cancel payment option or clicked their web browser's back button.

pending_funds

A payment session state of pending_funds indicates that customers must complete an asynchronous process before payment is authorized.

This state occurs when customers choose a payment method whose resulting source has a receiver authentication flow.

For example, an order with a payment.sources[].type of konbini and a payment.session.state of pending_funds means that customers have yet to complete payment at the designated convenience store (e.g. 7-11 or FamilyMart).

pending

A pending payment session state means that customers have completed all the necessary actions (such as SCA and redirects) but certain back-end payment processes remain incomplete.

complete

Once all of an order's payment charges[] are capturable, its payment.session.state typically transitions to complete.

Amount contributed and remaining

Once you associate a primary payment sources[] with a checkout, Digital River uses it to fund the transaction in full and payment.session.amountRemainingToContribute drops to 0.0.

But when checkouts only contain secondary payment sources[], you need to confirm that sufficient funds exist to cover the checkout's totalAmount. If this isn't the case, and you convert the checkout to an order, you receive the following error:

{
    "type": "bad_request",
    "errors": [
        {
            "code": "order_submit_failed",
            "message": "Payment session status is invalid."
        }
    ]
}

By comparing values in the checkout's payment.session, you can determine how much additional funding, if any, is required. The amountContributed represents the aggregated amount of all the checkout's payment.sources[]. The amountRemainingToBeContributed is how much is needed to fund the transaction.

If amountContributed is equal to the checkout's totalAmount or the amountRemainingToBeContributed is 0.0, then you don't need to request any more payment methods from the customer, and, once the payment session's state is requires_confirmation, you can create the order.

But if amountContributed is less than the checkout's totalAmount or amountRemainingToBeContributed is greater than 0.0, then the customer needs to supply additional payment methods before you create the order. This only happens however when you have yet to associate a primary payment source with the checkout. Once that's done, amountRemainingToBeContributed drops to 0.0.

Next action

If customers opt to fund a transaction with a payment method whose resulting source has an authentication flow of redirect or receiver, then, after you associate the source with the checkout and submit the create order request, the order, in most cases, will contain payment.session.nextAction and this object's nested action will be either redirect or show_payment_instructions.

If action is redirect, then send customers to the address specified by data.redirectUrl. For details, refer to Handling redirect payment methods.

Order
{
    "id": "240354510336",
    ...
    "payment": {
        ...
        "session": {
            "id": "1b682138-ce9f-46ec-8b5e-94b710128cd9",
            ...
            "nextAction": {
                "action": "redirect",
                "data": {
                    "redirectUrl": "https://api.digitalriver.com:443/payments/redirects/3fab742c-a7e8-4a90-8951-86d071fa070d?apiKey=pk_test_a45b91ba4f984df7a229b2ab5941ce1c"
                }
            }
        }
    },
    ...
}

Migrating to payment sessions

If you collect payment by using DigitalRiver.js with elements, and you're not currently using payment sessions, but want to migrate to this solution, then the conversion process is fairly straightforward.

To collect payment, we generally recommend that you use Drop-in payments.

In the Digital River APIs, payment sessions are automatically enabled. This means that each time you create a checkout, the response contains a payment session identifier that you use to configure createSource().

Update your code

You'll need to update your code to integrate with payment sessions. For each of your enabled payment methods, add sessionId to the payload that gets passed to createSource().

You'll also need to remove some parameters. The specific parameters that must be removed depends on the payment method.

For each payment method, you can find instructions and example code in the following sections: Credit Card, PayPal, PayPal Billing, PayPal Credit, SEPA Direct Debit, Wire Transfer, Cash on Delivery - Japan, Payco - Korea Payments, Bank Transfer - Korea Payments, Online Banking - IBP, bPay, Konbini, Klarna, Klarna Recurring, TreviPay.

Credit Card

For credit cards, you add sessionId to the payload but do not remove any existing parameters.

The following tabs provide code examples of how sources are created without and with payment sessions.

var payload = {
    "type": "creditCard",
    "owner": {
        firstName: "John",
        lastName: "Doe",
        email: "john.doe@digitalriver.com",
        phoneNumber: "000-000-0000",
        address: {
            line1: "10380 Bren Road West",
            line2: "Suite 123",
            city: "Minnetonka",
            state: "MN",
            postalCode: "55343",
            country: "US"
        }
    }
}

digitalriver.createSource(cardCVV, payload).then(function(result) {
    if (result.error) {
        //handle errors
    } else {
        var source = result.source;
        //send source to back end
        sendToBackend(source);
    }
});

PayPal

For PayPal, you add sessionId to the payload and remove amount, currency, payPal.items, payPal.taxAmount, payPal.shippingAmount, payPal.amountsEstimated, payPal.requestShipping, and payPal.shipping.

The following tabs provide code examples of how sources are created without and with payment sessions.

var payload = {
    "type": "payPal",
    "amount": 120.99,
    "currency": "USD",
    "payPal": {
        "returnUrl": "http://mypage.com",
        "cancelUrl": "https://mypage.com/cancel",
        "items": [{
                "name": "Cell Phone (Unlocked)",
                "quantity": 1,
                "unitAmount": 100
            },
            {
                "name": "Headphones",
                "quantity": 1,
                "unitAmount": 15
            }
        ],
        "taxAmount": 0.99,
        "shippingAmount": 5,
        "amountsEstimated": true,
        "requestShipping": true,
        "shipping": {
            "recipient": "John Doe",
            "phoneNumber": "952-555-1212",
            "address": {
                "line1": "54321 Fake St.",
                "line2": "Apt. 3C",
                "city": "Minnetonka",
                "state": "MN",
                "country": "US",
                "postalCode": "55341"
            }
        }
    }
}


digitalriver.createSource(payload).then(function(result) {
    if (result.error) {
        //handle errors
    } else {
        var source = result.source;
        //send source to back end
        sendToBackend(source);
    }
});

PayPal Billing

For PayPal Billing, you add sessionId to the payload and remove amount, currency, payPalBilling.items, payPalBilling.taxAmount, payPalBilling.shippingAmount, payPalBilling.amountsEstimated, payPalBilling.requestShipping, and payPalBilling.shipping.

The following tabs provide code examples of how sources are created without and with payment sessions.

var payload = {
    "type": "payPalBilling",
    "amount": 120.99,
    "currency": "USD",
    "payPal": {
        "returnUrl": "http://mypage.com",
        "cancelUrl": "https://mypage.com/cancel",
        "items": [{
                "name": "Cell Phone (Unlocked)",
                "quantity": 1,
                "unitAmount": 100
            },
            {
                "name": "Headphones",
                "quantity": 1,
                "unitAmount": 15
            }
        ],
        "taxAmount": 0.99,
        "shippingAmount": 5,
        "amountsEstimated": true,
        "requestShipping": true,
        "shipping": {
            "recipient": "John Doe",
            "phoneNumber": "952-555-1212",
            "address": {
                "line1": "54321 Fake St.",
                "line2": "Apt. 3C",
                "city": "Minnetonka",
                "state": "MN",
                "country": "US",
                "postalCode": "55341"
            }
        }
    }
}


digitalriver.createSource(payload).then(function(result) {
    if (result.error) {
        //handle errors
    } else {
        var source = result.source;
        //send source to back end
        sendToBackend(source);
    }
});

PayPal Credit

For PayPal Credit, you add sessionId to the payload and remove amount, currency, payPal.items, payPal.taxAmount, payPal.shippingAmount, payPal.amountsEstimated, payPal.requestShipping, and payPal.shipping.

The following tabs provide code examples of how sources are created without and with payment sessions.

var payload = {
    "type": "payPalCredit",
    "amount": 120.99,
    "currency": "USD",
    "payPal": {
        "returnUrl": "http://mypage.com",
        "cancelUrl": "https://mypage.com/cancel",
        "items": [{
                "name": "Cell Phone (Unlocked)",
                "quantity": 1,
                "unitAmount": 100
            },
            {
                "name": "Headphones",
                "quantity": 1,
                "unitAmount": 15
            }
        ],
        "taxAmount": 0.99,
        "shippingAmount": 5,
        "amountsEstimated": true,
        "requestShipping": true,
        "shipping": {
            "recipient": "John Doe",
            "phoneNumber": "952-555-1212",
            "address": {
                "line1": "54321 Fake St.",
                "line2": "Apt. 3C",
                "city": "Minnetonka",
                "state": "MN",
                "country": "US",
                "postalCode": "55341"
            }
        }
    }
}


digitalriver.createSource(payload).then(function(result) {
    if (result.error) {
        //handle errors
    } else {
        var source = result.source;
        //send source to back end
        sendToBackend(source);
    }
});

SEPA Direct Debit

For SEPA Direct Debit, you add sessionId to the payload and remove amount and currency.

The following tabs provide code examples of how sources are created without and with payment sessions.

let payload = {
    "type": "directDebit",
    "amount": 100,
    "currency": "EUR",
    "owner": {
        firstName: "John",
        lastName: "Doe",
        email: "test@digitalriver.com",
        phoneNumber: "000-000-0000",
        address: {
            line1: "123 Main Street",
            line2: "",
            city: "Paris",
            postalCode: "14390",
            country: "FR"
        }
    },
    "directDebit": {
        "returnUrl": "https://mypage.com"
    }
}

digitalriver.createSource(payload).then(function(result) {

    if (result.error) {
        //handle errors
    } else {
        var source = result.source;
        //send source to back end
        sendToBackend(source);
    }
});

Wire Transfer

For Wire Transfer, you add sessionIdto the payload and remove amount and currency.

The following tabs provide code examples of how sources are created without and with payment sessions.

let payload = {
    "type": "wireTransfer",
    "amount": 100,
    "currency": "EUR",
    "owner": {
        firstName: "John",
        lastName: "Doe",
        email: "test@digitalriver.com",
        phoneNumber: "000-000-0000",
        address: {
            line1: "123 Main Street",
            line2: "",
            city: "Paris",
            postalCode: "14390",
            country: "FR"
        }
    },
    "wireTransfer": {
    }
}

digitalriver.createSource(payload).then(function(result) {

    if (result.error) {
        //handle errors
    } else {
        var source = result.source;
        //send source to back end
        sendToBackend(source);
    }
});

Cash on Delivery - Japan

For Cash on Delivery - Japan, you add sessionId to the payload and remove amount and currency.

The following tabs provide code examples of how sources are created without and with payment sessions.

let payload = {
    "type": "codJapan",
    "amount": 100,
    "currency": "EUR",
    "owner": {
        firstName: "John",
        lastName: "Doe",
        email: "test@digitalriver.com",
        phoneNumber: "000-000-0000",
        address: {
            line1: "123 Main Street",
            line2: "",
            city: "Paris",
            postalCode: "14390",
            country: "FR"
        }
    },
    "codJapan": {
    }
}

digitalriver.createSource(payload).then(function(result) {

    if (result.error) {
        //handle errors
    } else {
        var source = result.source;
        //send source to back end
        sendToBackend(source);
    }
});

Payco - Korea Payments

For Payco - Korea Payments, you add sessionId to the payload and remove amount and currency.

The following tabs provide code examples of how sources are created without and with payment sessions.

let payload = {
    "type": "payco",
    "amount": 100,
    "currency": "KRW",
    "owner": {
        firstName: "John",
        lastName: "Doe",
        email: "test@digitalriver.com",
        address: {
            line1: "1234 Fake Street",
            line2: "Yaum-dong",
            city: "Ulsan-si",
            state: "Kyongsangnamdo",
            postalCode: "100-011",
            country: "KR"
        }