Leonardo Alonso
Posted on December 3, 2020
En nuestro post anterior al fin terminamos nuestro formulario de pago del lado de React JS, en este post daremos inicio a la creación de nuestra pequeña api para aceptar los pagos utilizando flask.
Instalando los paquetes
Antes de realizar cualquier instalación vamos a activar nuestro entorno virtual.
source env/bin/activate
Ahora si para instalar flask solo debemos de hacer:
pip install flask
Y para instalar la librería de stripe hacemos:
pip install stripe
Creando nuestra api
Esta será una api pequeña por lo que solo necesitaremos un archivo al que llamaremos api.py
Para validar que flask esta correctamente instalado vamos a escribir lo siguiente
import flask
app = flask.Flask(__name__)
app.config["DEBUG"] = True
@app.route('/', methods=["GET"])
def home():
return "<h1> Flask API </h1>"
app.run()
Ahora hacemos python api.py
lo cual iniciara el servidor de DEBUG de flask con el que podremos acceder a nuestro localhost en el puerto 5000 el cual es el puerto por defecto para flask, este puede ser cambiado dentro de los parámetros de la función run()
.
Entonces si accedemos a 127.0.0.1:5000 veremos el mensaje que hemos colocado dentro de la función home
.
Ahora, recordando un poco nuestra aplicacion de React esta apuntando a la siguiente ruta api/acept_payment
, por lo que procederemos a crearla.
@app.route('/api/acept_payment', methods=['POST'])
def acept_payment():
pass
Ahora vamos a iniciar nuestro proyecto de React y a reiniciar nuestro servidor de flask, al hacer la peticion tal cual la tenemos ahora en nuestra aplicación nos toparemos con un error relacionado a CORS, sobre este tema vamos a hablar mas en otro post de momento para solucionarlo haremos la siguiente modificación.
Vamos a instalar la libreria flask-cors
haciendo pip install flask-cors
y escribimos lo siguiente
from flask import Flask, request, jsonify
from flask_cors import CORS
app = Flask(__name__)
app.config["DEBUG"] = True
CORS(app)
Vale en principio pensaríamos que esto va a funcionar pero si hacemos la petición al backend nos vamos a topar con el siguiente error:
Y esto que significa? 😕 Bueno pues resulta que no podemos hacer peticiones a un servidor sin https.
Vale y eso como lo solucionamos? pues de inicio nos podemos crear un certificado autofirmado y esto lo vamos a hacer de la siguiente manera
openssl req -x509 -newkey rsa:4096 -nodes -out cert.pem -keyout key.pem -days 365
Completamos toda la información que nos solicita y listo ya solo nos queda agregarlo a nuestro proyecto en python
app.run(ssl_context=('cert.pem', 'key.pem'))
Ahora desde el navegador debemos entrar a nuestro localhost en el puesto 5000 o el que hayan configurado para el servidor de prueba de flask y darle permiso para que utilice nuestro certificado autofirmado.
Esta solución no debe ir NUNCA en producción, para producción o nos compramos los certificados o usamos letsencript o lo que sea pero jamás un autofirmado.
Ok, ahora si nuestra petición ha de funcionar como esperamos
Muy bien ya podemos modificar nuestra api para aceptar el objeto json que enviamos desde react.
@app.route('/api/acept_payment', methods=['POST'])
def acept_payment():
data = request.get_json()
print(data)
return {'ff':'ff'}
Con la función get_json() de request obtenemos todo lo que se envié por método POST en formato json y de momento regresamos un diccionario de prueba.
Con esto estamos listos ahora si para aceptar nuestro pago con Stripe, así que vamos a modificar nuestra api
from flask import Flask, request, jsonify
from flask_cors import CORS
import stripe
stripe.api_key = 'secret'
app = Flask(__name__)
app.config["DEBUG"] = True
CORS(app)
@app.route('/', methods=['GET'])
def home():
return "<h1> Flask API </h1>"
@app.route('/api/acept_payment', methods=['POST'])
def acept_payment():
data = request.get_json()
payment = stripe.PaymentIntent.create(
amount=2000,
currency='mxn',
payment_method=data['payment_method'],
payment_method_types=["card"],
off_session=True,
confirm=True
)
print(payment)
return payment
app.run(ssl_context=('cert.pem', 'key.pem'))
Con esto estamos haciendo uso de el api de stripe y mas en especifico de su api de paymentIntents
entre los parámetros que estamos enviando esta el monto a cobrar, el tipo de cambio, el tipo de método de pago.
Mas en especifico el parámetro off_session
significa que no estamos enviando un id para customer
y confirm
significa que queremos confirmar el pago, ahora para que confirm
sea True off_session
también debe ser True.
No hay que olvidar poner nuestro propia clave secreta en esta linea.
stripe.api_key = 'secret'
de lo contrario nada de esto va a funcionar.
Con esto ya estamos aceptando pagos con stripe solo queda ver si el pago realmente se realizo y eso lo podemos ver desde el dashboard de stripe.
Aquí vemos nuestro pago confirmado pero... en el monto le pusimos que queríamos cobrar 2000 y el cargo que tenemos es solo por 20. Bueno esto se debe a que stripe toma el monto dos ceros antes, pero la solución para eso es que el valor que queremos cobrar los multipliquemos por 100 y listo.
@app.route('/api/acept_payment', methods=['POST'])
def acept_payment():
data = request.get_json()
amount = 2000
payment = stripe.PaymentIntent.create(
amount=amount*100,
currency='mxn',
payment_method=data['payment_method'],
payment_method_types=["card"],
off_session=True,
confirm=True
)
print(payment)
return payment
Ahora si todo esta bien y con eso vamos a concluir este POST que fue un poco mas largo que los anteriores pero con el propósito de mostrar las posibles complicaciones a las que nos vamos a enfrentar cuando trabajemos proyectos de este tipo, si aun así quedan dudas pueden usar los comentarios y tratare de responder a cada uno de ellos. Por ultimo les dejo los repositorios de cada proyecto y nos vemos en el siguiente post.
https://github.com/leonardoAlonso/StripeForm
https://github.com/leonardoAlonso/stripe-flask-api
Happy Codding
Posted on December 3, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.