草庐IT

阿里云短信服务详细说明与实战开发后端代码

是谢添啊 2023-09-07 原文

文章目录

1.短信服务背景

目前在很多项目中都出现使用短信验证码来实现注册、登录、购买、支付、转账等功能,发短信功能几乎已经成为项目中不可或缺的技术之一。

2.短信发送流程

短信平台与运营商之间协同合作,利益分成。

短信发送流程通常涉及以下步骤:

  1. Java程序调用短信平台提供的API接口,将短信内容、接收手机号等参数发送给短信平台。
  2. 短信平台接收到请求后,进行身份验证和参数校验,验证通过后将短信内容提交给运营商的短信网关。
  3. 运营商的短信网关接收到短信内容后,进行短信内容的编码和协议转换,将短信内容转换为符合运营商要求的协议格式。
  4. 短信网关将短信发送到接收方手机所在的基站,再由基站转发到手机上。
  5. 接收方手机接收到短信后进行解码和显示。

需要注意的是,由于短信平台和运营商之间的协议和接口是不透明的,因此在实际使用中,需要根据具体的短信平台和运营商提供的文档和接口规范来实现短信发送功能。同时,也需要根据运营商的要求和规定进行短信内容的审核和审核通过后的定时发送等操作。

3.阿里云短信服务基本说明

这里只针对于国内短信验证码进行说明。

3.1 开通阿里云短信服务与购买短信套餐包

开通服务是免费的,短信套餐包可购买也可选择试用。

🏠 新用户试用地址:阿里云通信产品免费试用 (aliyun.com)

🏠 普通用户购买地址:短信服务_企业短信营销推广_验证码通知-阿里云 (aliyun.com)

3.2 短信服务帮助文档

🏠 短信服务 (aliyun.com)

3.3 手机短信模板介绍

3.3.1 基本说明

短信模版内容是由国家工信部制定,模版内容必须得有国家工信部进行审核,短信模版包含两部分:

  1. 短信签名:【XXXX】,例如:【逐浪教育】
  2. 短信正文,例如 “您正在进行登录校验,验证码为 ${code} ,该验证码5分钟内有效,请勿泄露于他人。

3.3.2 公共内容规范

🏠 公共内容规范 (aliyun.com)

3.3.3 验证码模板规范

🍀 内容规范

  • 国内短信模板必须包含“验证码、注册码、校验码、动态码(动态密码)”中的任意一个。
  • 模板必须体现和说明“使用平台、用途、失效时间”中的任意一种。
  • 为提升发送成功率,建议在模板中去除退订方式、与验证码无关的电话号码等信息。

🍀 变量规范

  • 验证码模板的变量属性建议选择仅数字
  • 验证码模板仅支持添加一个变量。
  • 自定义测试类模板仅支持数字变量。
  • 变量长度限制为4~6个字符,仅数字、数字+字母组合或仅字母,例如:12CDE。

3.3.4 短信签名规范

🏠 短信签名规范 (aliyun.com)

说明几个重要通知:

  • 签名名称不区分大小写字母,如【Aliyun通信】和【aliyun通信】视为名称相同。
  • 国内短信签名暂不支持繁体字;不支持中文、英文以外的其它语言。
  • 短信签名来源如果选择了公众号或小程序,暂不支持以个人名义认证的小程序或公众号。
  • 短信签名来源如果选择了测试或学习,发送会有限制,指的是不能申请带变量的通知模板,不能申请推广模板,且只能给绑定的手机号发送短信。

3.3.5 验证码模板示例

您可以参考下表示例,并根据实际业务需求创建符合规范的短信模板。

应用场景模板示例
登录/验证您的验证码${code},该验证码5分钟内有效,请勿泄漏于他人!
您的验证码:${code},您正进行身份验证,打死不告诉别人!
验证码为:${code},您正在登录,若非本人操作,请勿泄露。
注册您正在申请手机注册,验证码为:${code},5分钟内有效!
尊敬的用户,您的注册会员动态密码为:${code},请勿泄漏于他人!
您的注册码:${code},如非本人操作,请忽略本短信!
您的校验码:${code},您正在注册成为会员,感谢您的支持!
验证码为:${code},您正在注册成为平台会员,感谢您的支持!
重置密码您的动态码为:${code},您正在进行密码重置操作,如非本人操作,请忽略本短信!
变更信息验证码为:${code},您正在尝试变更重要信息,请妥善保管账户信息。

3.4 国内短信服务定价

3.4.1 按量付费

根据短信的发送条数和短信模板类型进行实时梯度计费。即实时计费,自动跨档,跨档后当月所有发送量按新阶梯价重新计算。

  • 若用户当月验证码短信+通知短信使用量为N条,N>300万,则当月费用=N * 0.036。
  • 若用户当月推广短信使用量为N条,50万<N≤100万,则当月费用=N * 0.048。

