def handle_payment_intent_succeeded_event( stripe_payment_intent: stripe.PaymentIntent, payment_intent: PaymentIntent) -> None: payment_intent.status = PaymentIntent.SUCCEEDED payment_intent.save() metadata: Dict[str, Any] = stripe_payment_intent.metadata assert payment_intent.customer.realm is not None user_id = metadata.get("user_id") assert user_id is not None user = get_active_user_profile_by_id_in_realm( user_id, payment_intent.customer.realm) description = "" for charge in stripe_payment_intent.charges: description = f"Payment (Card ending in {charge.payment_method_details.card.last4})" break stripe.InvoiceItem.create( amount=stripe_payment_intent.amount * -1, currency="usd", customer=stripe_payment_intent.customer, description=description, discountable=False, ) try: ensure_realm_does_not_have_active_plan(user.realm) except UpgradeWithExistingPlanError as e: stripe_invoice = stripe.Invoice.create( auto_advance=True, collection_method="charge_automatically", customer=stripe_payment_intent.customer, days_until_due=None, statement_descriptor="Zulip Cloud Standard Credit", ) stripe.Invoice.finalize_invoice(stripe_invoice) raise e process_initial_upgrade( user, int(metadata["licenses"]), metadata["license_management"] == "automatic", int(metadata["billing_schedule"]), True, False, )
def handle_payment_intent_payment_failed_event( stripe_payment_intent: stripe.PaymentIntent, payment_intent: Event) -> None: payment_intent.status = PaymentIntent.get_status_integer_from_status_text( stripe_payment_intent.status) billing_logger.info( "Stripe payment intent failed: %s %s %s %s", payment_intent.customer.realm.string_id, stripe_payment_intent.last_payment_error.get("type"), stripe_payment_intent.last_payment_error.get("code"), stripe_payment_intent.last_payment_error.get("param"), ) payment_intent.last_payment_error = { "description": stripe_payment_intent.last_payment_error.get("type"), } payment_intent.last_payment_error[ "message"] = stripe_payment_intent.last_payment_error.get("message") payment_intent.save(update_fields=["status", "last_payment_error"])
def setup_upgrade_checkout_session_and_payment_intent( user: UserProfile, seat_count: int, licenses: int, license_management: str, billing_schedule: int, billing_modality: str, onboarding: bool, ) -> stripe.checkout.Session: customer = update_or_create_stripe_customer(user) assert customer is not None # for mypy free_trial = is_free_trial_offer_enabled() _, _, _, price_per_license = compute_plan_parameters( CustomerPlan.STANDARD, license_management == "automatic", billing_schedule, customer.default_discount, free_trial, ) metadata = { "billing_modality": billing_modality, "billing_schedule": billing_schedule, "licenses": licenses, "license_management": license_management, "price_per_license": price_per_license, "seat_count": seat_count, "type": "upgrade", "user_email": user.delivery_email, "realm_id": user.realm.id, "realm_str": user.realm.string_id, "user_id": user.id, } if free_trial: if onboarding: session_type = Session.FREE_TRIAL_UPGRADE_FROM_ONBOARDING_PAGE else: session_type = Session.FREE_TRIAL_UPGRADE_FROM_BILLING_PAGE payment_intent = None else: session_type = Session.UPGRADE_FROM_BILLING_PAGE stripe_payment_intent = stripe.PaymentIntent.create( amount=price_per_license * licenses, currency="usd", customer=customer.stripe_customer_id, description= f"Upgrade to Zulip Cloud Standard, ${price_per_license/100} x {licenses}", receipt_email=user.delivery_email, confirm=False, statement_descriptor="Zulip Cloud Standard", metadata=metadata, ) payment_intent = PaymentIntent.objects.create( customer=customer, stripe_payment_intent_id=stripe_payment_intent.id, status=PaymentIntent.get_status_integer_from_status_text( stripe_payment_intent.status), ) stripe_session = stripe.checkout.Session.create( cancel_url=f"{user.realm.uri}/upgrade/", customer=customer.stripe_customer_id, mode="setup", payment_method_types=["card"], metadata=metadata, setup_intent_data={"metadata": metadata}, success_url= f"{user.realm.uri}/billing/event_status?stripe_session_id={{CHECKOUT_SESSION_ID}}", ) session = Session.objects.create(customer=customer, stripe_session_id=stripe_session.id, type=session_type) if payment_intent is not None: session.payment_intent = payment_intent session.save(update_fields=["payment_intent"]) return stripe_session