Square CreditCard payment in Reactjs - reactjs

I am trying to integrate react-square-web-payments-sdk , Need to add creditcard holder name field in the paymentform and how can i mention the amount to be deducted from card to do that please check the below code and let me know still i need to add anything more.
I have installed react-square-web-payments-sdk and added creditCard in paymentform and getting the fields like cardnumber, mm/yy, cvv. and zipcode, But i need Cardholder name and no need of zip code, How can i do that and from my below code how can i show how much money to be deducted. Below is my component.
const Payment = () => {
const [errorMessage, setErrorMessage] = useState(null);
const onNonceGenerated = async (error, nonce) => {
if (error) {
setErrorMessage(error.message);
return;
}
// Your code to process the payment
try {
// Call your server to process the payment
const response = await fetch("/process-payment", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ nonce }),
});
console.log(response, "resp");
if (!response.ok) {
throw new Error("Failed to process payment");
}
// Payment was successful
alert("Payment successful!");
} catch (error) {
setErrorMessage(error.message);
}
};
return (
<div className="container">
{errorMessage && <p>{errorMessage}</p>}
<PaymentForm
applicationId="sandbox-Id"
locationId="locationId"
cardTokenizeResponseReceived={async (token, verifiedBuyer) => {
console.log(token,"token");
console.log(verifiedBuyer,"verifiedBuyer");
const response = await fetch("/api/pay", {
method: "POST",
headers: {
"Content-type": "application/json",
},
body: JSON.stringify({
sourceId: token.token,
}),
});
console.log(await response.json());
}}
>
<CreditCard
buttonProps={{
css: {
backgroundColor: "#E56B6F",
fontSize: "14px",
color: "#fff",
"&:hover": {
backgroundColor: "#E56B6F",
},
},
}}
/>
</PaymentForm>
</div>
);
};

Related

REACT JS: Crud table delete

I have a parent component that sends props to a CRUD Table, i have a problem with deleting the items i want to delete the item with the selected id and i want to send both the email and id in the body of the request. i create the Info just to send it to the CRUD table to be shown because i don't want the entire pendingList to be shown. The id sent to the request when i click on deleteIcon={<IoTrashOutline style={{fontSize: '18px', color: 'red', cursor: 'pointer'}} onClick={() => handleDeleteProduct(info.id)} />} is undefined and i get it cause info is an array the problem is i'm not sure how to get the specific id of the item i want to delete and send it to the request. Any suggestions?
const UserNewDevice = () => {
const [pendingList, setPendingList] = useState([]);
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState('');
const email = localStorage.getItem("email")
useEffect(() => {
const fetchPendingList = async () => {
setIsLoading(true);
try {
const res = await fetch('http://localhost:5000/prods/user_product', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${localStorage.getItem("token")}`
},
body: JSON.stringify(email),
});
if (!res.ok) {
const data = await res.json();
throw new Error(data.msg);
}
const data = await res.json();
setPendingList(data);
} catch (err) {
setError(err.message);
} finally {
setIsLoading(false);
}
};
fetchPendingList();
}, []);
const info = pendingList.map(item => {
return {
id: item._id,
produit: item.produits,
marque: item.marque,
référence: item.référence,
installation: item.annéeInstallation,
entretenu: item.entretenu,
année: item.selectedYearEntretenu,
}
});
const handleDeleteProduct = async (id) => {
try {
const email = localStorage.getItem("email");
console.log('id', id)
const res = await fetch('http://localhost:5000/prods/remove_product', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${localStorage.getItem('token')}`
},
body: JSON.stringify({ id, email })
});
if (!res.ok) {
const data = await res.json();
throw new Error(data.msg);
}
const data = await res.json();
setPendingList(pendingList.filter(item => item.id !== id));
} catch (err) {
console.error(err);
setError(err.message);
}
};
return (
<>
<div className="mt-10 sm:mt-0 w-[92%] ml-12">
<div className="md:grid md:grid-cols-2 md:gap-6">
<div className="mt-5 md:col-span-2 md:mt-0">
<CRUDTable
data={info}
link={`/user-projets-details/`}
pencilIcon={<IoPencil style={{fontSize: '18px', cursor: 'pointer', color: 'green'}}/>}
eyeIcon={<IoEyeOutline style={{fontSize: '18px', cursor: 'pointer', color: '#f8c408'}}/>}
deleteIcon={<IoTrashOutline style={{fontSize: '18px', color: 'red', cursor: 'pointer'}} onClick={() => handleDeleteProduct(info.id)} />}
/>
</div>
</div>
</div>
</>
)
}
export default UserNewDevice
The issue is that info is an array, not an object, and info.id is not a valid reference. To get the specific id of the item you want to delete, you need to pass it as a parameter when calling the handleDeleteProduct function from within the deleteIcon prop. You can modify the code as follows:
deleteIcon={(id) => <IoTrashOutline style={{fontSize: '18px', color: 'red', cursor: 'pointer'}} onClick={() => handleDeleteProduct(id)} />}
And when you call it in the map function:
const info = pendingList.map(item => {
return {
id: item._id,
produit: item.produits,
marque: item.marque,
référence: item.référence,
installation: item.annéeInstallation,
entretenu: item.entretenu,
année: item.selectedYearEntretenu,
}
});
Becomes:
const info = pendingList.map(item => {
return {
id: item._id,
produit: item.produits,
marque: item.marque,
référence: item.référence,
installation: item.annéeInstallation,
entretenu: item.entretenu,
année: item.selectedYearEntretenu,
deleteIcon: item._id,
}
});

