使用原生JS实现一个简易的支付SDK

2 阅读3分钟

起因

最近接到一个需求,后端需要实现一个信用卡支付的功能,一开始让我在已有的系统上完成一个静态的表单,后端通过iframe在页面中嵌入表单,本地调试非常顺利,最后一步上线测试时发现iframe嵌套存在跨域问题,查阅资料发现并没有一个相对安全解决办法。再次与后端沟通后,发现他想要的功能就是一个类似支付的的SDK,可以同工具函数一样,在需要的地方引入,生成一个动态的form表单,调用提交按钮发起支付请求,最后再将支付结果返回给后端即可。

实现思路

理解真正的需求之后,发现实现起来也很简单。

 1.创建一个支付方法的类
 2.实现动态生成表单函数createPaymentForm
 3.实现收集表单数据函数collectFormData
 4.实现支付回调函数handleFormSubmit

代码实现

class PaymentSDK {  
  constructor(config) {  
      this.config = config;  
      // this.createPaymentForm()  可以构造函数中初始化表单 也可以手动调用 更加灵活
      // 初始化其他必要的设置或服务  
  }  

  // 创建一个支付表单的HTML  
  createPaymentForm() {  
      const formHTML = `  
          <form id="payment-form">  
            <div class="form-item">
              <label for="card-number">Cardholder Name:</label>  
              <input type="text" id="card-name" name="card-name">
            </div>
            <! -- 其他参数 -->
          </form>  
      `;  

      const bodyHtml = document.createElement('div')
      bodyHtml.innerHTML = formHTML
      if(this.config?.doc) { // 表单可以挂载在指定元素下,可以默认挂载在body
        const doc = this.config.doc
        doc.appendChild(bodyHtml)
      } else {
        document.body.appendChild(bodyHtml);  
      } 
  }  

  // 处理表单提交  
   handleFormSubmit() {  
      // 由于是示例,我们将仅打印表单数据  
      console.log('Form submitted with data:', this.collectFormData());  
      const {name, } = this.collectFormData()
      
      // 真实场景中,你会调用支付API,并处理响应  
      return new Promise((resolve, reject) => {
        // 这里可以直接使用fetch 不用引入jquery 现在的浏览器基本都支持fetch
        fetch('payUrl',{
          method: 'POST',
          headers: {  
            'Content-Type': 'application/json',  
          }, 
          body: JSON.stringify({
           // 支付需要的参数
          })
        }).then(res => {
          resolve('sucess',res)
        }).catch(err => {
          reject('err',err)
        })
      })
  }  

  // 收集表单数据  
  collectFormData() {  
      const name = document.getElementById('card-name').value
      // ...其他参数
  
      // 这里可以处理或转换formData以适应API的需求  
      return {
        name,
        // 其他参数
      };  
  }  
}

美化表单

上面的实现是一个简易的form表单,可以添加一些style样式来美化表单。

const styleTextt = `
  .form-item {
    display: flex;
    align-items: center;
    margin-bottom: 12px;
  }

  .form-item label {
    display: inline-block;
    height: 32px;
    line-height: 32px;
    margin-right: 12px;
    width: 150px;
    text-align: right;
    color: #606266;
    font-size: 14px
  }
  input {
    flex: 1;
    height: 32px;
    background: none;
    border-radius: 4px;
    padding: 1px 11px;
    border: 1px solid #dcdfe6;
    box-shadow: 0 0 0 1px var(#dcdfe6, #dcdfe6) inset;
  }
  input:hover, input:focus {
    border-color: #429a9a;
  }
  input:focus-visible {
    outline: none;
  }
`
class PaymentSDK {  
  constructor(config) {  
      this.config = config;  
      // this.createPaymentForm()  可以构造函数中初始化表单 也可以手动调用 更加灵活
      // 初始化其他必要的设置或服务  
  }  

  // 创建一个支付表单的HTML  
  createPaymentForm() {  
      const formHTML = `表单HTML`;  
      let style = document.createElement('style')
      style.type = 'text/css'
      style.innerHTML = styleTextt
      document.head.appendChild(style);
      const bodyHtml = document.createElement('div')
      bodyHtml.innerHTML = formHTML
      if(this.config?.doc) { // 表单可以挂载在指定元素下,可以默认挂载在body
        const doc = this.config.doc
        doc.appendChild(bodyHtml)
      } else {
        document.body.appendChild(bodyHtml);  
      } 
  }  

  // 处理表单提交  
   handleFormSubmit() {  
      // 由于是示例,我们将仅打印表单数据  
      console.log('Form submitted with data:', this.collectFormData());  
      const {name, } = this.collectFormData()
      // 真实场景中,你会调用支付API,并处理响应  
  }  

  // 收集表单数据  
  collectFormData() {  
      const name = document.getElementById('card-name').value
      // ...其他参数
  
      // 这里可以处理或转换formData以适应API的需求  
      return {
        name,
        // 其他参数
      };  
  }  
}

使用示例

<!DOCTYPE html>  
<html lang="en">  
<head>  
    <meta charset="UTF-8">  
    <meta name="viewport" content="width=device-width, initial-scale=1.0">  
    <title>Payment SDK Example</title>  
    <script src="payment-sdk.js.js"></script>
    <!-- 假设你的SDK脚本保存为payment-sdk.js -->  
    <style>
      #form {
        width: 500px;
      }
    </style>
</head>  
<body>  
    <div id="form"></div>
    <script>  
        const form = document.getElementById('form')
        const sdkConfig = {  
            // 这里填入你的支付服务配置,如API密钥等  
            doc:form
        };  
  
        const paymentSDK = new PaymentSDK(sdkConfig);  
        paymentSDK.createPaymentForm()
        paymentSDK.handleFormSubmit().then(res => {
          console.log(123, res)
        });  
    </script>  
</body>  
</html>

这样一个简易的支付SDK就完成了,可以将js放在项目文件中,也可以传到服务器。