Encrypted Card
介绍
Encrypted Card 用于收集并加密卡号、过期时间和 CVV 信息。如果您使用自定义支付表单并希望符合 PCI 标准,建议采用 Encrypted Card。
该方式基于支付 API,接入前需完成商户身份校验,请确认以下条件:
- 已注册商户并获取有效客户端密钥(Client key)。
- 能够自行调用我们的支付 API。
开始前准备
可以安装 PayKKa Checkout UI npm 包,或者通过 CDN 的方式嵌入到 HTML 中:
安装 @paykka/card-checkout-ui
:
npm i @paykka/card-checkout-ui
为了正常的展示组件,需要全局引入样式:
import '@paykka/card-checkout-ui/style.css'
创建 DOM
在您的收银台页面创建 DOM 元素,该元素用于呈现 Encrypted Card。
Encrypted Card 支持将卡号、过期时间和 CVV 合并或分开展示,您需要在 HTML 中预先定义好。
无论您选择如何展示,都需要使用 id
为 encryptedCardWrapper
的祖先元素将放置子表单域的元素包裹,data-eci
则表示对应表单域名称。
下面是两种展示方式的 DOM 定义示例:
<!-- 包裹整个表单的元素 -->
<div id="encryptedCardWrapper">
<!-- 卡号 -->
<div data-eci="cardNumber"></div>
<!-- 有效期 -->
<div data-eci="expiryDate"></div>
<!-- CVV -->
<div data-eci="securityCode"></div>
</div>
Encrypted Card 会根据元素的 id
和 data-eci
属性将表单域插入到指定位置,请务必对元素设置正确的属性名和值。
构建 Encrypted Card
构建参数
创建 Encrypted Card 实例时可传递参数及事件如下:
必填参数用 * 标识
名称 | 说明 | 类型 |
---|---|---|
*merchantId | 商户 ID。 | string |
*clientKey | 客户端密钥。 | string |
locale | 表单项所展示的语言。
| string |
brands | 有效的卡品牌数组。
| string |
styles | 输入框、label 和错误提示文字的样式。 | ElementStylesConfig |
showLabel | 是否展示表单项 label,默认为 true 。 | boolean |
sandbox | 是否使用 Sandbox 环境。 | boolean |
onReady | 身份校验完成后调用,并返回校验结果,若校验成功则返回可用卡品牌。 | (status: boolean, res?: { brands: string[] }) => void |
onActivated | 表单域渲染完成后触发,并返回对应表单域类型。 | (fieldType: FieldType) => void |
onFocus | 表单域获得焦点时触发,并返回对应表单域类型。 | (fieldType: FieldType) => void |
onBlur | 表单域失去焦点时触发,并返回对应表单域类型。 | (fieldType: FieldType) => void |
onBinChanged | 卡 bin 信息改变时触发。
| (binInfo: { binValue: string; brand?: CardBrand }) => void |
onBrand | 检测到卡品牌时调用,返回对应卡品牌。 | (brand?: CardBrand) => void |
onCardEncrypted | 卡信息加密成功后触发,返回加密结果。 | (encryptedInfo: EncryptCardRes) => void |
onCardEncryptionFailed | 卡信息加密失败后触发。 | () => void |
onValidationChanged | 通知表单项验证信息,返回对应表单域类型和验证状态。 | (validationInfo: { fieldType: FieldType; status: FormValidationStatus) }) => void |
初始化
调用 init
方法,携带 Encrypted Card 构建参数进行初始化:
import { PayKKaEncryptedCard } from '@paykka/card-checkout-ui'
const EncryptedCard = PayKKaEncryptedCard.init({
merchantId: 'xxx',
clientKey: 'xxx',
brands: ['VISA', 'MASTER_CARD'],
showLabel: true,
styles: {
input: {
base: {
fontSize: '16px'
},
focus: {
color: 'blue'
},
valid: {
border: '1px solid yellowgreen',
color: 'yellowgreen'
},
invalid: {
border: '1px solid red',
color: 'red'
}
}
}
})
设置 Encrypted Card 样式
Encrypted Card 自带默认样式,您可以自定义输入框、label 和错误提示文案下对应状态的样式,初始化时传递 styles
即可。
styles
对象类型如下,CSSStyleDeclaration
表示我们支持绝大部分符合标准的样式:
interface ElementStylesConfig {
/** input 元素的样式 */
input?: InputStylesConfig
/** label 文案的样式 */
label?: StylesConfig
/** 错误提示文案的样式 */
errorMessage?: Partial<CSSStyleDeclaration>
}
interface StylesConfig {
/** 默认样式 */
base?: Partial<CSSStyleDeclaration>
/** 校验通过时样式 */
valid?: Partial<CSSStyleDeclaration>
/** 校验不通过时样式 */
invalid?: Partial<CSSStyleDeclaration>
/** 聚焦元素时样式 */
focus?: Partial<CSSStyleDeclaration>
}
interface InputStylesConfig extends StylesConfig {
/** placeholder样式 */
placeholder?: {
/** 默认样式 */
base?: Partial<CSSStyleDeclaration>
/** 聚焦元素时样式 */
focus?: Partial<CSSStyleDeclaration>
}
/** 将鼠标悬停在元素上的样式 */
hover?: Partial<CSSStyleDeclaration>
}
下面是一个示例:
const EncryptedCard = PayKKaEncryptedCard.init({
styles: {
input: {
base: {
fontSize: '20px',
fontWeight: 'bold',
padding: '0 0 0 12px',
borderRadius: '0px',
boxShadow: 'none'
},
focus: {
color: 'blue',
caretColor: 'blue',
border: '1px solid blue'
},
valid: {
border: '1px solid yellowgreen',
color: 'yellowgreen'
},
invalid: {
border: '1px solid red',
color: 'red'
}
},
label: {
base: {
fontSize: '20px',
fontWeight: 'bold',
margin: '0',
color: 'purple'
},
valid: {
color: 'yellowgreen'
},
invalid: {
color: 'red'
},
focus: {
color: 'blue'
}
},
errorMessage: {
fontSize: '20px',
fontWeight: 'bold',
margin: '0',
color: 'yellow'
}
}
})
除输入框、label 和错误提示文案外,如果您想更改其他样式,可以直接编写 CSS 代码覆盖我们的默认样式。
加密结果
提交表单的时候,您需要调用 encrypt
方法,如果表单验证通过,我们会对表单信息进行加密:
<button onClick="handleClick">支付</button>
const handleClick = () => {
// 加密
EncryptedCard.encrypt()
}
由于加密过程是异步的,您需要通过注册 onCardEncrypted
事件回调获取加密结果:
let encryptedRes = null
const EncryptedCard = PayKKaEncryptedCard.init({
// 此处省略其他属性
onCardEncrypted: res => {
console.log('加密成功', res)
encryptedRes = res
processPay()
}
})
const processPay = () => {
// 调用支付 API 并传递加密信息 encryptedRes
}
加密结果类型定义如下:
interface EncryptCardRes {
/** 加密后的卡号 */
encryptedCardNumber: string
/** 加密后的 CVV */
encryptedCVV: string
/** 加密后的有效期年份 */
encryptedExpireYear: string
/** 加密后的有效期月份 */
encryptedExpireMonth: string
/** 卡信息 */
cardInfo: {
/** 卡 bin */
bin: string
/** 卡品牌 */
brand: CardBrand
/** 卡号后 4 位 */
last4: string
}
}
部分属性说明
卡品牌
CardBrand
目前我们支持的卡品牌枚举和对应卡品牌如下:
type CardBrand = keyof typeof CardBrandCode
enum CardBrandCode {
/** Visa */
VISA = 'VISA',
/** Mater Card */
MASTER_CARD = 'MASTER_CARD',
/** JCB */
JCB = 'JCB',
/** American Express */
AMEX = 'AMEX',
/** Discover */
DISCOVER = 'DISCOVER',
/** Diners Club */
DINERS_CLUB = 'DINERS_CLUB'
}
表单域类型
FieldType
表单类型枚举及对应描述如下:
type FieldType = keyof typeof EFieldType
enum EFieldType {
/** 卡号 */
CARD_NUMBER = 'CARD_NUMBER',
/** cvv */
CVV = 'CVV',
/** 过期时间 */
EXPIRE_DATE = 'EXPIRE_DATE'
}
验证状态
FormValidationStatus
表单验证状态分为三种,状态值和对应描述如下:
unValidate
: 内容为空。success
: 校验成功。error
: 校验失败。
type FormValidationStatus = 'unValidate' | 'success' | 'error'
示例
下面是从初始化表单域到完成加密的代码示例:
<div id="encryptedCardWrapper">
<!-- 卡号 -->
<div data-eci="cardNumber"></div>
<!-- 有效期 -->
<div data-eci="expiryDate"></div>
<!-- CVV -->
<div data-eci="securityCode"></div>
<button onClick="handleClick()">支付</button>
</div>
let encryptedRes = null
const EncryptedCard = PayKKaEncryptedCard.init({
merchantId: 'xxx',
clientKey: 'xxx',
brands: ['VISA', 'MASTER_CARD'],
showLabel: true,
styles: {
input: {
base: {
fontSize: '16px'
},
focus: {
color: 'blue'
},
valid: {
border: '1px solid yellowgreen',
color: 'yellowgreen'
},
invalid: {
border: '1px solid red',
color: 'red'
}
}
},
onCardEncrypted: res => {
console.log('加密成功', res)
encryptedRes = res
processPay()
}
})
const handleClick = () => {
// 加密
EncryptedCard.encrypt()
}
const processPay = () => {
// 调用支付 API 并将加密信息传入
}
Sandbox 环境接入
Sandbox 环境下接入,需要引入 Sandbox 环境的 CDN,并在初始化时设置 sandbox
为 true
。
<link
href="https://checkout-sandbox.aq.paykka.com/cp/style.css"
rel="stylesheet"
/>
<script src="https://checkout-sandbox.aq.paykka.com/cp/encrypted-card.js"></script>
const EncryptedCard = PayKKaEncryptedCard.init({
// 此处省略其他属性
sandbox: true
})