Skip to content

Commit

Permalink
Update stripe to latest package/api version
Browse files Browse the repository at this point in the history
  • Loading branch information
wlcx committed Jan 29, 2024
1 parent cf1f703 commit 9d47aa4
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 41 deletions.
11 changes: 7 additions & 4 deletions apps/admin/payments.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

from sqlalchemy.sql.functions import func

from main import db, stripe
from main import db, stripe_client
from models.payment import (
Payment,
RefundRequest,
Expand Down Expand Up @@ -448,7 +448,7 @@ def refund(payment_id):

if form.stripe_refund.data:
app.logger.info("Refunding using Stripe")
charge = stripe.Charge.retrieve(payment.charge_id)
charge = stripe_client.charges.retrieve(payment.charge_id)

if charge.refunded:
# This happened unexpectedly - send the email as usual
Expand Down Expand Up @@ -506,8 +506,11 @@ def refund(payment_id):

if form.stripe_refund.data:
try:
stripe_refund = stripe.Refund.create(
charge=payment.charge_id, amount=refund.amount_int
stripe_refund = stripe_client.refunds.create(
params={
"charge": payment.charge_id,
"amount": refund.amount_int,
}
)

except Exception as e:
Expand Down
8 changes: 4 additions & 4 deletions apps/payments/refund.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
from decimal import Decimal
from stripe.error import StripeError
from stripe import StripeError
from flask import current_app as app, render_template
from flask_mailman import EmailMessage
from typing import Optional

from models.payment import RefundRequest, StripePayment, StripeRefund, BankRefund
from main import stripe, db
from main import stripe_client, db
from ..common.email import from_email


Expand All @@ -23,14 +23,14 @@ def create_stripe_refund(
"""Initiate a stripe refund, and return the StripeRefund object."""
# TODO: This should probably live in the stripe module.
assert amount > 0
charge = stripe.Charge.retrieve(payment.charge_id)
charge = stripe_client.charges.retrieve(payment.charge_id)
if charge.refunded:
return None

refund = StripeRefund(payment, amount)

try:
stripe_refund = stripe.Refund.create(
stripe_refund = stripe_client.refunds.create(
charge=payment.charge_id, amount=refund.amount_int, metadata=metadata
)
except StripeError as e:
Expand Down
58 changes: 32 additions & 26 deletions apps/payments/stripe.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
complicate this code.
"""
import logging
from typing import Optional

from flask import (
render_template,
Expand All @@ -23,9 +24,9 @@
from flask_mailman import EmailMessage
from wtforms import SubmitField
from sqlalchemy.orm.exc import NoResultFound
from stripe.error import AuthenticationError
import stripe

from main import db, stripe
from main import db, stripe_client
from models.payment import StripePayment
from ..common import feature_enabled
from ..common.email import from_email
Expand Down Expand Up @@ -81,17 +82,19 @@ def stripe_capture(payment_id):

if payment.intent_id is None:
# Create the payment intent with Stripe. This intent will persist across retries.
intent = stripe.PaymentIntent.create(
amount=payment.amount_int,
currency=payment.currency.upper(),
statement_descriptor_suffix=payment.description,
metadata={"user_id": current_user.id, "payment_id": payment.id},
intent = stripe_client.payment_intents.create(
params={
"amount": payment.amount_int,
"currency": payment.currency.upper(),
"statement_descriptor_suffix": payment.description,
"metadata": {"user_id": current_user.id, "payment_id": payment.id},
},
)
payment.intent_id = intent.id
db.session.commit()
else:
# Reuse a previously-created payment intent
intent = stripe.PaymentIntent.retrieve(payment.intent_id)
intent = stripe_client.payment_intents.retrieve(payment.intent_id)
if intent.status == "succeeded":
logger.warn(f"Intent already succeeded, not capturing again")
payment.state = "charging"
Expand Down Expand Up @@ -171,15 +174,15 @@ def stripe_waiting(payment_id):
@payments.route("/stripe-webhook", methods=["POST"])
def stripe_webhook():
try:
event = stripe.Webhook.construct_event(
event = stripe_client.construct_event(
request.data,
request.headers["STRIPE_SIGNATURE"],
app.config.get("STRIPE_WEBHOOK_KEY"),
)
except ValueError:
logger.exception("Error decoding Stripe webhook")
abort(400)
except stripe.error.SignatureVerificationError:
except stripe.SignatureVerificationError:
logger.exception("Error verifying Stripe webhook signature")
abort(400)

Expand Down Expand Up @@ -212,29 +215,32 @@ def stripe_ping(_type, _obj):
return ("", 200)


def stripe_update_payment(payment: StripePayment, intent: stripe.PaymentIntent = None):
def stripe_update_payment(
payment: StripePayment, intent: Optional[stripe.PaymentIntent] = None
):
"""Update a Stripe payment.
If a PaymentIntent object is not passed in, this will fetch the payment details from the Stripe API.
If a PaymentIntent object is not passed in, this will fetch the payment details from
the Stripe API.
"""
if intent is None:
intent = stripe.PaymentIntent.retrieve(payment.intent_id)

if len(intent.charges) == 0:
intent = stripe_client.payment_intents.retrieve(
payment.intent_id, params=dict(expand=["latest_charge"])
)
if intent.latest_charge is None:
# Intent does not have a charge (yet?), do nothing
return
elif len(intent.charges) > 1:
raise StripeUpdateUnexpected(
f"Payment intent #{intent['id']} has more than one charge"
)

charge = intent.charges.data[0]
if type(intent.latest_charge) is stripe.Charge:
# The payment intent object has been expanded already
charge = intent.latest_charge
else:
charge = stripe_client.charges.retrieve(intent.latest_charge)

if payment.charge_id is not None and payment.charge_id != charge["id"]:
if payment.charge_id is not None and payment.charge_id != charge.id:
logger.warn(
f"Charge ID for intent {intent['id']} has changed from {payment.charge_id} to {charge['id']}"
f"Charge ID for intent {intent.id} has changed from {payment.charge_id} to {charge.id}"
)

payment.charge_id = charge["id"]
payment.charge_id = charge.id

if charge.refunded:
return stripe_payment_refunded(payment)
Expand Down Expand Up @@ -424,9 +430,9 @@ def stripe_validate():
result.append((False, "Webhook key not configured"))

try:
webhooks = stripe.WebhookEndpoint.list()
webhooks = stripe_client.webhook_endpoints.list()
result.append((True, "Connection to Stripe API succeeded"))
except AuthenticationError as e:
except stripe.AuthenticationError as e:
result.append((False, f"Connecting to Stripe failed: {e}"))
return result

Expand Down
7 changes: 6 additions & 1 deletion main.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ def include_object(object, name, type_, reflected, compare_to):
static_digest = FlaskStaticDigest()
toolbar = DebugToolbarExtension()
wise = None
stripe_client = None


def check_cache_configuration():
Expand Down Expand Up @@ -153,7 +154,11 @@ def load_user(userid):

login_manager.anonymous_user = load_anonymous_user

stripe.api_key = app.config["STRIPE_SECRET_KEY"]
global stripe_client
stripe_client = stripe.StripeClient(
api_key=app.config["STRIPE_SECRET_KEY"],
stripe_version="2023-10-16",
)
global wise
wise = pywisetransfer.Client(
api_key=app.config["TRANSFERWISE_API_TOKEN"],
Expand Down
11 changes: 6 additions & 5 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ pybarcode = {git = "https://github.com/emfcamp/python-barcode"}
pillow = "~=10.0"
icalendar = "==3.11.7"
pytz = "*"
stripe = "~=2.38.0"
stripe = "~=8.0.0"
ofxparse = "==0.16"
python-dateutil = "*"
slotmachine = {git = "https://github.com/emfcamp/slotmachine.git"}
Expand Down

0 comments on commit 9d47aa4

Please sign in to comment.