PayPal 稍后付款按钮未显示

时间:2021-05-03 08:28:55

标签: javascript reactjs paypal paypal-sandbox paypal-buttons

我正在学习一个教程,其中老师正在将 PayPal 集成到电子商务网站中。问题是,我只有 2 个按钮(图 1),但讲师有 3 个。 (图片 2)我试图一步一步地跟随他,但也许这是 react-paypal-button-v2 库的更新版本或类似的问题。其他 2 个按钮正在正确显示。 (即使它会很好,如果“借记卡或信用卡”按钮有说明)正如您所看到的,我还缺少按钮下方的“由 PayPal 提供支持”行。我已经通过沙箱帐户测试了主要 PayPal 按钮的功能,在这方面一切正常。有人可以帮我解决这个问题吗?非常感谢您的最终帮助。

这些是我当前的 PayPal 按钮 -(图片 0)

enter image description here

更新 - 从代码中删除注释(我将它们留在 SO 上的位置,所以我可以看到它们的位置)后,我已经解决了这个问题 “由 PayPal 提供支持”和“借记卡或信用卡”行。所以现在我的按钮看起来像这样 -(图 1)

enter image description here

这是想要的结果 -(图片 2)

enter image description here

OrderScreen.js -(请注意,尽管事实上,Stack Overflow 上的某些注释不是灰色的,但在我的 IDE 中它们实际上是灰色的)

import React, { useState, useEffect } from "react";
import { Button, Row, Col, ListGroup, Image, Card } from "react-bootstrap";
import { Link } from "react-router-dom";
import { useDispatch, useSelector } from "react-redux";
import { PayPalButton } from 'react-paypal-button-v2'
import Message from "../components/Message";
import Loader from '../components/Loader'
import { getOrderDetails, payOrder } from "../actions/orderActions";
import { ORDER_PAY_RESET } from '../constants/orderConstants'

