paypal createOrder (javascript sdk) - paypal

createOrder: function (data, actions) {
getOrderUid().then(res=>{
return actions.order.create({
purchase_units: [
{
amount: {
value: 100,
currency_code: 'USD'
},
reference_id: res.data.order.id
}
]
})
})
An error:
Uncaught Error: Expected an order id to be passed
I need to process the business at the same time before creating it, how can I do this?

The createOrder callback function needs to itself return (pass back) the result or Promise of an order being created. You appear to have inserted a 10 ms setTimeout for some reason and are not passing back anything what is necessary.
I need to process the business at the same time before creating it
What does this mean? Rephrase whatever you mean by this if it's important.

Related

I don't understand how to get a token to make API calls

I'm using the Payouts API and to do so I have to specify an access token when calling https://api-m.sandbox.paypal.com/v1/payments/payouts
To get an access token, as specified here I have to send a POST request with Postman to https://developer.paypal.com/docs/api/overview/#get-an-access-token and it returns in the response the token
My problem is that this token has an expiration time, which is an issue because I can't go in my app every 15 minutes to change the token in the Authorization header. How can I get a "permanent" or rather an "auto refreshed" token ?
I tried to make a call from my app instead of Postman but it doesn't seem to work, it says my credentials are invalid
This is my code in case it can be useful (I'm managing everything from the front-end):
window.paypal
.Buttons({
createOrder: (data, actions) => {
return actions.order.create({
purchase_units: [
{
description: this.product.description,
amount: {
value: this.product.price
}
}
]
});
},
onApprove: (data, actions) => {
const timestamp = new Date().getUTCMilliseconds();
const id = timestamp;
return actions.order.capture().then(details => {
axios
.post(
"https://api-m.sandbox.paypal.com/v1/payments/payouts",
{
sender_batch_header: {
sender_batch_id: id,
email_subject: "You have a payout!",
email_message:
"You have received a payout! Thanks for using our service!",
recipient_type: "EMAIL"
},
items: [
{
amount: {
value: this.product.price,
currency: "USD"
},
note: "congrats someone bought your stuff",
sender_item_id: id,
receiver: "john#doe.com"
}
]
},
{
headers: {
Authorization:
"Bearer <my token that I get from postman>"
}
}
)
.then(() => {
alert(
"Transaction completed by " + details.payer.name.given_name
);
})
.catch(err => console.log(err));
});
}
})
.render(".paypal");
}
},
Update
Reading the code a second time and noticing how your Payout is for the same this.product.price as the original payment, that makes no sense. Don't use payouts at all for this use case. The full amount will go to your account normally, but if you want the full amount to go somewhere else instead, set the payee variable for this checkout: https://developer.paypal.com/docs/checkout/integration-features/pay-another-account/
(original answer below)
Using Payouts from the client side is an absolutely terrible idea, anyone with your client credentials will be able to send money from your account to wherever they want
The payouts API must be used from your server only. Your server needs to do an API call to get an access token, similar to what you mention about postman -- except using whatever backend environment you have. You can integrate direct HTTPS calls, or there are also Payouts SDKs available which will handle getting the access token automatically.
As for how to trigger that backend action when capturing a payment, use a proper server integration:
Create two routes, one for 'Create Order' and one for 'Capture Order', documented here. These routes should return JSON data. Before returning JSON data, that last route (the capture one) should record the successful transaction in your database and trigger any Payout logic you want.
Pair those two routes with the following approval flow: https://developer.paypal.com/demo/checkout/#/pattern/server

Paypal Smart Button Integration - Is there a way i can add a discount coupon/SKU to the order.create function?

