版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
今天编写一个网页授权接口开发的实例,希望对大家的工作有所帮助
微信公众号开发文档地址:https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Overview.html
网页授权文档地址:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html
准备工作:
- 一个可以内网映射的域名, 如果没有请查看 微信开发-内网穿透的方式 文章
- 微信公众平台接口测试帐号 点击申请
微信平台测试号配置:
找到网页服务 -- 网页账号 -- 授权接口的配置
点击修改, 添加内网映射的域名
注意, 前方有坑,请注意躲避----------此处的填写的是域名,不是URL,无需添加 http:// 协议
公众号配置完成后,开始上代码:
1.创建实体类
/**
* @author: diego
* @date: 2019/2/20 15:57
* @description: 微信常用属性定义
* @version: 1.0
*/
public class WeChat {
//自定义Token
private String token = "token";
//微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
private String signature;
//时间戳
private String timestamp;
//随机数
private String nonce;
//随机字符串
private String echostr;
//用户同意授权返回code
private String code;
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public String getSignature() {
return signature;
}
public void setSignature(String signature) {
this.signature = signature;
}
public String getTimestamp() {
return timestamp;
}
public void setTimestamp(String timestamp) {
this.timestamp = timestamp;
}
public String getNonce() {
return nonce;
}
public void setNonce(String nonce) {
this.nonce = nonce;
}
public String getEchostr() {
return echostr;
}
public void setEchostr(String echostr) {
this.echostr = echostr;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
}
2.常量定义
public class WeChatConstDefine {
/*------------------------------------------- 常量 -------------------------------------------*/
public static final Boolean TRUE = true;
public static final Boolean FALSE = false;
public static final String GET = "GET";
public static final String POST = "POST";
public static final String ENCODE_UTF_8 = "UTF-8";
public static final String ENCODE_GBK = "GBK";
/*---------------------------------------- 微信请求地址 ----------------------------------------*/
//用户同意授权,获取code
public static final String authorize = "https://open.weixin.qq.com/connect/oauth2/authorize";
//通过code换取网页授权access_token
public static final String access_token = "https://api.weixin.qq.com/sns/oauth2/access_token";
//刷新access_token(如果需要)
public static final String refresh_token = "https://api.weixin.qq.com/sns/oauth2/refresh_token";
//拉取用户信息(需scope为 snsapi_userinfo)
public static final String userInfo = "https://api.weixin.qq.com/sns/userinfo";
//检验授权凭证(access_token)是否有效
public static final String auth = "https://api.weixin.qq.com/sns/auth";
//重定向后缀参数
public static final String weChat_redirect = "#wechat_redirect";
}
3.自定义异常类
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class MyException extends RuntimeException {
public MyException(String message) {
super(message);
log.info("/************************My Exception************************/");
log.info("");
log.info("");
log.info(message);
log.info("");
log.info("");
log.info("/************************My Exception************************/");
}
public MyException(Exception e) {
super(e);
log.info("/************************My Exception************************/");
log.info("");
log.info("");
log.info(e.getMessage());
log.info("");
log.info("");
log.info("/************************My Exception************************/");
}
public MyException(String message, Exception e) {
super(message, e);
log.info("/************************My Exception************************/");
log.info("");
log.info("");
log.info("My Message:" + message);
log.info("System Message:" + e.getMessage());
log.info("");
log.info("");
log.info("/************************My Exception************************/");
}
}
4.编码-解码工具类
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
/**
* @author: diego
* @date: 2019/1/29 10:39
* @description: 编码-解码工具类
* @version: 1.0
*/
public class EncodeUtils {
/**
* URL 编码
*/
public static String urlEncode(String url,String encode) {
if(null == url || "".equals(url) || null == encode && "".equals(encode)){
throw new MyException("The url or encode is not null.");
}else{
try {
return URLEncoder.encode(url, WeChatConstDefine.ENCODE_UTF_8);
} catch (UnsupportedEncodingException e) {
throw new MyException(e);
}
}
}
/**
* URL 解码
*/
public static String urlDecode(String url,String encode) {
if(null == url || "".equals(url) || null == encode && "".equals(encode)){
throw new MyException("The url or encode is not null.");
}else{
try {
return URLDecoder.decode(url, WeChatConstDefine.ENCODE_UTF_8);
} catch (UnsupportedEncodingException e) {
throw new MyException(e);
}
}
}
}
5.http工具类
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Iterator;
import java.util.Map;
/**
* @author: diego
* @date: 2019/1/29 10:39
* @description: Http请求工具类
* @version: 1.0
*/
public class HttpConnectionUtils {
public static HttpConnectionUtils getHttp() {
return new HttpConnectionUtils();
}
// url发送请求
public String sendRequest(String url, String method, Map<String, Object> map,String suffix) throws MyException{
String result = "";
if (null == url || url.equals("")) {
throw new MyException("The url is null.");
}else if (null == method || method.equals("")) {
method = WeChatConstDefine.GET;
}else{
if(!WeChatConstDefine.GET.equals(method) && !WeChatConstDefine.POST.equals(method)){
throw new MyException("request method is error. you only use 'POST' or 'GET'.");
}else{
if(WeChatConstDefine.GET.equals(method)){
return sendByGetMethod(url, map,suffix);
}else if(WeChatConstDefine.POST.equals(method)){
HttpURLConnection connection = getConnection(url, WeChatConstDefine.POST);
return sendByPostMethod(url,connection, map,suffix);
}
}
}
return result;
}
// url 拼接 参数
public String analyticParams(String url,Map<String,Object> map,String suffix) throws MyException{
StringBuffer params = new StringBuffer(url+"?");
if(map != null && map.size() > 0){
Iterator<String> it = map.keySet().iterator();
do{
String param = it.next();
if(it.hasNext()){
params.append(param + "=" + map.get(param) + "&");
}else{
params.append(param + "=" + map.get(param));
}
}while (it.hasNext());
}else{
throw new MyException("url parameter resolution failed.");
}
String httpUrl = "";
if(null != suffix){
httpUrl = params.toString() + suffix;
}else{
httpUrl = params.toString();
}
return httpUrl;
}
// get HttpURLConnection
private HttpURLConnection getConnection(String urlString, String method) throws MyException {
URL url = null;
HttpURLConnection result = null;
try {
url = new URL(urlString);
result = (HttpURLConnection) url.openConnection();
result.setRequestMethod(method);
} catch (Exception e) {
throw new MyException(e);
}
if (null == result) {
throw new MyException("HttpURLConnection is null.");
}
return result;
}
// get request method
private String sendByGetMethod(String url, Map<String, Object> params,String suffix) throws MyException {
// 拼接url
String urlParams = this.analyticParams(url,params,suffix);
HttpURLConnection connection = this.getConnection(urlParams, WeChatConstDefine.GET);
try {
connection.connect();
} catch (IOException e) {
throw new MyException(e);
}
return getResponseResult(connection);
}
// post request method
private String sendByPostMethod(String url,HttpURLConnection connection, Map<String, Object> params,String suffix) throws MyException {
// 初始化post请求属性
this.initPostProperties(connection);
// 发送参数
this.sendParams(url,connection, params,suffix);
return getResponseResult(connection);
}
// 初始化post请求属性
private void initPostProperties(HttpURLConnection connection) {
connection.setUseCaches(false);
connection.setInstanceFollowRedirects(true);
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
}
// 发送参数
private void sendParams(String url,HttpURLConnection connection, Map<String, Object> params,String suffix) throws MyException {
DataOutputStream out = null;
try {
connection.connect();
out = new DataOutputStream(connection.getOutputStream());
String stringParam = this.analyticParams(url,params,suffix);
out.writeBytes(stringParam);
out.flush();
} catch (IOException e) {
throw new MyException("Send param error : " + e);
} finally {
close(out);
}
}
// 获取服务器返回结果
private String getResponseResult(HttpURLConnection connection) throws MyException {
StringBuilder result = new StringBuilder();
InputStream in = null;
try {
in = connection.getInputStream();
byte[] buff = new byte[1024];
int flag = -1;
while ((flag = in.read(buff)) != -1) {
result.append(new String(buff, 0, flag, WeChatConstDefine.ENCODE_UTF_8));
}
in.close();
} catch (IOException e) {
throw new MyException(e);
} finally {
close(in);
}
return result.toString();
}
// close input stream
private void close(InputStream in) {
if (null != in) {
try {
in.close();
} catch (IOException e) {
throw new MyException(e);
}
}
}
// close output stream
private void close(OutputStream out) {
if (null != out) {
try {
out.close();
} catch (IOException e) {
throw new MyException(e);
}
}
}
}
6.请求接口
@Controller
public class WeChatController {
/**
* 授权后重定向的回调链接地址
*/
@RequestMapping("/index")
@ResponseBody
public String getCode(WeChat weChat){
return weChat.getCode();
}
}
打死都不会遗漏的pom:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- QRCode二维码工具包 -->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.3.3</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.3.3</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
测试:
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
*
* @author: lsg
* @create: 2019/10/25 13:33
*/
public class WeChatUtils {
public static void main(String[] args) {
//参数详情请查看接口文档
Map<String,Object> map = new HashMap<String, Object>();
map.put("appid", "测试账号中的appID");
map.put("response_type", "code");
map.put("scope", "snsapi_userinfo");
map.put("state", "ABC");
map.put("redirect_uri", EncodeUtils.urlEncode("http://内网穿透的域名/index",WeChatConstDefine.ENCODE_UTF_8));
//用户通过扫码获取授权信息
String url = HttpConnectionUtils.getHttp().analyticParams(WeChatConstDefine.authorize,map,WeChatConstDefine.weChat_redirect);
try {
System.out.println(url);
//二维码
QRCodeUtils.encode(url, "D:/WeChat.jpg");
} catch (Exception e) {
e.printStackTrace();
}
}
执行main方法,控制台输出URL,在微信中访问此URL或者找到D盘下 WeChat.jpg 文件进行扫码
点击允许,调用redirect_uri定义的URL,访问了Controllerinde 中 index 接口 在控制台输出用户授权 code。
此处预留一下 个人logo 位置,以后填充................