Skip to content

Commit

Permalink
初始化提交
Browse files Browse the repository at this point in the history
  • Loading branch information
HikariShine committed Dec 3, 2018
1 parent 7d28b9a commit c7d1650
Show file tree
Hide file tree
Showing 7 changed files with 273 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,6 @@

# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
.idea
target
*.iml
36 changes: 36 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?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>

<groupId>com.mxixm.spring</groupId>
<artifactId>boot-weixin</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>

<name>boot Maven Webapp</name>
<url>http://www.mxixm.com</url>

<!--Spring Boot项目需要指定的父项目-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.2.RELEASE</version>
</parent>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>

<dependencies>
<!--Spring Boot Web项目的starter包,Web项目引入此包-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>

</project>
13 changes: 13 additions & 0 deletions src/main/java/com/mxixm/spring/boot/weixin/Starter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.mxixm.spring.boot.weixin;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Starter {
// 启动入口,Java原生启动入口
public static void main(String[] args) {
SpringApplication.run(Starter.class, args);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* Copyright (c) 2016-2018, Guangshan ([email protected]) and the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.mxixm.spring.boot.weixin.core;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.time.Instant;

// 标记为Spring的Bean组件
@Component
public class WxAccessTokenManager implements InitializingBean {
// 注入配置的appId值
@Value("${wx.appId}")
private String appId;
// 注入配置的appSecret值
@Value("${wx.appSecret}")
private String appSecret;
// 用于发起Http请求的RestTemplate
private RestTemplate restTemplate;
// 上一次刷新时间
private long lastRefreshTime;
// 保存的AccessToken
private String accessToken;
// 初始化方法
@Override
public void afterPropertiesSet() throws Exception {
restTemplate = new RestTemplate();
// 启动时先初始化一次AccessToken提高后续访问速度
this.get();
}
// 获取AccessToken方法
public String get() {
long now = Instant.now().toEpochMilli();
// 如果当前已过期,默认一次获取7200000毫秒后过期
if (now > lastRefreshTime + 7200000) {
// 从接口获取AccessToken,更新当前内存维护的AccessToken
accessToken = this.fetchAccessToken();
// 更新上次刷新时间
lastRefreshTime = now;
}
// 返回AccessToken,未过期直接返回
return accessToken;
}
// 从接口获取AccessToken值
public String fetchAccessToken() {
// 构造请求地址
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl("https://api.weixin.qq.com/cgi-bin/token")
.queryParam("grant_type", "client_credential")
.queryParam("appid", appId)
.queryParam("secret", appSecret);
// 调用接口获取AccessToken响应结果
String result = restTemplate.getForObject(builder.toUriString(), String.class);
// 从结果中提取AccessToken
return extractAccessToken(result);
}

private static final String startString = "\"access_token\":\"";

private static final String endString = "\",";

private String extractAccessToken(String result) {
int startIndex = result.indexOf("\"access_token\":\"");
int endIndex = result.indexOf(endString, startIndex);
return result.substring(startIndex + startString.length(), endIndex);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.mxixm.spring.boot.weixin.core;

import com.mxixm.spring.boot.weixin.util.CryptUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.stream.Collectors;
import java.util.stream.Stream;

@Controller
public class WxTokenVerifyController {
// 注入配置中的wx.token值
@Value("${wx.token}")
private String token;
// 处理配置的wx.path路径下的get请求,因为token验证请求中包含四个参数,所以可以直接使用作为参数条件使用
@GetMapping(path = "${wx.path}", params = {"signature", "timestamp", "nonce", "echostr"})
// 作为相应体返回,如果不标记@ResponseBody,返回的字符串会被作为视图名处理。也可以直接标记控制器为@RestController
@ResponseBody
public String tokenVerify(@RequestParam("signature") String signature,
@RequestParam("timestamp") String timestamp,
@RequestParam("nonce") String nonce,
@RequestParam("echostr") String echostr) {
// 三个参数值按字典排序并拼接
String rawString = Stream.of(token, timestamp, nonce).sorted().collect(Collectors.joining());
// 对拼接后字符串使用工具类中sha1方法进行sha1加密之后和参数中signature比较
if (signature.equals(CryptUtils.encryptSHA1(rawString))) {
// 相同则是合法的token认证请求,返回请求参数echostr值作为响应
return echostr;
}
// 否则啥也不返回
return null;
}
}
98 changes: 98 additions & 0 deletions src/main/java/com/mxixm/spring/boot/weixin/util/CryptUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/*
* Copyright (c) 2016-2018, Guangshan ([email protected]) and the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.mxixm.spring.boot.weixin.util;

import org.springframework.util.StringUtils;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
* FastBootWeixin CryptUtils
*
* @author Guangshan
* @date 2017/7/16 23:37
* @since 0.1.2
*/
public abstract class CryptUtils {

private final static String KEY_SHA1 = "SHA-1";

/**
* 全局数组
*/
private final static String[] hexDigits = {"0", "1", "2", "3", "4", "5",
"6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};

/**
* SHA 加密
*
* @param data 需要加密的字符串
* @return 加密之后的字符串
*/
public static String encryptSHA1(String data) {
// 验证传入的字符串
if (StringUtils.isEmpty(data)) {
return "";
}
// 创建具有指定算法名称的信息摘要
MessageDigest sha = null;
try {
sha = MessageDigest.getInstance(KEY_SHA1);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("加密错误");
}
// 使用指定的字节数组对摘要进行最后更新
sha.update(data.getBytes(StandardCharsets.UTF_8));
// 完成摘要计算
byte[] bytes = sha.digest();
// 将得到的字节数组变成字符串返回
return byteArrayToHexString(bytes);
}


/**
* 转换字节数组为十六进制字符串
*
* @param bytes 字节数组
* @return 十六进制字符串
*/
private static String byteArrayToHexString(byte[] bytes) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < bytes.length; i++) {
sb.append(byteToHexString(bytes[i]));
}
return sb.toString();
}

/**
* 将一个字节转化成十六进制形式的字符串
*
* @param b 字节数组
* @return 字符串
*/
private static String byteToHexString(byte b) {
int ret = b;
if (ret < 0) {
ret += 256;
}
int m = ret / 16;
int n = ret % 16;
return hexDigits[m] + hexDigits[n];
}

}
2 changes: 2 additions & 0 deletions src/main/resources/application.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
wx.token=12345
wx.path=/wx

0 comments on commit c7d1650

Please sign in to comment.