PayPal as secondary payment option in Braintree - javascript

We're currently struggling with Braintree PayPal payment in combination with regular bank transfer via IBAN. Basically, we present two subscription options to the visitor: PayPal (via Braintree) and IBAN transaction.
The PayPal method works fine but when we don't select PayPal but IBAN bank transfer, we're getting the following console error:
We understand that this is the correct behaviour since the PayPal fields are not filled, but how is it possible to have PayPal as an optional payment method without throwing an error when the fields are not filled?
We're using the basic js implemetion via DropUI.
<div class="bt-drop-in-wrapper" id="showpaypalfields">
<div id="bt-dropin" class="paypaldiv"></div>
</div>
<script src="https://js.braintreegateway.com/js/braintree-2.27.0.min.js"></script>
<script>
var client_token = "123TOKEN";
braintree.setup(client_token, "dropin", {
container: "bt-dropin"
});
</script>
UPDATE:
Both forms are visible on the page instantly, they are not loaded afterwards via Ajax or any kind. So, the PayPal option via Braintree should only validate if for example a checkbox is set. For example, the checkbox given in the screenshot below (toggles visibility of both fieldsets).
UPDATE #2:
For anyone interested in the final solution:
var btInstance;
$('input#paymentmethod-1').change(function(){
if ( $(this).is(':checked') == true ) {
teardown();
}
});
$('input#paymentmethod-2').change(function(){
if ( $(this).is(':checked') == true ) {
setup();
}
});
function setup() {
if (btInstance) {
return;
} else {
var client_token = "<ps:braintreetoken />";
braintree.setup(client_token, "dropin", {
container: "bt-dropin",
onReady: function (bt) {
btInstance = bt;
}
});
}
}
function teardown() {
if (!btInstance) {
return;
}
btInstance.teardown(function () {
btInstance = null;
});
}

Full disclosure: I work at Braintree. If you have any further questions, feel free to contact support.
Drop-in UI is still loaded when you select the Lastschrift payment option, which is why you're receiving the validation errors.
One way to avoid these validation errors is to use the 'teardown' method in the 'onReady' callback in braintree.js to remove the Drop-in UI if a customer selects Lastschrift.
Alternatively, you can separate each of these payment methods into entirely different form elements on your page.

Related

How to have a custom handler instead of a PayPal button in React?

I have a website with multiple payment forms. I can switch between them and then I have a button with "Continue to checkout" label that when you click, it does something depending on the payment method chosen. The handler function looks something like this:
const handlePayment = (method) => {
if(method === paymentMethods.STRIPE){
// do something
}
if(method === paymentMethods.PAYPAL){
// do something else
}
}
The problem is I looked at the docs and it's always about showing a PayPal button, I don't want a PayPal button, I want to open the PayPal form directly from my button, when a method is selected.
So want I mean is, I want to do it programmatically. Is there any way to do this? I don't want to do a hacky solution hiding the button or triggering the click or some weird thing...
The React PayPal component is just a wrapper for the JS SDK.
My UI looks something like this: I'd like to open the PayPal payment form when I click on Pay, only if PayPal is selected.
If you use the PayPal JS SDK to open the checkout, you have to use its button, and the user has to click it themselves. PayPal does this intentionally so that the button shown uses their consistent branding.
If you want an alternative, you can integrate without the JS SDK (REST API only) and have your own button which redirects to the PayPal page for approval, which will then return to your site. This is an old integration pattern, for old websites, and not recommended.
Despite your misgivings and desire not to use it, the JS SDK and its button in a container sized to your requirements is in fact the best available solution.
Based on the UI shown, what you might op to do is hide your "Pay" button and replace it with one that says "Pay With PayPal" when that method is selected, which could look like this (sized to fit your container):
Here's sample HTML/JS for that, you can do the same from react-paypal-js :
<script src="https://www.paypal.com/sdk/js?client-id=test&currency=USD"></script>
<div id="paypal-button-container"></div>
<script>
paypal.Buttons({
fundingSource: paypal.FUNDING.PAYPAL,
style: {
color: "blue",
label: "pay"
},
// Set up the transaction
createOrder: function(data, actions) {
return actions.order.create({
purchase_units: [{
amount: {
value: '88.44'
}
}]
});
},
// Finalize the transaction
onApprove: function(data, actions) {
return actions.order.capture().then(function(orderData) {
// Successful capture! For demo purposes:
console.log('Capture result', orderData, JSON.stringify(orderData, null, 2));
var transaction = orderData.purchase_units[0].payments.captures[0];
alert('Transaction '+ transaction.status + ': ' + transaction.id + '\n\nSee console for all available details');
// Replace the above to show a success message within this page, e.g.
// const element = document.getElementById('paypal-button-container');
// element.innerHTML = '';
// element.innerHTML = '<h3>Thank you for your payment!</h3>';
// Or go to another URL: actions.redirect('thank_you.html');
});
}
}).render('#paypal-button-container');
</script>

