springboot连接微信公众号服务以及给前端签名

首先阅读文档
1、这个是什么意思呢,就是需要判断这个东西是不是来自于微信的,所以你需要填写你的请求的url和token(也就是密码,可以自定义的)

2、但是你保存配置肯定是失败的,因为你还需要写一个专门的请求给微信(注明是get请求),这个文档不适合我这种拿来主义的人阅读
在这里插入图片描述
java

//根据自己的习惯,我习惯是当工具类调用
import java.security.MessageDigest;
import java.util.Arrays;

public class WxUtils {

    private static final  String Token="123456";
    private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5',
            '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
    public static boolean CheckSignature(String signature, String timestamp, String nonce) {

//		1)将token、timestamp、nonce三个参数进行字典序排序
//		2)将三个参数字符串拼接成一个字符串进行sha1加密
//		3)开发者获得加密后的字符串可与signature对比,标识该请求来源于微信
        String[] strs=new String[]{Token,timestamp,nonce};

        Arrays.sort(strs);

        String str=strs[0]+strs[1]+strs[2];

        String mysignature=sha1(str);
        return mysignature.equals(signature);
    }

    private static String sha1(String str) {
        if (str == null) {
            return null;
        }
        try {
            MessageDigest messageDigest = MessageDigest.getInstance("SHA1");
            messageDigest.update(str.getBytes());
            return getFormattedText(messageDigest.digest());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static String getFormattedText(byte[] bytes) {
        int len = bytes.length;
        StringBuilder buf = new StringBuilder(len * 2);
        // 把密文转换成十六进制的字符串形式
        for (int j = 0; j < len; j++) {
            buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]);
            buf.append(HEX_DIGITS[bytes[j] & 0x0f]);
        }
        return buf.toString();
    }
}

