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


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是合适的。

Veo Veo

Google 最新发布的 AI 视频生成模型

Veo 567 查看详情 Veo
# ... (承接上述 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高级集成:自定义税率与优惠券应用的详细内容,更多请关注其它相关文章!


# json  # 天猫seo入口  # 正在播放seo探花  # 陕西整站网站推广工具  # 抛出  # 是一个  # 您可以  # 数据库中  # 子类  # 多个  # 每次都  # 自定义  # 应用于  # 您的  #   # js  # go  # 编码  # app  # session  # ai  # 环境变量  # 配置文件  # django  # api调用  # cos  # re  # 宁夏外贸营销推广  # 沾益区网站建设内容  # 健康推广网站  # 网站建设用户登录源码  # 金华双十一推广营销方案  # 安顺商城网站推广方案  # 泰州网站优化推荐 


相关栏目: 【 Google疑问12 】 【 Facebook疑问10 】 【 优化推广96088 】 【 技术知识133117 】 【 IDC资讯59369 】 【 网络运营7196 】 【 IT资讯61894


相关推荐: DeepSeek超全面指南:入门必看  QQ网页版官方账号登录入口 QQ网页版网页版入口快速导航  视频号视频怎么免费保存到相册?保存到相册需要注意什么?  《星露谷物语》克林特好感度事件介绍  《桃源记2》资源采集攻略  4399造梦西游3无敌版_4399游戏入口  如何在CSS中使用absolute实现登录弹窗居中_transform translate结合  Win10共享文件夹设置方法 Win10局域网文件共享全攻略【教程】  Python csv 模块处理非字符串数据:列表写入 CSV 文件的机制解析  J*aScript装饰器_元编程实战  鸣潮历史学家灯塔位置一览  5G和6G的连接密度有什么区别 6G每平方公里能连接多少设备  汽水音乐网页版登录 汽水音乐网页端官方入口  qq音乐官方网站入口_qq音乐在线听歌网页版链接  php如何实现多域名共享session_php存储session到redis与跨域读取配置  PyEZ 配置提交中 RpcTimeoutError 的健壮性处理策略  J*aScript事件处理:优化键盘输入与表单提交的实践指南  魔法祈幻界兑换码礼包大全  如何查找哪个composer包引入了特定的依赖?  抖音官网入口快速访问 抖音网页版账号注册解析  深入理解Python对象引用与链表属性赋值  J*aScript文本高亮功能优化:解决多词匹配错误与精确分割策略  《鹿路通》退余额方法  小米civi如何设置锁屏时间  Python定时发送QQ消息  解决Flex容器横向滚动内容截断与偏移问题  AO3中文入口稳定分享_AO3官网HTTPS看文详解  小红书网页版怎么进 小红书网页版通用入口  Dash应用多值文本输入处理与类型转换教程  263企业邮箱如何设置邮件转发功能  小红书如何引流到私信?引流到私信有用吗?  《一起考教师》账号注销方法  RxJS中如何高效地在一个函数内处理和合并多个数据集合  qq邮箱格式填写示例 qq邮箱标准填写规范  抖音如何解除|直播|权限绑定_抖音关闭并解绑|直播|功能的方法  网页版网易云音乐入口_网易云音乐在线官网登录  iPhone 13 Pro Max如何设置桌面小组件_iPhone 13 Pro Max小组件添加指南  《宝可梦大集结》S4冠军之路开始时间介绍  《律学法考》查看学习数据方法  J*a实现任务清单管理_集合框架综合入门练手  谷歌浏览器官网地址整理_谷歌浏览器新版直连2026稳定访问  可米酷漫画在线阅读入口_ 可米酷漫画官网直达链接  如何在解析前预检查XML文件的完整性? 比如检查文件大小或特定结束标签  支付宝登录刷脸不是本人如何解决  大众点评了却看不到是怎么回事  红手指专业版app注册教程  Pandas中基于动态偏移量实现DataFrame列值位移的策略  192.168.1.1路由器后台入口 192.168.1.1默认登录入口  《红果免费短剧》下载观看方法  电脑从睡眠中被自动唤醒怎么办_Windows唤醒源事件查看与禁用【解决】 

 2025-12-14

了解您产品搜索量及市场趋势,制定营销计划

同行竞争及网站分析保障您的广告效果

点击免费数据支持

提交您的需求,1小时内享受我们的专业解答。

运城市盐湖区信雨科技有限公司


运城市盐湖区信雨科技有限公司

运城市盐湖区信雨科技有限公司是一家深耕海外推广领域十年的专业服务商,作为谷歌推广与Facebook广告全球合作伙伴,聚焦外贸企业出海痛点,以数字化营销为核心,提供一站式海外营销解决方案。公司凭借十年行业沉淀与平台官方资源加持,打破传统外贸获客壁垒,助力企业高效开拓全球市场,成为中小企业出海的可靠合作伙伴。

 8156699

 13765294890

 8156699@qq.com

Notice

We and selected third parties use cookies or similar technologies for technical purposes and, with your consent, for other purposes as specified in the cookie policy.
You can consent to the use of such technologies by closing this notice, by interacting with any link or button outside of this notice or by continuing to browse otherwise.