Expo Download file. FileSystem Download Async method POST with body

I need a way to make a request with method Post passing a body but I didnt find a way to do it. The documentation: https://docs.expo.io/versions/latest/sdk/filesystem/ only show the GET method, I need a way to make a post request passing the body.
FileSystem.downloadAsync(${baseUrl}/v1/paycheck/pdf, FileSystem.documentDirectory + ‘file.pdf’,
{
headers: {
‘Authorization’: localToken
},
httpMethod: ‘POST’,
body: {
type: 'monthy',
year: '2021',
month: 2,
employer: {
name: "Pink",
}
}
}
)
.then(({uri}) => {
Sharing.shareAsync(uri, {dialogTitle: 'Salvar ou Compartilhar'})
})
.catch(error => {
console.error(error);
});
}
As far as I understand your problem
My Approach for Downloading and Sharing the PDF would be
Writing these two functions
// Execute this function when you to share the file...
const GetPDF = async () => {
try {
const response = await fetch(`${baseUrl}/v1/paycheck/pdf`, {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
Authorization: "localToken",
},
body: JSON.stringify({
type: "monthy",
year: "2021",
month: 2,
employer: {
name: "Pink",
},
}),
});
const content = await response.json();
DownloadThenShare(content); // Some URI
} catch (error) {
console.error(error);
}
};
Now DownloadAndShare function
// This function will execute after Download has been completed successfully
const DownloadThenShare = async (uri) => {
const downloadInstance = FileSystem.createDownloadResumable(
uri,
FileSystem.documentDirectory + "file.pdf"
);
const result = await FileSystem.downloadInstance.downloadAsync();
if (result.status === 200) {
Sharing.shareAsync(result.uri, { dialogTitle: "Salvar ou Compartilhar" });
} else {
console.log("Failed to Download");
}
};
I finally managed to make it work using axios e FileReader();
const response = await axios.post(`${baseUrl}/v1/paycheck/pdf`, data, {responseType: 'blob'});
const fr = new FileReader();
fr.onload = async () => {
const fileUri = `${FileSystem.documentDirectory}/document.pdf`;
const result = await FileSystem.writeAsStringAsync(fileUri, fr.result.split(',')[1], {encoding: FileSystem.EncodingType.Base64});
saveFile(fileUri);
};
fr.readAsDataURL(response.data);

React Redux components with REST Endpoints and reusable components

