微信公众号服务器配置

微信公众号开发-服务器配置

最近在进行公司的微信公众号和小程序的开发,由于都是由本人独立研发,所以框架和接口都要自己去搭去写,因此想把相关接口做完之后做一些记录,如今闲来无事就总结下相关接口,本篇内容为:微信公众号研发的服务器配置

1.微信公众平台配置

要进行服务器配置的话首先登入微信公众平台,总步骤如下:

  1. 登入微信公众平台 ,在左侧菜单栏最下方子菜单找到 开发–基本配置
    微信公众号服务器配置_第1张图片
  2. 点击进入 基本配置,出现下图
    微信公众号服务器配置_第2张图片
  3. 此处我已经进行过配置了,未进行配置的页面 服务器配置 相关信息应是空白。那么此页面需要配置的信息为 ip白名单+服务器配置信息,url填服务器+接口,token随便填,token用作生成签名(该Token会和接口URL中包含的Token进行比对,从而验证安全性),密钥直接点随机生成,加解密方式选明文模式。
  4. 具体配置: ip白名单应配置为你的服务器ip地址(不知道自己的ip?看完本条看下一条),服务器地址应配置为你的项目发布的服务器地址(必须是已备案的域名,端口必须是80或443)+项目名+接口名,(此条看懂的话,第五第六条可跳过)
  5. 不知道自己的ip地址,打开cmd命令,windows输入ipconfig,Linux输入ifconfig,windows或者可以直接打开百度,然后输入ip至搜索框,点搜索,往下翻翻,就可以看到下图
    微信公众号服务器配置_第3张图片
  6. 你的项目发布的服务器地址(必须是已备案的域名,端口必须是80或443)+项目名+接口名 :意思是你的项目必须发布在一台外网可以访问到的服务器上,且发布的端口必须是80或443,如果你想用本机发布并调试的话,建议去natapp买一个外网映射工具,在网站里叫隧道(图一),再在本网站二级域名菜单里点击注册买个已备案的二级域名(图二),然后把域名绑定到隧道上,下载一个小工具,解压,修改一下配置,然后启动之后,本机地址就映射到外网了(图三);URL格式示例http://top.XXX.cc/项目名/wechat

    微信公众号服务器配置_第4张图片
    微信公众号服务器配置_第5张图片

至此,微信公众平台上的配置就完成了,接下来是java端的接口写法。

2.JAVA接口写法

  1. 先看官方文档的说明

开发者提交信息后,微信服务器将发送GET请求到填写的服务器地址URL上,GET请求携带参数如下表所示:

参数 描述
signature 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
timestamp 时间戳
nonce 随机数
echostr 随机字符串

开发者通过检验signature对请求进行校验(下面有校验方式)。若确认此次GET请求来自微信服务器,请原样返回echostr参数内容,则接入生效,成为开发者成功,否则接入失败。加密/校验流程如下:

1)将token、timestamp、nonce三个参数进行字典序排序
2)将三个参数字符串拼接成一个字符串进行sha1加密
3)开发者获得加密后的字符串可与signature对比,标识该请求来源于微信

官方文档链接:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421135319

官方文档里还给了个PHP的代码示例,不过我做的框架是java的SSM,开始有点懵,后来在网上借鉴相关在ssm里配置相关借口资料研究之后终于走通,所以现在直接贴出java的相关代码

Controller层

package com.wechat.controller;

import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.wechat.service.WxService;

@RestController
@RequestMapping("/wxportal")
public class WxController {
  @Autowired
  private WxService wxService;
 
  private final Logger logger = LoggerFactory.getLogger(this.getClass());
  private static org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger("logfile");
  @ResponseBody
  @GetMapping(produces = "text/plain;charset=utf-8")
  public String authGet(@RequestParam(name = "signature", required = false) String signature,
      @RequestParam(name = "timestamp", required = false) String timestamp,
      @RequestParam(name = "nonce", required = false) String nonce,
      @RequestParam(name = "echostr", required = false) String echostr) {
    this.logger.info("\n接收到来自微信服务器的认证消息:[{}, {}, {}, {}]", signature, timestamp, nonce, echostr);

    if (StringUtils.isAnyBlank(signature, timestamp, nonce, echostr)) {
      throw new IllegalArgumentException("请求参数非法,请核实!");
    }

    if (this.getWxService().checkSignature(timestamp, nonce, signature)) {
      return echostr;
    }

    return "非法请求";
  }

