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
|
2020-05-12 18:04:35 +00:00
|
|
|
errors = list()
|
2020-05-12 17:40:10 +00:00
|
|
|
|
|
|
|
if request.method == "POST":
|
|
|
|
if "dollars" not in request.form:
|
|
|
|
errors.append("dollars is required")
|
2020-05-12 18:04:35 +00:00
|
|
|
dollars = None
|
|
|
|
try:
|
|
|
|
dollars = decimal.Decimal(request.form["dollars"])
|
|
|
|
except:
|
|
|
|
errors.append("dollars must be a number")
|
|
|
|
|
|
|
|
if dollars and dollars < decimal.Decimal(1):
|
2020-05-12 17:40:10 +00:00
|
|
|
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",
|
2020-05-12 18:04:35 +00:00
|
|
|
"amount": int(dollars*100)
|
2020-05-12 17:40:10 +00:00
|
|
|
}
|
|
|
|
]
|
|
|
|
)
|
|
|
|
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:
|
2020-05-12 18:04:35 +00:00
|
|
|
cents = checkout_session['display_items'][0]['amount']
|
|
|
|
dollars = decimal.Decimal(cents)/100
|
2020-05-12 17:40:10 +00:00
|
|
|
|
|
|
|
#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")
|
|
|
|
|