微信公众号之验证码推送(spring-boot+测试号)

2,748 阅读3分钟

根据此文可以实现简单的微信公众号验证码推送功能。

一、验证码推送使用场景

传统的验证码可以防止恶意攻击、以及防止网络爬虫。但是无论验证码设计的有多复杂,也可以通过智能算法破解。也许有人会想到手机验证码,手机验证码的确可以解决上述问题,但是如果你的系统用户存在海外用户,此项功能就被限制,所以使用微信公众号推送验证码是个非常不错的选择。

二、测试号中消息模板的搭建

  1. 想要实现验证码推送必须使用消息模板,但是订阅号想要使用消息模板必须要认证,所以这里选择了测试号,测试号申请过程如下: a.进入自己的公众号页面拉到最下面 image.png image.png b.找到消息模板选项 image.png
  2. 配置消息模板 注:其中变量必须用{{}}包裹起来、变量名后必须加.DATA否则得不到值。例:{{code.DATA}} image.png
  3. 至此微信公众平台基本已经搭建好了,以下信息是我们在服务端需要用到的。 a. appID wx5fc55e59461**** b. appsecret a8ae4637b095*df c. 模板id jerVx-******

三、服务端环境搭建

服务端我们使用weixin-java-mp框架,此框架封装了支付、认证等众多方法。

<dependency>
			<groupId>com.github.binarywang</groupId>
			<artifactId>weixin-java-mp</artifactId>
			<version>2.7.0</version>
</dependency>
  1. 在application.yml配置app-id和app-secret以认证此测试号,相对应的建立微信配置的相关的类。
wx:
  app-id: *******
  app-secret: ****
server:
  port: 80

1.1 微信账号配置类WxAccountConfig.class

@Component
@ConfigurationProperties("wx")
public class WxAccountConfig {
	// 公众号ID
	private String appId;
	// 公众号secret
	private String appSecret;

	public String getAppId() {
		return appId;
	}

	public void setAppId(String appId) {
		this.appId = appId;
	}

	public String getAppSecret() {
		return appSecret;
	}

	public void setAppSecret(String appSecret) {
		this.appSecret = appSecret;
	}

}

1.2 微信配置类,此类作用将appid等设置到封装的WxMpService 和 WxMpConfigStorage中。

@Configuration
public class WxConfig {

	@Autowired
	private WxAccountConfig wxAccountConfig;

	@Bean
	public WxMpService wxMpService() {
		WxMpService wxMpService = new WxMpServiceImpl();
		wxMpService.setWxMpConfigStorage(wxMpConfigStorage());
		return wxMpService;
	}

	@Bean
	public WxMpConfigStorage wxMpConfigStorage() {
		WxMpInMemoryConfigStorage wxMpConfigStorage = new WxMpInMemoryConfigStorage();
		// 在这里我们要设置appid 和 appsecret 需要在配置文件里面设置两个变量,这样全局都可以用
		// 然后设置一个WexAccountConfig类,来注入这两个参数,这样在使用的时候就可以直接调用这两个类
		wxMpConfigStorage.setAppId(wxAccountConfig.getAppId());
		wxMpConfigStorage.setSecret(wxAccountConfig.getAppSecret());
		wxMpConfigStorage.setAccessToken("wangyu");
		return wxMpConfigStorage;
	}

}
  1. 新建推送消息的Service接口和实现,这里只贴出实现。
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
	@Autowired
    private WxMpService wxMpService;
	
	@Override
	public void returnVerficationCode(String receiveId) {
		 //模板消息封装的对象
        WxMpTemplateMessage wxMpTemplateMessage = new WxMpTemplateMessage();
        //消息模板ID
        wxMpTemplateMessage.setTemplateId(WxConfigConstant.VERFICATION_CODE_TEMPLATE_ID);
        wxMpTemplateMessage.setToUser(receiveId);
        wxMpTemplateMessage.setData(wrapperTemplateData());
        try {
            wxMpService.getTemplateMsgService().sendTemplateMsg(wxMpTemplateMessage);
        }catch (WxErrorException errorException){
        	logger.error("推送出现错误!" );
        }
	}
	
	/**
	 *  得到验证码封装数据
	 * @return
	 */
	private List<WxMpTemplateData> wrapperTemplateData(){
		//得到4为验证码
		String code = VerficationCodeUtils.getVerficationCode(4);
		List<WxMpTemplateData> wxMpTemplateData = new ArrayList<>();
		wxMpTemplateData.add(new WxMpTemplateData("code",code));
		wxMpTemplateData.add(new WxMpTemplateData("validity",WxConfigConstant.VERFICATION_CODE_VALIDITY_TIME));
		return wxMpTemplateData;
	}

注:如想设置字体颜色,则需使用此构造方法WxMpTemplateData(String name, String value, String color) 3. 新建推送消息的Controller,userId为关注公众号的openId。

        @ResponseBody
	@RequestMapping(value = "/sendVertficationCode", produces = { "application/json;charset=utf-8" })
	public String sendVertficationCode(HttpServletRequest request, @RequestParam(required = true) String echostr,
			@RequestParam String userId) {
//    	userId = o3FqD1sJQdv0oQz_dEPvbgk3AFbE;
		pushMessageService.returnVerficationCode(userId);
		return echostr;
	}
  1. 贴上生成验证码的工具类
public class VerficationCodeUtils {
	
	private static final String SYMBOLS = "0123456789"; // 数字
	private static final Random RANDOM = new SecureRandom();
	
	/**
	 *  生成指定位数的数字验证码
	 * @return
	 */
	public static String getVerficationCode(int length) {
		
		// 如果需要4位,那 new char[4] 即可,其他位数同理可得
		char[] nonceChars = new char[length];
		
		for (int index = 0; index < nonceChars.length; ++index) {
			nonceChars[index] = SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length()));
		}
		return new String(nonceChars);
	}
	
}

四、实现验证码推送至公众号

我们再次打开我们测试号页面,如使用的本机搭建的环境,可以使用内网穿透工具,我这里使用的是natapp,里面有教程,非常方便。URL填写刚才Controller中可以访问的地址记得加上userId,Token要和wxMpConfigStorage.setAccessToken()一致,点击提交,现在你的公众号就收到验证码了。 image.png