更新时间:2024-12-17 GMT+08:00
分享

Java

  • 发送短信为单模板群发短信示例,发送分批短信为多模板群发短信示例。
  • 本文档所述Demo在提供服务的过程中,可能会涉及个人数据的使用,建议您遵从国家的相关法律采取足够的措施,以确保用户的个人数据受到充分的保护。
  • 本文档所述Demo仅用于功能演示,不允许客户直接进行商业使用。
  • 本文档信息仅供参考,不构成任何要约或承诺。

发送短信示例

本示例代码为调用API发送短信,您还可以使用发送短信SDK进行短信发送。

需额外引入maven依赖,示例代码中使用了该依赖实现AK/SK签名,发送短信是调用API实现:

以下代码示例中的version值,请根据实际的SDK版本号进行替换。具体的SDK版本号请参见SDK开发中心

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

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package com.huawei.smsapi;

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 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 javax.net.ssl.SSLContext;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Map;
import java.util.Objects;

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

/**
 * Example of Invoking the batchSendSms Interface to Send an SMS Message.
 */
public class BatchSendSms {
    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();
        sendSms(ak, sk);
    }

    /**
     * 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
     */
    private static void sendSms(String ak, String sk) throws UnsupportedEncodingException {
        // This address is of Beijing 4. Replace it with the actual value.
        String uri = "https://smsapi.cn-north-4.myhuaweicloud.com:8443/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=", "8824110605***");
        appendToBody(body, "&to=", "+86137****3774");
        appendToBody(body, "&templateId=", "e1440669a4354ccdb56ebf2283c6c***");
        appendToBody(body, "&templateParas=", "[\"1\",\"2\",\"3\"]");
        appendToBody(body, "&statusCallback=", "https://test/report");
        System.out.println("body:" + body);

        // Signature operation of the batchsendsms interface
        Map<String, String> signedHeaders = sign(ak, sk, body.toString(), uri);
        if (Objects.isNull(signedHeaders)) {
            System.out.println("sign failed!");
            return;
        }

        // Print Signature Results
        System.out.println("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()));

        // 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());

            // Print the response content.
            System.out.println("Response Content: " + EntityUtils.toString(response.getEntity()));
        } catch (IOException e) {
            System.out.println("response exception:" + e);
        }
    }

    /**
     * Create an HTTP client that ignores the HTTPS certificate check.
     * @return HTTP client
     * @throws Exception
     */
    private static 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));
    }
}

发送分批短信示例

本示例代码为调用API发送分批短信,您还可以使用发送短信SDK进行短信发送。

需额外引入maven依赖,示例代码中使用了该依赖实现AK/SK签名,发送短信是调用API实现:

以下代码示例中的version值,请根据实际的SDK版本号进行替换。具体的SDK版本号请参见SDK开发中心

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

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
package com.huawei.smsapi;

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 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 javax.net.ssl.SSLContext;
import java.io.IOException;

import java.io.UnsupportedEncodingException;
import java.util.Map;
import java.util.Objects;

/**
 * Example of Invoking the batchSendDiffSms Interface to Send an SMS Message.
 */
