|
@@ -1,12 +1,20 @@
|
|
|
package com.chelvc.framework.jpush;
|
|
|
|
|
|
+import java.security.GeneralSecurityException;
|
|
|
+import java.security.KeyFactory;
|
|
|
+import java.security.NoSuchAlgorithmException;
|
|
|
+import java.security.PrivateKey;
|
|
|
+import java.security.spec.InvalidKeySpecException;
|
|
|
+import java.security.spec.PKCS8EncodedKeySpec;
|
|
|
import java.util.Arrays;
|
|
|
+import java.util.Base64;
|
|
|
import java.util.Collection;
|
|
|
import java.util.Collections;
|
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
|
import java.util.Objects;
|
|
|
import java.util.stream.Collectors;
|
|
|
+import javax.crypto.Cipher;
|
|
|
|
|
|
import cn.jiguang.common.ServiceHelper;
|
|
|
import cn.jiguang.common.resp.APIRequestException;
|
|
@@ -33,6 +41,7 @@ import com.chelvc.framework.common.util.ObjectUtils;
|
|
|
import com.chelvc.framework.common.util.StringUtils;
|
|
|
import com.chelvc.framework.jpush.config.JPushProperties;
|
|
|
import com.chelvc.framework.jpush.context.JPushContextHolder;
|
|
|
+import com.google.common.collect.ImmutableMap;
|
|
|
import lombok.Getter;
|
|
|
import lombok.NonNull;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
@@ -49,6 +58,11 @@ import org.springframework.http.MediaType;
|
|
|
*/
|
|
|
@Slf4j
|
|
|
public class DefaultJPushHandler implements JPushHandler {
|
|
|
+ /**
|
|
|
+ * 极光认证接口地址
|
|
|
+ */
|
|
|
+ private static final String CODE2MOBILE_URL = "https://api.verification.jpush.cn/v1/web/loginTokenVerify";
|
|
|
+
|
|
|
/**
|
|
|
* 获取消息地址
|
|
|
*/
|
|
@@ -75,6 +89,7 @@ public class DefaultJPushHandler implements JPushHandler {
|
|
|
private final String appid;
|
|
|
@Getter
|
|
|
private final String authorization;
|
|
|
+ private final PrivateKey key;
|
|
|
private final JPushClient pushClient;
|
|
|
private final JMessageClient messageClient;
|
|
|
|
|
@@ -84,6 +99,17 @@ public class DefaultJPushHandler implements JPushHandler {
|
|
|
this.messageClient = messageClient;
|
|
|
this.appid = properties.getAppid();
|
|
|
this.authorization = ServiceHelper.getBasicAuthorization(properties.getAppid(), properties.getSecret());
|
|
|
+
|
|
|
+ // 初始化私钥
|
|
|
+ this.key = StringUtils.ifEmpty(properties.getKey(), secret -> {
|
|
|
+ byte[] bytes = Base64.getDecoder().decode(secret);
|
|
|
+ PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(bytes);
|
|
|
+ try {
|
|
|
+ return KeyFactory.getInstance("RSA").generatePrivate(spec);
|
|
|
+ } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
|
|
|
+ throw new RuntimeException(e);
|
|
|
+ }
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -98,15 +124,62 @@ public class DefaultJPushHandler implements JPushHandler {
|
|
|
headers.setContentType(MediaType.APPLICATION_JSON);
|
|
|
HttpEntity<?> entity = new HttpEntity<>(headers);
|
|
|
try {
|
|
|
- return RestContextHolder.execute(rest -> rest.exchange(
|
|
|
- url, HttpMethod.GET, entity, ChatMessage.class
|
|
|
- ).getBody());
|
|
|
+ return RestContextHolder.exchange(url, HttpMethod.GET, entity, ChatMessage.class);
|
|
|
} catch (Exception e) {
|
|
|
log.warn("JPush message get failed: {}, {}", url, e.getMessage());
|
|
|
return null;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 获取消息投递结果
|
|
|
+ *
|
|
|
+ * @param ids 消息ID(多个ID之间使用","号隔开,最多最多支持 100 个消息ID)
|
|
|
+ * @return 投递结果列表
|
|
|
+ */
|
|
|
+ private List<ReceivedsResult.Received> getDeliveries(String ids) {
|
|
|
+ if (StringUtils.isEmpty(ids)) {
|
|
|
+ return Collections.emptyList();
|
|
|
+ }
|
|
|
+ ReceivedsResult result;
|
|
|
+ try {
|
|
|
+ result = this.pushClient.getReceivedsDetail(ids);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("JPush delivery get failed: {}", e.getMessage());
|
|
|
+ return Collections.emptyList();
|
|
|
+ }
|
|
|
+ return ObjectUtils.ifNull(result.received_list, Collections::emptyList);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String code2mobile(@NonNull String token) {
|
|
|
+ // 根据令牌获取手机号
|
|
|
+ Map<String, String> body = ImmutableMap.of("loginToken", token);
|
|
|
+ HttpHeaders headers = new HttpHeaders();
|
|
|
+ headers.add("Authorization", this.authorization);
|
|
|
+ headers.setContentType(MediaType.APPLICATION_JSON);
|
|
|
+ HttpEntity<?> entity = new HttpEntity<>(body, headers);
|
|
|
+ Map<?, ?> response = RestContextHolder.exchange(CODE2MOBILE_URL, HttpMethod.POST, entity, Map.class);
|
|
|
+ Integer code = response == null ? null : (Integer) response.get("code");
|
|
|
+ if (code == null) {
|
|
|
+ throw new RuntimeException("Invalid jpush response");
|
|
|
+ } else if (code != 8000) {
|
|
|
+ throw new RuntimeException(code + ", " + response.get("content"));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 解码手机号
|
|
|
+ String mobile = (String) response.get("phone");
|
|
|
+ byte[] bytes = Base64.getDecoder().decode(mobile);
|
|
|
+ PrivateKey key = Objects.requireNonNull(this.key, "JPush key not specified");
|
|
|
+ try {
|
|
|
+ Cipher cipher = Cipher.getInstance("RSA");
|
|
|
+ cipher.init(Cipher.DECRYPT_MODE, key);
|
|
|
+ return new String(cipher.doFinal(bytes));
|
|
|
+ } catch (GeneralSecurityException e) {
|
|
|
+ throw new RuntimeException(e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
@Override
|
|
|
public boolean register(@NonNull RegisterInfo... registrations) {
|
|
|
if (registrations.length == 0) {
|
|
@@ -221,26 +294,6 @@ public class DefaultJPushHandler implements JPushHandler {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * 获取消息投递结果
|
|
|
- *
|
|
|
- * @param ids 消息ID(多个ID之间使用","号隔开,最多最多支持 100 个消息ID)
|
|
|
- * @return 投递结果列表
|
|
|
- */
|
|
|
- private List<ReceivedsResult.Received> getDeliveries(String ids) {
|
|
|
- if (StringUtils.isEmpty(ids)) {
|
|
|
- return Collections.emptyList();
|
|
|
- }
|
|
|
- ReceivedsResult result;
|
|
|
- try {
|
|
|
- result = this.pushClient.getReceivedsDetail(ids);
|
|
|
- } catch (Exception e) {
|
|
|
- log.warn("JPush delivery get failed: {}", e.getMessage());
|
|
|
- return Collections.emptyList();
|
|
|
- }
|
|
|
- return ObjectUtils.ifNull(result.received_list, Collections::emptyList);
|
|
|
- }
|
|
|
-
|
|
|
@Override
|
|
|
public ReceivedsResult.Received getDelivery(@NonNull Long id) {
|
|
|
List<ReceivedsResult.Received> deliveries = this.getDeliveries(String.valueOf(id));
|