当前位置: 首页 > article >正文

SpringBoot调用华为云短信实现发短信功能

参考 发送短信_消息&短信 MSGSMS_华为云

1.引入华为云短信pom依赖

<dependency>
    <groupId>com.huaweicloud.sdk</groupId>
    <artifactId>huaweicloud-sdk-smsapi</artifactId>
    <version>3.1.125</version>
</dependency>

2.参考华为云短信官方文档

Java_消息&短信 MSGSMS_华为云

import com.huaweicloud.sdk.core.auth.BasicCredentials;
import com.huaweicloud.sdk.core.http.HttpMethod;
import com.huaweicloud.sdk.core.http.HttpRequest;
import com.huaweicloud.sdk.smsapi.utils.SmsAkSkSigner;

import com.knowdee.cc.common.domain.CcSendMsgInfo;
import com.knowdee.cc.common.service.ICcSendMsgInfoService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;

import static java.nio.charset.StandardCharsets.UTF_8;

@Service
@Slf4j
public class HuaweiSmsService {

    @Value("${huawei.cloud.sms.access-key}")
    private String accessKey;

    @Value("${huawei.cloud.sms.secret-key}")
    private String secretKey;

    @Value("${huawei.cloud.sms.signature}")
    private String signature;

    @Value("${huawei.cloud.sms.endpoint}")
    private String endpoint;

    @Resource
    private ICcSendMsgInfoService ccSendMsgInfoService;

    private static CloseableHttpClient httpClient = null;

    public static void main(String[] args) throws Exception {
        /*
         * Send an SMS message using a special AK/SK authentication algorithm.
         * When the MSGSMS is used to send SMS messages, the AK is app_key, and the SK is app_secret.
         * There will be security risks if the app_key/app_secret used for authentication is directly written into code.
         * We suggest encrypting the app_key/app_secret in the configuration file or environment variables for storage.
         * In this sample, the app_key/app_secret is stored in environment variables for identity authentication.
         * Before running this sample, set the environment variables CLOUD_SDK_MSGSMS_APPKEY and CLOUD_SDK_MSGSMS_APPSECRET.
         * CLOUD_SDK_MSGSMS_APPKEY indicates the application key (app_key), and CLOUD_SDK_MSGSMS_APPSECRET indicates the application secret (app_secret).
         * You can obtain the value from Application Management on the console or by calling the open API of Application Management.
         */
        //String ak = System.getenv("CLOUD_SDK_MSGSMS_APPKEY");
        //String sk = System.getenv("CLOUD_SDK_MSGSMS_APPSECRET");
//        if (Objects.isNull(ak) || Objects.isNull(sk)) {
//            System.out.println("the ak or sk is null. please config the environment CLOUD_SDK_MSGSMS_APPKEY and CLOUD_SDK_MSGSMS_APPSECRET first!");
//            return;
//        }

        // To prevent API invoking failures caused by HTTPS certificate authentication failures, ignore the certificate trust issue to simplify the sample code.
//        httpClient = createIgnoreSSLHttpClient();
//        HuaweiSmsService huaweiSmsService = new HuaweiSmsService();
//        huaweiSmsService.sendSms("","xALlH903ix07t4agS5122U0O6A9J", "CSjuauYNbBHI0FqH3rCUI3Dpl0yA");
    }

