目录
2、配置文件:application.yml(需要读者填写你们自己的appid、secret以及后端服务的主地址)
一、登录微信公众平台
二、 配置
三、服务器代码
1、SDK依赖(读者直接COPY)
<!--微信开发sdk-->
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-mp</artifactId>
<version>2.7.0</version>
</dependency>
2、配置文件:application.yml(需要读者填写你们自己的appid、secret以及后端服务的主地址)
wechat:
mpAppId: APPID
mpAppSecret: SECRET
# 后端项目回调地址(这里我的项目带有context-path: /java,所以域名后面跟了/java)
projecturl: http://atcc-workshoptest.ciih.net/java/
3、编写配置类(读者直接COPY即可)
package com.ciih.workshop.utils.vx;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.Map;
@Data
@Component
//从配置文件里获取
@ConfigurationProperties(prefix = "wechat")
public class WechatAccountConfig {
/**
* 公众平台id
*/
private String mpAppId;
/**
* 公众平台密钥
*/
private String mpAppSecret;
/**
* 微信模版id
*/
private Map<String, String> templateId;
}
package com.ciih.workshop.utils.vx;
import me.chanjar.weixin.mp.api.WxMpConfigStorage;
import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
@Component
public class WechatMpConfig {
@Autowired
private WechatAccountConfig accountConfig;
/**
* @author :tao
* @date :Created in 2021/3/12 10:15
* @param: :
* @return: WxMpService 对象
* 配置wxMpConfigStorage,返回 WxMpService 对象
*/
@Bean
public WxMpService wxMpService() {
WxMpService wxMpService = new WxMpServiceImpl();
wxMpService.setWxMpConfigStorage(wxMpConfigStorage());
return wxMpService;
}
/**
* @author :tao
* @date :Created in 2021/3/12 10:20
* @param: :
* @return: WxMpConfigStorage 对象
* 配置AppId、和AppSecret,获取WxMpConfigStorage 对象
*/
@Bean
public WxMpConfigStorage wxMpConfigStorage() {
WxMpInMemoryConfigStorage wxMpConfigStorage = new WxMpInMemoryConfigStorage();
wxMpConfigStorage.setAppId(accountConfig.getMpAppId());
wxMpConfigStorage.setSecret(accountConfig.getMpAppSecret());
return wxMpConfigStorage;
}
}
4、接口编写(前后端不分离)
package com.ciih.workshop.controller;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
@Controller
@RequestMapping("/wechat")
@Slf4j
public class WxJsController {
@Autowired
private WxMpService wxMpService;
@Value("${wechat.projecturl}")
private String projectUrl;
/**
* 这个接口是提供给微信验证Token的。
*
* @param echostr 你在微信公众号配置页面填写的Token值
* @return
*/
@GetMapping("/auth")
@ResponseBody
public String auth(@RequestParam(value = "echostr", defaultValue = "sunziwen3366") String echostr) {
return echostr;
}
/**这个是前端唯一需要调用的接口
* @param returnUrl 要跳转到业务的H5页面的地址
*/
@GetMapping("/authorize")
public String authorize(@RequestParam(value = "returnUrl", defaultValue = "http://atcc-workshoptest.ciih.net/manager/#/login") String returnUrl) throws UnsupportedEncodingException {
log.info("【微信网页授权】进来了,参数={}", returnUrl);
System.out.println("进来了:" + returnUrl);
//1. 配置
//2. 调用方法
String url = projectUrl + "wechat/userInfo";
/*
* 相当于这种形式
* URLEncoder.decode(returnUrl,"UTF-8"
* https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
*/
String redirectUrl = wxMpService.oauth2buildAuthorizationUrl(url, WxConsts.OAUTH2_SCOPE_USER_INFO, URLEncoder.encode(returnUrl, "utf-8"));
log.info("【微信网页授权】获取code,result={}", redirectUrl);
return "redirect:" + redirectUrl;
}
/**
* 提供给上面的接口用的,用来获取用户信息,然后带着openid等信息跳转到业务的H5页面
*
* @author :tao
* @param: :
* @return: 重定向
* 获取用户信息类,最后重定向到指定url
*/
@GetMapping("/userInfo")
public String userInfo(@RequestParam("code") String code,
@RequestParam("state") String returnUrl) throws WxErrorException {
/*当用户同意授权后,会回调所设置的url并把authorization code传过来,
然后用这个code获得access token,其中也包含用户的openid等信息*/
WxMpOAuth2AccessToken wxMpOAuth2AccessToken = new WxMpOAuth2AccessToken();
try {
//获取access token
wxMpOAuth2AccessToken = wxMpService.oauth2getAccessToken(code);
log.info("【AccessToken:】{}", wxMpOAuth2AccessToken.getAccessToken());
} catch (WxErrorException e) {
log.error("【微信网页授权】{}", e);
}
// 拿到openid
String openId = wxMpOAuth2AccessToken.getOpenId();
log.info("【openid:】{}", openId);
log.info("【我是前端要回调的地址:】{}", returnUrl + "&openid=" + openId);
// 顺便获取一下用户信息
WxMpUser wxMpUser = wxMpService.oauth2getUserInfo(wxMpOAuth2AccessToken, "zh_CN");
log.info("【用户信息:】{}", wxMpUser.toString());
//注意拼接参数,第一个参数需要加问号,之后参数使用&拼接的问题
//return "redirect:" + returnUrl + "/#/?openid=" + openId;
return "redirect:" + returnUrl + "&openid=" + openId;
}
}
5、接口编写(前后端分离)
package com.ciih.workshop.controller;
import com.ciih.workshop.model.WeighbridgeDriverPerson;
import com.ciih.workshop.service.WeighbridgeDriverPersonService;
import com.ciih.workshop.utils.ServiceResult;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;
@Api(tags = {"地磅系统-微信公众号免登"})
@Controller
@RequestMapping("/wechat")
@Slf4j
public class WxJsController extends BaseController {
@Autowired
private WxMpService wxMpService;
@Value("${wechat.projecturl}")
private String projectUrl;
/**
* 这个接口是提供给微信验证Token的。
*
* @param echostr 你在微信公众号配置页面填写的Token值
* @return
*/
@GetMapping("/auth")
@ResponseBody
public String auth(@RequestParam(value = "echostr", defaultValue = "sunziwen3366") String echostr) {
return echostr;
}
/**
*
* @param returnUrl 要跳转到业务的H5页面的地址
*/
@GetMapping("/authorize")
public String authorize(@RequestParam(value = "returnUrl", defaultValue = "http://atcc-workshoptest.ciih.net/manager/#/login") String returnUrl) throws UnsupportedEncodingException {
log.info("【微信网页授权】进来了,参数={}", returnUrl);
System.out.println("进来了:" + returnUrl);
//1. 配置
//2. 调用方法
String url = projectUrl + "wechat/userInfo";
/*
* 相当于这种形式
* URLEncoder.decode(returnUrl,"UTF-8"
* https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
*/
String redirectUrl = wxMpService.oauth2buildAuthorizationUrl(url, WxConsts.OAUTH2_SCOPE_USER_INFO, URLEncoder.encode(returnUrl, "utf-8"));
log.info("【微信网页授权】获取code,result={}", redirectUrl);
return "redirect:" + redirectUrl;
}
/**
* 这个是前端唯一需要调用的接口,前端获取到openid后主动跳转相应页面
*
* @author :tao
* @param: :
* @return: 重定向
* 获取用户信息类,最后重定向到指定url
*/
@PostMapping("/userInfo")
@ResponseBody
public ServiceResult<?> userInfo(@RequestParam("code") String code,
@RequestParam("state") String returnUrl) {
/*当用户同意授权后,会回调所设置的url并把authorization code传过来,
然后用这个code获得access token,其中也包含用户的openid等信息*/
WxMpOAuth2AccessToken wxMpOAuth2AccessToken = new WxMpOAuth2AccessToken();
try {
//获取access token
wxMpOAuth2AccessToken = wxMpService.oauth2getAccessToken(code);
log.info("【AccessToken:】{}", wxMpOAuth2AccessToken.getAccessToken());
} catch (WxErrorException e) {
log.error("【微信网页授权】{}", e);
}
// 拿到openid
String openId = wxMpOAuth2AccessToken.getOpenId();
log.info("【openid:】{}", openId);
log.info("【我是前端要回调的地址:】{}", returnUrl + "&openid=" + openId);
// 顺便获取一下用户信息
WxMpUser wxMpUser = null;
try {
wxMpUser = wxMpService.oauth2getUserInfo(wxMpOAuth2AccessToken, "zh_CN");
} catch (WxErrorException e) {
return failure("获取用户信息失败");
}
log.info("【用户信息:】{}", wxMpUser.toString());
//注意拼接参数,第一个参数需要加问号,之后参数使用&拼接的问题
//return "redirect:" + returnUrl + "/#/?openid=" + openId;
// return "redirect:" + returnUrl + "&openid=" + openId;
return success(wxMpUser);
}
}
四、测试