繁体   English   中英

条纹优惠券验证

[英]Stripe coupon validation

我希望用户能够在有优惠券的情况下添加优惠券,并且通过按下按钮,代码应该检查优惠券是否存在于我的 Stripe 仪表板中。 到目前为止,我已经这样做了(见下面的代码),我想我并没有遗漏太多,但我想不出一种方法来将 validCoupon 从客户端发送到服务器端,并且他们能够在那里应用折扣。

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});
    }

.....

页面/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');
  }
}

//////////////////////////////////////// 更新 ///////// ///////////////////////////////

好的,现在我将 validCoupon object 添加到 cartsItems 并传入正文。 在服务器端,我遇到了问题,因为从来没有应用过折扣,我不知道为什么,但我觉得我真的很接近解决这个问题,只是缺少一些简单的东西。

购物车.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});
}

页面/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');
  }
}

您需要通过将优惠券添加到 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');
  }
}

我将 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});
    }

然后在服务器端,我像这样将每个 object 从身体中拉出来。

const {cartItems, validCoupon} = req.body;

然后分别使用每个 object。

validCoupon.id  or cartItems.map

暂无
暂无

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

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