Botón paypal 2021 react 17.x.x
npm i react-paypal-button-v2
¡Bienvenida! Este es un curso especial de React Hooks
¿Qué aprenderás en el Curso Profesional de React Hooks?
¿Qué son los React Hooks y cómo cambian el desarrollo con React?
Introducción a React Hooks
useState: estado en componentes creados como funciones
useEffect: olvida el ciclo de vida, ahora piensa en efectos
useContext: la fusión de React Hooks y React Context
useReducer: como useState, pero más escalable
¿Qué es memoization? Programación funcional en JavaScript
useMemo: evita cálculos innecesarios en componentes
useRef: manejo profesional de inputs y formularios
useCallback: evita cálculos innecesarios en funciones
Optimización de componentes en React con React.memo
Custom hooks: abstracción en la lógica de tus componentes
Third Party Custom Hooks de Redux y React Router
Configura un entorno de desarrollo profesional
Proyecto: análisis y retos de Platzi Conf Store
Git Hooks con Husky
Instalación de Webpack y Babel: presets, plugins y loaders
Configuración de Webpack 5 y webpack-dev-server
Configuración de Webpack 5 con loaders y estilos
Loaders de Webpack para Preprocesadores CSS
Flujo de desarrollo seguro y consistente con ESLint y Prettier
Estructura y creación de componentes para Platzi Conf Store
Arquitectura de vistas y componentes con React Router DOM
Maquetación y estilos del home
Maquetación y estilos de la lista de productos
Maquetación y estilos del formulario de checkout
Maquetación y estilos de la información del usuario
Maquetación y estilos del flujo de pago
Integración de íconos y conexión con React Router
Integración de React Hooks en Platzi Conf Merch
Creando nuestro primer custom hook
Implementando useContext en Platzi Conf Merch
useContext en la página de checkout
useRef en la página de checkout
Integrando third party custom hooks en Platzi Conf Merch
Configura mapas y pagos con PayPal y Google Maps
Paso a paso para conectar tu aplicación con la API de PayPal
Integración de pagos con la API de PayPal
Completando la integración de pagos con la API de PayPal
Paso a paso para conectar tu aplicación con la API de Google Maps
Integración de Google Maps en el mapa de checkout
Creando un Custom Hook para Google Maps
Estrategias de deployment profesional
Continuous integration y continuous delivery con GitHub Actions
Compra del dominio y despliega con Cloudflare
Optimización de aplicaciones web con React
Integración de React Helmet para mejorar el SEO con meta etiquetas
Análisis de performance con Google Lighthouse
Convierte tu aplicación de React en PWA
Bonus: trabaja con Strapi CMS para crear tu propia API
Crea una API con Strapi CMS y consúmela con React.js
¿Qué sigue en tu carrera profesional?
Próximos pasos para especializarte en frontend
No tienes acceso a esta clase
¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera
Oscar Barajas Tavares
Aportes 35
Preguntas 9
Botón paypal 2021 react 17.x.x
npm i react-paypal-button-v2
Para que se les abra en el navegador la documentación de cualquier paquete:
npm docs <nombre-paquete>
npm docs react-paypal-button
Archivo nuevo src/utils/index.js
export const handleSumTotal = (cart) => {
const reducer = (acc, cur) => acc + cur.price;
const sum = cart.reduce(reducer, 0);
return sum;
}
La libreria de react-paypal-button esta depreciada segun su documentacion yo use @paypal/react-paypal-js
Se importa un PayPalScriptProvider y se le pada un parametri option client-id que es el client id que se encuetra en el la app que creamos en paypal
import React from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import { Home } from '../containers/Home';
import { Checkout } from '../containers/Checkout';
import Information from '../containers/Information';
import Payment from '../containers/Payment';
import Success from '../containers/Success';
import NotFound from '../containers/NotFound';
import '../styles/components/App.css';
import Layout from '../components/Layout';
import useInitialState from '../hooks/useInitialState';
import AppContext from '../context/AppContext';
import { PayPalScriptProvider } from '@paypal/react-paypal-js';
function App() {
const initialState = useInitialState();
return (
<PayPalScriptProvider options={{"client-id": "AQ348XIPD92Fd586HLuYrTc1tqaYZHEpZIeT3rlMH04KUQBjZSZ0G2H4m4vsIhXs2-j3tSjtBbpcW-Ma"}}>
<AppContext.Provider value={initialState}>
<BrowserRouter>
<Layout>
<Routes>
<Route exact path="/" element={<Home />} />
<Route exact path="/checkout" element={<Checkout />} />
<Route
exact
path="/checkout/information"
element={<Information />}
/>
<Route exact path="/checkout/payment" element={<Payment />} />
<Route exact path="/checkout/success" element={<Success />} />
<Route element={<NotFound />} />
</Routes>
</Layout>
</BrowserRouter>
</AppContext.Provider>
</PayPalScriptProvider>
);
}
export default App;
despues en el payment tenemos esta vista que redirige a succes
import React, { useContext , useState} from 'react';
import AppContext from '../context/AppContext';
import { Link, useNavigate } from 'react-router-dom';
import '../styles/components/Payment.css';
import { handleSumTotal } from '../utils';
import { PayPalButtons } from '@paypal/react-paypal-js';
const Payment = () => {
const {
state: { cart },
} = useContext(AppContext);
const [paidFor , setPaidFor] = useState(false)
const handleApprove = (orderID) => {
setPaidFor(true)
}
const history = useNavigate()
if(paidFor)
{
history('/checkout/success')
}
return (
<div className="Payment">
<div className="Payment-content">
<h3>Resumen del pedido:</h3>
{cart.map((product, index) => (
<div key={index} className="Payment-item">
<div className="Payment-element">
<h4>{product.title}</h4>
<span>{product.price}</span>
</div>
</div>
))}
{cart.length > 0 ? (
<h3>{`Total: ${handleSumTotal(cart)}`}</h3>
) : <></> }
<div className="Payment-button" id="payment-button-container">
<PayPalButtons
createOrder={(data, actions) => {
return actions.order.create({
purchase_units: [
{
amount: {
value: handleSumTotal(cart),
},
},
],
});
}}
onApprove={(data, actions) => {
return actions.order.capture().then((details) => {
const name = details.payer.name.given_name;
handleApprove(data.orderID)
});
}}
/>
</div>
</div>
<div />
</div>
);
};
export default Payment;
Los tipos para typescript:
type PayPalButtonProps = {
paypalOptions: PaypalOptions;
buttonStyles: ButtonStylingOptions;
amount: number;
subscriptionPlanId?: string;
onApprove?: (data, authId) => void;
onPaymentStart?: () => void;
onPaymentSuccess?: (response: OnCaptureData) => void;
onPaymentError?: (msg: string) => void;
onPaymentCancel?: (data: OnCancelData) => void;
onShippingChange?: (data: OnShippingChangeData) =>
Promise<void | string | number> |
string |
number |
void;
}
Osea que solo yo está tomando este curso? Todos los comentarios son de hace un año, dos años, tres años… POR DIOS!
ESTUDIANTES 2023, les recomiendo esta docu
package/@paypal/react-paypal-js
Luego dejo mi código adjunto.
Comando
npm i react-paypal-button-v2
archivo Payment.jsx
import React, { useContext } from 'react';
import { PayPalButton } from 'react-paypal-button-v2';
import AppContext from '../context/AppContext';
import '../styles/components/Payment.css';
const Payment = ({ history }) => {
const { state, addNewOrder } = useContext(AppContext);
const { cart, buyer } = state;
const paypalOptions = {
clientId: 'ATN4MgsCVKSXinkSTL1YqlANTikW5fXyo5C7TkyVUG7JB0DTr1G2aabkWFF9Uz6kKo61tL48cfWpomc4',
intent: 'capture',
currency: 'USD',
};
const buttonStyles = {
layout: 'vertical',
shape: 'rect',
};
const handlePaymentSuccess = (data) => {
console.log(data);
if (data.status === 'COMPLETED') {
const newOrder = {
buyer,
product: cart,
payment: data,
};
addNewOrder(newOrder);
history.push('/checkout/success');
}
};
const handleSumTotal = () => {
const reducer = (accumulator, currentValue) => accumulator + currentValue.price;
const sum = cart.reduce(reducer, 0);
return sum;
};
return (
<div className='Payment'>
<div className='Payment-content'>
<h3>Resument del pedido:</h3>
{cart.map((item) => (
<div className='Payment-item' key={item.title}>
<div className='Payment-element'>
<h4>{item.title}</h4>
<span>
$
{' '}
{item.price}
</span>
</div>
</div>
))}
<div className='Payment-button'>
<PayPalButton
paypalOptions={paypalOptions}
buttonStyles={buttonStyles}
amount={handleSumTotal()}
onPaymentStart={() => console.log('Start Payment')}
onPaymentSuccess={(data) => handlePaymentSuccess(data)}
onPaymentError={(error) => console.log(error)}
onPaymentCancel={(data) => console.log(data)}
/>
</div>
</div>
<div />
</div>
);
};
export default Payment;
Me sale este error de dependencia y no encuentro como solucionarlo sin instalar otra versión de react:
Wow alguien más siente que el video fue un poco largo 😛 Necesario pero largo
Para las personas que tienen problemas con el btn de Paypal aqui les dejo una solución:
npm i @paypal/react-paypal-js
<code>
import React from 'react'
import { PayPalScriptProvider, PayPalButtons } from "@paypal/react-paypal-js";
const PaypalPay = () => {
return (
<PayPalScriptProvider
options={{
"client-id": process.env.REACT_APP_PAYPAL_ID,
currency: "USD",
}}>
<PayPalButtons
style={{ layout: "vertical" }}
disabled={false}
createOrder={(data, actions) =>
actions.order
.create({
purchase_units: [
{
amount: {
value: Number.parseFloat(handleSumTotal()).toFixed(2),
},
},
],
})
.then((orderId) => {
return orderId;
})
}
onApprove={(data, actions) => {
return actions.order
.capture()
.then((data) => {
// Your code here after capture the
paymentHandleSuccess(data);
})
.catch((error) => console.log(error));
}}
/>
</PayPalScriptProvider>
)
}
export default PaypalPay
Esta clase deberian de actualizar.
Pesima clase !
Despues de mucho renegar llegué a la misma solución que Hector:
const handleSumTotal = (cart) => {
const reducer = (accumulator, currentValue) =>
accumulator + currentValue.price;
const sum = cart.reduce(reducer, 0);
return sum;
};
export default handleSumTotal;
Y la invoco en Checkout, Information y Payment pasándole cart como parámetro:
<h3>{`Total Price: $${handleSumTotal(cart)}`}</h3>
Recordemos que (si no me equivoco) cart viene del estado, que viene del contexto. Así está en Checkout.jsx:
const { state, removeFromCart } = useContext(AppContext);
const { cart } = state;
Ojalá les sirva!
En dos años ha cambiado mucho el lenguaje.
nom i react-paypal-button-v2
import { PayPalButton } from 'react-paypal-button-v2'
...
<PayPalButton
paypalOptions={paypalOptions}
buttonStyles={buttonStyles}
amount={sumTotalAmount(cart)}
onPaymentStart={() => console.log("event paypal")}
onPaymentSuccess={data => handlePaymentSuccess(data)}
onPaymentError={error => console.log("error ", error)}
onPaymentCancel={data => console.log("data cancel ", data)}
/>
Les comparto algunos problemas que me ocurrieron. Primero no podía instalar react-paypal-button, lo solucioné con este comando: npm i react-paypal-button-v2
Segundo, el reto para hacer un outil la función de handleSumTotal lo resolví así:
-Crée la carpeta outils en src y dentro el archivo index.js.
-Copié y pegé la funcion de handleSumTotal pero le agregué unos cambios para que funcione:
En sí solo hay que agregar “cart” como parametro y cada vez que quieras usar la funcion en un componente la importas así:
import { handleSumTotal } from ‘…/utils/index’;
Y para usarlo así:
<h2>{`Total: $${handleSumTotal(cart)}`}</h2>
amount={handleSumTotal(cart)}
Intenté tambien usar dotenv para generar variables de entorno para las paypalOptions (sobre todo para que no quede hardcodeado el clientId) pero no conseguí que compile.
Si alguien lo hizo o implementó algo similar, sería buenisimo que lo comparta!
Pésima clase, deberían actualizar.
.
Todo lo que se hace, me genera varios errores.
In react-router-dom v6 useHistory() is replaced by useNavigate().
You can use:
import { useNavigate } from 'react-router-dom';
const navigate = useNavigate();
navigate('/home');
Hola! para los que le sale el error cuando quieren instalar la dependencia de react-paypal-button-v2
AQUI UNA POSIBLE SOLUCION!!!
npm install react-paypal-button-v2 --save
npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR!
npm ERR! While resolving: raycris-conf-merch@1.0.0
npm ERR! Found: react@18.0.0
npm ERR! node_modules/react
npm ERR! react@"^18.0.0" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer react@"^0.14.6 || 15.x.x || 16.x.x || 17.x.x" from react-paypal-button-v2@2.6.3
npm ERR! node_modules/react-paypal-button-v2
npm ERR! react-paypal-button-v2@"*" from the root project
npm ERR!
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force, or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
npm ERR!
npm ERR! See C:\Users\Raycris\AppData\Local\npm-cache\eresolve-report.txt for a full report.
npm ERR! A complete log of this run can be found in:
npm ERR! C:\Users\Raycris\AppData\Local\npm-cache\_logs\2022-04-05T23_37_11_773Z-debug-0.log
SOLAMENTE DEBEMOS DE PONER EL SIGUIENTE COMANDO npm i react-paypal-button-v2 --force
, NO ES LO MAS RECOMENDABLE PERO FUNCIONA
En mi caso, como estoy usando NextJS, usé el router de Next en vez de useHistory:
https://nextjs.org/docs/api-reference/next/router
Les dejo mi repositorio:
Les dejo una documentación que hice en el curso de webpack por si desean usar variables de entorno para su CLIENT_ID:
Es importante considerar las variables de entorno va a ser un espacio seguro donde podemos guardar datos sensibles.
Para instalar debemos correr el comando.
npm install -D dotenv-webpack
Posteriormente debemos crear un archivo .env
donde estarán la clave para acceder a la misma y el valor que contendrán (algo importante a tener en cueta es que el archivo .env
no se debe enviar al repositorio), aquí es buena idea subir por ejemplo nuestra llave de conexión a una API.
# Ejemplo
API=https://randomuser.me/api/
Es buena idea tener un archivo de ejemplo donde, el mismo si se pueda subir al repositorio como muestra de que campos van a ir.
Una vez creado el archivo .env
debemos agregar la siguiente configuración en webpack.config.js
.
...
const Dotenv = require('dotenv-webpack');
module.exports = {
...
plugins: [
new Dotenv()
],
}
.env
por defecto y lo agregar a nuestro proyectoPara usarlas en JavaScript debes hacer lo siguiente:
const nombre = process.env.NOMBRE_VARIABLE;
Toda la configuración se podrá acceder desde process.env
.
De esta manera podemos tener información delicada de manera segura.
Si al realizar el comando npm i react-paypal-button les sale el error: “Eresolve: unable to resolve dependency three” deben instalar la librería de paypal button pero agregándole el comando --legacy-peer-deps. En este caso, el comando quedaría así:
npm install react-paypal-button --save --legacy-peer-deps
Hola en 08-2022 se puede instalar el button con
npm install react-paypal-button-v2 --force
Dejo un video que es un excelente complemento para saber usar el botón de PayPal
https://www.youtube.com/watch?v=nAz8xRQaPZQ
El boton de react paypal me da el sgte error, el clientId esta correcto y el resto de configuracion tal cual la tiene Oscar.
React-paypal-button loading script error:
Make sure that that your clientID is correct and that you are passing valid values to the paypalOptions prop and the buttonStyles prop.
For a list of valid properties for paypalOptions see https://developer.paypal.com/docs/checkout/reference/customize-sdk/#query-parameters
For a list of valid properties for buttonStyles see https://developer.paypal.com/docs/checkout/integration-features/customize-button/#color
Parece que el paquete react-paypal-button requiere tener una versión menor de la 17 de react si no da un error al instalarla, así que instalen una 16.8.x
A mi me sirvió con el siguiente comando en la terminal:
npm install react-paypal-button --save
ya se puede usar useHistory quedaria algo asi
import { useHistory } from 'react-router-dom';
const history = useHistory();
const handlePaymentSuccess = (data) => {
console.log(data);
if (data.status === 'COMPLETED') {
const newOrder = {
buyer,
product: cart,
payment: data,
};
addNewOrder(newOrder);
history.push('/checkout/success');
}
};```
le agregue como componente con el nombre PayPal.jsx
import { useEffect } from "react";
import {PayPalScriptProvider, PayPalButtons,usePayPalScriptReducer} from "@paypal/react-paypal-js";
const amount = "2";
const currency = "USD";
const style = {"layout":"vertical"};
const ButtonWrapper = ({ currency, showSpinner }) => {
const [{ options, isPending }, dispatch] = usePayPalScriptReducer();
useEffect(() => {
dispatch({
value: {
...options,
currency: currency,
},
});
}, [currency, showSpinner]);
return (<>
{ (showSpinner && isPending) && <div className="spinner" /> }
<PayPalButtons
style={style}
disabled={false}
forceReRender={[amount, currency, style]}
fundingSource={undefined}
createOrder={(data, actions) => {
return actions.order
.create({
purchase_units: [
{
amount: {
currency_code: currency,
value: amount,
},
},
],
})
.then((orderId) => {
// Your code here after create the order
return orderId;
});
}}
onApprove={function (data, actions) {
return actions.order.capture().then(function () {
// Your code here after capture the order
});
}}
/>
</>
);
}
export default function App() {
return (
<div style={{ maxWidth: "750px", minHeight: "200px" }}>
<PayPalScriptProvider
options={{
"client-id": "test",
components: "buttons",
currency: "USD"
}}
>
<ButtonWrapper
currency={currency}
showSpinner={false}
/>
</PayPalScriptProvider>
</div>
);
}
y en payment le deje de esta manera la cual me permite tener el total de productos y el valor a pagar y genere el pago con tarjeta de crédito
import React, { useContext } from 'react';
import AppContext from '../context/AppContext';
import '../styles/components/Payment.css';
import PayPal from './PayPal'
const Payment = () => {
const { state: { cart }, removeToCart } = useContext(AppContext);
const handleRemote = product => {
removeToCart(product)
}
const handleSumtotal = () => {
const reducer = (accumulator, currentValue) => accumulator + (currentValue.price * currentValue.qty);
const sum = cart.reduce(reducer, 0);
return sum;
}
return (
<div className="Payment">
<div className="Payment-content">
<h3>Resument del pedido:</h3>
{cart.length > 0
? <>
{cart.map(product => (
<div key={product.id} className="Checkout-item">
<div className="Checkout-element">
<h4>{product.title}</h4>
<span>Cant. {product.qty}</span>
<span>$ {product.price}</span>
<span>Total: $ {product.price * product.qty}</span>
</div>
</div>
))}
<h3>Precio Total: {handleSumtotal()}</h3>
</>
: <p>No hay Articulos en el carrito</p>}
<div className="Payment-button">
<PayPal/>
</div>
</div>
<div />
</div>
);
}
export default Payment;
Llevando totalizador a un utilitario
const sumTotal = (arr, field) => {
const reducer = (accumulator, currentValue) =>
accumulator + currentValue[field];
const sum = arr.reduce(reducer, 0);
return sum;
};
export {
sumTotal
}
Si a alguien le sale el siguiente error instalando la dependencia del boton de Paypal
Lo puede solucionar intentando instalar la dependencia asi:
npm i react-paypal-button-v2 --legacy-peer-deps
¿Por qué oculta el clientId en el video y en los archivos adjuntos lo muestra? ¿Lo cambió en los archivos u olvidó ocultarlo?
b
¿Quieres ver más aportes, preguntas y respuestas de la comunidad?