Paypal Smart Buttons Metadata - Webhook - paypal

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.

Related

paypal createOrder (javascript sdk)

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.

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 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

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.

Passing discount code in Orders API on Shopify

I have been trying to develop an app that takes an order on Shopify on a different channel. I successfully placed an order through the API but I am not able to include the discount code along with the order. The JSON object for the POST data is as below:
{
order: {
email : request.params.order.email, // string
financial_status : 'pending', // string
send_receipt : true, // boolean
send_fulfillment_receipt : false, // boolean
note : request.params.order.note, // string
discount_codes : [], // supposed to be an array of Object| Problem here,
line_items : request.params.order.line_items, // array
customer : request.params.customer, // JSON object
billing_address : request.params.order.billing_address, // JSON object
shipping_address : request.params.order.shipping_address // JSON object
}
}
According to the documentation, the discount_codes is like this -
Applicable discount codes that can be applied to the order. If no codes exist the value will default to blank. A Discount code will include the following fields:
amount: The amount of the discount.
code: The discount code.
type: The type of discount. Can be one of : "percentage", "shipping", "fixed_amount" (default).
What am I doing wrong? My discount_codes is this
[{amount: 100,code:'WELCOME10',type:'percentage'}]
Has anyone done this before?
According to this response from Shopify what you are trying to do is only possible if you pass the total_discounts field along as well with the total amount of the discount you want to apply.
As you will see in this other answer, any codes you have created through Shopify are not available to use with the API and their usage will not be recorded.
I was trying to use this API in order to test the application of different coupon codes that I was generating, but this does not seem to be possible. Apparently, the API was intended for applying discounts that are custom, not ones that already exist in Shopify. This is a frustrating limitation to me.
I successfully create orders with discounts all the time, without ShopifyPlus as that is irrelevant. The data structure that works for me looks like this:
[ { "code": "Shop By PizzleFuzzle 10%", amount: "10", "type": "percentage" } ]
The discount object is available only for Shopify Plus merchants.
Once you are a Shopify Plus merchant, you will be able to create discount codes like that:
POST /admin/discounts.json
{
"discount": {
"discount_type": "percentage",
"value": "15.0",
"code": "balderdash"
}
}
Please see more detailed documentation in the discount object at Shopify API: https://help.shopify.com/api/reference/discount
You should use the value property name instead of amount property name.
e.g.
{value: 100,code:'WELCOME10',type:'percentage'}
and not
{amount: 100,code:'WELCOME10',type:'percentage'}