Can't get paypal smart button to accept php value - paypal

I am trying to create a paypal smart button in my php script. I am unable to get values from my php script to the javascript code in the json object. I tried echoing the php directly into the javascript but that didn't work. I tried using the Jquery but that didn't work. Can anyone help me? here is my code:
I tried using Jquery and directly echoing my php into the json object but neither of them worked.
var valueNumber = $("#grandTotal").html();
valueNumberArray = valueNumber.split(">")
valueNumberArray[1] = "'"+valueNumberArray[1]+"'";
alert(valueNumberArray[1]);
paypal.Buttons({
createOrder: function(data, actions) {
return actions.order.create({
purchase_units: [{
amount: {
value: valueNumberArray[1]
}
}]
});//insert JSON above this line
},
onApprove: function(data, actions) {
return actions.order.capture().then(function(details) {
alert('Transaction completed by ' + details.payer.name.given_name);
// Call your server to save the transaction
return fetch('/BurgerJoint/GetOrder.php', {
method: 'post',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify({
orderID: data.orderID
})
});
});
}
}).render('#paypal-button-container');

Please save your file with .php extension. You can assign php value into js variable and pass it to PayPal. I have attached sample code below: I am passing amount value from php variable.`<script>
var total_price= '<?php echo $total_price; ?>';
paypal.Buttons({
createOrder: function(data, actions) {
return actions.order.create({
purchase_units: [{
amount: {
value: total_price
}
}]
});//insert JSON above this line
},
onApprove: function(data, actions) {
return actions.order.capture().then(function(details) {
alert('Transaction completed by ' + details.payer.name.given_name);
// Call your server to save the transaction
return fetch('/BurgerJoint/GetOrder.php', {
method: 'post',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify({
orderID: data.orderID
})
});
});
}
}).render('#paypal-button-container');
</script>`

Related

With PayPal JS SDK, how to conditionally 'run' the onApprove part?

I have implemented a sandbox environment with PayPal JS SDK and the corresponding PHP SDK.
In JavaScript I use:
paypal.Buttons({
createOrder: function(data, actions) {
return fetch('../checkout-sdk/samples/CaptureIntentExamples/CreateOrder.php', {
method: 'post',
headers: {
'content-type': 'application/json'
}
}).then(function(resp) {
respjs = resp.json();
return respjs;
}).then(function(orderData) {
order_id = orderData.id;
return order_id;
});
},
onApprove: function(data, actions) {
return fetch('../checkout-sdk/samples/CaptureIntentExamples/CaptureOrder.php?order_id='+data.orderID, {
method: 'post',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify({
orderID: data.orderID
})
}).then(function(appr_res) {
apprjs = appr_res.json();
return apprjs;
}).then(function(orderData) {
var errorDetail = Array.isArray(orderData.details) && orderData.details[0];
if (errorDetail) {
if (errorDetail.issue === 'INSTRUMENT_DECLINED') {
return actions.restart(); // Recoverable state, per:
// https://developer.paypal.com/docs/checkout/integration-features/funding-failure/
} else {
var msg = 'Sorry, your transaction could not be processed.';
if (errorDetail.description) msg += '\n\n' + errorDetail.description;
if (orderData.debug_id) msg += ' (' + orderData.debug_id + ')';
return alert(msg); // Show a failure message
}
}
// Successful capture! For demo purposes:
console.log('Capture result', JSON.stringify(orderData, null, 2));
})
.catch(function(error) {
console.error("There was a problem with the approval fetch: ", error);
});
},
onError: function(err) {
alert(err);
}
}).render('#paypal-button-container');
When the function createOrder fails, the PHP-script CreateOrder.php should return a message to the javascript SDK so it's possible to inform the customer.
On failing, the onApprove does not needed to 'run'.
How can I change the code to conditionally let 'run' the onApprove function?
I tried something like below on JSLint:
paypal.Buttons({
createOrder: function(data, actions) {
return fetch(url, {
method: "post"
}).then(function(res) {
return res.json();
}).then(function(orderData) {
return orderData.id;
});
},
if (orderData !== false) { // error: Expected ')' and instead saw '!=='.
onApprove: function(data, actions) {
return fetch(url2 + data.orderID, {
method: "post"
}).then(function(res) {
return res.json();
}).then(function(orderData) {
//
});
},
}
}).render("#paypal-button-container");
but JSLint reported: Expected ')' and instead saw '!=='.
How can I conditionally implement an if-then condition there?
onApprove is already conditional on the create being successful and the order being successfully approved by the customer. It will not be called otherwise. You do not need to do anything.

PayPal Smart Button / Orders V2 API Shipping Value

