CustomHook with multiple functions doesn't work - javascript

I am not sure why this customhook doesn't work , I am trying to make a payment Integration to my website but it doesn't return the frame to the other component so i can get the link , here is the code
import React , {useState} from 'react'
import { useEffect } from 'react';
export async function usePayment(data) {
const API = process.env.PAYMOB_API;
const integrationID = 2874212;
const [frame,setFrame] = useState('');
async function firstStep (datas) {
let data = {
"api_key": API
}
let request = await fetch('https://accept.paymob.com/api/auth/tokens' , {
method : 'post',
headers : {'Content-Type' : 'application/json'} ,
body : JSON.stringify(data)
})
let response = await request.json()
let token = response.token
await secondStep(token , datas)
}
async function secondStep (token , datas) {
let data = {
"auth_token": token,
"delivery_needed": "false",
"amount_cents": datas.amount * 100,
"currency": "EGP",
"items": [],
}
let request = await fetch('https://accept.paymob.com/api/ecommerce/orders' , {
method : 'post',
headers : {'Content-Type' : 'application/json'} ,
body : JSON.stringify(data)
})
let response = await request.json()
let id = response.id
await thirdStep(datas , token , id)
}
async function thirdStep (datas , token , id) {
let data = {
"auth_token": token,
"amount_cents": datas.amount * 100,
"expiration": 3600,
"order_id": id,
"billing_data": {
"apartment": "803",
"email": datas.email,
"floor": "42",
"first_name": datas.name,
"street": "Ethan Land",
"building": "8028",
"phone_number": "00000000000",
"shipping_method": "PKG",
"postal_code": "01898",
"city": "Jaskolskiburgh",
"country": "CR",
"last_name": "Nicolas",
"state": "Utah"
},
"currency": "EGP",
"integration_id": integrationID
}
let request = await fetch('https://accept.paymob.com/api/acceptance/payment_keys' , {
method : 'post',
headers : {'Content-Type' : 'application/json'} ,
body : JSON.stringify(data)
})
let response = await request.json()
let TheToken = response.token
let iframURL = `https://accept.paymob.com/api/acceptance/iframes/377194?payment_token=${TheToken}`
setFrame(iframURL)
console.log(frame)
}
useEffect(() =>{
firstStep(data)
},[])
return { frame };
}
export default usePayment;`
I am not sure what is missing here , please need someone to guide me why multiple functions in customhook doesn't work , error message is
Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1 - You might have mismatching versions of React and the renderer (such as React DOM)
2 - You might be breaking the Rules of Hooks
3 - You might have more than one copy of React in the same app
and this is the code i use to call the function :
const handleSubmit = async (event) => {
event.preventDefault();
try {
if ( !name || !email || !amount ) {
generateError("Please Fill The Form !")
} else {
const { frame } = await usePayment(datas);
console.log(frame)
// location.href = pay.iframURL;
}
} catch (err) {
console.log(err);
}
};
I expect to get a url to the frame state then pass it to another component
NOTE : that this functions works fine when i add it to the component but its not working as a customhook , i am not sure why

For this use case it would be better not to use a hook, rather just write this as a js function. There's no advantage I can see to using a hook, since you're just waiting for data in useEffect and invoking the 3 api calls after that. Instead just send the payload directly to the async function when needed.
const API = process.env.PAYMOB_API;
const integrationID = 2874212;
async function firstStep (data) {
let data = {
"api_key": API
}
let request = await fetch('https://accept.paymob.com/api/auth/tokens' , {
method : 'post',
headers : {'Content-Type' : 'application/json'} ,
body : JSON.stringify(data)
})
const { token } = await request.json()
return token
}
async function secondStep ({token , data}) {
let data = {
"auth_token": token,
"delivery_needed": "false",
"amount_cents": data.amount * 100,
"currency": "EGP",
"items": [],
}
let request = await fetch('https://accept.paymob.com/api/ecommerce/orders' , {
method : 'post',
headers : {'Content-Type' : 'application/json'} ,
body : JSON.stringify(data)
})
const { id } = await request.json()
return id
}
async function thirdStep ({data , token , id}) {
let data = {
"auth_token": token,
"amount_cents": data.amount * 100,
"expiration": 3600,
"order_id": id,
"billing_data": {
"apartment": "803",
"email": data.email,
"floor": "42",
"first_name": data.name,
"street": "Ethan Land",
"building": "8028",
"phone_number": "00000000000",
"shipping_method": "PKG",
"postal_code": "01898",
"city": "Jaskolskiburgh",
"country": "CR",
"last_name": "Nicolas",
"state": "Utah"
},
"currency": "EGP",
"integration_id": integrationID
}
let request = await fetch('https://accept.paymob.com/api/acceptance/payment_keys' , {
method : 'post',
headers : {'Content-Type' : 'application/json'} ,
body : JSON.stringify(data)
})
let response = await request.json()
let TheToken = response.token
let iframURL = `https://accept.paymob.com/api/acceptance/iframes/377194?payment_token=${TheToken}`
return frame;
}
}
export async function handlePayment(data) => {
const token = await firstStep(data);
const id = await secondStep({ data, token });
return await thirdStep({ data, token, id })
}
export default handlePayment;`

Related

Why does my fetch function return undefined? [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 10 months ago.
I'm making a chrome extension where I'm calling the youtube API and using fetch() to do so. I don't understand why I'm getting an undefined variable when I call the function. Here is where I'm calling the function;
document.querySelector("[type=button]").addEventListener("click", function() {
//console.log("this was clicked");
let videoId = document.getElementById('vidUrl').value;
videoId = videoId.substring(videoId.indexOf('=') + 1);
console.log(videoId);
//chrome.runtime.sendMessage({ msg: "startFunc", vidId: videoId});
let request = addToQueue(videoId);
console.log(request);
console.log(request.snippet.title);
let table = document.querySelector(".table");
let row = table.insertRow(table.rows.length);
let title = row.insertCell(0);
let author = row.insertCell(1);
title.innerHTML = request.Data.snippet.title;
author.innerHTML = request.Data.snippet.videoOwnerChannelTitle;
})
and this is the function itself;
function addToQueue(vidId){
chrome.identity.getAuthToken({ interactive: true }, function (token) {
//console.log(token);
let fetchString = 'https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&key=xxxxxxxxxxxxxxxxxx'
let post =
{
"part": [
"snippet"
],
"id": "UC0E5pDp_c2riLV4UhEgynKA",
"snippet": {
"playlistId": "PLu4fFFN_062GzqARIz3gnERiJ8M4GbRcL",
"position": 1,
"resourceId": {
"kind": "youtube#video",
"videoId": vidId
}
}
}
let fetchOptions = {
method: 'POST',
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(post),
}
fetch(fetchString,fetchOptions)
.then((response) => response.json())
.then(function (data) {
console.log(data);
//console.log(typeof data);
//chrome.runtime.sendMessage({Data : data});
return data;
});
})
}
I'm fairly new to javascript and chrome extensions so please forgive me if this is something obvious.
The issue here is that you not returning anything from the addToQueue function. This will always return undefined. The return statement you are using returns from the callback, but not the function itself.
Update your method and put a return in front of the fetch call, like this:
async function addToQueue(vidId){
return chrome.identity.getAuthToken({ interactive: true }, async function (token) {
//console.log(token);
let fetchString = 'https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&key=xxxxxxxxxxxxxxxxxx'
let post =
{
"part": [
"snippet"
],
"id": "UC0E5pDp_c2riLV4UhEgynKA",
"snippet": {
"playlistId": "PLu4fFFN_062GzqARIz3gnERiJ8M4GbRcL",
"position": 1,
"resourceId": {
"kind": "youtube#video",
"videoId": vidId
}
}
}
let fetchOptions = {
method: 'POST',
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(post),
}
const response = await fetch(fetchString,fetchOptions)
return await response.json()
})
}
When calling this method the async/await you will need to update your event listener function to be async
document.querySelector("[type=button]").addEventListener("click", async function() {
//console.log("this was clicked");
let videoId = document.getElementById('vidUrl').value;
videoId = videoId.substring(videoId.indexOf('=') + 1);
console.log(videoId);
//chrome.runtime.sendMessage({ msg: "startFunc", vidId: videoId});
let request = await addToQueue(videoId);
console.log(request);
console.log(request.snippet.title);
let table = document.querySelector(".table");
let row = table.insertRow(table.rows.length);
let title = row.insertCell(0);
let author = row.insertCell(1);
title.innerHTML = request.Data.snippet.title;
author.innerHTML = request.Data.snippet.videoOwnerChannelTitle;
})
Also, I have used the new async/await syntax after discussing with OP in comments

Error response graph.microsoft.com/v1.0/me/manager

Look at my code, what am I doing wrong? I need to get https://graph.microsoft.com/v1.0/users/${uniqueName}/manager. But the request fails
But when I try to execute the https://graph.microsoft.com/v1.0/${uniqueName} query, everything goes well. What to fix so that the https://graph.microsoft.com/v1.0/users/${uniqueName}/manager request is successful?
fastify.post('/login', {
preHandler: (request, _, next) => {
if (!request.body || !request.body.username || !request.body.password) {
const error = new Error('Credentials are missing');
error.statusCode = 400;
return next(error);
}
return next();
},
}, async (request, reply) => {
const { username, password } = request.body;
const userData = await fastify.helpers.authentication.getUserTokens(username, password, azureConfig.CLIENT_SCOPE);
await replyWithTokens(fastify, reply, userData);
});
And next
const getUserTokens = async (username, password, scope) => {
const authUrl = `https://login.microsoftonline.com/${azureConfig.TENANT_NAME}/oauth2/v2.0/token`;
const body = {
client_id: azureConfig.CLIENT_ID,
client_secret: azureConfig.CLIENT_SECRET,
grant_type: 'password',
password,
scope,
username,
};
const authResponse = await fetch(authUrl, {
body: new URLSearchParams(body).toString(),
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'POST',
});
if (!authResponse.ok) {
fastify.helpers.error.throwError(422, 'Authentication failed');
}
const result = await authResponse.json();
const decodedData = jwt.decode(result.access_token);
const uniqueName = String(decodedData.unique_name || '').toLowerCase();
const name = String(decodedData.upn || uniqueName).toLowerCase();
const agentAttributes = {};
if (!uniqueName) {
fastify.helpers.error.throwError(400, 'Unique name not found');
}
let recheckSan = true;
let san = name.split('#').shift();
let agent = await fastify.db.models.Agent.findOne({
where: { uniqueName },
});
let radId = '';
const graphAuthResponse = await fetch(authUrl, {
body: new URLSearchParams({
...body,
scope: 'email openid profile https://graph.microsoft.com/User.Read',
}).toString(),
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'POST',
});
if (graphAuthResponse.ok) {
const graphAuthResult = await graphAuthResponse.json();
const { access_token: graphAccessToken = '' } = graphAuthResult;
// eslint-disable-next-line max-len
const graphResponse = await fetch(`https://graph.microsoft.com/v1.0/users/${uniqueName}/manager`, {
headers: {
authorization: `Bearer ${graphAccessToken}`,
'content-type': 'application/json',
},
});
if (graphResponse.ok) {
const graphResult = await graphResponse.json();
console.log(graphResult)
}
}
}
I want to receive such response
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#directoryObjects/$entity",
"#odata.type": "#microsoft.graph.user",
"id": "1111112-68cf-4896-b2d0-13b5c6264113",
"businessPhones": [
"111 111 11111"
],
"displayName": "Wer, John",
"givenName": "John",
"jobTitle": "SENIOR DEVELOPMENT ARCHITECT",
"mail": "somemail#mail.com",
"mobilePhone": "111 111 1111",
"officeLocation": "Atlanta",
"preferredLanguage": null,
"surname": "John",
"userPrincipalName": "somemail#mail.com"
}
But I get such an error response. What am I doing wrong? Thanks!
{
"error": {
"code": "Authorization_RequestDenied",
"message": "Insufficient privileges to complete the operation.",
"innerError": {
"date": "2022-01-14T20:40:30",
"request-id": "9e2b5937-4bd0-4fdb-a1ae-1b22cef09772",
"client-request-id": "9e2b5937-4bd0-4fdb-a1ae-1b22cef09772"
}
}
}
To get the managers of other users in your organization on your behalf, you need to have User.Read.All delegated permission
Once the permission is assigned, admin consent needs to be granted for the same.
Then you would be able to fetch the managers info of other users in your organization
You can test the same in Graph Explorer first. If it is successful, you can make the changes accordingly in your JavaScript code

