Remove shipping address option in PayPal Express Checkout - paypal

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"

Related

PayPal chectout returns UNPROCESSABLE_ENTITY

My checkout code
let ORDERPRICE = 2;
paypal.Buttons({
createOrder: function(data, actions) {
return actions.order.create({
application_context: {
shipping_preference: "NO_SHIPPING",
brand_name: "MYCOMP",
user_action: 'PAY_NOW',
payment_method: {
payee_preferred: 'IMMEDIATE_PAYMENT_REQUIRED'
}
},
payer: {
name: {
given_name: 'NAME'
},
email_address: 'EMAIL#EMAIL.com'
},
purchase_units: [{
description: "description",
amount: {
currency_code: 'EUR',
value: ORDERPRICE
}
}]
});
},
onApprove: function(data, actions) {
return actions.order.capture().then(function(details) {
//submitting my form to show thank you page
var sentform = document.getElementById('booking-sent');
sentform.submit();
});
},
style: {
color: 'blue'
}
}).render('#paypal-button-container');
In a browser debug i see a POST to https://www.paypal.com/smart/api/order/23H57866L56525306/capture And i get an answer from PayPal
{"ack":"contingency","contingency":"UNPROCESSABLE_ENTITY","data":
{"name":"UNPROCESSABLE_ENTITY","details":[{"issue":"TRANSACTION_REFUSED","description":"The request was refused"}],
"message":"The requested action could not be performed, semantically incorrect, or failed business validation.","debug_id":"282422b19213c",
"links":[{"href":"https://developer.paypal.com/docs/api/orders/v2/#error-TRANSACTION_REFUSED","rel":"information_link","method":"GET"}]},"meta":{"calc":"282422b19213c","rlog":"rZJvnqaaQhLn%2FnmWT8cSUueWscmrtUHe5Y1Bd%2FeqyvyOTq66rSXAcnM25I5c5rd3HxcyHxUk51TwoDOk%2By6wR%2Bw1HIUZ5ikN_17823c767ad"},"server":"OIZ58dNapHV5upm8ATCTYU49pCRnWLUsUjSypMRTXJSK5O3nEGxxJcKhByP9VmJq8cMcxl0h826w9SamyEn7niIWkJCJ_dYRHcQcnfMQSPWr2KIOUwJTg_fz4H6p100NKDfIiTBVCsopCu5fUadAqZMpyXvcJvyrj70N6Vvp9rMUXBfLj7d7HnDtxtM_0wO0JUB8gZUJzNmGTn6283Qwandfgn1LcTH6mnja87iXsKVRSFcuLVmSXDOWbhZ3Bh0Dk9hD5ihBeK4T9DYh5TCqe0"}
When I'm going to https://developer.paypal.com/docs/api/orders/v2/#error-TRANSACTION_REFUSED there's no clue there what to do.
The transaction was refused.
Perhaps it was refused in part because you specified:
payment_method: {
payee_preferred: 'IMMEDIATE_PAYMENT_REQUIRED'
}
And it was going to be 'pending' (not immediate), for any number of possible reasons.
The reason was business account settings. Above code is totally ok.
Setting you need to take care of is the currency. To be more specific, you need to point all currencies you (as a business account) accept. In this case, I have set up Euro (EUR) as a currency of the payment. Meanwhile business account by default has only US Dollar (USD) set up as accepted currency.

PayPal Checkout / Smart Buttons - Error with createOrder & empty fields which are optional

With the createOrder function I am passing some of the customer information, mainly to pre-populate the credit / debit card fields.
Something like phone number optional at checkout. With the following code if the order_phone field has a phone number, it works. If it is empty it returns an error and stops. Is there any way around this or let PayPal know it is optional? This happens with other variables too which may be optional for the customer.
createOrder: function(data, actions) {
return actions.order.create({
purchase_units: [{
amount: {
value: $("#grand_total").val(),
currency_code: ("#grand_total").val()
}
}],
"application_context" : {
"shipping_preference":"NO_SHIPPING"
},
payer: {
name: {
given_name: $("#first_name").val(),
surname: $("#last_name").val()
},
email_address: $("#email_address").val(),
phone: {
phone_number: {
national_number: $("#order_phone").val()
}
}
},
});
},
Try something like
createOrder: function(data, actions) {
var myOrder = {
purchase_units: [{
amount: {
value: $("#grand_total").val(),
currency_code: "USD"
}
}],
"application_context" : {
"shipping_preference":"NO_SHIPPING"
},
payer: {
name: {
given_name: $("#first_name").val(),
surname: $("#last_name").val()
},
email_address: $("#email_address").val(),
},
};
var phone = $("#order_phone").val();
if(phone) myOrder.payer.phone = {
phone_number: {
national_number: phone
}
};
return actions.order.create(myOrder);
},

Remove shipping address from paypal express checkout

I am using express checkout in my website. I want to disable shipping address from it while completing the transaction. i am using script on a button. Piece of code that i am using is this.
paypal.Button.render({
env: 'production', // sandbox | production
client: {
sandbox: 'mykey',
production: 'mykey'
},
// Show the buyer a 'Pay Now' button in the checkout flow
commit: true,
// 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: '5.00', currency: 'EUR' }
}
]
}
});
},
// onAuthorize() is called when the buyer approves the payment
onAuthorize: function(data, actions) {
// Make a call to the REST api to execute the payment
return actions.payment.execute().then(function() {
window.location = "address";
});
}
}, '#paypal-button-container');
Help will be really appreciated.Thanks
In case you are still looking for a solution the shipment address can be disabled by adding the following lines:
experience: {
input_fields: {
no_shipping: 1
}
}
So your code needs to be adjusted like this:
...
// Make a call to the REST api to create the payment
return actions.payment.create({
payment: {
transactions: [
{
amount: { total: '5.00', currency: 'EUR' }
}
],
experience: {
input_fields: {
no_shipping: 1
}
}
}
});
...

