PayPal Smart Payment Buttons error paypal.Buttons is not a function - php

I am integrating Smart Payment Buttons in my website, before it works properly, but earlier today, I am getting these errors
I loaded paypal SDK before I even loaded the paypal.Buttons().render() function which is inside my paypal.js file
<script src="https://www.paypal.com/sdk/js?client-id=<MY_CLIENT_ID_HERE>&currency=PHP"></script>
<script type="text/javascript" src="paypal.js"></script>
this is the content of my paypal.js file
paypal.Buttons({
createOrder : function(data, actions){
return actions.order.create({
purchase_units : [{
amount : {
value : amount_to_pay
}
}],
application_context: {
shipping_preference: "NO_SHIPPING",
},
country_code : "PH"
})
},
style: {
color: 'gold',
shape: 'rect',
label: 'buynow',
size: 'responsive',
branding: true
},
onApprove: function(data, actions) {
// Capture the funds from the transaction
return actions.order.capture().then(function(details) {
return fetch('/pay-with-pp', {
method: 'post',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify({
orderID: data.orderID,
product_id : product_id,
_token : token
})
}).then(function(res){
alert('Payment has been made! Please see the delivery status on orders page!');
window.location.href = redirect_url
});
});
},
}).render('#paypal-button-container');

I analyzed the errors carefully and found out the solution.
I added a data-namespace attribute to the script tag that loads the SDK
<script src="https://www.paypal.com/sdk/js?client-id=AaJMejIDjhumOr48XsycjfvQegxAku1dHdrA0DNfkqFSg7bFFkpJTnnwyaLIGUFsPijWx1g51gxp9F-5&currency=USD" data-namespace="paypal_sdk"></script>
then use the value of data-namespace in my paypal.js file
so instead of
paypal.Buttons().render()
i used
paypal_sdk.Buttons().render()
and it works!

(I got this error in ReactJs)
Make sure you're loading the <script> tags properly - to which I mean, don't delay their loading by adding things like the defer attribute, otherwise paypal.Buttons() is called before the script tags are called, hence the error.
I don't know if 2 years down the line since this question was asked whether my answer will be at all helpful.

Related

How to capture transaction data generated from PayPal smart button payment with PHP

I am trying to implement PayPal payment using a smart button with a script provided by PayPal:
<div id="smart-button-container">
<div style="text-align: center;">
<div id="paypal-button-container"></div>
</div>
</div>
<script src="https://www.paypal.com/sdk/js?client-id=MY_CLIENT_ID&currency=CAD" data-sdk-integration-source="button-factory"></script>
<script>
function initPayPalButton() {
paypal.Buttons({
style: {
shape: 'rect',
color: 'gold',
layout: 'horizontal',
label: 'pay',
},
createOrder: function(data, actions) {
return actions.order.create({
purchase_units: [{"description":"Package delivery","amount":{"currency_code":"CAD","value":1}}]
});
},
/* onApprove: function(data, actions) {
return actions.order.capture().then(function(details) {
alert('Transaction completed by ' + details.payer.name.given_name + '!');
});
}, */
onApprove: function(data) {
return fetch('/my-server/capture-paypal-transaction.php', {
headers: {
'content-type': 'application/json'
},
body: JSON.stringify({
orderID: data.orderID
})
}).then(function(res) {
return res.json();
}).then(function(details) {
alert('Transaction funds captured from ' + details.payer_given_name);
})
},
onError: function(err) {
console.log(err);
}
}).render('#paypal-button-container');
}
initPayPalButton();
</script>
I replaced the commented code with the function below that suggests one can link to a file on the server to process the returned data.
I can find no clear instruction on how this can be done with this PayPal-generated button and all the git examples relating to IPN is either outdated or has deprecated PHP code such as references to magic-quotes.
Is there an example PHP file on capturing the transaction data from a smart button?
Your example mixes a client-side actions.order.create() with a fetch to do a server-side capture. This mixing should not be done. Perform both steps from the server (or neither if not using a server-side language like PHP)
So, create two routes on your server, one for 'Create Order' and one for 'Capture Order', documented here. These routes should return only JSON data (no HTML or text). The latter one should (on success) store the payment details in your database before it does the return (particularly purchase_units[0].payments.captures[0].id, the PayPal transaction ID)
Pair those two routes with the following approval flow: https://developer.paypal.com/demo/checkout/#/pattern/server