3.4.2 国内短信套餐包

  • 为了降低用户的使用成本,阿里云短信服务提供国内短信套餐包,支持发送验证码短信通知推广短信三种类型。个人认证用户仅可使用验证码、短信通知,不可使用推广短信。您可以升级为企业认证用户体验相关功能。更多信息,请参见使用须知
  • 国内短信套餐包仅可用于国内文本短信服务,不可用于国际/港澳台短信服务。
  • 如果购买了套餐包,使用短信服务时优先抵用套餐包中的数量,超出部分自动按量付费。
  • 购买套餐包之前产生的短信发送量,自动按量付费。
  • 套餐包在账户欠费时不可使用,已使用套餐包剩余资源不支持退订或延期。其它退款内容,请参见退款说明

套餐包的具体计费,请参见国内通用短信套餐包

3.5 短信发送规则

3.5.1 国内短信内容长度计算规则

**短信长度(字数)=短信签名字数+短信模板内容字数。**其中,短信模板字数上限为500字。

  • 简体中文、字母、数字、标点符号(不区分全角和半角),都按照一个字计算。

    为避免与签名混淆,在模板内容任意位置均不能使用【】,在模板内容首尾不能使用[ ]。

  • 短信长度不超过70个字,按照一条短信计费;超过70个字,即为长短信,按照67字/条拆分成多条计费。

  • 📝 示例:短信长度为160个字,按照67字、67字、26字分隔成三条短信进行计费。

3.5.2 短信发送频率限制

在实际业务场景中,例如App或网站登录时,可能会有用户频繁获取短信验证码或者通过短信通知方式找回密码的操作。为了限制平台短信被恶意调用、在短时间内大量发起短信发送请求,阿里云对短信发送验证码的行为进行了流控限制。

  • 使用同一个签名,默认情况下对同一个手机号码发送验证码,最多支持1条/分钟,5条/小时,10条/天。仅企业认证用户可设置验证码短信发送频率。具体操作指引,请参见设置短信发送频率和频率限制白名单
  • 企业用户通过阿里云短信服务平台对同一个手机号码发送验证码,最多支持40条/天。此天级流控限制是针对手机号码这一维度进行的,即使短信发送方有多个,只要发送方使用阿里云短信服务平台,同一个手机号码一天只能接收40条验证码。

4.用户与用户组权限管理

4.1 进入管理控制台

4.2 创建用户组

4.3 创建子用户

注意这个 AccessKey IDAccessKey Secret 一定要保存下来,后面需要使用并且关闭该页面后无法再获取 AccessKey Secret

4.4 添加子用户到用户组

4.5 用户组权限管理

我们在这里只添加 短信服务 的权限。

5.添加签名

前提条件:

这里以签名来源为测试或学习进行演示,并注意 个人认证用户限申请一个验证码签名,一个自然日只能申请一个通用签名。如需申请多个签名,建议升级为企业认证用户。

通着这个需要两三小时左右,因此等这一步被通过了再进行接下来的操作。

6.添加模板

通着这个需要两三小时左右,因此等这一步被通过了再进行接下来的操作。

7.绑定测试手机号

由于我们这里指定的短信签名来源是测试或学习,因此只有绑定了的手机号才能收到短信消息。

8.在线测试签名模板API

查看绑定的手机,可以接受到消息:

9.自主测试Java SDK

8.在线测试签名模板API 中屏幕右边的代码进行拷贝自己运行即可:

<dependency>
  <groupId>com.aliyun</groupId>
  <artifactId>alibabacloud-dysmsapi20170525</artifactId>
  <version>2.0.23</version>
</dependency>
// This file is auto-generated, don't edit it. Thanks.
package demo;

import com.aliyun.auth.credentials.Credential;
import com.aliyun.auth.credentials.provider.StaticCredentialProvider;
import com.aliyun.core.http.HttpClient;
import com.aliyun.core.http.HttpMethod;
import com.aliyun.core.http.ProxyOptions;
import com.aliyun.httpcomponent.httpclient.ApacheAsyncHttpClientBuilder;
import com.aliyun.sdk.service.dysmsapi20170525.models.*;
import com.aliyun.sdk.service.dysmsapi20170525.*;
import com.google.gson.Gson;
import darabonba.core.RequestConfiguration;
import darabonba.core.client.ClientOverrideConfiguration;
import darabonba.core.utils.CommonUtil;
import darabonba.core.TeaPair;

