developer
  • 前言
    • changelog
  • 产品
    • 内嵌式收银台
    • 收银台
    • Server直连
  • 对接指导
    • 环境 BASE_URL
    • 签名指导
      • 签名
      • 验签
    • 集成指导
      • 沙盒启用
      • 生产启用
      • PCI 合规介绍
      • 沙盒测试
        • 测试卡号
        • 测试案例
  • Reference
    • API Reference(信用卡)
      • 收银台
        • 支付/预授权
      • 内嵌式收银台
        • JavaScript
        • Create Token
      • 订单
        • 预授权撤销
        • 退款
        • 订单详情
        • 预授权完成
      • 参数说明
      • Google Pay API
    • Local Pay 本地化
      • 本地化汇总
      • 本地化接口
        • 便利店支付
          • konbini
          • payeasy
        • 分期付款 Pay Later
          • Klarna
        • 电子钱包
          • Alipay
          • Wechat-HK
            • Jsapi支付下单接口
            • 小程序支付
            • 微信公众号支付
            • 扫码支付
        • 银行转账
          • Giropay
          • sofort
          • bancontact
          • Ideal
        • 本地化Card
          • carnet
        • Cash(Ticket)现金支付
          • Cash Common
          • oxxo
          • boleto
        • Other
      • 支付方式(国家/地区)
        • 荷兰
        • 巴西
        • 墨西哥
        • 中国香港
        • 日本
        • 德国
        • 奥地利
        • 西班牙
        • 波兰
        • 意大利
        • 哥伦比亚
        • 比利时
        • 瑞士
    • 物流接口
      • 物流信息上送
        • 物流信息上传2.1
        • 物流信息上送(已废弃)
      • 物流信息查询
        • 物流信息查询2.1
        • 物流信息查询(已废弃)
    • 错误码(错误信息)
    • 业务结果码(鉴定支付结果)
    • 同步/异步通知
      • 同步通知
      • 异步通知
    • Demo
  • 规范性说明
    • 货币单位
    • 国家信息参考
  • FAQ
    • 意见和建议
    • 支付和预授权的区别
Powered by GitBook
On this page
  • MD5
  • 生成MD5密钥
  • 生成MD5签名规则
  • MD5签名生成示例
  • RSA
  • 生成商户RSA密钥对
  • 上传商户RSA公钥
  • 保存 UseePay RSA 公钥
  • 生成RSA签名规则
  • RSA签名生成示例
  1. 对接指导
  2. 签名指导

签名

Previous签名指导Next验签

Last updated 3 years ago

UseePay 使用签名-验签名机制来防止数据传输的过程中被篡改。目前 API 集成 UseePay 支持两种签名方式: MD5, RSA。无论是 MD5 还是 RSA 方式, sign 和 value trim后为空的 key-value 都不参与签名计算过程!

MD5

生成MD5密钥

在 UseePay 商户后台的配置中心->密钥管理中点击获取MD5密钥

生成MD5签名规则

  1. 按照ASCII码生序对请求的 payload 进行排序

  2. 按第一步获取的结果,进行key-value 遍历, 对 value trim 后不为空的 key-value 使用 URL 键值对的格式进行拼接(key1=value1&key2=value2...),

  3. 第2步取到字符串, 拼接上 &pkey=商户的MD5密钥, 然后对该字符串进行MD5, 得到的值即为签名值

MD5签名生成示例

