Why will PayPal Smart buttons not recognise my items array? - javascript

I have integrated the PayPal smart buttons into my JavaScript shopping cart. I am trying to allow PayPal to tell the user the items they had in the cart at checkout. For example;
I know that to do this I need to use the following code:
<script>
paypal.Buttons({
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": [{
"description": "Stuff",
"amount": {
"value": "20.00",
"currency_code": "USD",
"breakdown": {
"item_total": {
"currency_code": "USD",
"value": "20.00"
},
}
},
"items": [
{
"unit_amount": {
"currency_code": "USD",
"value": "10.00"
},
"quantity": "1",
"name": "Item 1",
},
{
"unit_amount": {
"currency_code": "USD",
"value": "10.00"
},
"quantity": "1",
"name": "Item 2",
},
],
}
]
});
},
onApprove: function(data, actions) {
// This function captures the funds from the transaction.
return actions.order.capture().then(function(details) {
// This function shows a transaction success message to your buyer.
window.location.href = "orderConfirmed.php"
clearCart()
});
}
}).render('#paypal-button-container');
//This function displays Smart Payment Buttons on your web page.
</script>
In this example, there are 2 items in the dropdown tab: Item 1 and Item 2 but I need these to represent what the user has in their cart. I got an answer on her than said I needed to create amn array that held the cart item name, price and quantity.
I came up with this code, what I am trying to do is for every item in the cart, I want to return the product name, product price and product quantity. I came up with the code below:
function arrayOfItems() {
cart.forEach((cartItem, index) => {
let currency = cartItem.price;
let quantity = cartItem.quantity;
let itemName = cartItem.name;
let items = [{"unit_amount": {"currency_code": "USD","value": currency},"quantity": quantity,"name": itemName,}];
return items;
});
}
But when I run the new PayPal script like so:
<script src="cart.js"></script>
<script>
paypal.Buttons({
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: countCartTotal()
},
items: [
{
arrayOfItems()
},
],
}
]
});
},
onApprove: function(data, actions) {
// This function captures the funds from the transaction.
return actions.order.capture().then(function(details) {
// This function shows a transaction success message to your buyer.
window.location.href = "orderConfirmed.php"
clearCart()
});
}
}).render('#paypal-button-container');
//This function displays Smart Payment Buttons on your web page.
</script>
The PayPal buttons stop working!
Update
After making the changes the code now looks like this:
<script>
paypal.Buttons({
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": countCartTotal(),
"currency_code": "USD",
"breakdown": {
"item_total": {
"currency_code": "USD",
"value": countCartTotal()
},
},
"items": arrayOfItems()
}
]
});
},
onApprove: function(data, actions) {
// This function captures the funds from the transaction.
return actions.order.capture().then(function(details) {
// This function shows a transaction success message to your buyer.
window.location.href = "orderConfirmed.php"
clearCart()
});
}
}).render('#paypal-button-container');
//This function displays Smart Payment Buttons on your web page.
</script>
And is not producing any errors in my IDE, however when I run the code the JavaScript Console gives me this error:

You don't seem to be including the required breakdown. This may seem redundant, but it is required to have a breakdown section.
"breakdown": {
"item_total": {
"value": countCartTotal()
},
}
Also it looks like you are generating an items array, so you need to use it like so:
amount: {
value: countCartTotal()
},
items: arrayOfItems(),
All of the currency_code fields also seem to be required, and not optional when passing line item information, so you will need to add those back in.
That's three issues you need to fix.
If you still need help, post a runtime example of what everything is evaluating to, i.e. the output of the functions so we can tell you what's wrong

Related

Paypal api status pending in payment capture

Everything is fine in the PayPal sandbox but in the live environment, there is an issue with transactions.
My js :
<script src="https://www.paypal.com/sdk/js?client-id=key&currency=GBP"></script>
createOrder: (data, actions) => {
console.log("create order");
return actions.order.create({
purchase_units: [{
amount: {
value: 10.00
}
}]
});
},
onApprove: (data, actions) => {
console.log("on approve");
return actions.order.capture().then(function(orderData) {
const transaction = orderData.purchase_units[0].payments.captures[0];
alert(${transaction.status}: ${transaction.id});
});
}
}).render('#paypal-button-container');
This is my API response issue:
"payments": {
"captures": [
{
"amount": {
"currency_code": "GBP",
"value": "1.00"
},
"seller_protection": {
"dispute_categories": [
"ITEM_NOT_RECEIVED",
"UNAUTHORIZED_TRANSACTION"
],
"status": "ELIGIBLE"
},
"status": "PENDING",
"status_details": {
"reason": "PENDING_REVIEW"
}
}
]
},
the amount is received. but it's going to hold because of this status pending. but the PayPal team provides this as the solution " As for pending payments that would be a setting on your shopping cart, the setting would need to be set as 'sale' instead of 'Authorisation' " how do set this?
the setting would need to be set as 'sale' instead of 'Authorisation' "
This is not your issue, this is already a capture. The reason it is pending is given as "pending review", which basically means what it says. PayPal will review and either approve or deny the transaction, usually within 24 hours.