Php Paypal Express checkout: How to pay through server side request

Hello I am using Express checkout for my one of project. This is first time i am working with paypal.
I have following code.
var CREATE_PAYMENT_URL = '<?php echo site_url().'/cart/' ?>create-payment';
var EXECUTE_PAYMENT_URL = '<?php echo site_url().'/cart/' ?>execute-payment';
paypal.Button.render({
env: 'sandbox', // sandbox | production
intent:'authorize',
style: {
size: 'medium', // small | medium | large | responsive
shape: 'rect', // pill | rect
tagline: false
},
funding: {
allowed: [paypal.FUNDING.CREDIT]
},
client: {
sandbox: '<?php echo $this->config->item('clientId'); ?>',
},
payment: function (data, actions) {
return paypal.request.post(CREATE_PAYMENT_URL).then(function(data) {
return data.id;
});
},
// Wait for the payment to be authorized by the customer
onAuthorize: function (data, actions) {
return paypal.request.post(EXECUTE_PAYMENT_URL, {
paymentID: data.paymentID,
payerID: data.payerID
}).then(function() {
alert('payment completes!');
});
},
}, '#paypal-button-container');
Now i want to pay through server side api call. I searched a lot but not getting proper documents for it. I don't know how to pay through server side api.
Don't know what is wrong with documents. They are never adding proper information for integration.

Bug with PayPal API context checkout

I have a problem with PayPal Express Checkout integration : https://developer.paypal.com/docs/classic/express-checkout/in-context/javascript_advanced_settings/#color
If I close the pop-up before it loads completely, the pop-up won't show up anymore until I refresh!
This does occur on all browsers. The error on Chrome console is:
ppxo_paypal_legacy_gettoken_initxo Object
print # logger.js:65
Here is my code :
window.paypalCheckoutReady = function() {
paypal.checkout.setup("{$PayPal_in_context_checkout_merchant_id}", {
environment: {if $PAYPAL_SANDBOX}"sandbox"{else}"production"{/if},
click: function(event) {
event.preventDefault();
paypal.checkout.initXO();
updateFormDatas();
var str = '';
if($('.paypal_payment_form input[name="id_product"]').length > 0)
str += '&id_product='+$('.paypal_payment_form input[name="id_product"]').val();
if($('.paypal_payment_form input[name="quantity"]').length > 0)
str += '&quantity='+$('.paypal_payment_form input[name="quantity"]').val();
if($('.paypal_payment_form input[name="id_p_attr"]').length > 0)
str += '&id_p_attr='+$('.paypal_payment_form input[name="id_p_attr"]').val();
$.support.cors = true;
$.ajax({
url: "{$base_dir_ssl}modules/paypal/express_checkout/payment.php",
type: "GET",
data: '&ajax=1&onlytoken=1&express_checkout='+$('input[name="express_checkout"]').val()+'&current_shop_url='+$('input[name="current_shop_url"]').val()+'&bn='+$('input[name="bn"]').val()+str,
async: true,
crossDomain: true,
success: function (token) {
var url = paypal.checkout.urlPrefix +token;
paypal.checkout.startFlow(url);
},
error: function (responseData, textStatus, errorThrown) {
alert("Error in ajax post"+responseData.statusText);
paypal.checkout.closeFlow();
}
});
},
buttons: [
{
container: 'paypal_process_payment',
type: 'checkout',
color: 'blue',
size: 'small',
shape: 'pill'
},
{
container: 'payment_paypal_express_checkout',
type: 'checkout',
color: 'gold',
size: 'small',
shape: 'pill'
}
]
});
};
I ran into the same issue,
After looking into the source code, it turns out that when paypal.checkout.initXO(); the paypal.checkout.startFlow function is wrapped in a once function, which means you can only call startFlow once. and paypal.checkout.initXO is overwritten to show a warning in the console.
Inside, paypal.checkout.closeFlow there is a call to paypal.checkout.reset which is important to resetting these functions.
The problem was happening when the user clicks the close button too early, where the startFlow promise wasn't being resolved (which means when the user closes the modal it will redirect to the canceled url) nor the paypal.checkout.closeFlow catch wasn't being hit either.
I was able to resolve the issue, by keeping track of how many times the user clicked the button, if it was more than once, I called paypal.checkout.closeFlow (which will reset) beforepaypal.checkout.initXO();