I have a Paypal Smart Button integration with my eCommerce site. The entire setup is: User clicks on the Paypal button -> makes a payment -> IPN call to my backend -> saves data to database. This flow is working fine for me.
I now want to be able to pass a discount SKU to Paypal so i can capture it in my database with the IPN call. Right now, only the discount amount ie being sent to Paypal depending on the coupon code used.
Here's my current code:
purchase_units: [{
description: "Zing Energy Patches",
amount: {
currency_code: currencyCode,
value: (basePrice + shippingPrice + tax - creditPrice).toFixed(2),
breakdown: {
item_total: {
currency_code: currencyCode,
value: basePrice
},
shipping: {
currency_code: currencyCode,
value: shippingPrice
},
tax_total: {
currency_code: currencyCode,
value: tax
},
discount:{
currency_code: currencyCode,
value: creditPrice
}
}
},
items: productsArray
}]
});```
I tried adding the discount as an item with negative value, but Paypal rejected the request stating that negative values are not allowed.

Paypal checkout - Identify customer / Append order ID

I am currently implementing paypal Checkout as per https://developer.paypal.com/docs/checkout/integrate/#
I can send payments etc no problem. However, how can I identify who made the payment?
createOrder: function(data, actions) {
// This function sets up the details of the transaction, including the amount and line item details.
return actions.order.create({
purchase_units: [{
amount: {
value: '1.0'
}
}]
});
}
.create does not allow me to append a order id or user id. In the paypal dashboard I can only see the name and the amount .
In you onApprove function, inside actions.order.capture(:
console.log(data);
The information will be there for you.
You can see an example of it used for an alter in the demo here: https://developer.paypal.com/demo/checkout/#/pattern/client

Paypal Smart Buttons Metadata - Webhook

I'm using the Paypal Javascript SDK to render smart buttons and capture and authorize all client side. Everything is working great except for the occasional customer not waiting around for processing to complete on our side.
I have set up webhooks and subscribed to all events but am not able to/or not sure how to define and receive any of my custom data IDs etc.
I've attempted several different configurations to pass my data to the order from create order - mainly following this guide https://developer.paypal.com/docs/commerce-platform/v1/reference/orders-integration-guide/#create-order
Which adds custom data to purchase_units as custom and also a metadata json object with supplementary_data and postback_data
paypal.Buttons({
createOrder: function(data, actions) {
return actions.order.create({
intent: 'CAPTURE',
purchase_units : [{
items : ....,
description : ...,
amount : ...,
custom : 'purchase_units_data'
}],
metadata : {
supplementary_data : [{
data : 'supplementary_data'
}],
postback_data : [{
data : 'postback_data'
}]
}
});
},
onApprove: function(data, actions) {
return actions.order.capture().then(function(details) {
....
});
}
}).render('#paypal-button-container');
Would hope to find a way to pass a bit of custom data to a webhook payload.
The answer appears to be that I was looking at the wrong version of the API.
https://developer.paypal.com/docs/api/orders/v2/#definition-purchase_unit_request
While I can't create a nicely formed metadata object I can however add data to the purchase_units object with reference_id and custom_id.
I'll just have to get a bit creative.

How to Specify NoShipping 1 with Express Checkout checkout.js v4

I have express checkout working with the latest checkout.js but do not need to show any shipping address. Since it's a digital good, the docs say I need noshipping set to 1. However, I can't figure out how that goes into the javascript.
I followed the basic integration steps and then used the REST API to execute the payment so I can charge to my server.
I've tried adding noshipping:1 all over the place within the javascript to create the payment with no luck. Here's what it looks like ( ignore compile issues as I'm just trying to show how I tried adding the noshipping:1 information):
payment: function() {
var env = this.props.env;
var client = this.props.client;
return paypal.rest.payment.create(env, client, {
transactions: [
{
amount: { total: '4.99', currency: 'USD' }
DOESNT WORK-->noshipping: 1
}
],
DOESNT WORK-->noshipping: 1
});
},
Does anyone know how to properly pass the noshipping information using the latest checkout.js?
OK, it appears that they have finally added support for this. It looks like this:
payment: {
transactions: [
{
amount: { total: '19.99', currency: 'USD' }
// Possibly there is also a 'custom' field we can specify here;
// https://stackoverflow.com/questions/46320753/
}
],
application_context: {
shipping_preference: 'NO_SHIPPING'
}
}
Got an "official" response from paypal support a week later:
Thank you for contacting PayPal Merchant Technical Services.
Unfortunately we do not have an option for the noshipping when using
REST API. That option is only available on the classic express
checkout which uses the NVP/SOAP API.
There it is. This fairly simple concept isn't possible with their latest SDK.
Yes, there's a way to specify NOSHIPPING as follows on PayPal-Python-SDK, as per your code:
payment: function() {
var env = this.props.env;
var client = this.props.client;
return paypal.rest.payment.create(env, client, {
transactions: [
{
amount: { total: '4.99', currency: 'USD' }
}
],
application_context: {
shipping_preferences: 'NO_SHIPPING',
}
});
},
I hope it helps.