Trouble using session storeage to show message after form submission

I am trying to use session storage to show a message once a form has been submitted. I have it working to a point, but wanted to know if there is a better to optimise this code? Thanks in advance
Caling the function here;
$(document).on('click', '#submit', function() {
window.history.replaceState(null, null, "?account=pending");
$(this).addClass('active');
$('.reset__button').removeClass('active');
$('.create_account_b2b').hide();
$('.login_account_b2b').show();
$('.reset_password_b2b').hide();
handleMessage();
});
Here is the function that with session storage
function handleMessage(){
var create = sessionStorage.getItem('account');
if(create == '1'){
// display the under review message here
sessionStorage.setItem('account','0');
$('p.login-message').text('Your Account Is Currently Under Review and we will be in touch within 2 weeks');
} else {
// toggle back to orginal message
sessionStorage.setItem('account','1');
$('p.login-message').text('Please login to access our Wholesale store');
}
}
handleMessage();
You could combine the Jquery part togerther.
$('.create_account_b2b, .reset_password_b2b').hide();
And
function handleMessage(action = 'login'){
// Default Message
$('p.login-message').text('Please login to access our Wholesale store');
if(action == 'create') {
$('p.login-message').text('Your Account Is Currently Under Review and we will be in touch within 2 weeks');
}
}
Now that we have added a default parameter string as login, on your page refresh you would see the login message.
Call the handleMessage function in your form submission by passing the parameter as
handleMessage('create')

Stripe Javascript library confirmCardPayment not returning

I'm attempting to use Stripe as a payment method, on an ASP.Net MVC project
We've gone the route of using stripe elements to define our own look and feel for the card details.
I've followed the tutorials, and have managed to get the card widgit displaying nicely.
Where it fails is on the submission.
I've hooked up the following JS to the button (taken straight from the guides)
var form = document.getElementById('payment-form');
var clientSecret = $("#authcode").val();
form.addEventListener('submit', function(ev) {
ev.preventDefault();
stripe.confirmCardPayment(clientSecret, {
payment_method: {
card: card,
billing_details: {
name: 'Jenny Rosen'
}
}
}).then(function(result) {
if (result.error) {
// Show error to your customer (e.g., insufficient funds)
console.log(result.error.message);
} else {
// The payment has been processed!
if (result.paymentIntent.status === 'succeeded') {
// Show a success message to your customer
// There's a risk of the customer closing the window before callback
// execution. Set up a webhook or plugin to listen for the
// payment_intent.succeeded event that handles any business critical
// post-payment actions.
}
}
});
});
Now when I put a breakpoint on it does enter the stripe.confirmCardPayment function
However I never get a response. I've put a break point on the line if (result.error) { but it never fires. I've sat and left it for over two minutes.
No errors in the chrome console, and also no network traffic.
I am happy that the JS is all loaded correctly because if I hit submit again the Stripe JS lib correctly tells me I have an in-flight confirmCardPayment
Any suggestions are most appreciated.
Looks you are using jQuery at:
var clientSecret = $("#authcode").val();
You should wrap js with
$(document).ready(function(){
....
}):
Right, I've finally got it working.
Yes I believe with the answers given by Nolan / Raphael that it was indeed a caching issue!
However. Deleting the cache with CTRL+SHIFT+DEL had no effect.
Only way I could get the cache to clear was to physically alter the JS.
Thanks again to Nolan / Raphael for their suggestions :)

How to create custom donation amount using Payapl client side REST-API

