简体   繁体   English

条纹优惠券验证

[英]Stripe coupon validation

I want the user to be able to add a coupon if they have one and by pressing a button the code should check if the coupon exists in my Stripe dashboard.我希望用户能够在有优惠券的情况下添加优惠券,并且通过按下按钮,代码应该检查优惠券是否存在于我的 Stripe 仪表板中。 so far I have done this(see code below), I think I'm not missing much but I can't figure out a way to send the validCoupon across from client side to server side and them being able to apply the discount there.到目前为止,我已经这样做了(见下面的代码),我想我并没有遗漏太多,但我想不出一种方法来将 validCoupon 从客户端发送到服务器端,并且他们能够在那里应用折扣。

Cart.js (client side) Cart.js(客户端)

import React, {useRef, useState} from 'react';
import Link from 'next/link';
import {AiOutlineMinus, AiOutlinePlus, AiOutlineLeft, AiOutlineShopping} from 'react-icons/ai';
import {TiDeleteOutline} from 'react-icons/ti';
import toast from 'react-hot-toast';

import {useStateContext} from '../context/StateContext';
import {urlFor} from '../lib/client';
import getStripe from '../lib/getStripe';

const Cart = () => {
    const cartRef = useRef();
    const {
        totalPrice,
        totalQuantities,
        cartItems,
        setShowCart,
        toggleCartItemQuanitity,
        onRemove
    } = useStateContext();
    const [coupontext, setCouponText] = useState('');
    const [isCouponAdded, setisCouponAdded] = useState(false);
    const [validCoupon, setValidCoupon] = useState("");

    const handleChange = (event) => {
        setCouponText(event.target.value);
    };

    const checkCoupon = async () => {
      if(!isCouponAdded){
        const response = await fetch('https://api.stripe.com/v1/coupons', {
            headers: {
                'Authorization': `Bearer ${process.env.NEXT_PUBLIC_STRIPE_SECRET_KEY}`
            }
        });

        if (!response.ok) {
            toast.error("Error fetching coupons");
            return;
        }

        const {data} = await response.json();
        const validcoupon = data.find((c) => c.id === coupontext);
        if (validcoupon) {
            toast.success("Coupon is valid!");
            setValidCoupon(validcoupon);
            setisCouponAdded(true);
        } else {
            toast.error("Coupon is invalid!");
        }
      }else{
        toast.success("Coupon already added!");
      }
    
    }

    const handleCheckout = async () => {
        const stripeClient = await getStripe();

        const response = await fetch('/api/stripe', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(cartItems)
        });

        if (response.statusCode === 500)  
            return;
        
        const data = await response.json();

        toast.loading('Redirecting...');

        stripeClient.redirectToCheckout({sessionId: data.id});
    }

.....

pages/api/stripe.js页面/api/stripe.js

import Stripe from 'stripe';

const stripe = new Stripe(process.env.NEXT_PUBLIC_STRIPE_SECRET_KEY);

export default async function handler(req, res) {
  if (req.method === 'POST') {
    try {
      const params = {
        submit_type: 'pay',
        mode: 'payment',
        payment_method_types: ['card'],
        billing_address_collection: 'auto',
        shipping_address_collection: {
        allowed_countries: ["PT"],
      },
        shipping_options: [
          { shipping_rate: 'shr_1MMq2YJFNgzNJo7sbwDNnqhz' },
          { shipping_rate: "shr_1MMq3iJFNgzNJo7s2nVvfATq"}
        ],
        line_items: req.body.map((item) => {
          const img = item.image[0].asset._ref;
          const newImage = img.replace('image-', 'https://cdn.sanity.io/images/REDACTED/production/').replace('-png', '.png');
            
          return {
            price_data: { 
              currency: 'eur',
              product_data: { 
                name: item.name,
                images: [newImage],
              },
              unit_amount: item.price * 100,
            },
            adjustable_quantity: {
              enabled:true,
              minimum: 1,
            },
            quantity: item.quantity
          }
        }),
        success_url: `${req.headers.origin}/success`,
        cancel_url: `${req.headers.origin}/`,
      }

      // Create Checkout Sessions from body params.
      const session = await stripe.checkout.sessions.create(params);

      res.status(200).json(session);
    } catch (err) {
      res.status(err.statusCode || 500).json(err.message);
    }
  } else {
    res.setHeader('Allow', 'POST');
    res.status(405).end('Method Not Allowed');
  }
}

//////////////////////////////////////// UPDATE ///////////////////////////////////////// //////////////////////////////////////// 更新 ///////// ///////////////////////////////

