next.jspaypalpayment-gatewaypaypal-buttons

How to capture order Paypal in Nextjs


I am trying to add a PayPal payment functionality to my website. Currently, I am using PayPalButtons from react-paypal-js and PayPal API v2

I am trying to add a PayPal payment functionality to my website. Currently, I am using PayPalButtons from react-paypal-js and PayPal API v2. The issue I'm facing is that after creating the order, I am unable to retrieve the orderId, token that was just created for use with the capture API.

import React, { useEffect, useState } from "react";
import { PayPalButtons } from "@paypal/react-paypal-js";
import useBoundStore from "@/store/store";

type onApproveData = {
    token: string,
    orderId: string
}
export const PayPalButton = () => {
    const layout: "vertical" | "horizontal" = "vertical";
    const style = { layout };
    const base = process.env.NEXT_PUBLIC_PAYPAL_API_URL || 'https://api-m.sandbox.paypal.com'
    const ordersPaypalApi = {
        test: "https://api-m.sandbox.paypal.com/v2/checkout/orders",
        prod: "https://api-m.paypal.com/v2/checkout/orders"
    };
    const totalPrice = useBoundStore((state) => state.calculateRoomPrice?.reservations_amount_price)
    const [token, setToken] = useState("")
    const [orderId, setOrderId] = useState("")
    const [dataApprove, setDataApprove] = useState<onApproveData>({token:"", orderId:""})
    useEffect(()=>{
        setDataApprove({token:token, orderId:orderId})
    },[token, orderId])
    async function generateAccessToken() {
        const auth = Buffer.from(process.env.NEXT_PUBLIC_PAYPAL_CLIENT_ID + ':' + process.env.NEXT_PUBLIC_PAYPAL_CLIENT_SECRET).toString(
            'base64'
        )
        const response = await fetch(`${base}/v1/oauth2/token`, {
            method: 'POST',
            body: 'grant_type=client_credentials',
            headers: {
                Authorization: `Basic ${auth}`,
            },
        })
        return response.json()
    }
    const createOrder =async () => {
        const res = await generateAccessToken()
        const accessToken = res.access_token
        localStorage.setItem(accessToken,"PAYPAL_TOKEN")
        setToken(accessToken)
        const url = process.env.NEXT_ENV !== "production" ? ordersPaypalApi.test : ordersPaypalApi.prod
        const response = await fetch(url, {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
                Authorization: `Bearer ${accessToken}`,

            },
            body: JSON.stringify({
                intent: 'CAPTURE',
                purchase_units: [
                    {
                        amount: {
                            currency_code: 'USD',
                            value: Math.round(totalPrice),
                        },
                    },
                ],
            }),
        }
        )
        const responseData = await response.json();
        const id = responseData.id;
        setOrderId(id);
        return id;
    }
    const onApprove = async ()=> {
        const url = process.env.NEXT_ENV !== "production" ? ordersPaypalApi.test : ordersPaypalApi.prod + `/${orderId}/capture`
        const response = await fetch(url, {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
                Authorization: `Bearer ${token}`,
            },
        }
        );
        const capture = await response.json();
        console.log("capture", capture);
    }
    return (
        <PayPalButtons
            style={style}
            createOrder={createOrder}
            onApprove={onApprove}
        />
    );
};

created order but fail capture


Solution

  • After payer approval, the onApprove function is called and the orderId will be passed to it within the first argument to that function.

    Utilize that first argument to access the orderId value, and use it to make the fetch call to the backend.