//import javax.net.ssl.KeyManager;
//import javax.net.ssl.X509TrustManager;
import java.net.InetSocketAddress;
import java.time.Duration;
import java.util.*;
import java.util.concurrent.CompletableFuture;

public class SendSms {
    public static void main(String[] args) throws Exception {

        // HttpClient Configuration
        /*HttpClient httpClient = new ApacheAsyncHttpClientBuilder()
                .connectionTimeout(Duration.ofSeconds(10)) // Set the connection timeout time, the default is 10 seconds
                .responseTimeout(Duration.ofSeconds(10)) // Set the response timeout time, the default is 20 seconds
                .maxConnections(128) // Set the connection pool size
                .maxIdleTimeOut(Duration.ofSeconds(50)) // Set the connection pool timeout, the default is 30 seconds
                // Configure the proxy
                .proxy(new ProxyOptions(ProxyOptions.Type.HTTP, new InetSocketAddress("<your-proxy-hostname>", 9001))
                        .setCredentials("<your-proxy-username>", "<your-proxy-password>"))
                // If it is an https connection, you need to configure the certificate, or ignore the certificate(.ignoreSSL(true))
                .x509TrustManagers(new X509TrustManager[]{})
                .keyManagers(new KeyManager[]{})
                .ignoreSSL(false)
                .build();*/

        // Configure Credentials authentication information, including ak, secret, token
        StaticCredentialProvider provider = StaticCredentialProvider.create(Credential.builder()
                .accessKeyId("<your-accessKeyId>")
                .accessKeySecret("<your-accessKeySecret>")
                //.securityToken("<your-token>") // use STS token
                .build());

        // Configure the Client
        AsyncClient client = AsyncClient.builder()
                .region("cn-wulanchabu") // Region ID
                //.httpClient(httpClient) // Use the configured HttpClient, otherwise use the default HttpClient (Apache HttpClient)
                .credentialsProvider(provider)
                //.serviceConfiguration(Configuration.create()) // Service-level configuration
                // Client-level configuration rewrite, can set Endpoint, Http request parameters, etc.
                .overrideConfiguration(
                        ClientOverrideConfiguration.create()
                                .setEndpointOverride("dysmsapi.aliyuncs.com")
                        //.setConnectTimeout(Duration.ofSeconds(30))
                )
                .build();

        // Parameter settings for API request
        SendSmsRequest sendSmsRequest = SendSmsRequest.builder()
                .signName("逐浪教育")
                .templateCode("SMS_275395309")
                .phoneNumbers("18670082846")
                .templateParam("{\"code\":\"1234\"}")
                // Request-level configuration rewrite, can set Http request parameters, etc.
                // .requestConfiguration(RequestConfiguration.create().setHttpHeaders(new HttpHeaders()))
                .build();

        // Asynchronously get the return value of the API request
        CompletableFuture<SendSmsResponse> response = client.sendSms(sendSmsRequest);
        // Synchronously get the return value of the API request
        SendSmsResponse resp = response.get();
        System.out.println(new Gson().toJson(resp));
        // Asynchronous processing of return values
        /*response.thenAccept(resp -> {
            System.out.println(new Gson().toJson(resp));
        }).exceptionally(throwable -> { // Handling exceptions
            System.out.println(throwable.getMessage());
            return null;
        });*/

        // Finally, close the client
        client.close();
    }

}

10.⭐前后端实战开发-发送短信验证码

10.1 流程分析

10.2 配置参数说明

sms:
  ali:
    # 子用户的访问键
    accessKeyId: LTAI5tPBmf8y7ZoQSn9h****
    # 子用户的访问密钥
    accessKeySecret: cbd511ed24bd832d05af54f64c84****
    # 签名名称
    signName: 逐浪教育
    # 登录短信模板的code
    loginTemplateCode: SMS_27539****

10.2.1 访问键与密钥

就是在 4.3 创建子用户 中得到的 accessKeyId 与 accessKeySecret

10.2.2 签名名称

就是在 5.添加签名 中设置的签名内容。

10.2.3 登录短信模板code

10.3 🚀 后端代码

由于demo代码过多,这里不做展示。

实战demo源码地址:Mr-Write/SpringbootDemo: 各种demo案例 (github.com)

对应的是 sms-demo 包模块。

🍀 示例演示,用 Apipost7 进行测试:【POST】 http://127.0.0.1:10505/sms-ali/sendLoginCode

同时在我的手机上也接受到了验证码消息。

10.4 补充说明

10.4.1 调用 api 后响应的返回数据

