-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
7d28b9a
commit c7d1650
Showing
7 changed files
with
273 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
|
||
} |
85 changes: 85 additions & 0 deletions
85
src/main/java/com/mxixm/spring/boot/weixin/core/WxAccessTokenManager.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
|
||
} |
36 changes: 36 additions & 0 deletions
36
src/main/java/com/mxixm/spring/boot/weixin/core/WxTokenVerifyController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
98
src/main/java/com/mxixm/spring/boot/weixin/util/CryptUtils.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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]; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
wx.token=12345 | ||
wx.path=/wx |