Skip to main content

概述

当请求失败时,Dodo Payments API 会返回 HTTP 状态码和一个说明错误的 JSON 正文。使用此页面查找错误原因及其解决方法。 每个错误响应都包含:
  • 一个用于表示错误大致类别的 HTTP 状态码。
  • 一个用于标识确切错误的 code,例如 UNSUPPORTED_COUNTRY。
  • 一个以通俗语言解释错误的 message。例如,对于内部服务器错误,message 可能是 null。
应根据 code(而不是 message)分支处理错误。根据错误原因,同一个代码可能返回多条消息。 使用这些错误代码来:
  • 调试集成问题。
  • 在应用中正确处理错误。
  • 向客户显示有意义的反馈。
  • 确保支付处理可靠。
这些是 API 和业务逻辑 错误。对于失败支付返回的 卡片拒付原因(例如 INSUFFICIENT_FUNDS 或 CARD_DECLINED),请参阅 Transaction Failures 参考文档。

标准 API 错误代码

API 使用以下 HTTP 状态码表示错误:

错误响应格式

错误响应正文包含两个字段:code 和 message:

错误代码参考

以下错误代码按其涉及的 API 区域分组。每个条目列出触发错误的条件以及 API 返回的消息。{id} 等占位符表示由 API 填充的值。

身份验证与账户

  • UNAUTHORIZED
    • 触发条件: 请求没有 API 密钥、API 密钥无效(HTTP 401),或 API 密钥缺少该操作所需的角色(HTTP 403)
    • 消息: 您无权执行此操作
  • MERCHANT_NOT_LIVE
    • 触发条件: 对尚未启用实时支付的业务发起实时模式请求(HTTP 403)。这包括仅使用过测试模式的业务,以及由于 验证 尚未完成而尚未启用实时支付的业务。测试模式请求不受影响。
    • 消息: 商户尚未启用实时支付
  • BUSINESS_ARCHIVED
    • 触发条件: 面向客户的请求针对已归档业务(HTTP 403)。这包括结账、支付链接、店面、Customer Portal 和许可证密钥激活。
    • 消息: 此业务已归档,不再接受请求

支付与结账

  • CHECKOUT_SESSION_CONSUMED
    • 触发条件: 结账会话已经生成支付(HTTP 403)。请改为创建新的结账会话。
    • 消息: 使用给定结账会话的支付已生成。
  • MANUAL_RETRY_ALREADY_PAID
    • 触发条件: 对已成功支付的续订发票执行 手动重试。再次发送会导致向客户重复扣款。
    • 消息: 此发票的支付已成功
  • MANUAL_RETRY_HARD_DECLINE
    • 触发条件: 手动重试时,发票的最新失败属于硬拒付,或没有已分类的错误代码。再次使用同一张卡扣款无法成功,请改为更新支付方式。
    • 消息: 此发票的最后一次失败是硬拒付,因此重试无法成功 (或) 此发票的最后一次失败无法分类,因此无法重试
  • MANUAL_RETRY_IN_FLIGHT
    • 触发条件: 手动重试时,发票上的支付处于 processing 状态,或尚无记录状态。请等待该支付的结果,而不要再次发送。
    • 消息: 此发票的支付仍在处理中
  • MANUAL_RETRY_LIMIT_REACHED
    • 触发条件: 发票的 3 次发送机会均已用尽,或冷却时间尚未结束时执行手动重试(HTTP 429)。第二次发送需在第一次发送后等待 1 小时,第三次发送需在第二次发送后等待 3 小时。正文仅包含 code 和 message。要查找下次允许发送的时间,请从 GET /payments/{payment_id}/retry 读取 retry_available_at。
    • 消息: 此发票的所有手动重试次数均已用尽 (或) 此发票暂时无法立即重试
  • NO_ELIGIBLE_PAYMENT_METHODS
    • 触发条件: 过滤后没有可用于支付的支付方式(HTTP 422)
    • 消息: 未找到符合条件的支付方式
  • PAYMENT_NOT_PERMITTED
    • 触发条件: 位于商户 阻止列表 中的客户发起结账或支付尝试(HTTP 403)。代码和消息会刻意省略具体原因。
    • 消息: 此支付无法处理。
  • PAYMENT_NOT_RETRYABLE
    • 触发条件: 对不适用手动重试的支付执行手动重试。支付没有发票、发票不是未结的订阅续订发票、发票上的支付尚未失败、订阅未配置周期性计费(例如按需订阅),或客户位于阻止列表中。
    • 消息: 根据原因而异,例如:只能重试订阅续订支付
  • PAYMENT_NOT_SUCCEEDED
    • 触发条件: 尝试退款或处理尚未成功的支付
    • 消息: 提供的支付尚未成功
  • PREVIOUS_PAYMENT_PENDING
    • 触发条件: 上一次支付处于非终止状态时尝试创建扣款。当发票上的最新支付既不是 failed,也不在处理中时执行 手动重试 也会返回此错误,例如 requires_customer_action 或 cancelled。
    • 消息: 上一次支付尚未成功,无法创建新的扣款 (或) 此发票最近一次支付尚未失败
  • UNSUCCESSFUL_PAYMENT_ID
    • 触发条件: 支付 ID 指向尚未成功的支付
    • 消息: Payment ID 的状态不成功。

连接器与 BYOP

这些错误与商户自有支付连接器(Bring Your Own Processor,或 BYOP)有关。
  • BYOP_CONNECTOR_DISABLED
    • 触发条件: 更新通过已禁用 BYOP 连接器路由的订阅的支付方式。Dodo Payments 不会回退到自己的连接器,因此请先重新启用该连接器。
    • 消息: 此订阅通过商户自有的 BYOP 连接器路由,而该连接器当前已禁用
  • BYOP_CUSTOM_INVOICE_ADDRESS_MISSING
    • 触发条件: 通过商户连接器(BYOP)路由的支付没有自定义发票地址
    • 消息: 通过商户连接器路由支付时必须提供 BYOP 自定义发票地址
  • CONNECTOR_LABEL_ALREADY_EXISTS
    • 触发条件: 创建连接器时使用了已存在的标签
    • 消息: 此标签的连接器已存在。请选择其他标签。

退款

  • EXISTING_REFUND_REQUEST_PROCESSING
    • 触发条件: 之前的退款请求仍在处理中
    • 消息: 状态为 “Pending” 的退款请求仍在处理中
  • LINE_ITEM_FULLY_REFUNDED
    • 触发条件: 尝试退还已全额退款的行项目
    • 消息: 行项目 {id} 已全额退款,无法继续退款。
  • LINE_ITEM_NOT_FOUND
    • 触发条件: 项目 ID 不属于所引用的支付
    • 消息: 在支付中找不到行项目 {id}
  • LINE_ITEM_PRORATED
    • 触发条件: 尝试对按比例计费的行项目进行退款或更新
    • 消息: 行项目 {id} 无法退款,因为它是按比例计费的
  • LINE_ITEM_REFUND_AMOUNT_TOO_HIGH
    • 触发条件: 包含税费的退款金额高于已支付金额
    • 消息: 行项目 {id} 请求的含税退款金额为 {amount},高于已支付金额 {amount}
  • LINE_ITEM_REFUND_AMOUNT_TOO_LOW
    • 触发条件: 退款金额低于最低阈值
    • 消息: 行项目 {id} 请求的退款金额为 {amount},金额过低
  • NOTHING_TO_REFUND
    • 触发条件: 没有剩余可退款金额,因为所有正数行项目均已全额退款
    • 消息: 没有剩余可退款金额。所有正数行项目均已全额退款。
  • PARTIAL_REFUND_NOT_ALLOWED
    • 触发条件: 尝试对仅支持全额退款的支付方式进行部分退款
    • 消息: 此支付方式不允许部分退款
  • PAYMENT_ALREADY_REFUNDED
    • 触发条件: 重复退款
    • 消息: 此支付已退款
  • PAYMENT_HAS_BEEN_REFUNDED
    • 触发条件: 支付已全额退款
    • 消息: Payment ID 已全额退款。
  • REFUND_AMOUNT_EXCEEDS_PAID_AMOUNT
    • 触发条件: 总退款金额高于已支付金额
    • 消息: 计算出的退款金额大于已支付金额
  • REFUND_WINDOW_EXPIRED
    • 触发条件: 在允许的退款期限之外请求退款
    • 消息: 支付创建 {days} 天后无法发起退款。请联系 support@dodopayments.com。
  • ZERO_AMOUNT_PAYMENT_REFUND_NOT_ALLOWED
    • 触发条件: 尝试退还金额为零的支付
    • 消息: 无法退还货币金额为零的支付

订阅与附加项

  • ADDONS_IN_USAGE_BASED_BILLING_NOT_SUPPORTED
    • 触发条件: 尝试向基于用量计费的订阅添加附加项
    • 消息: 基于用量计费不支持订阅中的附加项
  • ADDONS_NOT_ALLOWED_FOR_ON_DEMAND
    • 触发条件: 尝试向按需订阅添加附加项
    • 消息: 按需订阅不允许附加项
  • CANCEL_SCHEDULED_PLAN_CHANGE_FOR_CUSTOMER_PORTAL_DISABLED
    • 触发条件: Customer Portal 尝试取消计划中的套餐变更,但业务已禁用此操作
    • 消息: Customer Portal 已禁用取消计划中的套餐变更。
  • CHARGE_NOT_ALLOWED_FOR_SCHEDULED_CANCELLATION
    • 触发条件: 尝试向计划取消的订阅收费
    • 消息: 订阅已计划取消
  • CUSTOMER_HAS_EXISTING_SUBSCRIPTION
    • 触发条件: 为已有订阅的客户创建订阅,而业务不允许每位客户拥有多个订阅
    • 消息: 客户 {id} 已有订阅。如需允许每位客户拥有多个订阅,请更改业务设置
  • DO_NOT_BILL_NOT_ALLOWED_IN_CUSTOMER_PORTAL
    • 触发条件: Customer Portal 套餐变更使用 do_not_bill 按比例计费模式
    • 消息: Customer Portal 不允许使用 do_not_bill 按比例计费模式
  • DUPLICATE_ADDON_IDS_IN_REQUEST
    • 触发条件: 同一个 addon_id 在请求中出现多次
    • 消息: 不允许重复的附加项 ID
  • INACTIVE_SUBSCRIPTION_PLAN_CHANGE_NOT_SUPPORTED
    • 触发条件: 对非活跃订阅进行套餐变更
    • 消息: 不支持更改非活跃订阅的套餐
  • INVALID_PRORATION_MODE_WITH_NEXT_BILLING_DATE
    • 触发条件: 将除 full_immediately 之外的按比例计费模式与 effective_at: next_billing_date 搭配使用
    • 消息: effective_at: next_billing_date 仅允许使用 full_immediately 按比例计费模式
  • MISSING_ADDON_IDS
    • 触发条件: addon_id 列表为空或包含未知 ID
    • 消息: 一个或多个产品 ID 不存在:{id}
  • ON_DEMAND_PLAN_CHANGE_NOT_SUPPORTED
    • 触发条件: 对按需订阅进行套餐变更
    • 消息: 不支持更改按需订阅的套餐
  • ON_DEMAND_USAGE_BASED_BILLING_NOT_SUPPORTED
    • 触发条件: 尝试将按需订阅与基于用量的计费结合使用
    • 消息: 基于用量计费不支持按需订阅
  • ONE_TIME_PRODUCTS_NOT_ALLOWED_FOR_ON_DEMAND
    • 触发条件: 向按需订阅添加一次性产品
    • 消息: 按需订阅不允许一次性产品
  • PENDING_PLAN_CHANGE_EXISTS
    • 触发条件: 之前的套餐变更仍在等待支付时请求新的套餐变更
    • 消息: 此订阅已有待处理的套餐变更。请等待当前支付完成。
  • PLAN_CHANGE_FOR_CUSTOMER_PORTAL_DISABLED
    • 触发条件: 通过 Customer Portal 进行套餐变更,但业务已禁用此功能
    • 消息: Customer Portal 的订阅套餐变更已禁用。
  • PLAN_CHANGE_NOT_ALLOWED_FOR_SCHEDULED_CANCELLATION
    • 触发条件: 对计划取消的订阅进行套餐变更
    • 消息: 订阅已计划取消
  • SCHEDULE_PLAN_CHANGE_FOR_CUSTOMER_PORTAL_DISABLED
    • 触发条件: 通过 Customer Portal 安排套餐变更,但业务已禁用此功能
    • 消息: 此业务已禁用安排套餐变更。
  • SCHEDULED_PLAN_CHANGE_EXISTS
    • 触发条件: 创建计划中的套餐变更,但已有一个计划中的变更
    • 消息: 此订阅已有计划中的套餐变更。请先取消现有的计划变更,再创建新的变更。
  • SCHEDULED_PLAN_CHANGE_NOT_FOUND
    • 触发条件: 引用或取消不存在的计划中的套餐变更
    • 消息: 未找到此订阅的计划中的套餐变更。
  • SUBSCRIPTION_EXPIRED
    • 触发条件: 在订阅的 expires_at 日期之后为其计费
    • 消息: 订阅已过期,无法创建新的扣款
  • SUBSCRIPTION_HAS_NO_PAYMENT_METHOD
    • 触发条件: 对没有已保存支付方式以进行非现场扣款的订阅执行手动重试
    • 消息: 此订阅没有已保存的支付方式可用于扣款
  • SUBSCRIPTION_INACTIVE
    • 触发条件: 订阅状态不是 active
    • 消息: 订阅未处于活跃状态 (或) 此订阅不是实时订阅,因此无法安排取消
  • SUBSCRIPTION_NOT_ON_DEMAND
    • 触发条件: 对按固定周期计费的订阅执行按需操作
    • 消息: 订阅已不是按需订阅
  • SUBSCRIPTION_PAYMENT_RETRY_LIMIT_EXCEEDED
    • 触发条件: 订阅支付重试次数超过最大尝试次数
    • 消息: 此订阅已超过 10 次的最大重试限制

客户与阻止列表

  • CUSTOMER_ALREADY_BLOCKED
    • 触发条件: 阻止已在 阻止列表 中且没有剩余实时订阅需要取消的客户(HTTP 409)
    • 消息: 此客户已在阻止列表中
  • PORTAL_ACTION_NOT_PERMITTED
    • 触发条件: 被阻止的客户调用 Customer Portal 写入路由:取消、暂停、恢复、更改套餐或更新支付方式(HTTP 403)。读取路由仍然开放。代码和消息会刻意省略具体原因。
    • 消息: 此操作不可用。

产品、购物车与品牌

  • BRAND_ALREADY_ARCHIVED
    • 触发条件: 归档已归档的品牌
    • 消息: 品牌已归档
  • BRAND_ARCHIVED
    • 触发条件: 更新已归档的品牌、提交品牌进行验证,或将新产品、产品集合或订阅关联到该品牌
    • 消息: 品牌已归档 (或) 品牌已归档,无法更新 (或) 品牌已归档,无法提交验证
  • BRAND_ARCHIVE_TARGET_REQUIRED
    • 触发条件: 归档仍包含产品、实时订阅或产品集合且没有 move_products_to 目标的品牌
    • 消息: 品牌有 {count} 个产品。请将 move_products_to 设置为目标品牌,以重新关联这些产品。如果阻止归档的是实时订阅或产品集合,消息会改为说明相应内容。
  • BRAND_MISMATCH
    • 触发条件: 购物车商品属于不同品牌
    • 消息: 产品购物车中的所有商品都应属于同一品牌
  • BRAND_NOT_ENABLED
    • 触发条件: 品牌已禁用或不活跃
    • 消息: 提供的品牌未启用
  • BRAND_SUBMISSION_NOT_ENABLED
    • 触发条件: 品牌重新提交验证功能未启用
    • 消息: Brand verificatin resubmission is not enabled(按 API 返回的原文拼写)
  • CANNOT_ARCHIVE_PRIMARY_BRAND
    • 触发条件: 归档主品牌,其品牌 ID 就是业务 ID
    • 消息: 无法归档主品牌
  • FILE_IN_USE
    • 触发条件: 删除仍被活跃权益授予记录引用的数字产品文件
    • 消息: 数字文件仍被活跃授予记录引用
  • INVALID_BRAND_ARCHIVE_TARGET
    • 触发条件: move_products_to 指向正在归档的品牌、已归档品牌或其他业务的品牌
    • 消息: move_products_to 必须是此业务中未归档的品牌 (或) move_products_to 不能是正在归档的品牌
  • INVALID_SUGGESTED_PRICE
    • 触发条件: Pay What You Want 建议价格低于最低价格
    • 消息: 建议价格不能低于最低价格。对于 pay what you want,价格会被视为可接受的最低金额
  • LOCALIZED_PRICE_ALREADY_EXISTS
    • 触发条件: 此产品和国家或货币已存在本地化价格
    • 消息: 此产品和国家/货币已存在本地化价格
  • LOCALIZED_PRICE_DUPLICATES_BASE
    • 触发条件: 本地化价格与产品的基础货币或国家重复
    • 消息: 本地化价格与产品的基础货币/国家重复
  • LOCALIZED_PRICE_SHAPE_MISMATCH
    • 触发条件: 本地化价格结构与产品的 pricing_mode 不匹配
    • 消息: 本地化价格结构与产品的 pricing_mode 不匹配
  • MISSING_PRODUCT_INFORMATION
    • 触发条件: 产品存在,但缺少必需信息
    • 消息: 产品 {id} 存在,但其他必需信息缺失或无效
  • PAY_AS_YOU_WANT_AMOUNT_REQUIRED
    • 触发条件: Pay What You Want 产品缺少金额
    • 消息: pay as you want 产品必须提供金额
  • PRODUCT_CART_EMTPY
    • 触发条件: 提交空产品购物车
    • 消息: product_cart 为空(错误代码有意拼写为 EMTPY,以匹配 API 返回的确切值)
  • PRODUCT_COLLECTION_IS_DELETED
    • 触发条件: 操作已删除的产品集合
    • 消息: 无消息
  • PRODUCT_COLLECTION_MUST_HAVE_PRODUCTS
    • 触发条件: 从集合中移除最后一个产品,或移除最后一个包含产品的分组
    • 消息: 无法删除集合中的最后一个产品。请改为归档集合。 (或) 无法删除最后一个包含产品的分组。请改为归档集合。
  • PRODUCT_IS_DELETED
    • 触发条件: 产品已被删除
    • 消息: 无消息
  • PRODUCT_PRICING_MODE_REQUIRED
    • 触发条件: 在设置产品的 pricing_mode 之前添加本地化价格
    • 消息: 添加本地化价格前必须设置产品的 pricing_mode
  • SLUG_ALREADY_TAKEN
    • 触发条件: 请求的产品 slug 或短 URL 已被使用
    • 消息: Slug 已被占用
  • UNABLE_TO_EDIT_PRIMARY_BRAND
    • 触发条件: 尝试通过常规品牌 API 更新主品牌
    • 消息: 无法通过此 API 端点更新主品牌。

折扣

  • DISCOUNT_ALREADY_USED_ON_SUBSCRIPTION
    • 触发条件: 再次应用已用于此订阅的折扣
    • 消息: 此折扣已用于此订阅
  • DISCOUNT_CODE_ALREADY_EXISTS
    • 触发条件: 创建已存在的折扣代码
    • 消息: 折扣代码已存在
  • DISCOUNT_CODE_EXPIRED
    • 触发条件: 折扣代码已超过其 expires_at 日期
    • 消息: 折扣代码已过期
  • DISCOUNT_CODE_USAGE_LIMIT_EXCEEDED
    • 触发条件: 折扣代码的使用次数已达到 usage_limit
    • 消息: 使用限制不能小于 times_used (或) 折扣代码已达到使用限制
    • 注意: 终止性错误。代码已耗尽,请勿重试。
  • DISCOUNT_CONCURRENT_REDEMPTION
    • 触发条件: 同一代码的另一次兑换持有使用限制锁的时间过长(HTTP 503)
    • 消息: 折扣正在被并发兑换;请重试
    • 注意: 暂时性错误。代码可能仍有可用次数,因此可以安全重试。不要向客户显示为代码已耗尽。
  • DISCOUNT_CURRENCY_OPTION_INVALID
    • 触发条件: 创建或更新时 currency_options 无效
    • 消息: 固定金额折扣至少需要一个可解析默认值的货币选项 (或) 不允许重复的货币选项 (或) 只能将一个货币选项标记为默认选项
  • DISCOUNT_CUSTOMER_NOT_ELIGIBLE
    • 触发条件: 客户不符合代码的 customer_eligibility(first_time、existing,或不在 specific 代码的允许列表中)
    • 消息: 客户不符合此折扣代码的使用条件
  • DISCOUNT_MINIMUM_SUBTOTAL_NOT_MET
    • 触发条件: 购物车小计低于为结账货币配置的 minimum_subtotal
    • 消息: 购物车小计低于折扣要求的最低小计
  • DISCOUNT_NOT_YET_ACTIVE
    • 触发条件: 在代码的 starts_at 日期之前使用代码
    • 消息: 折扣代码尚未生效(starts_at 位于未来)
  • DISCOUNT_PER_CUSTOMER_USAGE_LIMIT_EXCEEDED
    • 触发条件: 客户已兑换代码 per_customer_usage_limit 次
    • 消息: 已超过此折扣代码的每位客户使用限制
  • DISCOUNT_NOT_APPLICABLE_TO_NEW_PRODUCT
    • 触发条件: 将套餐变更为现有折扣不适用的产品
    • 消息: 折扣不适用于新套餐的产品
  • DISCOUNT_NOT_AVAILABLE_FOR_ON_DEMAND
    • 触发条件: 将代码应用于按需订阅
    • 消息: 按需订阅不适用折扣券
  • DISCOUNT_NOT_AVAILABLE_FOR_PRODUCT
    • 触发条件: 将代码应用于其不涵盖的产品
    • 消息: 此产品不适用折扣券
  • INVALID_DISCOUNT_CODE
    • 触发条件: 代码不存在,或不适用于购物车中的任何产品
    • 消息: 折扣代码无效 (或) 折扣代码无法应用于购物车中的任何产品
  • INVALID_PERCENTAGE
    • 触发条件: 百分比高于 100%(10,000 个基点)
    • 消息: 百分比金额不能超过 10000 (或) 折扣代码金额不能超过 100%
  • UNSUPPORTED_DISCOUNT_TYPE
    • 触发条件: 使用了不受支持的折扣类型。percentage 和 flat 均受支持;不支持按单位金额折扣。
    • 消息: 仅支持百分比和固定金额折扣代码 (或) 目前仅支持百分比折扣代码

许可证密钥

  • ACTIVATION_LIMIT_LESS_THAN_CURRENT_AMOUNT
    • 触发条件: 许可证密钥的新激活限制低于当前实例数量
    • 消息: 新激活限制不能低于当前实例数
  • INACTIVE_LICENSE_KEY
    • 触发条件: 许可证密钥状态不是 active
    • 消息: 许可证密钥未激活
  • LICENSE_KEY_LIMIT_REACHED
    • 触发条件: 激活数量已达到激活限制
    • 消息: 已达到许可证密钥激活限制
  • LICENSE_KEY_NOT_FOUND
    • 触发条件: 实例 ID 或许可证密钥 ID 无效
    • 消息: 未找到许可证密钥实例,或该实例不属于此许可证密钥
  • NO_EXPIRY_ON_SUBSCRIPTION_LICENSE_KEYS
    • 触发条件: 尝试为基于订阅的许可证密钥设置到期日期
    • 消息: 无法为基于订阅的许可证密钥设置到期日期

基于用量的计费与计量器

  • DUPLICATE_METER_IDS_IN_REQUEST
    • 触发条件: 同一个计量器 ID 在请求中出现多次
    • 消息: 不允许重复的计量器 ID
  • INVALID_QUANTITY
    • 触发条件: 对采用基于用量定价的产品使用了非 1 的数量
    • 消息: 基于用量定价的产品只能使用数量 1
  • METER_IS_DELETED
    • 触发条件: 尝试使用已删除的计量器
    • 消息: 计量器已被删除
  • MISSING_METER_IDS
    • 触发条件: 计量器 ID 列表为空或包含无效 ID
    • 消息: 一个或多个计量器 ID 不存在:{id}

基于额度的计费

  • CREDIT_ENTITLEMENT_IS_DELETED
    • 触发条件: 操作已删除的额度权益
    • 消息: 额度权益已被删除
  • CREDIT_ENTITLEMENT_NAME_ALREADY_EXISTS
    • 触发条件: 创建名称已存在的额度权益
    • 消息: 此名称的额度权益已存在
  • OVERAGE_LIMIT_EXCEEDED
    • 触发条件: 用量或额度扣减将超过配置的超额限制
    • 消息: 已超过超额限制

钱包

  • INSUFFICIENT_WALLET_FUNDS
    • 触发条件: 钱包余额低于扣款金额
    • 消息: 钱包资金不足
  • NEGATIVE_BALANCE_ADJUSTMENT
    • 触发条件: 尝试使钱包余额变为负数
    • 消息: 不允许将钱包余额变为负数

货币、税费与地区

  • EXCHANGE_RATE_NOT_FOUND
    • 触发条件: 不存在该货币对的汇率
    • 消息: 未找到将 {currency} 转换为 {currency} 的汇率
  • INVALID_TAX_ID
    • 触发条件: VAT、GST 或 TIN 验证失败
    • 消息: 税号无效
  • REQUEST_AMOUNT_BELOW_MINIMUM
    • 触发条件: 金额低于产品设置的最低金额
    • 消息: 金额不能低于产品指定的最低金额
  • TOTAL_PAYMENT_AMOUNT_BELOW_MINIMUM_AMOUNT
    • 触发条件: 购物车合计低于处理支付所需的最低金额
    • 消息: 处理支付至少需要 {display_str}
  • UNSUPPORTED_BILLING_CURRENCY
    • 触发条件: 请求的计费货币不支持此订阅
    • 消息: 订阅不支持非 USD 计费货币
  • UNSUPPORTED_COUNTRY
    • 触发条件: 不支持该国家/地区
    • 消息: 当前不支持国家/地区 {country_name}
  • UNSUPPORTED_CURRENCY
    • 触发条件: 产品或附加项货币不是 Dodo Payments 可用于扣款的货币。基础价格可以使用任何可扣款货币设置,因此此错误通常表示货币代码无效或不受支持。
    • 消息: 当前不支持此货币 (或) 目前仅支持 USD 和 INR 产品 (或) 附加项价格目前仅支持 USD 和 INR (或) billing_currency 只能请求 USD 或 INR (或) 不支持的货币 (或) 印度卡订阅使用了意外货币
  • UNSUPPORTED_TAX_CATEGORY
    • 触发条件: 税务类别不是受支持的值
    • 消息: 当前不支持类别 {category}

验证与请求

  • DUPLICATE_LINE_ITEMS_IN_REQUEST
    • 触发条件: 同一个 item_id 在 items[] 中出现多次
    • 消息: items 数组中指定了重复的 item_ids
  • INVALID_QUERY_PARAMS
    • 触发条件: 查询参数互斥或格式错误
    • 消息: 查询参数只能包含 time_frame,或包含 (start, end) (或) 范围的开始时间不能晚于结束时间
  • INVALID_REQUEST_BODY
    • 触发条件: JSON 格式错误或违反架构
    • 消息: 请求正文无效。请检查请求标头和对象。
  • INVALID_REQUEST_PARAMETERS
    • 触发条件: 参数值格式有效但语义无效,例如过去的日期
    • 消息: 无法将 next_billing_date 更改为过去的时间
  • MAXIMUM_KEYS_REACHED
    • 触发条件: Metadata 或自定义字段超过 50 个键值对
    • 消息: 超过 50 个键值对

常规与系统

  • INTEGER_CONVERSION_FAILURE
    • 触发条件: 服务器端在整数与字符串或小数之间转换失败,例如购物车总额过大而无法处理
    • 消息: 整数转换失败 (或) 购物车总额过大,无法处理。请减少数量,或选择其他计费货币。
  • INTERNAL_SERVER_ERROR
    • 触发条件: 意外的服务器错误。请在本地记录请求详情。
    • 消息: 无公开消息(通用 500,message 通常为 null)
  • NOT_FOUND
    • 触发条件: 任何缺失资源的通用 404
    • 消息: 未找到项目 (或返回说明缺失内容的更具体消息)
  • TOO_MANY_REQUESTS
    • 触发条件: 超出速率限制(HTTP 429)
    • 消息: 无消息
  • UNSUPPORTED_ACTION
    • 触发条件: 执行资源类型不支持的操作
    • 消息: 不支持更改基于用量的订阅套餐

最佳实践

处理 API 错误时,请遵循以下实践:
  1. 在应用中处理每个错误响应,并根据 code 而不是 message 进行分支处理。
  2. 记录每个失败请求的 HTTP 状态、code 和 message。
  3. 向最终用户显示为其编写的消息,而不是原始 API message。
  4. 仅在延迟一段时间后重试暂时性错误,例如 429 和 5xx 响应或 DISCOUNT_CONCURRENT_REDEMPTION。
  5. 对于无法解决的错误,请联系支持团队。

支持

如需错误代码或集成问题方面的更多帮助,请通过 support@dodopayments.com 联系支持团队。
最后修改于 2026年9月26日