Ask me anything
Ithy Logo
Sign in to save

使用Spring Boot开发微信服务号推送短信验证码提示的完整指南

全面实现微信服务号与短信验证码功能的步骤解析

wechat service sms verification

关键要点

  • 配置微信服务号: 注册微信服务号并获取必要的认证信息。
  • 整合Spring Boot与微信SDK: 构建后端服务以处理消息交互。
  • 集成短信服务提供商: 选择并配置短信API以发送验证码。

一、配置微信服务号

1. 注册微信服务号

首先,您需要在微信公众平台上注册并创建一个服务号。注册完成后,您将获得以下重要信息:

  • AppID
  • AppSecret
  • Token
  • EncodingAESKey

2. 配置服务器URL

在微信公众平台后台,配置服务器URL以接收微信的消息推送。确保您的服务器具备公网可访问的地址,并能通过微信的验证。

示例配置


@RestController
@RequestMapping("/wechat")
public class WechatController {
    
    private final String token = "yourToken";
    private final String encodingAesKey = "yourEncodingAESKey";
    private final String appId = "yourAppId";
    
    private WxMpService wxMpService;
    
    public WechatController() {
        WxMpDefaultConfigImpl config = new WxMpDefaultConfigImpl();
        config.setToken(token);
        config.setEncodingAesKey(encodingAesKey);
        config.setAppId(appId);
        this.wxMpService = new WxMpServiceImpl();
        this.wxMpService.setWxMpConfigStorage(config);
    }
    
    @GetMapping(produces = "text/plain;charset=utf-8")
    public String authGet(@RequestParam String signature,
                          @RequestParam String timestamp,
                          @RequestParam String nonce,
                          @RequestParam String echostr) {
        if (wxMpService.checkSignature(timestamp, nonce, signature)) {
            return echostr;
        }
        return "非法请求";
    }
    
    @PostMapping(produces = "application/xml; charset=UTF-8")
    public String post(@RequestBody String requestBody,
                       @RequestParam String signature,
                       @RequestParam String timestamp,
                       @RequestParam String nonce,
                       @RequestParam(required = false) String encrypt_type,
                       @RequestParam(required = false) String msg_signature) {
        try {
            WxMpXmlMessage inMessage;
            if ("aes".equals(encrypt_type)) {
                inMessage = WxMpXmlMessage.fromEncryptedXml(requestBody, wxMpService.getWxMpConfigStorage(), timestamp, nonce, msg_signature);
            } else {
                inMessage = WxMpXmlMessage.fromXml(requestBody);
            }
            WxMpXmlOutMessage outMessage = this.route(inMessage);
            if ("aes".equals(encrypt_type)) {
                return outMessage.toEncryptedXml(wxMpService.getWxMpConfigStorage());
            } else {
                return outMessage.toXml();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }
    
    private WxMpXmlOutMessage route(WxMpXmlMessage inMessage) {
        if ("验证码".equals(inMessage.getContent())) {
            // 触发短信验证码发送逻辑
            return WxMpXmlOutMessage.TEXT()
                .content("短信验证码已发送,请查收!")
                .fromUser(inMessage.getToUser())
                .toUser(inMessage.getFromUser())
                .build();
        }
        return WxMpXmlOutMessage.TEXT()
            .content("您好,请发送“验证码”来获取短信验证码。")
            .fromUser(inMessage.getToUser())
            .toUser(inMessage.getFromUser())
            .build();
    }
}

二、Spring Boot项目配置

1. 创建Spring Boot项目

使用Spring Initializr创建一个新的Spring Boot项目,并添加以下依赖:

  • spring-boot-starter-web
  • spring-boot-starter-security
  • spring-boot-starter-data-jpa(如果需要数据库交互)
  • weixin-java-mp(微信SDK)

2. 配置application.yml


wechat:
  mp:
    app-id: yourAppId
    app-secret: yourAppSecret
    token: yourToken
    encoding-aes-key: yourEncodingAESKey
  template-id: yourTemplateId
sms:
  provider: aliyun
  access-key: yourAccessKey
  secret-key: yourSecretKey
  sign-name: yourSignName
  template-code: yourTemplateCode

3. 集成微信SDK


@Configuration
public class WechatMpConfig {
    @Value("${wechat.mp.app-id}")
    private String appId;
    
    @Value("${wechat.mp.app-secret}")
    private String appSecret;
    
    @Value("${wechat.mp.token}")
    private String token;
    
    @Value("${wechat.mp.encoding-aes-key}")
    private String encodingAesKey;
    
    @Bean
    public WxMpService wxMpService() {
        WxMpDefaultConfigImpl config = new WxMpDefaultConfigImpl();
        config.setAppId(appId);
        config.setSecret(appSecret);
        config.setToken(token);
        config.setAesKey(encodingAesKey);
        
        WxMpService service = new WxMpServiceImpl();
        service.setWxMpConfigStorage(config);
        return service;
    }
}

三、集成短信服务

1. 选择短信服务提供商

常见的短信服务提供商包括阿里云、腾讯云等。根据需求选择合适的提供商,并获取API密钥。

2. 配置短信服务

以下是集成阿里云短信服务的示例:

Maven依赖


<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-core</artifactId>
    <version>4.5.3</version>
</dependency>
<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-dysmsapi</artifactId>
    <version>1.0.0</version>
</dependency>

短信服务配置类


@Service
public class SmsService {
    
    @Value("${sms.access-key}")
    private String accessKey;
    
    @Value("${sms.secret-key}")
    private String secretKey;
    
    @Value("${sms.sign-name}")
    private String signName;
    
    @Value("${sms.template-code}")
    private String templateCode;
    
    public boolean sendSmsCode(String phoneNumber, String code) {
        DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKey, secretKey);
        IAcsClient client = new DefaultAcsClient(profile);
        
        SendSmsRequest request = new SendSmsRequest();
        request.setPhoneNumbers(phoneNumber);
        request.setSignName(signName);
        request.setTemplateCode(templateCode);
        request.setTemplateParam("{\"code\":\"" + code + "\"}");
        
        try {
            SendSmsResponse response = client.getAcsResponse(request);
            return "OK".equals(response.getCode());
        } catch (ClientException e) {
            e.printStackTrace();
            return false;
        }
    }
}

四、实现短信验证码发送逻辑

1. 生成验证码

验证码通常为6位数字,可以通过以下工具类实现:


public class VerificationCodeUtils {
    public static String generateCode(int length) {
        Random random = new Random();
        StringBuilder sb = new StringBuilder();
        for(int i=0; i<length; i++) {
            sb.append(random.nextInt(10));
        }
        return sb.toString();
    }
}

2. 存储验证码

为了验证用户输入,需将验证码临时存储在服务器端,如Redis:


@Service
public class VerificationService {
    
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    
    public void storeCode(String phoneNumber, String code) {
        redisTemplate.opsForValue().set("sms:code:" + phoneNumber, code, 5, TimeUnit.MINUTES);
    }
    
