I am following a tutorial, where the teacher is integrating PayPal into an e-commerce website. The thing is, that I have only 2 buttons, (image 1) but the instructor has 3 of them. (image 2) I was trying to follow him step by step, but maybe it is a matter of newer version of react-paypal-button-v2 library or something like that. The other 2 buttons are being displayed properly. (even though it would be fine, if the "Debit or Credit Card" button would have a description) As You can see, I am also missing the "Powered by PayPal" line underneath the buttons. I have tested the functionality of the main PayPal button through the sandbox accounts and everything is ok in this regard. Could anybody please help me with this issue? Thank You very much for Your eventual assistance.
These are my current PayPal buttons - (image 0)
Update - After removing the comments (I have left them on their places here on SO, so I can see, where they were) from the code, I have solved the issue with the "Powered by PayPal" and "Debit or Credit Card" lines. So now my buttons look like this - (image 1)
And here is the desired outcome - (image 2)
OrderScreen.js - (please note, that despite the fact, that some of the comments are not gray here on Stack Overflow, they are actually grey in my 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;