名称类型描述示例
CodeString请求状态码。返回OK代表请求成功。其他错误码,请参见[API错误码](https://help.aliyun.com/document_detail/101346.html?spm=api-workbench.API Document.0.0.5be349a5PlzN8a)。OK
MessageString状态码的描述。OK
BizIdString发送回执ID。可根据发送回执ID在接口QuerySendDetails中查询具体的发送状态。9006197469364984****
RequestIdString请求ID。F655A8D5-B967-440B-8683-DAD6FF8DE990

正常返回的JSON格式示例

{
  "Code": "OK",
  "Message": "OK",
  "BizId": "9006197469364984****",
  "RequestId": "F655A8D5-B967-440B-8683-DAD6FF8DE990"
}

10.4.2 application.yml 文件中的配置需要进行修改。

  • redis 地址
  • redis 密码
  • 短信平台信息

10.4.3 ubuntu安装docker的步骤

  1. 安装需要的包

    sudo apt-get update
    
  2. 安装依赖包

    sudo apt-get install \
       apt-transport-https \
       ca-certificates \
       curl \
       gnupg-agent \
       software-properties-common
    
  3. 添加 Docker 的官方 GPG 密钥

    curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
    
  4. 设置远程仓库

    sudo add-apt-repository \
       "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
      $(lsb_release -cs) \
      stable"
    
  5. 安装 Docker-CE

    sudo apt-get update
    
    sudo apt-get install docker-ce docker-ce-cli containerd.io
    
  6. 验证是否成功

    sudo docker run hello-world
    

10.4.4 使用 docker 安装redis并设置密码的步骤

# 拉取redis镜像
docker pull redis

# 启动容器的时候,并为其设置密码
docker run -d --name myredis -p 6379:6379 redis --requirepass "123456"

10.4.5 其它注意事项

注意需要将服务器防火墙6379端口打开。

有关阿里云短信服务详细说明与实战开发后端代码的更多相关文章

  1. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  2. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  3. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  4. ruby-on-rails - Rails 源代码 : initialize hash in a weird way? - 2

    在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has

  5. ruby - 使用 C 扩展开发 ruby​​gem 时,如何使用 Rspec 在本地进行测试? - 2

    我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当

  6. ruby-on-rails - 启动 Rails 服务器时 ImageMagick 的警告 - 2

    最近,当我启动我的Rails服务器时,我收到了一长串警告。虽然它不影响我的应用程序,但我想知道如何解决这些警告。我的估计是imagemagick以某种方式被调用了两次?当我在警告前后检查我的git日志时。我想知道如何解决这个问题。-bcrypt-ruby(3.1.2)-better_errors(1.0.1)+bcrypt(3.1.7)+bcrypt-ruby(3.1.5)-bcrypt(>=3.1.3)+better_errors(1.1.0)bcrypt和imagemagick有关系吗?/Users/rbchris/.rbenv/versions/2.0.0-p247/lib/ru

  7. ruby-on-rails - s3_direct_upload 在生产服务器中不工作 - 2

    在Rails4.0.2中,我使用s3_direct_upload和aws-sdkgems直接为s3存储桶上传文件。在开发环境中它工作正常,但在生产环境中它会抛出如下错误,ActionView::Template::Error(noimplicitconversionofnilintoString)在View中,create_cv_url,:id=>"s3_uploader",:key=>"cv_uploads/{unique_id}/${filename}",:key_starts_with=>"cv_uploads/",:callback_param=>"cv[direct_uplo

  8. Ruby Sinatra 配置用于生产和开发 - 2

    我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm

  9. ruby-on-rails - 浏览 Ruby 源代码 - 2

    我的主要目标是能够完全理解我正在使用的库/gem。我尝试在Github上从头到尾阅读源代码,但这真的很难。我认为更有趣、更温和的踏脚石就是在使用时阅读每个库/gem方法的源代码。例如,我想知道RubyonRails中的redirect_to方法是如何工作的:如何查找redirect_to方法的源代码?我知道在pry中我可以执行类似show-methodmethod的操作,但我如何才能对Rails框架中的方法执行此操作?您对我如何更好地理解Gem及其API有什么建议吗?仅仅阅读源代码似乎真的很难,尤其是对于框架。谢谢! 最佳答案 Ru

  10. ruby - 是否可以覆盖 gemfile 进行本地开发? - 2

    我们的git存储库中目前有一个Gemfile。但是,有一个gem我只在我的环境中本地使用(我的团队不使用它)。为了使用它,我必须将它添加到我们的Gemfile中,但每次我checkout到我们的master/dev主分支时,由于与跟踪的gemfile冲突,我必须删除它。我想要的是类似Gemfile.local的东西,它将继承从Gemfile导入的gems,但也允许在那里导入新的gems以供使用只有我的机器。此文件将在.gitignore中被忽略。这可能吗? 最佳答案 设置BUNDLE_GEMFILE环境变量:BUNDLE_GEMFI

随机推荐