支付宝开发者社区

各位开发者,支付宝开发者社区已全面迁移至https://open.alipay.com/portal/forum,欢迎在支付宝开发者社区内提问,分享相关开发经验,有一系列的问答官激励、创作者计划等你参加~

1

回答

1

回答

guxiangfly 2019-09-04 3665浏览量 回答数 1

0

回答

1

回答

1815401893939962 2019-09-02 1976浏览量 回答数 1

1

回答

2

回答

游客frmvwhvehhidi 2019-09-02 2010浏览量 回答数 2

1

回答

1

回答

1171944098684050 2019-09-02 1414浏览量 回答数 1

1

回答

1349522860103173 2019-08-29 2596浏览量 回答数 1

1

回答

游客cpp3i2whlpt7k 2019-08-29 1583浏览量 回答数 1

1

回答

游客a2pdiavkh7txu 2019-08-29 2172浏览量 回答数 1

1

回答

游客y3m663vsoxgt2 2019-08-28 1424浏览量 回答数 1

1

回答

游客y3m663vsoxgt2 2019-08-27 1224浏览量 回答数 1

8

回答

=== 2018/8/30 16:00 终于搞定php对公钥证书签名 根据java SDK源码,用php取公钥证书SN如下:

$p = [];

$str = file_get_contents('./alipayRootCert.crt');
$p["alipay_root_cert_sn"] = getRootCertSN($str);

$str = file_get_contents('./alipayCertPublicKey_RSA2.crt');
$p["alipay_cert_sn"] = getCertSN($str);

$str = file_get_contents('./appCertPublicKey.crt');
$p["app_cert_sn"] = getCertSN($str);

var_export($p);

function getRootCertSN($str)
{
	$arr = preg_split('/(?=-----BEGIN)/', $str, -1, PREG_SPLIT_NO_EMPTY);
	$str = null;
	foreach ($arr as $e) {
		$sn = getCertSN($e, true);
		if (!$sn)
			continue;
		if ($str === null)
			$str = $sn;
		else
			$str .= "_" . $sn;
	}
	return $str;
}

function getCertSN($str, $matchAlgo=false)
{
/* 
根据java SDK源码:AntCertificationUtil::getRootCertSN
对证书链中RSA的项目进行过滤(猜测是gm国密算法java抛错搞不定,故意略去)
java源码为:

	if(c.getSigAlgOID().startsWith("1.2.840.113549.1.1"))

根据 https://www.alvestrand.no/objectid/1.2.840.113549.1.1.html
该OID为RSA算法系。
*/ 
	if ($matchAlgo) {
		openssl_x509_export($str, $out, false);
		if (!preg_match('/Signature Algorithm:.*?RSA/im', $out, $m))
			return;
	}
	$a = openssl_x509_parse($str);
	$issuer = null;
	// 注意:根据java代码输出,需要倒着排列 CN,OU,O
	foreach ($a["issuer"] as $k=>$v) {
		if ($issuer === null) {
			$issuer = "$k=$v";
		}
		else {
			$issuer = "$k=$v," . $issuer;
		}
	}
#	echo($issuer . $a["serialNumber"] . "\n");
	$sn = md5($issuer . $a["serialNumber"]);
	return $sn;
}



做为首批踩坑者,只能长叹一声

=== 2018/8/30 12:15 更新:

名字和序列化取出来像这样:

CN=Ant Financial Certification Authority Class 2 R1,OU=Certification Authority,O=Ant Financial,C=CN
42665268812499181166312682537244063920
  • 名字各段之间用逗号分隔,没有额外的空格
  • 序列号是10进制数,不是16进制,也没有任何分隔符
  • 取根证书sn需要遍历其中所有证书链,分别对name+serial进行md5编码,再用"_"连接起来。

看了半天java源码,终于运行起来,把sn值打出来了,拷贝到php中,终于看到手机上支付页面出来了。结果大致像这样:

"app_cert_sn" => "06de145e15a73a8ce87f3eefeddce8b2",
//"alipay_cert_sn" => "b1a855128d973b1ff1b1609bbce77fe0",
"alipay_root_cert_sn" => "687b59193f3f462dd5336e5abf83c5d8_02941eef3187dddf3d3b83462e1dfcf6"

