Search…
Install and configure the Digital River app
Learn how to install and configure the Digital River app.

Step 1: Install the Digital River app

  1. 1.
    Download the Digital River app from https://apps.vtex.com/.
  2. 2.
    Install the Digital River app in your account using the following command-line interface (CLI): vtex install vtexus.connector-digital-river
If you have multiple VTEX accounts configured in a marketplace-seller relationship, install the Digital River app and repeat the following steps in each of the related accounts.

Step 2: Configure the Digital River settings

You must have a Digital River account and register all SKUs with Digital River. You can register the SKUs using this app's catalog sync feature or through the Digital River API. If a shopper attempts to check out with an unregistered SKU, the Digital River Drop-in component will fail to load.
  1. 1.
    Under the Other section in the admin sidebar, click Digital River and then Configuration.
  2. 2.
    In the settings fields, enter your Digital River public key, Digital River token, VTEX app key, and VTEX app token.
    • For initial testing, use a test Digital River token and leave the Enable production mode turned off.
    • Turn on the Enable automatic catalog sync to enable syncing of SKUs from VTEX to Digital River each time you add or update a SKU in your VTEX catalog.
    • Toggle the Enable tax inclusive prices to enable tax-inclusive prices if your catalog uses tax-inclusive product prices.
  3. 3.
    Click Save Settings.
For multiple VTEX accounts configured in a marketplace-seller relationship, use the same VTEX app key and VTEX app token for all of the accounts in which the app is installed. You can use any of the accounts to generate the key or token, and then grant additional permissions to the key or token by creating a new user on each of the other accounts using the VTEX app key in place of the user's email address, and then assigning the Owner role to that user.
Digital River provides a tax calculation service. Therefore there should be no other tax calculation provider enabled on your account. If there is a tax calculation provider enabled on your account, you must disable it before you can configure Digital River.

Step 3: Run the initial full catalog sync

You must enable the Enable automatic catalog sync setting before you can perform this step. See Step 2: Configure the Digital River Settings.
We recommended you run an initial full catalog sync between VTEX and Digital River. To do a full catalog sync:
  1. 1.
    Under the Other section in the admin sidebar, click Digital River and then click Catalog Sync Logs.
  2. 2.
    Click the SYNC CATALOG button. This will send all current SKUs from your VTEX catalog to Digital River.
Note that each product requires valid values for Tax Code, ECCN, and Country of origin in the VTEX catalog to be eligible to be sent to Digital River. The logs on this page will show whether the sync processed each SKU successfully or encountered an error due to missing information. Since this process runs in the background, there is a RELOAD button to refresh the logs.

Step 4: Add Digital River Javascript to checkout6-custom.js

  1. 1.
    To add the following JavaScript to your checkout6-custom.js file, click Store Setup in your admin sidebar, click Checkout, then click the blue gear icon, and then click the Code tab.