    public boolean verifyCode(String phoneNumber, String inputCode) {
        String storedCode = redisTemplate.opsForValue().get("sms:code:" + phoneNumber);
        return inputCode != null && inputCode.equals(storedCode);
    }
}

3. 发送验证码并推送消息


@Service
public class WechatMessageService {
    
    @Autowired
    private WxMpService wxMpService;
    
    @Autowired
    private SmsService smsService;
    
    @Autowired
    private VerificationService verificationService;
    
    public boolean sendVerificationCodeMessage(String openId, String phoneNumber) {
        String code = VerificationCodeUtils.generateCode(6);
        verificationService.storeCode(phoneNumber, code);
        boolean smsSent = smsService.sendSmsCode(phoneNumber, code);
        if(smsSent) {
            WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder()
                .toUser(openId)
                .templateId("yourTemplateId")
                .data(Arrays.asList(
                    new WxMpTemplateData("code", code, "#FF0000")
                ))
                .build();
            try {
                wxMpService.getTemplateMsgService().sendTemplateMsg(templateMessage);
                return true;
            } catch (WxErrorException e) {
                e.printStackTrace();
            }
        }
        return false;
    }
}

五、安全性与优化

1. 限制验证码发送频率

避免用户频繁请求验证码,可以通过Redis设置发送间隔:


public boolean canSendCode(String phoneNumber) {
    Boolean exists = redisTemplate.hasKey("sms:sent:" + phoneNumber);
    if(Boolean.TRUE.equals(exists)) {
        return false;
    }
    redisTemplate.opsForValue().set("sms:sent:" + phoneNumber, "sent", 1, TimeUnit.MINUTES);
    return true;
}

2. 验证码输入限制

限制用户输入验证码的次数,防止暴力破解:


public boolean verifyCodeWithLimit(String phoneNumber, String inputCode) {
    String key = "sms:attempts:" + phoneNumber;
    Integer attempts = redisTemplate.opsForValue().get(key) != null ? Integer.parseInt(redisTemplate.opsForValue().get(key)) : 0;
    if(attempts >= 5) {
        return false;
    }
    boolean isValid = verifyCode(phoneNumber, inputCode);
    if(!isValid) {
        redisTemplate.opsForValue().increment(key, 1);
        redisTemplate.expire(key, 10, TimeUnit.MINUTES);
    }
    return isValid;
}

3. 数据加密传输

确保所有敏感数据在传输过程中采用加密方式,使用HTTPS协议保护数据安全。


六、测试与部署

1. 本地测试

使用内网穿透工具如Ngrok,将本地服务暴露到公网,配置微信服务器URL进行测试。

2. 部署到服务器

选择可靠的云服务提供商,将Spring Boot应用部署到生产环境,确保高可用性和稳定性。

3. 监控与日志

设置日志监控,实时监控系统运行状态,及时发现并解决问题。


七、示例代码汇总

1. 完整控制器示例


@RestController
@RequestMapping("/wechat")
public class WechatController {
    
