|
@@ -0,0 +1,158 @@
|
|
|
|
+package com.raycos.raycosdatacenterapi.amzorder.util;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+import com.alibaba.nacos.common.utils.StringUtils;
|
|
|
|
+
|
|
|
|
+import java.io.UnsupportedEncodingException;
|
|
|
|
+import java.security.InvalidKeyException;
|
|
|
|
+import java.security.NoSuchAlgorithmException;
|
|
|
|
+import java.util.*;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+public class AmazonUtil {
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 计算加密密钥及返回Header头
|
|
|
|
+ *
|
|
|
|
+ * @param methodName
|
|
|
|
+ * @param requestMethod 请求方式,例如: GET POST
|
|
|
|
+ * @param host 请求主机地址, 例如: sellingpartnerapi-na.amazon.com, 根据区域不同地址不同
|
|
|
|
+ * @param payload 传参,当为GET请求 参数留空, POST请求 拼为: abc=x1&efg=x2, 或json 格式 {"abc":"x1","efg":"x2"}
|
|
|
|
+ * @param queryString 当为GET请求,有传参则填写在这里,例如: abc=x1&efg=x2
|
|
|
|
+ * @param region 区域,例如:us-east-1
|
|
|
|
+ * @param accessToken 用户授权店铺后,短令牌token信息
|
|
|
|
+ * @return
|
|
|
|
+ * @throws UnsupportedEncodingException
|
|
|
|
+ * @throws NoSuchAlgorithmException
|
|
|
|
+ * @throws IllegalStateException
|
|
|
|
+ * @throws InvalidKeyException
|
|
|
|
+ */
|
|
|
|
+ public static Map<String, String> calculateAwsSignatureAndReturnHeaders(String methodName,
|
|
|
|
+ String requestMethod,
|
|
|
|
+ String host,
|
|
|
|
+ String payload,
|
|
|
|
+ String queryString,
|
|
|
|
+ String region,
|
|
|
|
+ String accessToken) throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException, IllegalStateException {
|
|
|
|
+
|
|
|
|
+ Date date = new Date();
|
|
|
|
+ String reqDate = CommonUtil.getTimeFormat(date, "yyyyMMdd", true);
|
|
|
|
+ String reqDateTime = CommonUtil.getTimeFormat(date, "yyyyMMdd'T'HHmmss'Z'", true);
|
|
|
|
+
|
|
|
|
+ Map<String, String> canonicalHeaders = canonicalHeaders(host, accessToken, reqDateTime);
|
|
|
|
+
|
|
|
|
+ List<String> canonicalHeaderList = new ArrayList<>();
|
|
|
|
+ for (Map.Entry<String, String> entry : canonicalHeaders.entrySet()) {
|
|
|
|
+ canonicalHeaderList.add(entry.getKey() + ":" + entry.getValue());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ String canonicalHeaderstr = StringUtils.join(canonicalHeaderList, "\n");
|
|
|
|
+
|
|
|
|
+ String credentialScope = credentialScopeStr(region, Constant.SERVICE, reqDate);
|
|
|
|
+ String canonicalRequestHash = canonicalRequestHashStr(requestMethod, methodName, payload, queryString,
|
|
|
|
+ canonicalHeaderstr);
|
|
|
|
+ String stringToSign = createStrToSignStr(credentialScope, canonicalRequestHash, reqDateTime);
|
|
|
|
+ byte[] kSigning = calculateKsigning(Constant.IAMUSERSECRET, region, Constant.SERVICE, reqDate);
|
|
|
|
+ byte[] sign = CommonUtil.hmacSha256(stringToSign, kSigning);
|
|
|
|
+
|
|
|
|
+ String credential = "Credential=" + Constant.IAMUSERKEY + "/" + credentialScope;
|
|
|
|
+ String signedHeaders = "SignedHeaders=" + Constant.SIGNEDHEADER;
|
|
|
|
+ String signature = "Signature=" + CommonUtil.byte2hex(sign);
|
|
|
|
+ String[] authorizationHeader = {credential, signedHeaders, signature};
|
|
|
|
+ String authorization = Constant.ALGORITHM + " " + StringUtils.join(Arrays.asList(authorizationHeader), ", ");
|
|
|
|
+ canonicalHeaders.put("authorization", authorization);
|
|
|
|
+
|
|
|
|
+ return canonicalHeaders;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 计算 kSigning
|
|
|
|
+ *
|
|
|
|
+ * @param iamUserSecret
|
|
|
|
+ * @param region 区域 us-east-1
|
|
|
|
+ * @param service 服务 例如:execute-api
|
|
|
|
+ * @return
|
|
|
|
+ * @throws UnsupportedEncodingException
|
|
|
|
+ * @throws IllegalStateException
|
|
|
|
+ * @throws NoSuchAlgorithmException
|
|
|
|
+ * @throws InvalidKeyException
|
|
|
|
+ */
|
|
|
|
+ private static byte[] calculateKsigning(String iamUserSecret, String region, String service, String reqDate) throws InvalidKeyException, NoSuchAlgorithmException, IllegalStateException, UnsupportedEncodingException {
|
|
|
|
+ String kSecret = "AWS4" + iamUserSecret;
|
|
|
|
+ byte[] kDate = CommonUtil.hmacSha256(reqDate, kSecret.getBytes());
|
|
|
|
+ byte[] kRegion = CommonUtil.hmacSha256(region, kDate);
|
|
|
|
+ byte[] kService = CommonUtil.hmacSha256(service, kRegion);
|
|
|
|
+ byte[] kSigning = CommonUtil.hmacSha256(Constant.TERMINATIONSTRING, kService);
|
|
|
|
+ return kSigning;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 获取请求头
|
|
|
|
+ *
|
|
|
|
+ * @param host 请求主机地址, 例如: sellingpartnerapi-na.amazon.com, 根据区域不同地址不同
|
|
|
|
+ * @param accessToken 用户授权店铺后,短令牌token信息
|
|
|
|
+ * @param reqDateTime 请求时间,格式,例如: "yyyyMMdd'T'HHmmss'Z'"
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ private static Map<String, String> canonicalHeaders(String host, String accessToken, String reqDateTime) {
|
|
|
|
+ Map<String, String> map = new TreeMap<String, String>();
|
|
|
|
+ map.put("content-type", Constant.CONTENT_TYPE);
|
|
|
|
+ map.put("host", host);
|
|
|
|
+ map.put("user-agent", Constant.USER_AGENT);
|
|
|
|
+ map.put("x-amz-access-token", accessToken);
|
|
|
|
+ map.put("x-amz-date", reqDateTime);
|
|
|
|
+ return map;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 计算请求Hash
|
|
|
|
+ *
|
|
|
|
+ * @param requestMethod 请求方式, 例如:GET, POST
|
|
|
|
+ * @param canonicalURI 请求URI 地址,例如:/orders/v0/orders
|
|
|
|
+ * @param canonicalPayload 提交参数, 当为GET请求 参数留空, POST请求 拼为: abc=x1&efg=x2, 或json 格式 {"abc":"x1","efg":"x2"}
|
|
|
|
+ * @param canonicalQueryString 提交参数,当为GET请求,有传参则填写在这里,例如: abc=x1&efg=x2
|
|
|
|
+ * @param canonicalHeaderStr
|
|
|
|
+ * @return
|
|
|
|
+ * @throws UnsupportedEncodingException
|
|
|
|
+ * @throws NoSuchAlgorithmException
|
|
|
|
+ */
|
|
|
|
+ private static String canonicalRequestHashStr(String requestMethod, String canonicalURI, String canonicalPayload,
|
|
|
|
+ String canonicalQueryString, String canonicalHeaderStr) throws NoSuchAlgorithmException, UnsupportedEncodingException {
|
|
|
|
+ String[] canonicalRequest = {requestMethod, canonicalURI, canonicalQueryString, canonicalHeaderStr + "\n",
|
|
|
|
+ Constant.SIGNEDHEADER, CommonUtil.sha256(canonicalPayload)};
|
|
|
|
+ String canonicalRequeststr = StringUtils.join(Arrays.asList(canonicalRequest), "\n");
|
|
|
|
+ return CommonUtil.sha256(canonicalRequeststr);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 计算Scope
|
|
|
|
+ *
|
|
|
|
+ * @param region 区域 us-east-1
|
|
|
|
+ * @param service 服务 例如:execute-api
|
|
|
|
+ * @param reqDate
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ private static String credentialScopeStr(String region, String service, String reqDate) {
|
|
|
|
+ String[] credentialScope = {reqDate, region, service, Constant.TERMINATIONSTRING};
|
|
|
|
+ return StringUtils.join(Arrays.asList(credentialScope), "/");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 计算 stringtoSing
|
|
|
|
+ *
|
|
|
|
+ * @param credentialScopeStr 前一个方法计算出来的字符串
|
|
|
|
+ * @param requestHashedCanonicalRequest
|
|
|
|
+ * @param reqDateTime 请求时间,格式,例如: "yyyyMMdd'T'HHmmss'Z'"
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ private static String createStrToSignStr(String credentialScopeStr, String requestHashedCanonicalRequest,
|
|
|
|
+ String reqDateTime) {
|
|
|
|
+ String[] stringToSign = {Constant.ALGORITHM, reqDateTime, credentialScopeStr, requestHashedCanonicalRequest};
|
|
|
|
+ String stringToSignStr = StringUtils.join(Arrays.asList(stringToSign), "\n");
|
|
|
|
+ return stringToSignStr;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+}
|