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);
    }
  }
}


                  
        
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章