I'm following the client side Client Side Rest API to create a donation button. The amount to charge is static in the code. I was able to pass in a variable after prompting the user to click a button to enter the amount, however, that is incredibly clunky and a default value is needed to prevent the PayPal window from closing as soon as it's opened if no values was entered.
// payment() is called when the button is clicked
payment: function(data, actions) {
// Make a call to the REST api to create the payment
return actions.payment.create({
payment: {
transactions: [
{
amount: { total: promptMe2(), currency: 'USD' }
}
]
}
});
},
You can see that I have the var donationAmount. That is set by default to a value. However, it can be changed by the user with:
<script>
var donationAmount = 16.11;
function promptMe(){
donationAmount = parseFloat(prompt("How much would you like to donate?"));
while (Number.isNaN(donationAmount)){
alert("Invalid number, try again!");
donationAmount = parseFloat(prompt("Amount to donate?"));
}
donationAmount = donationAmount.toFixed(2);
}
I tried to call promptMe() in place of the donationAmount variable (with an added return statement of donationAmount of course) and found that the page would just spam my error message for an invalid amount. When I hardcoded the value in it worked just fine. When I took the error checking out, it didn't even prompt me, it just instantly closed the paypal window. I was able to trigger an alert("Hello"); but that is pretty useless, I need to be able to accept user input and then pass it to Paypal.

Shopify: get current logged in user ID in JavaScript

I'm trying to build an app for shopify and I'm interested if I can get the current logged user ID using javascript api or something similar.
I was looking at the ajax api: http://docs.shopify.com/support/your-website/themes/can-i-use-ajax-api and I can see you can get the current products that the current user has added to his shopping cart, but nothing about the user ID.
Is it possible, or am I missing something?
You can try __st.cid in JavaScript for getting customer id.
I've found the __st variables unreliable (__st_uniqToken for one).
I believe the proper way to do this in Javascript is using the following call:
ShopifyAnalytics.lib.user().id()
You can also get the unique user id (non-logged in id) with:
ShopifyAnalytics.lib.user().properties().uniqToken
This is also the only reliable way to get it on the checkout page. I previously used __st_uniqToken, but it has since stopped working.
NOTE This is no longer 100% fool-proof. Shopify have AGAIN changed how their site works on the landing and thank-you pages.
I've had to resort to the following function to get a user id 'reliably'.
var user_id = function() {
try {
return ShopifyAnalytics.lib.user().id();
} catch(e) {}
try {
return ShopifyAnalytics.lib.user().properties().uniqToken;
} catch(e) {}
try {
return ShopifyAnalytics.lib.user().anonymousId();
} catch(e) {}
return __st_uniqToken;
};
Developing for Shopify is a true nightmare. I spend 50% of my time un-breaking my product every few weeks because them.
In layout.liquid file you can add this code to define global customerId variable
{% if customer %}
<script type="text/javascript">
window.customerId = "{{ customer.id }}";
</script>
{% endif %}
Just get it from ShopifyAnalytics.meta.page.customerId is your script
Your best bet would be to create an App that installs a simple ScriptTag in the shop. That script can then report the customer ID back to the App securely. Very simple to do that. Forget the front-end API as there is no secure way to call your App using that.
It seems that Shopify API was again changed, I see that now the user Id is in ShopifyAnalytics.lib.user().traits().uniqToken. Also, it may take time for this value to be loaded.
I use this code snippet to perform the job once the value available.
<script type="text/javascript">
actOnUser = function(retry, func){
if (ShopifyAnalytics && ShopifyAnalytics.lib && ShopifyAnalytics.lib.user) {
console.log(ShopifyAnalytics.lib.user().traits().uniqToken); // Do your work here.
} else {
if (retry > 0) {
setTimeout(function() {
func(retry - 1, func);
}, 1000);
}
console.log('User not ready'); // Can be removed - just for debug
}
}
console.log('Starting');
setTimeout(function() {
actOnUser(10, actOnUser);
}, 1000);
</script>
This solution is not 100% about getting user_id, but about detecting if current user is logged in as admin. You can use typeof Shopify.AdminBar to check if the admin bar exists. It's automatically created by Shopify if the current user is admin. Maybe this will help someone.

Categories