  @ResponseBody
  @PostMapping(produces = "application/xml; charset=UTF-8")
  public String post(@RequestBody String requestBody, @RequestParam("signature") String signature,
      @RequestParam(name = "encrypt_type", required = false) String encType,
      @RequestParam(name = "msg_signature", required = false) String msgSignature,
      @RequestParam("timestamp") String timestamp, @RequestParam("nonce") String nonce) {
    this.logger.info(
        "\n接收微信请求:[signature=[{}], encType=[{}], msgSignature=[{}],"
            + " timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ",
        signature, encType, msgSignature, timestamp, nonce, requestBody);

    if (!this.wxService.checkSignature(timestamp, nonce, signature)) {
      throw new IllegalArgumentException("非法请求,可能属于伪造的请求!");
    }
    String out = null;
    if (encType == null) {//unsubscribe event fromUser=oQmj3t35STb8TZHs7keHSYrYlPos  msgType=event
    	  //event=subscribe
      // 明文传输的消息
      WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(requestBody);
     
      
         WxMpXmlOutMessage outMessage = this.getWxService().route(inMessage);
      if (outMessage == null) {
        return "";
      }

      out = outMessage.toXml();
    } else if ("aes".equals(encType)) {
      // aes加密的消息
      WxMpXmlMessage inMessage = WxMpXmlMessage.fromEncryptedXml(requestBody,
          this.getWxService().getWxMpConfigStorage(), timestamp, nonce, msgSignature);
      this.logger.debug("\n消息解密后内容为:\n{} ", inMessage.toString());
      WxMpXmlOutMessage outMessage = this.getWxService().route(inMessage);
      if (outMessage == null) {
        return "";
      }

      out = outMessage.toEncryptedXml(this.getWxService().getWxMpConfigStorage());
    }

    this.logger.debug("\n组装回复信息:{}", out);

    return out;
  }

  protected WxService getWxService() {
    return this.wxService;
  }

}

Service层

package com.wechat.service;

import static me.chanjar.weixin.common.api.WxConsts.EventType.LOCATION;
import static me.chanjar.weixin.common.api.WxConsts.EventType.SCAN;
import static me.chanjar.weixin.common.api.WxConsts.EventType.SUBSCRIBE;
import static me.chanjar.weixin.common.api.WxConsts.EventType.UNSUBSCRIBE;
import static me.chanjar.weixin.common.api.WxConsts.MenuButtonType.CLICK;
import static me.chanjar.weixin.common.api.WxConsts.MenuButtonType.VIEW;
import static me.chanjar.weixin.common.api.WxConsts.XmlMsgType.EVENT;
import static me.chanjar.weixin.mp.constant.WxMpEventConstants.POI_CHECK_NOTIFY;
import static me.chanjar.weixin.mp.constant.WxMpEventConstants.CustomerService.KF_CLOSE_SESSION;
import static me.chanjar.weixin.mp.constant.WxMpEventConstants.CustomerService.KF_CREATE_SESSION;
import static me.chanjar.weixin.mp.constant.WxMpEventConstants.CustomerService.KF_SWITCH_SESSION;

import javax.annotation.PostConstruct;

import me.chanjar.weixin.common.api.WxConsts.XmlMsgType;
import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage;
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfOnlineList;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.wechat.config.WxMpConfig;
import com.wechat.handler.KfSessionHandler;
import com.wechat.handler.LocationHandler;
import com.wechat.handler.LogHandler;
import com.wechat.handler.MenuHandler;
import com.wechat.handler.MsgHandler;
import com.wechat.handler.NullHandler;
import com.wechat.handler.StoreCheckNotifyHandler;
import com.wechat.handler.SubscribeHandler;
import com.wechat.handler.UnsubscribeHandler;

@Service
public class WxService extends WxMpServiceImpl {
  private final Logger logger = LoggerFactory.getLogger(this.getClass());

  @Autowired
  protected LogHandler logHandler;

  @Autowired
  protected NullHandler nullHandler;

  @Autowired
  protected KfSessionHandler kfSessionHandler;

