capsul-flask/capsulflask/payment_stripe.py

116 lines
4.3 KiB
Python
Raw Normal View History

2020-05-12 17:40:10 +00:00
import stripe
import json
import decimal
from flask import Blueprint
from flask import request
from flask import current_app
from flask import session
from flask import redirect
from flask import url_for
from flask import jsonify
from flask import flash
from flask import render_template
from werkzeug.exceptions import abort
from capsulflask.auth import account_required
from capsulflask.db import get_model
bp = Blueprint("stripe", __name__, url_prefix="/stripe")
@bp.route("/", methods=("GET", "POST"))
@account_required
def index():
stripe_checkout_session_id=None
if request.method == "POST":
errors = list()
if "dollars" not in request.form:
errors.append("dollars is required")
elif decimal.Decimal(request.form["dollars"]) < decimal.Decimal(1):
errors.append("dollars must be >= 1")
if len(errors) == 0:
print(f"creating stripe checkout session for {session['account']}, ${request.form['dollars']}")
checkout_session = stripe.checkout.Session.create(
success_url=current_app.config['BASE_URL'] + "/stripe/success?session_id={CHECKOUT_SESSION_ID}",
cancel_url=current_app.config['BASE_URL'] + "/stripe",
payment_method_types=["card"],
customer_email=session["account"],
line_items=[
{
"name": "Capsul Cloud Compute",
"images": [current_app.config['BASE_URL']+"/static/capsul-product-image.png"],
"quantity": 1,
"currency": "usd",
"amount": request.form["dollars"]
}
]
)
stripe_checkout_session_id = checkout_session['id']
print(f"stripe_checkout_session_id={stripe_checkout_session_id} ( {session['account']}, ${request.form['dollars']} )")
get_model().create_stripe_checkout_session(stripe_checkout_session_id, session["account"], request.form["dollars"])
for error in errors:
flash(error)
return render_template(
"stripe.html",
stripe_checkout_session_id=stripe_checkout_session_id,
stripe_public_key=current_app.config["STRIPE_PUBLISHABLE_KEY"]
)
@bp.route("/success", methods=("GET",))
def success():
stripe_checkout_session_id = request.args.get('session_id')
if not stripe_checkout_session_id:
print("/stripe/success returned 400: missing required URL parameter session_id")
abort(400, "missing required URL parameter session_id")
else:
checkout_session = stripe.checkout.Session.retrieve(stripe_checkout_session_id)
if checkout_session and 'display_items' in checkout_session:
dollars = checkout_session['display_items'][0]['amount']
#consume_stripe_checkout_session deletes the checkout session row and inserts a payment row
# its ok to call consume_stripe_checkout_session more than once because it only takes an action if the session exists
success_account = get_model().consume_stripe_checkout_session(stripe_checkout_session_id, dollars)
if success_account:
print(f"{success_account} paid ${dollars} successfully (stripe_checkout_session_id={stripe_checkout_session_id})")
return redirect(url_for("console.account_balance"))
# I don't think the webhook is needed
# @bp.route("/webhook", methods=("POST",))
# def webhook():
# request_data = json.loads(request.data)
# signature = request.headers.get('stripe-signature')
# try:
# event = stripe.Webhook.construct_event(
# payload=request_data,
# sig_header=signature,
# secret=current_app.config['STRIPE_WEBHOOK_SECRET']
# )
# if event['type'] == 'checkout.session.completed':
# dollars = event['data']['object']['display_items'][0]['amount']
# stripe_checkout_session_id = event['data']['object']['id']
# #consume_stripe_checkout_session deletes the checkout session row and inserts a payment row
# # its ok to call consume_stripe_checkout_session more than once because it only takes an action if the session exists
# get_model().consume_stripe_checkout_session(stripe_checkout_session_id, dollars)
# return jsonify({'status': 'success'})
# except ValueError as e:
# print("/stripe/webhook returned 400: bad request", e)
# abort(400, "bad request")
# except stripe.error.SignatureVerificationError:
# print("/stripe/webhook returned 400: invalid signature")
# abort(400, "invalid signature")