首先阅读文档
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");
}
}
结构图