Ok so now I'm adding validCoupon object to the cartsItems and passing in the body.好的,现在我将 validCoupon object 添加到 cartsItems 并传入正文。 on the server side I'm having issues because no discount is being applied ever, I don't know why but i fell that I'm really close to solving this, just missing something simple.在服务器端,我遇到了问题,因为从来没有应用过折扣,我不知道为什么,但我觉得我真的很接近解决这个问题,只是缺少一些简单的东西。

Cart.js购物车.js

import React, {useRef, useState} from 'react';
import Link from 'next/link';
import {AiOutlineMinus, AiOutlinePlus, AiOutlineLeft, AiOutlineShopping} from 'react-icons/ai';
import {TiDeleteOutline} from 'react-icons/ti';
import toast from 'react-hot-toast';

import {useStateContext} from '../context/StateContext';
import {urlFor} from '../lib/client';
import getStripe from '../lib/getStripe';

const Cart = () => {
    const cartRef = useRef();
    const {
        totalPrice,
        totalQuantities,
        cartItems,
        setShowCart,
        toggleCartItemQuanitity,
        onRemove
    } = useStateContext();
    const [coupontext, setCouponText] = useState('');
    const [isCouponAdded, setisCouponAdded] = useState(false);
    const [validCoupon, setValidCoupon] = useState(null);

    const handleChange = (event) => {
        setCouponText(event.target.value);
    };

    const checkCoupon = async () => {
      if(!isCouponAdded){
        const response = await fetch('https://api.stripe.com/v1/coupons', {
            headers: {
                'Authorization': `Bearer ${process.env.NEXT_PUBLIC_STRIPE_SECRET_KEY}`
            }
        });

        if (!response.ok) {
            toast.error("Error fetching coupons");
            return;
        }

        const {data} = await response.json();
        console.log(data);
        const validcoupon = data.find((c) => c.id === coupontext);
        if (validcoupon) {
            toast.success("Coupon is valid!");
            setValidCoupon(validcoupon);
            setisCouponAdded(true);
        } else {
            toast.error("Coupon is invalid!");
        }
      }else{
        toast.success("Coupon already added!");
      }
    
    }

    const handleCheckout = async () => {
        const stripeClient = await getStripe();
        cartItems['validCoupon'] = validCoupon;
        console.log(cartItems);
        const response = await fetch('/api/stripe', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(cartItems)
        });

        if (response.statusCode === 500)  
            return;
        
        const data = await response.json();

        toast.loading('Redirecting...');

        stripeClient.redirectToCheckout({sessionId: data.id});
}

pages/api/stripe.js页面/api/stripe.js

import Stripe from 'stripe';

const stripe = new Stripe(process.env.NEXT_PUBLIC_STRIPE_SECRET_KEY);

export default async function handler(req, res) {
  if (req.method === 'POST') {
    try {
      
      const discounts = [];
    
      if(req.body.validCoupon && req.body.validCoupon.id) {
        discounts.push({coupon: req.body.validCoupon.id});
      }

      
      let shipping_options = [];

      
      const line_items = req.body;
      let total_amount = 0;
      for (const item of line_items) {
        total_amount += item.price * item.quantity;
      }

      
      if (total_amount >= 40) {
        shipping_options = [
          { shipping_rate: 'shr_1MMq3iJFNgzNJo7s2nVvfATq' },
        ];
      } else {
        shipping_options = [
          { shipping_rate: "shr_1MMq2YJFNgzNJo7sbwDNnqhz"}
        ];
      }
      

      const params = {
        submit_type: 'pay',
        mode: 'payment',
        discounts: discounts,
        payment_method_types: ['card'],
        billing_address_collection: 'auto',
        shipping_address_collection: {
        allowed_countries: ["PT"],
      },
      shipping_options: shipping_options,
        line_items: req.body.map((item) => {
          const img = item.image[0].asset._ref;
          const newImage = img.replace('image-', 'https://cdn.sanity.io/images/REDACTED/production/').replace('-png', '.png');
            
          return {
            price_data: { 
              currency: 'eur',
              product_data: { 
                name: item.name,
                images: [newImage],
              },
              unit_amount: item.price * 100,
            },
            quantity: item.quantity
          }
        }),
        success_url: `${req.headers.origin}/success`,
        cancel_url: `${req.headers.origin}/`,
      }

      // Create Checkout Sessions from body params.
      const session = await stripe.checkout.sessions.create(params);

      res.status(200).json(session);
    } catch (err) {
      res.status(err.statusCode || 500).json(err.message);
    }
  } else {
    res.setHeader('Allow', 'POST');
    res.status(405).end('Method Not Allowed');
  }
}