Is it possible to add a customized shipping fee to a PayPal checkout, like the items?
Here's some sample code with static values for reference.
var paypalAmount = {"value":"78.95","breakdown":{"item_total":{"currency_code":"USD","value":"78.95"}}};
var paypalItems = [{"name":"sample item","unit_amount":{"currency_code":"USD","value":"39.95"},"quantity":"1","category":"PHYSICAL_GOODS"},{"name":"sample item2","unit_amount":{"currency_code":"USD","value":"39.00"},"quantity":"1","category":"PHYSICAL_GOODS"}];
createOrder: function(data, actions) {
return actions.order.create({
purchase_units: [{
amount: paypalAmount,
items: paypalItems
}],
headers: {
'content-type': 'application/json'
},
});
}
In "amount" you are passing a "breakdown" object, which takes a "shipping" parameter, as documented here: https://developer.paypal.com/docs/api/orders/v2/#definition-amount_breakdown

PayPal SDK causing "Order could not be captured" error after completing payment

OMG this PayPal system is doing my head in! I have the following code:
<script src="https://www.paypal.com/sdk/js?client-id=MY_CODE_HERE&vault=true"></script>
Then this script:
paypal.Buttons({
createOrder: function(data, actions) {
return actions.order.create({
purchase_units: [{
amount: {
value: parseFloat( window.my_config.amount ),
currency: 'USD',
},
description: window.my_config.description,
invoice_id: invoice_id
}]
});
},
onApprove: function(data, actions) {
return actions.order.capture().then(function(details) {
console.log({ details: details });
// do something here
});
$('#AJAXloadingWrapper').show();
},
onError: function (err) {
// Show an error page here, when an error occurs
console.log("ERROR")
console.dir(err);
}
}).render('#paypalWrapper');
It gets into this bit fine:
onApprove: function(data, actions) {
But when it runs:
return actions.order.capture().then(function(details) {
I get an error and it fails: (no money is taken)
Error
​
code: undefined
​
columnNumber: 55441
​
fileName: "https://www.paypal.com/sdk/js?client-id=xxxx&vault=true"
​
lineNumber: 2
​
message: "Order could not be captured"
What does that even mean? This is an example of what I'm passing into purchase_units:
I'm so close to just calling it quits and saying "we are removing paypal".
UPDATE: In my searching, I keep coming up with people telling me that the issue is probably from PayPal that I'm using duplicated invoice_id's. I know that isn't the case, but maybe I'm passing it along wrong?
return actions.order.create({
purchase_units: [{
amount: {
value: parseFloat( window.my_config.amount ),
currency: 'USD',
},
description: window.my_config.description,
invoice_id: invoice_id
}]
});
},
OK so I'm really hoping my pain will help someone else in the future. I spent hours going over this myself, and then more hours going over it with a PayPal support tech. The eventual solution was to wipe my browsers cache. A bit extreme, but it seems to have sorted it. I wish I'd thought of that before!

Paypal Checkout - don't ask for delivery address for non-members?

I've just started playing with this module:
https://github.com/paypal/paypal-checkout
I'm trying to work out how to can turn off the shipping address for clients. I know in order versions you could do &NOSHIPPING=1 in the URL, but I can't find anything about the API 4 version. My code is:
paypal.Button.render({
// Pass the client ids to use to create your transaction on sandbox and production environments
locale: 'fr_FR',
//env: 'production',
env: 'sandbox',
client: {
sandbox: "...",
production: "..."
},
// Pass the payment details for your transaction
// See https://developer.paypal.com/docs/api/payments/#payment_create for the expected json parameters
payment: function() {
return paypal.rest.payment.create(this.props.env, this.props.client, {
transactions: [
{
amount: {
total: window.my_config.grand_total,
currency: 'EUR',
details: {
"subtotal": window.my_config.price,
"tax": window.my_config.vat_amount
}
},
}
]
});
},
// Display a "Pay Now" button rather than a "Continue" button
commit: true,
// Pass a function to be called when the customer completes the payment
onAuthorize: function(data, actions) {
return actions.payment.execute().then(function() {
console.log('The payment was completed!');
console.log(data, actions)
if (error === 'INSTRUMENT_DECLINED') {
actions.restart();
}
});
},
// Pass a function to be called when the customer cancels the payment
onCancel: function(data) {
console.log('The payment was cancelled!');
},
style: {
shape: 'rect',
size: "medium"
}
}, '#paypalContainerEl');
Use "shipping_preference: 'NO_SHIPPING'."
createOrder: function(data, actions) {
$('#paypalmsg').html('<b>' + 'WAITING ON AUTHORIZATION TO RETURN...' + '</b>');
$('#chkoutmsg').hide()
return actions.order.create({
purchase_units: [{
description: 'GnG Order',
amount: {
value: cartTotal
}
}],
application_context: {
shipping_preference: 'NO_SHIPPING'
}
});
},
You need to pass the no_shipping option under experience in the payment function, like so:
return actions.payment.create(
{
payment:
{
transactions: [
{
amount:
{
total: "10",
currency: 'EUR'
}
}]
},
experience:
{
input_fields:
{
no_shipping: 1
}
}
});
In the docs, here and here. A quick note though, guests will still be asked for their billing address, even though their shipping address will no longer be asked.
For those of you integrating via PayPal REST API in PHP, to set the no_shipping attribute:
apiContext = $this->apiContext;
$payer = new \PayPal\Api\Payer();
$payer->setPaymentMethod('paypal');
$inputFields = new \PayPal\Api\InputFields();
$inputFields->setNoShipping(1); //<-- NO SHIPPING!!!!!!!!!!
$webProfile = new \PayPal\Api\WebProfile();
$webProfile->setName($uid); // <-- UNIQUE NAME FOR THE TRANSACTION
$webProfile->setInputFields($inputFields);
$createProfileResponse = $webProfile->create($apiContext);
$webProfile = \PayPal\Api\WebProfile::get($createProfileResponse->getId(), $apiContext);
$amount = new \PayPal\Api\Amount();
$amount->setCurrency('EUR')
->setTotal($this->deposit_eur);
$transaction = new \PayPal\Api\Transaction();
$transaction->setAmount($amount);
$redirectUrls = new \PayPal\Api\RedirectUrls();
$redirectUrls->setReturnUrl($this->return_url)
->setCancelUrl($this->cancel_url);
$payment = new \PayPal\Api\Payment();
$payment->setIntent('sale')
->setPayer($payer)
->setRedirectUrls($redirectUrls)
->setTransactions(array($transaction))
->setExperienceProfileId($webProfile->getId()); //<-- SET EXPERIENCE PROFILE
try{
$payment->create($apiContext);
} catch (\Exception $ex) {
debug($ex);
exit;
}
$approvalUrl = $payment->getApprovalLink();
For the unlucky lads integrating this via PayPal REST API, using C#, this is a bit trickier.
You create a WebProfile as in the Paypal Repo Example.
var experienceProfile = new WebProfile()
{
name = Guid.NewGuid().ToString(), // required field
input_fields = new InputFields()
{
no_shipping = 1
}
};
var experienceId = experienceProfile .Create(_apiContext).id;
new Payment
{
intent = "sale",
payer = new Payer
{
payment_method = "paypal"
},
transactions = new List<Transaction>
{
// ...
},
redirect_urls = new RedirectUrls
{
return_url = "..",
cancel_url = ".."
},
experience_profile_id = experienceId
};
If anyone runs into this problem with the v2 API REST approach, setting application_context with shipping_preference on create order in the body did work for me.
https://developer.paypal.com/docs/api/orders/v2/#definition-experience_context_base
const response = await fetch(url, {
method: 'post',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${accessToken}`,
},
body: JSON.stringify({
intent: 'CAPTURE',
application_context: {
shipping_preference: 'NO_SHIPPING',
},
purchase_units: []
})
For the new API you need to set the parameter no_shipping=1
https://developer.paypal.com/docs/classic/paypal-payments-standard/integration-guide/Appx_websitestandard_htmlvariables/

Remove shipping address option in PayPal Express Checkout

I am using the JS script recommended by PayPal. It's working well, however it is showing a "Ship to" address of the buyers.
I am trying to search the internet and found that https://api.sandbox.paypal.com/v1/payment-experience/web-profiles/ requested with "no_shipping": 1, can do the trick. But for that we need to make a curl request before the payment.create, so that we can pass it returned id in the function.
Is this possible in JS?
Or is there a much better and simpler way to remove it using the following JS?
<script src="https://www.paypalobjects.com/api/checkout.js" data-version-4></script>
<script>
paypal.Button.render({
env: 'sandbox', // Optional: specify 'sandbox' or 'production'
client: {
sandbox: '{{$data['SandboxId']}}',
production: '{{$data['ProductionId']}}'
},
payment: function() {
var amount = document.getElementById("amount").value;
var env = this.props.env;
var client = this.props.client;
return paypal.rest.payment.create(env, client, {
transactions: [
{
amount: {
total: amount,
currency: "USD",
details: {
subtotal: amount,
tax: "0.00",
shipping: "0.00"
}
},
description: "This is payment description.",
item_list: {
items:[
{
quantity:"1",
name:"Orders",
price:amount,
sku:"product12345",
currency:"USD"
}
],
},
}],
});
},
commit: false, // Optional: show a 'Pay Now' button in the checkout flow
onAuthorize: function(data, actions) {
console.log(data);
alert('confirmation here');
// Optional: display a confirmation page here
return actions.payment.execute().then(function() {
alert('Success here');
// Show a success page to the buyer
});
},
}, '#paypal-button');
</script><div id="paypal-button" ></div>
To expand on Bluepnume's answer, here is a complete example:
payment: function(data, actions) {
return actions.payment.create({
payment: {
transactions: [
{
amount: { total: '1.00', currency: 'USD' }
}
]
},
experience: {
input_fields: {
no_shipping: 1
}
}
});
},
You can pass an experience options like so:
paypal.rest.payment.create({
// payment options here
}, {
// experience options here
});
This is how it needs to be done in ngx-paypal version 11
application_context:
{
shipping_preference: "NO_SHIPPING"
}
ngx-paypal: "^11.0.0"