===================== 聚合鉴权 RealMe 介绍 ===================== .. role:: raw-latex(raw) :format: latex .. .. _header-n2: 介绍 ============= 聚合鉴权平台专注企业级鉴权服务,聚合各类识别认证功能,为企业提供标准统一的鉴权服务接口和基于场景的行业解决方案。 .. _header-n3: 服务调用说明 ============= 聚合鉴权 RealMe 遵循标准 HTTP 协议及 RESTful 规范,使用 HTTP 标准状态码返回接口服务调用结果,并自定义了业务级别的错误代码以提供更详细的错误描述。结果数据将以 json 格式返回,易于解析,便于扩展。 .. _header-n6: 调用前准备 ~~~~~~~~~~ 1) 注册并登录“\ `聚合鉴权 RealMe 网站 `__\ ”,在“应用列表”中,查看应用的 ``app_token`` 及 ``app_key``。 2) ``app_token``:调用接口服务时使用,作为调用方系统标识,建议为不同产品及不同应用 (如 web/ Android / iOS 等) 申请不同的 ``app_token``,聚合鉴权 RealMe 可帮您区分并记录不同 ``app_token`` 的使用情况。 3) ``app_key``:对请求数据加签时使用,与 ``app_token`` 一一对应,参考“签名_”。 .. _header-n14: 编码转换 ~~~~~~~~ 对于含中文或特殊字符等参数的请求,请在请求前做转码 (URL Encode) ,编码格式为 ``UTF-8``。 .. _header-n17: .. _签名: 签名 ~~~~ 调用接口服务时,需提供请求签名 (sign) ,以保证请求数据未被篡改。签名公式为:HMAC-SHA256-HEX (请求方式 + 服务地址 + 拼接的请求参数值,``app_key``)。 1) 请求方式:POST/GET/PUT/DELETE,当前接口的请求方式。 2) 服务地址:完整的请求 URL 地址,GET 请求不含 “ ? ” 后的参数部分。 3) 拼接的请求参数值:请求参数按照 key 的 ASCII 字符串顺序升序排列,将value 拼接后做编码转换。 4) app_key:应用列表中展示的调用方密钥值。 5) 特殊说明:对于请求值为二进制的参数 (如图片等文件),由于数据量过大,请求值取二进制数据的 MD5 值。 .. _header-n30: 调用示例 ~~~~~~~~ 如测试应用: +--------------+---------+ | app_token | app_key | +==============+=========+ | TESTRA000401 | 123456 | +--------------+---------+ 1) 确定公共请求参数及应用请求参数。 如调用身份证实名认证接口: 请求地址:\ https://realme.cloudpnr.com/realme-proxy/v4/trade/namecheck 请求参数: order_date = 20170306 order_id = 20170119000002 app_token = TESTRA000401 full_name = 测试 id_number = 330326198511230201 video_pic = YmV0YSAgICCGL2V7kJn9XV5leMhFnH/8ShgmCGVXbZKKuQSORISK0ByujPxN9gfuTlptg7H nHaREhJ3kC66WIkoIFN5yTl18jsoEflCEitAcr4z8TggU3lBuXGyeuAR+RIWK0ByuniJOKRTeYE5cbIq5BH 5EhJ72INyM/FYIFN5MT source_channel = 0 imei = mer_bg_url = http://test.chinapnr.com/recv 2) 生成签名值。 - 请求方式为 ``POST``, 服务地址为 https://realme.cloudpnr.com/realme-proxy/v4/trade/namecheck - 请求参数含图片, 对图片做 32 位 ``MD5``,并全转为大写,得到:EBECFDBCF6D86D558781C110C9623661 - 请求参数按照 key 的 ASCII 字符串顺序升序排列,将 value 拼接,得到: 330326198511230201http://test.chinapnr.com/recv40170306201701190000020EBECFDBCF6D86 D558781C110C9623661 - 请求方式、服务地址与请求参数值拼接,得到: POSThttps://realme.cloudpnr.com/realme-proxy/v4/trade/namecheck330326198511230201ht tp://test.chinapnr.com/recv40170306201701190000020EBECFDBCF6D86D558781C110C9623661 - 使用 ``app_key`` 作为密钥,对获得的字符串 (message) 做HMAC-SHA256,得到签名: cb3c818a286ca47f1f92c6cf235923c8285b8bbfb190d274e806125dd50c2a5f .. code:: java public static String HMACSHA256(byte[] data, byte[] key) { try { SecretKeySpec signingKey = new SecretKeySpec(key, "HmacSHA256"); Mac mac = Mac.getInstance("HmacSHA256"); mac.init(signingKey); return byte2hex(mac.doFinal(data)); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } return null; } public static String byte2hex(byte[] b) { StringBuilder hs = new StringBuilder(); String stmp; for (int n = 0; b != null && n < b.length; n++) { stmp = Integer.toHexString(b[n] & 0XFF); if (stmp.length() == 1) hs.append('0'); hs.append(stmp); } return hs.toString(); } 3) 发送请求。 .. code:: java HttpClient client = new DefaultHttpClient(); HttpPost post = new HttpPost("https://realme.cloudpnr.com/realme-api/v4/trade/staticfacecheck"); try { List nvps = new ArrayList(); nvps.add(new BasicNameValuePair("order_date","20170101")); nvps.add(newBasicNameValuePair("order_id", "201701010000001")); nvps.add(newBasicNameValuePair("app_token", "TESTRA000401")); nvps.add(new BasicNameValuePair("sign","cb3c818a286ca47f1f92c6cf235923c8285b8bbfb190d274e806125dd50c2a5f")); .......//TODO 添加所有参数 post.setEntity(new UrlEncodedFormEntity(nvps)); post.addHeader(“env”, ”test”); HttpResponse httpResponse = client.execute(post); int code = httpResponse.getStatusLine().getStatusCode(); String returnStr = EntityUtils.toString(httpResponse.getEntity()); } catch (Exception e) { e.printStackTrace(); } .. _header-n80: 异步结果通知 ~~~~~~~~~~~~ 1) 对于无法实时返回处理结果的请求,聚合鉴权 RealMe 仅返回请求已接收,并将在请求处理完成后,把处理结果以 ``post`` 方式发送至调用方指定的接收地址。 2) 每个异步结果通知将有一个唯一标识,一般为系统流水号 ``seq_id``。在接收到异步结果后,请输出 ``“RECV_ORD_ID_唯一标识”``,告知聚合鉴权 RealMe 已接收到异步结果。 3) 出于数据安全考虑,建议接收地址使用更安全的 HTTPS 协议地址。 异步结果通知处理示例: .. code:: java String seqId = ""; String returnCode = ""; String returnMessage = ""; for (em = request.getParameterNames(); em.hasMoreElements();) { String key = em.nextElement().toString(); String value = request.getParameter(key); if(StringUtils.equals(key, "seq_id")) { seqId = value; } else if (StringUtils.equals(key, "return_code")){ returnCode = value; } else if (StringUtils.equals(key, "return_message")){ returnMessage = value; } } if(StringUtils.isNotBlank(seqId)) { getWriter().print("RECV_ORD_ID_"+seqId); }