I'm trying to integrate PayPal and I get the error below
You can test the code here with any PayPal sandbox buyer account:
Codepen
Here is the code I'm using
paypal.Buttons({
createOrder: function (data, actions) {
// This function sets up the details of the transaction, including the amount and line item details.
return actions.order.create({
purchase_units: [{
amount: {
value: '5.00'
}
}]
});
},
onApprove: function (data, actions) {
// This function captures the funds from the transaction.
return actions.order.capture().then(details => {
// This function shows a transaction success message to your buyer.
alert('Transaction completed by ' + details.payer.name.given_name);
});
}
}).render('#paypal-button-container');
more about the error
Testing your Codepen from the Network tab, you are getting a COMPLIANCE_VIOLATION -- probably due to the country of the account you are testing with not being properly set up in sandbox.
Try simply using a different country for your testing within sandbox. Create a new business account at https://www.paypal.com/signin?intent=developer&returnUri=https%3A%2F%2Fdeveloper.paypal.com%2Fdeveloper%2Faccounts%2F , and then create a new REST app with a new ClientID/Secret for it.
Related
Can somebody tell me why? This is a simple integration of paypal sdk for javascript. And It is working fine except that the event bellow onShippingChange is never fired. I've searching this for 2 days now. I need to update my price according to the user address.
src="https://www.paypal.com/sdk/js?client-id=XXXXXXXXX"> // Required. Replace SB_CLIENT_ID with your sandbox client ID.
</script>
<div id="paypal-button-container"></div>
<script>
paypal.Buttons({
createOrder: function(data, actions) {
// This function sets up the details of the transaction, including the amount and line item details.
console.log('createOrder ' + data);
return actions.order.create({
application_context : {
shipping_preference: 'SET_PROVIDED_ADDRESS'
},purchase_units: [{
shipping: {
address: {
address_line_1: '555 example bs',
admin_area_2: 'San bastard',
admin_area_1: 'CA',
postal_code: '95111',
country_code: 'CA'
}
},
amount: {
value: '0.01'
}
}]
});
},
onApprove: function(data, actions) {
console.log('onApprove ' + data);
// This function captures the funds from the transaction.
return actions.order.capture().then(function(details) {
// This function shows a transaction success message to your buyer.
alert('Transaction completed by ' + details.payer.name.given_name);
});
},
onClientAuthorization: (data) => {
console.log('onClientAuthorization - you should probably inform your server about completed transaction at this point', data);
this.showSuccess = true;
},
onShippingChange: (data, actions) => {
// this event is never fired no matter what I do
console.log('onShippingChange - Shipping information have changed', data, actions);
},
onCancel: (data, actions) => {
console.log('OnCancel', data, actions);
},
onError: err => {
console.log('OnError', err);
},
onClick: (data, actions) => {
console.log('onClick', data, actions);
}
}).render('#paypal-button-container');
//This function displays Smart Payment Buttons on your web page.
</script>
here is the solution of this question first of the shippings fees can only be managed after you enable it on your account (Login to PayPal >> Hover over to the profile name >> Account Settings >> Shipping >> Here you can create shipping profiles as per your requirements.) it will be available only for customer who pay from a paypal account. For any other payment you won't be able to manage it.
Regards
I am using PayPal smart button for payments in JavScript. Currently, I am using sandbox accounts to test.
This code gives an error
function addPaypal()
{
paypal.Buttons({
createOrder: function(data, actions) {
return actions.order.create({
purchase_units: [{
amount: {
currency_code:'USD',
value: '30.00'
}
}]
});
},
onApprove: function(data, actions) {
return actions.order.capture().then(function(details) {
console.log(details);
});
},
onCancel: function (data) {
},
onError: function (err) {
console.log(err)
}
}).render('#paypal-button'); // Display payment options on your web page
}
The error I am getting is
details.purchase_units.amount is undefined
I am using two sandbox accounts. One from which I created an app and using its credentials. And other one from which I am paying the amount for testing.
I checked both accounts. I am not getting more details of the error.
I'm implementing the Paypal Smart buttons to my website for subscription, with the following code:
paypal.Buttons({
commit: false,
createSubscription: function(data, actions) {
return actions.subscription.create({
plan_id: 'P-4688500211745173CL4LO52Y'
});
},
onCancel: function (data) {
},
onApprove: function(data, actions) {
}
}).render('#paypal-button-container');
I subscribed via Debit Or Credit Card (paypal.FUNDING.CARD button). It returns the JSON data for subscription:
{
billingToken: "BA-28952229JX1690450"
facilitatorAccessToken: "A21AAF2g9HmhCrpdlvKv82KzTOL7s-
h7udVM63Jx6PoEQJvhRHUKZXuxdEewBWbAlh7Tta44GREGBKPqydgSaWBdTZBInLTMA"
orderID: "91D07990YA8971453"
subscriptionID: "I-EN0D6RAEFN8R"
}
But when I need to downgrade or upgrade the current subscription using https://api.sandbox.paypal.com/v1/billing/subscriptions/I-EN0D6RAEFN8R/revise API endpoint base on the PayPal docs. https://developer.paypal.com/docs/business/subscriptions/add-capabilities/revise-subscriptions/
The PayPal window automatically close and I get the error: "Uncaught Error: Api: /smart/api/billagmt/subscriptions/I-EN0D6RAEFN8R/cartid returned status code: 500 (Corr ID: e0a949aefc835)"
This is my code to revise subscription:
paypal.Buttons({
commit: false,
createSubscription: function(data, actions) {
return actions.subscription.revise('I-EN0D6RAEFN8R', {
plan_id: 'P-0P5665289K689682KL4MD5PQ'
});
},
onCancel: function (data) {
},
onApprove: function(data, actions) {
}
}).render('#paypal-button-container');
Note: Subscribing via PayPal Account (paypal.FUNDING.PAYPAL button) doesn't have the error that I'm encountering when I subscribe via PayPal Credit Or Debit Card. I can also upgrade or downgrade the subscription plan using the revise code above.
Anybody experienced the same issue?
The behavior makes sense, you need to log into a PayPal account to approve revising a subscription.
When there is nothing to log into, there is no way to approve a revision on the client side. Your own authorized server-side API call is necessary to modify/cancel it. You can have the user sign up again (new profile) and cancel the original one.
My website has products in several currencies up for sale on the same page, so a person can click the product that sold in EUR and pay in euros, or they can click the product that is sold in USD and pay in usd and so on...
The problem is that once you initialise the new PayPal SDK, you cannot change the currency that it accepts without:
destroying the element
changing the link to the SDK, so that it would accept a different currency
manually injecting it into the page
reinitialising it
As you can probably understand it is not very fast, stable or safe at the same time. Am I missing something? I know that you could send the currency as a parameter in the old Express Checkout version.
The PayPal documentation is infuriating, it is missing a lot of information and doesn't have a big community around it, so I could not find the answer to my question anywhere.
I have tried sending the currency in the payment parameters, but if it is different from the initialised currency, it throws a currency mismatch error once you try to confirm the payment.
Right now I am manually reinjecting and reinitialising the paypal SDK with the correct currency if the user clicks on the option of paying with PayPal, but it is slow and requires hardcoding sleep (although it is probably due to my lack of knowledge, there are probably better ways).
Here's the pseudocode of my current setup that is not acceptable:
initialisePaypalSDK(currency) {
destroy old initialisation
change link to paypal with new currency
inject new link to page
initialise the new sdk
sleep until the paypal variable is defined
showPayPalButton()
}
I expect that there is an easier and a safer way of changing the currency than this. Thanks.
You can use a backend to solve this issue.
First, define createOrder function like this:
const createOrder = async (data, actions) => {
return await axios.get('/yourbackend/api/get_order_id')
}
const onApprove = (data, actions) => {
// ... code to handle the payment status
}
paypal.Buttons({createOrder, onApprove}).render('#paypal-button-container')
Then just implement REST Api for order creation (/v2/checkout/orders) on your backend. Then return id of the created payment.
For those using React, this is now possible with the new library #paypal/react-paypal-js. From the README:
The usePayPalScriptReducer hook can be used to reload the JS SDK script when parameters like currency change. It provides the action resetOptions for reloading with new parameters. For example, here's how you can use it to change currency.
// get the state for the sdk script and the dispatch method
const [{ options }, dispatch] = usePayPalScriptReducer();
const [currency, setCurrency] = useState(options.currency);
function onCurrencyChange({ target: { value } }) {
setCurrency(value);
dispatch({
type: "resetOptions",
value: {
...scriptProviderOptions,
currency: value,
},
});
}
return (
<>
<select value={currency} onChange={onCurrencyChange}>
<option value="USD">United States dollar</option>
<option value="EUR">Euro</option>
</select>
<PayPalButtons />
</>
);
You can add the script once the currency has been selected.
let myScript = document.createElement("script");
myScript.setAttribute(
"src",
"https://www.paypal.com/sdk/js?client-id="your cliend id"&components=buttons¤cy=" + currencyVariable
);
let head = document.head;
head.insertBefore(myScript, head.firstElementChild);
myScript.addEventListener("load", scriptLoaded, false);
function scriptLoaded() {
console.log("Script is ready to rock and roll!");
paypal
.Buttons({
style: {
layout: "vertical",
color: "blue",
shape: "rect",
label: "paypal",
},
createOrder: function (data, actions) {
// Set up the transaction
return actions.order.create({
purchase_units: [
{
amount: {
value: traspasoCantidad,
},
payee: {
},
description: "",
},
],
application_context: {
},
});
},
onApprove: function (data, actions) {
return actions.order.capture().then(function (details) {
/* window.location.href = "approve.html"; */
});
},
onError: function (err) {
myApp.alert("Ha ocurrido un error al hacer el traspaso", "ERROR");
},
})
.render("#paypal-button-container");
}
I am using paypal Buttons SDK. The Code activating the button is:-
paypal.Buttons({
createOrder: ( data, actions ) => {
return actions.order.create({
purchase_units: [{
amount: {
value: this.amount.toFixed(2),
currency_code: "GBP",
}
}]
})
},
onApprove: ( data, actions ) => {
return actions.order.capture().then(details => {
console.log('details',details);
})
},
onError: ( error ) => {
console.log('error',error);
}
}).render('#paypal-button-container')
The User Interface operates as expected, there is then a long pause before the error is returned. The client_id used in the script tag is for a sandbox account. I can find not documentation describing possible cause for the error...
error Error: Order could not be captured
Any advice greatly appreciated.
Paypal.. https://developer.paypal.com/docs/checkout/integrate/#1-get-paypal-rest-api-credentials
As suggested in the comment try to do a curl with this URL :
https://www.sandbox.paypal.com/smart/api/order/ODER_ID/capture
And it replies with code 401 and did some research and end up finding that I was using a wrong account to make payments.
I refresh the PayPal login and login with the correct sandbox buyer account and make the payment and It works.
Probably paypal should give correct errors messages.
Can you check using CURL which returns the Paypal server?
This is a comment but I do not have 50pkt S / O. Sorry.
If you get a Xss message in the console, just try in private navigation, disconnect from your paypal buyer account.
I have had the same "Order could not be captured" error at "actions.order.capture()" in the onApprove callback.
In my case, it worked on the first run but not the subsequent calls. I found my order always had the same invoice_id. I removed invoice_id and Paypal stopped complaining.
It should be good if the invoice_id was always unique.
Same problem with Nuxt , checkout works but catch error response : Error 500 order-could-not-be-captured
<template>
<no-ssr>
<v-layout row wrap>
<div ref="paypal"></div>
</v-layout>
</no-ssr>
</template>
Script
mounted() {
const script = document.createElement("script");
script.src =
"https://www.paypal.com/sdk/js?client-id=MyKeyID";
script.addEventListener("load", this.setLoaded);
document.body.appendChild(script);
},
methods: {
setLoaded: function() {
this.loaded = true;
window.paypal
.Buttons({
createOrder: (data, actions) => {
return actions.order.create({
purchase_units: [
{
description: "Test description",
amount: {
currency_code: "USD",
value: 1
}
}
]
});
},
onApprove: async (data, actions) => {
const order = await actions.order.capture();
this.paidFor = true;
console.log(order);
},
onError: err => {
console.log(err);
}
})
.render(this.$refs.paypal);
}