Paypal integration improvements

This commit is contained in:
Joao Ramos
2024-03-07 11:18:48 +00:00
parent 0cff310354
commit 330c177ff9
4 changed files with 125 additions and 85 deletions

View File

@@ -70,11 +70,14 @@ export default function PayPalPayment({
throw new Error("trackingId is not set"); throw new Error("trackingId is not set");
} }
const request = await axios.post<{ ok: boolean; reason?: string }>( axios
"/api/paypal/approve", .post<{ ok: boolean; reason?: string }>("/api/paypal/approve", {
{ id: data.orderID, duration, duration_unit, trackingId } id: data.orderID,
); duration,
duration_unit,
trackingId,
})
.then((request) => {
if (request.status !== 200) { if (request.status !== 200) {
toast.error("Something went wrong, please try again later"); toast.error("Something went wrong, please try again later");
return; return;
@@ -82,6 +85,11 @@ export default function PayPalPayment({
toast.success("Your account has been credited more time!"); toast.success("Your account has been credited more time!");
return onSuccess(duration, duration_unit); return onSuccess(duration, duration_unit);
})
.catch((err) => {
console.error(err);
toast.error("Something went wrong, please try again later");
});
}; };
const onError = async (data: Record<string, unknown>) => { const onError = async (data: Record<string, unknown>) => {

View File

@@ -15,6 +15,8 @@ import InviteCard from "@/components/Medium/InviteCard";
import {useRouter} from "next/router"; import {useRouter} from "next/router";
import {PayPalScriptProvider} from "@paypal/react-paypal-js"; import {PayPalScriptProvider} from "@paypal/react-paypal-js";
import { usePaypalTracking } from "@/hooks/usePaypalTracking"; import { usePaypalTracking } from "@/hooks/usePaypalTracking";
import {ToastContainer} from "react-toastify";
interface Props { interface Props {
user: User; user: User;
@@ -47,6 +49,7 @@ export default function PaymentDue({user, hasExpired = false, clientID, reload}:
return ( return (
<> <>
<ToastContainer />
{isLoading && ( {isLoading && (
<div className="absolute left-0 top-0 z-[999] h-screen w-screen overflow-hidden bg-black/60"> <div className="absolute left-0 top-0 z-[999] h-screen w-screen overflow-hidden bg-black/60">
<div className="absolute left-1/2 top-1/2 flex h-fit w-fit -translate-x-1/2 -translate-y-1/2 animate-pulse flex-col items-center gap-8 text-white"> <div className="absolute left-1/2 top-1/2 flex h-fit w-fit -translate-x-1/2 -translate-y-1/2 animate-pulse flex-col items-center gap-8 text-white">

View File

@@ -49,12 +49,13 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
"PayPal-Client-Metadata-Id": trackingId, "PayPal-Client-Metadata-Id": trackingId,
}, },
}; };
const request = await axios.post(url, {}, headers); axios
.post(url, {}, headers)
.then(async (request) => {
if (request.data.status === "COMPLETED") { if (request.data.status === "COMPLETED") {
const user = req.session.user; const user = req.session.user;
const subscriptionExpirationDate = const subscriptionExpirationDate =
req.session.user.subscriptionExpirationDate; user!.subscriptionExpirationDate;
const today = moment(new Date()); const today = moment(new Date());
const dateToBeAddedTo = !subscriptionExpirationDate const dateToBeAddedTo = !subscriptionExpirationDate
? today ? today
@@ -62,9 +63,12 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
? moment(subscriptionExpirationDate) ? moment(subscriptionExpirationDate)
: today; : today;
const updatedExpirationDate = dateToBeAddedTo.add(duration, duration_unit); const updatedExpirationDate = dateToBeAddedTo.add(
duration,
duration_unit
);
await setDoc( await setDoc(
doc(db, "users", req.session.user.id), doc(db, "users", req.session.user!.id),
{ {
subscriptionExpirationDate: updatedExpirationDate.toISOString(), subscriptionExpirationDate: updatedExpirationDate.toISOString(),
status: "active", status: "active",
@@ -75,10 +79,11 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
try { try {
await setDoc(doc(db, "paypalpayments", v4()), { await setDoc(doc(db, "paypalpayments", v4()), {
orderId: id, orderId: id,
userId: req.session.user.id, userId: req.session.user!.id,
status: request.data.status, status: request.data.status,
createdAt: new Date().toISOString(), createdAt: new Date().toISOString(),
value: request.data.purchase_units[0].payments.captures[0].amount.value, value:
request.data.purchase_units[0].payments.captures[0].amount.value,
currency: currency:
request.data.purchase_units[0].payments.captures[0].amount request.data.purchase_units[0].payments.captures[0].amount
.currency_code, .currency_code,
@@ -90,14 +95,14 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
console.error("Failed to insert paypal payment!", err); console.error("Failed to insert paypal payment!", err);
} }
if (user.type === "corporate") { if (user!.type === "corporate") {
const snapshot = await getDocs(collection(db, "groups")); const snapshot = await getDocs(collection(db, "groups"));
const groups: Group[] = ( const groups: Group[] = (
snapshot.docs.map((doc) => ({ snapshot.docs.map((doc) => ({
id: doc.id, id: doc.id,
...doc.data(), ...doc.data(),
})) as Group[] })) as Group[]
).filter((x) => x.admin === user.id); ).filter((x) => x.admin === user!.id);
await Promise.all( await Promise.all(
groups groups
@@ -124,4 +129,9 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
ok: false, ok: false,
reason: "Order ID not found or purchase was not approved!", reason: "Order ID not found or purchase was not approved!",
}); });
})
.catch((err) => {
console.error(err.response.status, err.response.data);
res.status(err.response.status).json(err.response.data);
});
} }

View File

@@ -32,16 +32,29 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
return res.status(401).json({ ok: false, reason: "Missing tracking id!" }); return res.status(401).json({ ok: false, reason: "Missing tracking id!" });
const url = `${process.env.PAYPAL_ACCESS_TOKEN_URL}/v2/checkout/orders`; const url = `${process.env.PAYPAL_ACCESS_TOKEN_URL}/v2/checkout/orders`;
const amount = {
currency_code: currencyCode,
value: price.toString(),
};
const data = { const data = {
purchase_units: [ purchase_units: [
{ {
invoice_id: `INV-${v4()}`, invoice_id: `INV-${v4()}`,
amount: { amount: {
currency_code: currencyCode, ...amount,
value: price.toString(), breakdown: {
item_total: amount,
}, },
reference_id: v4(), },
items: [
{
name: "Encoach Subscription",
quantity: "1",
category: "DIGITAL_GOODS",
unit_amount: amount,
},
],
}, },
], ],
payment_source: { payment_source: {
@@ -74,7 +87,13 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
}) })
); );
const request = await axios.post<OrderResponseBody>(url, data, headers); axios
.post<OrderResponseBody>(url, data, headers)
.then((request) => {
res.status(request.status).json(request.data); res.status(request.status).json(request.data);
})
.catch((err) => {
console.error(err.response.status, err.response.data);
res.status(err.response.status).json(err.response.data);
});
} }