非SDK接入
<h3>签名重要规则</h3>
<ul>
<li>按照参数名字符升序排列</li>
<li><font style="color:red;">如果参数的值为空不参与签名</font></li>
<li>参数名区分大小写;</li>
<li>验证调用返回或主动通知签名时,传送的sign参数不参与签名,将生成的签名与该sign值作校验。</li>
<li><font style="color:red;">接口可能增加字段,验证签名时必须支持动态扩展字段</font></li>
</ul>
<p>以下程序使用到了,签名、RSA2、HTTP工具类。
<a href="https://platform-sdk-data.oss-cn-hzfinance.aliyuncs.com/newT3/util.zip">下载工具类</a></p>
<hr />
<h3>接入步骤</h3>
<h4>第一步:构建请求微保报文为MAP</h4>
<pre><code>
// 创建接口基础参数
Map<String,String> requestBaseMap = new HashMap<>();
// 设置接入接口的参数
requestBaseMap.put("orderNo","123456");
// 计算签名,要考虑扩展参数时支持正常加签验签。
String sign = VbaoSignUtils.sign(requestBaseMap,"微保提供的签名key");
requestBaseMap.put("sign",sign);
// 加密报文
String reqmsg = RSA2Utils.encryptByPublicKey(JsonUtil.toJson(requestBaseMap),"微保提供的公钥串");
// 构建请求微保报文
Map<String,String> requestMap = new HashMap<>();
requestMap.put("customerNo","微保提供的商户号");
requestMap.put("reqmsg",reqmsg);
// 转换为JSON
String requestStr = JsonUtil.toJson(requestMap);
</code></pre>
<h4>第二步:请求微保接口</h4>
<pre><code>
String resultJson = HttpsUtils.doPostJson(url,requestStr);
</code></pre>
<h4>第三步:解析微保接口</h4>
<pre><code>
// 解析微保返回结果
VbaoResponse vbaoResponse = JsonUtil.parse(resultJson,VbaoResponse.class);
if(vbaoResponse == null || !"200".equals(vbaoResponse.getCode())){
throw new VbaoException("返回非正常态。" + vbaoResponse);
}
Map<String,String> responseMap = JsonUtil.parse(vbaoResponse.getData().toString(),Map.class);
String reqMsg = responseMap.get(VbaoConfig.REQMSG);
if(responseMap == null || reqMsg == null){
throw new VbaoException("数据格式不正确。" + vbaoResponse);
}
// 解密
reqMsg = RSA2Utils.decryptByPublicKey(reqMsg,"微保提供的公钥串");
// 验签
Map<String,String> reqMsgMap = JsonUtil.parse(reqMsg,Map.class);
if(reqMsgMap == null){
throw new VbaoException("解密失败。" + reqMsgMap);
}
String parSign = reqMsgMap.get(VbaoConfig.SIGN);
String platSign = VbaoSignUtils.sign(reqMsgMap,VbaoConfig.getValue(VbaoConfig.SIGN_KEY));
if(!parSign.equals(platSign)){
throw new VbaoException("验签失败。parSign=" + parSign + ",platSign=" + platSign);
}
// reqMsgMap为微保返回的json串
</code></pre>
<hr />
<h3>签名生成步骤</h3>
<p>1、设所有发送或者接收到的数据为集合M,参数按照参数名字符升序排列,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串Origin</p>
<pre><code>
String Origin=p1=v1&p2=v2&key=微保提供的签名key
</code></pre>
<p>2、在Origin最后拼接上key(Origin&key+微保提供的签名Key),得到stringSignTemp字符串</p>
<pre><code>
Origin= Origin + "&key=微保提供的签名key";
</code></pre>
<p>3、对Origin进行MD5运算,并将得到的字符串所有字符转换为大写,得到sign值</p>
<pre><code>
String sign = MD5(Origin).toUpperCase();
</code></pre>
<h4>业务示例</h4>
<ul>
<li>请求参数:</li>
</ul>
<pre><code>
{
"orgCode": "xxx",
"orderNo": "xxxx"
}
</code></pre>
<ul>
<li>拼装参数:</li>
</ul>
<pre><code>
orgCode=xxx&orderNo=xxxx
</code></pre>
<ul>
<li>拼接密钥key:(示例:123456)</li>
</ul>
<pre><code>
orgCode=xxx&orderNo=xxxx&key=123456
</code></pre>
<ul>
<li>最终得到发送的数据:</li>
</ul>
<pre><code>
{
"orgCode": "xxx",
"orderNo": "xxxx",
"sign": "10AD305A511101E9EC1D899B6EEF4102"
}
</code></pre>
<hr />
<h3>加密说明</h3>
<ul>
<li>通过微保分配的公钥加密步骤1的结果,得到reqmsg密文串</li>
</ul>
<pre><code>
示例公钥:MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhgHFCQUoJcF7yrL+JCa7JeCkF4lAEOXSn1NvDN+8mDjFsBtlQYnKEZ6vWQKiIavBr3IzXdE+2dXeFtNTSJd4+wGO4r4mbsboOGnama3lcGMljC7EWG+GP/LLV4H+vbUBJ65ROgulf0wZq0+dYCh85uadNMiRWI4MYZun26g9fxxKjZF0HyvVWrpFA0pWz2twxJw4mYkoXJ8Nc6oTvmtxlRuO0uhnw1ya/IwXJxojNvd9gfuGuytiWADhnJPWn4SXdHPknQfGfVv2H0rjZVkzdbXRSP2LI4O9HzeGPioP+WVqNKWX98vdXB7gLtJl4egULgIWUXUCdPMU2ZLs15dxaQIDAQAB
原明文:
{
"orgCode": "xxx",
"orderNo": "xxxx",
"sign": "10AD305A511101E9EC1D899B6EEF4102"
}
加密后报文:
MaN4tl0LcRf49Wd9woWUs1QpuCZRDF2giFNuCgDHcsE0qfsj4l2X3TWKvlf286D35UieP8qMJiYwe9W8V/Wp7SSHDWXQe+0ihhd2gZTnOhVtI5HXW6MI+LmxYmOKTU7WAlwqAdCI79BCrl8WY9jjAbREvS0BRiKnEs0MoHByTb5InHGSpjpwDd+ZdVVcgevy2CyeKQohdKSJZk14c3ASORV+ZdleYBY5x5pjYN7evSbRawOM19eW2OxBp11p/Bt+82Rq/B+6vNQP4Dmu8d8hMreMcLGh4ysyCcDULCE7hY7RSiIJ8K0BGXo3a8ksyROwEihxINZRAPL1avRioYWJbQ==
发送给微保报文:
{
"customerNo": "微保分配给商户的商户号",
"reqmsg": "MaN4tl0LcRf49Wd9woWUs1QpuCZRDF2giFNuCgDHcsE0qfsj4l2X3TWKvlf286D35UieP8qMJiYwe9W8V/Wp7SSHDWXQe+0ihhd2gZTnOhVtI5HXW6MI+LmxYmOKTU7WAlwqAdCI79BCrl8WY9jjAbREvS0BRiKnEs0MoHByTb5InHGSpjpwDd+ZdVVcgevy2CyeKQohdKSJZk14c3ASORV+ZdleYBY5x5pjYN7evSbRawOM19eW2OxBp11p/Bt+82Rq/B+6vNQP4Dmu8d8hMreMcLGh4ysyCcDULCE7hY7RSiIJ8K0BGXo3a8ksyROwEihxINZRAPL1avRioYWJbQ=="
}
</code></pre>