支付宝根证书要用特殊方法来取(源码里用AntCertificationUtil.getRootCertSN),怪不得之前写的不行。

定此接口的人需要深刻检讨,竟然直接以java语言的某个输出来定接口规范。难怪php或其它语言的相关sdk没有出来,我感觉也不好写。

============ 旧消息

新申请的开放平台帐号,被强制使用了公钥证书签名。 !!!下面开始吐槽:

首先是接口文档比如 https://docs.open.alipay.com/api_1/alipay.trade.app.pay 中完全没提到有公钥证书签名这回事。

调用支付出问题后(报错总是报“支付取消”??),四处查文档,才找到php SDK没有提供此功能,于是决定按接口文档来写。

签名算法的文档中介绍是这样介绍算法的: “SN值是通过解析X.509证书文件中签发机构名称(name)以及内置序列号(serialNumber),将二者拼接后的字符串计算MD5值获取”

尼码,文档完全没有介绍name和serialNumber分别是怎样的文本格式?也没有例子。 我试了name是 “ROOTCA”,“/C=CN/O=NRCAC/CN=ROOTCA”,“C=CN, O=NRCAC, CN=ROOTCA”各种格式,而serialNumber格式我试了 “69e2fec0170ac67b”以及加"69 e2..."、加“69:e2..."等,以及各种组合,都没有验签成功。

于是走第二条路,找它说的java SDK源码来参考。打开java sdk链接,是在maven上的,找了好久才搜到了新版本java源码。

终于找到了介绍的getCertSN函数,其核心是这样实现的:

    public static String getCertSN(String certPath)throws AlipayApiException{
        InputStream inputStream = null;
            inputStream = new FileInputStream(certPath);
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            X509Certificate cert = (X509Certificate)cf.generateCertificate(inputStream);
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update((cert.getIssuerX500Principal().getName()+cert.getSerialNumber()).getBytes());
            String certSN = new BigInteger(1,md.digest()).toString(16);
            //BigInteger会把0省略掉,需补全至32位
            certSN = fillMD5(certSN);
            return certSN;

于是找这cert.getIssuerX500Principal().getName()+cert.getSerialNumber()文档 实在看不懂,算了,还是直接运行这段java代码吧,把结果复制到php中填参数也可以,眼看就要成功了,结果运行java是这样的:

java.security.cert.CertificateParsingException: java.io.IOException: Unknown named curve: 1.2.156.10197.1.301
        at sun.security.x509.X509CertInfo.<init>(Unknown Source)
        at sun.security.x509.X509CertImpl.parse(Unknown Source)
        at sun.security.x509.X509CertImpl.<init>(Unknown Source)
        at sun.security.provider.X509Factory.engineGenerateCertificate(Unknown Source)
        at java.security.cert.CertificateFactory.generateCertificate(Unknown Source)
        at j1.getCertSN(j1.java:33)
        at j1.main(j1.java:24)

搜索发现,是java不支持国密算法。。。(https://cloud.tencent.com/info/fcfae2f8bd49fcce8737c7485afcdf29.html)

天笑2001 评论 1

1

回答

0

回答

1

回答

情义&mdash;帝道 2019-08-23 1412浏览量 回答数 1

1

回答

1555744697047567 2019-08-23 1025浏览量 回答数 1

1

回答

情义&mdash;帝道 2019-08-22 1242浏览量 回答数 1

方式1:可以去支付宝开发者中心查看相应的开发文档:link

方式2: 可以去支付宝技术支持中心搜索相应问答:link

方式3:可以使用在线咨询(小码答):

link

方式3:拨打官方客户电话:0571-88158090

方式4:加入支付宝开发者官方钉钉群:23390832

生活号+钉钉群.png

扬朋 评论 0

1

回答

游客4yo2pgx6uluni 2019-08-01 2027浏览量 回答数 1

公告

如果你在支付宝开放平台入驻时遇到问题,想寻求其他开发者的帮助;如果你有支付宝小程序相关开发经验想要分享,欢迎各位开发者来支付宝开发者社区(https://open.alipay.com/portal/forum),分享经验,答疑解惑。

展开