mirror of
https://gitee.com/dromara/sms4j.git
synced 2025-12-06 17:08:40 +08:00
commit
6ef9c692b8
@ -59,5 +59,6 @@ public abstract class SupplierConstant {
|
||||
* 鼎众
|
||||
*/
|
||||
public static final String DINGZHONG = "dingzhong";
|
||||
public static final String QINIU = "qiniu";
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,32 @@
|
||||
package org.dromara.sms4j.qiniu.config;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.dromara.sms4j.comm.constant.SupplierConstant;
|
||||
import org.dromara.sms4j.provider.config.BaseConfig;
|
||||
|
||||
/**
|
||||
* @author Administrator
|
||||
* @Date: 2024/1/30 15:56 30
|
||||
* @描述: QiNiuConfig
|
||||
**/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class QiNiuConfig extends BaseConfig {
|
||||
|
||||
|
||||
private String baseUrl = "https://sms.qiniuapi.com";
|
||||
|
||||
private String templateName;
|
||||
|
||||
private String singleMsgUrl = "/v1/message/single";
|
||||
|
||||
private String massMsgUrl = "/v1/message";
|
||||
|
||||
private String signatureId;
|
||||
|
||||
@Override
|
||||
public String getSupplier() {
|
||||
return SupplierConstant.QINIU;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
package org.dromara.sms4j.qiniu.config;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.dromara.sms4j.comm.constant.SupplierConstant;
|
||||
import org.dromara.sms4j.netease.config.NeteaseConfig;
|
||||
import org.dromara.sms4j.netease.config.NeteaseFactory;
|
||||
import org.dromara.sms4j.netease.service.NeteaseSmsImpl;
|
||||
import org.dromara.sms4j.provider.factory.AbstractProviderFactory;
|
||||
import org.dromara.sms4j.qiniu.service.QiNiuSmsImpl;
|
||||
|
||||
/**
|
||||
* @author Administrator
|
||||
* @Date: 2024/1/30 16:06 29
|
||||
* @描述: QiNiuFactory
|
||||
**/
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class QiNiuFactory extends AbstractProviderFactory<QiNiuSmsImpl, QiNiuConfig> {
|
||||
|
||||
private static final QiNiuFactory INSTANCE = new QiNiuFactory();
|
||||
|
||||
|
||||
public static QiNiuFactory instance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public QiNiuSmsImpl createSms(QiNiuConfig qiNiuConfig) {
|
||||
return new QiNiuSmsImpl(qiNiuConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSupplier() {
|
||||
return SupplierConstant.QINIU;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,131 @@
|
||||
package org.dromara.sms4j.qiniu.service;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.google.gson.Gson;
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.sms4j.api.entity.SmsResponse;
|
||||
import org.dromara.sms4j.comm.constant.SupplierConstant;
|
||||
import org.dromara.sms4j.comm.delayedTime.DelayedTime;
|
||||
import org.dromara.sms4j.netease.config.NeteaseConfig;
|
||||
import org.dromara.sms4j.provider.service.AbstractSmsBlend;
|
||||
import org.dromara.sms4j.qiniu.config.QiNiuConfig;
|
||||
import org.dromara.sms4j.qiniu.util.QiNiuUtils;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/**
|
||||
* @author Administrator
|
||||
* @Date: 2024/1/30 16:06 59
|
||||
* @描述: QiNiuSmsImpl
|
||||
**/
|
||||
@Slf4j
|
||||
public class QiNiuSmsImpl extends AbstractSmsBlend<QiNiuConfig> {
|
||||
|
||||
private int retry = 0;
|
||||
|
||||
@Override
|
||||
public String getSupplier() {
|
||||
return SupplierConstant.QINIU;
|
||||
}
|
||||
|
||||
public QiNiuSmsImpl(QiNiuConfig config, Executor pool, DelayedTime delayed) {
|
||||
super(config, pool, delayed);
|
||||
}
|
||||
|
||||
public QiNiuSmsImpl(QiNiuConfig config) {
|
||||
super(config);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SmsResponse sendMessage(String phone, String message) {
|
||||
return sendSingleMsg(phone, getConfig().getTemplateId(), new LinkedHashMap<String, String>() {{
|
||||
put(getConfig().getTemplateName(), message);
|
||||
}});
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SmsResponse sendMessage(String phone, LinkedHashMap<String, String> messages) {
|
||||
return sendSingleMsg(phone, getConfig().getTemplateId(), messages);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SmsResponse sendMessage(String phone, String templateId, LinkedHashMap<String, String> messages) {
|
||||
return sendSingleMsg(phone, templateId, messages);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SmsResponse massTexting(List<String> phones, String message) {
|
||||
LinkedHashMap<String, String> params = new LinkedHashMap<>();
|
||||
params.put(getConfig().getTemplateName(), message);
|
||||
return senMassMsg(phones, getConfig().getTemplateId(), params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SmsResponse massTexting(List<String> phones, String templateId, LinkedHashMap<String, String> messages) {
|
||||
return senMassMsg(phones, templateId, messages);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return SmsResponse
|
||||
* @author 初拥。
|
||||
* @date 2024/1/31 8:54
|
||||
* @Description: 统一处理返回结果
|
||||
*/
|
||||
public SmsResponse handleRes(String url, HashMap<String, Object> params) {
|
||||
JSONObject jsonObject = http.postJson(url, QiNiuUtils.getHeaderAndSign(url, params, getConfig()), params);
|
||||
SmsResponse smsResponse = new SmsResponse();
|
||||
smsResponse.setSuccess(ObjectUtil.isEmpty(jsonObject.getStr("error")));
|
||||
smsResponse.setData(jsonObject);
|
||||
smsResponse.setConfigId(getConfigId());
|
||||
if (smsResponse.isSuccess() || retry == getConfig().getMaxRetries()) {
|
||||
retry = 0;
|
||||
return smsResponse;
|
||||
}
|
||||
http.safeSleep(getConfig().getRetryInterval());
|
||||
retry++;
|
||||
log.warn("短信第 {" + retry + "} 次重新发送");
|
||||
return handleRes(url, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param phones
|
||||
* @param templateId
|
||||
* @param messages
|
||||
* @return SmsResponse
|
||||
* @author 初拥。
|
||||
* @date 2024/1/31 9:20
|
||||
* @Description: 发送群发短信
|
||||
*/
|
||||
private SmsResponse senMassMsg(List<String> phones, String templateId, LinkedHashMap<String, String> messages) {
|
||||
String url = getConfig().getBaseUrl() + getConfig().getMassMsgUrl();
|
||||
HashMap<String, Object> params = new HashMap<>();
|
||||
params.put("template_id", templateId);
|
||||
params.put("mobiles", phones.toArray());
|
||||
params.put("parameters", messages);
|
||||
return handleRes(url, params);
|
||||
}
|
||||
|
||||
|
||||
private SmsResponse sendSingleMsg(String phone, String templateId, LinkedHashMap<String, String> messages) {
|
||||
String url = getConfig().getBaseUrl() + getConfig().getSingleMsgUrl();
|
||||
//手机号
|
||||
HashMap<String, Object> hashMap = new HashMap<>();
|
||||
hashMap.put("mobile", phone);
|
||||
hashMap.put("template_id", templateId);
|
||||
hashMap.put("parameters", messages);
|
||||
|
||||
log.info("hashMap:{}", hashMap);
|
||||
|
||||
return handleRes(url, hashMap);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,76 @@
|
||||
package org.dromara.sms4j.qiniu.util;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.sms4j.comm.constant.Constant;
|
||||
import org.dromara.sms4j.comm.exception.SmsBlendException;
|
||||
import org.dromara.sms4j.qiniu.config.QiNiuConfig;
|
||||
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
|
||||
import static org.apache.commons.codec.digest.HmacUtils.hmacSha1;
|
||||
|
||||
/**
|
||||
* @author Administrator
|
||||
* @Date: 2024/1/30 16:37 50
|
||||
* @描述: QiNiuUtils
|
||||
**/
|
||||
@Data
|
||||
@Slf4j
|
||||
public class QiNiuUtils {
|
||||
|
||||
private static final String HMAC_SHA1_ALGORITHM = "HmacSHA1";
|
||||
|
||||
public static String getSignature(String method, String url, QiNiuConfig qiNiuConfig, String body, String signDate) throws NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException, MalformedURLException {
|
||||
URI reqUrl = URI.create(url);
|
||||
StringBuilder dataToSign = new StringBuilder();
|
||||
dataToSign.append(method.toUpperCase()).append(" ").append(reqUrl.getPath());
|
||||
dataToSign.append("\nHost: ").append(reqUrl.getHost());
|
||||
dataToSign.append("\n").append("Content-Type").append(": ").append(Constant.ACCEPT);
|
||||
dataToSign.append("\n").append("X-Qiniu-Date").append(": ").append(signDate);
|
||||
dataToSign.append("\n\n");
|
||||
if (ObjectUtil.isNotEmpty(body)) {
|
||||
dataToSign.append(body);
|
||||
}
|
||||
Mac sha1Mac = Mac.getInstance(HMAC_SHA1_ALGORITHM);
|
||||
SecretKeySpec secretKeySpec = new SecretKeySpec(qiNiuConfig.getAccessKeySecret().getBytes(StandardCharsets.UTF_8), HMAC_SHA1_ALGORITHM);
|
||||
sha1Mac.init(secretKeySpec);
|
||||
byte[] signData = sha1Mac.doFinal(dataToSign.toString().getBytes(StandardCharsets.UTF_8));
|
||||
String encodedSignature = Base64.getEncoder().encodeToString(signData);
|
||||
|
||||
System.out.println("encodedSignature = " + encodedSignature);
|
||||
|
||||
return "Qiniu " + qiNiuConfig.getAccessKeyId() + ":" + encodedSignature;
|
||||
}
|
||||
|
||||
public static Map<String, String> getHeaderAndSign(String url, HashMap<String, Object> hashMap, QiNiuConfig qiNiuConfig) {
|
||||
String signature = null;
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd'T'HHmmss'Z'");
|
||||
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
|
||||
String signDate = dateFormat.format(new Date());
|
||||
try {
|
||||
signature = getSignature("POST", url, qiNiuConfig, JSONUtil.toJsonStr(hashMap), signDate);
|
||||
} catch (Exception e) {
|
||||
log.error("签名失败", e);
|
||||
throw new SmsBlendException(e.getMessage());
|
||||
}
|
||||
|
||||
//请求头
|
||||
Map<String, String> header = new HashMap<>();
|
||||
header.put("Authorization", signature);
|
||||
header.put("X-Qiniu-Date", signDate);
|
||||
header.put("Content-Type", "application/json");
|
||||
return header;
|
||||
}
|
||||
}
|
||||
@ -1,8 +1,14 @@
|
||||
package org.dromara.sms4j.example;
|
||||
|
||||
import org.dromara.sms4j.api.entity.SmsResponse;
|
||||
import org.dromara.sms4j.comm.constant.SupplierConstant;
|
||||
import org.dromara.sms4j.core.factory.SmsFactory;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
/**
|
||||
* 主类
|
||||
*
|
||||
|
||||
@ -79,13 +79,20 @@ sms:
|
||||
access-key-secret: 你的Access Key Secret
|
||||
sdkAppId: 你的应用ID
|
||||
#自定义广州掌骏短信,添加factory全路径。config,factory,SmsImpl复制其他默认实现即可,修改对应的supplier和发送核心逻辑即可
|
||||
zhangjun:
|
||||
supplier: zhangjun
|
||||
factory: org.dromara.sms4j.example.zhangjun.ZhangJunFactory
|
||||
templateId: d2a****777
|
||||
appId: 64c52d2a****77775fe72e3
|
||||
sid: d2a****777
|
||||
url: https://sms.idowe.com/**/**/**/send
|
||||
# zhangjun:
|
||||
# supplier: zhangjun
|
||||
# factory: org.dromara.sms4j.example.zhangjun.ZhangJunFactory
|
||||
# templateId: d2a****777
|
||||
# appId: 64c52d2a****77775fe72e3
|
||||
# sid: d2a****777
|
||||
# url: https://sms.idowe.com/**/**/**/send
|
||||
qiniu:
|
||||
access-key-id: EQcDflLTCYnU1******CmqIYLhog1lkWHb2
|
||||
access-key-secret: NeS2ptvZQoIy*****err2DdLe7wxFfQvji1
|
||||
templateId: 1752130****15859456
|
||||
signatureId: 175185*****1624960
|
||||
templateName: code
|
||||
|
||||
sms-oa:
|
||||
config-type: yaml
|
||||
oas:
|
||||
|
||||
@ -30,6 +30,7 @@ import org.dromara.sms4j.netease.config.NeteaseFactory;
|
||||
import org.dromara.sms4j.provider.config.SmsConfig;
|
||||
import org.dromara.sms4j.provider.factory.BaseProviderFactory;
|
||||
import org.dromara.sms4j.provider.factory.ProviderFactoryHolder;
|
||||
import org.dromara.sms4j.qiniu.config.QiNiuFactory;
|
||||
import org.dromara.sms4j.starter.adepter.ConfigCombineMapAdeptor;
|
||||
import org.dromara.sms4j.tencent.config.TencentFactory;
|
||||
import org.dromara.sms4j.unisms.config.UniFactory;
|
||||
@ -123,6 +124,7 @@ public class SmsBlendsInitializer {
|
||||
ProviderFactoryHolder.registerFactory(ZhutongFactory.instance());
|
||||
ProviderFactoryHolder.registerFactory(LianLuFactory.instance());
|
||||
ProviderFactoryHolder.registerFactory(DingZhongFactory.instance());
|
||||
ProviderFactoryHolder.registerFactory(QiNiuFactory.instance());
|
||||
if(SmsUtils.isClassExists("com.jdcloud.sdk.auth.CredentialsProvider")) {
|
||||
ProviderFactoryHolder.registerFactory(JdCloudFactory.instance());
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user