Wechat公众平台开发

微信公众平台 https://mp.weixin.qq.com/
微信公众平台开发者文档 http://mp.weixin.qq.com/wiki/17/2d4265491f12608cd170a95559800f2d.html


15年元旦的时候,产品要做微信版,便开始研究微信公众平台以及开发者文档,给我的感觉是微信测试很不方便,职能配置一个回调URL,测试和正式通用,还会有回调两次的现象。以及弹出哭脸:请在微信客户端中打开。
半年多过去了,微信开放平台也在不断的完善和优化。自己凭着回忆和代码,做下迟来的总结,作为留念。


项目设计分为两大部分,基础服务搭建和具体业务接入。


基础服务搭建


1. 开发者接入


申请公众号后,微信分配了开发者ID,包括AppID,AppSecret。

按照微信开发者文档中的接入指南,配置微信交互的url、Token、EncodingAESKey.三者都是自定义的,启用兼容模式,方便调试,项目上线稳定后改为安全模式。url自己写的controller,接受布置在具有外网权限的服务器上。


微信交互消息文本采用XML格式,加解密采用SHA1
<pre name="code" class="java">  @RequestMapping(value = {"mp/callback.action"}, method = RequestMethod.POST, produces = "text/xml")
  @ResponseBody
  public String receive(@RequestBody String xmlbody,
      @RequestParam(value = "signature") String signature,
      @RequestParam(value = "timestamp") String timestamp,
      @RequestParam(value = "nonce") String nonce,
      @RequestParam(value = "encrypt_type") String encrypt_type, @RequestParam(
          value = "msg_signature") String msg_signature, HttpServletResponse response, Model model) {
	// TODO 1. 通过对签名的效验判断此条消息的真实性	  2. 解密xmlbody密文 3. 解析消息,交给按照不同的处理策略,得到相应的响应消息加密后返回。
 }


 2. 菜单·这是重要的基础环节。按照格式,构建菜单。按等级划分: 一级菜单、二级菜单。二级菜单即一级菜单的子菜单。当然一级菜单可以不包含菜单。有种树的感觉:节点,子节点。按按钮事件类型划分: view、 click。view是点击按钮打开url链接。click是点击发送一条消息Message。很简单。关键是做好click类型key与message消息的对应,做到动态配置,可以做管理后台,菜单变更后,立即向微信发送restful请求,刷新菜单。 
[{
	name: "看点啥",
	sub_button: [{
		key: "TONIGHT_FOCUS",
		name: "今晚看啥",
		type: "click"
	},
	{
		name: "小编推荐",
		type: "view",
		url: "http://"
	},
	{
		key: "COLUMN_SEARCH",
		name: "搜索影片",
		type: "click"
	},
	{
		name: "会员片库",
		type: "view",
		url: "http://"
	}]
},
{
	name: "特色片",
	sub_button: [{
		name: "8月观影指南",
		type: "view",
		url: "http://"
	},
	{
		name: "新片推荐",
		type: "view",
		url: "http://"
	},
	{
		name: "美味周边",
		type: "view",
		url: "http://"
	},
	{
		name: "免费电影票",
		type: "view",
		url: "http://"
	},
	{
		name: "更多专题",
		type: "view",
		url: "http://"
	}]
},
{
	name: "我的",
	sub_button: [{
		key: "SERVICE_VIP",
		name: "会员状态",
		type: "click"
	},
	{
		key: "SERVICE_HIS",
		name: "观看记录",
		type: "click"
	},
	{
		key: "SERVICE_KF",
		name: "专属客服",
		type: "click"
	},
	{
		name: "会员中心",
		type: "view",
		url: "http://"
	}]
}]


3. 用户
   做用户这块,折腾了好久,难点在于与公司用户体系打通。
  
  /***
   * 获取用户基本信息(UnionID机制)
   * 
   * @param openid
   * @return
   */
  public UserInfo getUserInfo(String openid);
  /***
   * 通过code换取网页授权access_token
   * 
   * @param code
   * @return null if code is blank.
   */
  public Oauth2AccessToken oauth2_access_token(String code);
  /***
   * 拉取用户信息(需scope为 snsapi_userinfo)
   * 
   * @param access_token
   * @param openid
   * @return
   */
  public UserInfo oauth2_userinfo(String access_token, String openid);


  
  
   
4. 用户与公众平台消息交互
用户动作分为消息和事件两种,根据消息EventType为msg或event,分别构建两种策略模式。
public class EventStrategyFactory {


  public static IEventStrategy getDealer(String event) {


    // 按事件发生概率由高到低排序
    switch (event) {


    // 自定义菜单 —— 点击菜单拉取消息时的事件
      case "CLICK":
        return EventStrategy.CLICK;


        // 自定义菜单 —— 点击菜单跳转链接时的事件
      case "VIEW":
        return EventStrategy.VIEW;


        // 关注事件 || 扫描带参数二维码, 用户未关注时,进行关注后的事件推送
      case "subscribe":
        return EventStrategy.subscribe;


        // 模版消息发送任务完成后的事件
      case "TEMPLATESENDJOBFINISH":
        return EventStrategy.TEMPLATESENDJOBFINISH;


        // 上报地理位置事件
      case "LOCATION":
        return EventStrategy.LOCATION;


        // 取消关注事件
      case "unsubscribe":
        return EventStrategy.unsubscribe;


        // 扫描带参数二维码, 用户已关注时的事件推送
      case "SCAN":
        return EventStrategy.SCAN;


        // 自定义菜单 —— 扫码推事件的事件
      case "scancode_push":
        return EventStrategy.scancode_push;


        // 自定义菜单 —— 扫码推事件且弹出“消息接收中”提示框的事件
      case "scancode_waitmsg":
        return EventStrategy.scancode_waitmsg;


        // 自定义菜单 —— 弹出系统拍照发图的事件
      case "pic_sysphoto":
        return EventStrategy.pic_sysphoto;


        // 自定义菜单 —— 弹出拍照或者相册发图的事件
      case "pic_photo_or_album":
        return EventStrategy.pic_photo_or_album;


        // 自定义菜单 —— 弹出微信相册发图器的事件
      case "pic_weixin":
        return EventStrategy.pic_weixin;


        // 自定义菜单 —— 弹出地理位置选择器的事件
      case "location_select":
        return EventStrategy.location_select;


      default:
        return null;
    }
  }
}




