Java 三方接口PHP写法;doHmacSHA2; 将字节数组转换成16进制字符串;Mac.getInstance;HmacSHA256;
先看一段 Java 代码,一个签名过程
1 package com.sixents.bss.filter; 2 3 4 import org.apache.http.HttpEntity; 5 import org.apache.http.NameValuePair; 6 import org.apache.http.client.entity.UrlEncodedFormEntity; 7 import org.apache.http.client.methods.CloseableHttpResponse; 8 import org.apache.http.client.methods.HttpPost; 9 import org.apache.http.impl.client.CloseableHttpClient; 10 import org.apache.http.impl.client.HttpClients; 11 import org.apache.http.message.BasicNameValuePair; 12 import org.apache.http.util.EntityUtils; 13 14 import javax.crypto.Mac; 15 import javax.crypto.spec.SecretKeySpec; 16 import java.nio.charset.Charset; 17 import java.security.InvalidKeyException; 18 import java.security.NoSuchAlgorithmException; 19 import java.util.*; 20 import java.util.Map.Entry; 21 22 /** 23 * @author zy 24 * date 2021-08-19 25 */ 26 public class demoTest { 27 28 29 public static void main(String[] args) throws Exception{ 30 String sik = "0797517995";//请填写您申请的sik 31 String sis = "inuHf8DvK+z3lqor168yDcx60lAcMCtAagcchaxWRlvWTq6WImQ4zQVEibnwhegShrQNft8zvGXA" + 32 "C6TSH4gjQzmaTSeNzugv0dTSj9m2eiQ=";//请填写您申请的sis 33 String apiName = "get-account-list";// 访问的API接口名称 34 String apiPath = "/rest/" + apiName + "/" + "sik" + "/"+sik;// API路径,注意没有问号 35 // 参数列表(加签的时候需要进行字典序升序排序) 36 Map<String, String> paramMap = new HashMap<String, String>(); 37 paramMap.put("pageNum", "1"); 38 paramMap.put("pageSize", "20"); 39 paramMap.put("serverType", "1"); 40 // 毫秒级时间戳,一定是毫秒级!重要!!! 41 String timestamp = String.valueOf(System.currentTimeMillis()); 42 System.out.println("时间戳:"+timestamp); 43 String signatureStr = demoTest.doHmacSHA2(apiPath, paramMap, sis, timestamp); 44 System.out.println("加签值:"+signatureStr);//打印sign值 45 46 String qxwzUrl = "http://localhost:21009";//服务器地址 47 String queryUrl = qxwzUrl + apiPath + "?_sign=" + signatureStr; 48 System.out.println(queryUrl); 49 50 //发送http请求,获取返回值 51 doHttpPost(queryUrl,paramMap,timestamp); 52 } 53 54 public static void doHttpPost(String url,Map<String, String> paramMap, String timestamp) throws Exception { 55 CloseableHttpClient httpClient = HttpClients.createDefault(); 56 HttpPost httpPost = new HttpPost(url); 57 httpPost.setHeader("content-type", "application/json"); 58 httpPost.setHeader("wz-acs-timestamp", timestamp);//此处注意加上时间戳,否则http请求将无效 59 List<NameValuePair> nvps = new ArrayList<NameValuePair>(); 60 for (Map.Entry<String, String> entry : paramMap.entrySet()){ 61 if (entry.getValue() == null) continue; 62 nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue())); 63 } 64 httpPost.setEntity(new UrlEncodedFormEntity(nvps, "UTF-8"));//处理中文编码的问题 65 66 67 try { 68 CloseableHttpResponse response = (CloseableHttpResponse) httpClient.execute(httpPost); 69 try { 70 HttpEntity entity = response.getEntity(); 71 if (entity != null) { 72 System.out.println("返回值:"+EntityUtils.toString(entity)); 73 /* 74 * 此处针对返回结果进行不同的处理 75 */ 76 EntityUtils.consume(entity); 77 } 78 } finally { 79 response.close(); 80 } 81 82 } catch (Exception e) { 83 e.printStackTrace(); 84 }finally { 85 if (httpPost != null) { 86 httpPost.releaseConnection();//释放资源 87 } 88 if(httpClient != null){ 89 httpClient.close();//释放资源 90 } 91 } 92 } 93 94 /* 95 * 将字节数组转换成16进制字符串 96 * */ 97 public static String encodeHexStr(final byte[] bytes){ 98 if (bytes == null) { 99 return null; 100 } 101 char[] digital = "0123456789ABCDEF".toCharArray(); 102 char[] result = new char[bytes.length * 2]; 103 for (int i = 0; i < bytes.length; i++) { 104 result[i * 2] = digital[(bytes[i] & 0xf0) >> 4]; 105 result[i * 2 + 1] = digital[bytes[i] & 0x0f]; 106 } 107 return new String(result); 108 } 109 110 /* 111 * 加签算法 112 * */ 113 public static <T> String doHmacSHA2(String path, Map<String, T> params, String key, String timestamp) { 114 115 List<Map.Entry<String, T>> parameters = new ArrayList<Map.Entry<String,T>>(params.entrySet()); 116 SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), "HmacSHA256"); 117 Charset CHARSET_UTF8 = Charset.forName("UTF-8"); 118 Mac mac; 119 try { 120 mac = Mac.getInstance("HmacSHA256"); 121 mac.init(signingKey); 122 } catch (NoSuchAlgorithmException e) { 123 throw new IllegalStateException(e.getMessage(), e); 124 } catch (InvalidKeyException e) { 125 throw new IllegalStateException(e.getMessage(), e); 126 } 127 if(path != null && path.length() > 0){ 128 mac.update(path.getBytes(CHARSET_UTF8)); 129 } 130 if(parameters != null){ 131 Collections.sort(parameters, new MapEntryComparator<String, T>()); 132 for (Map.Entry<String, T> parameter : parameters) { 133 byte[] name = parameter.getKey().getBytes(CHARSET_UTF8); 134 Object value = parameter.getValue(); 135 if(value instanceof Collection){ 136 for (Object o : (Collection)value){ 137 mac.update(name); 138 if(o != null){ 139 mac.update(o.toString().getBytes(CHARSET_UTF8)); 140 } 141 } 142 }else{ 143 mac.update(name); 144 if(value != null){ 145 mac.update(value.toString().getBytes(CHARSET_UTF8)); 146 } 147 } 148 } 149 } 150 if(timestamp != null && timestamp.length() > 0){ 151 mac.update(timestamp.toString().getBytes(CHARSET_UTF8)); 152 } 153 return encodeHexStr(mac.doFinal()); 154 } 155 } 156 157 /* 158 * Map参数排序类 159 * */ 160 161 class MapEntryComparator<K, V> implements Comparator<Map.Entry<K, V>> { 162 163 @Override 164 public int compare(Entry<K, V> o1, Entry<K, V> o2) { 165 if (o1 == o2) { 166 return 0; 167 } 168 final String k1 = o1.getKey().toString(); 169 final String k2 = o2.getKey().toString(); 170 int l1 = k1.length(); 171 int l2a = k2.length(); 172 for (int i = 0; i < l1; i++) { 173 char c1 = k1.charAt(i); 174 char c2; 175 if (i < l2a) { 176 c2 = k2.charAt(i); 177 } else { 178 return 1; 179 } 180 if (c1 > c2) { 181 return 1; 182 } else if (c1 < c2) { 183 return -1; 184 } 185 } 186 if (l1 < l2a) { 187 return -1; 188 }else if(l1 == l2a) { 189 return 0; 190 }else { 191 return -1; 192 } 193 } 194 195 }
PHP 写法如此简单:
1 private function get_sign($path, $params, $timestamp) 2 { 3 if (empty($params)) { 4 die('miss params'); 5 } 6 7 // 排序 8 ksort($params); 9 10 $ctx = hash_init('sha256', HASH_HMAC, $this->sis); 11 12 hash_update($ctx, utf8_encode($path)); 13 14 foreach ($params as $key => $value) { // 如果 $value 还是数组再循环一次即可 15 hash_update($ctx, utf8_encode($key)); 16 hash_update($ctx, utf8_encode($value)); 17 } 18 19 hash_update($ctx, utf8_encode($timestamp)); 20 21 return strtoupper(hash_final($ctx)); 22 } 23