Handling subscription acquisitions

If you're pairing the Direct Integration solution with Digital River's subscription service, learn how to handle acquisitions.

If you're pairing the Direct Integrations checkout solution with Digital River's subscription service, this page explains how to process it:

Once you convert the checkout to an order, you'll also need to activate the subscription, fulfill the goods, and manage renewals. For details on handling these and other processes, refer to the Managing a subscription page.

Subscription acquisitions

During subscription acquisitions, you must:

Creating a subscription

In checkouts, you define subscriptions in items[]. Checkouts can contain either a single items[] with subscriptionInfo or multiple subscription line items. We also support mixed cart checkouts.

For each items[].subscriptionInfo in the request:

  • Use planId to associate the subscription with a plan. For details, refer to Defining a business model.

  • Pass terms. To do this, make a GET /plans/{planId} request. From the response, retrieve the plan's terms and use that value to set the line item's terms. If you don't send terms, a 400 Bad Request with a code of missing_parameter is thrown.

  • Set autoRenewal to true or omit the value. If you set autoRenewal to false, you receive a 400 Bad Request with a code of invalid_parameter.

  • Use freeTrial to set up trial periods. For details, refer to Trial subscription acquisitions.

  • If you don't provide a unique subscriptionId, we generate one for you.

In subscription acquisitions, make sure you also set the checkout's chargeType to customer_initiated.

curl --location --request POST 'https://api.digitalriver.com/checkouts' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <API_key>' \
...
--data-raw '{
	"customerId": "0aa4bb94-2995-4689-9b57-f11d1beb18c9",
	"sourceId": "586ffca0-ca4f-4d87-a933-192afa36cc6b",
	"locale": "en_US",
	"email": "jsmith123@digitalriver.com",
	"currency": "USD",
	"items": [{
			"skuId": "d273122b-e78d-4fcb-a1ab-10c07c871ee7",
			"quantity": 5,
			"price": 5.01,
			...
			"subscriptionInfo": {
				"planId": "460d1943-5ac1-48b8-98e8-237c6e3019a7",
				"terms": "These are the terms...."
			},
			"metadata": {
				"key1_ItemLevel": "tets"
			}
	}],
	...
}'

Checkouts with multiple subscriptions

Checkouts can contain multiple items[] with subscriptionInfo. All the recurring items however must share the same planId and (if you set your own value) subscriptionId. Once you submit the request, Digital River adds these line items to a single subscription.

If you attempt to create checkouts with multiple items[] that reference different plans, then the following error is returned:

{
    "type": "conflict",
    "errors": [
        {
            "code": "plan_limit_reached",
            "parameter": "planId",
            "message": "Only one unique subscription plan can be supported in a checkout"
        }
    ]
}

Checkouts with subscription and non-subscription items

Digital River's subscription service supports building checkouts that contains both subscription and non-subscription line items and then successfully converting those checkouts to orders. The subscription line items, however, must all reference the same plan.

A common use case for these types of mixed checkouts is to process transactions that combine a one-time physical product with a digital subscription service.

Handling the acquisition checkout response

After you submit the POST/ checkouts request, Digital River creates a subscription, sets its to state to draft and then generates an event with a type of subscription.created.

In the response's body and the event's data.object, the subscriptionId uniquely identifies that subscription. At a minimum, make sure you persist this value.

At this point, no additional subscription line items can be added to the checkout. Furthermore, you're restricted to what product information can be updated.

Since Digital River's subscription service doesn't support manual renewals, autoRenewal always returns true .

For details on how to handle manual renewals, where you invite customers to actively renew subscriptions at a designated time, refer to the Third party subscription services page.

