Stripe Checkout Session高级集成:自定义税率与优惠券应用

花韻仙語
发布: 2025-12-14 16:15:23
原创
930人浏览过

Stripe Checkout Session高级集成:自定义税率与优惠券应用

本教程详细指导如何在stripe checkout session中集成自定义税率和折扣。文章将深入解析stripe api中`taxrate`和`coupon`对象的创建与应用,纠正常见的参数配置错误,并提供包含动态税费和优惠券处理的完整代码示例。旨在帮助开发者构建功能完善、符合业务需求的stripe支付流程。

1. 理解Stripe Checkout Session与集成需求

Stripe Checkout Session是Stripe提供的一种快速、安全地收集客户支付信息的方式。在构建电子商务应用时,往往需要根据业务逻辑动态应用税费和折扣。这要求开发者能够正确地创建和管理Stripe中的TaxRate(税率)和Coupon(优惠券)对象,并将其关联到Checkout Session。

原始代码尝试集成这些功能,但在discounts参数的格式上出现了错误,导致InvalidRequestError。本教程将纠正这些错误并提供一个健壮的集成方案。

2. 集成自定义税率(Tax Rates)

Stripe允许您创建自定义税率,并将其应用于Checkout Session中的商品。这些税率可以是包含性的(价格已含税)或排他性的(税费额外计算)。

2.1 创建Stripe TaxRate对象

在将税率应用于Checkout Session之前,您需要先在Stripe中创建TaxRate对象。这些对象定义了税率的百分比、显示名称、描述和管辖区域等信息。在实际应用中,通常会持久化这些税率(例如,存储在数据库中,并仅在需要时更新Stripe),而不是每次都动态创建。

import stripe

# 假设您的Order模型关联了Tax模型,Tax模型包含name, rate等字段
# order.tax.all() 返回一个Tax对象列表

tax_rate_ids = []
for tax_obj in order.tax.all():
    # 最佳实践:检查Stripe中是否已存在同名或同配置的TaxRate,避免重复创建
    # 简单示例中,我们假设每次都创建,但生产环境应优化此逻辑
    try:
        # 尝试查找已存在的税率,如果您的Tax模型中存储了Stripe TaxRate ID
        # 例如:if tax_obj.stripe_tax_rate_id: tax_rate_ids.append(tax_obj.stripe_tax_rate_id)
        # 否则,进行创建
        tax_rate = stripe.TaxRate.create(
            display_name=tax_obj.name,
            description=f"{tax_obj.name} ({tax_obj.rate}%)",
            percentage=tax_obj.rate, # 假设tax_obj.rate是百分比数值,如5.0代表5%
            inclusive=False,         # 设置为True表示价格已含税,False表示税费额外计算
            jurisdiction="US",       # 根据实际业务设置管辖区域,例如 "US", "EU", "CA" 等
        )
        tax_rate_ids.append(tax_rate.id)
    except stripe.error.StripeError as e:
        # 处理Stripe API错误
        print(f"Error creating tax rate: {e}")
        # 根据错误类型决定是否继续或抛出异常
登录后复制

2.2 将TaxRate应用于Checkout Session

创建TaxRate后,您可以通过两种主要方式将其应用于Checkout Session:

  1. 应用于单个line_item(推荐): 如果您的订单包含多个商品,且每个商品可能适用不同的税率,或者您希望更精细地控制税费,这是首选方法。
  2. 应用于整个Session: 如果所有商品都适用相同的税率,或者您只有一个代表整个订单的line_item,可以在Session级别应用。

在用户提供的代码中,只有一个line_item代表整个订单,因此将其应用于line_item是合适的。

美图AI开放平台
美图AI开放平台

美图推出的AI人脸图像处理平台

美图AI开放平台 111
查看详情 美图AI开放平台
# ... (承接上述 tax_rate_ids 的创建) ...

line_items_data = [
    {
        'price_data': {
            'currency': 'usd',
            'unit_amount': order.get_total_cost() * 100, # Stripe金额以最小单位(美分)计
            'product_data': {
                'name': order.__str__(),
            },
        },
        'quantity': 1,
        'tax_rates': tax_rate_ids, # 将税率ID列表添加到line_item中
    },
]

# 如果选择应用于整个Session(不推荐与line_item同时使用相同的税率)
# session = stripe.checkout.Session.create(
#     # ...
#     line_items=line_items_data,
#     tax_rates=tax_rate_ids, # 在Session级别应用税率
# )
登录后复制