1
// DIGITAL RIVER Version 2.0.0
2
let checkoutUpdated = false
3
const digitalRiverPaymentGroupClass = '.DigitalRiverPaymentGroup'
4
const digitalRiverPaymentGroupButtonID =
5
'payment-group-DigitalRiverPaymentGroup'
6
7
const digitalRiverPublicKey = 'pk_test_1234567890' // NOTE! Enter your Digital River public API key here
8
9
const paymentErrorTitle = 'Unable to check out with selected payment method.'
10
const paymentErrorDescription =
11
'Please try a different payment method and try again.'
12
const loginMessage = 'Please log in to continue payment.'
13
const loginButtonText = 'LOG IN'
14
const addressErrorTitle = 'Incomplete shipping address detected.'
15
const addressErrorDescription =
16
'Please check your shipping information and try again.'
17
const genericErrorTitle = 'Digital River checkout encountered an error.'
18
const genericErrorDescription =
19
'Please check your shipping information and try again.'
20
let digitalriver
21
let digitalRiverCompliance
22
23
async function getCountryCode(country) {
24
return await fetch(
25
`${
26
__RUNTIME__.rootPath || ``
27
}/_v/api/digital-river/checkout/country-code/${country}`
28
)
29
.then((response) => {
30
return response.json()
31
})
32
.then((json) => {
33
return json.code
34
})
35
}
36
37
function loadCompliance(orderForm) {
38
const locale = orderForm && orderForm.clientPreferencesData && orderForm.clientPreferencesData.locale;
39
const complianceOptions = {
40
classes: {
41
base: 'DRElement'
42
},
43
compliance: {
44
locale,
45
entity: 'DR_INC-ENTITY'
46
}
47
}
48
if ($('#compliance').length == 0) {
49
$('.container-main').append('<div id="compliance"></div>')
50
digitalRiverCompliance = digitalriver.createElement('compliance', complianceOptions);
51
digitalRiverCompliance.mount('compliance');
52
} else {
53
digitalRiverCompliance.update(complianceOptions);
54
}
55
}
56
57
function renderErrorMessage(title, body, append = false) {
58
if (!append) {
59
$(digitalRiverPaymentGroupClass).html(
60
`<div><div class='DR-card'><div class='DR-collapse DR-show'><h5 class='DR-error-message'>${title}</h5><div><p>${body}</p></div></div></div></div>`
61
)
62
63
return
64
}
65
66
$('#VTEX-DR-error').remove()
67
$('.DR-pay-button').after(
68
`<div id='VTEX-DR-error'><h5 class="DR-error-message">${title}</h5><div><p>${body}</p></div></div>`
69
)
70
}
71
72
async function updateOrderForm(method, checkoutId) {
73
const orderFormID = vtexjs.checkout.orderFormId
74
75
return await $.ajax({
76
url: `${window.location.origin}${
77
__RUNTIME__.rootPath || ``
78
}/api/checkout/pub/orderForm/${orderFormID}/customData/digital-river/checkoutId`,
79
type: method,
80
data: { value: checkoutId },
81
success() {
82
vtexjs.checkout.getOrderForm().done((orderForm) => {
83
const { clientPreferencesData } = orderForm
84
if (!clientPreferencesData) return
85
return vtexjs.checkout.sendAttachment(
86
'clientPreferencesData',
87
clientPreferencesData
88
)
89
})
90
},
91
})
92
}
93
94
function showBuyNowButton() {
95
$('.payment-submit-wrap').show()
96
}
97
98
function hideBuyNowButton() {
99
$('.payment-submit-wrap').hide()
100
}
101
102
function clickBuyNowButton() {
103
$('#payment-data-submit').click()
104
}
105
106
function loadDigitalRiverScript() {
107
const e = document.createElement('script')
108
109
;(e.type = 'text/javascript'),
110
(e.src = 'https://js.digitalriver.com/v1/DigitalRiver.js')
111
const [t] = document.getElementsByTagName('script')
112
113
t.parentNode.insertBefore(e, t)
114
115
const f = document.createElement('link')
116
117
;(f.type = 'text/css'),
118
(f.rel = 'stylesheet'),
119
(f.href = 'https://js.digitalriverws.com/v1/css/DigitalRiver.css')
120
const [u] = document.getElementsByTagName('link')
121
122
u.parentNode.insertBefore(f, u)
123
}
124
125
function loadStoredCards(checkoutId) {
126
fetch(`${__RUNTIME__.rootPath || ``}/_v/api/digital-river/checkout/sources?v=${new Date().getTime()}`)
127
.then((response) => {
128
return response.json()
129
})
130
.then(async (response) => {
131
if (response.customer && response.customer.sources) {
132
var sources = response.customer.sources
133
if (sources.length > 0) {
134
var radiosHtmls =
135
'<div class="stored-credit-cards-title" style="margin-bottom: 16px;"><span class="DR-payment-method-name DR-payment-method-name-with-image" style="color: rgba(0,0,0,.75); font-size: 1rem; font-weight: 400; line-height: 20px; margin: 0px;">Saved Cards</span></div>'
136
for (var i = 0; i < sources.length; i++) {
137
radiosHtmls +=
138
'<input name="DR-stored-cards" type="radio" id="' +
139
sources[i].id +
140
'" value="' +
141
sources[i].id +
142
'">'
143
radiosHtmls +=
144
'<label style="display: inline-block; vertical-align: sub; margin-bottom: 8px; margin-left: 4px; font-size: 0.875rem" for="' +
145
sources[i].id +
146
'">' +
147
sources[i].creditCard.brand +
148
' ending with ' +
149
sources[i].creditCard.lastFourDigits +
150
' expires ' +
151
('0' + sources[i].creditCard.expirationMonth).slice(-2) +
152
'/' +
153
sources[i].creditCard.expirationYear +
154
'</label></br>'
155
}
156
radiosHtmls +=
157
'<div class="stored-credit-cards" style="margin-top: 16px;"><button id="submit-stored-creditCard" style="background-color: #1264a3; color: #FFF; height: 56px; border-radius: .25rem; text-align: center; border-top: none!important; border: none; font-weight: 400; padding: 1rem; width: 250px; margin-bottom: 24px;">BUY NOW WITH SAVED CARD</button></div>'
158
159
$('#drop-in').prepend(
160
'<div class="DR-stored-cards">' + radiosHtmls + '</div>'
161
)
162
$('#submit-stored-creditCard').click(function () {
163
var sourceId = $('input[name=DR-stored-cards]:checked').attr('id')
164
fetch(
165
`${
166
__RUNTIME__.rootPath || ``
167
}/_v/api/digital-river/checkout/update`,
168
{
169
method: 'POST',
170
body: JSON.stringify({
171
checkoutId,
172
sourceId,
173
readyForStorage: false,
174
}),
175
}
176
)
177
.then((rawResponse) => {
178
return rawResponse.json()
179
})
180
.then(() => {
181
checkoutUpdated = true
182
clickBuyNowButton()
183
})
184
})
185
$('#' + sources[0].id).click()
186
}
187
}
188
})
189
}
190
191
function loadDigitalRiver(orderForm) {
192
const locale = orderForm && orderForm.clientPreferencesData && orderForm.clientPreferencesData.locale
193
digitalriver = new DigitalRiver(digitalRiverPublicKey, {
194
locale: locale ?? 'en-US',
195
})
196
}
197
198
async function initDigitalRiver(orderForm) {
199
hideBuyNowButton()
200
201
if (
202
$('#drop-in-spinner').length ||
203
($('#drop-in').length && $('#drop-in').html().length)
204
) {
205
return
206
}
207
208
$(digitalRiverPaymentGroupClass).html(
209
`<div id='drop-in-spinner'><i class="icon-spinner icon-spin"></i></div>`
210
)
211
212
$(digitalRiverPaymentGroupClass).append(`<div id='drop-in'></div>`)
213
214
if (!orderForm.canEditData) {
215
hideBuyNowButton()
216
$(digitalRiverPaymentGroupClass).html(
217
`<div><div class='DR-card'><div class='DR-collapse DR-show'><h5 class='DR-error-message'>${loginMessage}</h5><div><a style='cursor: pointer;' onClick='window.vtexid.start()' class='DR-button-text'>${loginButtonText}</a></div></div></div></div>`
218
)
219
return
220
}
221
222
fetch(`${__RUNTIME__.rootPath || ``}/_v/api/digital-river/checkout/create`, {
223
method: 'POST',
224
body: JSON.stringify({ orderFormId: orderForm.orderFormId, taxIdPayload: { // NOTE: The taxIdPayload field is optional
225
taxId: {
226
"type": "uk",
227
"value": "GB999999999"
228
},
229
customerType: "business"
230
}}),
231
})
232
.then((response) => {
233
return response.json()
234
})
235
.then(async (response) => {
236
const { checkoutId = null, paymentSessionId = null } = response
237
238
if (!checkoutId || !paymentSessionId) {
239
renderErrorMessage(genericErrorTitle, genericErrorDescription, false)
240
241
return
242
}
243
244
await updateOrderForm('PUT', checkoutId)
245
246
const country = await getCountryCode(
247
orderForm.shippingData.address.country
248
)
249
250
const configuration = {
251
sessionId: paymentSessionId,
252
options: {
253
flow: 'checkout',
254
showComplianceSection: false,
255
showSavePaymentAgreement: true,
256
showTermsOfSaleDisclosure: true,
257
button: {
258
type: 'buyNow',
259
},
260
},
261
billingAddress: {
262
firstName: orderForm.clientProfileData.firstName,
263
lastName: orderForm.clientProfileData.lastName,
264
email: orderForm.clientProfileData.email,
265
phoneNumber: orderForm.clientProfileData.phone,
266
address: {
267
line1: `${
268
orderForm.shippingData.address.number
269
? `${orderForm.shippingData.address.number} `
270
: ''
271
}${orderForm.shippingData.address.street}`,
272
line2: orderForm.shippingData.address.complement,
273
city: orderForm.shippingData.address.city,
274
state: orderForm.shippingData.address.state,
275
postalCode: orderForm.shippingData.address.postalCode,
276
country,
277
},
278
},
279
onSuccess(data) {
280
fetch(
281
`${
282
__RUNTIME__.rootPath || ``
283
}/_v/api/digital-river/checkout/update`,
284
{
285
method: 'POST',
286
body: JSON.stringify({
287
checkoutId,
288
sourceId: data.source.id,
289
readyForStorage: data.readyForStorage,
290
}),
291
}
292
)
293
.then((rawResponse) => {
294
return rawResponse.json()
295
})
296
.then(() => {
297
checkoutUpdated = true
298
clickBuyNowButton()
299
})
300
},
301
onCancel(data) {},
302
onError(data) {
303
console.error(data)
304
renderErrorMessage(paymentErrorTitle, paymentErrorDescription, true)
305
},
306
onReady(data) {
307
loadStoredCards(checkoutId)
308
},
309
}
310
const dropin = digitalriver.createDropin(configuration)
311
$('#drop-in-spinner').remove();
312
$('#drop-in').children().remove();
313
dropin.mount('drop-in')
314
})
315
}
316
317
$(document).ready(function () {
318
loadDigitalRiverScript();
319
if (~window.location.hash.indexOf('#/payment')) {
320
if (
321
$('.payment-group-item.active').attr('id') ===
322
digitalRiverPaymentGroupButtonID
323
) {
324
vtexjs.checkout.getOrderForm().done(function (orderForm) {
325
loadDigitalRiver(orderForm);
326
initDigitalRiver(orderForm)
327
})
328
} else {
329
showBuyNowButton()
330
}
331
}
332
})
333
334
$(window).on('orderFormUpdated.vtex', function (evt, orderForm) {
335
loadDigitalRiver(orderForm);
336
loadCompliance(orderForm);
337
if (
338
~window.location.hash.indexOf('#/payment') &&
339
$('.payment-group-item.active').attr('id') ===
340
digitalRiverPaymentGroupButtonID
341
) {
342
if (
343
!orderForm.shippingData.address ||
344
!orderForm.shippingData.address.street ||
345
!orderForm.shippingData.address.city ||
346
!orderForm.shippingData.address.state ||
347
!orderForm.shippingData.address.postalCode ||
348
!orderForm.shippingData.address.country
349
) {
350
return
351
} else {
352
initDigitalRiver(orderForm)
353
}
354
}
355
})
Copied!

Step 5: Configure payment settings

  1. 1.
    In your admin sidebar, click Transactions, click Payments, and then click Settings.
  2. 2.
    Click the Gateway Affiliations tab and then click the green plus sign to add a new affiliation.
  3. 3.
    Click DigitalRiverV2 from the Others list.
  4. 4.
    Modify the Affiliation name if needed, choose an Auto Settlement behavior from the dropdown (Digital River recommends setting this to Disabled: Do Not Auto Settle), and then click Save. Leave Application Key and Application Token blank.
  5. 5.
    Click the Payment Conditions tab and click the green plus sign to add a new payment condition.
  6. 6.
    Click DigitalRiver from the Other list.
  7. 7.
    In the Process with affiliation dropdown, choose the name of the affiliation that you created in step 3 of this task.
  8. 8.
    Set the status to Active and click Save.
By clicking Save, you will activate the payment method in checkout!

Step 5: Enable production mode

  1. 1.
    After successfully testing the payment method in test mode, under the Other section in the admin sidebar, click Digital River, and then click Configuration.
  2. 2.
    Replace your test Digital River token with a production token, and turn on the Enable Production mode toggle.
  3. 3.
    Click Save. Your checkout page will start accepting production orders.
Last modified 1mo ago