随机字段的工具类

 /**
     * 获取随机字符串
     *
     * @param len   长度
     * @param type  类型(0=数字 1=小写字母 2=大写字母 3=大写字母+数字 4=大小写字母+数字 5=UUID)
     * @return String
     */
    public static String getRandomString(int type, int len) {
        StringBuilder sb = new StringBuilder();
        StringBuffer buffer = null;
        switch (type) {
            case 0:
                buffer = new StringBuffer("0123456789");
                break;
            case 1:
                buffer = new StringBuffer("abcdefghijklmnopqrstuvwxyz");
                break;
            case 2:
                buffer = new StringBuffer("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
                break;
            case 3:
                buffer = new StringBuffer("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ");
                break;
            case 4:
                buffer = new StringBuffer("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
                break;
            case 5:
                buffer = new StringBuffer("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
                String s = UUID.randomUUID().toString();
                sb = new StringBuilder(s);
        }
        if (StringUtils.isEmpty(buffer)) {
            return null;
        }
        if (sb.length() > len) {
            return sb.substring(0, len);
        }
        Random random = new Random();
        random.setSeed(new Date().getTime());
        int range = buffer.length();
        for (int i = 0; i < len; i++) {
            sb.append(buffer.charAt(random.nextInt(range)));
        }
        return sb.toString();
    }

json的工具类

package org.xing.wx.utils;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class JsonUtils {
    public static String toJson(Object obj) {
        Gson gson = new GsonBuilder()
            .setPrettyPrinting()
            .create();
        return gson.toJson(obj);
    }
}

config配置类信息

package org.xing.wx.config;

import org.springframework.context.annotation.Configuration;
import org.xing.wx.utils.JsonUtils;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.util.List;

@Data
@Configuration
@ConfigurationProperties(prefix = "wx.mp")
public class WxMpProperties {
    private List<MpConfig> configs;

    @Data
    public static class MpConfig {
        /**
         * 设置微信公众号的appid
         */
        private String appId;

        /**
         * 设置微信公众号的app secret
         */
        private String secret;

        /**
         * 设置微信公众号的token
         */
        private String token;

        /**
         * 设置微信公众号的EncodingAESKey
         */
        private String aesKey;
    }

    @Override
    public String toString() {
        return JsonUtils.toJson(this);
    }
}

RestTemplate的配置

package org.xing.constant.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

@Configuration
public class RestTemplateConfig {

    @Bean
    public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
        return new RestTemplate(factory);
    }

    @Bean
    public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
        SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
        factory.setReadTimeout(5000);
        factory.setConnectTimeout(5000);
        return factory;
    }
}

yml配置类信息
在这里插入图片描述
然后就是pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.7.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    
    <groupId>org.xing</groupId>
    <artifactId>xing_Warehouse</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <weixin-java-mp.version>3.5.0</weixin-java-mp.version>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <maven.compiler.encoding>UTF-8</maven.compiler.encoding>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.build.locales>zh_CN</project.build.locales>
        <java.version>1.8</java.version>
        <skipTests>true</skipTests>
    </properties>

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>com.fasterxml.jackson.core</groupId>
                    <artifactId>jackson-databind</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.2</version>
        </dependency>
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.3</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.13</version>
        </dependency>
        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>core</artifactId>
            <version>3.2.1</version>
        </dependency>
        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>javase</artifactId>
            <version>3.2.1</version>
        </dependency>


        <dependency>
            <groupId>com.github.binarywang</groupId>
            <artifactId>weixin-java-mp</artifactId>
            <version>${weixin-java-mp.version}</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <scope>provided</scope>
        </dependency>

        <!--<dependency>-->
            <!--<groupId>redis.clients</groupId>-->
            <!--<artifactId>jedis</artifactId>-->
            <!--<version>2.9.0</version>-->
        <!--</dependency>-->

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.xing.framework</groupId>
            <artifactId>xing-core</artifactId>
            <version>0.0.1</version>
        </dependency>


        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-redis</artifactId>
            <version>2.1.3.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.9.0</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

这个是控制类,关于微信的全部在这里完结*

package org.xing.controller;

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import org.xing.framework.core.utils.CommonUtils;
import org.xing.system.vo.Result;
import org.xing.system.vo.ResultUtils;
import org.xing.wx.config.WxMpProperties;
import org.xing.wx.utils.WxUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/wx")
public class WeixinController {

    private final RestTemplate restTemplate;
    private final WxMpProperties wxMpProperties;
    private final RedisTemplate redisTemplate;

    @Autowired
    public WeixinController(RestTemplate restTemplate, WxMpProperties wxMpProperties, RedisTemplate redisTemplate) {
        this.restTemplate = restTemplate;
        this.wxMpProperties = wxMpProperties;
        this.redisTemplate = redisTemplate;
    }
//来自服务端的验证(url为:http://jdmsrw.natappfree.cc/xing_Warehouse/wx/checkSignature)
    @RequestMapping("checkSignature")
    public void checkSignature(HttpServletRequest request, HttpServletResponse response)throws Exception{
        String signature = request.getParameter("signature");
        String timestamp = request.getParameter("timestamp");
        String nonce = request.getParameter("nonce");
        String echostr = request.getParameter("echostr");
        System.out.println(signature);
        System.out.println(timestamp);
        System.out.println(nonce);
        System.out.println(echostr);
        boolean checkSignature = WxUtils.CheckSignature(signature,timestamp,nonce);
        if (checkSignature) {
            System.out.println("success");
            //
            PrintWriter writer = response.getWriter();
            writer.print(echostr);
            writer.flush();
            writer.close();
        }else {
            System.out.println("failed");
        }
    }

    @RequestMapping("/wechatParam")
    public Result getWXConfigSignature(String url) {
        WxMpProperties.MpConfig config = wxMpProperties.getConfigs().get(0);
        long timeStampSec = System.currentTimeMillis() / 1000;
        String timestamp = String.format("%010d", timeStampSec);
        //随机字段
        String nonceStr = CommonUtils.getRandomString(4,16);
        //System.out.println("------------------------------------------------");
        String[] urls = url.split("#");
        String newUrl = urls[0];
        //logger.info("随机串:"+nonceStr+", 获取签名URL: " + newUrl);
        JSONObject respJson = new JSONObject();
        String wxJsapiTicket = getWXJsapiTicket(config.getAppId(), config.getSecret());
        String[] signArr = new String[]{"url=" + newUrl, "jsapi_ticket=" + wxJsapiTicket, "noncestr=" + nonceStr, "timestamp=" + timestamp};
        Arrays.sort(signArr);
        String signStr = String.join("&", signArr);
        String resSign = DigestUtils.sha1Hex(signStr);
        //logger.info("返回的签名:" + resSign);
        respJson.put("appId", config.getAppId());
        respJson.put("timestamp", timestamp);
        respJson.put("nonceStr", nonceStr);
        respJson.put("signature", resSign);
        respJson.put("url", url);
        System.out.println("appId"+"---"+config.getAppId());
        System.out.println("timestamp"+"---"+timestamp);
        System.out.println("nonceStr"+"---"+nonceStr);
        System.out.println("wxJsapiTicket"+"---"+wxJsapiTicket);
        System.out.println("signature"+"---"+resSign);
        System.out.println("url"+"---"+url);
        System.out.println("signArr"+"---"+signArr.toString());
        return ResultUtils.success(respJson);
    }

    private String getWXJsapiTicket(String appid, String secret) {
        ValueOperations valueOperations = redisTemplate.opsForValue();
        String ticket = (String) valueOperations.get(appid);
        if (Strings.isBlank(ticket)) {
            String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + getWXaccessToken(appid,secret) + "&type=jsapi";
            String resp = restTemplate.getForObject(url, String.class);
            JSONObject resJson = JSONObject.parseObject(resp);
            valueOperations.set(appid, resJson.getString("ticket"), 2, TimeUnit.HOURS);
            return resJson.getString("ticket");
        }
        return ticket;
    }
    private String getWXaccessToken(String appid, String secret) {
        String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appid + "&secret=" + secret;
        String resp = restTemplate.getForObject(url, String.class);
        JSONObject resJson = JSONObject.parseObject(resp);
        return resJson.getString("access_token");
    }
}

结构图
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值