You need to pass coupon to server by adding it to cartItems and you need to pass stripe coupon name in discount array in session params您需要通过将优惠券添加到 cartItems 将优惠券传递给服务器,并且需要在 session 参数中传递discount数组中的条带优惠券名称

import React, {useRef, useState} from 'react';
import Link from 'next/link';
import {AiOutlineMinus, AiOutlinePlus, AiOutlineLeft, AiOutlineShopping} from 'react-icons/ai';
import {TiDeleteOutline} from 'react-icons/ti';
import toast from 'react-hot-toast';

import {useStateContext} from '../context/StateContext';
import {urlFor} from '../lib/client';
import getStripe from '../lib/getStripe';

const Cart = () => {
    const cartRef = useRef();
    const {
        totalPrice,
        totalQuantities,
        cartItems,
        setShowCart,
        toggleCartItemQuanitity,
        onRemove
    } = useStateContext();
    const [coupontext, setCouponText] = useState('');
    const [isCouponAdded, setisCouponAdded] = useState(false);
    const [validCoupon, setValidCoupon] = useState("");

    const handleChange = (event) => {
        setCouponText(event.target.value);
    };

    const checkCoupon = async () => {
      if(!isCouponAdded){
        const response = await fetch('https://api.stripe.com/v1/coupons', {
            headers: {
                'Authorization': `Bearer ${process.env.NEXT_PUBLIC_STRIPE_SECRET_KEY}`
            }
        });

        if (!response.ok) {
            toast.error("Error fetching coupons");
            return;
        }

        const {data} = await response.json();
        const validcoupon = data.find((c) => c.id === coupontext);
        if (validcoupon) {
            toast.success("Coupon is valid!");
            setValidCoupon(validcoupon);
            setisCouponAdded(true);
        } else {
            toast.error("Coupon is invalid!");
        }
      }else{
        toast.success("Coupon already added!");
      }
    
    }

    const handleCheckout = async () => {
        const stripeClient = await getStripe();
        cartItems['validCoupon'] = validCoupon;
        const response = await fetch('/api/stripe', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(cartItems)
        });

        if (response.statusCode === 500)  
            return;
        
        const data = await response.json();

        toast.loading('Redirecting...');

        stripeClient.redirectToCheckout({sessionId: data.id});
    }

.....

const stripe = new Stripe(process.env.NEXT_PUBLIC_STRIPE_SECRET_KEY);

export default async function handler(req, res) {
  if (req.method === 'POST') {
    try {
      const params = {
        submit_type: 'pay',
        mode: 'payment',
        discounts: [
           {
             coupon: "Your_coupon_name_asper_stripe"
           }
        ]
        payment_method_types: ['card'],
        billing_address_collection: 'auto',
        shipping_address_collection: {
        allowed_countries: ["PT"],
      },
        shipping_options: [
          { shipping_rate: 'shr_1MMq2YJFNgzNJo7sbwDNnqhz' },
          { shipping_rate: "shr_1MMq3iJFNgzNJo7s2nVvfATq"}
        ],
        line_items: req.body.map((item) => {
          const img = item.image[0].asset._ref;
          const newImage = img.replace('image-', 'https://cdn.sanity.io/images/REDACTED/production/').replace('-png', '.png');
            
          return {
            price_data: { 
              currency: 'eur',
              product_data: { 
                name: item.name,
                images: [newImage],
              },
              unit_amount: item.price * 100,
            },
            adjustable_quantity: {
              enabled:true,
              minimum: 1,
            },
            quantity: item.quantity
          }
        }),
        success_url: `${req.headers.origin}/success`,
        cancel_url: `${req.headers.origin}/`,
      }

      // Create Checkout Sessions from body params.
      const session = await stripe.checkout.sessions.create(params);

      res.status(200).json(session);
    } catch (err) {
      res.status(err.statusCode || 500).json(err.message);
    }
  } else {
    res.setHeader('Allow', 'POST');
    res.status(405).end('Method Not Allowed');
  }
}

I included the validCoupon inside the body of the POST request.我将 validCoupon 包含在 POST 请求的正文中。

const handleCheckout = async () => {
        const stripeClient = await getStripe();
        const response = await fetch('/api/stripe', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
              cartItems,
              validCoupon
          })
        });

        if (response.statusCode === 500)  
            return;
        
        const data = await response.json();

        toast.loading('Redirecting...');

        stripeClient.redirectToCheckout({sessionId: data.id});
    }

then on the server side I pulled each object out of the body like this.然后在服务器端,我像这样将每个 object 从身体中拉出来。

const {cartItems, validCoupon} = req.body;

and then used each object separately.然后分别使用每个 object。

validCoupon.id  or cartItems.map

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM