> ## Documentation Index
> Fetch the complete documentation index at: https://waffo.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# 收银台集成 - Element API 参考

> Payment Element 的全部属性、方法、事件、状态取值与错误码。

本页列出 Payment Element 的全部公开属性、方法、事件和取值。接入步骤见 [Element 集成](https://waffo.com/docs/zh/developer-docs/integration/checkout/element)。

## 初始化

### new WaffoSDK(clientApiKey, options)

| 参数 | 类型 | 必填 | 说明 |
| - | - | - | - |
| `clientApiKey` | `string` | 是 | 商户的前端 Client API Key，不是服务端签名密钥 |
| `options.env` | `'prod' \| 'sandbox' \| 'testing'` | 是 | 运行环境，必须与 `sessionId`、Client API Key 所属环境一致 |
| `options.locale` | `string` | 否 | SDK 默认语言，默认 `en`。可选值见 [Element 集成](https://waffo.com/docs/zh/developer-docs/integration/checkout/element#外观与语言) |
| `options.preloadTokenization` | `boolean` | 否 | 是否在初始化时预加载绑卡 iframe，默认 `true`。只用 Payment Element 时建议传 `false`，不影响组件内的卡支付 |

### sdk.createElements(sessionId, options?)

返回 `Elements`。`sessionId` 为空时抛出 `SDK_INVALID_SESSION_ID`。

| 参数 | 类型 | 必填 | 说明 |
| - | - | - | - |
| `sessionId` | `string` | 是 | 商户服务端创建的支付 session |
| `options.appearance` | `Appearance` | 否 | 所有组件共用的主题与布局，见 [Appearance](#appearance) |
| `options.locale` | `string` | 否 | 覆盖 SDK 的 `locale` |
| `options.handleNextAction` | `boolean` | 否 | 是否由 SDK 自动处理 3DS、付款指引和跳转，默认 `true`。传 `false` 时返回 `requires_action`，由你自行处理 |
| `options.url` | `string` | 否 | 覆盖组件页面地址，仅用于联调或私有部署，不要指向不受信任的页面 |

## Elements

同一个 session 下所有组件的集合。

| 成员 | 返回 | 说明 |
| - | - | - |
| `sessionId` | `string` | 只读，当前 session |
| `create(type, options?)` | `PaymentElement` | 创建组件；相同的选择返回已有实例，重复调用不会更新配置 |
| `create(payMethodName, { customRender: true })` | `Promise<CustomPaymentElement>` | 创建自定义渲染组件；session 不支持该支付方式时 reject |
| `getElement(type)` | `PaymentElement \| null` | 查找已创建的普通组件，不会新建 |
| `getState()` | `ElementsState` | 整次支付的生命周期 `{ phase, loading }`，不依赖某个组件；`phase` 取值见 [phase 取值](#phase-取值) |
| `confirmPayment(element?, options?)` | `Promise<PaymentResult>` | 提交 `confirmTrigger` 为 `merchant` 的组件，见 [confirmPayment](#confirmpayment) |
| `updateSessionId(sessionId)` | `Promise<void>` | 重新读取 session 并原地刷新所有组件。加载或上一次更新未完成时调用会排队，只有最后一个 `sessionId` 生效；同一 session 刷新时保留用户已填写的内容 |
| `updateAppearance(appearance)` | `Promise<void>` | 为所有组件应用新主题，无需重新挂载 |
| `on(event, handler)` | `() => void` | 订阅 `payment`、`redirect`、`error`，返回取消订阅函数 |
| `off(event, handler)` | `void` | 用同一个函数引用取消订阅 |
| `destroy()` | `void` | 销毁所有组件、弹层和监听，之后实例不可再用 |

### create 的 type

| 取值 | 示例 | 说明 |
| - | - | - |
| `'payment'` | `create('payment')` | 展示 session 中所有可用支付方式 |
| 分组数组 | `create(['express'])`、`create(['collection', 'card'])` | 小写，可选 `express`、`collection`、`card` |
| 支付方式数组 | `create(['APPLEPAY'])`、`create(['WECHATPAY', 'ALIPAY'])` | 大写 `payMethodName`；`CARD` 表示卡表单 |

分组和支付方式不能混在同一个数组里。

### create 的 options

> [tab] 普通组件
>
> | 参数 | 类型 | 说明 |
> | - | - | - |
> | `customRender` | `false` | 省略或传 `false` |
> | `style` | `IframeStyle` | iframe 外层的 CSS，如 `width`、`border`、`borderRadius`；高度由组件自动调整。组件内部样式请用 `appearance` |
> | `paymentMethodOrder` | `string[]` | 展示顺序。列出的支付方式排在前面，其余保持 session 原顺序。可填 `payMethodName`（如 `CC_VISA`）或 `payMethodType`（如 `APPLEPAY`、`CREDITCARD`）。只排序，不过滤；原子化接入无需传 |

> [tab] 自定义渲染
>
> | 参数 | 类型 | 说明 |
> | - | - | - |
> | `customRender` | `true` | 必填。由你渲染字段和按钮，SDK 自动管理隐藏 iframe，不调用 `mount()` |
>
> `type` 只能是单个非卡、非 `APPLEPAY`、非 `GOOGLEPAY` 的支付方式名称，如 `WECHATPAY`。

### confirmPayment

`elements.confirmPayment(element?, options?)`

| 参数 | 类型 | 说明 |
| - | - | - |
| `element` | `PaymentElement` | 要提交的组件。只挂载了一个需要你提交的组件时可省略；挂载了多个时必须传 |
| `options.payMethodName` | `string` | 仅自定义渲染。必须与组件的支付方式一致 |
| `options.userFields` | `Record<string, string>` | 仅自定义渲染。key 为 `requiredFields[].field`，value 为用户输入或选中的 `code`；扁平结构，不展开成嵌套对象；多余的 key 不会提交 |

以下情况会 reject：

| 情况 | 结果 |
| - | - |
| 当前选中的支付方式由组件自己提交 | 抛出 `SDK_ELEMENT_NOT_CONFIRMABLE` |
| 挂载了多个需要你提交的组件但未指定 `element` | 抛出 `SDK_ELEMENT_NOT_CONFIRMABLE` |
| 正在加载、更新、提交，或支付已进入后续流程 | 抛出 `SDK_ELEMENTS_BUSY` |
| 表单未填完或格式不对 | `SDK_ELEMENT_INCOMPLETE`，`field` 指向第一个出错的收集字段；卡号等卡字段出错时不带 `field` |
| 订阅 session 未同意协议 | `TERMS_NOT_AGREED` |
| `options` 用错：普通组件传了 `options`，或 `payMethodName` 与自定义组件不一致 | `SDK_INVALID_CONFIRM_OPTIONS` |
| 自定义渲染时 `userFields` 校验不过 | `INVALID_USER_FIELD`，带 `field` |
| 提交时接口返回错误 | 接口错误码，如 `A0068`，`message` 为本地化文案 |

## PaymentElement

| 成员 | 返回 | 说明 |
| - | - | - |
| `type` | `ElementType` | 只读，创建时的选择 |
| `mount(container)` | `void` | 挂载到选择器或 DOM 元素。容器不存在时抛出 `SDK_CONTAINER_NOT_FOUND`；已挂载或与其他组件重叠时抛出 `SDK_IFRAME_CREATE_FAILED`。请先订阅 `change` 再挂载 |
| `unmount()` | `void` | 移除这个组件的 iframe，不会取消后端订单 |
| `getState()` | `ElementState \| null` | 读取当前状态，就绪前为 `null` |
| `getIframe()` | `HTMLIFrameElement \| null` | 获取 iframe 元素，未挂载时为 `null`。不要尝试读取 iframe 内部内容 |
| `on(event, handler)` | `() => void` | 订阅 `ready`、`change`、`error`，返回取消订阅函数 |
| `off(event, handler)` | `void` | 取消订阅 |

### CustomPaymentElement

在 `PaymentElement` 的基础上增加：

| 成员 | 类型 | 说明 |
| - | - | - |
| `payMethod` | `ElementPayMethod \| null` | 只读，当前支付方式的信息。session 更新后请从 `change` 事件读取最新值 |

## 事件

| 事件 | 载荷 | 说明 |
| - | - | - |
| `element.on('ready')` | `ElementState` | 组件渲染完成，可以交互。不代表支付成功 |
| `element.on('change')` | `ElementState` | 选中的支付方式、表单、加载状态或生命周期变化时触发 |
| `element.on('error')` | `ElementError` | 该组件的错误，同时也会出现在 `elements.on('error')` |
| `elements.on('payment')` | `PaymentResult` | 所有支付结果。`processing` 之后可能再触发一次终态结果；挂载时 session 已支付或已结束也会立即触发 |
| `elements.on('redirect')` | `{ url: string }` | SDK 即将整页跳转到外部支付页面。不要在回调里跳转页面 |
| `elements.on('error')` | `ElementError` | 所有错误的统一入口 |

## ElementState

| 字段 | 类型 | 说明 |
| - | - | - |
| `phase` | `ElementsPhase` | 当前生命周期，取值见下表 |
| `loading` | `boolean` | 加载、更新、提交、等待后续动作期间为 `true`，可用于加载提示；`processing` 时为 `false` |
| `ready` | `boolean` | 组件是否已渲染。建议在 `ready` 之前隐藏你的**支付**按钮 |
| `complete` | `boolean` | 当前选中的支付方式是否已填完。仅供参考，不要据此禁用**支付**按钮；自定义渲染时始终为 `false` |
| `payMethodName` | `string \| null` | 当前选中的支付方式，未选中时为 `null`；卡为 `CARD` |
| `availablePayMethods` | `string[]` | 当前可用的支付方式，由 session、组件选择和浏览器能力共同决定 |
| `confirmTrigger` | `'merchant' \| 'element'` | `merchant`：由你调用 `confirmPayment()`；`element`：由组件内按钮提交 |
| `errors` | `ElementError[]` | 可选。仅自定义渲染时出现，`code` 为 `INVALID_USER_FIELD`；内置表单的字段错误直接显示在组件内 |
| `customRender` | `boolean` | 可选。是否为自定义渲染组件 |
| `payMethod` | `ElementPayMethod \| null` | 可选。仅自定义渲染时出现，当前支付方式的信息 |

### phase 取值

| 取值 | `loading` | 说明 |
| - | - | - |
| `idle` | `false` | 尚未挂载组件 |
| `loading` | `true` | 初始化中，不能提交 |
| `ready` | `false` | 可以交互，按 `confirmTrigger` 决定提交方 |
| `updating` | `true` | 正在更新 session |
| `submitting` | `true` | 正在提交，不能重复提交 |
| `awaiting_action` | `true` | 等待 3DS、付款指引、跳转或你自行处理后续动作 |
| `processing` | `false` | 等待最终结果，不能再次提交 |
| `succeeded` | `false` | 支付成功，当前 session 不能再次支付 |
| `failed` | `false` | 支付失败，需要换新 session 后再支付 |
| `error` | `false` | 本次操作出错，修正后可以重新提交 |
| `destroyed` | `false` | 实例已销毁，需要重新创建 |

> [!NOTE]
>
> `phase` 为 `ready` 或 `error` 时才可以调用 `confirmPayment()`。

### ElementPayMethod

| 字段 | 类型 | 说明 |
| - | - | - |
| `payMethodName` | `string` | 支付方式名称，如 `WECHATPAY`，提交时保持一致 |
| `payMethodType` | `string` | 支付方式类别 |
| `userAmount` | `string \| number \| null` | 可选。用户支付金额，缺失时不要自行推算 |
| `userCurrency` | `string \| null` | 可选。用户支付币种 |
| `requiredFields` | `RequiredField[]` | 需要你渲染和收集的字段 |

### RequiredField

| 字段 | 类型 | 说明 |
| - | - | - |
| `field` | `string` | 字段路径，如 `userInfo.userEmail`，同时作为 `userFields` 的 key |
| `required` | `boolean` | 是否必填。列表中也可能包含选填字段 |
| `options` | `{ name: string; code: string }[] \| null` | 可选。非空时渲染为下拉框，显示 `name`，提交 `code`；为空时渲染为输入框 |

组件只校验必填和选项取值，不提供邮箱、手机号等格式校验，你可以在前端自行补充。

### ElementError

| 字段 | 类型 | 说明 |
| - | - | - |
| `code` | `string` | 错误码，见 [错误码](#错误码) |
| `message` | `string` | 已本地化的错误说明，可直接展示 |
| `field` | `string` | 可选。关联的字段路径 |

## PaymentResult

`confirmPayment()` 的返回值和 `payment` 事件的载荷。

| 字段 | 类型 | 说明 |
| - | - | - |
| `status` | `'succeeded' \| 'processing' \| 'failed' \| 'requires_action'` | 支付结果状态。`requires_action` 仅在 `handleNextAction: false` 时出现 |
| `code` | `string` | 可选。失败时的结果码，不保证每次都有 |
| `message` | `string` | 可选。结果说明 |
| `data` | `PaymentOrderData \| PaymentSubscriptionData` | 可选。订单或订阅数据；校验失败、连接失败等没有订单的情况下可能为空 |

用 `'sessionType' in data` 区分订阅和订单。

### PaymentOrderData

| 字段 | 类型 | 说明 |
| - | - | - |
| `paymentRequestId` | `string` | 可选。支付请求 ID |
| `merchantOrderId` | `string` | 可选。商户订单号 |
| `acquiringOrderId` | `string` | 可选。Waffo 订单号 |
| `orderStatus` | `string` | 可选。订单状态，如 `PAY_IN_PROGRESS`、`AUTHORIZATION_REQUIRED`、`AUTHED_WAITING_CAPTURE`、`PAY_SUCCESS`、`ORDER_CLOSE`。`AUTHED_WAITING_CAPTURE` 表示已授权、尚未请款 |
| `orderAction` | `string \| null` | 可选。后续动作的 JSON 字符串，自行处理后续动作时解析使用 |

### PaymentSubscriptionData

| 字段 | 类型 | 说明 |
| - | - | - |
| `sessionType` | `'SUBSCRIPTION'` | 标识订阅 session |
| `subscription` | `object \| null` | 可选。订阅数据，包含 `subscriptionId`、`subscriptionStatus`、`subscriptionAction`（均为可选的 `string \| null`） |

## Appearance

`createElements` 的 `appearance` 和 `updateAppearance()` 的参数。

| 字段 | 类型 | 说明 |
| - | - | - |
| `variables` | `AppearanceVariables` | 颜色、字体、圆角、按钮等主题变量 |
| `layout` | `ElementLayout` | 支付方式的排列方式。与 `variables` 平级，不要放进 `variables` |
| `rules` | `AppearanceRules` | 用 CSS 声明单独调整某类组件的样式，仅 Payment Element 生效，见 [AppearanceRules](#appearancerules) |
| `inputs` | `'spaced' \| 'condensed'` | 输入框样式，对齐 Stripe 的 `appearance.inputs`，目前只作用于卡表单。`spaced`（默认）每个字段单独带标签；`condensed` 卡号、有效期和 CVV 拼成一块，只保留一个「银行卡信息」标题，持卡人姓名在下方单独一个输入框（与 Stripe Checkout 一致） |
| `labels` | `'above' \| 'floating'` | 字段名的位置，对齐 Stripe 的 `appearance.labels`，目前只作用于卡表单。`above`（默认）放在框上方；`floating` 放进框里，聚焦或填写后浮到左上角 |
| `logoUrl` | `string` | 商户 Logo。Payment Element 不展示 Logo，仅对嵌入式收银台生效 |

### AppearanceVariables

所有字段均可选。颜色使用 CSS 颜色值，尺寸使用带单位的字符串（如 `8px`）。

| 字段 | 说明 | 默认值 |
| - | - | - |
| `colorPrimary` | 主色 | |
| `colorPrimaryForeground` | 主色背景上的文字颜色，`#RGB` 或 `#RRGGBB` | 自动计算 |
| `colorBackground` | 背景色 | |
| `colorCard` | 卡片或内容区背景色 | |
| `colorText` | 主要文字颜色 | |
| `colorTextSecondary` | 次要文字颜色 | |
| `colorTextTertiary` | 弱化文字颜色 | |
| `colorBorder` | 边框颜色 | |
| `colorDanger` | 错误提示颜色 | |
| `colorInfo` | 信息提示背景色 | |
| `fontSizeBase` | 基础字号。输入框文字是它的 0.875 倍 | |
| `borderRadius` | 基础圆角 | |
| `buttonRadius` | 按钮圆角 | `9999px` |
| `buttonHeight` | 支付、钱包、跳转按钮的高度 | `42px` |
| `buttonVariant` | 非卡支付方式按钮样式：`solid` 主色实心、`outlined` 主色描边、`dashed` 主色虚线描边、`filled` 主色浅底 | `solid` |
| `spacing` | 组件内的间距，见 [SpacingConfig](#spacingconfig)。仅 Payment Element 生效 | |
| `headerDisplay` | 头部展示配置。Payment Element 不展示头部，仅对嵌入式收银台生效 | |
| `amountDisplay` | 金额展示配置。Payment Element 不展示金额，仅对嵌入式收银台生效 | |

> [!NOTE]
>
> Apple Pay、Google Pay 按钮由厂商渲染，只有黑白两种样式，不受 `colorPrimaryForeground`、`buttonVariant` 和 `rules` 影响。

### SpacingConfig

`variables.spacing`，组件内的间距：

```javascript theme={null}
variables: {
  spacing: { button: '8px', accordionItem: '8px', gridRow: '16px', gridColumn: '12px' },
}
```

| 字段 | 间距 | 默认值 |
| - | - | - |
| `button` | 快捷按钮之间；`layout.type` 为 `horizontal` 时也是列间距 | `12px` |
| `accordionItem` | 手风琴各行之间 | `8px` |
| `gridRow` | 表单字段之间的上下间距（卡表单、需要填写的字段） | `12px` |
| `gridColumn` | 并排字段之间的左右间距（有效期和 CVV） | `12px` |

取值为非负的 `px`、`rem` 或 `em`，其他值按默认值处理。

### AppearanceRules

`appearance.rules`，用 CSS 声明单独调整某类组件的样式，写法参考 Stripe Appearance API。键是下表的选择器，值是一组 CSS 声明，可以写成对象（属性名用驼峰或连字符均可），也可以写成 CSS 声明字符串：

```javascript theme={null}
rules: {
  '.Input': { border: '1px solid #d0d5dd', borderRadius: '10px', padding: '12px 14px' },
  '.Input:focus': 'border-color: var(--colorPrimary); box-shadow: 0 0 0 3px rgb(var(--colorPrimary) / 0.2)',
  '.AccordionItem--selected': { backgroundColor: 'rgb(var(--colorPrimary) / 0.06)' },
  '.PayMethodButton': { backgroundColor: 'rgb(var(--colorText) / 0.06)', color: 'var(--colorText)' },
  '.PayMethodButton:hover': { backgroundColor: 'rgb(var(--colorText) / 0.1)' },
  '.PayMethodLogo': { backgroundColor: '#fff', borderRadius: '6px' },
}
```

| 选择器 | 作用对象 |
| - | - |
| `.PayMethodButton`、`:hover`、`:focus-visible` | 点击即跳转的支付方式按钮（如 Alipay、PayMe），在 `buttonVariant` 的样式之上覆盖 |
| `.PayMethodLogo` | 跳转按钮里的支付方式图标，默认 28×28px。和其他选择器不同，它可以设置 `width`、`height`；图片在框内保持原始比例 |
| `.Input`、`:focus`、`--invalid`、`::placeholder` | 卡号、有效期、CVV、持卡人输入框，以及需要填写的字段（文本、下拉、手机号）。字段报错时 `:focus` 不生效 |
| `.Label` | 字段标签 |
| `.Label--floating` | `labels: 'floating'` 时框内的浮动标签。`.Label` 的规则不会改变它的颜色，要调整请用这个选择器 |
| `.Error` | 字段错误提示 |
| `.AccordionItem`、`--selected` | 手风琴的一行（卡和需要填写信息的支付方式），`color` 只作用于行标题；`--selected` 为展开的那一行 |

基础选择器的规则不会覆盖组件自带的报错、禁用和选中样式；要改这些状态，请用对应的状态选择器。

输入框的高度、内边距、字重和字号都可以用 `.Input` 调整；`height` 不能直接写，可以用上下 `padding` 调整高度。

> [accordion] 可以写的内容
>
> * **属性**：任意 CSS 属性，但不能改布局或可见性：`position`、`top` / `right` / `bottom` / `left`、`inset*`、`z-index`、`display`、`visibility`、`content`、`width` / `height`（含 `min-` / `max-`，`.PayMethodLogo` 除外）、`margin*`、`float`、`clear`、`overflow*`、`transform*`、`translate`、`rotate`、`scale`、`clip*`、`mask*`、`pointer-events`、`all`，以及自定义属性（`--*`）。
> * **值**：数字、单位、颜色、关键字，以及 `rgb()`、`rgba()`、`hsl()`、`hsla()`、`calc()`、`min()`、`max()`、`clamp()`。可以用 `var(--colorText)` 引用颜色变量，或用 `rgb(var(--colorText) / 0.06)` 加透明度。可引用的变量：`colorPrimary`、`colorPrimaryForeground`、`colorBackground`、`colorCard`、`colorText`、`colorTextSecondary`、`colorTextTertiary`、`colorBorder`、`colorDanger`。
> * **不能写**：`url()` 等其他函数、引号、`!important`，以及值里的 `;`、`{`、`}`。
>
> 不符合要求的声明会被忽略，组件会在浏览器控制台输出被忽略的内容和原因（`[appearance] rules …`）。

### ElementLayout

只影响非卡支付方式按钮的排列；卡表单和需要填写信息的支付方式始终整行展示。

容器较窄时，点击即跳转的支付方式按钮文字不换行、放不下时显示省略号，按钮宽度不足 96px 时只显示图标；Apple Pay、Google Pay 按钮有钱包方要求的最小宽度。

| 字段 | 类型 | 说明 | 默认值 |
| - | - | - | - |
| `type` | `'vertical' \| 'horizontal'` | `vertical` 每行一个；`horizontal` 按可用宽度自动分列 | `vertical` |
| `maxColumns` | `number` | `horizontal` 时最多几列，窄屏仍会自动换行 | 不限 |
| `visibleExpressItemsCount` | `number` | 快捷支付区（钱包和点击即跳转的支付方式）先展示几个，其余收进“更多支付方式” | 全部展示 |

## 错误码

> [tab] SDK 错误码
>
> 由 SDK 定义，在浏览器中由 SDK 或组件代为抛出，不会由接口返回。
>
> | 错误码 | 说明 |
> | - | - |
> | `SDK_INVALID_SESSION_ID` | `sessionId` 为空 |
> | `SDK_CONTAINER_NOT_FOUND` | 找不到挂载容器 |
> | `SDK_IFRAME_CREATE_FAILED` | 组件已挂载，或多个组件展示的内容有重叠 |
> | `SDK_ELEMENT_NOT_MOUNTED` | 没有已挂载的组件 |
> | `SDK_ELEMENT_NOT_CONFIRMABLE` | 当前支付方式由组件自己提交；或挂载了多个需要你提交的组件但未指定目标 |
> | `SDK_ELEMENT_INCOMPLETE` | 调用 `confirmPayment()` 时表单没填完或格式不对，`field` 指向第一个出错的收集字段 |
> | `SDK_INVALID_CONFIRM_OPTIONS` | `confirmPayment()` 的 `options` 用错：普通组件传了 `options`，或 `payMethodName` / `userFields` 与自定义组件不符 |
> | `SDK_ELEMENTS_BUSY` | 正在提交支付、加载或更新 session 时调用 `confirmPayment()`；支付已开始后调用 `updateSessionId()` |
> | `SDK_ELEMENTS_DESTROYED` | Elements 实例已销毁，或 session 已被替换 |
> | `SDK_CONNECTION_FAILED` | 组件页面加载失败或 30 秒内未能就绪；或更新 session 时某个组件 15 秒内没有响应。结账页不是 HTTPS 时也会表现为此错误 |
> | `SDK_PAYMENT_ACTION_FAILED` | 3DS / 付款指引无法启动 |
> | `SDK_PAYMENT_ACTION_TIMEOUT` | 3DS / 付款指引 15 分钟内没有结果 |
> | `SDK_PAYMENT_ACTION_CANCELED` | 3DS / 付款指引弹层因 `destroy()`、`unmount()` 或 `updateSessionId()` 被关闭 |
> | `SDK_UNKNOWN_ERROR` | 没有更具体错误码的异常；尚未升级的组件页拒绝提交时也会归到这里，`message` 保留原文 |

> [tab] 组件错误码
>
> 由组件产生，通过 `error` 事件返回；阻止了提交时，也作为 `confirmPayment()` 的 reject 返回。
>
> | 错误码 | 说明 |
> | - | - |
> | `ELEMENT_INIT_FAILED` | 组件读取 session 时因非接口原因失败，如网络异常；接口返回的错误会使用接口错误码 |
> | `ELEMENT_PAYMENT_ERROR` | 没有接口错误码的支付失败，如钱包不可用、支付被拒绝 |
> | `TERMS_NOT_AGREED` | 订阅 session 中用户未同意协议就提交 |
> | `INVALID_USER_FIELD` | 自定义渲染时字段校验失败：`confirmPayment()` 以它拒绝并带 `field`，`ElementState.errors` 中也会出现 |

> [tab] 接口错误码
>
> 接口返回的错误码通过 `error` 事件原样转发。
>
> | 错误码 | 说明 | 建议处理 |
> | - | - | - |
> | `A0063` | session 不存在、已过期或不属于当前商户 | 服务端新建 session，前端调用 `updateSessionId(newId)` |
> | `A0064` | 该支付请求已有订单 | 服务端新建 session |
> | `A0065` | session 中途被更新，提交时的信息已失效 | 组件会自动刷新，用户重新提交即可 |
> | `A0066` | session 已经提交过 | 通常不会收到：组件会重新读取 session，按它的状态返回结果，见 [Element 集成 - 会话状态](https://waffo.com/docs/zh/developer-docs/integration/checkout/element#会话状态) |
> | `A0067` | 缺少必填的用户信息 | 提示用户补全信息 |
>
> 收到 `A0063`、`A0064` 时，`error` 事件之后还会触发一次 `status: 'failed'` 的 `payment` 事件。


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.