I am having trouble setting up Partner Referrals when calling the PayPal API using Node.
Every time I attempt to call the API I receive the following error:
error: "invalid_token"
error_description: "The token passed in was not found in the system"
According to the documentation the URL to call is https://api-m.sandbox.paypal.com/v2/customer/partner-referrals
Looking at the URL and the error message, I believe I am getting this error because I am using production credentials, not sandbox. However, I cannot find any documentation showing the production URL for this.
Am I correct in believing this is the sandbox URL? What is the production URL if so?
Ive followed the onboarding checklist but cant seem to make this work.
Here is my code:
getAuthToken = async () => {
const clientIdAndSecret = "mylongsecret";
const authUrl = "https://api-m.paypal.com/v1/oauth2/token";
const base64 = Buffer.from(clientIdAndSecret).toString('base64')
const response = await fetch(authUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Accept-Language': 'en_US',
'Authorization': `Basic ${base64}`,
},
body: 'grant_type=client_credentials'
});
const data = await response.json();
return data;
}
setUpMerchant = async () => {
let authData = await this.getAuthToken();
const partnerUrl = "https://api-m.sandbox.paypal.com/v2/customer/partner-referrals";
let data = {
"operations": [
{
"operation": "API_INTEGRATION",
"api_integration_preference": {
"rest_api_integration": {
"integration_method": "PAYPAL",
"integration_type": "THIRD_PARTY",
"third_party_details": {
"features": [
"PAYMENT",
"REFUND"
]
}
}
}
}
],
"products": [
"EXPRESS_CHECKOUT"
],
"legal_consents": [
{
"type": "SHARE_DATA_CONSENT",
"granted": true
}
]
};
const request = await fetch(partnerUrl, {
method: 'POST',
headers: {
'Authorization': 'Bearer '+authData.access_token,
'Content-Type': 'application/json',
'data': data,
},
});
const partnerData = await request.json();
return partnerData;
}
Edit: I discovered the issue was I was running a GET request instead of a POST. The accepted answer is the correct URL
According to the documentation the URL to call is https://api-m.sandbox.paypal.com/v2/customer/partner-referrals
The production URL does not have sandbox. in the domain.
Related
In Pipedream, I have an OpenWeatherAPI request that successfully retrieves forecast data for temperature on a given day.
My goal is to send this forecast to send a PUT request to a service called Apilio that stores a temperature value for further evaluation.
I’m able to conduct the GET and PUT HTTP requests respectively, but unable to pass the data within Pipedream. In other words, I can manually type in a temperature value in the PUT request, but unable to pass it as a variable.
Here is my script thus far:
import axios from "axios"
export default defineComponent({
async run({ steps, $ }) {
const feelslikeresponse =
steps.OpenWeatherAPI.$return_value.daily[7].feels_like.morn;
return feelslikeresponse;
const { data } = await axios({
method: "PUT",
url: "https://api.apilio.com/api/v1/numeric_variables/(my UUID)",
})
return data.species
}, })
var data = { "numeric_variable": { "value": feelslikeresponse } };
let config = {
"method": 'put',
"url": 'https://api.apilio.com/api/v1/numeric_variables/(my UUID)',
"headers": {
'Content-Type': 'application/json',
'Authorization': 'Basic (my header code)'
},
data : data
};
axios(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});
Within the code preview, I am able to hover over steps.OpenWeatherAPI.$return_value.daily[7].feels_like.morn and see the temperature value, but subsequent references to it are lost.
I am still new to coding and would appreciate any pointers or guidance.
Thanks to Wesley for the lesson and scrutinizing syntax. Between this and some hints from the Pipedream forums, how Axios works, and other documentation, I worked out the solution as follows:
import {axios} from "#pipedream/platform";
export default defineComponent({
async run({ steps, $ }) {
const feelslikeresponse =
steps.OpenWeatherAPI.$return_value.daily[7].feels_like.morn;
let data = JSON.stringify({
"numeric_variable":{
"value":feelslikeresponse
}
})
const { config } = await axios($,{
method: "put",
url: "(myUUID)",
headers: {
"Content-Type": "application/json",
Authorization:
"Basic (headercode)",
},
data : data
});
return feelslikeresponse;
},
});
So I have an axios request to a rapid API, my function looks like this...
//Initialize the lookup API that utalizes rapidAPI to get breach data
app.get("/lookup/:email/:function", (req, res) => {
var options = {
method: "GET",
url: "https://breachdirectory.p.rapidapi.com/",
params: { func: `${req.params.function}`, term: `${req.params.email}` },
headers: {
"x-rapidapi-host": "breachdirectory.p.rapidapi.com",
"x-rapidapi-key": `${config.RAPID_API_KEY}`,
},
};
axios
.request(options)
.then(function (response) {
res.json(response.data);
})
.catch(function (error) {
console.error(error);
});
}
});
The res.json(response.data); will show on the page a result like this:
{
"disclaimer": "This data is aggregated from BreachDirectory, HaveIBeenPwned, and Vigilante.pw.",
"info": "For full source info, request e.g. https://breachdirectory.tk/api/source?name=Animoto",
"sources": [
"123RF",
"500px",
"Adobe",
"AntiPublic",
"Apollo",
"Bitly",
"Dave",
"Disqus",
"Dropbox",
"ExploitIn",
"ShareThis",
"Straffic",
"Ticketfly",
"Tumblr",
"VerificationsIO"
]
}
I want to loop through everything in the "sources" array, and call upon the following:
https://haveibeenpwned.com/api/v3/breach/[ITEM]
So, the first one will call upon https://haveibeenpwned.com/api/v3/breach/123RF
So each result from that call will look like this:
{
"Name": "123RF",
"Title": "123RF",
"Domain": "123rf.com",
"BreachDate": "2020-03-22",
"AddedDate": "2020-11-15T00:59:50Z",
"ModifiedDate": "2020-11-15T01:07:10Z",
"PwnCount": 8661578,
"Description": "In March 2020, the stock photo site 123RF suffered a data breach which impacted over 8 million subscribers and was subsequently sold online. The breach included email, IP and physical addresses, names, phone numbers and passwords stored as MD5 hashes. The data was provided to HIBP by dehashed.com.",
"LogoPath": "https://haveibeenpwned.com/Content/Images/PwnedLogos/123RF.png",
"DataClasses": [
"Email addresses",
"IP addresses",
"Names",
"Passwords",
"Phone numbers",
"Physical addresses",
"Usernames"
],
"IsVerified": true,
"IsFabricated": false,
"IsSensitive": false,
"IsRetired": false,
"IsSpamList": false
}
I want to make my res.json send over a JSON string that will have all the sources still there, along with the "Title","Description", and "LogoPath" from the API calls that it pulled for each one of the sources. So I will have a JSON string with the sources along with the title of each source, description of each source, and LogoPath of each source.
You have two options:
Create an array of promises and run with Promise.all
app.get('/lookup/:email/:function', async (req, res) => {
var options = {
method: 'GET',
url: 'https://breachdirectory.p.rapidapi.com/',
params: { func: `${req.params.function}`, term: `${req.params.email}` },
headers: {
'x-rapidapi-host': 'breachdirectory.p.rapidapi.com',
'x-rapidapi-key': `${config.RAPID_API_KEY}`,
},
};
axios.request(options)
.then((response) => {
const requestTasks = [];
for (let item of response.data.sources) {
const itemOption = {
method: 'GET',
url: `https://haveibeenpwned.com/api/v3/breach/${item}`,
headers: {
'content-type': 'application/json; charset=utf-8'
}
};
requestTasks.push(axios.request(itemOption));
}
return Promise.all(requestTasks);
})
.then((responseList) => {
for (let response of responseList) {
console.log(response.data);
}
})
.catch((error) => {
console.error(error);
});
});
Use async/await (promise) and for await for get data from for loop
app.get('/lookup/:email/:function', async (req, res) => {
try {
var options = {
method: 'GET',
url: 'https://breachdirectory.p.rapidapi.com/',
params: { func: `${req.params.function}`, term: `${req.params.email}` },
headers: {
'x-rapidapi-host': 'breachdirectory.p.rapidapi.com',
'x-rapidapi-key': `${config.RAPID_API_KEY}`,
},
};
const response = await axios.request(options);
for await (let item of response.data.sources) {
const itemOption = {
method: 'GET',
url: `https://haveibeenpwned.com/api/v3/breach/${item}`,
headers: {
'content-type': 'application/json; charset=utf-8'
}
};
const itemResponse = await axios.request(itemOption);
console.log(itemResponse.data);
}
} catch (error) {
console.error(error);
}
});
This how I managed to make it works.
first: I didn't had any APi key (and didn't want to register to get one) So i used a dummy Api.
although the logic stay the same as i have tested the result.
second i kept all your initial url just next to the one i used.so you can easily switch back to your original url.
finally i put comment to any critical part, and i named variable in a
way that they almost describe what they do.
so you can copy past test it to understand my logic then adapt it to your use case.
here the code
// make sure to replace /lookup by /lookup/:email/:function after testing my logic
app.get('/lookup', async (req, res) => {
try {
// in this options no change just switch back to your url
var options = {
method: 'GET',
url: 'https://jsonplaceholder.typicode.com/albums',
// url: "https://breachdirectory.p.rapidapi.com/",
// params: { func: `${req.params.function}`, term: `${req.params.email}` },
// headers: {
// 'x-rapidapi-host': 'breachdirectory.p.rapidapi.com',
// 'x-rapidapi-key': `${config.RAPID_API_KEY}`,
// },
};
// here you get all your sources list (in my case it an array of object check picture 1 bellow)
const allSources = await axios.request(options)
console.log(allSources.data);
// because my dummy api response is a huge array i slice to limited number
const reduceAllsource = allSources.data.slice(0,5);
console.log(reduceAllsource);
// note here you need to replace reduceAllsource.map by allSources.data.map
// because you don't need a sliced array
const allSourcesWithDetails = reduceAllsource.map(async (_1sourceEachtime)=>{
// here you can switch back to your original url
// make sure to replace [ITEM] by ${_1sourceEachtime}
const itemOption = await axios({
method: 'GET',
url: `https://jsonplaceholder.typicode.com/albums/${_1sourceEachtime.id}/photos`,
// url:`https://haveibeenpwned.com/api/v3/breach/[ITEM]`
headers: {
'content-type': 'application/json; charset=utf-8'
}
});
// this the place you can mix the 2 result.
const mixRes1AndRes2 ={
sources:_1sourceEachtime.title,
details:itemOption.data.slice(0,1)
}
return mixRes1AndRes2;
})
// final result look like the picture 2 below
finalRes= await Promise.all(allSourcesWithDetails);
return res.status(200).json({response: finalRes});
}
catch (error) {
console.log(error);
}
});
Picture 1
Picture 2
A contract consists of a number of tokens with different balances. I am using an API to get the information about the tokens present in it in an array. Information I am getting is given below:
"token_address": "0x2d30ca6f024dbc1307ac8a1a44ca27de6f797ec22ef20627a1307243b0ab7d09",
"name": "Kylin Network",
"symbol": "KYL",
"decimals": "18",
"balance": "123456789"
}]
I want to use the address of each token to call another api to get the current price of the token and multiply it with the balance present in the information above. Here is my code :
var add = "0x0e09fabb73bd3ade0a17ecc321fd13a19e81ce82"
var tokens = [];
fetch(`https://deep-index.moralis.io/api/account/erc20/balances?chain=bsc&chain_name=mainnet&address=${add}`, {
method: 'GET',
headers: {
'X-API-KEY': 'unT7o....bgF6fVAgNW6AU',
'Accept': '*/*',
}
}).then(res => res.json()).then(json => json.map(item => {
tokens.push(item.token_address);
tokens.forEach((token) => fetch(`https://deep-index.moralis.io/api/token/ERC20/${token}/price?chain=bsc&chain_name=mainnet&providerUrl=https%3A%2F%2Fthrjqwgeodkr.usemoralis.com%3A2053%2Fserver`, {
method: 'GET',
headers: {
'X-API-KEY': 'unT7...........rZhbgF6fVAgNW6AU',
'Accept': '*/*',
}
}).then(res => res.json()).then(data => console.log(data.usdPrice)));
}))
I am getting promise pending for some of the tokens. Is there an issue with the code?
That code is pretty unreadable. Instead of using promise chaining and getting the issues like you are, I would suggest an async await approach which achieves the same thing as promise chaining in a more readable manner. The below is to get you started, but I think you need to do some more reading/research first.
var add = '0x0e09fabb73bd3ade0a17ecc321fd13a19e81ce82'
const fetchOne = await(
await fetch(
`https://deep-index.moralis.io/api/account/erc20/balances?chain=bsc&chain_name=mainnet&address=${add}`,
{
method: 'GET',
headers: {
'X-API-KEY': 'unT7o....bgF6fVAgNW6AU',
Accept: '*/*',
},
},
),
).json()
const tokens = fetchOne.map((item) => item.token_address)
const data = await Promise.all(
tokens.map((token) => {
return fetch(
`https://deep-index.moralis.io/api/token/ERC20/${token}/price?chain=bsc&chain_name=mainnet&providerUrl=https%3A%2F%2Fthrjqwgeodkr.usemoralis.com%3A2053%2Fserver`,
{
method: 'GET',
headers: {
'X-API-KEY': 'unT7...........rZhbgF6fVAgNW6AU',
Accept: '*/*',
},
},
).json()
}),
)
I recently found out that request is no longer maintained, so the best alternative I found is got. I am trying to make an external API call to a REST Server but I am unsure as to how I can add a Bearer token in the authorization header of the POST request.
This is my code:
const response = await got.post(
"https://${SERVER}/${SOME_ID}/conversations/${CONVERSATION_ID}/messages",
{
json: [
{
text: req.body.message,
type: "SystemMessage",
}
],
responseType: "json",
headers: {
token: "Bearer pXw4BpO95OOsZiDQS7mQvOjs"
}
}
);
This results in a 401 Unauthorized. I was unable to find direction to such implementation in the documentation provided by GOT. And since there are not a lot of queries regarding this package, I was unsuccessful in finding anything on Google as well. If anyone can help me out in this regard, that would be very helpful!
Are you sure that the header name is "token" ?
Usually in API, the Bearer is in a header called "Authorization"
const response = await got.post(
"https://${SERVER}/${SOME_ID}/conversations/${CONVERSATION_ID}/messages",
{
json: [
{
text: req.body.message,
type: "SystemMessage",
}
],
responseType: "json",
headers: {
"Authorization": "Bearer pXw4BpO95OOsZiDQS7mQvOjs"
}
}
);
Here is the code
npm i postman-request link for npm package
const request = require('postman-request');
request({
url: 'your url',
headers: {
'Authorization': 'Bearer 71D50F9987529'
},
rejectUnauthorized: false
}, function(err, res) {
if(err) {
console.error(err);
} else {
console.log(res.body);
}
});
I'm trying to create media item using Google Photos API. Endpoint is documented here. If I copy and paste my payload to an API explorer which can be found in documentation, I get success:
Request inputed to an API Explorer and Successful response.
If I do the same in my node js program, I'm getting an error.
This is what I do:
const accessToken = "MyAccessToken";
payload = {
"newMediaItems": [
{
"description": "picture",
"simpleMediaItem": {
"uploadToken": "CAIS+QIASsyg4OQLX2Ao5hy6I734/b01mjk3Mqpom6DQ24iv7ZfAYLiXAy0WpOXCWJBNHrmBs6FE+a9Axu5CML+Ryu4VGawyf4skxM763mzC5GcjMY4rS/r6IwOekBIoE/aMJLJpRr1gW8jdhVJM89+kioTx9d+shyYeQDbVI8ezb1lXGp6irc9hZl7QA6xd+msXzbLD5nb+wc5CA6du95tP3buh5R5N/Knn+NwByebdEPCusl+X3p7DZ6ha72kLthUqdvwFsp8dpnGbNQBq8AFPVNHXB4C543iq+dYiRFYtICCxO8xi2cpONVT54Jl6l9rGh3Vnidwj5IwkbsXkyiN96HfRb9XLh0rCBw4ydV6Y9+C+OmTAqlQwIKy50I/ykHyzggroeJSbgphiQwFR2EbHwAeSKdsdIB03ItnunHtf3F2LRIitDRGI1n4VUEYE1dYjrrjR791ao24Dp8J3Hg8IRb8E3vFTeYMWyOk4mh/zQGInfNBnRY2ruHH0JA"
}
}
]
};
const response = await fetch('https://photoslibrary.googleapis.com/v1/mediaItems:batchCreate', {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${accessToken}`
},
payload: JSON.stringify(payload)
});
const json = await response.json();
console.log(json);
And getting this response:
{ error:
{ code: 400,
message: 'Request must have at least one newMediaItem.',
status: 'INVALID_ARGUMENT' } }
What could go wrong here?
Any help is appreciated, thank you.
It looks like you are setting the JSON payload in the wrong parameter in your call to fetch. It should be set in the parameter body (and not in payload). The JSON itself looks okay.
This snippet should work:
const response = await fetch('https://photoslibrary.googleapis.com/v1/mediaItems:batchCreate', {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${accessToken}`
},
body: JSON.stringify(payload)
});
Source: node-fetch 'Post with JSON' example