Passing JSON data from a PHP page as a Javascript variable

In the middle of a PayPal Checkout Express (client-side) javascript, I need to use AJAX to call the output of a PHP page, but I'm a bit stuck.
The PHP page:
$data = array('retid' => $username);
header('Content-Type: application/json');
echo json_encode($data);
Now inside the other javascript page I simply want to capture the PHP variable $username, via AJAX, as a javascript variable.
<?php
$IDToPassPlus = ($id.'&retid=');
?>
<script>
//It's the inclusion of this part, which tries to get the "retid" js variable, that stops the script from rendering the Paypal button:
$.ajax({
type: 'POST',
url: 'test-call.php',
dataType: 'json',
success: function(response) {
var retid = response.data.retid;
},
});
paypal.Button.render({
env: 'sandbox',
client: {
sandbox: 'xxxxx',
production: 'xxxxx'
},
commit: true,
style: {
layout: 'vertical',
size: 'responsive',
shape: 'rect',
color: 'gold'
},
payment: function(data, actions) {
return actions.payment.create({
payment: {
transactions: [
{
amount: { total: '0.99', currency: 'GBP' }
}
],
redirect_urls: {
'cancel_url': 'pay-return-cancel.php?id=<?php echo $IDToPassPlus; ?>'+retid
}
}
});
},
onAuthorize: function(data, actions, error) {
return actions.payment.execute().then(function() {
window.alert('Payment Complete!');
window.location.replace('test-return.php?id=<?php echo $IDToPassPlus; ?>'+retid);
if (error === 'INSTRUMENT_DECLINED') {
actions.restart();
}
});
},
onCancel: function(data, actions) {
return actions.redirect();
},
onError: function(err) {
window.location.replace('pay-return-error.php?id=<?php echo $id; ?>'+retid);
}
}, '#paypal-button');
</script>
Without the contributor's AJAX suggestion, the button works perfectly. But I'm trying to pass a variable from a PHP page by way of AJAX, to add it onto the redirects.
it's possible to use on in-page javascript as
<script>
var js_var = "<?php echo $php_var;?>";
//now you have php var value in javascript to use on .php page
If it's not what you are seeking, then please elaborate your question.
ok so as far I understood you want to retrieve the PHP response via ajax and you don't know how to make ajax call. Here is an example you may use on your js file:
$.ajax({
type: 'POST',
url: 'YOUR PHP SCRIPT URL',
dataType: 'json',//this will make it understand what datatype to expect in response
success: function(response) {
var retid = response.data.retid; //here you get on successfull response
},
});
First, read this entire page; it will really help you throughout your career as a developer, it has helped me tremendously: https://stackoverflow.com/help/mcve
Then, lets use the knowledge gained from that page to make an MCVE. Put this on a new page:
$.ajax({
type: 'POST',
url: 'test-call.php',
dataType: 'json',
success: function(response) {
var retid = response.data.retid;
console.log(retid);
},
});
This should print the value of retid to your console. Take a look at your console. Notice any errors, or does the value of retid print as expected?
So why have we taken time to create a new page and put this on it? We are narrowing down our issue, we're trying to find the exact cause of the problem by creating an MCVE. If we don't know what is causing the problem, and if we can't create a very basic example to illustrate the problem, we will have a hard time solving the problem and/or asking for help.
(Note 1, make your code "pretty" when you post it here. Indent it as it should be indented; this makes it easier for others to read. You are asking people to take time out of their day to help you, for free; make it as easy as possible for them to read and understand your code)
(Note 2, here is an example of where I had some very, very complicated MySQL interactions that I had a question about. Rather than post all of the complicated code, I followed the MCVE concept: DRY - how to extract repeated code to...a stored function maybe? and made some fake, very very simplified examples of my problem. Since I did that, I was able to get quick, concise answers from experts, notice the answer I accepted was from one of the top-scored users on all of Stackoverflow)

