!134 七牛云短信对接

Merge pull request !134 from yym/dev-3.0.x  贡献者 yym
This commit is contained in:
风如歌 2024-02-02 01:15:46 +00:00 committed by Gitee
commit 6ef9c692b8
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
8 changed files with 300 additions and 7 deletions

View File

@ -59,5 +59,6 @@ public abstract class SupplierConstant {
* 鼎众 * 鼎众
*/ */
public static final String DINGZHONG = "dingzhong"; public static final String DINGZHONG = "dingzhong";
public static final String QINIU = "qiniu";
} }

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -1,8 +1,14 @@
package org.dromara.sms4j.example; 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.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import java.util.ArrayList;
import java.util.LinkedHashMap;
/** /**
* 主类 * 主类
* *

View File

@ -79,13 +79,20 @@ sms:
access-key-secret: 你的Access Key Secret access-key-secret: 你的Access Key Secret
sdkAppId: 你的应用ID sdkAppId: 你的应用ID
#自定义广州掌骏短信添加factory全路径。config,factory,SmsImpl复制其他默认实现即可修改对应的supplier和发送核心逻辑即可 #自定义广州掌骏短信添加factory全路径。config,factory,SmsImpl复制其他默认实现即可修改对应的supplier和发送核心逻辑即可
zhangjun: # zhangjun:
supplier: zhangjun # supplier: zhangjun
factory: org.dromara.sms4j.example.zhangjun.ZhangJunFactory # factory: org.dromara.sms4j.example.zhangjun.ZhangJunFactory
templateId: d2a****777 # templateId: d2a****777
appId: 64c52d2a****77775fe72e3 # appId: 64c52d2a****77775fe72e3
sid: d2a****777 # sid: d2a****777
url: https://sms.idowe.com/**/**/**/send # 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: sms-oa:
config-type: yaml config-type: yaml
oas: oas:

View File

@ -30,6 +30,7 @@ import org.dromara.sms4j.netease.config.NeteaseFactory;
import org.dromara.sms4j.provider.config.SmsConfig; import org.dromara.sms4j.provider.config.SmsConfig;
import org.dromara.sms4j.provider.factory.BaseProviderFactory; import org.dromara.sms4j.provider.factory.BaseProviderFactory;
import org.dromara.sms4j.provider.factory.ProviderFactoryHolder; 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.starter.adepter.ConfigCombineMapAdeptor;
import org.dromara.sms4j.tencent.config.TencentFactory; import org.dromara.sms4j.tencent.config.TencentFactory;
import org.dromara.sms4j.unisms.config.UniFactory; import org.dromara.sms4j.unisms.config.UniFactory;
@ -123,6 +124,7 @@ public class SmsBlendsInitializer {
ProviderFactoryHolder.registerFactory(ZhutongFactory.instance()); ProviderFactoryHolder.registerFactory(ZhutongFactory.instance());
ProviderFactoryHolder.registerFactory(LianLuFactory.instance()); ProviderFactoryHolder.registerFactory(LianLuFactory.instance());
ProviderFactoryHolder.registerFactory(DingZhongFactory.instance()); ProviderFactoryHolder.registerFactory(DingZhongFactory.instance());
ProviderFactoryHolder.registerFactory(QiNiuFactory.instance());
if(SmsUtils.isClassExists("com.jdcloud.sdk.auth.CredentialsProvider")) { if(SmsUtils.isClassExists("com.jdcloud.sdk.auth.CredentialsProvider")) {
ProviderFactoryHolder.registerFactory(JdCloudFactory.instance()); ProviderFactoryHolder.registerFactory(JdCloudFactory.instance());
} }