编程技术分享平台

网站首页 > 技术教程 正文

Step by Step之最简腾讯云短信实践

xnh888 2024-11-24 00:27:20 技术教程 60 ℃ 0 评论

一个微信小程序版简化功能的商城,需要在订单流转环节增加短信提醒功能,原本都以为要整一个通用消息推送,即整合微信公众号、钉钉、短信等推送模块,后来想想现在就是一个过渡阶段,还是采用最小成本实现策略吧。因服务器托管在腾讯云,原本框架中内置实现了阿里云的短信推送,但一来功能复杂,二来也没有为其他云短信接入预留设计,所以索性就用最简化方法接入腾讯云短信,短平快一天解决战斗!

一、环境及流程概述

因短信接收功能并不涉及前端及小程序端,所以环境部分只列了后端系统。

1、部署及开发环境

(1)线上部署环境

腾讯云服务器,CentOS,JAR直接运行在云服务器上。

MySQL、Redis、XXL-Job采用Docker方式部署。

(2)开发测试环境

MAC Pro个人电脑,开发测试一体化

2、整体实现流程

(1)腾讯云短信业务开通及配置,主要包括短信业务开通、免费包申请、短信相关模板配置、接入API配置等。

(2)后端,主要包括工具类开发、业务调用代码开发及测试验证。

3、原始需求

业务部门提出,希望在小程序或后台管理端,订单流转入下一环节时,下一环节的操作员能够收到短信提示。

二、腾讯云短信业务开通及配置

因腾讯云短信产品后续升级可能调整相关流程及配置页面,以下流程及截图截至2023年11月4日有效。

Step 1.1:腾讯云开通短信产品

注意个人首次开通赠送100条国内短信,企业赠送500条。

开通后,即可按照新手配置指引进行相关配置,注意在没有配置完成且通过审核之前是无法发送短信的。

Step 1.2:创建短信签名

在“国内短信”-“签名管理”中,可以进行短信签名的列表和增删。

因为是小程序使用,所以签名类型选择“小程序”,签名内容就必须填写小程序的全称,系统会关联检查你输入的名称是否正确。

相关准备的材料有:营业执照,法人身份证,经办人身份证等信息。

注意如果是给其他公司的小程序发送短信,以上材料就变成其他公司对应的内容,而且还要第三方公司的授权委托书,更加麻烦一些。

填写完成,上报后,工作日一般2小时内会反馈通过。

记录短信签名的签名名称(注意不是Id!),在列表页中即可看到。

Step 1.3:创建短信正文模板

在“国内短信”-“正文模板管理”中,可以进行正文模板的列表和增删。

正文模板的输入就比较简单了,尤其是选择“普通短信”时,可按业务需要增加{1}、{2}等自定义参数,即在API调用时可传参数进行替换。

填写完成,上报后,审核时间比签名的要短。

记录正文模板的模板Id,在列表页中即可看到。

Step 1.4:创建或使用默认应用

开通短信业务后,在“应用管理”-“应用列表”中,会自动生成一个“默认应用”,可使用它或者创建新的应用。

核心是复制上图红框中的SDKAppID,以便在后续调用时作为参数传递。

Step 1.5:创建或使用API接入的SecretId和SecretKey

从短信控制台的“概览”页中,左下角“常用操作”的“API发送”中,点击“获取SecretId和SecretKey”即可进入“访问管理”。

或直接搜索“访问管理”产品也可。

然后,在“访问密钥”-“API密钥管理”中,可以进行密钥模板的列表和新建、禁用。

注意要记录所用密钥的SecretId和SecretKey。


小结一下Step 1.2~1.5中需要记录的内容如下:

步骤

参数名称

参数说明

Step 1.2

signName

邮件签名内容

Step 1.3

templateId

短信正文模板Id

Step 1.4

SDKAppID

短信应用Id

Step 1.5

SecretId

SecretKey

SDK接入Id

SDK接入密钥

三、后端开发工作

1、概要开发思路

(1)为了简化对接,采用云SDK接入方式,不从头写代码以API方式进行对接,因为有许多签名的复杂算法与流程,也可以减少对接调试工作量。

腾讯云帮助文档中也有详细的文档,Java SDK接入文档见链接:https://cloud.tencent.com/document/product/382/43194。

(2)在项目的通用工具包中增加一个短信发送类,封装短信发送功能,包括腾讯云的接入,对外暴露短信发送需要提供的参数。

2、具体开发步骤

