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