alipay / alipay-sdk-nodejs-all

支付宝开放平台 Alipay SDK for Node.js
https://docs.open.alipay.com/54/103419/
Other
407 stars 64 forks source link

如何使用证书签名方式请求? #56

Closed dcboy closed 3 months ago

dcboy commented 4 years ago

如何使用证书签名方式请求?

raymclee commented 4 years ago

同问

raymclee commented 4 years ago

刚试到,只要在运行exec时加入appCertSn和alipayRootCertSn就可以了 但前题是你要找到证书的sn

Messilimeng commented 4 years ago

@cheuk3 你好 请问 appCertSn 和 alipayRootCertSn 具体是放在哪个里面 放在公共参数里面吗?

raymclee commented 4 years ago

@cheuk3 你好 请问 appCertSn 和 alipayRootCertSn 具体是放在哪个里面 放在公共参数里面吗?

給你參考

alipaySdk.exec("alipay.trade.pay", {
      appCertSn: string,
      alipayRootCertSn: string,
      notifyUrl: string
      bizContent: {
          ...
       }
});
Messilimeng commented 4 years ago

{ code: '40002', msg: 'Invalid Arguments', subCode: 'isv.app-cert-not-exist', subMsg: '应用公钥证书不存在' } 一直都是这个错误 烦死了额

raymclee commented 4 years ago

應該是你的sn不Œ對, 他找不到那証書

Messilimeng commented 4 years ago

let publicdata = { charset: "UTF-8", method: "alipay.fund.trans.uni.transfer", timestamp: , version: "1.0", appCertSn: 'xxxx', alipayRootCertSn: '687b59f3d3b83462e1dfcf6', bizContent: biz_content };

    const alipaySdk = new AlipaySdk({
        appId: '',
        privateKey: fs.readFileSync(think.ROOT_PATH + '//rsa_private_key.pem', 'ascii'),
        keyType: "PKCS8",
    });

我是用 c# sdk 搞出了sn 应该不会错吧

Messilimeng commented 4 years ago

@cheuk3 可以加个qq 吗

raymclee commented 4 years ago

我是用以下php找出sn來的,你可以試試

<?

// 大数十六进制转十进制字符串表示
function bchexdec($hex) {
  $dec = 0;
  $len = strlen($hex);
  for ($i = 1; $i <= $len; $i++) {
      $dec = bcadd($dec, bcmul(strval(hexdec($hex[$i - 1])), bcpow('16', strval($len - $i))));
  }
  return $dec;
}
// 索引数组反转拼接 k3=v3,k2=v2,k1=v1
function issuersToString($issuers){
$issuer_arr = [];
foreach ($issuers as $key => $val) {
  $issuer_arr[] = $key . '=' . $val;
}
return implode(',', array_reverse($issuer_arr));
}
// 生成应用证书SN
function getCertSN() {
$cert = file_get_contents('./appCertPublicKey_2021001104697912.crt');
$certdata = openssl_x509_parse($cert);
// 支付宝应用公钥应当可以不要下面的分支逻辑
// 需要检查是否为十六进制
if (strpos($certdata['serialNumber'], '0x') === 0) {
  // 转换十进制表示
  $serialNumber = bchexdec($certdata['serialNumber']);
} else {
  $serialNumber = $certdata['serialNumber'];
}
// 拼装issuser串
$issuer = issuersToString($certdata['issuer']);

echo md5($issuer . $serialNumber);
return md5($issuer . $serialNumber);
}
// 生成支付宝根证书SN
function getRootCertSN() {
// 读取证书内容
$cert = file_get_contents('./alipayRootCert.crt');
$split_str = "-----END CERTIFICATE-----";
// 证书链分割为多个证书部分
$cert_parts = explode($split_str, $cert);
$md5_arr = [];
foreach ($cert_parts as $part) {
  if (!empty(trim($part))) {
    // 完整结构表示
    $cert = $part . $split_str;
    $certdata = openssl_x509_parse($cert);
    // 仅检查 signatureTypeSN='RSA-SHA256', 'RSA-SHA1'
    // 或者检查 signatureTypeLN='sha256WithRSAEncryption','sha1WithRSAEncryption'
    if (in_array($certdata['signatureTypeSN'], ['RSA-SHA256', 'RSA-SHA1'])) {
      // 需要检查是否为十六进制
      // 例如 CN=iTrusChina Class 2 Root CA - G3 证书的serialNumber则为0x开头
      if (strpos($certdata['serialNumber'], '0x') === 0) {
        // 转换十进制表示
        $serialNumber = bchexdec($certdata['serialNumber']);
      } else {
        $serialNumber = $certdata['serialNumber'];
      }
      // 拼装issuser串
      $issuer = issuersToString($certdata['issuer']);
      // 追加每个证书serialNumber结果
      $md5_arr[] = md5($issuer . $serialNumber);
    }
  }
}
// 最后使用 _ 连接
echo implode('_', $md5_arr);
return implode('_', $md5_arr);
}

getRootCertSN();
getCertSN();

?>
Messilimeng commented 4 years ago

@cheuk3 我这个得到是 66 位的字符串数据

raymclee commented 4 years ago

let publicdata = { charset: "UTF-8", method: "alipay.fund.trans.uni.transfer", timestamp: , version: "1.0", appCertSn: 'xxxx', alipayRootCertSn: '687b59f3d3b83462e1dfcf6', bizContent: biz_content };

    const alipaySdk = new AlipaySdk({
        appId: '',
        privateKey: fs.readFileSync(think.ROOT_PATH + '//rsa_private_key.pem', 'ascii'),
        keyType: "PKCS8",
    });

我是用 c# sdk 搞出了sn 应该不会错吧

你的rootsn跟我的差別很大,我的不是21位的 所以我相信應該是sn不對

raymclee commented 4 years ago

@cheuk3 我这个得到是 66 位的字符串数据

那應該正確了 你試試

Messilimeng commented 4 years ago

应用公钥证书不存在 是什么问题 我这个证书都是从开放平台下载下来的 为什么还会出现证书不存在

Messilimeng commented 4 years ago

@cheuk3

Messilimeng commented 4 years ago

image @cheuk3

raymclee commented 4 years ago

应用公钥证书不存在 是什么问题 我这个证书都是从开放平台下载下来的 为什么还会出现证书不存在

Screenshot 2020-02-28 at 2 15 11 PM

你是在這裡下載的嗎

Messilimeng commented 4 years ago

@cheuk3 文件名叫什么

raymclee commented 4 years ago

@cheuk3 文件名叫什么

alipayCertPublicKey_RSA2 alipayRootCert

Messilimeng commented 4 years ago

@cheuk3 我实在不知道哪里错了 头晕了 你是台湾还是香港的 不方便加qq吗

Messilimeng commented 4 years ago

已经可以了 谢谢

raymclee commented 4 years ago

已经可以了 谢谢

之前是什麼問題?

Messilimeng commented 4 years ago

@cheuk3 不知道为什么 我在获取sn的时候 c#代码和java 获取出来的居然不一样 用java 获取出来的是正确的

Messilimeng commented 4 years ago

我用nodejs 写了一个获取sn 的方法 https://github.com/alipay/alipay-sdk-nodejs-all/issues/62