{
"name":"DropinError",
"message":"options.selector or options.container must reference a valid DOM node."
}
[Violation] Permissions policy violation: payment is not allowed in this document.
<template >
<div lwc:ref="dropinContainer"></div>
<button id="submit-button" class="button button--small button--green" onclick={handlePay}>Purchase</button>
</template>
import { LightningElement } from "lwc";
import { loadScript } from "lightning/platformResourceLoader";
import braintreeZip from "@salesforce/resourceUrl/braintree";
export default class BraintreePayment extends LightningElement {
instance;
loaded = false;
connectedCallback() {
this.initBraintree();
}
async initBraintree() {
if (this.loaded) {
return;
}
this.loaded = true;
try {
await Promise.all([loadScript(this, braintreeZip + "/braintree/dropin.min.js")]);
let sdk = window.braintree;
let container = this.refs.dropinContainer;
let dropinInstance = await sdk.dropin.create({
authorization: "sandbox_d5nprxpr_whf33646k9nf5ncs",
container: container,
});
this.instance = dropinInstance;
} catch (e) {
console.error("loading js failed", JSON.stringify(e));
}
}
async handlePay(event) {
let payload = await this.instance.requestPaymentMethod();
let responseStream = await fetch("https://demo-backend.vercel.app/api/braintree/checkout", {
method: "POST",
body: JSON.stringify({ paymentMethodNonce: payload.nonce }),
headers: {
"Content-Type": "application/json",
},
});
let response = await responseStream.json();
await this.instance.teardown();
if (response.success) {
console.log("Your Drop-in UI is working! Check your https://sandbox.braintreegateway.com/login sandbox Control Panel for your test transactions.");
} else {
console.log("Error", response);
}
}
}
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
import { BraintreeGateway, Environment } from "braintree";
export const POST = async (request: NextRequest) => {
const body = await request.json();
const gateway = new BraintreeGateway({
environment: Environment.Sandbox,
merchantId: "whf33646k9nf5ncs",
publicKey: "6sht3v2xzn9q2sf8",
privateKey: "95c4da9669b5ca53bcfb67024e404808",
});
const nonceFromTheClient = body.paymentMethodNonce;
if (!nonceFromTheClient) {
return NextResponse.json({error: "nonce cannot be blank"}, {
status: 400,
headers: getCorsHeaders(),
});
}
const newTransaction = await gateway.transaction.sale({
amount: "10.00",
paymentMethodNonce: nonceFromTheClient,
options: {
submitForSettlement: true,
},
});
return NextResponse.json(newTransaction, {
status: 200,
headers: getCorsHeaders(),
});
};
const getCorsHeaders = () => {
const headers = {
"Access-Control-Allow-Methods": "GET,DELETE,OPTIONS,PATCH,POST,PUT",
"Access-Control-Allow-Headers": "X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version",
"Access-Control-Allow-Origin": "*",
};
return headers;
};
export const OPTIONS = async (request: NextRequest) => {
return NextResponse.json(
{},
{
status: 200,
headers: getCorsHeaders(),
}
);
};
<apex:page controller="PaypalPaymentCtrl" showHeader="false" sidebar="false" standardStylesheets="false">
<script src="https://www.paypal.com/sdk/js?client-id=sb¤cy=EUR"></script>
<div id="paypal-button-container"></div>
<script>
paypal.Buttons({
createOrder: function (data, actions) {
return actions.order.create({
purchase_units: [{
amount: {
value: '10.00'
}
}]
});
},
onApprove: function (data, actions) {
return actions.order.capture().then(function (details) {
let paymentDto = parsePayPalResponse(details);
savePaymentDetails(paymentDto);
console.log('Transaction completed by ', details.payer.name.given_name);
});
}
}).render('#paypal-button-container');
function savePaymentDetails(paymentDto) {
var paymentDataJson = JSON.stringify(paymentDto);
Visualforce.remoting.Manager.invokeAction(
'{!$RemoteAction.PaypalPaymentCtrl.savePayment}',
paymentDataJson,
function (result, event) {
if (event.status) {
console.log('Payment saved', result);
} else {
console.log('Error saving payment');
}
}
);
}
function parsePayPalResponse(response) {
return {
orderId: response.id,
status: response.status,
amount: response.purchase_units[0].amount.value,
xCurrency: response.purchase_units[0].amount.currency_code,
payerEmail: response.payer.email_address,
payerName: `${response.payer.name.given_name} ${response.payer.name.surname}`,
};
}
</script>
</apex:page>
public class PaypalPaymentCtrl {
public class PaymentData {
public String orderId;
public String status;
public String amount;
public String xCurrency;
public String payerEmail;
public String payerName;
}
@RemoteAction
public static String savePayment(String paymentDataJson) {
PaymentData paymentData = (PaymentData)JSON.deserialize(paymentDataJson, PaymentData.class);
PaymentAuthorization paymentAuth = new PaymentAuthorization();
paymentAuth.Status = 'Processed';
paymentAuth.ProcessingMode = 'External';
paymentAuth.Amount = Decimal.valueOf(paymentData.amount);
insert paymentAuth;
return 'Success';
}
}
{
"orderId": "57443461NR723715C",
"status": "COMPLETED",
"amount": "10.00",
"currency": "EUR",
"payerEmail": "sb-rczkx29511364@personal.example.com",
"payerId": "SCHSHFWJE9N8E",
"payerName": "John Doe",
"payerAddress": "Lul. Dubois Stanisława 121, Łódź, 93-474, PL",
"payeeEmail": "barco.09-facilitator@gmail.com",
"payeeMerchantId": "YQZCHTGHUK5P8",
"createTime": "2024-01-30T11:49:28Z",
"updateTime": "2024-01-30T11:51:20Z",
"captureId": "9XX41187YX114115B"
}