How to put a buffer in an HTTP request?

I’m trying to put a buffer in a request because I have a list of data to import. I want to have success request after one another. The problem I’m encountering is that it waits to upload all data of the request.
Here is the sample data:
[
{
"contacts": "dsds#dsd.com",
"recipient": "dsd#dsd.com",
"date_sent": "07/08/2020 17:05:04",
"subject": "repurchase"
},
{
"contacts": "asd#ret.com",
"recipient": "test#yahoo.com",
"date_sent": "07/10/2020 17:31:51",
"subject": "biz"
},
{
"contacts": "we#sdf.com",
"recipient": "abc#yahoo.com",
"date_sent": "07/09/2020 13:02:54",
"subject": "rock"
}
];
const createEngage = async(body) => {
const BASE_URL = '/api/import'
var requestOptions = {
method: 'POST',
headers: {
'Accept': 'application/json',
"Content-Type": "application/json"
},
body: body
};
fetch(BASE_URL, requestOptions)
.then(response => response.text())
.then(async result => {
console.log(result);
})
.catch(error => console.log('error', error));
}
What you probably want to do is to loop over your data and use async / await to wait at each iteration. Your implementation of your asynchronous function currently does not await anything. Instead it should await the fetch request and the decoding of the body with response.text().
Check the response for errors and wrap the fetch request in a try...catch block. If an error occurs then the catch block will be executed. Otherwise check the response object for any states or errors you want to include.
const data = [
{
"contacts": "dsds#dsd.com",
"recipient": "dsd#dsd.com",
"date_sent": "07/08/2020 17:05:04",
"subject": "repurchase"
},
{
"contacts": "asd#ret.com",
"recipient": "test#yahoo.com",
"date_sent": "07/10/2020 17:31:51",
"subject": "biz"
},
{
"contacts": "we#sdf.com",
"recipient": "abc#yahoo.com",
"date_sent": "07/09/2020 13:02:54",
"subject": "rock"
}
];
const BASE_URL = '/api/import'
/**
* Sends a request for each individual item.
*/
const createEngage = async body => {
const requestOptions = {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body
};
try {
const response = await fetch(BASE_URL, requestOptions);
if (!response.ok) {
alert('Your request has failed');
return null;
}
const text = await response.text();
return text;
} catch(error) {
alert('Your request caused an error');
}
};
/**
* Loop over each item and call createEngage.
* Wait for the request to finish and continue.
*/
const createMultipleEngages = async data => {
for (const item of data) {
const result = await createEngage(item); // This will make the loop wait every time.
console.log(result);
}
};
// Call the function and start looping.
createMultipleEngages(data);