function getPayload(){
    payload['version'] = '1.0'
    payload['autoRedirect'] = false
    payload['transactionId'] = ORDER_ID_IN_YOUR_SYSTEM
    payload['transactionType'] = 'pay'
    payload['transactionExpirationTime'] = 14400
    payload['appId'] = YOUR_APP_ID
    payload['amount'] = 1234
    payload['currency'] = 'USD'
    
    const userInfo = {
        userId: USER_ID_IN_YOUR_SYSTEM,
        phoneNo: USER'S_PHONE_NO,
        email: USER'S_EMAIL,
        IP: USER'S_IP
    }
    payload['userInfo'] = JSON.stringify(userInfo)
    
    const payerInfo = {
        paymentMethod: 'credit_card',
        authorizationMethod: 'cvv'
    }
    const billingAddress = {}
    billingAddress['houseNo'] = CUSTOMER'S_HOUSE_NO
    billingAddress['email'] = CUSTOMER'S_EMAIL
    billingAddress['phoneNo'] = CUSTOMER'S_PHONE_NO
    billingAddress['firstName'] = CUSTOMER'S_FIRST_NAME
    billingAddress['lastName'] = CUSTOMER'S_LAST_NAME
    billingAddress['street'] = CUSTOMER'S_STREET
    billingAddress['postalCode'] = CUSTOMER'S_POSTAL_CODE
    billingAddress['city'] = CUSTOMER'S_CITY
    billingAddress['state'] = CUSTOMER'S_STATE
    billingAddress['country'] = CUSTOMER'S_COUNTRY // ISO 3166-1-alpha-2
    payerInfo['billingAddress'] = billingAddress
    payload['payerInfo'] = JSON.stringify(payerInfo)
    
    const orderInfo = {
        subject: ORDER_SUBJECT_IN_YOUR_SYSTEM,
    }
    const goodsInfo = Array()
    goodsInfo.push(
      {
        id: SKU_ID_IN_YOUR_SYSTEM,
        name: PRODUCT_NAME,
        price: PRICE,
        quantity: QUANTITY,
        url: PRODUCT_LINK,
        image: IMAGE_OF_PRODUCT
      },
      {    
        id: SKU_ID_IN_YOUR_SYSTEM,
        name: PRODUCT_NAME,
        price: PRICE,
        quantity: QUANTITY,
        url: PRODUCT_LINK,
        image: IMAGE_OF_PRODUCT
      },
    )
    const shippingAddress = {}
    shippingAddress['houseNo'] = CUSTOMER'S_HOUSE_NO
    shippingAddress['email'] = CUSTOMER'S_EMAIL
    shippingAddress['phoneNo'] = CUSTOMER'S_PHONE_NO
    shippingAddress['firstName'] = CUSTOMER'S_FIRST_NAME
    shippingAddress['lastName'] = CUSTOMER'S_LAST_NAME
    shippingAddress['street'] = CUSTOMER'S_STREET
    shippingAddress['postalCode'] = CUSTOMER'S_POSTAL_CODE
    shippingAddress['city'] = CUSTOMER'S_CITY
    shippingAddress['state'] = CUSTOMER'S_STATE
    shippingAddress['country'] = CUSTOMER'S_COUNTRY // ISO 3166-1-alpha-2
    orderInfo['goodsInfo'] = goodsInfo
    orderInfo['shippingAddress'] = shippingAddress
    payload['orderInfo'] = JSON.stringify(orderInfo)
    
    payload['signType'] = 'MD5'
    payload['merchantNo'] = YOUR_MERCHANT_NO
    payload['notifyUrl'] = ASYNC_NOTIFY_URL
    payload['echoParam'] = ECHO_PARAM
    payload['sign'] = calcMD5(payload)

}

function calcMD5(payload) {
  const data = Object.keys(payload)
    .sort()
    .reduce((obj, key) => {
      obj[key] = payload[key]
      return obj
    }, {})
  var str = ''
  Object.keys(data).forEach((key) => {
    if (data[key] != '' && key != 'sign') {
      str = str + key + '=' + data[key] + '&'
    }
  })
  str = str + 'pkey=' + YOUR_MD5_SECRET_KEY
  return md5(str)
}

RSA

生成商户RSA密钥对

注意: RSA的格式为 1024 PKCS8

上传商户RSA公钥

注意, 请将公钥字符串中的首行(-----BEGIN PUBLIC KEY-----)与尾行(------END PUBLICK KEY-----)删除, 然后将中间部分格式化成一行粘贴进去

保存 UseePay RSA 公钥

在上图中, 你需要保存 UseePay RSA 公钥, 请求的响应数据, UseePay 会使用 UseePay 的 RSA 私钥进行签名, 并返回 sign 值, 你需要使用 UseePay RSA 公钥进行验签

生成RSA签名规则

  1. 按照ASCII码生序对请求的 payload 进行排序

  2. 按第一步获取的结果,进行key-value 遍历, 对 value trim 后不为空和 key 不为 sign 的 key-value 使用 URL 键值对的格式进行拼接(key1=value1&key2=value2...),

  3. 对第2步取到字符串, 用之前生成的商户 RSA 密钥进行签名做 base64, 获取 sign 值

RSA签名生成示例

// Node.js 示例倒入了 node-rsa
const NodeRSA = require('node-rsa')

