@ co栏-na/ card- reveal
在您的网页上显示一列卡的完整号码, CVV, 过期和持卡人名 。 卡片数据从不触及你的代码或服务器.
如何运作
- 浏览器 电话
client.prepareReveal()。列框为https://reveal.column.com让你的页面只有指纹,keyThumbprint。用卡片标识发送到您的服务器. - 您的服务器 使用您的 API 密钥创建单一用途的显示符, 有效期为 1 分钟, 绑定在该密钥上 :
请检查access-indate=中的日期值 (帮助) 登录用户在这样做之前拥有卡. 那就只发信条curl -X POST 'https://api.column.com/issuing/cards/<card_id>/reveal-tokens' -u :<YOUR API KEY> \ -H 'Content-Type: application/json' -d '{"reveal_key_thumbprint": "<keyThumbprint>"}' # {"id":"crtk_...","card_id":"card_...","expires_at":"...","reveal_key_thumbprint":"..."}id到浏览器. - 浏览器 电话
prepared.reveal(...)还有身份证和证物 每个值都会在自己孤立的iframe内被Colle所服务,所以你的页面的JavaScript无法读取. 帧直接从Colonel的API取出卡片细节,加密端到结束到一次性密钥上,该密钥从未离开帧. 信使只用那把钥匙 所以从你的日志或页面上漏出的信使 对其他人都没用.
安装
npm install @column-na/card-reveal
或者装入主机脚本, 绑入精确的版本 与子资源完整性。 每个版本的标记,包括其散列,都在该版本的发行注释中:
<script
src="https://reveal.column.com/<version>/card-reveal.js"
integrity="sha384-..."
crossorigin="anonymous"
></script>
<script>
const client = window.ColumnCardReveal.createCardRevealClient({ environment: 'live' });
</script>
主机脚本拒绝创建客户端( H)integrity_required),除非 <script> 标签有一个 integrity 属性持有一个或多个 sha256-, (中文(简体) ), sha384- 或者说 sha512- hashes, 值浏览器验证 。 SDK读取了浏览器的属性方式:散列由ASCII白相间相隔,每个散列都必须有良好的外形. 占位符,一个没有浏览器检查的算法,或者一个散列浏览器无法解析(一个是随即从文档粘贴到的不破空格,比如),同样遭到拒绝,因为一个浏览器跳过它无法解析的东西,然后将脚本装入完全没有检查. 装入经典 <script src> 标记如下: <script type="module"> 不被支持,因为模块脚本无法看到自己的标记,因此无法分辨它是否已被验证. 每个版本的文件发布一次,永远不变. 版本最多为0.1.3 https://js.column.com/card-reveal/<version>/card-reveal.js呆在这里.
使用量
import { createCardRevealClient, CardRevealError } from '@column-na/card-reveal';
// Create one client and reuse it.
const client = createCardRevealClient({ environment: 'live' }); // or 'sandbox'
// One prepared reveal per token: makes the one-time key, and gives you its thumbprint to mint with.
const prepared = await client.prepareReveal();
const revealToken = await myServer.createRevealToken(cardId, prepared.keyThumbprint);
const { ready, unmount } = prepared.reveal({
cardId,
revealToken,
fields: {
pan: '#card-number',
cvv2: '#cvv2',
cardholder_name: '#name',
expiration_month: '#exp-month',
expiration_year: '#exp-year',
},
style: { color: '#fff', 'font-family': 'ui-monospace, monospace', 'font-size': '15px' },
fieldStyles: { pan: { 'font-size': '19px' } },
format: { pan: 'spaced', expirationYear: 'YY' },
timeoutMs: 15000,
});
try {
await ready;
} catch (error) {
if (CardRevealError.is(error)) showMessage(error.code); // error.field and error.status when known
}
// Later, or when the component unmounts:
unmount();
在反应中,使用下面的绑定或调用 reveal 影响和返回 unmount 作为它的清理。 每一次揭发都需要一个新的标志, 因为标志是单用 prepareReveal(),因为每个准备的密钥都使用过一次.
反应
@column-na/card-reveal/react 准备是否 ? 薄荷 ? 显示 ? 卸载序列
import { CardRevealProvider, CardRevealSlot } from '@column-na/card-reveal/react';
<CardRevealProvider
client={client}
cardId={cardId}
mintToken={({ cardId, keyThumbprint }) => myServer.createRevealToken(cardId, keyThumbprint)}
>
<CardRevealSlot field="pan" style={{ width: 280, height: 30 }} />
<CardRevealSlot field="cvv2" style={{ width: 60, height: 30 }} />
</CardRevealProvider>;
mintToken({ cardId, keyThumbprint })请求您的服务器提供一个绑定在 启示的密钥上的符号并用它解决id每一次都叫这个.<CardRevealSlot field="...">是一个空的<div>一个字段的框填满, 所以给它一个宽度和高度。 这需要任何div属性.<CardRevealProvider>还要style, (中文(简体) ),fieldStyles, (中文(简体) ),format, (中文(简体) ),timeoutMs财务报告和审定财务报表enabled(默认)true· ;false或隐藏显示的牌.- 在它内部,
useCardRevealState()返回时{ status, error, retry }。 。 。 .status实值'idle', (中文(简体) ),'preparing', (中文(简体) ),'minting', (中文(简体) ),'revealing', (中文(简体) ),'ready'或者说'error'。 。 。 .error是一个CardRevealError(与CardRevealError.is或随便什么mintToken抛出.retry()以新的键和符号开始 . - 改变客户端,卡片,插槽,样式,
format或者说timeoutMs用新的符文再次显示;卸载提供者卸载该符文。 为永不发生的启示准备的密钥( 卸载, 或严格模式的双挂载) 被丢弃 . useCardReveal({ client, cardId, mintToken, fields })跟钩子一样fields将每个字段映射到一个CSS选择器,如果你宁愿自己管理容器的话.
按键符号 : prepareReveal()
client.prepareReveal() 将下一个显示的一次性 P-256 键对放在 Colon's 框内,作为不可提取的 WebCrypto 键,在符号存在之前. 它决心:
keyThumbprint键的 RFC 7638 (法语) SHA-256拇指印,基底64url不粘贴(43个字符). 传到你的服务器上 用它来铸造信物reveal_key_thumbprint这是公用钥匙的散文 不是秘密.reveal(options):用该键显示,具有相同的选项和结果:client.reveal()。它可能被称为一次;第二次呼叫invalid_options。在使用密钥前丢出无效的选项,所以更正后的调用仍然可以使用.discard():在不透露的情况下放下密钥并去掉其隐藏的框,因为当透露不会发生时(指使无法被刻出,或者页面移动了). 后来reveal()掷出invalid_options。 。 。 .
列只为发送密钥的启示回答绑定符. 任何其它密钥都有一个 401 (单位:千美元)reveal_failed)),而代币并未用完. prepareReveal() 拒绝方式 script_load_failed, (中文(简体) ), reveal_failed 或者说 timeout 如果框架不能制造钥匙。 直到曝光时,密钥会在结尾处一个隐藏的零尺寸框中等待 <body>;被揭示会删除.
每一个显出的迹象都用一个 reveal_key_thumbprint,所以,每一次披露从 prepareReveal()。 。 。 . client.reveal() 选择相同的选项,但为另一个密钥刻出一个符号,或者没有准备的密钥的显示,得到一个 401。 。 。 .
选项
| 选项 | 说明 |
|---|---|
cardId | 该卡的身份证( E)card_...) (中文(简体) ). |
revealToken | 显式代号 ID (crtk_...从您的服务器上。 单用,有效期为一分. |
fields | 地图 pan, (中文(简体) ), cvv2, (中文(简体) ), cardholder_name, (中文(简体) ), expiration_month, (中文(简体) ), expiration_year 财务报告和审定财务报表 pin 用于集装箱的CSS选择器。 只包含您想要的字段; 见 揭发PIN。 。 。 . |
style | 每个字段的样式. |
fieldStyles | 每个字段样式,在顶部应用 style。 。 。 . |
format.pan | 'spaced' (默认 : 4111 1111 1111 1111 16位数字)或 'plain'。 。 。 . |
format.expirationYear | 'YYYY' (违约)或 'YY'。 。 。 . |
timeoutMs | 多长时间 ready 在拒绝前等待 timeout. 默认为 15000,最高为 120000. |
copyable | true,或每个字段({ pan: true }:字段成为列框内的复制按钮. 见 复制、隐藏和显示. 仅网. |
onCopy | 打电话 { field, copied } 每次拷贝后,在 copied 表示浏览器是否接受. 从不值钱. |
hidden | true 显示被遮蔽的字段( e)••••直到你打电话 show()默认 false。 。 。 . |
autoHideMs | 卸载此数毫秒之后的显示 ready 决议(1至360000). |
onAutoHide | 打电话一次 autoHideMs 卸载显示. |
样式对象接受 CSS 属性( kebab- case 或 cameasCase), 伪类块, 如 '&:hover': { ... }, (中文(简体) ), '@media (...)': { ... } 财务报告和审定财务报表 '@font-face': { ... }。样式适用于iframe内部,每个容器决定iframe的大小,因此给您的容器一个宽度和高度.
一个 '@font-face' 规则 src 必须将字体嵌入为基数64 data: URL (中文(简体) )url(data:font/ttf;base64,...) format("truetype")),或用 local(...)A级 src 在 URL 中点数被丢弃,而 iframe 永远不会取出它: 装入的框的字体会告诉该服务器卡片数据包含的字符。 一个样式,包括其嵌入式字体,作为JSON可能高达256KB.
内嵌字体必须是 纯真Type: sfnt 文件 (.ttf,签名 00 01 00 00 或者说 true仅由 cmap, (中文(简体) ), glyf, (中文(简体) ), head, (中文(简体) ), hhea, (中文(简体) ), hmtx, (中文(简体) ), loca, (中文(简体) ), maxp, (中文(简体) ), name, (中文(简体) ), post, (中文(简体) ), OS/2 财务报告和审定财务报表 gasp 表格,每张格子是简略的轮廓(无复合格子),取自其原生地约2em(从-1em到+2em之间),而前行宽度不超过2em, 未装入 (无) cvt , (中文(简体) ), fpgm 或者说 prep 表格和无格言指示),最多 64个KBWOFF和WOFF2, OpenType CFF (中文(简体) ).otf),字体收藏,提示字体,并有布局的字体 (GSUB, (中文(简体) ), GPOS, (中文(简体) ), GDEF),颜色或变相表不能通过. 未通过字体会默默地删除, 与不安全值相同, 文本会在您的下个字体中生成 font-family 列表中,请列出一个倒数。 为什么:页面可以给一个揭示的时间,而一个字体的大小并不约束它的成本. 格莱克可能画得远远超出它的模具 font-size,WOFF2将兆字节的轮廓打入了千字节,一个替代特性将一个字符扩展为许多格来克,复合格来克乘积分,一个提示程序是将浏览器的光栅器运行到每个格来克来克来克来克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克去克.
正在准备字体 . 运出的一个品牌字体通常带有克宁(GPOS• 结扎(GSUB),并提示,并常常是复合格言,所以导出一个副本用于揭示: 平坦的TrueType,无插图,没有布局表,只有显示的字符. 与 字体工具数字 :
pyftsubset brand.ttf --flavor= --no-hinting --layout-features='' --drop-tables+=GSUB,GPOS,GDEF,DSIG,kern --unicodes=U+0020-007E --output-file=brand-reveal.ttf
然后分解子集保存的任何复合甘油 (fontTools') DecomposingRecordingPen 重放为 TTGlyphPen,作为 conformance/scripts/plain-fonts.py 在SDK仓库中,检查文件最多为64 KB,并嵌入为 url(data:font/ttf;base64,...) format("truetype")。 。 。 .
样式是被限定的,因为页面可以给一个揭示的时间,一个值需要多长时间来作画,决不能取决于它所说的内容. 使用一个提供页面的字体,一个数字的格莱弗非常昂贵,在模糊的阴影下,每个浏览器中,数字的数值都大大延长了文字的长度。 所以说:
font-size被夹住 96px (英语) (截至2004年12月31日)min(<your value>, 96px),无论单位)和font手写,zoom, (中文(简体) ),font-size-adjust财务报告和审定财务报表text-size-adjust拒绝。 字体大小的关键词( Q)large, (中文(简体) ),larger通过。 。 .text-shadow财务报告和审定财务报表box-shadow保持最多 2个 阴影,每个阴影最多 8个px (赐入px. 带有更多阴影、更大的模糊或var()或者说calc()完全放弃.filter, (中文(简体) ),backdrop-filter, (中文(简体) ),transform(和transform-*, (中文(简体) ),translate, (中文(简体) ),rotate, (中文(简体) ),scale, (中文(简体) ),perspective, (中文(简体) ),-webkit-text-stroke, (中文(简体) ),text-emphasis, (中文(简体) ),mask, (中文(简体) ),paint-order财务报告和审定财务报表will-change拒绝,如-webkit-box-reflect销售商前缀的拼写-webkit-transform, (中文(简体) ),-moz-transform, (中文(简体) ),-webkit-filter,.)作为别名的财产处理,因此,它被拒绝,被夹住或被捆绑的方式相同.- 每个嵌入
@font-face字体可能最多 64个KB 解码后必须纯正无缝的TrueType,其模具箱内有简单的格子,如上;size-adjust被拒绝。 每个格莱克最多可以 600点 财务报告和审定财务报表 30 轮廓 (一个复杂的文字glyph有不到400和30个),其大纲最多可能 32分钟 长相,沿轴被测量(每相轮廓相绕相接点之间的水平和垂直距离之和):画出壁画的成本是其边缘交叉多少个扫描线,一个64 KB字体可以持有30,000个相接点的壁画,而每个相接点都横跨于盒子上,甚至有600个相接点是1,800 em相接点. 在对macOS的TrueType字体的调查中,包含最密集的Songti和STheiti的CJK glyphs都低于26em;只有shush ligature,遮荫图案和书法阿拉伯语ligatures超过32em. - 框从不合成 粗体 或者说 斜边 永远不要计算 跳转到 相交点( e)
font-synthesis: none财务报告和审定财务报表text-decoration-skip-ink: none在它自己的样式表,一种样式不能凌驾于此之上,因为两者都将油漆作品相乘于每格力. 宣布一个粗体或斜体的脸@font-face如果你想要的话;font-weight财务报告和审定财务报表font-style然后选择它。 下划线通过下划线直接取出. background-clip: text拒绝,因为长手(前缀与否)和内部background简指:是每幅画上再穿透出一幅格言图. A 类var()内background-clip或者说background因为它可能扩大至text; 写出数值.
在这些界限以外的财产被悄悄地抛出,一个不安全价值的方式;揭示仍然成功.
ready, (中文(简体) ), unmount, (中文(简体) ), hide 财务报告和审定财务报表 show
ready一旦每个请求字段都打开,就解决.- 如果有球场失败,或者超时,
ready拒绝和每个字段都被删除。 一个启示显示它所有的田地或者没有它们. unmount()删除每个字段。 若为ready仍然悬而未决,它拒绝unmountedA级ready已经解决了的 仍然解决.hide()财务报告和审定财务报表show()面罩并解开每个字段;见 复制、隐藏和显示。 。 。 .- 丢弃无效的选项
invalid_options同步从reveal()。 。 。 .
复制、隐藏和显示
const reveal = client.reveal({
cardId,
revealToken,
fields: { pan: '#pan', cvv2: '#cvv2' },
copyable: { pan: true },
onCopy: ({ field, copied }) => showToast(copied ? 'Card number copied' : "Couldn't copy"),
autoHideMs: 60_000,
onAutoHide: () => showRevealButton(),
});
hideButton.onclick = () => reveal.hide();
showButton.onclick = () => reveal.show();
- 收到了,长官. 可复制字段是框内的一个按钮(可聚焦,
role="button",标题"Copy". 点击、 Enter 或 Space 从框内写入剪贴板的值, 因此它永远不会通过您的页面; 您只得到onCopy({ field, copied })。一个卡号会被复制,没有空格。 复制控件有类copyable,所以样式可以瞄准它:'&.copyable:hover', (中文(简体) ),'&:focus-visible': { outline: '2px solid #0a84ff' }显示您自己的确认onCopy。 。 。 . - 浏览器. 目前Chrome, Edge, Firefox 和 Safari 复制到点击, Enter and Space. SDK代表们
clipboard-write只可复制的框架( e)allow="clipboard-write"),并倒转至document.execCommand('copy')在无法使用或拒绝使用剪贴板 API 的框内。 如果两者都不起作用,copied实值false什么都没有写. hide()财务报告和审定财务报表show()覆盖每个设置的字段(每个字符但空格显示为•,所以布局会保留),并再次显示,没有新的符号或请求. 一个隐藏的字段不会复制. 两人之后什么都不做unmount()或者失败.hidden: true开始伪装.autoHideMs删除很久后的字段ready,作为unmount()does:这些值已经消失,再次显示它们需要一个新的符号.ready继续解决,以及onAutoHide被叫做一次。 使用hide()如果你想让持卡人再给他们看一次.
错误
每个错误都是 CardRevealError 拥有稳定 code启用 CardRevealError.is(error) 检查,因为它也工作 跨越单独的副本 SDK.
code | 含义 |
|---|---|
invalid_options | 糟糕的选项( 驱动同步) , 或者没有浏览器环境 . |
integrity_required | 主机脚本 <script> 标签没有 integrity 带有属性 sha256-, (中文(简体) ), sha384- 或者说 sha512- 散列,或作为模块脚本装入. |
script_load_failed | 列的显示框无法装入. 下一个 reveal() 重试. |
container_not_found | 没有元素匹配字段选择器 . field 已经设定. |
reveal_failed | 披露请求失败 . status 当知道时,即设定 apiCode 当列的 API 返回出错代码时. 401 指代号缺失,无效,已经使用,过期,用于不同的卡片或绑入不同的显示密钥. |
timeout | timeoutMs 在每一块地都变成原地之前就已经过去了. |
unmounted | unmount() 被调用之前的披露完成. |
出错消息从不包含符号或任何卡片数据,SDK也从不登录.
揭发PIN
添加 pin 改为 fields 显示借记卡的PIN。 SDK 只为您列出的字段询问列, 所以 PIN 只在您包含时返回 pin,而只有PIN的显示不能返回卡号或CVV. 您的服务器以同样的方式创建出信号符 。 该卡的程序必须允许 PIN 显示 。 在你透露他们的PIN前 检查持卡人.
启示 pin 而不是卡片号码旁边 如果PIN不能被揭示,整个揭示失败了,所以与其他域一起要求它也会隐藏这些. 当它失败时, reveal_failed 将列的错误代码载入 apiCode数字 :
apiCode | 含义 |
|---|---|
pin_not_revealable | PIN是在PIN披露之前设定的. 重新设置 PIN 使其可公开 . |
feature_not_enabled | PIN显示卡程序没有启用. |
invalid_field_value | 该卡没有PIN,或者不是借记卡. |
这些失败发生在使用显式符号之前, 所以同样的显式仍然有效 pin。 。 。 .
沙盒活下来
| 现场直播 | 沙盒 | |
|---|---|---|
| 数据 | 真实牌 | 模拟牌 |
| 渲染 | 每个栏目1个 | 每个栏目1个 |
| 请求 | Live-Mode: Yes | Live-Mode: No |
两者在 Colle 的显示框中渲染,从中获取卡片细节 GET https://api.column.com/issuing/cards/{id}/reveal,加密端到端, 所以沙盒看起来和行为像活。 在沙盒里, sandboxBaseUrl 可以将框架指向本地的模拟:必须是 https://api.column.com (默认)或平面 http://localhost 或者说 http://127.0.0.1 与任何端口。 其他一切,包括: https 在回转时,丢出 invalid_options。 。 。 . renderer: 'column' 不再需要,也改变不了任何东西.
内容安全政策
每条信息都显示在列框中 https://reveal.column.com,而您的页面本身不会获取任何东西.
script-src 'self' https://reveal.column.com;
frame-src https://reveal.column.com;
- 丢弃
https://reveal.column.com从script-src如果你从 npm 安装. - 您的页面不需要
connect-srcsDK,在沙盒或活的,没有'unsafe-inline'。 。 。 .
版本
这个软件包遵循语义化的版本,主机脚本和回放原生SDK的同版本发行. 准确的版本。 每个请求都会发出 X-Column-SDK-Version: card-reveal-js/<version> 因此,列可以知道你运行的哪个版本.
许可证
专有. 使用须遵守列卡显示的 SDK 许可证 LICENSE 并需要与Colle协议.