# PayKKa Checkout UI 组件

## 如何工作

Description of image
## 开始前准备

可以安装 PayKKa Checkout UI npm 包，或者通过 CDN 的方式嵌入到 HTML 中：

npm（推荐）
安装 `@paykka/card-checkout-ui`：

npm
```bash
npm i @paykka/card-checkout-ui
```

pnpm
```bash
pnpm i @paykka/card-checkout-ui
```

yarn
```bash
yarn add @paykka/card-checkout-ui
```

为了正常的展示组件，需要全局引入样式：

```typescript
import '@paykka/card-checkout-ui/style.css'
```

CDN 引入
通过 CDN 链接在 HTML 中引入 PayKKa Checkout UI 样式和脚本，推荐使用对应区域的 CDN 链接：

欧洲
```html
<link href="https://checkout.eu.paykka.com/cp/style.css" rel="stylesheet" />
<script src="https://checkout.eu.paykka.com/cp/card-checkout-ui.js"></script>
```

香港
```html
<link href="https://checkout.aq.paykka.com/cp/style.css" rel="stylesheet" />
<script src="https://checkout.aq.paykka.com/cp/card-checkout-ui.js"></script>
```

Sandbox
```html
<link href="https://checkout-sandbox.aq.paykka.com/cp/style.css" rel="stylesheet"/>
<script src="https://checkout-sandbox.aq.paykka.com/cp/card-checkout-ui.js"></script>
```

## 初始化

在正式使用组件之前，您需要初始化 PayKKa 收银台实例：

npm
```javascript
import { PayKKaCheckout } from '@paykka/card-checkout-ui'

// 创建收银台实例
const paykkaCheckout = new PayKKaCheckout({
  sessionId: 'xxx',
  clientKey: 'xxx',
  env: 'xx'
  // ...其他配置
})

// 等待收银台初始化完成再加载组件
paykkaCheckout.init().then(() => {
  // ...加载组件
})
```

CDN
```javascript
// PayKKaCardCheckoutUI 为挂载到 window 上的收银台对象
const { PayKKaCheckout } = PayKKaCardCheckoutUI

// 创建收银台实例
const paykkaCheckout = new PayKKaCheckout({
  sessionId: 'xxx',
  clientKey: 'xxx',
  env: 'xx'
  // ...其他配置
})

// 等待收银台初始化完成再加载组件
paykkaCheckout.init().then(() => {
  // ...加载组件
})
```

强烈建议您不要在 iframe 元素内创建收银台，否则可能导致收银台无法正常使用。

### 初始化配置

目前您可以在创建收银台时进行如下配置：

必填参数用 * 标识

| 名称  | 说明  | 类型  | 默认值  |
|  --- | --- | --- | --- |
| *sessionId | 收银台 ID，用来创建收银台 | `string` | `undefined` |
| *clientKey | 客户端密钥 | `string` | `undefined` |
| *env | 环境配置- `eu` 为欧洲商户
- `hk` 为香港商户
- `sandbox` 为沙箱环境商户

 | `eu | hk | sandbox` | `undefined` |
