MAPI接口MD5密钥升级手册:支付宝商家支付接口私钥公钥生成RSA加密

暂时没有接到停止服务的通知,这次主要是督促商户自主进行升级,如果有新的消息,我们会在第一时间通知给大家,并给大家预留足够的时间来处置,原则上不会影响大家的正常业务,感谢您的反馈。
wap支付的密钥不需要升级成为RSA哈,目前确认老版的Wap支付只支持MD5;
整改有问题的商户,可以在评论区留言,或拨打95188进行咨询;

序号

文档修订记录

修订时间

1

编辑手册草稿,发布初稿

2021-10-20

2

商家服务端升级提供代码Demo

2021-10-25

3

补充商户升级FAQ

2021-11-22

 

MAPI接口MD5密钥升级手册

一、手册总览
二、RSA密钥查看/修改
  • 2.1 进入密钥管理功能页
  • 2.2 设置开发者公钥
  • 2.3 查看支付宝公钥
三、商家服务端升级
 
  • (a)接口参数加签逻辑介绍
  • (b)支付通知验签逻辑介绍
 
3.1 签名代码Demo
 
  • (a)获取待加签字符串
  • (b)请求加签
  • (c)合并请求参数
3.2 验证签名Demo
  • 获取待验签字符
  • 验证签名
3.3 官方SDK Demo:
四、FAQ问题汇总
  • (a)接口加签算法升级为RSA后, 相应服务通知验签算法也要升级成为RSA?
  • (b)为什么要强制MD5密钥升级到RSA密钥?
  • (c)MD5密钥升级时长是多少?
  • (d)接口改造过程中是否有测试联调环境?
  • (e)ASP服务端如何进行升级?
  • (f)本次升级范围为mapi网关接口,可以通过接口请求地址区分识别该接口是否属于mapi网关,目前mapi网关暴露在公网的域名包括:
  • (g)可否通过替代mapi接口为openapi接口完成升级?
  • (h) “alipay.mobile.qrcode.manage”接口异步通知验签出错!
五、整改风险提示

一、手册总览

为了构建更安全的安全防控能力,支付宝开放平台正在推动所有使用MD5密钥加/验签的接口进行升级,具体而言,就是从之前MD5加签算法升级到RSA算法,本手册主要指导商户快速完成密钥升级,包含了密钥升级的全流程演示,商户完成该升级大致需要经过2个步骤。

  1. 在开放平台上传自己的开发者私钥,下载保存支付宝的公钥;
  2. 对商家服务端代码进行升级,将MD5加/验签名逻辑替换成为RSA签名逻辑

PS:如果您是使用了第三方服务提供商提供的软件/系统,请联系服务提供商完成升级!

二、RSA密钥查看/修改

2.1 进入密钥管理功能页

访问开放平台管理中心:https://openhome.alipay.com/platform/developerIndex.htm,进入【密钥管理】功能页

2.2 设置开发者公钥

因为RSA密钥是非对称密钥,开发者生成RSA密钥后,自己保存好私钥,将公钥上传到开放平台。在进行接口参数加签时,使用自己RSA私钥进行签名,支付宝侧将使用用户上传的RSA公钥进行请求验签,确保请求在传输中未被篡改。

密钥生成方法https://opendocs.alipay.com/mini/02c7i5

支付宝开发者公钥在哪里

2.3 查看支付宝公钥

支付宝侧为每个商户生成了不同的RSA密钥,其中开发者可以在密钥管理中心查看支付宝公钥,支付宝私钥由支付宝开放平台安全保存,不对外泄漏。商家在接收到支付宝侧的服务通知时,需要使用支付宝公钥进行请求验签,确保该请求在传输中未被篡改。

支付宝公钥在哪里看

 

三、商家服务端升级

如果加/验签名逻辑是商户自定义开发,支付宝使用的是标准的加/验签名逻辑,商户只需可以参照代码demo完成升级即可;

a) 接口参数加签逻辑介绍

详见:https://opendocs.alipay.com/open/58/103591

b) 支付通知验签逻辑介绍

签名验证:https://opendocs.alipay.com/open/58/103596

 