  @Autowired
  protected StoreCheckNotifyHandler storeCheckNotifyHandler;

  @Autowired
  private WxMpConfig wxConfig;

  @Autowired
  private LocationHandler locationHandler;

  @Autowired
  private MenuHandler menuHandler;

  @Autowired
  private MsgHandler msgHandler;

  @Autowired
  private UnsubscribeHandler unsubscribeHandler;

  @Autowired
  private SubscribeHandler subscribeHandler;

  private WxMpMessageRouter router;

  @PostConstruct
  public void init() {
    final WxMpInMemoryConfigStorage config = new WxMpInMemoryConfigStorage();
    // 设置微信公众号的appid
    config.setAppId(this.wxConfig.getAppid());
    // 设置微信公众号的app corpSecret
    config.setSecret(this.wxConfig.getAppSecret());
    // 设置微信公众号的token
    config.setToken(this.wxConfig.getToken());
    // 设置消息加解密密钥
    config.setAesKey(this.wxConfig.getAesKey());
    super.setWxMpConfigStorage(config);

    this.refreshRouter();
  }

  private void refreshRouter() {
    final WxMpMessageRouter newRouter = new WxMpMessageRouter(this);

    // 记录所有事件的日志
    newRouter.rule().handler(this.logHandler).next();

    // 接收客服会话管理事件
    newRouter.rule().async(false).msgType(EVENT).event(KF_CREATE_SESSION)
      .handler(this.kfSessionHandler).end();
    newRouter.rule().async(false).msgType(EVENT).event(KF_CLOSE_SESSION)
      .handler(this.kfSessionHandler).end();
    newRouter.rule().async(false).msgType(EVENT).event(KF_SWITCH_SESSION)
      .handler(this.kfSessionHandler).end();

    // 门店审核事件
    newRouter.rule().async(false).msgType(EVENT).event(POI_CHECK_NOTIFY)
      .handler(this.storeCheckNotifyHandler).end();

    // 自定义菜单事件
    newRouter.rule().async(false).msgType(EVENT).event(CLICK).handler(this.menuHandler).end();

    // 点击菜单连接事件
    newRouter.rule().async(false).msgType(EVENT).event(VIEW).handler(this.nullHandler).end();

    // 关注事件
    newRouter.rule().async(false).msgType(EVENT).event(SUBSCRIBE).handler(this.subscribeHandler).end();

    // 取消关注事件
    newRouter.rule().async(false).msgType(EVENT).event(UNSUBSCRIBE).handler(this.unsubscribeHandler).end();

    // 上报地理位置事件
    newRouter.rule().async(false).msgType(EVENT).event(LOCATION).handler(this.locationHandler).end();

    // 接收地理位置消息
    newRouter.rule().async(false).msgType(XmlMsgType.LOCATION).handler(this.locationHandler).end();

    // 扫码事件
    newRouter.rule().async(false).msgType(EVENT).event(SCAN).handler(this.nullHandler).end();

    // 默认
    newRouter.rule().async(false).handler(this.msgHandler).end();

    this.router = newRouter;
  }

  public WxMpXmlOutMessage route(WxMpXmlMessage message) {
    try {
      return this.router.route(message);
    } catch (Exception e) {
      this.logger.error(e.getMessage(), e);
    }

    return null;
  }

  public boolean hasKefuOnline() {
    try {
      WxMpKfOnlineList kfOnlineList = this.getKefuService().kfOnlineList();
      return kfOnlineList != null && kfOnlineList.getKfOnlineList().size() > 0;
    } catch (Exception e) {
      this.logger.error("获取客服在线状态异常: " + e.getMessage(), e);
    }

    return false;
  }

}

配置文件 wx.properties

wx_appid=wx3cd70cbxxxxxxx
wx_appsecret=8e939b9e582f4fdfxxxxxxx
wx_token=123487xxx
wx_aeskey=2Ud4dSEEM6ykj0Cgs5Q5xxxx
wx_url=http://top.xxxxxx.cc
wx_key=cafdae5e6xxxxxxxxa8c6cd143e
file_Path=E\:\\apache-tomcat-7.0.77\\apiclient_cert.p12

[参考链接]:[https://github.com/binarywang/weixin-java-mp-demo-springboot]

你可能感兴趣的:(微信公众号,JAVA)