    @Autowired
    private WechatMessageService wechatMessageService;
    
    @GetMapping(produces = "text/plain;charset=utf-8")
    public String authGet(@RequestParam String signature,
                          @RequestParam String timestamp,
                          @RequestParam String nonce,
                          @RequestParam String echostr) {
        // 微信验证逻辑
    }
    
    @PostMapping(produces = "application/xml; charset=UTF-8")
    public String post(@RequestBody String requestBody,
                       @RequestParam String signature,
                       @RequestParam String timestamp,
                       @RequestParam String nonce,
                       @RequestParam(required = false) String encrypt_type,
                       @RequestParam(required = false) String msg_signature) {
        // 消息处理逻辑
    }
    
    private WxMpXmlOutMessage route(WxMpXmlMessage inMessage) {
        if ("验证码".equals(inMessage.getContent())) {
            String phoneNumber = getPhoneNumberByOpenId(inMessage.getFromUser());
            if(phoneNumber != null && wechatMessageService.sendVerificationCodeMessage(inMessage.getFromUser(), phoneNumber)) {
                return WxMpXmlOutMessage.TEXT()
                    .content("短信验证码已发送,请查收!")
                    .fromUser(inMessage.getToUser())
                    .toUser(inMessage.getFromUser())
                    .build();
            } else {
                return WxMpXmlOutMessage.TEXT()
                    .content("验证码发送失败,请稍后再试。")
                    .fromUser(inMessage.getToUser())
                    .toUser(inMessage.getFromUser())
                    .build();
            }
        }
        return WxMpXmlOutMessage.TEXT()
            .content("您好,请发送“验证码”来获取短信验证码。")
            .fromUser(inMessage.getToUser())
            .toUser(inMessage.getFromUser())
            .build();
    }
}

2. 短信发送服务示例


@Service
public class SmsService {
    
    @Value("${sms.access-key}")
    private String accessKey;
    
    @Value("${sms.secret-key}")
    private String secretKey;
    
    @Value("${sms.sign-name}")
    private String signName;
    
    @Value("${sms.template-code}")
    private String templateCode;
    
    public boolean sendSmsCode(String phoneNumber, String code) {
        // 阿里云短信发送逻辑
    }
}

3. 短信验证码生成与验证


@Service
public class VerificationService {
    
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    
    public void storeCode(String phoneNumber, String code) {
        redisTemplate.opsForValue().set("sms:code:" + phoneNumber, code, 5, TimeUnit.MINUTES);
    }
    
    public boolean verifyCode(String phoneNumber, String inputCode) {
        String code = redisTemplate.opsForValue().get("sms:code:" + phoneNumber);
        return inputCode != null && inputCode.equals(code);
    }
}

八、功能概览表

功能模块 描述 技术/工具
微信服务号配置 注册并配置微信服务号,获取认证信息 微信公众平台
Spring Boot集成 建立后端服务处理微信消息 Spring Boot, weixin-java-mp
短信服务集成 发送短信验证码给用户 阿里云短信API
验证码管理 生成、存储和验证短信验证码 Redis
安全性措施 限制发送频率和输入次数,确保安全 Spring Security, Redis
部署与监控 将应用部署到生产环境并进行监控 云服务器, 日志监控工具

九、结论

通过以上步骤,您可以成功使用Spring Boot开发一个微信服务号,实现向用户推送短信验证码的功能。关键在于正确配置微信服务号、整合短信服务提供商以及确保系统的安全性和稳定性。完善的验证码管理和安全措施将有效提升用户体验并保障系统安全。

参考资料

blog.csdn.net
CSDN Blog
blog.csdn.net
CSDN QQ Blog
codeease.top
CodeEase Blog
showapi.com
ShowAPI News
juejin.cn
Juejin Post
sfcboost.com
SFCBoost Blog
gavin-yyj.github.io
Gavin's Blog
ihuyi.com
iHuyi Baike

Last updated February 8, 2025

AI-assisted research. Sources, methodology and corrections · Source-checked guides and tools · Explore published answers

Ask Ithy AI