package com.changshin.himalaya;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import cn.hutool.json.JSONObject;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.http.*;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.Mac;
public class SignatureDemo {
private static final String DEFAULT_ENCODING = "UTF-8";
private static final String HMAC_SHA1 = "HmacSHA1";
private static final String APP_KEY = "d6ee8fea9256c259af9cae4499722cd5";
private static final String APP_SECRET = "780ac99bd0654912760b4a7277fcdd2f";
private static final String REDIRECT_URL = "http://api.ximalaya.com/openapi-collector-app/get_access_token";
/**
* 生成签名
*
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
Map<String, String> paramsMap = new LinkedHashMap<String, String>();
String accesstoken = buildAccessToken();
String ticket = buildTicket(accesstoken);
paramsMap.put("js_ticket", ticket);
String nonce = UUID.randomUUID().toString();
paramsMap.put("nonce", nonce);
Date date = new Date();
String timestamp = String.valueOf(date.getTime());
paramsMap.put("timestamp", timestamp);
paramsMap.put("url", "http://xmly.work/jssdk-demo/jsdebug/?id=cl9u0");
String appSecret = APP_SECRET;
String serverAuthStaticKey = "z0hh5l9A";
String seed = appSecret + serverAuthStaticKey;
String sig = caculateSignature(paramsMap, seed);
System.out.println("calculate signature: " + sig);
System.out.println("timestamp:" + timestamp + ",nonce:" + nonce + ",signature:" + sig);
}
public static String buildAccessToken() throws UnsupportedEncodingException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
RestTemplate himalayaRestTemplate = new RestTemplate(RestTemplateConfig.skipSslCheckHttpRequestFactory());
String requestUrl = "https://api.ximalaya.com/oauth2/js/access_token";
String redirectUrl = "https://www.baidu.com.cn";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, String> request = new LinkedMultiValueMap<>();
request.add("client_id", APP_KEY);
request.add("client_secret", APP_SECRET);
request.add("grant_type", "js_client_credentials");
request.add("device_id", "app_jssdk_device");
String urlEncoderStr = URLEncoder.encode(REDIRECT_URL, "UTF-8");
String parseStr = URLDecoder.decode("http%3a%2f%2fapi.ximalaya.com%2fopenapi-collector-app%2fget_access_token", "UTF-8");
System.out.println(parseStr);
request.add("redirect_uri", urlEncoderStr);
request.add("nonce", UUID.randomUUID().toString());
Date date = new Date();
request.add("timestamp", String.valueOf(date.getTime()));
HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<MultiValueMap<String, String>>(request, headers);
ResponseEntity<String> stringResponseEntity = himalayaRestTemplate.exchange(requestUrl, HttpMethod.POST, requestEntity, String.class);
String body = stringResponseEntity.getBody();
JSONObject jsonObject = new JSONObject(body);
System.out.println(body.toString());
return jsonObject.get("access_token").toString();
}
public static String buildTicket(String accessToken) throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException, UnsupportedEncodingException {
RestTemplate himalayaRestTemplate = new RestTemplate(RestTemplateConfig.skipSslCheckHttpRequestFactory());
String requestUrl = "https://api.ximalaya.com/oauth2/js/ticket";
String redirectUrl = "https://www.baidu.com.cn";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, String> request = new LinkedMultiValueMap<>();
request.add("client_id", APP_KEY);
request.add("client_secret", APP_SECRET);
request.add("access_token", accessToken);
request.add("device_id", "app_jssdk_device");
String urlEncoderStr = URLEncoder.encode(REDIRECT_URL, "UTF-8");
String parseStr = URLDecoder.decode("http%3a%2f%2fapi.ximalaya.com%2fopenapi-collector-app%2fget_access_token", "UTF-8");
System.out.println(parseStr);
request.add("redirect_uri", urlEncoderStr);
request.add("nonce", UUID.randomUUID().toString());
Date date = new Date();
request.add("timestamp", String.valueOf(date.getTime()));
HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<MultiValueMap<String, String>>(request, headers);
ResponseEntity<String> stringResponseEntity = himalayaRestTemplate.exchange(requestUrl, HttpMethod.POST, requestEntity, String.class);
String body = stringResponseEntity.getBody();
JSONObject jsonObject = new JSONObject(body);
System.out.println(body.toString());
return jsonObject.get("js_ticket").toString();
}
/**
* 璁$畻鍙傛暟鐨勭鍚嶅€� demo
*
* @param paramsMap
* @param seed: seed鍗充负app_secret+serverAuthenticateStaticKey
* @return
* @throws NoSuchAlgorithmException
* @throws InvalidKeyException
* @throws UnsupportedEncodingException
*/
public static String caculateSignature(Map<String, String> paramsMap, String seed) throws InvalidKeyException, NoSuchAlgorithmException, UnsupportedEncodingException {
if (paramsMap == null || paramsMap.isEmpty() || StringUtils.isEmpty(seed)) {
throw new IllegalArgumentException("paramsMap and seed should not empty");
}
if (!(paramsMap instanceof TreeMap<?, ?>)) {
paramsMap = new TreeMap<String, String>(paramsMap);
}
StringBuilder paramsBuilder = new StringBuilder();
for (Map.Entry<String, String> entry : paramsMap.entrySet()) {
paramsBuilder.append(entry.getKey());
paramsBuilder.append("=");
paramsBuilder.append(entry.getValue());
paramsBuilder.append("&");
}
System.out.println(paramsBuilder.toString());
paramsBuilder.deleteCharAt(paramsBuilder.length() - 1);
String paramsEncodedStr = base64Encode(paramsBuilder.toString());
String sig = hmacSHA1ToStr(paramsEncodedStr, seed);
// LOG.debug(String.format("caculateSignature, paramsMap: %s, paramsEncodedStr: %s, seed: %s, caculated sig: %s", paramsMap, paramsEncodedStr,
// seed, sig));
return sig;
}
/**
* HMAC SHA1绛惧悕鎴栨憳瑕佺畻娉�
*
* @param data
* @param key
* @return
* @throws InvalidKeyException
* @throws NoSuchAlgorithmException
*/
private static String hmacSHA1ToStr(String data, String key) throws InvalidKeyException, NoSuchAlgorithmException {
if (data == null || key == null) {
return null;
}
return hmacSHA1ToStr(data.getBytes(), key.getBytes());
}
/**
* HMAC SHA1绛惧悕鎴栨憳瑕佺畻娉�
*
* @param data 寰呮憳瑕佺殑瀛楄妭鏁版嵁
* @param key 浣跨敤鐨刱ey
* @return
* @throws NoSuchAlgorithmException
* @throws InvalidKeyException
*/
private static String hmacSHA1ToStr(byte[] data, byte[] key) throws NoSuchAlgorithmException, InvalidKeyException {
return DigestUtils.md5Hex(hmacSHA1(data, key));
}
private static byte[] hmacSHA1(byte[] data, byte[] key) throws NoSuchAlgorithmException, InvalidKeyException {
if (data == null || key == null) {
return null;
}
SecretKeySpec signingKey = new SecretKeySpec(key, HMAC_SHA1);
Mac mac = Mac.getInstance(HMAC_SHA1);
mac.init(signingKey);
return mac.doFinal(data);
}
/**
* Base64缂栫爜
*
* @param data 瀛楃涓叉暟鎹�
* @return
* @throws UnsupportedEncodingException
*/
private static String base64Encode(String data) throws UnsupportedEncodingException {
if (data == null) {
return null;
}
return Base64.encodeBase64String(data.getBytes(DEFAULT_ENCODING));
}
}