    /**
     * Example of Invoking the batchSendSms Interface to Send an SMS Message
     *
     * @param ak AK is the app_key of the SMS application.
     * @param sk SK is the app_secret of the SMS application.
     * @throws UnsupportedEncodingException
     */
    public Boolean sendSms(String templateId, String phone, String content) throws UnsupportedEncodingException {
        // This address is of Beijing 4. Replace it with the actual value.
        //String uri = "https://smsapi.cn-north-4.myhuaweicloud.com:443/sms/batchSendSms/v1";
        try {
            httpClient = createIgnoreSSLHttpClient();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        String uri = endpoint + "/sms/batchSendSms/v1";
        // Construct the message body of the sample code.
        // For details about how to construct a body, see the API description.
        StringBuilder body = new StringBuilder();

        appendToBody(body, "from=", signature);
        appendToBody(body, "&to=", phone);
        appendToBody(body, "&templateId=", templateId);
        appendToBody(body, "&templateParas=", "[\"" + content + "\"]");
        //appendToBody(body, "&statusCallback=", "https://test/report");
        log.info("body:" + body);
        //System.out.println("body:" + body);

        // Signature operation of the batchsendsms interface
        Boolean flag = false;
        Map<String, String> signedHeaders = sign(accessKey, secretKey, body.toString(), uri);
        if (Objects.isNull(signedHeaders)) {
            //System.out.println("sign failed!");
            log.info("sign failed!");
            return flag;
        }

        // Print Signature Results
        //System.out.println("BatchSendSms sign result:" + signedHeaders);
        log.info("BatchSendSms sign result:" + signedHeaders);

        HttpPost postRequest = new HttpPost(uri);
        postRequest.setHeader("Accept", "application/json");
        postRequest.setHeader("Content-Type", "application/x-www-form-urlencoded");
        signedHeaders.forEach((key, value) -> postRequest.setHeader(key, value));
        postRequest.setEntity(new StringEntity(body.toString(), StandardCharsets.UTF_8));

        // Invoke /sms/batchSendSms/v1 api to send messages
        try (CloseableHttpResponse response = httpClient.execute(postRequest)) {
            // Print the response status code.
//            System.out.println("Response Status Code: " + response.getStatusLine().getStatusCode());
//            System.out.println("Response Content: " + EntityUtils.toString(response.getEntity()));
            log.info("Response Status Code: " + response.getStatusLine().getStatusCode());
            log.info("Response Content: " + EntityUtils.toString(response.getEntity()));
            if (response.getStatusLine().getStatusCode() == 200) {
                flag = true;
            }else{
                CcSendMsgInfo ccSendMsgInfo = new CcSendMsgInfo();
                ccSendMsgInfo.setContent(content);
                ccSendMsgInfo.setTemplateId(templateId);
                ccSendMsgInfo.setTime(new Date());
                ccSendMsgInfo.setPhone(phone);
                ccSendMsgInfo.setFailInfo(response.getStatusLine().getReasonPhrase());
                ccSendMsgInfoService.getBaseMapper().insert(ccSendMsgInfo);
            }
            // Print the response content.
        } catch (IOException e) {
            //System.out.println("response exception:" + e);
            log.info("response exception:" + e);
        }
        return flag;
    }

    /**
     * Create an HTTP client that ignores the HTTPS certificate check.
     *
     * @return HTTP client
     * @throws Exception
     */
    private CloseableHttpClient createIgnoreSSLHttpClient() throws Exception {
        SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, (x509CertChain, authType) -> true).build();
        return HttpClients.custom().setSSLSocketFactory(new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE)).build();
    }

    /**
     * Add the parameter to the original body after URL encoding.
     *
     * @param body Message body
     * @param key  Parameter key
     * @param val  Parameter value
     * @throws UnsupportedEncodingException
     */
    private static void appendToBody(StringBuilder body, String key, String val) throws UnsupportedEncodingException {
        if (null != val && !val.isEmpty()) {
            body.append(key).append(URLEncoder.encode(val, UTF_8.name()));
        }
    }

    /**
     * The algorithm for generating the signature header field (Authorization, X-Sdk-Date, Host) is provided.
     *
     * @param ak       AK is the app_key of the SMS application.
     * @param sk       SK is the app_secret of the SMS application.
     * @param body     Message body to be signed
     * @param endpoint the api uri
     * @return signature header field (Authorization, X-Sdk-Date, Host)
     */
    private static Map<String, String> sign(String ak, String sk, String body, String endpoint) {
        // The signature algorithm uses the AK and SK signature algorithms provided by HUAWEI CLOUD IAM and API Gateway.
        // Signature algorithm implementation. The capabilities provided by the SDK are used here.
        // Developers can also use the signature capability provided by HUAWEI CLOUD APIG. For details, see the following website: https://support.huaweicloud.com/devg-apisign/api-sign-sdk-java.html
        // For the signature operation of an interface, the signature must contain the body.
        return SmsAkSkSigner.sign(HttpRequest.newBuilder().withBodyAsString(body)
                        .withMethod(HttpMethod.POST)
                        .withEndpoint(endpoint)
                        .addHeader("Content-Type", "application/x-www-form-urlencoded").build(),
                new BasicCredentials().withAk(ak).withSk(sk));
    }
}

3.踩坑问题

3.1如果使用短信模版时,要注意短信templateParas参数的个数


http://www.kler.cn/a/585689.html

相关文章:

  • 如何把绿色可执行应用程序添加到Ubuntu的收藏夹Dock中
  • 【Azure 架构师学习笔记】- Azure Databricks (20) --Delta Live Table 建议
  • Markdown Poster – 免费Markdown转图片工具|优雅图文海报制作与社交媒体分享
  • Vue 中如何使用 slot 和 scoped slot?
  • OpenCV图像加权函数:addWeighted
  • 成功破解加密机制,研究人员解锁LinuxESXi Akira勒索软件
  • Redis的持久化-AOF
  • 【Qt】带参数的信号和槽函数
  • 计算机网络 网络层IP数据报首部格式、数据链路层帧格式综合练习
  • 神经网络微调技术解析
  • vue3实现星星打分组件
  • Java 集合框架大师课:集合框架的暗黑料理(六)
  • 数据结构(三)——链表
  • 流水线(Pipeline)
  • Linux 进程的创建、终止、等待与程序替换函数 保姆级讲解
  • KICK第五课:Mac 系统下安装 Xcode 或 Clang
  • C++初阶——类和对象(一)
  • 3DS模拟器使用(pc+安卓)+金手指+存档互传
  • visual studio编译fortran
  • Springboot项目发送请求