How to ammend paypal smart button to include vat (tax)

I have a Paypal generated smart button that I want to amend so that vat is broken down correctly on the paypal receipt.
I've read the paypal pages that say it cant be done in the paypal interface but have to be called through on the api.
The code I current have is...
<div id="paypal-button-container"></div>
<script src="https://www.paypal.com/sdk/js?client-id=xxxzzz&currency=GBP" data-sdk-integration-source="button-factory"></script>
<script>
paypal.Buttons({
style: {
shape: 'rect',
color: 'gold',
layout: 'vertical',
label: 'paypal',
},
createOrder: function(data, actions) {
return actions.order.create({
purchase_units: [{
description: "my amazing rocketpack",
amount: {
value: '2.99'
}
}]
});
}, onApprove: function(data, actions) {
return actions.order.capture().then(function(details) {
alert('Shop transaction completed by ' + details.payer.name.given_name + '!');
});
}
}).render('#paypal-button-container');
</script>
Looking at the paypal docs for purchase units it suggests I need to turn on amount.breakdown and specify item_total and tax_total.
But I cant seem to get it right (it either breaks the button so it doesn't display at all or the receipt is still just gross amount) and can find no examples of the code
Solved, in case anyone else wants to know, the below is how you initiate amount.breakdown (there is no dot)
purchase_units: [{
description: "my item",
amount: {
value: '29.99',
currency_code: 'GBP',
breakdown: {
item_total: {
currency_code: 'GBP',
value: '24.99'
},
tax_total: {
currency_code: 'GBP',
value: '5.00'
},
}
}
}]

I've found a Json data using findById, how do I use it in my code?

I am creating an API that gets Patients data(id and name), Physicians data(id and name) and Appointments(id, phyId, patId, app_date) and displays the Patients appointed to a particular physician. I need to create a remote method in physician.js in such a way that I get related Appointment that has phyId and print the details of the Patients using the patId obtained from appointment.
I'm using loopback 3.
Refer this link for clear idea:
https://loopback.io/doc/en/lb3/HasManyThrough-relations.html
I have related models (Physicians, Patients) that are related by "hasMany" with each other "through" Appointment(another model) and Appointment is related to each of these by belongsTo, in my loopback application and i need to print the Patients of a particular Physician.
Patient data:
[
{
"id": 1,
"name": "Anna Mull"
},
{
"id": 2,
"name": "Paige Trner"
}
]
Physician data:
[
{
"id": 1,
"name": "Cardiologist"
}
]
Appointment data:
[
{
"id": 1,
"physicianId": 1,
"patientId": 1,
"appointmentDate": "2019-01-28T10:06:33.530Z"
},
{
"id": 2,
"physicianId": 1,
"patientId": 2,
"appointmentDate": "2019-01-28T10:06:33.530Z"
}
]
I know there is a method already available to query the Patients of a Physician, but I want to code it myself to learn and also print it in the following format.
My idea is to get all the Appointments having the specific phyId in it and find the patId in those appointment and store it in an array. I then use that array to get the patients from the Patient model. I managed to get the Patient details in a function, but I can only console.log(Patients) but I am not able to display it in the API response.
The following is the format i need it in. (EXPECTED OUTPUT in API response)
Physician:
{
"id": 1,
"name": "Cardiologist"
}
Patients:
[
{
"id": 1,
"name": "Anna Mull"
},
{
"id": 2,
"name": "Paige Trner"
}
]
or any similar format.
I've tried to the same and here is my code.
common/models/physician.js
'use strict';
var app = require('../../server/server');
module.exports = function (Physician) {
Physician.getDetails = function (phyid, cb) {
var Appointments = app.models.Appointment;
var Patient = app.models.Patient;
Physician.findById(phyid, function (err, Physician) {
Appointments.find({ where: { physicianId: phyid } }, function (err, Appointment) {
if (err) {
cb(null, "Errorrrrrrrr", "Errorrrrrr");
}
else {
var patients = [], i = 0;
var patobj= [];
for (i in Appointment) {
patients[i] = Appointment[i].patientId;
//console.log(patients);
Patient.findById(patients[i], function(err, Patients){
if(err){
cb("Error in patients", "--");
}
else{
patobj[i]=Patients;//doesnt have any effect
console.log(Patients);//prints in console
}
});
}
cb(null, Physician, patobj);//only Physician is printed, patobj is empty.
}
});
});
}
Physician.remoteMethod('getDetails', {
http: {
path:
'/:phyid/getDetails',
verb: 'get'
},
accepts: {
arg: 'phyid',
type: 'number'
},
returns: [{
arg: 'Physician',
type: 'Object'
}, {
arg: 'Patient',
type: 'Object'
}]
});
};
I am actually getting this in the API response:
{
"Physician": {
"id": 1,
"name": "Cardiologist"
},
"Patient": []
}
and this in the console:
D:\Project\Project1>node .
Web server listening at: http://localhost:3000
Browse your REST API at http://localhost:3000/explorer
{ name: 'Anna Mull', id: 1 }
{ name: 'Paige Trner', id: 2 }
How am I supposed to get the patient data to be printed in the API response?
You patients are empty because, finding Patients by Id is an asynchronous operation. But the for loop is synchronous. The loop finishes and calls the following line before any of the Patients are found.
cb(null, Physician, patobj);//only Physician is printed, patobj is empty.
You need to wait for all the patients to be found by using either Promise.all or async.each.

Facebook Graph API - Ads Insights with different Action Values from Post

I'm using facebook Graph API to retrieve action values from campaigns. But the JSON returned is always different from any values from facebook screen.
My Request from JavaScript
var d = new FormData();
d.append("access_token", "MY_ADS_INSIGHTS_TOKEN");
d.append("fields", "actions");
d.append("date_preset", "lifetime"); // I want lifetime data
return await (await fetch("https://graph.facebook.com/v3.1/" + campaignid + "/insights", {
method: "post",
body: d
})).json();
and after I access the report insights using the URL:
https://graph.facebook.com/v3.1/REPORT_RUN_ID/insights?access_token=MY_ADS_INSIGHTS_TOKEN
JSON returned after access report task
{
"data": [
{
"actions": [
{
"action_type": "comment",
"value": "2"
},
{
"action_type": "like",
"value": "4"
},
{
"action_type": "photo_view",
"value": "30"
},
{
"action_type": "post",
"value": "1"
},
{
"action_type": "link_click",
"value": "7"
},
{
"action_type": "page_engagement",
"value": "249"
},
{
"action_type": "post_engagement",
"value": "245"
},
{
"action_type": "post_reaction",
"value": "205"
}
],
"date_start": "2018-07-09",
"date_stop": "2018-07-15",
"ad_id": null // removed
}
],
"paging": {
"cursors": {
"before": "MAZDZD",
"after": "MAZDZD"
}
},
"__fb_trace_id__": null // removed
}
Facebook Post Results
I want to know:
Why Facebook Graph API return the post_reaction as 205 since from facebook view it is 160 or 150? the value doesn't match anything, happens to action like too
Notes:
I'm not using any SDK, but this isn't the problem.
The Ad has only ONE ads group and the group has only ONE campaign
I make the requisition at the same time as I see the post. There are no major interactions in this post, it is old enough that the values do not change.
I known that Facebook cache anything, but this Ad is from 10, July.
Ad Campaign Insights reference: https://developers.facebook.com/docs/marketing-api/reference/ad-campaign-group/insights/
I accept answers using SDKs or different programming languages like C#, php or Java as example, I want only know HOW make the right request or what is exactly happening.

Backbone - Updating models in collection with data polled from another API

I have a Backbone collection that I'm populating from an API endpoint. This return data such as:
[
{
"gameId": 1234,
"gameName": "Fun Game 1"
},
{
"gameId": 1235,
"gameName": "Fun Game 2"
},
{
"gameId": 1236,
"gameName": "Fun Game 3"
},
etc,
etc,
etc
]
The collection is very simple and is initialised in the router so it's accessible to the entire app:
var GamesCollection = Backbone.Collection.extend({
model: GameModel,
url: '/path/to/games/list',
parse:function(response){
return response;
}
});
I have another endpoint that returns a collection of data related to the original data. This data looks like:
[
{
"gameId": 1234,
"numberOfPlayers": "1,000"
},
{
"gameId": 1235,
"numberOfPlayers": "Fun Game 2"
},
{
"gameId": 9999,
"numberOfPlayers": "Some other game that's not in the original list"
}
]
Note that the number of players response may or may not contain data for every game in the original response and may or may not contain data for games that do not exist in the original games response.
I need to be poll the number of players endpoint every X minutes and update the models in the GamesCollection with the data from the response so I can show this in the view.
What is the best way to handle this?
Query your numberOfPlayers endpoint and then set the fetched data on your collection. You can customize how set works with add and remove options.
For example,
var GamesCollection = Backbone.Collection.extend({
model: GameModel,
url: '/path/to/games/list',
parse: function(response){
return response;
},
pollNumberOfPlayers: function() {
var self = this;
return Backbone.ajax('/numberOfPlayers/endpoint').then(function(resp) {
self.set(resp, {add: false, remove: false, merge: true});
});
},
startPolling: function() {
var self = this,
timer = 10000; //10 seconds
self.pollNumberOfPlayers().then(function() {
setTimeout(function() {
self.startPolling();
}, timer);
});
}
});
Note that I assumed your GameModel objects have gameId as their idAttribute.

Categories