function getPayload(){
    payload['version'] = '1.0'
    payload['autoRedirect'] = false
    payload['transactionId'] = ORDER_ID_IN_YOUR_SYSTEM
    payload['transactionType'] = 'pay'
    payload['transactionExpirationTime'] = 14400
    payload['appId'] = YOUR_APP_ID
    payload['amount'] = 1234
    payload['currency'] = 'USD'
    
    const userInfo = {
        userId: USER_ID_IN_YOUR_SYSTEM,
        phoneNo: USER'S_PHONE_NO,
        email: USER'S_EMAIL,
        IP: USER'S_IP
    }
    const billingAddress = {}
    billingAddress['houseNo'] = CUSTOMER'S_HOUSE_NO
    billingAddress['email'] = CUSTOMER'S_EMAIL
    billingAddress['phoneNo'] = CUSTOMER'S_PHONE_NO
    billingAddress['firstName'] = CUSTOMER'S_FIRST_NAME
    billingAddress['lastName'] = CUSTOMER'S_LAST_NAME
    billingAddress['street'] = CUSTOMER'S_STREET
    billingAddress['postalCode'] = CUSTOMER'S_POSTAL_CODE
    billingAddress['city'] = CUSTOMER'S_CITY
    billingAddress['state'] = CUSTOMER'S_STATE
    billingAddress['country'] = CUSTOMER'S_COUNTRY // ISO 3166-1-alpha-2
    payerInfo['billingAddress'] = billingAddress
    payload['userInfo'] = JSON.stringify(userInfo)
    
    const payerInfo = {
        paymentMethod: 'credit_card',
        authorizationMethod: 'cvv'
    }
    payload['payerInfo'] = JSON.stringify(payerInfo)
    
    const orderInfo = {
        subject: ORDER_SUBJECT_IN_YOUR_SYSTEM,
    }
    const goodsInfo = Array()
    goodsInfo.push(
      {
        id: SKU_ID_IN_YOUR_SYSTEM,
        name: PRODUCT_NAME,
        price: PRICE,
        quantity: QUANTITY,
        url: PRODUCT_LINK,
        image: IMAGE_OF_PRODUCT
      },
      {    
        id: SKU_ID_IN_YOUR_SYSTEM,
        name: PRODUCT_NAME,
        price: PRICE,
        quantity: QUANTITY,
        url: PRODUCT_LINK,
        image: IMAGE_OF_PRODUCT
      },
    )
    const shippingAddress = {}
    shippingAddress['houseNo'] = CUSTOMER'S_HOUSE_NO
    shippingAddress['email'] = CUSTOMER'S_EMAIL
    shippingAddress['phoneNo'] = CUSTOMER'S_PHONE_NO
    shippingAddress['firstName'] = CUSTOMER'S_FIRST_NAME
    shippingAddress['lastName'] = CUSTOMER'S_LAST_NAME
    shippingAddress['street'] = CUSTOMER'S_STREET
    shippingAddress['postalCode'] = CUSTOMER'S_POSTAL_CODE
    shippingAddress['city'] = CUSTOMER'S_CITY
    shippingAddress['state'] = CUSTOMER'S_STATE
    shippingAddress['country'] = CUSTOMER'S_COUNTRY // ISO 3166-1-alpha-2
    orderInfo['goodsInfo'] = goodsInfo
    orderInfo['shippingAddress'] = shippingAddress
    payload['orderInfo'] = JSON.stringify(orderInfo)
    
    payload['signType'] = 'RSA'
    payload['merchantNo'] = YOUR_MERCHANT_NO
    payload['notifyUrl'] = ASYNC_NOTIFY_URL
    payload['echoParam'] = ECHO_PARAM
    payload['sign'] = calcRSA(payload)

}

function calcRSA(payload) {
  const data = Object.keys(payload)
    .sort()
    .reduce((obj, key) => {
      obj[key] = payload[key]
      return obj
    }, {})
  var str = ''
  Object.keys(data).forEach((key) => {
    if (data[key] != '' && key != 'sign') {
      str = str + key + '=' + data[key] + '&'
    }
  })
  str = str.substr(0, str.length - 1)
  return new NodeRSA(YOUR_RSA_PRIVATE_KEY, 'pkcs8-private').sign(
    Buffer.from(str),
    'base64',
  )
}

访问如 生成密钥对:

http://www.metools.info/code/c80.html