通过按比例分配 Stripe Python 升级和降级订阅

问题描述 投票:0回答:0

我正在开发一个使用 Stripe API 来管理订阅的 Python 应用程序。我提供多种不同价位的订阅计划,特别是 42 美元和 70 美元。

我正在尝试使用 Stripe 的 Python 库实现以下场景,并正在寻求有关如何继续的帮助。

场景一:订阅升级/降级

当用户想要更改他们的订阅(从 42 美元计划升级到 70 美元计划或从 70 美元计划降级到 42 美元计划)时,我想计算他们应该收取的金额如下:

新计划价格 - 旧计划价格 - 根据他们已经使用该应用程序的时间按比例分配的金额。 我希望通过 Stripe Checkout 会话进行此交易。

场景2:计费周期维护

无论用户升级还是降级他们的套餐,我希望他们的计费周期保持不变。因此,例如,如果用户在 2023 年 3 月 8 日 12:45 更改订阅,他们将立即支付按比例分配的差额,然后在 2023 年 3 月 9 日 12:45,他们将被收取全价他们的新订阅计划。

任何有关如何实施这些场景的指导将不胜感激。请注意,我专门寻找使用 Stripe Python 库的解决方案。

这是我现有的一些代码,可以让您了解我当前的方法:

@stripe_blueprint.route('/stripe/<string:product_id>/<string:recurring_type>', methods=['POST', 'GET'])
def stripe_payment(product_id, recurring_type):
    global sidebar_links
    user = None
    subscription_id = None
    expiry_date_timestamp_int = None

    # product_types = ['plan', 'addon', 'one_time','top_up']
    if current_user.is_authenticated:
        user = load_user_or_sub(current_user)
        # if the user does not have a stripe customer id, create stripe customer
        customer_id = stripe.Customer.retrieve(user.stripe_customer_id)

        if customer_id.get('deleted') or not user.stripe_customer_id:
            logger.info(f'User {user.id} has a deleted stripe customer id or does not have a stripe customer id, creating one')
            create_stripe_customer(user)

    if PRODUCTS_JSON.get(product_id) is None:
        return abort(404)

    if recurring_type == 'monthly':
        price_id = PRODUCTS_JSON[product_id]['month']['id']

    elif recurring_type == "yearly":
        price_id = PRODUCTS_JSON[product_id]['year']['id']
    else:
        return abort(404)

    try:
        # Retrieve and update the subscription only if the user is authenticated and they have a valid subscription
        if user and user.stripe_subscription_id:
            subscription = stripe.Subscription.retrieve(user.stripe_subscription_id)
            if subscription['status'] != 'canceled':

                # Assuming subscription_expiry_date is the string representation of your user's subscription expiry date
                subscription_expiry_date_str = user.subscription_expired_date
                # subscription_expiry_date_str = "03/08/2023 12:40"

                # Convert the string to a datetime object
                expiry_date_obj = datetime.strptime(subscription_expiry_date_str, "%d/%m/%Y %H:%M")
                # Convert the datetime object to a Unix timestamp
                expiry_date_timestamp = time.mktime(expiry_date_obj.timetuple())

                # Convert the Unix timestamp to an integer
                expiry_date_timestamp_int = int(expiry_date_timestamp)


        checkout_session = checkout.Session.create(
            line_items=[{"price": price_id, "quantity": 1}],
            client_reference_id=user.user_hash_identifier if user else None,
            payment_method_types=['card'],
            mode="subscription",
            billing_address_collection='required',
            allow_promotion_codes=True,
            customer=user.stripe_customer_id if user else None,
            metadata={'recurring_type': recurring_type},
            subscription_data={"billing_cycle_anchor": expiry_date_timestamp_int, "proration_behavior": "create_prorations"} if expiry_date_timestamp_int else None,
            locale='auto',
            success_url=url_for('stripe_blueprint.order_success', _external=True) + '?session_id={CHECKOUT_SESSION_ID}',
            cancel_url=url_for('stripe_blueprint.order_cancel', _external=True),
            )
    except Exception as e:
        logger.error(f'User {user.id} failed to pay for {id} due to {e}')
        return str(e)

    return redirect(checkout_session.url, code=303)
python flask stripe-payments integration
© www.soinside.com 2019 - 2024. All rights reserved.