mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-11-04 12:18:42 +08:00 
			
		
		
		
	【功能优化】短信:华为云的实现优化,调整 sender 配置到 accessKey 中
This commit is contained in:
		@@ -49,25 +49,43 @@ public class HuaweiSmsClient extends AbstractSmsClient {
 | 
			
		||||
        super(properties);
 | 
			
		||||
        Assert.notEmpty(properties.getApiKey(), "apiKey 不能为空");
 | 
			
		||||
        Assert.notEmpty(properties.getApiSecret(), "apiSecret 不能为空");
 | 
			
		||||
        validateSender(properties);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 参数校验华为云的 sender 通道号
 | 
			
		||||
     *
 | 
			
		||||
     * 原因是:验华为云发放短信的时候,需要额外的参数 sender
 | 
			
		||||
     *
 | 
			
		||||
     * 解决方案:考虑到不破坏原有的 apiKey + apiSecret 的结构,所以将 secretId 拼接到 apiKey 字段中,格式为 "secretId sdkAppId"。
 | 
			
		||||
     *
 | 
			
		||||
     * @param properties 配置
 | 
			
		||||
     */
 | 
			
		||||
    private static void validateSender(SmsChannelProperties properties) {
 | 
			
		||||
        String combineKey = properties.getApiKey();
 | 
			
		||||
        Assert.notEmpty(combineKey, "apiKey 不能为空");
 | 
			
		||||
        String[] keys = combineKey.trim().split(" ");
 | 
			
		||||
        Assert.isTrue(keys.length == 2, "华为云短信 apiKey 配置格式错误,请配置 为[accessKeyId sender]");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private String getAccessKey() {
 | 
			
		||||
        return StrUtil.subBefore(properties.getApiKey(), " ", true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private String getSender() {
 | 
			
		||||
        return StrUtil.subAfter(properties.getApiKey(), " ", true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public SmsSendRespDTO sendSms(Long sendLogId, String mobile, String apiTemplateId,
 | 
			
		||||
                                  List<KeyValue<String, Object>> templateParams) throws Throwable {
 | 
			
		||||
        // 1. 执行请求
 | 
			
		||||
        // 参考链接 https://support.huaweicloud.com/api-msgsms/sms_05_0001.html
 | 
			
		||||
        // 相比较阿里短信,华为短信发送的时候需要额外的参数“通道号”,考虑到不破坏原有的的结构,
 | 
			
		||||
        // 所以将 sender 通道号,拼接到 apiTemplateId 字段中,格式为 "apiTemplateId 通道号"(空格为分隔符)
 | 
			
		||||
        String sender = apiTemplateId.split(" ")[1]; // 中国大陆短信签名通道号或全球短信通道号
 | 
			
		||||
        String templateId = apiTemplateId.split(" ")[0]; //模板ID
 | 
			
		||||
        String statusCallBack = properties.getCallbackUrl();
 | 
			
		||||
        StringBuilder requestBody = new StringBuilder();
 | 
			
		||||
        appendToBody(requestBody, "from=", sender);
 | 
			
		||||
        appendToBody(requestBody, "from=", getSender());
 | 
			
		||||
        appendToBody(requestBody, "&to=", mobile);
 | 
			
		||||
        appendToBody(requestBody, "&templateId=", templateId);
 | 
			
		||||
        appendToBody(requestBody, "&templateId=", apiTemplateId);
 | 
			
		||||
        appendToBody(requestBody, "&templateParas=", JsonUtils.toJsonString(
 | 
			
		||||
                convertList(templateParams, kv -> String.valueOf(kv.getValue()))));
 | 
			
		||||
        appendToBody(requestBody, "&statusCallback=", statusCallBack);
 | 
			
		||||
        appendToBody(requestBody, "&statusCallback=", properties.getCallbackUrl());
 | 
			
		||||
        appendToBody(requestBody, "&extend=", String.valueOf(sendLogId));
 | 
			
		||||
        JSONObject response = request("/sms/batchSendSms/v1/", "POST", requestBody.toString());
 | 
			
		||||
 | 
			
		||||
@@ -107,7 +125,7 @@ public class HuaweiSmsClient extends AbstractSmsClient {
 | 
			
		||||
                + canonicalHeaders + "\n" + SIGNEDHEADERS + "\n" + sha256Hex(requestBody);
 | 
			
		||||
        String stringToSign = "SDK-HMAC-SHA256" + "\n" + sdkDate + "\n" + sha256Hex(canonicalRequest);
 | 
			
		||||
        String signature = SecureUtil.hmacSha256(properties.getApiSecret()).digestHex(stringToSign);  // 计算签名
 | 
			
		||||
        headers.put("Authorization", "SDK-HMAC-SHA256" + " " + "Access=" + properties.getApiKey()
 | 
			
		||||
        headers.put("Authorization", "SDK-HMAC-SHA256" + " " + "Access=" + getAccessKey()
 | 
			
		||||
                + ", " + "SignedHeaders=" + SIGNEDHEADERS + ", " + "Signature=" + signature);
 | 
			
		||||
 | 
			
		||||
        // 2. 发起请求
 | 
			
		||||
@@ -131,11 +149,10 @@ public class HuaweiSmsClient extends AbstractSmsClient {
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public SmsTemplateRespDTO getSmsTemplate(String apiTemplateId) throws Throwable {
 | 
			
		||||
        // 相比较阿里短信,华为短信发送的时候需要额外的参数“通道号”,考虑到不破坏原有的的结构,
 | 
			
		||||
        // 所以将 sender 通道号,拼接到 apiTemplateId 字段中,格式为 "apiTemplateId 通道号"(空格为分隔符)
 | 
			
		||||
        // 华为短信模板查询和发送短信,是不同的两套 key 和 secret,与阿里、腾讯的区别较大,这里模板查询校验暂不实现
 | 
			
		||||
        String[] strs = apiTemplateId.split(" ");
 | 
			
		||||
        Assert.isTrue(strs.length == 2, "格式不正确,需要满足:apiTemplateId sender");
 | 
			
		||||
        return new SmsTemplateRespDTO().setId(strs[0]).setContent(null)
 | 
			
		||||
        return new SmsTemplateRespDTO().setId(apiTemplateId).setContent(null)
 | 
			
		||||
                .setAuditStatus(SmsTemplateAuditStatusEnum.SUCCESS.getStatus()).setAuditReason(null);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -29,7 +29,7 @@ import static org.mockito.Mockito.mockStatic;
 | 
			
		||||
public class HuaweiSmsClientTest extends BaseMockitoUnitTest {
 | 
			
		||||
 | 
			
		||||
    private final SmsChannelProperties properties = new SmsChannelProperties()
 | 
			
		||||
            .setApiKey(randomString())// 随机一个 apiKey,避免构建报错
 | 
			
		||||
            .setApiKey(randomString() + " " + randomString()) // 随机一个 apiKey,避免构建报错
 | 
			
		||||
            .setApiSecret(randomString()) // 随机一个 apiSecret,避免构建报错
 | 
			
		||||
            .setSignature("芋道源码");
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -95,15 +95,16 @@ public class SmsClientTests {
 | 
			
		||||
    @Test
 | 
			
		||||
    @Disabled
 | 
			
		||||
    public void testHuaweiSmsClient_sendSms() throws Throwable {
 | 
			
		||||
        String sender = "x8824060312575";
 | 
			
		||||
        SmsChannelProperties properties = new SmsChannelProperties()
 | 
			
		||||
                .setApiKey(System.getenv("SMS_HUAWEI_ACCESS_KEY"))
 | 
			
		||||
                .setApiKey(System.getenv("SMS_HUAWEI_ACCESS_KEY") + " " + sender)
 | 
			
		||||
                .setApiSecret(System.getenv("SMS_HUAWEI_SECRET_KEY"))
 | 
			
		||||
                .setSignature("runpu");
 | 
			
		||||
        HuaweiSmsClient client = new HuaweiSmsClient(properties);
 | 
			
		||||
        // 准备参数
 | 
			
		||||
        Long sendLogId = System.currentTimeMillis();
 | 
			
		||||
        String mobile = "17321315478";
 | 
			
		||||
        String apiTemplateId = "3644cdab863546a3b718d488659a99ef x8824060312575";
 | 
			
		||||
        String apiTemplateId = "3644cdab863546a3b718d488659a99ef";
 | 
			
		||||
        List<KeyValue<String, Object>> templateParams = List.of(new KeyValue<>("code", "1024"));
 | 
			
		||||
        // 调用
 | 
			
		||||
        SmsSendRespDTO smsSendRespDTO = client.sendSms(sendLogId, mobile, apiTemplateId, templateParams);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user