PAYPAL PAYMENT Client Side REST SCRIPT

I have integerated PayPal Client Side REST to my website. I have used the sample code provided from link below:
https://developer.paypal.com/demo/checkout/#/pattern/client
This code below worked over a month, however today it shows below error
Error: Request to post https://www.sandbox.paypal.com/v1/payments/payment
failed with 400 error
{
"name": "MALFORMED_REQUEST",
"message": "Incoming JSON request does not map to API request",
"information_link": "https://developer.paypal.com/webapps/developer/docs/api/#MALFORMED_REQUEST",
"debug_id": "a26904ff6211a"
}
my code follows:
<div id="paypal-button-container" class="info"></div><script src="https://www.paypalobjects.com/api/checkout.js"></script>
<script>
// Render the PayPal button
paypal.Button.render({
// Set your environment
env: 'production', // sandbox | production
// PayPal Client IDs - replace with your own
// Create a PayPal app: https://developer.paypal.com/developer/applications/create
client: {
sandbox: '<?=SANDBOXPAYPAL?>',
production: '<?=PAYPAL_TOKEN?>'
},
// Set to 'Pay Now'
commit: true,
// Wait for the PayPal button to be clicked
payment: function() {
$('#card').attr('checked',true);
// Make a client-side call to the REST api to create the payment
return paypal.rest.payment.create(this.props.env, this.props.client, {
transactions: [
{
amount: { total: '12.99', currency: 'GBP' }
}
]
});
},
// Wait for the payment to be authorized by the customer
onAuthorize: function(data, actions) {
jQuery.ajax({
type: "POST",
url: "ipn.php",
data: data,
success: function(data){
}
});
return actions.payment.execute().then(function() {
document.querySelector('#paypal-button-container').innerText = 'Payment Complete!';
});
}
}, '#paypal-button-container');
</script>
Your code does not quite match the example, but I am also using the client-sdie API from a Laravel Shoping Cart I am building, I use AJAX to push the payment data back to my system this way:
onAuthorize:function(data, actions)
{
console.log("onAuthorize()");
console.log("Dumping DATA");
console.log(data);
console.log("Dumping ACTIONS");
console.log(actions);
return actions.payment.execute().then(function(payment)
{
console.log("payment.execute called");
document.querySelector('#paypal-button-container').innerText = 'Payment Complete!';
console.log("Dumping payment:");
console.log("CART: "+payment['cart']);
console.log(payment);
var values = encodeURIComponent(JSON.stringify(payment));
$.ajaxSetup({headers:{'X-CSRF-TOKEN':'{{ $token }}' } } );
ajaxRequest= $.ajax({ url: "/ajax/payment", type: "post",data:values });
ajaxRequest.done(function(response, textStatus, jqXHR)
{
var result = $.parseJSON(response);
console.log(result);
});
});
},
/ajax/payment is my capture script i'm developing at present but it does record all the data from the purchase.. hope it helps.

Categories