function OrderScreen({ match }) {
  const orderId = match.params.id
  const dispatch = useDispatch();

  const [sdkReady, setSdkReady] = useState(false)
  //we are updating the setSdkReady
  //false is the default value, but once we load the setSdkReady, then it will be set to true
  //if we are not ready, then we will not add the button, but if we are ready, we will add the button
  //that is going to depend on whether successPay is true or not (?)

  const orderDetails = useSelector(state => state.orderDetails)
  const {order, error, loading} = orderDetails

  const orderPay = useSelector(state => state.orderPay)
  const { loading:loadingPay, success:successPay } = orderPay //here we are setting a custom name for the loading
  
  if(!loading && !error){
     order.itemsPrice = order.orderItems
     .reduce((acc, item) => acc + item.price * item.qty, 0)
     .toFixed(2);
    //acc znamená accumulator, toFixed(2) znamená, že výsledné číslo bude mít maximálně jen 2 decimal places
  } //orderItems gets calculated only once we have that order
  
  const addPayPalScript = () => { //this function is going to be dependent on our order status
      const script = document.createElement('script')
      script.type = 'text/javascript'
      script.src = 'https://www.paypal.com/sdk/js?client-id=AVrrJLnByiAFSjPZ91_-o5OeBqUzCQulKVl0aly2FyVOQfZ9cHn2kvUSDNvSJqMv8S9KzBc2_lxRBnuV'
      script.async = true
      script.onload = () => {
        setSdkReady(true)
      }
      document.body.appendChild(script) //we are appending the script to the dom
  }
  
  useEffect(() => {
      if (!order || successPay || order._id !== Number(orderId)){ //we are going to dispatch this, if we don´t have an order or if the order id is not here yet
          dispatch({ type:ORDER_PAY_RESET })
          dispatch(getOrderDetails(orderId)) //this is going to make the api call using that id
          //we only get the order details when we don´t have that information yet
      } else if(!order.isPaid){ //if order is not paid
           if(!window.paypal){
              addPayPalScript() //if the script is not there, then add it
           } else {
             setSdkReady(true) //this gets our script ready
           }
      }   
  }, [dispatch, order, orderId, successPay]) //uvnitř hranatých závorek jsou dependencies

  const successPaymentHandler = (paymentResult) => {
    //paymentResult is going to be the data, that the paypal will give us
    //it will be the response from paypal
    dispatch(payOrder(orderId, paymentResult)) //payOrder is taking in 2 parameters
    //payOrder sends our API call and it goes and updates our database
  }

  return loading ? ( //we are checking, if (?) we are loading
      <Loader/> //load spinner
  ) : error ? ( //if we are not loading, then (else je :) we will check for an error
      <Message variant='danger'>{error}</Message> //if there is an error, let´s throw out that message
  ) : ( //if none of the above are true, then pass in the final component
    <div>
      <h1>Order: {order._id}</h1>
      <Row>
        <Col md={8}>
          <ListGroup variant="flush">
            <ListGroup.Item>
              <h2>Shipping</h2>
              <p><strong>Name: </strong> {order.user.name}</p>
              <p><strong>Email: </strong><a href={`mailto:${order.user.email}`}>{order.user.email}</a></p>
              <p>
                <strong>Shipping: </strong>
                {order.shippingAddress.address}, {order.shippingAddress.city}
                {"  "}
                {order.shippingAddress.postalCode},{"  "}
                {order.shippingAddress.country}
              </p>

              {order.isDelivered ? ( //this will be updated from the admin panel
                  <Message variant='success'>Delivered on {order.deliveredAt}</Message>
              ) : ( // if this is not delivered, then the else statement will take place
                  <Message variant='warning'>Not Delivered</Message>
              )}
            </ListGroup.Item>

            <ListGroup.Item>
              <h2>Payment Method</h2>
              <p>
                <strong>Method: </strong>
                {order.paymentMethod}
              </p>
              {order.isPaid ? ( //this will be updated from the admin panel
                  <Message variant='success'>Paid on {order.paidAt}</Message>
              ) : ( // if this is not paid, then the else statement will take place
                  <Message variant='warning'>Not Paid</Message>
              )}
            </ListGroup.Item>

            <ListGroup.Item>
              <h2>Order Items</h2>
              {order.orderItems.length === 0 ? (
                <Message variant="info">Order is empty</Message>
              ) : (
                <ListGroup variant="flush">
                  {order.orderItems.map((item, index) => (
                    <ListGroup.Item key={index}>
                      <Row>
                        <Col md={1}>
                          <Image
                            src={item.image}
                            alt={item.name}
                            fluid
                            rounded
                          />
                        </Col>

                        <Col>
                          <Link to={`/product/${item.product}`}>
                            {item.name}
                          </Link>
                        </Col>

                        <Col md={4}>
                          {item.qty} X ${item.price} = $
                          {(item.qty * item.price).toFixed(2)}
                        </Col>
                      </Row>
                    </ListGroup.Item>
                  ))}
                </ListGroup>
              )}
            </ListGroup.Item>
          </ListGroup>
        </Col>

        <Col md={4}>
          <Card>
            <ListGroup variant="flush">
              <ListGroup.Item>
                <h2>Order Summary</h2>
              </ListGroup.Item>

              <ListGroup.Item>
                <Row>
                  <Col>Items:</Col>
                  <Col>${order.itemsPrice}</Col>
                </Row>
              </ListGroup.Item>

              <ListGroup.Item>
                <Row>
                  <Col>Shipping:</Col>
                  <Col>${order.shippingPrice}</Col>
                </Row>
              </ListGroup.Item>

              <ListGroup.Item>
                <Row>
                  <Col>Tax:</Col>
                  <Col>${order.taxPrice}</Col>
                </Row>
              </ListGroup.Item>

              <ListGroup.Item>
                <Row>
                  <Col>Total:</Col>
                  <Col>${order.totalPrice}</Col>
                </Row>
              </ListGroup.Item>

              {!order.isPaid && (
                <ListGroup.Item>
                  {loadingPay && <Loader/>}
                  
                  {!sdkReady ? ( //while we are loading, then output the loader
                    <Loader/>
                  ) : ( //else
                      <PayPalButton
                          amount={order.totalPrice}
                          onSuccess={successPaymentHandler}
                      />
                  )}
                </ListGroup.Item>
              )}

            </ListGroup>
          </Card>
        </Col>
      </Row>
    </div>
  );
}

export default OrderScreen;

0 个答案:

没有答案