3.1 签名代码Demo

a) 获取待加签字符串

如将参数存储在Map中,获取待签名参数的代码Demo如下所示:

	/** 
     * 把数组所有元素排序,并按照“参数=参数值”的模式用“&”字符拼接成字符串
     * @param params 需要排序并参与字符拼接的参数组
     * @return 拼接后字符串
     */
    public static String createLinkString(Map<String, String> params) {

        List<String> keys = new ArrayList<String>(params.keySet());
        Collections.sort(keys); //按照参数key有序排列

        String prestr = "";

        for (int i = 0; i < keys.size(); i++) { //有序合并参数
            String key = keys.get(i);
            String value = params.get(key);

            if (i == keys.size() - 1) {//拼接时,不包括最后一个&字符
                prestr = prestr + key + "=" + value;
            } else {
                prestr = prestr + key + "=" + value + "&";
            }
        }

        return prestr;
    }

b) 请求加签

获得有序的待加签名字符后,即可使用标准的RSA加签算法对请求进行加签名,如下Demo中使用的是java.security.Signature类完成请求加签。

/**
     * 生成签名结果
     * @param sPara 要签名的参数Map
     * @return 签名结果字符串
     */
	public static String buildRequestMysign(Map<String, String> sPara) {
    	String prestr = AlipayCore.createLinkString(sPara); //把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串
        String mysign = "";
        if(AlipayConfig.sign_type.equals("RSA") ){
        	mysign = RSA.sign(prestr, AlipayConfig.private_key, AlipayConfig.input_charset);
        }
        return mysign;
    }

-----------------------分割线-----------------------------
/**
	* RSA签名
	* @param content 待签名数据
	* @param privateKey 商户私钥
	* @param input_charset 编码格式
	* @return 签名值
	*/
	public static String sign(String content, String privateKey, String input_charset)
	{
        try 
        {
        	PKCS8EncodedKeySpec priPKCS8 	= new PKCS8EncodedKeySpec( Base64.decode(privateKey) ); 
        	KeyFactory keyf 				= KeyFactory.getInstance("RSA");
        	PrivateKey priKey 				= keyf.generatePrivate(priPKCS8);

        	//获取SHA1WithRSA签名算法对象
            java.security.Signature signature = java.security.Signature.getInstance("SHA1WithRSA");

            signature.initSign(priKey); //初始化私钥
            signature.update( content.getBytes(input_charset) ); //设置需要签名的数据

            byte[] signed = signature.sign();  //获得签名值(bytes类型)
            
            return Base64.encode(signed);  //签名值转换成为base64格式(String类型)
        }
        catch (Exception e) 
        {
        	e.printStackTrace();
        }
        
        return null;
    }

c) 合并请求参数

为了支付宝侧能够验证签名,签名值和采用的签名算法,需要与请求参数合并,一起发送出来。

 /**
     * 生成要请求给支付宝的参数数组
     * @param sParaTemp 请求前的参数数组
     * @return 要请求的参数数组
     */
    public static Map<String, String> buildRequestPara(Map<String, String> sParaTemp) {
        //除去数组中的空值和签名参数
        Map<String, String> sPara = AlipayCore.paraFilter(sParaTemp);
        //生成签名结果
        String mysign = buildRequestMysign(sPara); //获取参数签名结果

        //签名结果与签名方式加入请求提交参数组中
        sPara.put("sign", mysign);  //参数签名值
        sPara.put("sign_type", AlipayConfig.sign_type); //采用的签名算法类型

        return sPara;
    }

3.2 验证签名Demo

a) 获取待验签字符

同“签名代码Demo/获取待加签字符串”的逻辑完全相同,请直接参考;

 

b) 验证签名

获取待验签字符串后,同样可以调用标准的RSA的验签算法进行验签,Demo中同样采用的是java.security.Signature类完成请求验签。

