I try to integrate Paypal as a payment method.
When the User clicks on "checkout", it should be able that the user click's on 'direct to paypal' to do the express checkout. Or going the "normal" way, entering his shipping data and clicks on the last page "pay with paypal"
I follow the Paypal REST API documentation and the express checkout works fine. But I didn't get the "normal" checkout to run.
The problem isn't in the backend. So all backend operations (create payment, accept payment, etc.) running well.
But in the frontend I'm getting errors.
My Code for the Express checkout is:
<script type="text/javascript" src="https://www.paypalobjects.com/api/checkout.js?ver=4.6.1">
//....
if (jQuery('#paypal_express_btn_div').length > 0) {
paypal.Button.render({
env: 'sandbox'
payment: function(resolve, reject) {
var orderId = jQuery("#orderPostId").val();
// Set up the payment here, when the buyer clicks on the button
var CREATE_PAYMENT_URL = ajaxObject.ajaxURL;
paypal.request.post(
CREATE_PAYMENT_URL,
{
action: 'create_paypal_payment',
orderId: orderId,
}
)
.then(function(data) {
resolve(data.paymentID);
})
.catch(function(err) {
reject(err);
});
},
onAuthorize: function(data, actions) {
//After the reload, a confirm page will be shown
window.location = data.returnUrl;
},
onCancel: function(data, actions) {
return actions.redirect();
},
}, '#paypal_express_btn_div');
}
As I said, this works well.
When the user clicks the button, the method "create_paypal_payment" runs on the backend. The payment get's created and when the payment is created, the paypal window get's shown to the user.
Now he can confirm the payment by clicking "next". Then (after the page reload) a confim page is shown to the user (with all payment and shipping data) and when he clicks "confirm payment" everything is fine.
But now I try to do the payment at the end of the order. (So the user has entered his shipping data etc.)
The first steps running well. So I can create the payment in the backend.
But now I'm getting an error when I try to run the payment execute method in the "onAuthorize" Action. My method "executePayPerPayPalBasic" will not be executed. I'm getting directly an error.
My Code:
if (jQuery("#paypal_btn_div").length > 0) {
var RS_IB_PAYMENT_URL = ajaxObject.ajaxURL;
paypal.Button.render({
env: 'sandbox'
commit: true, //button "pay now" in the paypal window
payment: function(resolve, reject) {
var orderId = jQuery("orderPostId").val();
// Set up the payment here, when the buyer clicks on the button
paypal.request.post(
RS_IB_PAYMENT_URL,
{
action: 'create_paypal_payment',
orderId: orderId,
}
)
.then(function(data) {
resolve(data.paymentID);
})
.catch(function(err) {
reject(err);
});
},
onAuthorize: function(data, actions) {
// Execute the payment here, when the buyer approves the transaction
var payerID = data.payerID;
var paymentID = data.paymentID;
var paymentToken = data.paymentToken;
var returnUrl = data.returnUrl;
paypal.request.post(
RS_IB_PAYMENT_URL,
{
action: 'executePayPerPayPalBasic',
orderId: orderId,
payerID: payerID,
paymentID: paymentID,
paymentToken: paymentToken,
returnUrl: returnUrl
}
)
.then(function(data) {
var paypallink = data.data["PERMALINK"];
window.location = paypallink;
})
.catch(function(err) {
reject(err);
});
}
}, '#paypal_btn_div');
}
The error:
"Error: window.paypal<["./node_modules/post-robot/src/drivers/receive/types.js"]/exports.RECEIVE_MESSAGE_TYPES<#https://www.paypalobjects.com/api/checkout.js:3319:40
receiveMessage#https://www.paypalobjects.com/api/checkout.js:1444:13
messageListener#https://www.paypalobjects.com/api/checkout.js:1462:13
"
Another strange thing is, as I understand, normaly the "commit" parameter should handle if the paypal button is "pay now" or "next".
Because of this, I'm not set the parameter in my express checkout (because I want the "next" button) and setting the parameter to true in my normal checkout.
But since I used the commit Parameter 1 time. I always getting the "pay now" button. Even in my Express Checkout Button.
I have tried to set the parameter to false manually. But it doensn't work.
I tried this with Firefox, Google Chrome and Microsoft Edge.
The error only occurs on Firefox.
In Google Chrome and Microsoft Edge it works like a charm.
But on each of these three Browsers the Button Text has the Text "pay now" and never shows "next".
Also, all payments are marked as Paypal Express Payments. Is there any Parameter to check my second code als 'normal' payment. Or is it normal, that when I do the payment with the checkout.js all payments are marked as Express Payment?
Where is my failure? Can anybody help me?
Related
i have a Django Store Website which use Paypal for payment
but in my views.py,Django do everything except go to the directed page that i choose
this is my views.py
def capture(request,id):
do some stuff
return redirect(reverse("shop:success"))
and this is JavaScript
<script type="text/javascript">
function completeOrder(){
var url = "{% url 'shop:paypal' id=orders.id %}"
fetch(url, {
method:'POST',
headers:{
'Content-type':'application/json',
'X-CSRFToken':csrftoken,
},
body:JSON.stringify("{{orders.id}}")
})
}
// Render the PayPal button into #paypal-button-container
paypal.Buttons({
style: {
layout: 'horizontal',
color:"blue",
label:"checkout",
tagline:"false",
shape:"pill",
size:"small",
},
// Set up the transaction
createOrder: function(data, actions) {
return actions.order.create({
purchase_units: [{
amount: {
value: '{{orders.converter}}'
}
}]
});
},
// Finalize the transaction
onApprove: function(data, actions) {
return actions.order.capture().then(function(details) {
// Show a success message to the buyer
completeOrder()
alert('Transaction completed by ' + details.payer.name.given_name + '!');
});
}
}).render('#paypal-button-container');
</script>
Do not use actions.order.create() and actions.order.capture() to create+capture on the client side and then call a server with fetch after a client-side capture. This is thoroughly bad design when using a server.
Instead, switch to a proper server-side integration: make two routes on the server, one for 'Create Order' and one for 'Capture Order', documented here; there is a Checkout-Python-SDK you can use. These two 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 your two routes with the following approval flow: https://developer.paypal.com/demo/checkout/#/pattern/server
In the success code of that flow, the redirect can be done with actions.redirect(), or simply setting window.location.href (general JavaScript solution)
I am using the PayPal javascript SDK to create a Paypal subscription button for my web page, the problem resides when testing the button using a sandbox account in which after performing all the payment for the subscription the following error appears:
Error: Use intent=capture to use client-side capture ...
Here's my HTML script used to show my pay PayPal button
<script src="https://www.paypal.com/sdk/js?client-id=MY_CLIENT_ID&vault=true&intent=subscription&components=buttons"></script>
<div id="paypal-button-container"></div>
Heres my js file which performs the respective handlers depending on the actions and status of the payment:
paypal.Buttons({
style: {
shape: 'rect',
color: 'black',
layout: 'vertical',
label: 'subscribe'
},
createSubscription: function(data, actions) {
if (discordUser.value === "") {
alert("Introduce tu usuario de discord");
return;
}
slotDecremented = true;
alterSlots();
return actions.subscription.create({
'plan_id': 'P-ID' // here is my plan id
});
},
onApprove: function(data, actions) {
return actions.order.capture().then(function(details) {
sendEmailToken(details.payer.email_address, discordUser.value, data.subscriptionID);
});
},
onCancel: function(data) {
alterSlots(true);
slotDecremented = false;
},
onError: function(data) {
if (!slotDecremented) {
return;
}
alterSlots(true);
slotDecremented = false;
}
}).render('#paypal-button-container');
the alterSlot() function makes an API call with AJAX to my specific endpoint, just extra information if neccesary
EDIT:
The sendEmailToken() function makes an AJAX request to an API hosted on my server, such that the server performs the correct action and being secure (just metadata for knowing what's going on in that part)
onApprove: function(data, actions) {
return actions.order.capture().then(function(details) {
sendEmailToken(details.payer.email_address, discordUser.value, data.subscriptionID);
});
},
actions.order.capture() is for a client-side one-time payment button. It does not belong in a Subscribe button, as there is no order to capture.
See e.g. the PayPal Subscriptions documentation, which only has a basic success alert in its onApprove example: https://developer.paypal.com/docs/subscriptions/integrate/#create-the-subscription
Since it appears your intent is to perform a server-side operation such as sending an email after subscription approval, you should be activating said subscription from your server to ensure subscriptions don't become active without your server being correctly being notified of this fact. Here is some information: https://stackoverflow.com/a/65139331/2069605
I followed this documentation and my stripe checkout is not working. I have taken out the sku and pk from the SO snippet below but can anybody see what I have done wrong as I thought I implemented it correctly.
When I click the buy now link, nothing happens, don't even redirect to the checkout page.
HTML link:
<a class="buy-btn">Buy Now</a>
...
Javascript:
<script>
(function () {
var stripe = Stripe('pk_test_xxx');
var checkoutButton = document.getElementsByClassName('buy-btn');
checkoutButton.addEventListener('click', function () {
// When the customer clicks on the button, redirect
// them to Checkout.
stripe.redirectToCheckout({
items: [{ sku: 'sku_xxx', quantity: 1 }],
// Do not rely on the redirect to the successUrl for fulfilling
// purchases, customers may not always reach the success_url after
// a successful payment.
// Instead use one of the strategies described in
// https://stripe.com/docs/payments/checkout/fulfillment
successUrl: window.location.protocol + '//www.xxx-online.com/xxx-leap/success',
cancelUrl: window.location.protocol + '//www.xxx-online.com/xxx-leap/cancelled',
})
.then(function (result) {
if (result.error) {
// If `redirectToCheckout` fails due to a browser or network
// error, display the localized error message to your customer.
var displayError = document.getElementById('error-message');
displayError.textContent = result.error.message;
}
});
});
})();
I am using star-rating plugin in vue js, and I am using v-model to show the ratings from db. Everything works fine as when user is not logged in and he/she tries to rate it shows an error "login to rate", but the stars dont reset to db value instead it shows the rating of not logged in user. Currently after the error msg I am refreshing the whole page. Is there a simple way to reset the stars instead of refreshing the whole page?
:show-rating="false" #rating-selected="setRating" v-model="rating"
v-bind:star-size="20"
above is the start rating and while clicking it calls a function where I am checking if user is logged in or not with an api call. Thanks in advance.
setRating: function (rating) {
axios.get('/checkuser').then(response => {
this.user = response.data;
if (this.user === "Logout") {
toastr.error('Please login to rate', 'Error', {
positionClass: 'toast-bottom-right'
});
window.location = "/menu/" + this.menu_id;
} else {
// save in to db
}
}).catch(error => {
// TODO: Handle error
});
},
You will have to reset rating object if it's not logged in.
setRating: function (rating) {
axios.get('/checkuser').then(response => {
...
if (this.user === "Logout") {
...
this.rating = 0; <=== reset rating here (in data, not the rating parameter)
}
...
})
...
},
managed to fix it by using "this.load()" after the api call, which refreshes all components. :)
I've a problem with my sandbox app. I integrated the script given for the paypal checkout express payment in my web app. This the script :
<script src="https://www.paypalobjects.com/api/checkout.js"></script>
<div id="paypal-button-container"></div>
<script>
var total = 0;
$.getJSON("/Home/getTotal", function (result) {
total = result;
});
// Render the PayPal
paypal.Button.render({
// Set your environment
env: 'sandbox', // sandbox | production
// Specify the style of the button
style: {
label: 'buynow',
fundingicons: true, // optional
branding: true // optional
},
// PayPal Client IDs - replace with your own
// Create a PayPal app: https://developer.paypal.com/developer/applications/create
client: {
sandbox: 'AT9iydEDhcqfM_dhU8MR0lvkFgZBjD1oXQVrG-CR9CyK_vd-aXpNzEnyVV7um_hAPrkqQX8JhtjGCbBt'
},
// Wait for the PayPal button to be clicked
payment: function (data, actions) {
return actions.payment.create({
transactions: [
{
amount: { total: total, currency: 'USD' }
}
]
});
},
// Wait for the payment to be authorized by the customer
onAuthorize: function (data, actions) {
return actions.payment.execute().then(function () {
window.alert('Payment Complete!');
});
}
}, '#paypal-button-container');
</script>
This code displays a paypal button. When I click on the button, it shows me a login page to proceed to the payement. The problem is : I can't login on this page with a paypal account that I have. I read somewhere that only the sandbox's test accounts can be used to login on this page, but I want to let everyone who has a paypal account login in this page. What should I do ? Thank you for your answers!
I've found the solution : if you want to let everybody login into your payment's page, you've to pass to production mode.