mirror of
https://gitee.com/dromara/sms4j.git
synced 2025-12-07 17:38:38 +08:00
1.修改uni-sms短信实现,去除SDK依赖
2.修复回调bug,该bug导致回调未在主线程中执行 3.**暂时注释腾讯云短信JDK不兼容部分等待修复**
This commit is contained in:
parent
d62a4af123
commit
f5625f2c5c
2
.gitignore
vendored
2
.gitignore
vendored
@ -35,4 +35,4 @@ build/
|
|||||||
### Temp
|
### Temp
|
||||||
.flattened-pom.xml
|
.flattened-pom.xml
|
||||||
**/.flattened-pom.xml
|
**/.flattened-pom.xml
|
||||||
/.fastRequest/
|
/.fastRequest/**
|
||||||
|
|||||||
22
pom.xml
22
pom.xml
@ -47,7 +47,7 @@
|
|||||||
</scm>
|
</scm>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<spring.boot.version>2.7.10</spring.boot.version>
|
<spring.boot.version>2.7.11</spring.boot.version>
|
||||||
<revision>2.0.1</revision>
|
<revision>2.0.1</revision>
|
||||||
<aliyun.version>2.0.23</aliyun.version>
|
<aliyun.version>2.0.23</aliyun.version>
|
||||||
<tencent.version>3.1.622</tencent.version>
|
<tencent.version>3.1.622</tencent.version>
|
||||||
@ -89,6 +89,7 @@
|
|||||||
<version>${revision}</version>
|
<version>${revision}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!--核心模块-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.dromara.sms4j</groupId>
|
<groupId>org.dromara.sms4j</groupId>
|
||||||
<artifactId>sms4j-core</artifactId>
|
<artifactId>sms4j-core</artifactId>
|
||||||
@ -145,19 +146,6 @@
|
|||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!--合一短信依赖-->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.apistd.uni</groupId>
|
|
||||||
<artifactId>uni-sdk</artifactId>
|
|
||||||
<version>${unisms.version}</version>
|
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>com.squareup.okhttp3</groupId>
|
|
||||||
<artifactId>okhttp</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- 京东云短信依赖 -->
|
<!-- 京东云短信依赖 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.jdcloud.sdk</groupId>
|
<groupId>com.jdcloud.sdk</groupId>
|
||||||
@ -165,12 +153,6 @@
|
|||||||
<version>${jdcloud.version}</version>
|
<version>${jdcloud.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- okhttp依赖,防止出现java.lang.NoSuchFieldError: Companion异常-->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.squareup.okhttp3</groupId>
|
|
||||||
<artifactId>okhttp</artifactId>
|
|
||||||
<version>${okhttp.version}</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,5 @@
|
|||||||
|
/**
|
||||||
|
* 公共API
|
||||||
|
* @author :Wind
|
||||||
|
*/
|
||||||
|
package org.dromara.sms4j.api;
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
/**
|
||||||
|
* Spring Boot自动装配配置
|
||||||
|
* @author :Wind
|
||||||
|
*/
|
||||||
|
package org.dromara.sms4j.autoimmit;
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
/**
|
||||||
|
* 公共模块
|
||||||
|
* @author :Wind
|
||||||
|
*/
|
||||||
|
package org.dromara.sms4j.comm;
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
/**
|
||||||
|
* 核心模块
|
||||||
|
* @author :Wind
|
||||||
|
*/
|
||||||
|
package org.dromara.sms4j.core;
|
||||||
@ -20,12 +20,6 @@
|
|||||||
<artifactId>sms4j-api</artifactId>
|
<artifactId>sms4j-api</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- 合一短信依赖 -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.apistd.uni</groupId>
|
|
||||||
<artifactId>uni-sdk</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- 京东云短信依赖 -->
|
<!-- 京东云短信依赖 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.jdcloud.sdk</groupId>
|
<groupId>com.jdcloud.sdk</groupId>
|
||||||
|
|||||||
@ -17,6 +17,7 @@ import org.dromara.sms4j.comm.factory.BeanFactory;
|
|||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -111,10 +112,8 @@ public class AlibabaSmsImpl implements SmsBlend {
|
|||||||
@Override
|
@Override
|
||||||
@Restricted
|
@Restricted
|
||||||
public void sendMessageAsync(String phone, String message, CallBack callBack) {
|
public void sendMessageAsync(String phone, String message, CallBack callBack) {
|
||||||
pool.execute(() -> {
|
CompletableFuture<SmsResponse> smsResponseCompletableFuture = CompletableFuture.supplyAsync(() -> sendMessage(phone, message), pool);
|
||||||
SmsResponse smsResponse = sendMessage(phone, message);
|
smsResponseCompletableFuture.thenAcceptAsync(callBack::callBack);
|
||||||
callBack.callBack(smsResponse);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -128,10 +127,8 @@ public class AlibabaSmsImpl implements SmsBlend {
|
|||||||
@Override
|
@Override
|
||||||
@Restricted
|
@Restricted
|
||||||
public void sendMessageAsync(String phone, String templateId, LinkedHashMap<String, String> messages, CallBack callBack) {
|
public void sendMessageAsync(String phone, String templateId, LinkedHashMap<String, String> messages, CallBack callBack) {
|
||||||
pool.execute(() -> {
|
CompletableFuture<SmsResponse> smsResponseCompletableFuture = CompletableFuture.supplyAsync(() -> sendMessage(phone,templateId, messages), pool);
|
||||||
SmsResponse smsResponse = sendMessage(phone, templateId, messages);
|
smsResponseCompletableFuture.thenAcceptAsync(callBack::callBack);
|
||||||
callBack.callBack(smsResponse);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import org.dromara.sms4j.comm.annotation.Restricted;
|
|||||||
import org.dromara.sms4j.comm.delayedTime.DelayedTime;
|
import org.dromara.sms4j.comm.delayedTime.DelayedTime;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -75,10 +76,8 @@ public class CloopenSmsImpl implements SmsBlend {
|
|||||||
@Override
|
@Override
|
||||||
@Restricted
|
@Restricted
|
||||||
public void sendMessageAsync(String phone, String message, CallBack callBack) {
|
public void sendMessageAsync(String phone, String message, CallBack callBack) {
|
||||||
pool.execute(() -> {
|
CompletableFuture<SmsResponse> smsResponseCompletableFuture = CompletableFuture.supplyAsync(() -> sendMessage(phone, message), pool);
|
||||||
SmsResponse smsResponse = sendMessage(phone, message);
|
smsResponseCompletableFuture.thenAcceptAsync(callBack::callBack);
|
||||||
callBack.callBack(smsResponse);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -90,10 +89,8 @@ public class CloopenSmsImpl implements SmsBlend {
|
|||||||
@Override
|
@Override
|
||||||
@Restricted
|
@Restricted
|
||||||
public void sendMessageAsync(String phone, String templateId, LinkedHashMap<String, String> messages, CallBack callBack) {
|
public void sendMessageAsync(String phone, String templateId, LinkedHashMap<String, String> messages, CallBack callBack) {
|
||||||
pool.execute(() -> {
|
CompletableFuture<SmsResponse> smsResponseCompletableFuture = CompletableFuture.supplyAsync(() -> sendMessage(phone,templateId, messages), pool);
|
||||||
SmsResponse smsResponse = sendMessage(phone, templateId, messages);
|
smsResponseCompletableFuture.thenAcceptAsync(callBack::callBack);
|
||||||
callBack.callBack(smsResponse);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import org.dromara.sms4j.comm.exception.SmsBlendException;
|
|||||||
import org.dromara.sms4j.comm.factory.BeanFactory;
|
import org.dromara.sms4j.comm.factory.BeanFactory;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
@ -89,10 +90,8 @@ public class EmaySmsImpl implements SmsBlend {
|
|||||||
@Override
|
@Override
|
||||||
@Restricted
|
@Restricted
|
||||||
public void sendMessageAsync(String phone, String message, CallBack callBack) {
|
public void sendMessageAsync(String phone, String message, CallBack callBack) {
|
||||||
pool.execute(() -> {
|
CompletableFuture<SmsResponse> smsResponseCompletableFuture = CompletableFuture.supplyAsync(() -> sendMessage(phone, message), pool);
|
||||||
SmsResponse smsResponse = sendMessage(phone, message);
|
smsResponseCompletableFuture.thenAcceptAsync(callBack::callBack);
|
||||||
callBack.callBack(smsResponse);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -104,10 +103,8 @@ public class EmaySmsImpl implements SmsBlend {
|
|||||||
@Override
|
@Override
|
||||||
@Restricted
|
@Restricted
|
||||||
public void sendMessageAsync(String phone, String templateId, LinkedHashMap<String, String> messages, CallBack callBack) {
|
public void sendMessageAsync(String phone, String templateId, LinkedHashMap<String, String> messages, CallBack callBack) {
|
||||||
pool.execute(() -> {
|
CompletableFuture<SmsResponse> smsResponseCompletableFuture = CompletableFuture.supplyAsync(() -> sendMessage(phone, templateId, messages), pool);
|
||||||
SmsResponse smsResponse = sendMessage(phone, templateId, messages);
|
smsResponseCompletableFuture.thenAcceptAsync(callBack::callBack);
|
||||||
callBack.callBack(smsResponse);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -15,6 +15,7 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import org.dromara.sms4j.api.SmsBlend;
|
import org.dromara.sms4j.api.SmsBlend;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
import static org.dromara.sms4j.huawei.utils.HuaweiBuilder.listToString;
|
import static org.dromara.sms4j.huawei.utils.HuaweiBuilder.listToString;
|
||||||
@ -94,10 +95,8 @@ public class HuaweiSmsImpl implements SmsBlend {
|
|||||||
@Override
|
@Override
|
||||||
@Restricted
|
@Restricted
|
||||||
public void sendMessageAsync(String phone, String message, CallBack callBack) {
|
public void sendMessageAsync(String phone, String message, CallBack callBack) {
|
||||||
pool.execute(() -> {
|
CompletableFuture<SmsResponse> smsResponseCompletableFuture = CompletableFuture.supplyAsync(() -> sendMessage(phone, message), pool);
|
||||||
SmsResponse smsResponse = sendMessage(phone, message);
|
smsResponseCompletableFuture.thenAcceptAsync(callBack::callBack);
|
||||||
callBack.callBack(smsResponse);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -109,10 +108,8 @@ public class HuaweiSmsImpl implements SmsBlend {
|
|||||||
@Override
|
@Override
|
||||||
@Restricted
|
@Restricted
|
||||||
public void sendMessageAsync(String phone, String templateId, LinkedHashMap<String, String> messages, CallBack callBack) {
|
public void sendMessageAsync(String phone, String templateId, LinkedHashMap<String, String> messages, CallBack callBack) {
|
||||||
pool.execute(() -> {
|
CompletableFuture<SmsResponse> smsResponseCompletableFuture = CompletableFuture.supplyAsync(() -> sendMessage(phone, templateId, messages), pool);
|
||||||
SmsResponse smsResponse = sendMessage(phone, templateId, messages);
|
smsResponseCompletableFuture.thenAcceptAsync(callBack::callBack);
|
||||||
callBack.callBack(smsResponse);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -17,6 +17,7 @@ import java.util.Collections;
|
|||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@ -87,10 +88,8 @@ public class JdCloudSmsImpl implements SmsBlend {
|
|||||||
@Override
|
@Override
|
||||||
@Restricted
|
@Restricted
|
||||||
public void sendMessageAsync(String phone, String message, CallBack callBack) {
|
public void sendMessageAsync(String phone, String message, CallBack callBack) {
|
||||||
pool.execute(() -> {
|
CompletableFuture<SmsResponse> smsResponseCompletableFuture = CompletableFuture.supplyAsync(() -> sendMessage(phone, message), pool);
|
||||||
SmsResponse smsResponse = sendMessage(phone, message);
|
smsResponseCompletableFuture.thenAcceptAsync(callBack::callBack);
|
||||||
callBack.callBack(smsResponse);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -102,10 +101,8 @@ public class JdCloudSmsImpl implements SmsBlend {
|
|||||||
@Override
|
@Override
|
||||||
@Restricted
|
@Restricted
|
||||||
public void sendMessageAsync(String phone, String templateId, LinkedHashMap<String, String> messages, CallBack callBack) {
|
public void sendMessageAsync(String phone, String templateId, LinkedHashMap<String, String> messages, CallBack callBack) {
|
||||||
pool.execute(() -> {
|
CompletableFuture<SmsResponse> smsResponseCompletableFuture = CompletableFuture.supplyAsync(() -> sendMessage(phone, templateId, messages), pool);
|
||||||
SmsResponse smsResponse = sendMessage(phone, templateId, messages);
|
smsResponseCompletableFuture.thenAcceptAsync(callBack::callBack);
|
||||||
callBack.callBack(smsResponse);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -0,0 +1,5 @@
|
|||||||
|
/**
|
||||||
|
* 厂商模块
|
||||||
|
* @author :Wind
|
||||||
|
*/
|
||||||
|
package org.dromara.sms4j;
|
||||||
@ -16,6 +16,7 @@ import org.dromara.sms4j.tencent.config.TencentConfig;
|
|||||||
import org.dromara.sms4j.tencent.utils.TencentUtils;
|
import org.dromara.sms4j.tencent.utils.TencentUtils;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@ -119,10 +120,8 @@ public class TencentSmsImpl implements SmsBlend {
|
|||||||
@Override
|
@Override
|
||||||
@Restricted
|
@Restricted
|
||||||
public void sendMessageAsync(String phone, String message, CallBack callBack) {
|
public void sendMessageAsync(String phone, String message, CallBack callBack) {
|
||||||
pool.execute(() -> {
|
CompletableFuture<SmsResponse> smsResponseCompletableFuture = CompletableFuture.supplyAsync(() -> sendMessage(phone, message), pool);
|
||||||
SmsResponse smsResponse = sendMessage(phone, message);
|
smsResponseCompletableFuture.thenAcceptAsync(callBack::callBack);
|
||||||
callBack.callBack(smsResponse);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -136,10 +135,8 @@ public class TencentSmsImpl implements SmsBlend {
|
|||||||
@Override
|
@Override
|
||||||
@Restricted
|
@Restricted
|
||||||
public void sendMessageAsync(String phone, String templateId, LinkedHashMap<String, String> messages, CallBack callBack) {
|
public void sendMessageAsync(String phone, String templateId, LinkedHashMap<String, String> messages, CallBack callBack) {
|
||||||
pool.execute(() -> {
|
CompletableFuture<SmsResponse> smsResponseCompletableFuture = CompletableFuture.supplyAsync(() -> sendMessage(phone, templateId, messages), pool);
|
||||||
SmsResponse smsResponse = sendMessage(phone, templateId, messages);
|
smsResponseCompletableFuture.thenAcceptAsync(callBack::callBack);
|
||||||
callBack.callBack(smsResponse);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import org.dromara.sms4j.tencent.config.TencentConfig;
|
|||||||
|
|
||||||
import javax.crypto.Mac;
|
import javax.crypto.Mac;
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
import javax.xml.bind.DatatypeConverter;
|
//import javax.xml.bind.DatatypeConverter;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
@ -44,7 +44,8 @@ public class TencentUtils {
|
|||||||
private static String sha256Hex(String s) throws Exception {
|
private static String sha256Hex(String s) throws Exception {
|
||||||
MessageDigest md = MessageDigest.getInstance("SHA-256");
|
MessageDigest md = MessageDigest.getInstance("SHA-256");
|
||||||
byte[] d = md.digest(s.getBytes(StandardCharsets.UTF_8));
|
byte[] d = md.digest(s.getBytes(StandardCharsets.UTF_8));
|
||||||
return DatatypeConverter.printHexBinary(d).toLowerCase();
|
// return DatatypeConverter.printHexBinary(d).toLowerCase();
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -85,10 +86,10 @@ public class TencentUtils {
|
|||||||
byte[] secretDate = hmac256(("TC3" + tencentConfig.getAccessKeySecret()).getBytes(StandardCharsets.UTF_8), date);
|
byte[] secretDate = hmac256(("TC3" + tencentConfig.getAccessKeySecret()).getBytes(StandardCharsets.UTF_8), date);
|
||||||
byte[] secretService = hmac256(secretDate, tencentConfig.getService());
|
byte[] secretService = hmac256(secretDate, tencentConfig.getService());
|
||||||
byte[] secretSigning = hmac256(secretService, "tc3_request");
|
byte[] secretSigning = hmac256(secretService, "tc3_request");
|
||||||
String signature = DatatypeConverter.printHexBinary(hmac256(secretSigning, stringToSign)).toLowerCase();
|
// String signature = DatatypeConverter.printHexBinary(hmac256(secretSigning, stringToSign)).toLowerCase();
|
||||||
// ************* 步骤 4:拼接 Authorization *************
|
// ************* 步骤 4:拼接 Authorization *************
|
||||||
return ALGORITHM + " " + "Credential=" + tencentConfig.getAccessKeyId() + "/" + credentialScope + ", "
|
return ALGORITHM + " " + "Credential=" + tencentConfig.getAccessKeyId() + "/" + credentialScope + ", ";
|
||||||
+ "SignedHeaders=" + signedHeaders + ", " + "Signature=" + signature;
|
// + "SignedHeaders=" + signedHeaders + ", " + "Signature=" + signature;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
package org.dromara.sms4j.unisms.config;
|
package org.dromara.sms4j.unisms.config;
|
||||||
|
|
||||||
import com.apistd.uni.Uni;
|
|
||||||
import org.dromara.sms4j.comm.factory.BeanFactory;
|
import org.dromara.sms4j.comm.factory.BeanFactory;
|
||||||
|
import org.dromara.sms4j.unisms.core.Uni;
|
||||||
import org.dromara.sms4j.unisms.service.UniSmsImpl;
|
import org.dromara.sms4j.unisms.service.UniSmsImpl;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -0,0 +1,93 @@
|
|||||||
|
package org.dromara.sms4j.unisms.core;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化统一环境的单例类.
|
||||||
|
*/
|
||||||
|
public class Uni {
|
||||||
|
/** 模仿SDK版本*/
|
||||||
|
public static final String VERSION = "0.0.4";
|
||||||
|
|
||||||
|
public static String signingAlgorithm = "hmac-sha256";
|
||||||
|
public static String endpoint = System.getenv().getOrDefault("UNI_ENDPOINT", "https://uni.apistd.com");
|
||||||
|
public static String accessKeyId = System.getenv("UNI_ACCESS_KEY_ID");
|
||||||
|
|
||||||
|
private static String accessKeySecret = System.getenv("UNI_ACCESS_KEY_SECRET");
|
||||||
|
private static volatile UniClient client;
|
||||||
|
|
||||||
|
private Uni() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化Uni环境(简单验证模式).
|
||||||
|
*
|
||||||
|
* @param accessKeyId access key ID
|
||||||
|
* @author :Wind
|
||||||
|
*/
|
||||||
|
public static void init(final String accessKeyId) {
|
||||||
|
Uni.setAccessKeyId(accessKeyId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化Uni环境(HMAC验证模式).
|
||||||
|
*
|
||||||
|
* @param accessKeyId access key ID
|
||||||
|
* @param accessKeySecret access key secret
|
||||||
|
* @author :Wind
|
||||||
|
*/
|
||||||
|
public static void init(final String accessKeyId, final String accessKeySecret) {
|
||||||
|
Uni.setAccessKeyId(accessKeyId);
|
||||||
|
Uni.setAccessKeySecret(accessKeySecret);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void setAccessKeyId(final String accessKeyId) {
|
||||||
|
Uni.accessKeyId = accessKeyId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void setAccessKeySecret(final String accessKeySecret) {
|
||||||
|
Uni.accessKeySecret = accessKeySecret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void setEndpoint(final String endpoint) {
|
||||||
|
Uni.endpoint = endpoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回(如果未初始化则初始化)统一客户端.
|
||||||
|
*
|
||||||
|
* @return the Uni Client
|
||||||
|
* @author :Wind
|
||||||
|
*/
|
||||||
|
public static UniClient getClient() {
|
||||||
|
if (Uni.client == null) {
|
||||||
|
synchronized (Uni.class) {
|
||||||
|
if (Uni.client == null) {
|
||||||
|
Uni.client = buildClient();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Uni.client;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setClient(final UniClient client) {
|
||||||
|
synchronized (Uni.class) {
|
||||||
|
Uni.client = client;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static UniClient buildClient() {
|
||||||
|
UniClient.Builder builder = new UniClient.Builder(Uni.accessKeyId);
|
||||||
|
|
||||||
|
if (Uni.accessKeySecret != null) {
|
||||||
|
builder.accessKeySecret(Uni.accessKeySecret);
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.endpoint(Uni.endpoint);
|
||||||
|
builder.signingAlgorithm(Uni.signingAlgorithm);
|
||||||
|
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,152 @@
|
|||||||
|
package org.dromara.sms4j.unisms.core;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.dtflys.forest.config.ForestConfiguration;
|
||||||
|
import org.dromara.sms4j.comm.exception.SmsBlendException;
|
||||||
|
import org.dromara.sms4j.comm.factory.BeanFactory;
|
||||||
|
|
||||||
|
import javax.crypto.Mac;
|
||||||
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
import java.util.Base64;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class UniClient {
|
||||||
|
|
||||||
|
public static final String USER_AGENT = "uni-java-sdk" + "/" + Uni.VERSION;
|
||||||
|
private final ForestConfiguration http = BeanFactory.getForestConfiguration();
|
||||||
|
|
||||||
|
private final String accessKeyId;
|
||||||
|
private final String accessKeySecret;
|
||||||
|
private final String endpoint;
|
||||||
|
private final String signingAlgorithm;
|
||||||
|
|
||||||
|
protected UniClient(Builder b) {
|
||||||
|
this.accessKeyId = b.accessKeyId;
|
||||||
|
this.accessKeySecret = b.accessKeySecret;
|
||||||
|
this.endpoint = b.endpoint;
|
||||||
|
this.signingAlgorithm = b.signingAlgorithm;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getSignature(final String message, final String secretKey) {
|
||||||
|
try {
|
||||||
|
Mac hmac = Mac.getInstance("HmacSHA256");
|
||||||
|
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(), "HmacSHA256");
|
||||||
|
hmac.init(secretKeySpec);
|
||||||
|
|
||||||
|
byte[] bytes = hmac.doFinal(message.getBytes());
|
||||||
|
return Base64.getEncoder().encodeToString(bytes);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String queryStringify(final Map<String, Object> params) {
|
||||||
|
Map<String, Object> sortedMap = new TreeMap<>(new MapKeyComparator());
|
||||||
|
sortedMap.putAll(params);
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
Iterator<?> iter = sortedMap.entrySet().iterator();
|
||||||
|
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
if (sb.length() > 0) {
|
||||||
|
sb.append('&');
|
||||||
|
}
|
||||||
|
Entry<?, ?> entry = (Entry<?, ?>) iter.next();
|
||||||
|
sb.append(entry.getKey()).append("=").append(entry.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, Object> sign(final Map<String, Object> query) {
|
||||||
|
if (this.accessKeySecret != null) {
|
||||||
|
query.put("algorithm", this.signingAlgorithm);
|
||||||
|
query.put("timestamp", new Date().getTime());
|
||||||
|
query.put("nonce", UUID.randomUUID().toString().replaceAll("-", ""));
|
||||||
|
|
||||||
|
String strToSign = UniClient.queryStringify(query);
|
||||||
|
query.put("signature", UniClient.getSignature(strToSign, this.accessKeySecret));
|
||||||
|
}
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* request
|
||||||
|
* <p>向 uni-sms发送请求
|
||||||
|
* @param action 接口名称
|
||||||
|
* @author :Wind
|
||||||
|
*/
|
||||||
|
public UniResponse request(final String action, final Map<String, Object> data) throws SmsBlendException {
|
||||||
|
Map<String, Object> query = new HashMap<String, Object>();
|
||||||
|
query.put("action", action);
|
||||||
|
query.put("accessKeyId", this.accessKeyId);
|
||||||
|
|
||||||
|
Map<String, String> headers = new HashMap<>();
|
||||||
|
headers.put("User-Agent", USER_AGENT);
|
||||||
|
headers.put("Content-Type", "application/json;charset=utf-8");
|
||||||
|
headers.put("Accept", "application/json");
|
||||||
|
return new UniResponse(
|
||||||
|
JSONObject.parseObject(
|
||||||
|
http.post(this.endpoint)
|
||||||
|
.addHeader(headers)
|
||||||
|
.addQuery(this.sign(query))
|
||||||
|
.addBody(JSONObject.toJSONString(data))
|
||||||
|
.successWhen(((req, res) -> {
|
||||||
|
return res.noException() && // 请求过程没有异常
|
||||||
|
res.statusIsNot(500); // 不能是 500
|
||||||
|
}))
|
||||||
|
.onError((ex, req, res) -> {
|
||||||
|
throw new SmsBlendException(ex.getMessage());
|
||||||
|
})
|
||||||
|
.executeAsString()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
private String accessKeyId;
|
||||||
|
private String accessKeySecret;
|
||||||
|
private String endpoint;
|
||||||
|
private String signingAlgorithm;
|
||||||
|
|
||||||
|
public Builder(final String accessKeyId) {
|
||||||
|
this.accessKeyId = accessKeyId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder(final String accessKeyId, final String accessKeySecret) {
|
||||||
|
this.accessKeyId = accessKeyId;
|
||||||
|
this.accessKeySecret = accessKeySecret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder accessKeySecret(final String accessKeySecret) {
|
||||||
|
this.accessKeySecret = accessKeySecret;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder endpoint(final String endpoint) {
|
||||||
|
this.endpoint = endpoint;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder signingAlgorithm(final String signingAlgorithm) {
|
||||||
|
this.signingAlgorithm = signingAlgorithm;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniClient build() {
|
||||||
|
return new UniClient(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MapKeyComparator implements Comparator<String> {
|
||||||
|
@Override
|
||||||
|
public int compare(String str1, String str2) {
|
||||||
|
return str1.compareTo(str2);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,53 @@
|
|||||||
|
package org.dromara.sms4j.unisms.core;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import org.dromara.sms4j.comm.exception.SmsBlendException;
|
||||||
|
|
||||||
|
|
||||||
|
public class UniResponse {
|
||||||
|
public static final String REQUEST_ID_HEADER_KEY = "x-uni-request-id";
|
||||||
|
public String requestId;
|
||||||
|
public String code;
|
||||||
|
public String message;
|
||||||
|
public String status;
|
||||||
|
public JSONObject data = null;
|
||||||
|
public Object raw;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Uni Response.
|
||||||
|
*
|
||||||
|
* @param response raw HTTP response
|
||||||
|
*/
|
||||||
|
public UniResponse(final JSONObject response) throws SmsBlendException {
|
||||||
|
JSONObject body = response.getJSONObject("data");
|
||||||
|
this.status = body.getJSONArray("messages").getJSONObject(0).getString("status");
|
||||||
|
this.requestId = body.getJSONArray("messages").getJSONObject(0).getString("id");
|
||||||
|
this.raw = body;
|
||||||
|
|
||||||
|
if (this.status != "400") {
|
||||||
|
String code = response.getString("code");
|
||||||
|
String message = body.getJSONArray("messages").getString(0);
|
||||||
|
if (!"0".equals(code)) {
|
||||||
|
throw new SmsBlendException(message, code, this.requestId);
|
||||||
|
}
|
||||||
|
this.code = code;
|
||||||
|
this.message = message;
|
||||||
|
this.data = body;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new SmsBlendException(response.getString("message"), "-1");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "UniResponse{" +
|
||||||
|
"requestId='" + requestId + '\'' +
|
||||||
|
", code='" + code + '\'' +
|
||||||
|
", message='" + message + '\'' +
|
||||||
|
", status='" + status + '\'' +
|
||||||
|
", data=" + data +
|
||||||
|
", raw=" + raw +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,8 +1,5 @@
|
|||||||
package org.dromara.sms4j.unisms.service;
|
package org.dromara.sms4j.unisms.service;
|
||||||
|
|
||||||
import com.apistd.uni.UniResponse;
|
|
||||||
import com.apistd.uni.sms.UniMessage;
|
|
||||||
import com.apistd.uni.sms.UniSMS;
|
|
||||||
import org.dromara.sms4j.api.SmsBlend;
|
import org.dromara.sms4j.api.SmsBlend;
|
||||||
import org.dromara.sms4j.api.callback.CallBack;
|
import org.dromara.sms4j.api.callback.CallBack;
|
||||||
import org.dromara.sms4j.api.entity.SmsResponse;
|
import org.dromara.sms4j.api.entity.SmsResponse;
|
||||||
@ -11,11 +8,19 @@ import org.dromara.sms4j.comm.delayedTime.DelayedTime;
|
|||||||
import org.dromara.sms4j.comm.exception.SmsBlendException;
|
import org.dromara.sms4j.comm.exception.SmsBlendException;
|
||||||
import org.dromara.sms4j.unisms.config.UniConfig;
|
import org.dromara.sms4j.unisms.config.UniConfig;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.dromara.sms4j.unisms.core.Uni;
|
||||||
|
import org.dromara.sms4j.unisms.core.UniResponse;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -52,10 +57,12 @@ public class UniSmsImpl implements SmsBlend {
|
|||||||
@Override
|
@Override
|
||||||
@Restricted
|
@Restricted
|
||||||
public SmsResponse sendMessage(String phone, String templateId, LinkedHashMap<String, String> messages) {
|
public SmsResponse sendMessage(String phone, String templateId, LinkedHashMap<String, String> messages) {
|
||||||
UniMessage uniMes = UniSMS.buildMessage().setSignature(config.getSignature()).setTo(phone)
|
Map<String, Object> data = new HashMap<>();
|
||||||
.setTemplateId(templateId)
|
data.put("to", Collections.singletonList(phone));
|
||||||
.setTemplateData(messages);
|
data.put("signature", config.getSignature());
|
||||||
return getSmsResponse(uniMes);
|
data.put("templateId", templateId);
|
||||||
|
data.put("templateData", messages);
|
||||||
|
return getSmsResponse(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -75,20 +82,19 @@ public class UniSmsImpl implements SmsBlend {
|
|||||||
if (phones.size()>1000){
|
if (phones.size()>1000){
|
||||||
throw new SmsBlendException("单次发送超过最大发送上限,建议每次群发短信人数低于1000");
|
throw new SmsBlendException("单次发送超过最大发送上限,建议每次群发短信人数低于1000");
|
||||||
}
|
}
|
||||||
String[] s = new String[phones.size()];
|
Map<String, Object> data = new HashMap<>();
|
||||||
UniMessage uniMes = UniSMS.buildMessage().setSignature(config.getSignature()).setTo(phones.toArray(s))
|
data.put("to", phones);
|
||||||
.setTemplateId(templateId)
|
data.put("signature", config.getSignature());
|
||||||
.setTemplateData(messages);
|
data.put("templateId", templateId);
|
||||||
return getSmsResponse(uniMes);
|
data.put("templateData", messages);
|
||||||
|
return getSmsResponse(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Restricted
|
@Restricted
|
||||||
public void sendMessageAsync(String phone, String message, CallBack callBack) {
|
public void sendMessageAsync(String phone, String message, CallBack callBack) {
|
||||||
pool.execute(()->{
|
CompletableFuture<SmsResponse> smsResponseCompletableFuture = CompletableFuture.supplyAsync(() -> sendMessage(phone, message), pool);
|
||||||
SmsResponse smsResponse = sendMessage(phone, message);
|
smsResponseCompletableFuture.thenAcceptAsync(callBack::callBack);
|
||||||
callBack.callBack(smsResponse);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -101,10 +107,8 @@ public class UniSmsImpl implements SmsBlend {
|
|||||||
@Override
|
@Override
|
||||||
@Restricted
|
@Restricted
|
||||||
public void sendMessageAsync(String phone, String templateId, LinkedHashMap<String, String> messages, CallBack callBack) {
|
public void sendMessageAsync(String phone, String templateId, LinkedHashMap<String, String> messages, CallBack callBack) {
|
||||||
pool.execute(()->{
|
CompletableFuture<SmsResponse> smsResponseCompletableFuture = CompletableFuture.supplyAsync(() -> sendMessage(phone, templateId, messages), pool);
|
||||||
SmsResponse smsResponse = sendMessage(phone,templateId,messages);
|
smsResponseCompletableFuture.thenAcceptAsync(callBack::callBack);
|
||||||
callBack.callBack(smsResponse);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -156,10 +160,10 @@ public class UniSmsImpl implements SmsBlend {
|
|||||||
},delayedTime);
|
},delayedTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SmsResponse getSmsResponse(UniMessage uniMes) {
|
private SmsResponse getSmsResponse( Map<String, Object> data) {
|
||||||
SmsResponse smsResponse = new SmsResponse();
|
SmsResponse smsResponse = new SmsResponse();
|
||||||
try {
|
try {
|
||||||
UniResponse send = uniMes.send();
|
UniResponse send = Uni.getClient().request("sms.message.send", data);
|
||||||
smsResponse.setCode(String.valueOf(send.status));
|
smsResponse.setCode(String.valueOf(send.status));
|
||||||
smsResponse.setErrorCode(send.code);
|
smsResponse.setErrorCode(send.code);
|
||||||
smsResponse.setMessage(send.message);
|
smsResponse.setMessage(send.message);
|
||||||
|
|||||||
@ -12,6 +12,7 @@ import org.dromara.sms4j.comm.exception.SmsBlendException;
|
|||||||
import org.dromara.sms4j.yunpian.config.YunpianConfig;
|
import org.dromara.sms4j.yunpian.config.YunpianConfig;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
@ -74,10 +75,8 @@ public class YunPianSmsImpl implements SmsBlend {
|
|||||||
@Override
|
@Override
|
||||||
@Restricted
|
@Restricted
|
||||||
public void sendMessageAsync(String phone, String message, CallBack callBack) {
|
public void sendMessageAsync(String phone, String message, CallBack callBack) {
|
||||||
pool.execute(() -> {
|
CompletableFuture<SmsResponse> smsResponseCompletableFuture = CompletableFuture.supplyAsync(() -> sendMessage(phone, message), pool);
|
||||||
SmsResponse smsResponse = sendMessage(phone, message);
|
smsResponseCompletableFuture.thenAcceptAsync(callBack::callBack);
|
||||||
callBack.callBack(smsResponse);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -89,10 +88,8 @@ public class YunPianSmsImpl implements SmsBlend {
|
|||||||
@Override
|
@Override
|
||||||
@Restricted
|
@Restricted
|
||||||
public void sendMessageAsync(String phone, String templateId, LinkedHashMap<String, String> messages, CallBack callBack) {
|
public void sendMessageAsync(String phone, String templateId, LinkedHashMap<String, String> messages, CallBack callBack) {
|
||||||
pool.execute(() -> {
|
CompletableFuture<SmsResponse> smsResponseCompletableFuture = CompletableFuture.supplyAsync(() -> sendMessage(phone, templateId, messages), pool);
|
||||||
SmsResponse smsResponse = sendMessage(phone, templateId, messages);
|
smsResponseCompletableFuture.thenAcceptAsync(callBack::callBack);
|
||||||
callBack.callBack(smsResponse);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -33,5 +33,11 @@
|
|||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter</artifactId>
|
<artifactId>spring-boot-starter</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user