| locale | 收银台文案展示语言- 不传则获取浏览器语言，若浏览器语言不在[可支持语言列表](#%E8%AF%AD%E8%A8%80)，则默认使用 `en-GB`

 | `string` | 浏览器语言 | `en-GB` |
| hidePaymentButton | 是否隐藏支付按钮- 若隐藏支付按钮，则需要手动调用组件的 `payment` 方法进行支付，用法[参考](#%E8%87%AA%E5%AE%9A%E4%B9%89%E6%94%AF%E4%BB%98%E6%8C%89%E9%92%AE)

 | `boolean` | `false` |
| onPaymentMethodsReady | 收银台已经获取[可用支付方式](#%E6%94%AF%E4%BB%98%E6%96%B9%E5%BC%8F)时调用，返回可用支付方式- 若返回空数组，则表示无可用支付方式，且组件不会展示
- 收银台状态为成功或过期时，同样会返回空数组

 | `(methods: PaymentMethod[]) => void` | `undefined` |
| onInitError | 收银台初始化时报错触发- `error` 为[错误信息](#%E9%94%99%E8%AF%AF%E4%BF%A1%E6%81%AF)
- 收银台状态为成功或过期后再次初始化，同样会触发该回调

 | `(error: PayKKaError) => void` | `undefined` |
| threeDSFrame | 定义 3DS 所需[配置](#3ds-%E9%85%8D%E7%BD%AE) | `ThreeDSFrameConfig` | `undefined` |


下面是对一些配置的详细说明：

### 自定义支付按钮

`hidePaymentButton` 用来配置是否隐藏 PayKKa 内置的支付按钮。

如果您想用自己的支付按钮，可以将 `hidePaymentButton` 配置为 `true` 来隐藏 PayKKa 的支付按钮，用户点击您的支付按钮后，可以调用组件实例暴露出的 `payment` 方法进行支付。

下面用 Card 组件举个例子：

npm
```html html
<button onclick="handleClickPayment()">支付</button>
```

```javascript javascript
// 假设我们已经初始化收银台并把 hidePaymentButton 设置为 true
import { Card } from '@paykka/card-checkout-ui'

// 创建 Card 组件
const CheckoutCard = paykkaCheckout.create(Card, {
  // card 配置
})

const handleClickPayment = () => {
  // 点击支付按钮后，调用 payment 方法进行支付
  CheckoutCard.ref.payment()
}
```

CDN
```html html
<button onclick="handleClickPayment()">支付</button>
```

```javascript javascript
// 假设我们已经初始化收银台并把 hidePaymentButton 设置为 true
const { Card } = PayKKaCardCheckoutUI

// 创建 Card 组件
const CheckoutCard = paykkaCheckout.create(Card, {
  // card 配置
})

const handleClickPayment = () => {
  // 点击支付按钮后，调用 payment 方法进行支付
  CheckoutCard.ref.payment()
}
```

### 语言

目前 PayKKa Checkout UI 支持如下 11 种国际化语言，按照 IETF BCP 47 格式展示：

- `de-DE`：德语（德国）
- `en-GB`：英语（英国）
- `es-ES`：西班牙语（西班牙）
- `fr-FR`：法语（法国）
- `ja-JP`：日语（日本）
- `ko-KR`：韩语（韩国）
- `pt-PT`：葡萄牙语（葡萄牙）
- `ru-RU`：俄语（俄罗斯）
- `zh-CN`：中文（中国）
- `zh-HK`：中文（香港）
- `zh-TW`：中文（台湾）


默认情况下，创建收银台时，我们会从请求到的收银台信息中获取语言，若没有符合的语言则会使用浏览器语言，若仍然不符合则使用 `en-GB`，如果您想固定展示某种语言，则可以在创建收银台的时候配置 `locale`。

### 支付方式

目前 PayKKa Checkout UI 支持如下 8 种支付方式：

- `APPLE_PAY`：Apple Pay
- `GOOGLE_PAY`：Google Pay
- `VISA`：Visa
- `MASTER_CARD`：Master Card
- `JCB`：JCB
- `AMEX`：AMEX
- `DINERS_CLUB`：Diners Club
- `DISCOVER`：Discover


### 3DS 配置

您可以在初始化时定义部分 3DS 配置，目前包含以下配置项：

```typescript
interface ThreeDSFrameConfig {
  /** 3DS 弹窗宽度，不传默认自适应。传 number 单位为 px， 传 string 可自定义单位，最小宽度为 350px */
  modalWidth?: number | string
  /** 3DS 弹窗高度，不传默认自适应。传 number 单位为 px， 传 string 可自定义单位，最小高度为 500px */
  modalHeight?: number | string
}
```

### 欺诈检测

关于欺诈检测（FraudDetection）的配置，请参考 [Fraud Detection SDK](/zh-hans/payments/docs/fraud/fraud-detection)。

### 错误信息

收银台的所有错误都会已 `PayKKaError` 实例的形式抛出，通常包含以下属性：

- `type`: 错误类型
- `message`: 错误信息
- `code`: 错误码，在发生接口错误时，会返回具体的[错误码](/zh-hans/payments/docs/developer-resources/transaction-error-code)


## 如何使用组件

创建收银台实例后，您就可以创建组件了，举个例子，假设我们需要引入组件 Card：

npm
```javascript
import { Card } from '@paykka/card-checkout-ui'
```

CDN
```javascript
const { Card } = PayKKaCardCheckoutUI
```

调用收银台实例的 `create` 方法，传入组件所需参数 `props` 即可创建组件实例：

```typescript
const props = {
  // card props
}

// 调用收银台实例的 create 方法
const InstCard = paykkaCheckout.create(Card, props)
```

`mount` 方法支持传入 `HTMLElement` 对象或者 CSS 选择器字符串，并将组件实例渲染，挂载到真实 DOM 中：

组件实例会提供 `mount` 方法用来将组件渲染到 DOM 上：

```html
<div id="card"></div>
```

```typescript
// 传入 HTMLElement
const container = document.querySelector('#card')
InstCard.mount(container)

// or

// 传入 CSS 选择器字符串
InstCard.mount('#card')
```

到此，组件就成功渲染到页面上了。

## Sandbox 环境使用

如果您想在 Sandbox 环境下接入收银台，这里用 CDN 的方式举例：

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>PaKKa Checkout Sandbox Example</title>
    <!-- 引入 sandbox 环境的样式和脚本 -->
    <link href="https://checkout-sandbox.aq.paykka.com/cp/style.css" rel="stylesheet"/>
    <script src="https://checkout-sandbox.aq.paykka.com/cp/card-checkout-ui.js"></script>
  </head>
  <body>
    <div id="card"></div>

    <script>
      const { PayKKaCheckout, Card } = PayKKaCardCheckoutUI

      // 创建收银台实例
      const paykkaCheckout = new PayKKaCheckout({
        sessionId: 'xxx',
        clientKey: 'xxx',
        // 环境设置为 sandbox
        env: 'sandbox'
        // ...其他配置
      })

      // 等待收银台初始化完成
      paykkaCheckout.init().then(() => {
        // 创建组件，这里用 Card 举例
        const InstCard = paykkaCheckout.create(Card, {})
        const container = document.querySelector('#card')
        // 挂载组件
        InstCard.mount(container)
      })
    </script>
  </body>
</html>
```