3. 集成自定义折扣(Discounts/Coupons)

Stripe通过Coupon(优惠券)对象来管理折扣。您可以创建固定金额折扣或百分比折扣的优惠券,并将其应用于Checkout Session。

3.1 创建Stripe Coupon对象

与税率类似,优惠券也应该在Stripe中创建。在生产环境中,通常会有一个管理后台来创建和管理这些优惠券,并将其Stripe ID存储在您的数据库中。

import stripe

# 假设您的Order模型关联了Discount模型,Discount模型包含amount, name等字段
# order.discount.all() 返回一个Discount对象列表

discount_items = []
for discount_obj in order.discount.all():
    # 最佳实践:检查Stripe中是否已存在同名或同配置的Coupon,避免重复创建
    # 简单示例中,我们假设每次都创建,但生产环境应优化此逻辑
    try:
        # 创建一个Stripe Coupon
        # amount_off 是固定金额折扣,以最小单位(美分)计
        # percent_off 是百分比折扣,与amount_off互斥
        coupon = stripe.Coupon.create(
            amount_off=discount_obj.amount * 100, # 假设discount_obj.amount是美元金额
            duration='once', # 'once', 'repeating', 'forever'
            currency='usd',
            name=discount_obj.name,
        )
        discount_items.append({"coupon": coupon.id}) # 正确的格式是 {"coupon": "coupon_id"}
    except stripe.error.StripeError as e:
        # 处理Stripe API错误
        print(f"Error creating coupon: {e}")
        # 根据错误类型决定是否继续或抛出异常
登录后复制

3.2 将Coupon应用于Checkout Session

将优惠券应用于Checkout Session需要使用discounts参数。注意:原始代码中的discounts=[{"discounts": '{{COUPON_ID}}'}]是错误的,导致了InvalidRequestError。 正确的格式是一个包含字典的列表,每个字典都应该有一个"coupon"键,其值为优惠券的ID。

# ... (承接上述 discount_items 的创建) ...

session = stripe.checkout.Session.create(
    # ... 其他参数 ...
    discounts=discount_items, # 正确的优惠券应用方式
)
登录后复制

4. 完整集成示例代码

以下是结合了税率和折扣的优化后的完整代码示例,基于您提供的原始结构进行改进:

import stripe
from django.views import View
from django.http import JsonResponse
from .models import Order # 假设您的Order模型在此处定义

# 请替换为您的Stripe Secret Key
stripe.api_key = 'sk_test_YOUR_STRIPE_SECRET_KEY' # 务必使用环境变量或配置文件管理密钥

