微信官方文档参考地址: https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Overview.html
**注意说明:**当前接口主要是生成临时二维码,调用腾讯服务器获取公众号二维码并将企业logo合成到二维码中。
@GetMapping("qrcode")
public Response login(HttpServletResponse response, HttpServletRequest request){
return wxMpManager.qrcode();
}
public Response qrcode() {
Map<String,Object> showQrcodeMap = new HashMap();
String accessToken = getAccessToken();
String url = String.format(PUBLICACCOUNT_QRCODE_URL,accessToken);
Map<String,Object> paramMap = new HashMap();
paramMap.put("expire_seconds",604800);
paramMap.put("action_name","QR_SCENE");
Map<String,Object> sceneMap = new HashMap();
Map<String,Object> sceneMap2 = new HashMap();
sceneMap2.put("scene_id",IdGen.uuid());
sceneMap.put("scene",sceneMap2);
paramMap.put("action_info",sceneMap);
HttpEntity httpEntity = new HttpEntity<>(new Gson().toJson(paramMap),new HttpHeaders());
ResponseEntity<String> response = restTemplate.postForEntity(url,httpEntity,String.class);
JSONObject jsonObject =new JSONObject(response.getBody());
log.info("临时二维码获取ticket,获取json:{}",jsonObject);
String qrCodeUrl = jsonObject.getString("url");
if(StringUtils.isEmpty(qrCodeUrl)){
log.error("临时二维码获取ticket,获取json:{}",jsonObject);
return ResponseUtils.returnCommonException("二维码获取失败");
}
try(ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
InputStream inputStream = getClass().getResourceAsStream(JIANMO_LOG_PATH)){
BufferedImage bufferedImage =QRCodeUtil.createImage(qrCodeUrl,inputStream , false, QR_CODE_SIZE);
ImageIO.write(bufferedImage,"jpg",outputStream);
String content = Base64.getEncoder().encodeToString(outputStream.toByteArray());
showQrcodeMap.put("showQrcodeUrl", "data:image/jpeg;base64,"+content);
showQrcodeMap.put("ticket",jsonObject.getString("ticket"));
} catch (IOException e) {
log.error(e.getMessage(),e);
} catch (Exception e) {
log.error(e.getMessage(),e);
}
return ResponseUtils.returnObjectSuccess(showQrcodeMap);
}
说明: 验证回调接口参数是否合法,如果合法直接返回入参中的echostr,这样公众平台中的回调校验才能正常通过。
@RequestMapping(method ={RequestMethod.GET,RequestMethod.POST},value ="login" )
public String login(PublicAccountCallDTO publicAccountCallDTO,HttpServletRequest request,HttpServletResponse response) {
log.info("publicAccountCallDTO={}",publicAccountCallDTO);
boolean flag= wxMpManager.getSignature(publicAccountCallDTO);
return flag ? publicAccountCallDTO.getEchostr():"";
}
public boolean getSignature(PublicAccountCallDTO publicAccountCallDTO) {
if(StringUtils.isEmpty(publicAccountCallDTO.getSignature())){
return false;
}
String[] array = new String[]{wxpayConfig.getWxOpenToken() , publicAccountCallDTO.getTimestamp() , publicAccountCallDTO.getNonce()};
StringBuilder sb = new StringBuilder();
// 字符串排序
Arrays.sort(array);
for (int i = 0; i < 3; i++) {
sb.append(array[i]);
}
String signature = DigestUtils.sha1Hex(sb.toString());
return signature.equals(publicAccountCallDTO.getSignature());
}
注意说明: 当前接口响应公众平台回调,所以返回格式为xml文件格式,为了避免返回数据乱码,此处需要二外配置produces = “application/xml; charset=UTF-8”
@RequestMapping(method ={RequestMethod.POST},value ="login",produces = "application/xml; charset=UTF-8")
public String login( @RequestBody String requestBody,PublicAccountCallDTO publicAccountCallDTO,HttpServletRequest request,
HttpServletResponse response) {
log.info("body={},publicAccountCallDTO={},paramMap={}",requestBody,publicAccountCallDTO,new Gson().toJson(request.getParameterMap()));
boolean flag= wxMpManager.getSignature(publicAccountCallDTO);
if(!flag){
log.error("非法回调,body={},publicAccountCallDTO={}",requestBody,publicAccountCallDTO);
return "";
}
wxMpManager.updateUser(requestBody,publicAccountCallDTO.getOpenid(), request);
WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(requestBody);
WxMpXmlOutMessage outMessage = wxMpMessageRouter.route(inMessage);
if(outMessage!=null) {
log.info("输出xml数据,{}",outMessage.toXml());
return outMessage.toXml();
}
return "";
}
@Component
@Slf4j
public class WxMpSubscribeHandler implements WxMpMessageHandler {
@Override
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService,
WxSessionManager sessionManager) throws WxErrorException {
log.info("wxMessage={}",wxMessage);
return WxMpXmlOutMessage.TEXT().
fromUser(wxMessage.getToUser()).
toUser(wxMessage.getFromUser()).
content("欢迎关注,用户登录成功").
build();
}
}
@Component
@Slf4j
public class WxMpUnSubscribeHandler implements WxMpMessageHandler {
@Override
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService,
WxSessionManager sessionManager) throws WxErrorException {
log.info("wxMessage={}",wxMessage);
return WxMpXmlOutMessage.TEXT().
fromUser(wxMessage.getToUser()).
toUser(wxMessage.getFromUser()).
content("请别离开我").
build();
}
}
@Component
@Slf4j
public class WxMpScanHandler implements WxMpMessageHandler {
@Override
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService,
WxSessionManager sessionManager) throws WxErrorException {
log.info("绑定系统用户成功,wxMessage={}",wxMessage);
return WxMpXmlOutMessage.TEXT().
content("用户登录成功!").
fromUser(wxMessage.getToUser()).
toUser(wxMessage.getFromUser()).
build();
}
}
@Configuration
public class WeChartConfig {
@Resource
private WxMpSubscribeHandler wxMpSubscribeHandler;
@Resource
private WxMpUnSubscribeHandler wxUnSubscribeHandler;
@Resource
private WxMpScanHandler wxMpScanHandler;
@Resource
private WeChartWxMpService weChartWxMpService;
@Bean
public WxMpMessageRouter wxMpMessageRouter(){
WxMpMessageRouter router = new WxMpMessageRouter(weChartWxMpService);
router.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT).event(WxConsts.EventType.SUBSCRIBE)
.handler(wxMpSubscribeHandler).end();
router.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT).event(WxConsts.EventType.UNSUBSCRIBE)
.handler(wxUnSubscribeHandler).end();
router.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT).event(WxConsts.EventType.SCAN)
.handler(wxMpScanHandler).end();
return router;
}
}
公众号平台参考文档:
1、https://developers.weixin.qq.com/doc/offiaccount/Account_Management/Generating_a_Parametric_QR_Code.html
2、https://developers.weixin.qq.com/doc/offiaccount/User_Management/Get_users_basic_information_UnionID.html#UinonId
公众号接口参考信息:
//获取accessToken
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=&secret=
//临时二维码获取ticket
https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=%s
//公众号获取用户信息接口
https://api.weixin.qq.com/cgi-bin/user/info?access_token=%s&openid=%s&lang=zh_CN