def stripe_update_payment(payment: StripePayment, intent: 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 intent is None: intent = stripe.PaymentIntent.retrieve(payment.intent_id) if len(intent.charges) == 0: # 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 payment.charge_id is not None and payment.charge_id != charge["id"]: logging.warn( f"Charge ID for intent {intent['id']} has changed from {payment.charge_id} to {charge['id']}" ) payment.charge_id = charge["id"] if charge.refunded: return stripe_payment_refunded(payment) elif charge.status == "succeeded": return stripe_payment_paid(payment) elif charge.status == "failed": return stripe_payment_failed(payment) raise StripeUpdateUnexpected( "Charge object is not paid, refunded or failed")