# Antom Web SDK 完整集成指南

## 目录

1. [集成流程概览](#1-集成流程概览)
2. [集成准备](#2-集成准备)
3. [AMSElement - 创建实例](#3-amselement---创建实例)
4. [mount() - 挂载组件](#4-mount---挂载组件)
5. [on() - 事件监听](#5-on---事件监听)
6. [validateFields() - 验证字段](#6-validatefields---验证字段)
7. [submitPayment() - 提交支付](#7-submitpayment---提交支付)
8. [错误码速查表](#8-错误码速查表)
9. [最佳实践](#9-最佳实践)

---

## 1. 集成流程概览

```
┌─────────────────────────────────────────────────────────────────────────┐
│                           完整集成流程                                    │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│  服务端                          前端                                    │
│  ────────                        ────                                    │
│     │                              │                                      │
│     ▼                              │                                      │
│  createPaymentSession API          │                                      │
│     │                              │                                      │
│     ├─→ paymentSessionData ────────┼─→ new AMSElement()                   │
│     │                              │         │                            │
│     │                              │         ▼                            │
│     │                              │    mount() 挂载组件                   │
│     │                              │         │                            │
│     │                              │         ▼                            │
│     │                              │    on() 监听事件 (可选)               │
│     │                              │         │                            │
│     │                              │         ▼                            │
│     │                              │    validateFields() (可选)           │
│     │                              │         │                            │
│     │                              │         ▼                            │
│     │                              │    submitPayment() 提交支付          │
│     │                              │         │                            │
│     ▼                              ▼         ▼                            │
│  异步通知 ←───────────────────── 支付结果 ←──┘                            │
│                                                                          │
└─────────────────────────────────────────────────────────────────────────┘
```

---

## 2. 集成准备

### 2.1 环境要求

- 安装 npm (Node Package Manager)
- 处理浏览器兼容性：为 Internet Explorer 等旧浏览器提供相应的 polyfills，推荐使用 `babel-preset-env`

### 2.2 浏览器支持

#### 移动端浏览器

| 浏览器 | 版本要求 |
|--------|----------|
| iOS Safari | iOS 11 及以上 |
| Android Browser | Android 5.0 及以上 |

#### 桌面浏览器

| 浏览器 | 版本要求 |
|--------|----------|
| Edge | 最新 2 个版本 |
| Firefox | 最新 2 个版本 |
| Chrome | 最新 2 个版本 |
| Safari | 最新 2 个版本 |
| Opera | 最新 2 个版本 |
| Electron | 最新 2 个版本 |

### 2.3 安装 SDK

**方式一：使用 npm**

```bash
npm install @alipay/ams-checkout
```

**方式二：使用 CDN**


```html
<script src="https://js.antom.com/v2/ams-checkout.js"></script>
```

### 2.4 预加载 SDK（可选）

在创建支付会话前预加载 SDK，可提高支付页面渲染速度。

```javascript
AMSElement.preload();
```

> **注意**：Payment Element 目前不支持 SDK 预加载。

---

## 3. AMSElement - 创建实例

### 3.1 概述

AMSElement 是用于在前端页面创建 Payment Element 实例的类。

### 3.2 构造函数

```typescript
// TypeScript
new AMSElement(options: IElementOptions)

// JavaScript
new AMSElement(options)
```

### 3.3 参数说明

| 参数 | 类型 | 必需 | 说明 |
|------|------|------|------|
| environment | String | 否 | 环境信息。`sandbox`: 沙箱环境, `prod`: 生产环境（默认） |
| locale | String | 否 | 语言信息，见下表。默认 `en_US` |
| sessionData | String | **是** | 支付会话数据，来自 `createPaymentSession` API 响应 |

### 3.4 支持的语言

| 语言代码 | 语言 | 语言代码 | 语言 |
|----------|------|----------|------|
| en_US | 英语（默认） | pt_BR | 葡萄牙语（巴西） |
| pt_PT | 葡萄牙语 | es_ES | 西班牙语 |
| ko_KR | 韩语 | zh_CN | 简体中文 |
| zh_HK | 繁体中文 | ms_MY | 马来语 |
| in_ID | 印尼语 | th_TH | 泰语 |
| vi_VN | 越南语 | tl_PH | 菲律宾语 |
| it_IT | 意大利语 | de_DE | 德语 |
| fr_FR | 法语 | nl_NL | 荷兰语 |
| ja_JP | 日语 | ro | 罗马尼亚语 |
| pl_PL | 波兰语 | ar_SA | 阿拉伯语 |
| tr_TR | 土耳其语 | hi_IN | 印地语 |

### 3.5 代码示例

**CDN 方式**

```javascript
const elementPayment = new window.AMSElement({
  environment: "sandbox",
  locale: "en_US",
  sessionData: sessionData
})
```

**npm 方式**

```javascript
import { AMSElement } from '@alipay/ams-checkout'

const elementPayment = new AMSElement({
  environment: "sandbox",
  locale: "en_US",
  sessionData: sessionData
})
```

---

## 4. mount() - 挂载组件

### 4.1 概述

mount() 方法用于将 Payment Element 组件渲染到商户页面的指定 DOM 容器中。

### 4.2 方法签名

```typescript
// TypeScript
mount(renderOptions: PaymentMountOptions, sdkSelector: string): Promise<ICommonApiResponse>

// JavaScript
mount(renderOptions, sdkSelector)
```

### 4.3 参数说明

#### 顶层参数

| 参数 | 类型 | 必需 | 说明 |
|------|------|------|------|
| renderOptions | Object | 是 | 渲染选项配置 |
| sdkSelector | String | 是 | DOM 容器选择器（CSS 选择器） |

#### renderOptions 子参数

| 参数 | 类型 | 必需 | 说明 |
|------|------|----|------|
| appearance | Object | 否  | 自定义外观配置，包含 theme、layout、variables |
| notRedirectAfterComplete | Boolean | 否  | 支付完成后是否跳转。`false`(默认): 自动跳转; `true`: 不自动跳转 |
| type | String | 是  | 组件类型。`payment`: 支付组件 |

> **注意**：不同产品场景可能需要额外的 `renderOptions` 参数。例如：
> - **组件类型**： `type: 'payment'`
> - 其他特定场景请参考对应的产品集成文档

### 4.4 返回值

返回 Promise 对象，resolve 为包含错误信息的对象（仅失败时）。

| 参数 | 类型 | 说明 |
|------|------|------|
| error.code | String | 错误码 |
| error.message | String | 错误信息 |
| error.traceId | String | 日志链路 ID |

### 4.5 mount() 错误码

| 错误码 | status | 说明 | 建议操作 |
|--------|--------|------|----------|
| UNKNOWN_EXCEPTION | PROCESSING | 未知原因 API 调用失败 | 重试，持续失败联系技术支持 |
| INQUIRY_PAYMENT_SESSION_FAILED | FAIL | 支付会话已过期 | 使用新 paymentRequestId 重新发起 |
| UI_STATE_ERROR | FAIL | mount() 调用时机异常 | 排查集成代码 |
| ERR_DATA_STRUCT_UNRECOGNIZED | None | SDK 未返回所需支付信息 | 联系技术支持 |
| PARAM_INVALID | None | SDK 输入参数异常 | 排查集成代码 |
| INITIALIZE_API_TIMEOUT | None | SDK 超时 | 重试 mount() |
| INITIALIZE_WEB_TIMEOUT | None | 静态资源加载超时 | 重试 mount() |

### 4.6 容器要求

- 最小宽度：375px
- 高度：不限制，允许自动扩展

---

## 5. on() - 事件监听

### 5.1 概述

on() 方法用于监听组件事件，**仅适用于 Payment Element 场景**。

### 5.2 方法签名

```typescript
// TypeScript
on(event: EventName, callback: (payload: Payload) => void): void

// JavaScript
on(event, callback)
```

### 5.3 支持的事件

| 事件名 | 说明 | 触发时机 |
|--------|------|----------|
| `paymentMethodChanged` | 支付方式变更 | 买家切换支付方式时 |
| `valuesChanged` | 表单数据变更 | 买家编辑支付表单时 |

### 5.4 事件详情

#### paymentMethodChanged

```javascript
on('paymentMethodChanged', (payload) => {
  console.log(payload.type); // 支付方式类型
});
```

| 参数 | 类型 | 说明 |
|------|------|------|
| type | String | 支付方式类型枚举值 |

#### valuesChanged

> 目前仅适用于 `billingAddress` 场景。

```javascript
on('valuesChanged', (payload) => {
  console.log(payload.billingAddress);
});
```

| 参数 | 类型 | 说明 |
|------|------|------|
| billingAddress.region | String | 国家/地区代码（ISO 3166） |
| billingAddress.state | String | 州/省代码（ISO 3166-2） |
| billingAddress.city | String | 城市名称 |
| billingAddress.address1 | String | 地址行 1 |
| billingAddress.address2 | String | 地址行 2 |
| billingAddress.zipCode | String | 邮政编码 |
| billingAddress.phoneNo | String | 电话号码（E.164 格式） |
| billingAddress.name | Object | 买家姓名（firstName/lastName/middleName） |

---

## 6. validateFields() - 验证字段

### 6.1 概述

validateFields() 方法用于验证当前支付方式的表单字段完整性和格式正确性。

### 6.2 方法签名

```typescript
// TypeScript
validateFields(): Promise<{ isValid: boolean }>

// JavaScript
validateFields()
```

### 6.3 返回值

| 参数 | 类型 | 说明 |
|------|------|------|
| isValid | Boolean | `true`: 验证通过; `false`: 存在错误 |

### 6.4 使用场景

```javascript
const result = await validateFields();
if (result.isValid) {
  // 执行自定义业务逻辑
  await submitPayment();
}
```

> **注意**：即使不显式调用 `validateFields()`，`submitPayment` 执行时也会自动验证并显示错误。

---

## 7. submitPayment() - 提交支付

### 7.1 概述

submitPayment() 是 Web SDK 核心支付提交方法，用于发起支付请求并自动处理支付流程（包括 3D 认证等）。

### 7.2 方法签名

```javascript
// JavaScript / TypeScript
submitPayment(options)
```

### 7.3 参数说明

#### options 配置对象

| 参数 | 类型 | 必需 | 说明 |
|------|------|------|------|
| handleActions | Boolean | 否 | 是否由 SDK 自动处理重定向。默认 `true` |
| shippingInfo | Object | 否 | 收货地址信息 |

#### handleActions 说明

| 值 | 说明 |
|----|------|
| `true` | 默认值。SDK 自动控制支付流程 |
| `false` | SDK 返回 URL 信息，由商户自行处理重定向 |

> **限制**：`handleActions` 为 `false` 仅适用于卡、Apple Pay 和 Google Pay 以外的场景。

#### shippingInfo 配置

| 参数 | 类型 | 必需 | 说明 |
|------|------|------|------|
| shippingAddress | Object | 是 | 收货地址 |
| shippingName | Object | 是 | 收件人姓名 |
| shippingPhoneNo | String | 是 | 收件人电话（E.164 格式） |

**shippingAddress 子参数**

| 参数 | 类型 | 说明 |
|------|------|------|
| region | String | 国家/地区代码（ISO 3166） |
| state | String | 州/省代码（ISO 3166-2） |
| city | String | 城市名称 |
| address1 | String | 地址行 1 |
| address2 | String | 地址行 2 |
| zipCode | String | 邮政编码 |

**shippingName 子参数**

| 参数 | 类型 | 必需 | 说明 |
|------|------|------|------|
| firstName | String | 是 | 收件人名 |
| lastName | String | 是 | 收件人姓 |
| middleName | String | 否 | 收件人中间名 |
| fullName | String | 否 | 收件人全名 |

### 7.4 返回值

返回 Promise 对象，resolve 为包含支付结果的对象。

| 参数 | 类型 | 说明 |
|------|------|------|
| status | String | 支付状态 |
| userCanceled3D | Boolean | 买家是否主动关闭 3D Secure 认证弹窗 |
| session | Object | 支付会话信息 |
| error | Object | 错误对象（仅失败时） |

#### status 状态值

| 值 | 说明 |
|----|------|
| `SUCCESS` | 支付成功 |
| `FAIL` | 支付失败 |
| `PROCESSING` | 支付处理中 |
| `CANCELLED` | 支付已取消 |

#### session.nextAction 对象

| 参数 | 类型 | 说明 |
|------|------|------|
| applinkUrl | String | App Link URL（iOS Universal Link / Android App Link） |
| schemeUrl | String | 自定义 URL Scheme 链接 |
| normalUrl | String | 常规 H5 页面链接 |

#### error 对象

| 参数 | 类型 | 说明 |
|------|------|------|
| code | String | 错误码 |
| message | String | 错误信息 |
| traceId | String | 问题追踪 ID |
| context | Any | 错误上下文信息 |

---

## 8. 错误码速查表

### submitPayment() 错误码

| 错误码 | status | 买家提示语 | 推荐操作 |
|--------|--------|-----------|----------|
| UNKNOWN_EXCEPTION | PROCESSING | 未知异常。请检查付款情况并联系商户。 | 从服务器轮询结果，或重试 submitPayment() |
| INQUIRY_PAYMENT_SESSION_FAILED | FAIL | 订单状态异常。请检查付款情况并联系商户。 | 使用新 paymentRequestId 重新发起 |
| UI_STATE_ERROR | FAIL | 请求异常，交易无法发起。 | 排查集成代码 |
| USER_BALANCE_NOT_ENOUGH | FAIL | 用户余额不足。请充值或选择其它支付方式。 | 显示弹窗提示，可重试 |
| ORDER_NOT_EXIST | FAIL | 订单状态异常。请检查付款情况并联系商户。 | 联系技术支持 |
| PROCESS_FAIL | FAIL | 支付失败。请检查付款情况并联系商户。 | 联系技术支持 |
| ORDER_IS_CANCELLED | FAIL | 订单状态异常。请检查付款情况并联系商户。 | 使用新 paymentRequestId 重新发起 |
| RISK_REJECT | FAIL | 风控拒绝。建议换卡重试或联系发卡行。 | 显示弹窗提示，可重试 |
| ORDER_IS_CLOSED | FAIL | 订单状态异常。请检查付款情况并联系商户。 | 使用新 paymentRequestId 重新发起 |
| CARD_EXPIRED | FAIL | 卡片已过期，请核对过期日期或使用其他卡片。 | 可重试 |
| INVALID_CVV | FAIL | 卡片 CVV 不正确，请核对 CVV 或使用其他卡片。 | 可重试 |
| INVALID_CARD_NUMBER | FAIL | 卡号不正确，建议换卡重试或联系发卡行。 | 可重试 |
| CARD_NOT_SUPPORTED | FAIL | 卡片不支持。建议换卡重试或联系发卡行。 | 可重试 |
| PAYMENT_IN_PROCESS | PROCESSING | 支付正在处理中，请等待支付完成。 | 从服务器轮询结果 |
| CURRENCY_NOT_SUPPORT | FAIL | 商户不支持该币种，交易无法发起。 | 联系技术支持 |
| INVALID_CARD | FAIL | 卡号无效，请核对卡片详细信息或使用其他卡片。 | 显示弹窗提示，可重试 |
| ISSUER_REJECTS_TRANSACTION | FAIL | 发卡行拒绝交易，建议换卡重试或联系发卡行。 | 显示弹窗提示，可重试 |
| PAYMENT_AMOUNT_EXCEED_LIMIT | FAIL | 商户支付金额超过限额，交易无法发起。 | 检查金额是否超限 |
| USER_AMOUNT_EXCEED_LIMIT | FAIL | 金额超限。使用小于或等于账户可用余额的金额重新发起支付。 | 显示弹窗提示，可重试 |
| USER_KYC_NOT_QUALIFIED | FAIL | 用户状态异常。建议换卡重试或换支付方式重试。 | 显示弹窗提示，可重试 |
| DO_NOT_HONOR | FAIL | 支付被发卡行拒绝。建议换卡重试或联系发卡行。 | 显示弹窗提示，可重试 |
| EXTERNAL_RESOURCE_LOAD_FAILED | FAIL | 请求异常，请检查网络状况或者设备情况。 | 显示弹窗提示检查网络 |
| SUBMIT_PAYMENT_TIMEOUT | PROCESSING | 请求异常，交易无法发起。 | 从服务器轮询结果 |
| PAYMENT_RESULT_TIMEOUT | PROCESSING | 请求异常，交易无法发起。 | 从服务器轮询结果 |
| USER_CANCELED | PROCESSING | 无。 | 可重试 |
| FORM_INVALID | FAIL | 无。 | 可重试 |

---

## 9. 最佳实践

### 9.1 加载管理

```javascript
// 显示 loading
showLoading();

try {
  await mount(renderOptions, '#payment-container');
  // mount 完成
} finally {
  hideLoading();
}
```

```javascript
// submitPayment 前后管理
showLoading();
try {
  const result = await submitPayment(options);
  // 处理结果
} finally {
  hideLoading();
}
```

### 9.2 支付结果处理

**重要原则**：
- 客户端 `submitPayment().then()` 返回的结果**仅用于页面导航和状态展示**
- **最终订单状态必须从服务端获取**（通过 `notifyPayment` 或 `inquiryPayment` API）

### 9.3 重定向控制

| notRedirectAfterComplete | 支付结果 | 处理方式 |
|--------------------------|----------|----------|
| `true` | 成功/失败 | 根据 `submitPayment()` 返回的 `{code, status}` 自行处理跳转 |
| `false` | 成功 | 自动跳转到 `paymentRedirectUrl` |
| `false` | 失败 | 根据 `submitPayment()` 返回的错误信息处理 |

### 9.4 3D Secure 处理

```javascript
const result = await submitPayment();

if (result.userCanceled3D) {
  // 买家主动关闭 3D Secure 弹窗
  // 建议从服务端轮询结果
  pollServerResult();
}
```

### 9.5 完整集成示例

```javascript
import { AMSElement } from '@alipay/ams-checkout';

// 1. 创建实例
const paymentElement = new AMSElement({
  environment: 'prod',
  locale: 'en_US',
  sessionData: serverResponse.paymentSessionData
});

// 2. 挂载组件
await paymentElement.mount({
  appearance: { theme: 'default' },
  notRedirectAfterComplete: false
}, '#payment-container');

// 3. 监听事件（可选）
paymentElement.on('paymentMethodChanged', (payload) => {
  console.log('支付方式变更:', payload.type);
});

// 4. 提交支付
async function handlePay() {
  // 可选：前置验证
  const validation = await paymentElement.validateFields();
  if (!validation.isValid) {
    return;
  }

  // 提交支付
  const result = await paymentElement.submitPayment();

  if (result.status === 'SUCCESS') {
    // 跳转到成功页（如果 notRedirectAfterComplete 为 false，SDK 会自动跳转）
    window.location.href = '/payment/success';
  } else if (result.error) {
    // 处理错误
    console.error('支付失败:', result.error.code, result.error.message);
  }
}
```

---

## 附录：业务场景与 API 对应

| 业务场景 | 调用 API |
|----------|----------|
| Payment Element | `createPaymentSession (One-time Payments)` |
| Embedded Checkout Page | `createPaymentSession (One-time Payments)` |
| EasySafePay | `createPaymentSession (EasySafePay)` |