I'm trying to integrate Adyen's payment methods (including CashApp) into my Django web application, but the CashApp payment method isn't rendering on the front end. Instead, I receive the following error:
ERROR Error during initialization ERROR: Error during initialization
at e.<anonymous> (https://checkoutshopper-test.adyen.com/checkoutshopper/sdk/5.68.0/adyen.js:1:460538)
at P (https://checkoutshopper-test.adyen.com/checkoutshopper/sdk/5.68.0/adyen.js:1:41524)
at Generator.<anonymous> (https://checkoutshopper-test.adyen.com/checkoutshopper/sdk/5.68.0/adyen.js:1:42844)
This same code is rendering the card payment gateway but not working on the cashapp.
My html Code: Where is used adyen sdk=5.68.0 version. Version greater than 5.69.0 gives different error that AdyenCheckout is not defined I don't know how to solve that too.
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="vtokvaldat" content="{{ csrf_token }}">
<!-- Adyen css from TEST environment (change to live for production)-->
<link rel="stylesheet"
href="https://checkoutshopper-test.adyen.com/checkoutshopper/sdk/5.68.0/adyen.css"
integrity="sha384-gpOE6R0K50VgXe6u/pyjzkKl4Kr8hXu93KUCTmC4LqbO9mpoGUYsrmeVLcp2eejn"
crossorigin="anonymous">
<div id="payment-page">
<div class="container">
<div class="payment-container">
<div id="component" class="payment">
<!-- Component will be rendered here -->
</div>
</div>
</div>
{% csrf_token %}
</div>
<!-- Adyen JS from TEST environment (change to live for production)-->
<script src="https://checkoutshopper-test.adyen.com/checkoutshopper/sdk/5.68.0/adyen.js"
integrity="sha384-U9GX6Oa3W024049K86PYG36/jHjkvUqsRd8Y9cF1CmB92sm4tnjxDXF/tkdcsk6k"
crossorigin="anonymous"></script>
{{ client_key|json_script:"client-key" }}
{{ method|json_script:"integration-type" }}
<script>
const clientKey = JSON.parse(document.getElementById('client-key').innerHTML);
const type = JSON.parse(document.getElementById('integration-type').innerHTML);
// Used to finalize a checkout call in case of redirect
const urlParams = new URLSearchParams(window.location.search);
const sessionId = urlParams.get('sessionId'); // Unique identifier for the payment session
const redirectResult = urlParams.get('redirectResult');
// Start the Checkout workflow
async function startCheckout() {
try {
// Init Sessions
const checkoutSessionResponse = await callServer({% url 'sessions' %});
// Create AdyenCheckout using Sessions response
const checkout = await createAdyenCheckout(checkoutSessionResponse)
// Create an instance of Drop-in and mount it to the container you created.
const dropinComponent = checkout.create(type).mount("#component"); // pass DIV id where component must be rendered
} catch (error) {
console.error(error);
alert("Error occurred. Look at console for details");
}
}
// Some payment methods use redirects. This is where we finalize the operation
async function finalizeCheckout() {
try {
// Create AdyenCheckout re-using existing Session
const checkout = await createAdyenCheckout({id: sessionId});
// Submit the extracted redirectResult (to trigger onPaymentCompleted(result, component) handler)
checkout.submitDetails({details: {redirectResult}});
} catch (error) {
console.error(error);
alert("Error occurred. Look at console for details");
}
}
function getCSRFToken() {
const token = document.querySelector('meta[name="vtokvaldat"]').getAttribute('content');
return token;
}
async function createAdyenCheckout(session) {
const configuration = {
clientKey,
locale: "en-US",
environment: "test", // change to live for production
showPayButton: true,
session: session,
paymentMethodsConfiguration: {
ideal: {
showImage: true
},
card: {
hasHolderName: true,
holderNameRequired: true,
name: "Credit or debit card",
countryCode: "US"
},
paypal: {
environment: "test",
countryCode: "US" // Only needed for test. This will be automatically retrieved when you are in production.
},
cashapp: {
environment: "test",
countryCode: "US",
referenceId: "5465456435156",
showsStorePaymentMethodField: true,
storePaymentMethod: true
}
},
onPaymentCompleted: (result, component) => {
console.info(result, component);
handleServerResponse(result, component);
},
onError: (error, component) => {
console.error(error.name, error.message, error.stack, component);
}
};
return new AdyenCheckout(configuration);
}
// Calls your server endpoints
async function callServer(url, data) {
const res = await fetch(url, {
method: "POST",
body: data ? JSON.stringify(data) : "",
headers: {
"Content-Type": "application/json",
"X-CSRFToken": getCSRFToken()
}
});
return await res.json();
}
// Handles responses sent from your server to the client
function handleServerResponse(res, component) {
if (res.action) {
component.handleAction(res.action);
} else {
switch (res.resultCode) {
case "Authorised":
window.location.href = "{% url 'success' %}";
break;
case "Pending":
case "Received":
window.location.href = "/pending";
break;
case "Refused":
window.location.href = "{% url 'failed' %}";
break;
default:
window.location.href = "{% url 'error' %}";
break;
}
}
}
if (!sessionId) {
startCheckout();
}
else {
// existing session: complete Checkout
finalizeCheckout();
}
</script>
django view.py file:
import json
import uuid
from django.conf import settings
from django.http import JsonResponse
from django.shortcuts import render
import Adyen
def adyen_sessions(request):
# payments = ["card", "cashapp", "paypal"]
session_response = {
'client_key': settings.ADYEN_CLIENT_KEY,
'method': 'cashapp'
}
return render(request, 'component.html', context=session_response)
def sessions(request):
if request.method == "POST":
adyen = Adyen.Adyen()
adyen.payment.client.xapikey = settings.ADYEN_API_KEY
adyen.payment.client.platform = settings.ADYEN_ENVIRONMENT
adyen.payment.client.merchant_account = settings.ADYEN_MERCHANT_ACCOUNT
request_data = {
'amount': {
"value": 1900, # amount in minor units
"currency": "USD"
},
'reference': f"Reference {uuid.uuid4()}",
'returnUrl': f"{request.build_absolute_uri('/redirect?shopperOrder=myRef')}",
'countryCode': "US",
'channel': 'Web',
"recurringProcessingModel": "CardOnFile",
"storePaymentMethodMode": "askForConsent",
'lineItems': [
{
"quantity": 1,
"amountIncludingTax": 5000,
"description": "Sunglasses"
},
{
"quantity": 1,
"amountIncludingTax": 5000,
"description": "Headphones"
}
],
'merchantAccount': settings.ADYEN_MERCHANT_ACCOUNT,
}
result = adyen.checkout.payments_api.sessions(request_data)
data = json.loads(result.raw_response)
print("/sessions response:\n" + data.__str__())
return JsonResponse(data, status=200, safe=False)
def redirect_view(request):
return render(request, 'home.html')
def success(request):
return render(request, 'checkout-success.html')
def failed(request):
return render(request, 'checkout-failed.html')
def error(request):
return render(request, 'error.html')
django urls.py:
from django.urls import path
from . import views
urlpatterns = [
path('', views.adyen_sessions, name='adyen_sessions'),
path('redirect/', views.redirect_view, name='redirect_view'),
path('sessions/', views.sessions, name='sessions'),
path('success/', views.success, name='success'),
path('failed/', views.failed, name='failed'),
path('error/', views.error, name='error'),
]
According to the Adyen Documentation for CashApp you have to include the following two parameters in your request:
"storePaymentMethodMode": "askForConsent"
"recurringProcessingModel": "CardOnFile"
I'd also ensure that startCheckout(..) is called on the page. I don't see the startCheckout(..) being called in the inserted snippet.
Here's my version of the code, I've started with the Python-integration-example on Github and modified it slightly:
// sessions.py (backend)
def adyen_sessions(host_url):
adyen = Adyen.Adyen()
adyen.payment.client.xapikey = get_adyen_api_key()
adyen.payment.client.platform = "test"
adyen.payment.client.merchant_account = get_adyen_merchant_account()
request_data = {
'amount': {
'value': 1900,
'currency': 'USD'
},
'reference': f"Reference {uuid.uuid4()}",
'returnUrl': f"{host_url}/redirect?shopperOrder=myRef", # Modify this so it will return the user to your specific page when redirected
'countryCode': 'US',
'channel': 'Web',
'recurringProcessingModel': 'CardOnFile',
'storePaymentMethodMode': 'askForConsent',
'lineItems': [
{
'quantity': 1,
'amountIncludingTax': 5000,
'description': 'Sunglasses'
},
{
'quantity': 1,
'amountIncludingTax': 5000,
'description': 'Headphones'
}
],
'merchantAccount': get_adyen_merchant_account(),
}
result = adyen.checkout.payments_api.sessions(request_data)
formatted_response = json.dumps((json.loads(result.raw_response)))
print("/sessions response:\n" + formatted_response)
return formatted_response
// In config.py (added 'cashapp' for components)
def get_supported_integration():
return ['dropin', 'card', 'ideal', 'klarna', 'directEbanking', 'alipay', 'boletobancario',
'sepadirectdebit', 'dotpay', 'giropay', 'ach', 'paypal', 'applepay',
'klarna_paynow', 'klarna', 'klarna_account', 'cashapp']
// Frontend
const clientKey = JSON.parse(document.getElementById('client-key').innerHTML);
const type = JSON.parse(document.getElementById('integration-type').innerHTML);
// Used to finalize a checkout call in case of redirect
const urlParams = new URLSearchParams(window.location.search);
const sessionId = urlParams.get('sessionId'); // Unique identifier for the payment session
const redirectResult = urlParams.get('redirectResult');
// Start the Checkout workflow
async function startCheckout() {
try {
// Init Sessions
const checkoutSessionResponse = await callServer("/api/sessions?type=" + type);
// Create AdyenCheckout using Sessions response
const checkout = await createAdyenCheckout(checkoutSessionResponse)
// Create an instance of Drop-in and mount it to the container you created.
const dropinComponent = checkout.create(type).mount("#component");
} catch (error) {
console.error(error);
alert("Error occurred. Look at console for details");
}
}
// Some payment methods use redirects. This is where we finalize the operation
async function finalizeCheckout() {
try {
// Create AdyenCheckout re-using existing Session
const checkout = await createAdyenCheckout({id: sessionId});
// Submit the extracted redirectResult (to trigger onPaymentCompleted(result, component) handler)
checkout.submitDetails({details: {redirectResult}});
} catch (error) {
console.error(error);
alert("Error occurred. Look at console for details");
}
}
function getCSRFToken() {
const token = "token";// document.querySelector('meta[name="vtokvaldat"]').getAttribute('content'); // Our example doesn't have this field, hence why I left this one out for now
return token;
}
async function createAdyenCheckout(session) {
const configuration = {
clientKey,
locale: "en-US",
environment: "test", // change to live for production
showPayButton: true,
session: session,
paymentMethodsConfiguration: {
ideal: {
showImage: true
},
card: {
hasHolderName: true,
holderNameRequired: true,
name: "Credit or debit card",
countryCode: "US"
},
paypal: {
environment: "test",
countryCode: "US" // Only needed for test. This will be automatically retrieved when you are in production.
},
cashapp: {
environment: "test",
countryCode: "US",
referenceId: "5465456435156",
showsStorePaymentMethodField: true,
storePaymentMethod: true,
style: { button: { shape: 'semiround' } }
}
},
onPaymentCompleted: (result, component) => {
console.info(result, component);
handleServerResponse(result, component);
},
onError: (error, component) => {
console.error(error.name, error.message, error.stack, component);
}
};
return new AdyenCheckout(configuration);
}
// Calls your server endpoints
async function callServer(url, data) {
const res = await fetch(url, {
method: "POST",
body: data ? JSON.stringify(data) : "",
headers: {
"Content-Type": "application/json",
"X-CSRFToken": getCSRFToken()
}
});
return await res.json();
}
// Handles responses sent from your server to the client
function handleServerResponse(res, component) {
if (res.action) {
component.handleAction(res.action);
} else {
switch (res.resultCode) {
case "Authorised":
window.location.href = "{% url 'success' %}";
break;
case "Pending":
case "Received":
window.location.href = "/pending";
break;
case "Refused":
window.location.href = "{% url 'failed' %}";
break;
default:
window.location.href = "{% url 'error' %}";
break;
}
}
}
if (!sessionId) {
startCheckout();
}
else {
// existing session: complete Checkout
finalizeCheckout();
}
Hope this helped!