public class BatchSendDiffSms {
    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();
        sendSmsUsingDiff(ak, sk);
    }

    /**
     * Example of Invoking the batchSendDiffSms 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
     */
    private static void sendSmsUsingDiff(String ak, String sk) throws UnsupportedEncodingException {
        // This address is of Beijing 4. Replace it with the actual value.
        String uri = "https://smsapi.cn-north-4.myhuaweicloud.com:8443/sms/batchSendDiffSms/v1";

        /*
         * Construct the message body of the sample code.
         * For details about how to construct a body, see the API description.
         * Example is:
           {
              "from": "8824110605***",
              "statusCallback": "https://test/report",
              "smsContent": [{
                  "to": ["+86137****3774", "+86137****3775"],
                  "templateId": "e1440669a4354ccdb56ebf2283c6c***",
                  "templateParas": ["1", "23", "e"]
              },
              {
                  "to": ["+86137****3777"],
                  "templateId": "e1440669a4354ccdb56ebf2283c6c***",
                  "templateParas": ["4", "5", "6"]
              }]
           }
         */
        String body = "{" +
                "    \"from\": \"8824110605***\"," +
                "    \"statusCallback\": \"https://test/report\"," +
                "    \"smsContent\": [{" +
                "        \"to\": [\"+86137****3774\", \"+86137****3775\"]," +
                "        \"templateId\": \"e1440669a4354ccdb56ebf2285666***\"," +
                "        \"templateParas\": [\"1\", \"23\", \"e\"]" +
                "    }," +
                "    {" +
                "        \"to\": [\"+86137****3777\"]," +
                "        \"templateId\": \"e1440669a4354ccdb56ebf2283c6c***\"," +
                "        \"templateParas\": [\"4\", \"5\", \"6\"]" +
                "    }]" +
                "}";
        System.out.println("body:" + body);

        // Signature operation of the batchsenddiffsms interface
        Map<String, String> signedHeaders = sign(ak, sk, body, uri);
        if (Objects.isNull(signedHeaders)) {
            System.out.println("sign failed!");
            return;
        }

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

        // Invoke /sms/batchSendDiffSms/v1 api to send messages
        HttpPost postRequest = new HttpPost(uri);
        postRequest.setHeader("Accept", "application/json");
        postRequest.setHeader("Content-Type", "application/json;charset=utf8");
        signedHeaders.forEach((key, value) -> postRequest.setHeader(key, value));
        postRequest.setEntity(new StringEntity(body.toString()));

        try (CloseableHttpResponse response = httpClient.execute(postRequest)) {
            // Print the response status code.
            System.out.println("Response Status Code: " + response.getStatusLine().getStatusCode());

            // Print the response content.
            System.out.println("Response Content: " + EntityUtils.toString(response.getEntity()));
        } catch (IOException e) {
            System.out.println("response exception:" + e);
        }
    }

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

    /**
     * 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
        return SmsAkSkSigner.sign(HttpRequest.newBuilder().withBodyAsString(body)
                        .withMethod(HttpMethod.POST)
                        .withEndpoint(endpoint)
                        .addHeader("Content-Type", "application/json;charset=utf8").build(),
                new BasicCredentials().withAk(ak).withSk(sk));
    }
}

接收状态报告

需要引入的maven依赖为:org.springframework:spring-web:5.3.21(样例版本)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class DemoController {
    /**
     * 同步短信回执
     */
    @PostMapping("/report")
    public void smsHwReport(@RequestParam String smsMsgId,  //	发送短信成功时返回的短信唯一标识。
                            @RequestParam(required = false) String total,     //	长短信拆分后的短信条数。当短信未拆分时该参数取值为1。
                            @RequestParam(required = false) String sequence,  //	长短信拆分后的短信序号,当total参数取值大于1时,该参数才有效。当短信未拆分时该参数取值为1。
                            @RequestParam String status,    //	短信状态报告枚举值,常见取值请参考“API参考”
                            @RequestParam(required = false) String source,    //	短信状态报告来源:1:短信平台自行产生的状态报告。2:短信中心返回的状态报告。3:华为平台产生的状态报告。
                            @RequestParam(required = false) String updateTime,//	短信资源的更新时间,通常为短信平台接收短信状态报告的时间,为UTC时间,格式为:yyyy-MM-dd'T'HH:mm:ss'Z',该时间会通过urlencode转义为%3a。//	当短信平台未收到短信中心上报的状态报告时,会自行构造状态报告,该状态报告中不携带“updateTime”参数。
                            @RequestParam(required = false) String orgCode,   //	透传南向网元状态码,仅国际/港澳台短信状态报告携带,国内短信不涉及。//	当南向网元未返回状态码时不携带该参数。
                            @RequestParam(required = false) String extend,    //	扩展字段,由用户在发送短信的请求中携带。若用户发送短信时未携带extend参数,则状态报告中也不会携带extend参数。
                            @RequestParam(required = false) String to) {      //	本条状态报告对应的短信的接收方号码,仅当状态报告中携带了extend参数时才会同时携带该参数。
        System.out.println("  ================receive smsStatusReport ======================");
        System.out.println("smsMsgId: " + smsMsgId);
        System.out.println("total: " + total);
        System.out.println("sequence: " + sequence);
        System.out.println("status: " + status);
        System.out.println("source: " + source);
        System.out.println("updateTime: " + updateTime);
        System.out.println("orgCode: " + orgCode);
        System.out.println("extend: " + extend);
        System.out.println("to: " + to);
    }
}

接收上行短信

需要引入的maven依赖为:org.springframework:spring-web:5.3.21(样例版本)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.PostMapping;

@RestController
public class DemoController {
     /*
     * @param smsMsgId   上行短信的唯一标识。
     * @param from       上行短信发送方的号码。
     * @param to         上行短信接收方的号码。
     * @param body       上行短信发送的内容。
     * @param createTime //	上行短信创建时间,即短信平台接收到用户发送的上行短信的时间(采用标准UTC格式,例如:2018-02-12T15:30:20Z。不同编程语言中的时间格式转换方式不同,部分语言可参考表 不同编程语言的时间格式)。
     *                   //	在控制台创建应用时配置需要“接收上行短信回复时间”后,平台才会在Body中附带此字段,该字段只对http协议的短信生效。
     */
    @PostMapping("/upSMS")
    public void receiveHwSms(@RequestParam String smsMsgId,
                             @RequestParam String from,
                             @RequestParam String to,
                             @RequestParam String body,
                             @RequestParam(required = false) String createTime) {
        System.out.println("  ================receive upSMS ======================");
        // 打印上面的RequestParam
        System.out.println("  smsMsgId: " + smsMsgId);
        System.out.println("  from: " + from);
        System.out.println("  to: " + to);
        System.out.println("  body: " + body);
        System.out.println("  createTime: " + createTime);
    }
}

相关文档