I am working on a React-Redux (with hooks) project, where I have a baseURL with different endpoints. For example
baseURL = "https://jsonplaceholder.typicode.com"
endpoints = "/posts", "/comments", "/albums"
I have 2 questions:
Where to keep the endpoint in the react (comments) component (for example: "/comments")
How to reuse the code for other components like posts and albums because the accessToken code and headers are same for all of them.
const accessToken = localStorage.getItem("accessToken");
Cookies.set("XSRF-TOKEN", Cookies.get("XSRF-TOKEN"));
var bodyParameters = {
page: 1,
pageSize: 50,
};
return fetch(baseURL, {
credentials: "include",
method: "post",
body: JSON.stringify(bodyParameters),
headers: {
Authorization: `JWT ${accessToken}`,
"X-XSRF-TOKEN": Cookies.get("XSRF-TOKEN"),
"cache-control": "no-cache",
pragma: "no-cache",
},
My redux action looks like this
export const readList = () => {
return (dispatch) => {
const accessToken = localStorage.getItem("accessToken");
Cookies.set("XSRF-TOKEN", Cookies.get("XSRF-TOKEN"));
var bodyParameters = {
page: 1,
pageSize: 50,
};
return fetch(baseURL, {
credentials: "include",
method: "post",
body: JSON.stringify(bodyParameters),
headers: {
Authorization: `JWT ${accessToken}`,
"X-XSRF-TOKEN": Cookies.get("XSRF-TOKEN"),
"cache-control": "no-cache",
pragma: "no-cache",
},
})
.then((response) => {
return response.json();
})
.then((data) =>
dispatch(
{
type: READ_LIST,
payload: data,
},
console.log("Actions: ", data)
)
)
.catch((error) => {
console.log(error.response);
throw error;
});
};
};
and the react component looks like this
import "./styles.css";
import React, { useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";
import { readList } from "./redux/actionCreators";
import { FormattedMessage } from "react-intl";
import { DataGrid } from "#material-ui/data-grid";
export default function App() {
const dispatch = useDispatch();
const historyList = useSelector(
(state) => state.reducers.commentsData.data || []
);
useEffect(() => {
dispatch(readList());
}, [dispatch]);
let rows = historyList.map((obj, index) => {
return (rows = {
id: index,
"User ID": obj.userId,
Title: obj.title,
Body: obj.body
});
});
const columns = [
{
field: "User ID",
flex: 1,
renderHeader: () => <FormattedMessage id={"userId"} />
},
{
field: "Title",
flex: 1,
value: "dropdown",
renderHeader: () => <FormattedMessage id={"title"} />
},
{
field: "Body",
flex: 1,
type: "date",
renderHeader: () => <FormattedMessage id={"body"} />
}
];
return (
<div className={"uhes-pageWrapper"}>
<h1 className="uhes-pageHeader">
<FormattedMessage id="History" />
</h1>
<div style={{ height: "90%", width: "100%" }}>
<DataGrid
pageSize={50}
rowsPerPageOptions={[50, 100, 150]}
rows={rows}
columns={columns}
/>
</div>
</div>
);
}
Thank you!
The ideas to reuse api configs, includes baseURL, accesstoken,... somethings like this
You will have a service called apiService: where you manage your fetch configs like headers, and you can also add your token in there. apiService will return REST functions: POST/PUT/GET/DELETE/PATCH with available header configurations
Example:
const customFetch = (path, options) => {
const accessToken = localStorage.getItem("accessToken");
Cookies.set("XSRF-TOKEN", Cookies.get("XSRF-TOKEN"));
var bodyParameters = {
page: 1,
pageSize: 50
};
return fetch(`${baseURL}/${path}`, {
credentials: "include",
headers: {
Authorization: `JWT ${accessToken}`,
"X-XSRF-TOKEN": Cookies.get("XSRF-TOKEN"),
"cache-control": "no-cache",
pragma: "no-cache"
},
...options
});
};
const post = (path, bodyParameters) =>
customFetch(path, {
method: "POST",
body: JSON.stringify(bodyParameters)
});
const get = (path, queries) =>
customFetch(queries ? `${path}/${qs.stringify(queries)}` : path, {
method: "GET"
});
const put = (path, bodyParameters) =>
customFetch(path, {
method: "PUT"
body: JSON.stringify(bodyParameters)
});
const delete = (path, id) =>
customFetch(`${path}/${id}`, {
method: "DELETE"
});
After that you can custom your readList with dynamic endpoint like this
const readList = (resource) => apiService.get(resource)
readList('/posts');
readList('/comments');
readList('/albums');

Update the likes array in a post in the frontend

I have a PUT route in the backend for liking posts, it adds the users id to the likes array in the post. This works fine when tested on Postman (by providing the post in the body) and the likes array is updated. However, when the icon is clicked in the frontend, I want the likes array to update but I'm not sure how to update the state for the post. result is showing the response in the frontend with a 200 status code but that's as far as I'm getting.
How can I update the likes array in the frontend?
Post.js
const Post = (props) => {
const [post, setPost] = useState({});
const [error, setError] = useState(false);
const id = props.match.params.id;
const loadSinglePost = (id) => {
read(id).then((data) => {
if (error) {
console.log(data.error);
setError(data.error);
} else {
setPost(data);
console.log(data);
}
});
};
useEffect(() => {
loadSinglePost(id);
}, [props]);
const like = (id) => {
const {user: { _id }, token} = isAuthenticated();
fetch(`${API}/like/${_id}`, {
method: "PUT",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
body: JSON.stringify({
id: id,
}),
})
.then(result => { console.log(result)})
.catch((err) => {
console.log(err);
});
};
return (
<div>
<Navbar />
<div>
<h3>{post && post.title}</h3>
<p>
{post && post.author ? post.author.name : ""}
</p>
<p>{post && post.body}</p>
<h5>{post && post.likes && post.likes.length} likes</h5>
<img
onClick={() => {
like(id);
}}
alt="..."
/>
</div>
</div>
);
};
export default Post;
controllers/post.js
exports.like = (req, res) => {
Post.findByIdAndUpdate(req.body._id, {
$push: {likes: req.profile._id}
}, {new: true}).exec((err, result) => {
if (err) {
return res.status(422).json({error: err})
} else {
return res.json(result)
}
})
}
exports.readById = (req, res) => {
const id = req.params.id
Post.findById(id)
.then(post => res.json(post))
.catch(err => res.status(400).json('Error: ' + err));
}
You can update likes in post in then callback like this:
const like = (id) => {
const {user: { _id }, token} = isAuthenticated();
fetch(`${API}/like/${_id}`, {
method: "PUT",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
body: JSON.stringify({
id: id,
}),
})
.then(result => {
// here update post likes
let updatedPost = {...post}; //to make copy of post
updatedPost.likes = [...updatedPost.likes, id]; //add new id to updatedPost' likes array
setPost(updatedPost); //update post
console.log(result)
})
.catch((err) => {
console.log(err);
});
};
Also from front-end you're sending id key in body:
body: JSON.stringify({
id: id, // here
})
And at back end you're expecting _id
Post.findByIdAndUpdate(req.body._id, { // here
$push: {likes: req.profile._id}
}

The localhost api can not be fetched from the expo

The localhost api can not be fetched from the expo.
const search = async(type) => {
let response = await fetch(http://localhost:3000/api/${type}, {
accept: 'application/json'
});
let result = await response.json();
return result;
}
const create = async(type, data) => {
let response = await fetch(http://localhost:3000/api/${type}, {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
method: 'post',
body: JSON.stringify(data)
});
let result = await response.json();
return result;
}
const Client = {search, create};
export default Client;
Client.js
const search = async(type) => {
let response = await fetch(`http://localhost:3000/api/${type}`, {
accept: 'application/json'
});
let result = await response.json();
return result; }
const create = async(type, data) => {
let response = await fetch(`http://localhost:3000/api/${type}`, {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
method: 'post',
body: JSON.stringify(data)
});
let result = await response.json();
return result;
}
const Client = {search, create};
export default Client;
App.js
import React, { Component } from 'react';
import {
Text,
View,
TextInput,
Button,
StyleSheet
} from "react-native";
import Client from './Client.js';
class App extends Component {
constructor() {
super()
this.state = {
users: [] // user에 대한 정보를 담기 위한 state
}
this.handleUserInputChange = this.handleUserInputChange.bind(this)
}
componentWillMount = () => {
this.getUser()
}
handleUserInputChange = event => {
const {target: {name, value}} = event
this.setState({
[name]: value
});
}
getUser = async() => {
Client.search('User') // Client.js에서
.then(data => {
this.setState({
users: data
})
})
}
submitUser = () => {
const data = {
"$class": "org.acme.model.User",
"phonenumber": this.state.phonenumber,
"email": this.state.email,
"firstName": this.state.firstName,
"lastName": this.state.lastName,
}
Client.create('User', data)
.then(() => {
this.getUser()
})
}
render() {
return(
<View className="App">
<Text>Add User</Text>
<Text>phonenumber:</Text>
<TextInput
onChange={this.handleUserInputChange}
type="text"
name="phonenumber" />
<Text>email:</Text>
<TextInput
onChange={this.handleUserInputChange}
type="text"
name="email" />
<Text>firstName:</Text>
<TextInput
onChange={this.handleUserInputChange}
type="text"
name="firstName" />
<Text>lastName:</Text>
<TextInput
onChange={this.handleUserInputChange}
type="text"
name="lastName" />
<Button title="New User" onPress={()=> this.submitUser}/>
<View style={styles.container}>
<Text style={styles.userlist}>
User List
</Text>
{this.state.users.map((r, i) => (
<View style={styles.userstate}
key={i}>
<Text>phonenumber: {r.phonenumber}</Text>
<Text>email: {r.email}</Text>
<Text>firstName: {r.firstName}</Text>
<Text>lastName: {r.lastName}</Text>
</View>
))}
</View>
</View>
)
}
}
const styles=StyleSheet.create({
container: {
flex:1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
userlist:{
fontSize: 20,
textAlign: 'center',
margin: 10,
},
userstate:{
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
export default App;
The error is logical, because "localhost" is the name that designates a logical interface of the local computer.
So when you ask your application to make a request to "http://localhost:3000/api", it sends the request to the phone so it will never reach your computer.
But if your local network allows it, you can put directly the IP address of your computer.
You have to expose your APIs. One way you can do this is by using ngrok.
Try the below:
https://ngrok.com/ and follow the steps for installation after signing up
After unzipping open terminal and ./ngrok http <port_number>
If it is working, you should see a Forwarding: <forwarding_address>
Copy this forwarding address as your base url in the app
Just to test, try hitting this forwarding address in your browser, ex. http://1a6b3022.ngrok.io/api/testing you should get a response
Hopefully this is helpful!

Resources