签名规则(RSA)

RSA的签名时,需要私钥和公钥一起参与签名。私钥与公钥皆是客户通过OPENSSL来生成得出的。客户把生成出的公钥与小y技术人员配置好的公钥做交换。因此,在签名时,客户要用到的
是客户的私钥及小y的公钥。

(1) 请求签名(可选)


  参考下面实例,按照支付调用参数说明拼写字符串,并将生成的签名字符串通过setsign(String)传入.


(2) 响应验签

当获得到通知返回时的待签名字符串后,把待签名字符串、小y提供的公钥、小y返回的sign参数,一并放入RSA验证签名函数中进行验证签名运算。返回true,签名正确;false,签名错误。

需要参与签名的参数:

1)在请求参数列表中,除去payChannel,sign参数外,其他需要使用到的参数皆是要签名的参数;

2)sign值要做UTF-8 URLEncode,并且去掉换行符。

生成待签名字符串过程:

1)对数组里的每一个值从a到z的顺序排序,若遇到相同首字母,则看第二个字母,以此类推;

2)排序完成之后,再把所有数组值以“&”字符连接起来;

示例:

{
    "corpId": "CM00001001",
    "appId": "APP00001001",
    "outTradeNo": "wechat12-18-20",
    "totalAmount": 1,
    "body": "%E7%AC%A6%E7%9F%B31",
    "detail": "testdetail",
    "attach": "testattach",
    "notifyUrl": "notifyUrl",
    "sign": "MInepBgdb2E0smW7MHXT8qmnV1RjPFlt%2F4sEMnyWY74N2pYExKnVlcMxqmby
%2FLrceXGCudSgN2oPCUDkRQpThJP31HxlimcNGe6Y3jasuDoyBSqs7IEFaiqWA6D5jVqwW1T5kntsXdGBolBEnA0z%2F5eNxtGEX14X0Q%2FQcgGS3ds%3D"
}


需要签名的字符串:

appId=APP00001001&attach=testattach&body=%E7%AC%A6%E7%9F%B31&corpId=CM00001001&detail=testdetail¬ifyUrl=notifyUrl&outTradeNo=wechat12-18-20&totalAmount=1

注意:

实际中没有值的参数无需传递,也无需包含到待签名数据中。


(3) 签名示例(参照资源下载:RSACoder.java签名Java工具类)

//签名生成

String content="appId=APP00000023&cashFee=1&corpId=CM00001006&orderCreateTime=20160324163734&orderExpireTime=20160324183734&outTradeNo=1458808672024
&totalFee=1&xiaoyTradeNo=xy0220160324145880865453986772";

String privateKey="MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAIP/lY5TjL01QGyZp0+X29LzuPrgg/12OfZ+1TSOYJ8dF6bqfGoAJzuX4xKfIKj
GDnClX4Q6aelSoYQkAkn2ysYkB5oNJbplFrQ7xfY8bXUylTpO9gJLawFcCr2PNPU0TqQU68zzk11lFCMEq9Kzm73hXiVJ2vlqw4HsKc8xE8XXAgMBAAECgYAxz5IF
WnwCroS4NqePfpPioDxO18iXLjUjUqtsIMpPYPAa+eOnMJWdhGyZC1mMtuieE5ne0RhEhv0SW3BNrwbHgJxMfcdNyFMvzCJ1SCBvdK5ySRJpiNpoEuvrx0j9eoNzQR
41W1M9sbFZOMFRcjet65KS5Imc1zQ0rgdo1SY7QQJBANNVEXXPEi0teg6I6rev0fGdHeg5p56Bt2gcIPmwVRcO4u6q3VHVDWoBLNuBGERwg94qm86sCYKzF31HP
mg1lXcCQQCf5drKahILXo8TTjv87FjzSx53WlSolcOr3aYa7dbeKyBoRRz0ec6JlMInhprjV1JzEuzlCqweATNPQriRzuqhAkAO06sT7uFBli04E9cT6Bv8rZ9JibH+5u7tOP
v/SKXPplW5lPdOJHp6c3aoN9hyBMrbrXWc/Gj2aIY/Xd49BXVlAkBOrxOda9j5U0zg2SzX545WGu8hGIh0dU5WsrncopGLvnkyFmCLRa2HMnbgcHKj0QK3seZ1R20v
TrPrGxAsYEBBAkBkoDT85Oo96Tb4LtqgmGncfNNnDkmKVQ5/xcmxnX/nZ//p3qjZ5Ic3osAytwsQc7uZqJ4pJ5+g2IGx1ukZYubu";

String sign = sign(content.getBytes(), privateKey);

String xiaoySign = URLEncoder.encode(sign.replace("\n", ""), "UTF-8");

System.out.println("签名内容:" + content);

System.out.println("小y签名:"+xiaoySign);

//签名验证

String publicKey="MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCD/5WOU4y9NUBsmadPl9vS87j64IP9djn2ftU0jmCfHRem6nxqACc7l+MSnyCoxg5wpV+EOmnp
UqGEJAJJ9srGJAeaDSW6ZRa0O8X2PG11MpU6TvYCS2sBXAq9jzT1NE6kFOvM85NdZRQjBKvSs5u94V4lSdr5asOB7CnPMRPF1wIDAQAB";

boolean bverify = verify(content.getBytes(), publicKey, URLDecoder.decode(xiaoySign, "UTF-8"));

System.out.println("验证结果:"+bverify);

//输出结果

>>签名内容:appId=APP00000023&cashFee=1&corpId=CM00001006&orderCreateTime=20160324163734&orderExpireTime=20160324183734&outTradeNo=1458808672024&totalFee=1&
xiaoyTradeNo=xy0220160324145880865453986772

>>小y签名:YVMViO%2FEvID%2BWhvsjszhZgp0scwr4uOKi2U%2FZe3NBWll%2BTFHvElmDSrrIA33u1aO6ERJnPA%2BpQGpz3GFJvUQ1juWIR6rva%2BWFfsz7DTkpK2u0B65nWio9
XudUP09t3Bzk6AO7YhTAQqIUSjL%2F4knPHipPV0CZhHG7qnyLCVx1yA%3D

>>验证结果:true