Search code examples
next.jsstripe-payments

can not send tax amount in stripe from next js app


In my project, I am using WordPress woo-commerce as backend and next js as frontend. I am trying to implement stripe payment. I can send line items in stripe sessionData and they show perfectly on the stripe page, how ever when I am trying to send the tax amounts with line items I am getting errors.

import { createCheckoutSession } from "next-stripe/client"; // @see https://github.com/ynnoj/next-stripe
import { loadStripe } from "@stripe/stripe-js";

.....
.....

const createCheckoutSessionAndRedirect = async (orderData) => {
  const sessionData = {
    success_url:
      window.location.origin +
      `/thank-you?session_id={CHECKOUT_SESSION_ID}&order_id=${orderData.orderId}`,
    cancel_url: window.location.href,
    customer_email: orderData.customer_email,
    line_items: getStripeLineItems(orderData.products),
    metadata: getMetaData(
      orderData.billing,
      orderData.shipping,
      orderData.orderId
    ),
    payment_method_types: ["card"],
    mode: "payment",
    total_details:{
      amount_discount: 0,
      amount_shipping: Math.round(10 * 100),
      amount_tax: Math.round(10 * 100),
    },
  };
  console.log("Session from another1:", sessionData);

  const session = await createCheckoutSession(sessionData);

  console.log("Session from another2:", sessionData);
  console.log("from another2:", orderData);

  try {
    console.log("session data", session);
    const stripe = await loadStripe(
      process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY
    );
    if (stripe) {
      stripe.redirectToCheckout({ sessionId: session.id });
    }
  } catch (error) {
    console.log(error);
  }
};

Solution

  • After many attempts, I could solve the problem.

    This is the controller.

    const stripe = require("stripe")(process.env.STRIPE_PRIVATE_KEY);
    const stripePaymentService = require('../service/stripePaymentService');
    
    
    module.exports.checkoutSessionCreate = async (req, res) => {
    
        const responseFromService = await stripePaymentService.checkoutSessionCreate(req.body);
    
        console.log("this is session data", responseFromService);
    
        try{
            const session = await stripe.checkout.sessions.create(responseFromService);
            res.json({ url: session.url });
            console.log("success session:", session.url);
        }
        catch(e){
            res.status(500).json({ error: e.message })
            console.log("success session:", e.message);
        }
        
    }

    This is the service...

    const stripe = require("stripe")(process.env.STRIPE_PRIVATE_KEY);
    const lodash = require('lodash');
    
    module.exports.checkoutSessionCreate = async (serviceData) => {
        // console.log(serviceData.products);
    
        const sessionData = {
            success_url:`${process.env.CLIENT_URL}/thank-you?session_id={CHECKOUT_SESSION_ID}&order_id=${serviceData.orderId}`,
            cancel_url: `${process.env.CLIENT_URL}`,
            customer_email: serviceData.customer_email,
            line_items: await getStripeLineItems(serviceData.products),
            metadata: getMetaData(
              serviceData.billing,
              serviceData.shipping,
              serviceData.orderId
            ),
            payment_method_types: ["card"],
            mode: "payment",
        };
    
        return sessionData;
    }
    
    
    const getMetaData = (billing, shipping, orderId) => {
        return {
          billing: JSON.stringify(billing),
          shipping: JSON.stringify(shipping),
          orderId,
        };
    };
    
    let getStripeLineItems =async (products) => {
        if (lodash.isEmpty(products) && !isArray(products)) {
            return [];
        }
    
        const productData = await Promise.all(
            products.map(async (product) => {
                const taxArr = await getTaxID(product.tax_data);
                return {
                quantity: product?.quantity ?? 0,
                name: product?.name ?? "",
                images: [product?.images ?? ""],
                amount: Math.round(product?.amount * 100),
                currency: product?.currency ?? "",
                tax_rates: taxArr,
                };
            })
        );
        return productData;
    };
    
    let getTaxID = async (taxData) => {
        let idArr = await Promise.all(
            taxData.map(async (item)=>{
                const taxRate = await stripe.taxRates.create({
                    display_name: item.display_name,
                    inclusive: item.inclusive,
                    percentage: item.percentage,
                });
            
                return taxRate?.id;
            })
        );
        return idArr;
    }

    I hope this will help somebody....