如何在具有不同支付选项的 React 中实施 PayPal?

How do I implement PayPal in React with different payment options?

我正在尝试掌握如何在 React 中正确设置 PayPal 方法。

我有三张卡,每张卡的付款金额都不同,我不知道如何将道具从我的 Class 传递到 PayPal 功能。

我只需要更改 PayPal 函数中的 purchase_items[] 数组的成本和说明,对吗?

仅供参考:我主要按照 PayPal 的教程进行操作,可以进行付款,只是没有我想要的不同费用和描述。

PayPal.js

import React, {useRef, useEffect} from 'react';
export default function PayPal(){
const [paid, setPaid] = React.useState(false);
const paypal = useRef()

useEffect(()=> {
    window.paypal.Buttons({
        createOrder: (data, actions, err) => {
            return actions.order.create({
                intent: "CAPTURE",
                purchase_units: [
                    {
                        description: "Dummy",
                        amount: {
                            currency_code: "AUD",
                            value: 15.49
                        }
                    }
                ]
            })
        },
        onApprove: async(data, actions) => {
            const order = await actions.order.capture()
            setPaid(true);
            console.log(order);
        },
        onError: (err) => {
            console.error(err);
        }
    }).render(paypal.current)
}, [])

return(
    <div className="Processing">
        {paid ?(
            // If the payment is made
            <div>Payment successful!</div>
        ):(
            // If any error occurs
            <div>Error Occurred in processing payment! Please try again.</div>
        )}
    </div>
);
}

Purchases.js

import React, {Component} from 'react';
import PayPal from '../../Components/PayPal.js';
import {Card, CardActions} from '@material-ui/core';

class Purchases extends Component(){

constructor(props){
    super(props);
    this.state ={
        cost: 5.00,
        checkout: false,
        desc: "Test"
    };
}

setCheckout = (bool) =>{
    this.setState({checkout: bool});
};

handlePayment = (price, info) =>{
    this.setState(state => ({cost: price}, {desc: info}));
};

render(){
    return (
        <div className="Purchase">
            {this.state.checkout ?(
                <PayPal cost={this.state.cost} desc={this.state.desc}/>
            ) : (      
                <div>
                <Card>
                    Payment 1 =  AUD
                    <CardActions
                    onClick={() =>{
                        setCheckout(true);
                        this.handlePayment(1.00, "Purchase Plan 1");
                    }}
                />
                </Card>
                <Card>
                    Payment 2 =  AUD
                    <CardActions
                    onClick={() =>{
                        setCheckout(true);
                        this.handlePayment(2.00, "Purchase Plan 2");
                    }}
                    />
                </Card>
                <Card>
                    Payment 3 =  AUD
                    <CardActions
                        onClick={() =>{
                            setCheckout(true);
                            this.handlePayment(3.00, "Purchase Plan 3");
                        }}
                    />
                </Card>
            </div>
            )}
        </div>
    );
}
}
export default Purchases;

我不熟悉 PayPal API,但我可以在 React 方面帮助您。

<PayPal cost={this.state.cost} desc={this.state.desc}/>

您正在使用道具 costdesc 调用 PayPal 组件,因此我们需要让 PayPal 组件接受这些道具并使用它们。

ref const paypal = useRef() 只是创建一个可以附加到组件的 ref。它本身不会做任何事情,因为 paypal.current 永远只是 undefined。但是 seems like render() 的参数应该是一个选择器而不是一个元素。

现在您只有“已付款”和“错误”,但我认为您需要“待处理”的第三种呈现情况。

export default function PayPal({ cost, desc }) {
  const [completed, setCompleted] = React.useState(false);
  const [paid, setPaid] = React.useState(false);

  useEffect(() => {
    window.paypal?.Buttons({
        createOrder: (data, actions, err) => {
          return actions.order.create({
            intent: "CAPTURE",
            purchase_units: [
              {
                description: desc, // from props
                amount: {
                  currency_code: "AUD",
                  value: cost // from props
                }
              }
            ]
          });
        },
        onApprove: async (data, actions) => {
          const order = await actions.order.capture();
          setPaid(true);
          setCompleted(true);
          console.log(order);
        },
        onError: (err) => {
          setCompleted(true);
          console.error(err);
        }
      })
      .render("#paypal-button-container");
  }, [cost, desc]);

  return (
    <div className="Processing">
      <div id="paypal-button-container" />
      {completed &&
        (paid ? (
          // If the payment is made
          <div>Payment successful!</div>
        ) : (
          // If any error occurs
          <div>Error Occurred in processing payment! Please try again.</div>
        ))}
    </div>
  );
}

您的 Purchases 组件中存在一些语法错误。我建议使用函数组件,因为它们通常更容易,但这并不重要。我实际上玩得很开心所以我做了很多改变!

import React from "react";
import {Card, CardActions, CardContent, Typography, Button} from "@material-ui/core";
import PayPal from "./PayPal";

const Purchases = () => {
  const [state, setState] = React.useState({
    cost: 5.0,
    checkout: false,
    desc: "Test"
  });

  // helper to avoid repetition between the cards
  const renderCard = (title, desc, cost) => {
    return (
      <Card className="purchase-card">
        <CardContent>
          <Typography variant="h5" component="h2">
            {title}
          </Typography>
        </CardContent>
        <CardActions>
          <Button
            onClick={() =>
              setState({
                cost,
                desc,
                checkout: true
              })
            }
            color="primary"
          >
            ${cost} AUD
          </Button>
        </CardActions>
      </Card>
    );
  };

  console.log(state);
  return (
    <div className="Purchase">
      {state.checkout ? (
        <div>
          <Typography variant="h2">Checkout</Typography>
          <Typography variant="h4">
            {state.desc}: ${state.cost} AUD
          </Typography>
          <Button
            onClick={() => setState((prev) => ({ ...prev, checkout: false }))}
          >
            Change Plan
          </Button>
          <PayPal cost={state.cost} desc={state.desc} />
        </div>
      ) : (
        <div className="card-group">
          {renderCard("Payment 1", "Purchase Plan 1", 1)}
          {renderCard("Payment 2", "Purchase Plan 2", 2)}
          {renderCard("Payment 3", "Purchase Plan 3", 3)}
        </div>
      )}
    </div>
  );
};
export default Purchases;

Code Sandbox Link