{
    "id": "88aaf811-a8a8-4b7a-9a23-5bc0241e039a",
    "createdTime": "2021-08-11T20:06:32Z",
    "customerId": "0aa4bb94-2995-4689-9b57-f11d1beb18c9",
    "currency": "USD",
    "email": "jsmith123@digitalriver.com",
    "billTo": {
        "address": {
            "line1": "10380 Bren Road West",
            "city": "Minnetonka",
            "postalCode": "55343",
            "state": "MN",
            "country": "US"
        },
        "name": "Digital Development",
        "email": "testdummy@digitalriver.com",
        "organization": "DR",
        "additionalAddressInfo": {
            "neighborhood": "Centro"
        }
    },
    "totalAmount": 26.9,
    "subtotal": 25.05,
    "totalFees": 0.0,
    "totalTax": 1.85,
    "totalImporterTax": 0.0,
    "totalDuty": 0.0,
    "totalDiscount": 0.0,
    "totalShipping": 0.0,
    "items": [
        {
            "id": "b0ae5bf9-6df7-4185-91f2-7e2589acbe8d",
            "skuId": "d273122b-e78d-4fcb-a1ab-10c07c871ee7",
            "amount": 25.05,
            "quantity": 5,
            "metadata": {
                "key1_ItemLevel": "tets"
            },
            "tax": {
                "rate": 0.07375,
                "amount": 1.85
            },
            "importerTax": {
                "amount": 0.0
            },
            "duties": {
                "amount": 0.0
            },
            "subscriptionInfo": {
                "subscriptionId": "192a2549-8b16-482e-b1bb-b4a64cd6a0c0",
                "planId": "460d1943-5ac1-48b8-98e8-237c6e3019a7",
                "terms": "Please accept terms",
                "autoRenewal": true,
                "freeTrial": false
            },
            "fees": {
                "amount": 0.0,
                "taxAmount": 0.0
            }
        }
    ],
    "updatedTime": "2021-08-11T20:06:32Z",
    "locale": "en_US",
    "customerType": "individual",
    "sellingEntity": {
        "id": "C5_INC-ENTITY",
        "name": "DR globalTech Inc."
    },
    "liveMode": false,
    "payment": {
        "sources": [
            {
                "id": "586ffca0-ca4f-4d87-a933-192afa36cc6b",
                "type": "creditCard",
                "amount": 26.9,
                "owner": {
                    "firstName": "Digital",
                    "lastName": "Development",
                    "email": "testdummy@digitalriver.com",
                    "address": {
                        "line1": "10380 Bren Road West",
                        "city": "Minnetonka",
                        "postalCode": "55343",
                        "state": "MN",
                        "country": "US"
                    },
                    "organization": "DR",
                    "additionalAddressInfo": {
                        "neighborhood": "Centro"
                    }
                },
                "creditCard": {
                    "brand": "Visa",
                    "expirationMonth": 7,
                    "expirationYear": 2027,
                    "lastFourDigits": "1111"
                }
            }
        ],
        "session": {
            "id": "9fb4036f-5051-4255-9189-16e449d69ca6",
            "amountContributed": 26.9,
            "amountRemainingToBeContributed": 0.0,
            "state": "requires_confirmation",
            "clientSecret": "9fb4036f-5051-4255-9189-16e449d69ca6_3c6275e8-e065-4bb9-b75a-829f62b78c2c"
        }
    }
}

At this stage of the acquisition process, if you retrieve the subscription, you'll notice that key fields have yet to be populated. This is because the subscription's state is still draft and the contractBindingUntil, nextReminderDate, currentPeriodEndDate, and nextInvoiceDate are generated when you activate the subscription.

{
    "id": "7f784dd8-a76f-4d3a-84e1-abdc9c7ac3b9",
    "createdTime": "2022-02-07T14:02:46Z",
    "updatedTime": "2022-02-07T14:02:46Z",
    "stateTransitions": {},
    "taxInclusive": false,
    "currency": "USD",
    "planId": "82cbf763-fa27-401a-aa69-5e6640539ce7",
    "state": "draft",
    "items": [
        {
            "price": 100.0,
            "skuId": "bd933514-43fa-40d3-863c-8ff6fce0db76",
            "quantity": 1
        }
    ],
    "liveMode": false
}

During acquisitions, you must disclose a subscription's terms and then acquire the customer's active acceptance of them. How you do this depends on whether you're using Drop-in payments or DigitalRiver.js with elements. In either case, the plan's terms should match those displayed to customers.

For details on required disclosures, see the Subscriptions and Auto-Renewal Considerations article (refer to Learning tools for access information).

A subscription's terms are displayed in the modal window if you're using Drop-in payments. For details, see the Acquiring payment section on this page.

After you convert an acquisition checkout to an order, the subscription's terms are stored in the billing agreement.

Acquiring payment

During acquisition checkouts, you can give customers the option to:

Creating a new payment source

How you create a payment source to fund a recurring transaction depends on whether your integration uses Drop-in payments or DigitalRiver.js with elements.

For more details, refer to the subscriptions section on the Building payment workflows page.

After building a checkout with subscription information, configure createDropin():

let digitalriverpayments = new DigitalRiver("pk_hc_a209389e4588433bb6e00b32466b82c3", {
    "locale": "en_US"
});

let configuration = { 
    "sessionId": "2bc96772-1142-4289-9d20-f6905591d7e4",
    "options": {
        "flow": "checkout",
        "showComplianceSection": true,
        "showSavePaymentAgreement": false,
        "showTermsOfSaleDisclosure": true,
        "usage": "subscription"
    }
    ...
}

let dropin = digitalriverpayments.createDropin(configuration);
dropin.mount("drop-in-container");

Pass the configuration object to createDropin()and mount Drop-in payments in the appropriate container. If the request is successful, onReady returns the transaction's eligible payment methods:

{
    "paymentMethodTypes": [
        "creditCard",
        "payPalBilling",
        "googlePay",
        "klarnaCreditRecurring",
        "msts"
    ]
}

Each payment method, accompanied by the subscription's terms and conditions, is displayed in the modal window.

If customers click the configurable continue button without agreeing to the terms, Drop-in prevents the transaction from proceeding.