class CreateCheckoutSessionOrderView(View):
    def get(self, request, *args, **kwargs):
        order_id = self.kwargs["order_id"]
        DOMAIN: str = 'http://127.0.0.1:8000' # 生产环境请使用您的实际域名

        try:
            order = Order.objects.get(id=order_id)
        except Order.DoesNotExist:
            return JsonResponse({'error': 'Order not found'}, status=404)

        # --- 1. 处理自定义税率 ---
        tax_rate_ids = []
        for tax in order.tax.all(): # 假设order关联了多个Tax对象
            try:
                # 在生产环境中,您应该查询数据库或Stripe来获取已存在的TaxRate ID
                # 避免每次都创建新的TaxRate
                tax_rate = stripe.TaxRate.create(
                    display_name=tax.name,
                    description=f"{tax.name} ({tax.rate}%)",
                    percentage=tax.rate, # 假设tax.rate是百分比,如5.0代表5%
                    jurisdiction="US",   # 根据实际业务设置
                    inclusive=False,     # 设为True则价格含税,False则税费额外计算
                    active=True,         # 确保税率是激活状态
                )
                tax_rate_ids.append(tax_rate.id)
            except stripe.error.StripeError as e:
                print(f"Error creating Stripe TaxRate for {tax.name}: {e}")
                # 根据业务需求处理错误,例如跳过此税率或返回错误

        # --- 2. 处理自定义折扣 ---
        discounts_list = []
        for discount in order.discount.all(): # 假设order关联了多个Discount对象
            try:
                # 在生产环境中,您应该查询数据库或Stripe来获取已存在的Coupon ID
                # 避免每次都创建新的Coupon
                coupon = stripe.Coupon.create(
                    amount_off=discount.amount * 100, # amount_off以最小货币单位(美分)计
                    duration='once', # 'once', 'repeating', 'forever'
                    currency='usd',
                    name=discount.name,
                )
                discounts_list.append({"coupon": coupon.id}) # 正确的折扣参数格式
            except stripe.error.StripeError as e:
                print(f"Error creating Stripe Coupon for {discount.name}: {e}")
                # 根据业务需求处理错误

        # --- 3. 创建Stripe Checkout Session ---
        try:
            session = stripe.checkout.Session.create(
                payment_method_types=['card'],
                line_items=[
                    {
                        'price_data': {
                            'currency': 'usd',
                            'unit_amount': order.get_total_cost() * 100, # 总金额以最小货币单位计
                            'product_data': {
                                'name': order.__str__(),
                                'images': [order.get_thumbnail_url()] if hasattr(order, 'get_thumbnail_url') else [], # 可选:添加商品图片
                            },
                        },
                        'quantity': 1,
                        'tax_rates': tax_rate_ids, # 将收集到的税率ID应用于line_item
                    },
                ],
                payment_intent_data={
                    'metadata': {
                        'order_id': order.id,
                    },
                },
                mode='payment',
                success_url=DOMAIN + '/success/?session_id={CHECKOUT_SESSION_ID}', # 推荐添加session_id参数
                cancel_url=DOMAIN + '/cancel/',
                discounts=discounts_list, # 将收集到的折扣应用于Session
            )
            return JsonResponse({'id': session.id})

        except stripe.error.StripeError as e:
            # 捕获Stripe API可能抛出的所有错误
            print(f"Error creating Stripe Checkout Session: {e}")
            return JsonResponse({'error': str(e)}, status=500)
        except Exception as e:
            # 捕获其他未知错误
            print(f"An unexpected error occurred: {e}")
            return JsonResponse({'error': 'An unexpected error occurred'}, status=500)
登录后复制

5. 注意事项与最佳实践

  1. Stripe API Key管理: 永远不要将您的Stripe Secret Key硬编码到代码中。使用环境变量、Django设置文件或专门的密钥管理服务来安全地存储和访问它。
  2. Stripe对象持久化: 在生产环境中,频繁地创建TaxRate和Coupon对象是不高效且不必要的。
    • 税率: 通常税率是相对稳定的。您可以在Stripe仪表板中创建它们一次,然后将它们的Stripe ID存储在您的数据库中(例如,在您的Tax模型中添加stripe_tax_rate_id字段)。在创建Checkout Session时,直接从数据库中检索这些ID。
    • 优惠券: 优惠券可能更具动态性。对于预设的优惠券,同样可以存储其Stripe ID。对于用户输入的促销码,您需要使用PromotionCode对象,它链接到Coupon。
  3. 错误处理: 务必捕获stripe.error.StripeError及其子类,以便优雅地处理Stripe API调用失败的情况,并向用户提供有意义的反馈。
  4. 金额单位: Stripe API要求所有金额都以最小货单位(例如,美元为美分,欧元为欧分)表示。请确保在传递unit_amount和amount_off时进行正确的转换(例如,乘以100)。
  5. success_url中的session_id: 在success_url中添加?session_id={CHECKOUT_SESSION_ID}是一个很好的实践。当客户成功完成支付后,Stripe会将实际的Session ID填充到此URL中,您的成功页面可以使用此ID来检索Session详情并验证支付状态。
  6. 测试: 在将代码部署到生产环境之前,务必在Stripe的测试模式下进行彻底测试,以确保税费和折扣的计算和应用符合预期。
  7. Webhook: 对于更复杂的订单流程(例如,需要更新订单状态、发送确认邮件等),强烈建议设置Stripe Webhook来监听支付事件(如checkout.session.completed)。

总结

通过本教程,您应该已经掌握了在Stripe Checkout Session中正确集成自定义税率和折扣的方法。关键在于理解Stripe TaxRate和Coupon对象的创建,以及在stripe.checkout.Session.create方法中line_items的tax_rates参数和discounts参数的正确格式。遵循最佳实践,特别是关于Stripe对象持久化和错误处理,将有助于构建一个稳定、高效的支付系统。

以上就是Stripe Checkout Session高级集成:自定义税率与优惠券应用的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号