convert xml data into json in javascript

Need help to convert xml response data into json value and fetch a value from JSON object.
My current code is:
const soapRequest = require('easy-soap-request');
const fs = require('fs');
var convert = require('xml-js');
// example data
const url = 'https://sentro.com/ws/apf/ticketing/Gateway?WSDL';
const sampleHeaders = {
'user-agent': 'sampleTest',
'Content-Type': 'application/html;charset=UTF-8',
};
const xml = fs.readFileSync('Auto_query_request.txt', 'utf-8');
// usage of module
(async () => {
const { response } = await soapRequest({ url: url, headers: sampleHeaders, xml: xml, timeout: 1000 }); // Optional timeout parameter(milliseconds)
const { headers, body, statusCode } = response;
console.log(headers);
//console.log(body);
const options = {ignoreComment: true, alwaysChildren: true};
var result = JSON.parse(convert.xml2json(body, options));
console.log(result);
})();
When i executed above code , i am getting response like below.
{"declaration":{"attributes":{"version":"1.0","encoding":"UTF-8"}},"elements":[{"type":"element","name":"env:Envelope","attributes":{"xmlns:env":"http://schemas.xmlsoap.org/soap/envelope/","xmlns:wsa":"http://www.w3.org/2005/08/addressing"},"elements":[{"type":"element","name":"env:Header","elements":[{"type":"element","name":"wsa:MessageID","elements":[{"type":"text","text":"urn:5C8DC410D18D11EABFB75749E02F1482"}]},{"type":"element","name":"wsa:ReplyTo","elements":[{"type":"element","name":"wsa:Address","elements":[{"type":"text","text":"http://www.w3.org/2005/08/addressing/anonymous"}]},{"type":"element","name":"wsa:ReferenceParameters","elements":[{"type":"element","name":"instra:tracking.compositeInstanceCreatedTime","attributes":{"xmlns:instra":"http://xmlns.oracle.com/sca/tracking/1.0"},"elements":[{"type":"text","text":"2020-07-29T06:19:25.981-05:00"}]}]}]},{"type":"element","name":"wsa:FaultTo","elements":[{"type":"element","name":"wsa:Address","elements":[{"type":"text","text":"http://www.w3.org/2005/08/addressing/anonymous"}]},{"type":"element","name":"wsa:ReferenceParameters","elements":[{"type":"element","name":"instra:tracking.compositeInstanceCreatedTime","attributes":{"xmlns:instra":"http://xmlns.oracle.com/sca/tracking/1.0"},"elements":[{"type":"text","text":"2020-07-29T06:19:25.981-05:00"}]}]}]}]}
with the above results its very difficult for me to fetch data from JSON object.
So i need convert this xml body with proper JSON object as below.
{
"Header": {
"MessageID": "urn:45597DC0D1B511EA8F1C35236A977E2C",
"ReplyTo": {
"Address": "http://www.w3.org/2005/08/addressing/anonymous",
"ReferenceParameters": {
"tracking.compositeInstanceCreatedTime": "2020-07-29T11:05:06.880-05:00"
}
},
"FaultTo": {
"Address": "http://www.w3.org/2005/08/addressing/anonymous",
"ReferenceParameters": {
"tracking.compositeInstanceCreatedTime": "2020-07-29T11:05:06.880-05:00"
}
}
},
"Body": {
"processResponse": {
"payload": {
"RfcProject": {
"IntegrationStatus": "Query - Success",
"Id": "something query",
"Created": "2020-06-16T10:24:18",
"CreatedBy": "something",
"Updated": "2020-07-23T14:14:03",
"UpdatedBy": "somevalue",
"ProjectNum": "something",
and also how to fetch value from JSON Value .Can anyone help here

How can I get the same content in my react native app as in my postman GET?

I'm communicating with a REST server, which should return ( and this is what I get when I use Postman to request it):
{
"organizer": "Fontysgroup2",
"eventStart": "2019-11-25T11:00:00Z",
"eventStop": "2019-11-25T11:00:00Z",
"room": {
"roomName": "Test Room",
"roomEmail": null,
"password": null
}
},
{
"organizer": "Fontysgroup2",
"eventStart": "2019-11-25T11:00:00Z",
"eventStop": "2019-11-25T11:00:00Z",
"room": {
"roomName": "Test Room",
"roomEmail": null,
"password": null
}
}
]
but this block of code of mine :
await fetch('https://gitroom-backend.azurewebsites.net/api/Event', {
headers: {
Authorization: 'Bearer eyJhbGciOiJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGRzaWctbW9yZSNobWFjLXNoYTI1NiIs',
}
})
.then(res => {
console.log("content"+JSON.stringify(res))
})
}
is returning:
content{"type":"default","status":200,"ok":true,"headers":{"map":{"cache-control":"public, max-age=0","date":"Mon, 25 Nov 2019 13:14:09 GMT","set-cookie":"ARRAffinity=84e8f0e39af3bde1a8c7117e525b046a8722dc904bb8684ace19b555cc8f3590;Path=/;HttpOnly;Domain=gitroom-backend.azurewebsites.net","x-powered-by":"ASP.NET","request-context":"appId=cid-v1:65c12a05-4adc-4521-b71d-69ccdcb78d9f","server":"Microsoft-IIS/10.0","vary":"Accept-Encoding","content-type":"application/json; charset=utf-8","transfer-encoding":"chunked"}},"url":"https://gitroom-backend.azurewebsites.net/api/Event","_bodyInit":{"_data":{"size":331,"offset":0,"blobId":"7592c623-fb09-415e-92f7-a97e75b08d37"}},"_bodyBlob":{"_data":{"size":331,"offset":0,"blobId":"7592c623-fb09-415e-92f7-a97e75b08d37"}}}
How can I access the actual content that I want and which Postman is giving me?
EDIT:
MY Postman:
fetchData = async () => {
const response = await fetch(
"YOUR_URL"
);
const json = await response.json();
}
Now render items iterative using constructor of your data set.
and call in your view by,
{item.YOUR_KEY}

Categories

Resources