java内网环境使用代理访问阿里云api
最近在开发一个app推送功能,我们选用了阿里云和极光的推送接口,在本地有网络的情况都推送成功了,用的阿里云的java_sdk。但是发布测试环境的时候,却推送失败了,是因为服务器属于内网环境,不可直接访问外网接口,所以需要通过代理服务器正向代理访问。
阿里云推送服务文档 https://help.aliyun.com/document_detail/48088.html.
-
本人通过阿里云官方文档多次测试无果!
-
所以准备不通过sdk的方式,而是通过http直接访问阿里云的open_api
在翻读阿里云java_sdk的源代码后 找到了用于加密和签名的工具类 -
com.aliyuncs.utils.ParameterHelper.class 时间工具类 获取东八区
-
com.aliyuncs.auth.ShaHmac1.class Hmac-SHA1参数签名工具
-
com.aliyuncs.auth.RpcSignatureComposer.class 重写此方法加密参数获取Signature
maven
<!--阿里云推送依赖-->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-push</artifactId>
<version>3.10.0</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>3.2.8</version>
</dependency>
封装推送Open_Api
@Value("${xxx.xxx.http.proxyHost:10.1.1.2}")
private String aliProxyHost; //代理服务器地址
@Value("${xxx.xxx.http.port:8888}") //代理服务器端口
private int aliPort;
private static final String ALI_URL = "http://cloudpush.aliyuncs.com";
/**
* @param queries 推送必传参数,不同系统参数不同
* @return
*/
private PushResultDTO pushNotice(Map<String, String> queries) {
PushResultDTO pushResultDTO = new PushResultDTO();
String iso8601Time = ParameterHelper.getISO8601Time(new Date());
queries.put("Format", "XML");
queries.put("RegionId", regionId);
queries.put("Version", "2016-08-01");
queries.put("AccessKeyId", accessKeyId);
queries.put("SignatureMethod", "HMAC-SHA1");
queries.put("SignatureNonce", String.valueOf(System.currentTimeMillis()));
queries.put("SignatureVersion", "1.0");
queries.put("Timestamp", iso8601Time);
String StringToSign = composeStringToSign(MethodType.POST, queries);
System.out.println(StringToSign);
ShaHmac1 shaHmac1 = new ShaHmac1();
String secret = "";
try {
secret = shaHmac1.signString(StringToSign, accessKeySecret + "&");
System.out.println(secret);
} catch (InvalidKeyException e) {
e.printStackTrace();
}
queries.put("Signature", secret);
log.info("开始代理请求 >>>>>>>>>>>>>>>>>>>");
HttpHost proxy = new HttpHost(aliProxyHost, aliPort);
String result = httpPostWithParam(ALI_URL, queries, proxy);
log.info("代理结束{}", result);
pushResultDTO.setPushMsg(result);
pushResultDTO.setPushFlag(true);
return pushResultDTO;
}
/**
* 获取签名
* @param method 请求方式
* @param queries 请求参数
* @return
*/
private static String composeStringToSign(MethodType method, Map<String, String> queries) {
String[] sortedKeys = (String[]) queries.keySet().toArray(new String[0]);
Arrays.sort(sortedKeys);
StringBuilder canonicalizedQueryString = new StringBuilder();
try {
String[] arr$ = sortedKeys;
int len$ = sortedKeys.length;
for (int i$ = 0; i$ < len$; ++i$) {
String key = arr$[i$];
canonicalizedQueryString.append("&").append(AcsURLEncoder.percentEncode(key)).append("=").append(AcsURLEncoder.percentEncode((String) queries.get(key)));
}
StringBuilder stringToSign = new StringBuilder();
stringToSign.append(method.toString());
stringToSign.append("&");
stringToSign.append(AcsURLEncoder.percentEncode("/"));
stringToSign.append("&");
stringToSign.append(AcsURLEncoder.percentEncode(canonicalizedQueryString.toString().substring(1)));
return stringToSign.toString();
} catch (UnsupportedEncodingException var13) {
throw new RuntimeException("UTF-8 encoding is not supported.");
}
}
public static String httpPostWithParam(String url, Map<String, String> map, HttpHost proxy) {
long startTime = System.currentTimeMillis();
String returnValue = "";
CloseableHttpClient httpClient = HttpClients.createDefault();
ResponseHandler<String> responseHandler = new BasicResponseHandler();
try {
//第一步:创建HttpClient对象
httpClient = HttpClients.createDefault();
//第二步:创建httpPost对象
HttpPost httpPost = new HttpPost(url);
RequestConfig requestConfig = RequestConfig.custom()
.setProxy(proxy)
.build();
httpPost.setConfig(requestConfig);
//第三步:给httpPost设置form-data格式的参数
List params = new ArrayList();
for (String key : map.keySet()) {
params.add(new BasicNameValuePair(key, map.get(key)));
}
HttpEntity httpEntity = new UrlEncodedFormEntity(params, "UTF-8");
httpPost.setEntity(httpEntity);
//第四步:发送HttpPost请求,获取返回值
returnValue = httpClient.execute(httpPost, responseHandler); //调接口获取返回值时,必须用此方法
} catch (Exception e) {
log.warn("异常:", e);
} finally {
try {
httpClient.close();
} catch (IOException e) {
// TODO Auto-generated catch block
log.warn("异常:", e);
}
long endTime = System.currentTimeMillis();
log.debug("http post url: " + url + ",时间秒: " + (double) (endTime - startTime) / 1000 + ",请求参数: "
+ map + ",返回参数: " + returnValue);
}
//第五步:处理返回值
return returnValue;
}
推送到ios
/**
*调用自己封装的方法
*/
public PushResultDTO pushNoticeToSingleIOS(PushUser pushUser, UserDevice userDevice) {
PushResultDTO pushResultDTO = new PushResultDTO();
Map<String, String> queries = new LinkedHashMap<>();
queries.put("AppKey", appKeyIOS);
queries.put("ApnsEnv", apnsEnv);
queries.put("Target", TARGET_DEVICE);
queries.put("TargetValue", userDevice.getDeviceIdAli());
String title = pushUser.getTitle();
String body = pushUser.getContent();
queries.put("Title", title);
queries.put("Body", body);
queries.put("Action", ActionEnum.IOS.getDeviceMpush());
logger.info("推送开始,ios调用阿里云接口");
PushResultDTO pushResultDTO1 = pushNotice(queries);
logger.info("推送结束,ios调用阿里云成功");
return pushResultDTO1 ;
}