Adyen
Implementing Adyen as payment provider
Adyen is a Dutch payment company which enables you to accept electronic payment using a variety of payment methods, like credit cards, debit cards, etc.
You can sign up for an Adyen test account here.
To configure Adyen Checkout you need the following 5 keys:
- Merchant name – this is your account name, in our case DynamicwebTestEcom
- API key – see Adyen docs on How to get the API key
- Client key – see Adyen docs on How to get an client key
- Live URL prefix – see Adyen docs for more information. Only required when moving from test to production.
- HMAC key – see Adyen docs on HMAC signature calculation
After obtaining the 5 keys you can configure the payment method
- Open Settings > Areas > Commerce > Order Management > Payment and click '+ New payment
- Select the Adyen Checkout payment provider and configure it
The following settings are available:
Section | Setting | Use | Notes |
---|---|---|---|
General | Merchant name | The Adyen account name | |
API key | The Adyen API key | ||
Client key | The Adyen Client key | ||
Live URL prefix | If it is not set, the test mode will be used, even if corresponding checkbox is not checked | ||
Allow save cards | Check to allow users to save cards via Adyen | ||
Skip security code for one-off payments | If not checked, the provider will redirect you to a template where you can enter the security code of your saved card. If checked, the provider will attempt to complete the payment transaction using the stored card data. Please note: SkipCvCForOneClick must be enabled on your Adyen account to make it work. | ||
Test mode | Switch between live/test mode | ||
Debug mode | |||
Template settings | Payments template | This template renders the payment form | |
Cancel template | This payment renders the feedback if the user cancels a payment | ||
Error template | This payment renders errors from Adyen if they occur | ||
Notification settings | HMAC key | If it is not set, notification processing will not be performed, even if it is configured in the Adyen control panel. |
Payment templates
Templates for the Adyen provider should be placed in an Adyen-folder with subfolders located under Files/Templates/eCom7/CheckoutHandler
:
/CheckoutHandler/
├── Adyen/
│ ├── Cancel/
│ │ ├── cancel_payment.cshtml
│ ├── Card/
│ │ ├── saved_card.cshtml
│ ├── Error/
│ │ ├── payment_error.cshtml
│ ├── Form/
│ │ ├── payment_form.cshtml
If it's not available on your solution, the standard payment form template we supply looks like this:
@using System.Collections.Generic
@using Dynamicweb.Rendering
@inherits RazorTemplateBase<RazorTemplateModel<Template>>
@{
var supportedLocales = new HashSet<string>(
new[] { "zh-CN", "zh-TW", "da-DK", "nl-NL", "en-US", "fi-FI", "fr-FR", "de-DE", "it-IT", "ja-JP", "ko-KR", "no-NO", "pl-PL", "pt-BR", "ru-RU", "es-ES", "sv-SE" },
StringComparer.OrdinalIgnoreCase
);
var currentLocale = GetGlobalValue("Global:Area.Culture.Name");
if (!supportedLocales.Contains(currentLocale))
{
currentLocale = "en-US";
}
}
<script src="@GetString("Adyen.JavaScriptUrl")"
integrity="@GetString("Adyen.JsIntegrityKey")"
crossorigin="anonymous"></script>
<link rel="stylesheet" href="@GetString("Adyen.CssUrl")"
integrity="@GetString("Adyen.CssIntegrityKey")"
crossorigin="anonymous">
<div id="dropin-container"></div>
<script type="module">
const baseUrl = '/Default.aspx?ID=@GetGlobalValue("Global:Page.ID")&CheckoutHandlerOrderID=@GetString("Ecom:Order.ID")&redirect=false';
const configuration = {
onSubmit: function (state, dropin) {
dropin.setStatus('loading');
processPaymentOperation(baseUrl + '&Action=SelectMethod', state.data, dropin);
},
onAdditionalDetails: (state, dropin) => { },
onPaymentCompleted: (result, component) => { },
showPayButton: true,
locale: '@currentLocale',
environment: '@GetString("Adyen.Environment")',
clientKey: '@GetString("Adyen.ClientKey")',
amount: {
currency: '@GetString("Adyen.Currency")',
value: @GetLong("Adyen.Price")
},
session: {
id: '@GetString("Adyen.PaymentSessionId")',
sessionData: '@GetString("Adyen.PaymentSessionData")'
}
};
const checkout = await AdyenCheckout(configuration);
checkout.create('dropin').mount('#dropin-container');
async function processPaymentOperation(url, data, dropin) {
const configuration = {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
};
const response = await fetch(url, configuration);
if (!response.ok) {
showError(`Something went wrong. Response status: ${response.status}`, dropin);
return;
}
const json = await response.json();
if (json.redirectToReceipt) {
// show payment result and redirect to receipt
dropin.setStatus("success");
setTimeout(function () {
document.location = json.redirectToReceipt;
}, 1500);
return;
}
if (json.action) {
dropin.handleAction(json.action);
} else if (json.errorCode) {
showError(json.message, dropin);
} else {
showError("Something went wrong.", dropin);
}
}
function showError(message, dropin) {
if (message && message.length > 0) {
dropin.setStatus("error", { message: message });
} else {
dropin.setStatus("error");
}
}
</script>
The standard saved card payment form could look like this:
@using System.Collections.Generic
@using Dynamicweb.Rendering
@inherits RazorTemplateBase<RazorTemplateModel<Template>>
@{
var supportedLocales = new HashSet<string>(
new[] { "zh-CN", "zh-TW", "da-DK", "nl-NL", "en-US", "fi-FI", "fr-FR", "de-DE", "it-IT", "ja-JP", "ko-KR", "no-NO", "pl-PL", "pt-BR", "ru-RU", "es-ES", "sv-SE" },
StringComparer.OrdinalIgnoreCase
);
var currentLocale = GetGlobalValue("Global:Area.Culture.Name");
if (!supportedLocales.Contains(currentLocale))
{
currentLocale = "en-US";
}
}
<script src="@GetString("Adyen.JavaScriptUrl")"
integrity="@GetString("Adyen.JsIntegrityKey")"
crossorigin="anonymous"></script>
<link rel="stylesheet" href="@GetString("Adyen.CssUrl")"
integrity="@GetString("Adyen.CssIntegrityKey")"
crossorigin="anonymous">
<div id="card-container"></div>
<span style="color:red" id="errorsContainer"></span>
<script type="module">
const baseUrl = '/Default.aspx?ID=@GetGlobalValue("Global:Page.ID")&CheckoutHandlerOrderID=@GetString("Ecom:Order.ID")&redirect=false';
const configuration = {
onSubmit: function (state, card) {
processPaymentOperation(baseUrl + '&Action=UseSavedMethod', state.data, card);
},
onAdditionalDetails: (state, card) => { },
onPaymentCompleted: (result, card) => { },
showPayButton: true,
locale: '@currentLocale',
environment: '@GetString("Adyen.Environment")',
clientKey: '@GetString("Adyen.ClientKey")',
amount: {
currency: '@GetString("Adyen.Currency")',
value: @GetLong("Adyen.Price")
},
enableStoreDetails: true,
paymentMethodsResponse: JSON.parse(`@GetString("Adyen.PaymentMethods")`)
};
const checkout = await AdyenCheckout(configuration);
const paymentMethod = checkout.paymentMethodsResponse.storedPaymentMethods[0];
const cardComponent = checkout.create('card', paymentMethod).mount('#card-container');
async function processPaymentOperation(url, data, card) {
const configuration = {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
};
const response = await fetch(url, configuration);
if (!response.ok) {
showError(`Something went wrong. Response status: ${response.status}`);
return;
}
const json = await response.json();
if (json.redirectToReceipt) {
document.location = json.redirectToReceipt;
return;
}
if (json.action) {
card.handleAction(json.action);
} else if (json.errorCode) {
showError(json.message);
} else {
showError(null);
}
}
function showError(message) {
const errorsContainer = document.getElementById("errorsContainer");
errorsContainer.textContent = message && message.length > 0 ? message : "Unhandled error is occured";
}
</script>
Testing Adyen
Adyen supplies test cards which can be used to test the setup. Please note that some features, like saved cards, must be enabled in the Adyen administration before they work in DynamicWeb.
Please note that Adyen requires SSL & a public URL in order to complete a test payment. You must also add the website URL as an allowed origin under Developers > Api Credentials in the Adyen administration interface.