/***
 * 事件枚举策略
 * 
 * @author charles
 *
 */
public enum EventStrategy implements IEventStrategy {


  // 关注事件 || 扫描带参数二维码, 用户未关注时,进行关注后的事件推送
  subscribe {
    @Override
    public String dealEvent(Element root) {
      return SubscribeStrategy.dealEvent(root);
    }
  },


  // 取消关注事件
  unsubscribe {
    @Override
    public String dealEvent(Element root) {
      return UnSubscribeStrategy.dealEvent(root);
    }
  },


  // 扫描带参数二维码, 用户已关注时的事件推送
  SCAN {
    @Override
    public String dealEvent(Element root) {
      return ScanStrategy.dealEvent(root);
    }
  },


  // 上报地理位置事件
  LOCATION {
    @Override
    public String dealEvent(Element root) {
      return LocationStrategy.dealEvent(root);
    }
  },


  // 自定义菜单 —— 点击菜单拉取消息时的事件
  CLICK {
    @Override
    public String dealEvent(Element root) {
      return ClickStrategy.dealEvent(root);
    }
  },


  // 自定义菜单 —— 点击菜单跳转链接时的事件
  VIEW {
    @Override
    public String dealEvent(Element root) {
      return ViewStrategy.dealEvent(root);
    }
  },


  // 自定义菜单 —— 扫码推事件的事件
  scancode_push {
    @Override
    public String dealEvent(Element root) {
      return Scancode_pushStrategy.dealEvent(root);
    }
  },


  // 自定义菜单 —— 扫码推事件且弹出“消息接收中”提示框的事件
  scancode_waitmsg {
    @Override
    public String dealEvent(Element root) {
      return Scancode_waitmsgStrategy.dealEvent(root);
    }
  },


  // 自定义菜单 —— 弹出系统拍照发图的事件
  pic_sysphoto {
    @Override
    public String dealEvent(Element root) {
      return Pic_sysphotoStrategy.dealEvent(root);
    }
  },


  // 自定义菜单 —— 弹出拍照或者相册发图的事件
  pic_photo_or_album {
    @Override
    public String dealEvent(Element root) {
      return Pic_photo_or_albumStrategy.dealEvent(root);
    }
  },


  // 自定义菜单 —— 弹出微信相册发图器的事件
  pic_weixin {
    @Override
    public String dealEvent(Element root) {
      return Pic_weixinStrategy.dealEvent(root);
    }
  },


  // 自定义菜单 —— 弹出地理位置选择器的事件
  location_select {
    @Override
    public String dealEvent(Element root) {
      return Location_selectStrategy.dealEvent(root);
    }
  },


  // 模版消息发送任务完成后的事件
  TEMPLATESENDJOBFINISH {
    @Override
    public String dealEvent(Element root) {
      return TemplateSendStrategy.dealEvent(root);
    }
  }
}





/***
 * 消息策略简单工厂
 * 
 * @author charles
 *
 */
public class MessageStrategyFactory {


  public static IMessageStrategy getDealer(String msgType) {


    switch (msgType) {


    // 文本消息
      case "text":
        return MessageStrategy.text;


        // 图片消息
      case "image":
        return MessageStrategy.image;


        // 语音消息
      case "voice":
        return MessageStrategy.voice;


        // 视频消息
      case "video":
        return MessageStrategy.video;


        // 地理位置消息
      case "location":
        return MessageStrategy.location;


        // 链接消息
      case "link":
        return MessageStrategy.link;


      default:
        return null;
    }
  }
}




/***
 * 消息枚举策略
 * 
 * @author charles
 *
 */
public enum MessageStrategy implements IMessageStrategy {


  // 文本消息
  text {
    @Override
    public String dealMsg(Element root) {


      return TextStrategy.dealMsg(root);
    }
  },


  // 图片消息
  image {
    @Override
    public String dealMsg(Element root) {
      return ImageStrategy.dealMsg(root);
    }
  },


  // 语音消息
  voice {
    @Override
    public String dealMsg(Element root) {
      return VoiceStrategy.dealMsg(root);
    }
  },


  // 视频消息
  video {
    @Override
    public String dealMsg(Element root) {
      return VideoStrategy.dealMsg(root);
    }
  },


  // 地理位置消息
  location {
    @Override
    public String dealMsg(Element root) {
      return LocationStrategy.dealMsg(root);
    }
  },


  // 链接消息
  link {
    @Override
    public String dealMsg(Element root) {
      return LinkStrategy.dealMsg(root);
    }
  }
}


                  
        
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值