04 国密无感登录

国密无感登录集成文档说明


服务端接入文档

<p>[TOC]</p> <h2>通用说明</h2> <h3>接口协议说明</h3> <p>接口数据请求不采用 json 格式封装的字符串,直接采用post 的 application/x-www-form-urlencoded 方式提交请求。响应返回均为 json 格式。</p> <table> <thead> <tr> <th style="text-align: left;">名称</th> <th style="text-align: left;">说明</th> </tr> </thead> <tbody> <tr> <td style="text-align: left;">说明</td> <td style="text-align: left;">服务端接口说明</td> </tr> <tr> <td style="text-align: left;">协议</td> <td style="text-align: left;">HTTPS</td> </tr> <tr> <td style="text-align: left;">请求方式</td> <td style="text-align: left;">POST</td> </tr> <tr> <td style="text-align: left;">编码格式</td> <td style="text-align: left;">UTF8</td> </tr> <tr> <td style="text-align: left;">请求内容类型</td> <td style="text-align: left;">application/x-www-form-urlencoded</td> </tr> <tr> <td style="text-align: left;">响应内容类型</td> <td style="text-align: left;">application/json</td> </tr> </tbody> </table> <h3>API请求结构</h3> <table> <thead> <tr> <th style="text-align: left;">名称</th> <th style="text-align: left;">描述</th> <th style="text-align: left;">备注</th> </tr> </thead> <tbody> <tr> <td style="text-align: left;">公共参数</td> <td style="text-align: left;">每个接口都包含的通用参数</td> <td style="text-align: left;">详见 <strong>公共请求参数</strong> 说明</td> </tr> <tr> <td style="text-align: left;">私有参数</td> <td style="text-align: left;">每个接口特有的参数</td> <td style="text-align: left;">详见每个API接口定义</td> </tr> </tbody> </table> <h2>公共请求参数</h2> <p>在进行API请求时,需要传递的一系列共同的参数。</p> <table> <thead> <tr> <th style="text-align: left;">参数名称</th> <th style="text-align: left;">类型</th> <th style="text-align: left;">是否必选</th> <th style="text-align: left;">最大长度</th> <th style="text-align: left;">描述</th> </tr> </thead> <tbody> <tr> <td style="text-align: left;">appId</td> <td style="text-align: left;">String</td> <td style="text-align: left;">必填</td> <td style="text-align: left;">9</td> <td style="text-align: left;">应用标识,在商户管理平台创建产品时统一分配,应用标识。</td> </tr> <tr> <td style="text-align: left;">ver</td> <td style="text-align: left;">String</td> <td style="text-align: left;">必填</td> <td style="text-align: left;">2</td> <td style="text-align: left;">接口版本号 详见 <strong>版本号参数</strong> 说明</td> </tr> <tr> <td style="text-align: left;">timestamp</td> <td style="text-align: left;">Number</td> <td style="text-align: left;">必填</td> <td style="text-align: left;">13</td> <td style="text-align: left;">请求当前 UNIX 时间戳(毫秒单位)</td> </tr> <tr> <td style="text-align: left;">nonce</td> <td style="text-align: left;">String</td> <td style="text-align: left;">必填</td> <td style="text-align: left;">32</td> <td style="text-align: left;">随机字符串与timestamp 联合起来</td> </tr> <tr> <td style="text-align: left;">sign</td> <td style="text-align: left;">String</td> <td style="text-align: left;">必填</td> <td style="text-align: left;">32</td> <td style="text-align: left;">签名,详见 <strong>签名工具类</strong>。所有请求参数(包括公共参数和私有参数,但不包括 sign 参数)。 <strong>1&gt; </strong>按照参数名ASCII码表升序顺序排序 如:foo=1, bar=2, foobar=3, baz=4 排序后的顺序是 bar=2, baz=4, foo=1, foobar=3 将排序好的参数名和参数值构造成字符串,格式为:key1+value1+key2+value2…根据上面的示例得到的构造结果为:bar2baz4foo1foobar3 <strong>2&gt; </strong>选择与 appid 配对的 appkey ,加到上一步构造好的参数字符串之后,如 appKey=6308afb129ea00301bd7c79621d07591则最后的参数字符串为 bar2baz4foo1foobar36308afb129ea00301bd7c79621d07591 <strong>3&gt; </strong>把拼装好的字符串采用 utf-8 编码,使用 SM3 算法对字符串进行摘要,计算得到 sign 参数值,将其加入到接口请求参数中即可。</td> </tr> </tbody> </table> <h2>API接口</h2> <h3>获取会话密钥解密uToken</h3> <p><strong>请求URL:</strong></p> <ul> <li><code>https://mr.jjdaq.com/mirenServer/{ver}/app/getRiskControlKey</code></li> </ul> <p><strong>请求方式:</strong></p> <ul> <li>POST</li> </ul> <p><strong>参数:</strong></p> <table> <thead> <tr> <th style="text-align: left;">参数名称</th> <th style="text-align: left;">类型</th> <th style="text-align: left;">是否必选</th> <th style="text-align: left;">最大长度</th> <th style="text-align: left;">描述</th> </tr> </thead> <tbody> <tr> <td style="text-align: left;">digest</td> <td style="text-align: left;">string</td> <td style="text-align: left;">必填</td> <td style="text-align: left;">96</td> <td style="text-align: left;">签名摘要(SDK无感登录接口返回的签名值)</td> </tr> </tbody> </table> <p><strong>返回示例</strong></p> <pre><code>{ &amp;quot;msg&amp;quot;: &amp;quot;描述&amp;quot;, &amp;quot;code&amp;quot;: 状态码, &amp;quot;data&amp;quot;: &amp;quot;{\&amp;quot;sessionKey\&amp;quot;:\&amp;quot;base64编码后的会话密钥\&amp;quot;}&amp;quot; } </code></pre> <p>&lt;br/&gt;&lt;br/&gt;</p> <h2>工具类</h2> <h3>签名工具类</h3> <pre><code class="language-java">/** * 生成签名信息 * * @param appkey 产品私钥 * @param params 接口请求参数名和参数值,不包括sign参数名 * @return sign 签名摘要 */ public static String genSignature(Map&amp;lt;String, String&amp;gt; params, String appkey) { // 1. 参数名按照ASCII码表升序排序 String[] keys = params.keySet().toArray(new String[0]); Arrays.sort(keys); // 2. 按照排序拼接参数名与参数值 StringBuilder sb = new StringBuilder(); for (String key : keys) { sb.append(key).append(params.get(key)); } // 3. 将appkey拼接到最后 sb.append(appkey); System.out.println(&amp;quot;原数据: &amp;quot; + sb); byte[] md = new byte[32]; // 4. SM3签名 byte[] msg1 = sb.toString().getBytes(StandardCharsets.UTF_8); SM3Digest sm3 = new SM3Digest(); sm3.update(msg1, 0, msg1.length); sm3.doFinal(md, 0); String sign = new String(Hex.encode(md)); return sign; }</code></pre> <h3>HTTP工具类</h3> <pre><code class="language-java"> /** * @param url :请求接口地址 * @param params :参数 * @return jsonObject 请求结果 */ public static JSONObject postRequest(String url, Map&amp;lt;String, String&amp;gt; params) { try { FormBody.Builder builder = new FormBody.Builder(); for (Map.Entry&amp;lt;String, String&amp;gt; m : params.entrySet()) { builder.add(m.getKey(), m.getValue()); } RequestBody body = builder.build(); Request request = new Request.Builder().post(body).url(url).build(); Response response = OkHttpUtil.getInstance().newCall(request).execute(); if (response.isSuccessful()) { String content = response.body().string(); if (StringUtils.isNotBlank(content)) { JSONObject jsonObject = JSONObject.parseObject(content); return jsonObject; } } } catch (Exception e) { e.printStackTrace(); } return null; }</code></pre> <h3>密钥格式转换</h3> <pre><code class="language-java"> /** * @param salt :密钥因子 * @return result 密钥 */ public static String getSecretKey(String salt) throws NoSuchAlgorithmException { String result = &amp;quot;&amp;quot;; MessageDigest md = MessageDigest.getInstance(&amp;quot;MD5&amp;quot;); md.update(salt.getBytes()); byte[] byteResult = md.digest(); int i; StringBuffer stringBuffer = new StringBuffer(&amp;quot;&amp;quot;); for (int offset = 0; offset &amp;lt; byteResult.length; offset++) { i = byteResult[offset]; if (i &amp;lt; 0) { i += 256; } if (i &amp;lt; 16) { stringBuffer.append(&amp;quot;0&amp;quot;); } stringBuffer.append(Integer.toHexString(i)); } result = stringBuffer.toString().substring(8, 24); return result; }</code></pre> <p>&lt;br/&gt;&lt;br/&gt;</p> <h2>接口响应参数</h2> <p>所有接口响应值采用 JSON 格式,如无特殊说明,每次请求的返回值中,都包含下面字段:</p> <table> <thead> <tr> <th style="text-align: left;">字段名</th> <th style="text-align: left;">类型</th> <th style="text-align: left;">参数描述</th> <th style="text-align: left;">说明</th> </tr> </thead> <tbody> <tr> <td style="text-align: left;">code</td> <td style="text-align: left;">int</td> <td style="text-align: left;">响应代码</td> <td style="text-align: left;">0表示成功,其他代码都为失败,详情参考附录。</td> </tr> <tr> <td style="text-align: left;">msg</td> <td style="text-align: left;">String</td> <td style="text-align: left;">响应描述</td> <td style="text-align: left;">响应代码描述</td> </tr> <tr> <td style="text-align: left;">data</td> <td style="text-align: left;">Object</td> <td style="text-align: left;">数据内容</td> <td style="text-align: left;">数据内容 </td> </tr> </tbody> </table> <h3>响应码</h3> <p>响应码(code)是密认服务 API 调用的结果。当返回码不为 0 时,表示请求未正常执行,返回码描述 (msg) 对该结果进行了细化补充,用户可根据返回码判断 API 的执行情况。 所有接口调用返回值均包含 code 和 msg 字段,code 为返回码值,msg 为返回码描述信息,返回码表如下:</p> <table> <thead> <tr> <th style="text-align: left;">序号</th> <th style="text-align: left;">参数</th> <th style="text-align: left;">说明</th> </tr> </thead> <tbody> <tr> <td style="text-align: left;">1</td> <td style="text-align: left;">0</td> <td style="text-align: left;">调用成功</td> </tr> <tr> <td style="text-align: left;">2</td> <td style="text-align: left;">1</td> <td style="text-align: left;">错误描述参考 msg</td> </tr> <tr> <td style="text-align: left;">3</td> <td style="text-align: left;">1001</td> <td style="text-align: left;">参数不能为空</td> </tr> <tr> <td style="text-align: left;">4</td> <td style="text-align: left;">1002</td> <td style="text-align: left;">时间戳过期</td> </tr> <tr> <td style="text-align: left;">5</td> <td style="text-align: left;">1003</td> <td style="text-align: left;">验签失败</td> </tr> <tr> <td style="text-align: left;">6</td> <td style="text-align: left;">1004</td> <td style="text-align: left;">应用不存在</td> </tr> <tr> <td style="text-align: left;">7</td> <td style="text-align: left;">1005</td> <td style="text-align: left;">应用已停用</td> </tr> <tr> <td style="text-align: left;">8</td> <td style="text-align: left;">1006</td> <td style="text-align: left;">商户信息不存在</td> </tr> <tr> <td style="text-align: left;">9</td> <td style="text-align: left;">1007</td> <td style="text-align: left;">重复请求</td> </tr> </tbody> </table>

页面列表

ITEM_HTML