If customers consent to the terms and submit their payment information and the resulting create source request is successful, then the onSuccess event's data contains a source that is readyForStorage and chargeable. The object also contains the agreed-upon terms (mandate.terms) and the time the customer accepted those terms (mandate.signedTime).

For details, refer to the Drop-in payments integration guide and the Drop-in payments builder tool.

Next, send the customer identifier and source to your back-end.

Submit a POST /customers/{customerId}/sources/{sourceId} to attach the source to the customer. This flips the source's reusable attribute to true, meaning the object can be used in both the subscription's acquisition and as the designated source in renewals.

Once saved to the customer, your integration should then attach the source to the checkout.

You should also retrieve mandate.terms from the source and use this value to set each of the checkout's items[].subscriptionInfo.terms. This ensures that the subscription's terms are added to the billing agreement.

Authenticating a saved payment source

Drop-in payments does not currently support retrieving saved payment methods.

If you give customers the option to select a saved payment source during subscription acquisitions, then after building a checkout with subscription information, send the payment session identifier to your front end and use it to set sessionId in the configuration object of retrieveAvailablePaymentMethods().

...
digitalRiver.retrieveAvailablePaymentMethods({
    "sessionId": "1c86a97f-45ea-4d73-8c99-ca533e392ab1"
}).then(function(result) {
    //do something with the result
    console.log(result)
});
...

For each payment method contained in the response, determine if its type matches the type of one or more of the customer's sources[]. If it does, you can retrieve those saved sources[] from the customer and display them as options on your payments page.

If the customer selects a saved source, pass its sources[].id and sources[].clientSecret (along with the checkout's payment session identifier) to authenticateSource(). This method determines whether strong customer authentication is required.

{
    "id": "533319260336",
    ...
    "sources": [
        {
            "id": "5e359d60-1d23-4234-84ee-e1c9b3ed7edc",
            ...
            "type": "creditCard",
            "reusable": true,
            "state": "chargeable",
            ...
            "clientSecret": "5e359d60-1d23-4234-84ee-e1c9b3ed7edc_bf74c04c-8586-41e2-964a-f5e618d2b7e3",
            ...
        },
        {
            "id": "19f47eba-418f-41b3-882c-462e335770e7",
            ...
            "type": "payPalBilling",
            "reusable": true,
            "state": "chargeable",
            ...
            "clientSecret": "19f47eba-418f-41b3-882c-462e335770e7_cc871d23-474d-4a3f-9803-4e98fa39f2ee",
            ...
        }
    ],
    ...
}

If the response status is complete or authentication_not_required, the method resolves, allowing your integration to attach the authenticated source to the checkout.

For additional details, refer to the section on retrieving saved payment sources during subscription acquisitions on the Building payment workflows page.

Managing subscriptions after acquisition

After you convert the checkout to an order, you'll need to active the subscription and process renewals. To learn more, refer to the Managing a subscription page.

Trial subscription acquisitions

You handle free-trial subscription acquisitions in much the same way as standard acquisitions.

In free trials, however, you must configure the checkout in a slightly different way.

Once customers initiate checkout, determine whether their cart contains any trial-based subscription products. If it does, use items[].subscriptionInfo to describe those products in your POST /checkouts.

You can also add non-trial subscription products, as well as non-subscription products, to the same checkout. All the subscription line items, however, must reference the same plan. For details, refer to Checkouts with multiple subscriptions.

Each trial-based subscription line item in the request must specify a price of 0.0, set freeTrial to true, and pass a planId that references a trial period plan.

POST /checkouts
curl --location --request POST 'https://api.digitalriver.com/checkouts' \
--header 'Content-Type: application/json' \
...
--data-raw '{
    "customerId": "563089630336",
    "sourceId": "8687447b-a04d-4838-af6c-0de0810f23a7",
    "locale": "en_US",
    "email": "jdoe@digitalriver.com",
    "currency": "USD",
    "items": [
        {
            "skuId": "sku_3e5ab173-d52e-4d9e-8888-2a00f6bb188e",
            "quantity": 2,
            "price": 0.0,
            "subscriptionInfo": {
                "planId": "186cf07e-a1ea-4ec0-9d9a-8aa93b3af43a",
                "terms": "The terms of the subscription",
                "autoRenewal": true,
                "freeTrial": true
            }
        }       
    ]
}'

If you create or update a checkout and (1) freeTrial is true and price or aggregatePrice contain a value that's greater than 0.0 or (2) freeTrial is false and price or aggregatePrice are 0.0, then the following error is thrown:

400 Bad Request
{
    "type": "bad_request",
    "errors": [
        {
            "code": "invalid_parameter",
            "parameter": "items",
            "message": "The value of the Free Trial flag is not consistent with the item price or the aggregate price."
        }
    ]
}

Managing trial subscriptions after acquisition

For details on how to process a trial subscription after you convert the checkout to an order, refer to Trial subscription management on the Managing a subscription page.

Last updated