I'm making an investment fundraising page for a small business and I'm trying to create a custom PayPal button where the amount to give is set by a slider. The reason for this is that the business doesn't want to take loans less than a certain amount, but they don't want to restrict people to a limited number of choices (most PayPal buttons give people limited options for donation amounts). They want to be able to choose any amount from $500-$38,000. The idea is that they'll select this amount with a slider, then click a button that takes them to a payment screen for that amount. The code is on my GitHub at https://github.com/cbarboza2011/funkychickenfoodtruck. The slider and paypal button on are on donate.html
I've looked into the PayPal Docs, but I'm really new to backend stuff and so I'm not sure how to implement the information provided. I think I need to somehow access the HTML variable amount but I'm not sure how to do so. Currently, the slider has no effect on the resulting paypal page; users are taken to a page showing "$0.01". I want the slider to set the amount so that when a user clicks the paypal button, a payment page with their chosen amount comes up instead of a page showing "$0.01".
NOTE: The donate.html page is only currently styled for mobile, so view in devtools mobile view on Chrome if possible, otherwise everything will be enormous in a regular desktop window. It will still work, but it's huge.
$('.slider').slider({
max: 38000,
min: 500,
step: 100,
value: 500,
});
function getLoanAmount() {
var loanAmount = $('.loanamount');
var $selection = $( ".slider" ).slider( "value" );
$(loanAmount).text($selection);
}
getLoanAmount();
$('.slider').on('slide', function() {
getLoanAmount();
});
$(".slider").on( "slidestop", function() {
var $amount = $('.loanamount').text();
$( ".slider" ).slider( "option", "value", $amount );
$('a.paypalbutton').attr('href', 'https://www.paypal.com/donate?hosted_button_id=LR2YL2LXSYSTQ&amount=' + $amount);
});
$('button.submitloan').on('click', function() {
$('.loan-setter').slideUp();
$('#smart-button-container').css('display', 'block');
});
<div class="slider"></div>
<!-- PayPal Widget -->
<a href="https://www.paypal.com/donate?hosted_button_id=LR2YL2LXSYSTQ" class="paypalbutton">
<img src="https://www.paypalobjects.com/webstatic/en_US/i/btn/png/btn_buynow_107x26.png" alt="Buy Now" />
</a>
UPDATE: I've tried modifying the PayPal JS, but I don't know how to check if it works?
function initPayPalButton() {
paypal.Buttons({
style: {
shape: 'pill',
color: 'white',
layout: 'vertical',
label: 'paypal',
},
createOrder: function(data, actions) {
var $amount = $('.loanamount').text();
$('.dollaramount').text($amount);
return actions.order.create({
purchase_units: [{"amount":{"currency_code":"USD","value": $amount}}]
});
},
onApprove: function(data, actions) {
return actions.order.capture().then(function(details) {
alert('Transaction completed by ' + details.payer.name.given_name + '!');
});
},
onError: function(err) {
console.log(err);
}
}).render('#paypal-button-container');
}
initPayPalButton();
For a classic HTML-only button that redirects:
Use an unhosted button (no hosted_button_id), of type Donate or Buy Now.
Go to https://www.paypal.com/buttons , sign in, start creating your button, but before creating it ensure that in Step 2 you uncheck the option to Save the button at PayPal, so it is unhosted.
Once you generate your code, click above it to remove the code protection.
Now you have code that can be copied and edited, or you can use the 'Email' tab if you prefer a URL. The input parameter to add/modify is "amount", as documented here.
For a better JS in-context payment experience, use a smart checkout button; here is an example implementation: https://developer.paypal.com/demo/checkout/#/pattern/client
I got the new amount from your slider from copying the $selection var of your getLoanAmount function. Its originally a var called AmountNumeral because its a number value. Then $amount uses toString() just to make it a text string so that you can pass it into your paypal URL as the amount you want to show up. The console logs can just show how it formats it from numeral to string if that helps in seeing the difference
The amount on paypal still shows up as $0.00 initially. I read that if your paypal donate button is "hosted" then its impossible to change the amount value or any preset numbers as a safety precaution. Not sure if your paypal button was setup as "hosted" or "unhosted" but I would check that out maybe.
I haven't worked with PayPal before I just quickly skimmed through some answers about it and their website. But this should fix your updated slider value at least.
Pre-populate Donation Amount on Website
function getLoanAmount() {
var loanAmount = $('.loanamount');
var $selection = $( ".slider" ).slider( "value" );
$(loanAmount).text($selection);
console.log(($selection));
console.log($(loanAmount).text($selection));
}
getLoanAmount();
$('.slider').on('slide', function() {
getLoanAmount();
});
$(".slider").on( "slidestop", function() {
var $amountNumeral = $( ".slider" ).slider( "value" );
console.log($amountNumeral);
var $amount = $amountNumeral.toString();
console.log('$amount');
$( ".slider" ).slider( "option", "value", $amount );
$('a.paypalbutton').attr('href', 'https://www.paypal.com/donate?hosted_button_id=LR2YL2LXSYSTQ¤cy_code=USD&amount=10.00');
});
Related
PayPal allows adding a delivery address street without a number.
As far as I know, it is not possible to check this behavior during the order process before the payment is finished.
The order data is available in the onApprove function scope.
But that's too late, because the payment is finished then?
Is there a way to add address validation?
<script src="https://www.paypal.com/sdk/js?client-id=abc123&disable-funding=credit,card,sepa,giropay¤cy=EUR"></script>
<script>
paypal.Buttons({
createOrder: function(data, actions) {
return fetch('/paypal/order/create/', {
method: 'post'
}).then(function(res) {
return res.json();
}).then(function(orderData) {
if (orderData.error)
{
return actions.reject();
}
return orderData.id;
});
},
onShippingChange: function(data, actions) {
if (data.shipping_address.country_code !== 'DE')
{
return actions.reject();
}
return actions.resolve();
},
onApprove: function(data, actions) {
return fetch('/paypal/order/' + data.orderID + '/capture/', {
method: 'post'
}).then(function(res)
{
return res.json();
}).then(function(orderData) {
let re = /[0-9]/;
// test
if (re.exec(orderData.payer.address.address_line_1) === null)
{
// cancle payment on this place is to late, because payment is finished
}
var errorDetail = Array.isArray(orderData.details) && orderData.details[0];
if (errorDetail && errorDetail.issue === 'INSTRUMENT_DECLINED') {
return actions.restart();
}
if (errorDetail)
{
return;
}
return fetch('/paypal/finish-order/' + data.orderID + '/',{
headers: {
'Content-Type' : 'application/json',
},
body: JSON.stringify(orderData),
method: 'post'
}).then(function(result){
let dat = result.json();
return dat;
}).then(function(data)
{
if (data.error)
{
actions.reject();
}
if (data.destination)
{
actions.redirect(data.destination)
}
});
});
},
funding: {
allowed: [ paypal.FUNDING.CARD ],
disallowed: [ paypal.FUNDING.CREDIT ]
},
style: {
size: 'medium',
height: 40,
label: 'checkout'
}
}).render('#ppbut');
</script>
When onApprove is called, the payment is not finished. The order still needs to be captured.
Before capture, you can show an order review step if desired (for the customer to verify a new total, for example, or select from available shipping methods). This step can be done by updating the DOM dynamically (a redirect can also work but is best avoided).
If the address is invalid, show an error message accordingly and give an option to restart; do not proceed with any capture. You do not need to void the order (there is no method), simply forget about that order id and never capture it.
You can patch the order to a new total as needed (automatically, or based on selections in the review step you add).
Finally, proceed with the capture as normal and show success.
If you do add a user review step after approval, you should also change the last button at PayPal to say "Continue" instead of the default "Pay Now" to match your behavior. This is only a text change, the behavior only changes based on what you do in onApprove, which must correspond. To make the text change, add an application_context object to the top level (not inside purchase_units) of your order creation request, in which you specify a user_action parameter with the value CONTINUE.
Magento 2.4 PHP 7.4
Clicking on the 'Order Now' button on the checkout page does not trigger any action. There are no errors on Console or in the Network tab.
Our setup uses the Amasty_CheckoutCore module on the front end to create a generic 'Order Now' button which will be triggered for the different types of Place order requests depending on the Payment methods.
By referring some online solutions I linked the Order Now button with the Place Order that will appear on UI. But that didn't work. Please find below the code for the same. I added the summary.js.
app\design\frontend\Vendor\Amasty_CheckoutCore\web\js\summary.js
require(
[
'jquery',
'ko',
'Magento_Checkout/js/view/summary',
'Magento_Checkout/js/model/step-navigator',
],
function(
$,
ko,
Component,
stepNavigator
) {
'use strict';
console.log("inside summary js");
return Component.extend({
isVisible: function () {
return stepNavigator.isProcessed('shipping');
},
initialize: function () {
$(function() {
$('body').on("click", '#place-order-trigger', function () {
$(".payment-method._active").find('.action.primary.checkout').trigger( 'click' );
});
});
var self = this;
this._super();
}
});
}
);
I am new to Magento 2, I want to show/hide custom shipping method like delivery in 2 hours radio button if customer fills particular city on checkout page.if he is from that city will show "2 hour delivery option" if not will hide it.
Can anybody help me in this?
Thanks in advance.
You can use write js in template file like that:
\Namespace\Module\view\frontend\templates\XXX\view\abc.phtml
<script>
// <![CDATA[
require(
['jquery', 'namespace/module'],
function ($, xyz) {
var ajaxurl = '<?php echo $block->getAjaxUrl() ?>';
$(document).ready(xyz.chkCity(ajaxurl));
});
// ]]>
</script>
and keep your js at:
\Namespace\Module\view\frontend\web\js\abc.js
define([
'jquery'
],
function ($, xyz) {
return {
chkCity: function (ajaxurl) {
$('#city').on('blur', function (e) {
//you logic here
});
}
};
});
I am using the advanced integration procedure to integrate a paypal button, but I would like to change the default image of the button with the one that includes also the credit card logos, e.g.:
<script src="https://www.paypalobjects.com/api/checkout.js"></script>
<div id="paypal-button"></div>
<script>
paypal.Button.render({
env: 'sandbox',
locale:'it_IT',
payment: function(resolve, reject) {
var CREATE_PAYMENT_URL = '/make-payment';
paypal.request.post(CREATE_PAYMENT_URL)
.then(function(data) { resolve(data.paymentID); })
.catch(function(err) { reject(err); });
},
style: {
size: 'medium',
color: 'blue',
shape: 'rect'
},
onAuthorize: function(data, actions) {
console.log("done")
}
}, '#paypal-button');
</script>
By reading the documentation it seems that it is not possible to set an attribute to change the default paypal image. Any ideas?
Going forward, the integration requires that the button is rendered by PayPal -- this mean we can keep a consistently hi-resolution button across all devices, so the button looks sharp no matter what the display, including retina devices.
I'm part of the team that works on this button, so we can look into adding a variation which includes card logos. I think it'd be a useful addition.
https://medium.com/#bluepnume/less-is-more-reducing-thousands-of-paypal-buttons-into-a-single-iframe-using-xcomponent-d902d71d8875#.sf9jm8q4s
I have an HTML5 page with several data inputs inside a jQuery Dialog box. I sweep this data into form processing with the input attribute form=dataInput. It works fine in Firefox and Chrome, but not in IE because IE does not support the input form attribute. Something about the Dialog widget makes input box elements 'invisible' to form processing. The form attribute fixes this for browsers that support HTML5, but no released IE has this support. I tried $('.ui-dialog').appendTo('form'); in the Dialog open: option, but it does not fix the problem. Is there a way to get IE to sweep input data out of a Dialog widget and into $_POST ?
Here is a sample of an input box inside the Dialog
<label><input type="radio" id="unitedStates" name="country" form="dataInput" value="US">United States</label>
I use the jQuery Form plug-in to perform the submit. It has some options, like beforeSubmit and beforeSerialize, but I don't understand the documentation or the submit process well enough to know if they can be used to solve this problem. Please be specific with code or tutorials. I'm new enough to this that I don't follow general instructions well. ;-) (BTW, IE has the other feature support I need, just not this one.)
Here's my code with Andrew Hagner's suggestion and my modification. Dialog works, but IE does not set a value for the country. What needs to change?
var countrySelected = $("input[type=radio][name=country]").val(); //set earlier by W3C geocoding
var countryChooser = $('#countryChoices').dialog( {
autoOpen: false,
bgiframe: true,
height: 300,
width: 850,
resizable: false,
draggable: true,
title: "Click to select another country",
open: function () {
$('#regions').tabs(
{
event: "mouseover",
})
},
buttons: {
'Close / continue location input': function ()
{
countrySelected = $('input[name=country]:checked').val();
$(this).dialog('close');
}
}
});
//then later on
getCityFromGeonames3Step(countrySelected);
Updated:
// Before you enter dialog, assign the element you will
// be grabbing the info from to a variable.
var countrySelectionElement = $("input[type=radio][name=country]").val();
var countrySelected = "";
var countryChooser = $('#countryChoices').dialog( {
autoOpen: false,
bgiframe: true,
height: 300,
width: 850,
resizable: false,
draggable: true,
title: "Click to select another country",
open: function () {
$('#regions').tabs(
{
event: "mouseover",
})
},
buttons: {
'Close / continue location input': function ()
{
// Since jQuery won't work in here, use the variable
// we assigned above to access value.
countrySelected = countrySelectionElement.val();
$(this).dialog('close');
}
}
});
//then later on
getCityFromGeonames3Step(countrySelected);
Original:
Before you open the dialog assign the input to a variable:
function OpenDialog()
{
var input = $("yourinput");
// Open dialog, use input to work with that element.
// If you want you can then place the entered data in a hidden field
// using jQuery, in the same way we are using input here. Then you will
// be able to post that data back however you like.
}
I had this problem the other day, I found this solution on jQuery's Dialog site.
http://jqueryui.com/demos/dialog/#modal-form