/**
	* RSA验签名检查
	* @param content 待签名数据
	* @param sign 签名值
	* @param alipay_public_key 支付宝公钥
	* @param input_charset 编码格式
	* @return 布尔值
	*/
	public static boolean verify(String content, String sign, String alipay_public_key, String input_charset)
	{
		try 
		{
			KeyFactory keyFactory = KeyFactory.getInstance("RSA");
	        byte[] encodedKey = Base64.decode(alipay_public_key);
	        PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));

		
			java.security.Signature signature = java.security.Signature
			.getInstance("SHA1WithRSA");
		
			signature.initVerify(pubKey); //初始化公钥 
			signature.update( content.getBytes(input_charset) ); //设置待验签字符
		
			boolean bverify = signature.verify( Base64.decode(sign) ); //验证签名是否一致
			return bverify;
			
		} 
		catch (Exception e) 
		{
			e.printStackTrace();
		}
		
		return false;
	}

 

3.3 官方SDK Demo:

为了帮助开发者快速完成升级,也为了开发者通过代码快速熟悉RSA加/验签名流程,支付宝提供了【官方DEMO】,开发者可以参考官方demo的【RSA签名版本】代码逻辑,了解加/验签逻辑,并完成RSA加/验签流程改造。

官方SDK DEMOhttps://opendocs.alipay.com/open/66/104511

 

 

四、FAQ问题汇总

a) 接口加签算法升级为RSA后, 相应服务通知验签算法也要升级成为RSA?

答:是的,由于接口参数加签算法与支付宝侧服务通知的加签算法不一定严格对应(接口参数使用RSA签名,接口通知不一定使用RSA),建议商户在完成接口加签升级后,对服务通知的验签逻辑也进行升级,使服务端通知同时支持MD5和RSA算法;具体而言,接口加签只支持RSA,服务通知验签同时支持MD5和RSA。

 

b) 为什么要强制MD5密钥升级到RSA密钥?

答:随着计算机算力的提升,MD5密钥已经无法应对未来的安全要求,并且国家监管部门已经出台相关的制度法规,为了您业务安全,也为了业务合规考虑,请您尽快升级。

 

c) MD5密钥升级时长是多少?

从通知触达之日起,为期6个月,请商户尽量在期限内完成升级!逾期未升级商户,支付宝将根据商户的升级情况,评估是否采用进一步的安全措施。

 

d) 接口改造过程中是否有测试联调环境?

目前该接口暂无对外的联调环境,由于开放协议使用的是普通的Https协议,开发者可以在测试环境中构造加签请求后,请求支付宝的正式网关,完成整改验证。

 

e) ASP服务端如何进行升级?

由于ASP编程语言比较老旧,目前没有公开的ASP RSA加密类库,针对这部分存量商户,可以参考支付宝加/验签名逻辑自行实现编码。如无编码能力,可以暂时不进行升级,支付宝将保持这部分商户的业务连续性。

 

f) 本次升级范围为mapi网关接口,可以通过接口请求地址区分识别该接口是否属于mapi网关,目前mapi网关暴露在公网的域名包括:

  • mapi-hk.alipay.com
  • mapi.alipay.com
  • intlmapi.alipay.com
  • mapi-us2c.alipay.com

注意:mapi网关RSA密钥不支持其他网关使用,非mapi网关接口升级RSA会出现报错问题!

 

g) 可否通过替代mapi接口为openapi接口完成升级?

答:可以,openapi接口是现在最新的网关,商户可以自行完成类似接口的签约,通过签约新的openapi替代老的mapi网关,避免升级老的mapi接口。

 

h) “alipay.mobile.qrcode.manage”接口异步通知验签出错!

由于业务历史原因,该接口关联的异步通知使用的老版wap支付RSA密钥(非MAPI密钥),所以这个地方的升级逻辑要注意,该接口的加签使用mapi网关产品密钥,该接口关联异步通知的接签使用老版wap支付RSA密钥

老版wap支付RSA密钥:https://open.alipay.com/platform/keyManage.htm?keyType=wireless

mapi网关产品密钥:https://open.alipay.com/platform/keyManage.htm?keyType=partner

五、整改风险提示

商户在进行RSA密钥升级时,一定要注意加签RSA私钥安全存放,禁止将RSA私钥文件直接保存在服务端程序的文件目录中,避免被外部访问,造成RSA私钥泄漏;


郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。