PayPal REST API / paypal-checkout Javascript integration: setting payee, permission denied

I'm having a problem using the REST API along with the
paypal-checkout javascript integration
(https://github.com/paypal/paypal-checkout) to set a third party as the
payment receiver.
According to this
https://devblog.paypal.com/setting-payee/
a third-party payee should be allowed now. Correct?
The heart of the matter seems to be this call:
paypal.rest.payment.create(button_member.env,
button_member.client,
pp_data_member);
where button_member.env is "sandbox"
and button_member.client is
{"sandbox":"Ab**********0O","production":"AW**********38"}
When pp_data_member is
{"intent":"authorize",
"payer":{"payment_method":"paypal"},
"transactions":[
{ "amount":{"total":"5.50",
"currency":"USD",
"details":{
"subtotal":"5.00","tax":"0.00","shipping":"0.50"
}},
"payee":{"email":"development-facilitator#troc*****.com"},
"soft_descriptor":"ZenKitsch",
"notify_url":
"https://www.trocadero.com/_internal/alpha/**********",
"description":"Your Zen Kitsch order of September 16, 2017",
"invoice_number":"CHKT-zenkitsch-479618-SV16M8PSFG",
"item_list":{
"items":[{"sku":"844697","name":"United Airlines Beverage Menu Card","quantity":"1","price":"5.00","currency":"USD"}]
}
}
]
}
all works fine. But when I set the payee to a different sandbox address and
nothing else changes:
...
"payee":{"email":"development-seller#troc*****.com"},
...
while I get the popup as expected, after I log in with the buyer sandbox
account and confirm the purchase, I get a failure back from the API, a
400 status code and a "contingency":"PERMISSION_DENIED" error message:
Request URL: https://www.sandbox.paypal.com/webapps/hermes/api/payment/PAY-9TX329794L770414LLG6YSZQ/execute
Request Method:POST
Status Code:400 Bad Request
Remote Address:173.0.82.77:443
{"ack":"contingency",
"contingency":"PERMISSION_DENIED",
"meta":
{"calc":"e305762ccebe",
"rlog":"7Jz2DIxLg7B25ErQ1yIJI2shyI%2FIqDJZY2fbMMEef%2FVnBUNHVn2YYp4ptK5fN6DoGzjRHFjL6nRZkZqdnHIRwQ_15e8c60e8a8"
},
"server":"6ajNNYfBIhVmBs2ogHWhF35ezBlTaOHlCtx2erpwzk-5XmIY9isE5Hk07x5GBputw5DXmqsjLE71y3mJtJHw6TPBWcgBGzPpOkEXIWpJVOPsgsani23mTTQPfrrhKtd2pLLSFQDXQ0ISqpWOC0vZa4DvUshowfLFfFn_oNyAB_gquO5vWd1wIZOEp8z6EiUAnjsDBhCv1K1xBjn6KsOFyczIThuWeoh86RnPLJnhzpqXWAuSDCof_00kGVXCskQDxDqLpa4-0Ry"
}
Any help greatly appreciated. Thanks!
Edited to add: small code to demo the issue. The first button with payee set to app owner works, the second button fails with an error that can be ssen in the console.
<html><head><title>PP Button Test</title></head>
<body>
<script src="https://www.paypalobjects.com/api/checkout.js" data-version-4></script>
<div id="myContainerElement1"></div>
<hr>
<div id="myContainerElement2"></div>
<script>
paypal.Button.render({
client: {
sandbox: 'AbR*****T0O',
production: 'xxxxxxxxx'
},
payment: function(data, actions) {
return actions.payment.create({
transactions: [
{
amount: {
total: '1.00',
currency: 'USD'
},
payee:{email:'development-facilitator#troc*****.com'},
}
]
});
},
commit: true,
locale: 'en_US',
style: {
size: 'medium', // tiny, small, medium
color: 'blue', // orange, blue, silver
shape: 'pill' // pill, rect
},
env: 'sandbox', // Optional: specify 'sandbox' or 'production'
onAuthorize: function(data, actions) {
return actions.payment.execute().then(function(response) {
console.log('payment 1 completed!');
});
},
onCancel: function(data) {
console.log('payment 1 was cancelled!');
}
}, '#myContainerElement1');
paypal.Button.render({
client: {
sandbox: 'AbRF38w5WaF4qE3nSr_JLsxdGGOEGSpS4wxI8HbW-QYcnISvpmPEc-hJfUemR1k57IrCKwBDNamV9T0O',
production: 'xxxxxxxxx'
},
payment: function(data, actions) {
return actions.payment.create({
transactions: [
{
amount: {
total: '1.00',
currency: 'USD'
},
payee:{email:'development-seller#troc*****.com'},
}
]
});
},
commit: true,
locale: 'en_US',
style: {
size: 'medium', // tiny, small, medium
color: 'blue', // orange, blue, silver
shape: 'pill' // pill, rect
},
env: 'sandbox', // Optional: specify 'sandbox' or 'production'
onAuthorize: function(data, actions) {
return actions.payment.execute().then(function(response) {
console.log('payment 2 completed!');
});
},
onCancel: function(data) {
console.log('payment 2 was cancelled!');
}
}, '#myContainerElement2');
</script>
</body></html>

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/