Bobolo
  • Home
  • Me

ZoidJs

Crypto.com SDK 的实现

8 Min Read

Sat Apr 23 2022

Written By Bobolo

Crypto.com Pay for Business 是 Crypto.com Pay 的产品,主要是提供给 Crypto.com 的 Merchant 使用,方便 Merchant 在自己的网站集成所需要的功能,包含前端和后端。提供 Checkout Subscription Promotion Banner 等功能,文章主要说明 Web 部分。

Web SDK

要想做实现一个 Web SDK 提供给商家,必然会遇到跨域问题,商家域名与 SDK 不可能相同。在这样的情况下,父页面和子页面通信是重点,所以先简单回顾一下跨域的解决方案

  • jsonp:只支持 GET,不支持 POST 请求,不安全 XSS
  • websocket:需要后台配合修改协议,不兼容,需要使用 http://socket.io
  • proxy:nodejs 中间件或 nginx 等代理服务器
  • cors:需要后台配合进行相关的设置
  • document.domain:仅限于同一域名下的子域
  • window.name:配合 iframe,需要一个代理 proxy.html
  • location.hash:借助中间页实现
  • postMessage:配合使用 iframe,需要兼容 IE6、7、8、9

SDK 是需要具备可持续交互的功能,并不是单一跨域成功获取资源即可,如果每次通信需要 发送请求 或者 刷新界面 的方式是不适合的,即使能完成功能,性能也有非常大的问题,所以可以排除

  • jsonp
  • proxy
  • window.name
  • websocket

然后我们对比剩下的可选方案,document.domain 需要在同一域名也可以排除,cors 同样也可以排除

  • location.hash
  • postMessage

location.hash,本质是借助 hastchange 来进行通信,子页面可以通过 hashchange 来获取父页面的通知,但是父页面难以知道子页面通知,需要借助 setInterval 等轮训来实现,最后我们看看 postMessage

postMessage

postMessage Api,它主要是可以实现安全地跨域通信。通常使用在页面和它生成的弹出窗口,或者页面和嵌入其中的 iframe。

广义上讲,一个窗口可以获得对另一个窗口的引用(如 targetWindow = window.opener),然后用 targetWindow.postMessage() dispatch 一个 MessageEvent 给它。接收窗口可以根据需要自由处理此事件。

Flow

它既可以不需要发送网络请求,同时也不需要对页面进行刷新,是比较当然跨域必不可少的安全问题是需要注意的。

  • 不希望从其他网站接收 message,则不要为 message 事件添加任何事件侦听器
  • 请始终使用 origin 和 source 属性验证发送人身份
  • 使用 postMessage 将数据发送到其他窗口时,始终指定精确的 origin,而不是 *。

ZoidJs

Zoidjs,由 PayPal 开发的用于构建跨域交互的 JavaScript 库。这些组件可以是独立的,具有自己的 HTML、CSS 和 JavaScript,也可以与父级页面进行通信,从而创建高度交互性的用户界面。

虽然 postMessgae 可以进行跨域通信,但是它还不是很完善,有不少的场景下还是有缺陷,如

  • 没有响应或回调,这使得从另一个窗口请求数据和获取信息非常困难
  • IE/Edge 不允许 postMessage 在两个不同域的弹出窗口和父窗口之间使用
  • 不存在的错误处理。不能确定其他窗口是否收到过发送的消息
  • 不能发送其他数据类型,比如 function、promise、error objects 等

post-robot

post-robot,Paypal 实现的跨域消息传递的 Javascript 库,是 Zoidjs 的依赖之一,解决了上所说的问题。

<!-- 引入 Post-Robot 库 -->
<script src="https://unpkg.com/[email protected]/dist/post-robot.min.js"></script>

<!-- 发送消息 -->
<script>
  postRobot.send(window.parent, 'hello from A')
</script>
<!-- 引入 Post-Robot 库 -->
<script src="https://unpkg.com/[email protected]/dist/post-robot.min.js"></script>

<!-- 接收消息 -->
<script>
  postRobot.on('message', event => console.log('received message:', event.data))
</script>

Implementation

以 Checkout Button 为例来说明实现的流程,流程以现有的 SDK 文档信息为基础,不会超过现有文档的内容,主要是数据脱敏和安全问题。

SDK 的使用会涉及三个对象,Merchant、Customer、Crypto.com。

  • Merchant:商家需要通知 Crypto.com 扣取用户货币
  • Customer:用户用于购买和扣取手中的货币
  • Crypto.com:确保信息安全和执行商家要求

所以 Crypto.com 需要提供给 Merchant 一个能配对的 secret key 和 publishable key,用于确认商家。商家需要向 Crypto.com 请求创建一个 Payment。用户则确定扣取货币以及类型等信息。

Flow

部分 Merchant 可能不需要 Server,也可以只集成 Web SDK 的部分。

Flow

Zoid 的作用

上面是整个功能的 Flow,Zoid 主要的是 Crypto.com 提供给 Merchat 一些固定的 Api 和功能,它在 Merchant 使用时的作用为以下几点

  1. 在 Merchange Page 中 Create Iframe 并增加 listener 来接收 Iframe 的 message
  2. Iframe 渲染完成后同样增加 listener 用来初始化 Iframe 的window.xpropx,listener 的通信就是 Zoid 中的 post-robot
  3. Merchange Page 在 Iframe 渲染完成后将定义的 Props Send 给 Iframe,完成初始化
  4. 后续业务逻辑在 Iframe 中完成
  5. 当业务逻辑处理完后需要执行 onApprove() 时,用 window.xpropx.button.onApprove()

Iframe 中执行 window.xpropx.button.onApprove(data),不是直接执行 onApprove,而是通过 post-robot 传过去 data 和 emit listener 去执行 onApprove

Flow

Flow

Flow

Conclusion

Zoid 是一个不错的跨域组件库,它也同样支持 React、Vue,在需要用到做 SDK 时是一个不错的选,以 Npm 的形式可能需要更多的维护成本,因为又不同的框架需要兼容,也不如 Iframe 的使用场景广泛,Iframe 实在是浏览器本身支持的功能。

Paypal 实现的 post-robot 加强了 postMessage,它序列化 Promise 等特殊对象,是个比较有意思的地方,值得去了解。

Reference

Powered by Bobolo

Copyright © Bobolo Blog 2021