Step 2.1:在Common包中的POM文件中加入腾讯云SDK的依赖包

一开始加入后,编译通不过,出来一个非常奇怪的报错,upload模块的文件找不到,想了想估计还是依赖包冲突的问题,查了腾讯文档,发现腾讯SDK依赖于okhttp 2.5.0,所以如果项目用了okhttp3,就会因为okio的版本而产生冲突。用mvntree查看,果然找到了原因,因为使用了七牛云作为图片存储和CDN,而qiniu SDK使用了okhttp3,进而使用了okio版本2.8.0。

找到问题,解决方案就简单了,在POM文件中明确依赖版本就好。

// part of pom.xml of Common package
        <dependency>
            <groupId>com.squareup.okio</groupId>
            <artifactId>okio</artifactId>
            <version>2.8.0</version>
        </dependency>
        <dependency>
            <groupId>com.tencentcloudapi</groupId>
            <artifactId>tencentcloud-sdk-java</artifactId>
            <version>3.1.572</version>
        </dependency>

Step 2.2: 在Common包中增加短信工具类

在主模块的application.yml中增加配置信息,需要替换成上面步骤得到的数据。

tengxun-sms:
  secretId: <secretId>
  secretKey: <secretKey>
  appId: <appId>
  signName: <signName>
  templateId: <templateId>

在Common包中,增加MessageUtils.java,需要注意以下几点:

(1)从application.yml中读取配置信息,到static变量,需要使用@PostConstruct及构造函数进行赋值;

(2)百度上看到过几篇腾讯短信发送案例,问题和差异有两个,一是49、50不能缺少,即还是要用HttpProfile,有几篇直接设置算法,我试了不能用;二是新版本将setSign改为了setSignName。

package com.<app>.common.util;

import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import lombok.extern.slf4j.Slf4j;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.sms.v20210111.SmsClient;
import com.tencentcloudapi.sms.v20210111.models.SendSmsRequest;
import com.tencentcloudapi.sms.v20210111.models.SendSmsResponse;
import org.checkerframework.framework.qual.PostconditionAnnotation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;

@Slf4j
@Configuration
public class MessageUtils {
    private static Logger logger = LoggerFactory.getLogger(MessageUtils.class);

    private static String TX_SECRET_ID , TX_SECRET_KEY, SMS_APP_ID, SMS_SIGN_NAME, SMS_TEMPLATE_ID;

    // configuration of tengxun cloud sms
    @Value("${tengxun-sms.secretId}")
    private String secretId;
    @Value("${tengxun-sms.secretKey}")
    private String secretKey;
    @Value("${tengxun-sms.appId}")
    private String appId;
    @Value("${tengxun-sms.signName}")
    private String signName;
    @Value("${tengxun-sms.templateId}")
    private String templateId;

    @PostConstruct
    private void init() {
        TX_SECRET_ID = secretId;
        TX_SECRET_KEY = secretKey;
        SMS_APP_ID = appId;
        SMS_SIGN_NAME = signName;
        SMS_TEMPLATE_ID = templateId;
    }

    public static Boolean sendMessage(String[] phoneNumbers, String[] tempplateParams) {
        try {
            Credential cred = new Credential(TX_SECRET_ID, TX_SECRET_KEY);
            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint("sms.tencentcloudapi.com");
            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);

            SmsClient client = new SmsClient(cred, "ap-guangzhou", clientProfile);
            SendSmsRequest sendReq = new SendSmsRequest();
            sendReq.setSmsSdkAppId(SMS_APP_ID);
            sendReq.setSignName(SMS_SIGN_NAME);
            sendReq.setTemplateId(SMS_TEMPLATE_ID);
            sendReq.setPhoneNumberSet(phoneNumbers);
            sendReq.setTemplateParamSet(tempplateParams);

            logger.info("vars is {}, {}, {}, {}, {}", TX_SECRET_ID, TX_SECRET_KEY, SMS_APP_ID, SMS_SIGN_NAME, SMS_TEMPLATE_ID);

            SendSmsResponse sendRes = client.SendSms(sendReq);

            logger.info("sms sent, response is {}", SendSmsResponse.toJsonString(sendRes));
        } catch (TencentCloudSDKException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }
}

Step 2.3:短信工具包调用

import com.yami.shop.common.util.MessageUtils;

### 其他业务代码 ###

if (!MessageUtils.sendMessage(new String[] {'13888888888'}, new String[]{})) {
	logger.info("Error sending sms to operators of next step");
}

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表