什么是第三方开放平台

来波官方解释:
我才是官方文档

第三方平台的开放,让公众号或小程序运营者在面向垂直行业需求时,可以通过一键登录授权给第三方开发者,来完成相关能力。

简单的说,就是让公众号授权给第三个开放平台,根据授权不同,第三开放平台可以获取到该公众号的接口权限,从而直接调用微信api,进行公众号开发;

开通创建流程

开发者资质审核通过后,就可以创建第三方开放平台了,由于我们第三方开放平台已经建立了。就不演示创建平台的过程了,下面解释下填写的资料

  1. 第一步基本资料填写,不做多余说明,填写基本资料即可
  2. 第二步选择权限集,大概意思就是 选择下 你这个第三方开放平台 要代替公众号实现那些业务 获取公众号的那些接口权限,需要注意的是首先要确保该公众号已经有了这个权限 我是官方文档
  3. 第三步是填写开发资料,基本上就是域名,白名单一些的配置了 这里官方文档写的也比较清楚 不懂看这里

开始开发
首先要做的 是授权事件接收URL的处理,用于接收取消授权通知、授权成功通知、授权更新通知,也用于接收ticket,ticket是验证平台方的重要凭据,服务方在获取component_access_token时需要提供最新推送的ticket以供验证身份合法性。此ticket作为验证服务方的重要凭据,请妥善保存。

权限变更这些可以先不考虑,先考虑的是 接受这个ticket,只有拥有了ticket才能去换取第三方平台的token
下面是主要代码。实体类这些不提供了,根据需求可以自行创建

 package com.ysh.wxtest.controller;import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Date;
import java.util.List;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.websocket.Session;import org.apache.commons.lang.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;import com.qq.weixin.mp.aes.AesException;
import com.qq.weixin.mp.aes.WXBizMsgCrypt;
import com.ysh.wxtest.model.Users;
import com.ysh.wxtest.model.Wxauthinfo;
import com.ysh.wxtest.model.Wxauthorizerinfo;
import com.ysh.wxtest.model.Wxcomtoken;
import com.ysh.wxtest.model.Wxticket;
import com.ysh.wxtest.service.WxauthinfoService;
import com.ysh.wxtest.service.WxauthorizerinfoService;
import com.ysh.wxtest.service.WxcomtokenService;
import com.ysh.wxtest.service.WxticketService;
import com.ysh.wxtest.util.AjaxMessage;import common.Logger;
import weixin.popular.bean.component.*;
import weixin.popular.util.XMLConverUtil;/*** 微信 第三方开放平台  controller层* @author YaoShiHang**/
@Controller
public class WeixinAccreditController {@Autowiredprivate WxticketService  wxticketService;   //微信推送 ticket服务,用于保存 ticket@Autowiredprivate WxcomtokenService wxcomtokenService; //微信第三方平台  token服务 ,有效期2小时。获取次数有限 注意缓存@Autowiredprivate WxauthinfoService wxauthinfoService; //微信授权信息 服务   @Autowiredprivate WxauthorizerinfoService WxinfoService; private final String APPID = "???";private Logger log= Logger.getLogger(getClass());/*** 微信全网测试账号*/private final static String COMPONENT_APPID = "XXXXXXXXXXXX"; //第三方平台 APPIDprivate final String COMPONENT_APPSECRET = "XXXXXXXXXXXX";    //第三方平台 秘钥private final static String COMPONENT_ENCODINGAESKEY = "XXXXXXXXXXXX";  //开发者 设置的 keyprivate final static String COMPONENT_TOKEN = "XXXXXXXXXXXX";   //开发者 设置的 token // 授权事件接受url 每隔10分钟 获取微信服务器推送ticket 接收后需要解密 接收到后 必须返回字符串success@RequestMapping("/openwx/getticket")public void getTicket(HttpServletRequest request, HttpServletResponse response)throws IOException, DocumentException, AesException {processAuthorizeEvent(request);output(response, "success"); // 输出响应的内容。}/***  授权事件处理 * @param request* @throws IOException* @throws DocumentException* @throws AesException*/public void processAuthorizeEvent(HttpServletRequest request) throws IOException, DocumentException, AesException {String nonce = request.getParameter("nonce");String timestamp = request.getParameter("timestamp");String signature = request.getParameter("signature");String msgSignature = request.getParameter("msg_signature");HttpSession session  = request.getSession();if (!StringUtils.isNotBlank(msgSignature)){ //判断消息是否空return;// 微信推送给第三方开放平台的消息一定是加过密的,无消息加密无法解密消息}boolean isValid = checkSignature(COMPONENT_TOKEN, signature, timestamp, nonce);if (isValid) {StringBuilder sb = new StringBuilder();BufferedReader in = request.getReader();String line;while ((line = in.readLine()) != null) {sb.append(line);}String xml = sb.toString();log.info("第三方平台全网发布-----------------------原始 Xml="+xml);String encodingAesKey = COMPONENT_ENCODINGAESKEY;// 第三方平台组件加密密钥String appId =  (xml);// 此时加密的xml数据中ToUserName是非加密的,解析xml获取即可log.info("第三方平台全网发布-------------appid----------getAuthorizerAppidFromXml(xml)-----------appId="+appId);WXBizMsgCrypt pc = new WXBizMsgCrypt(COMPONENT_TOKEN, encodingAesKey, COMPONENT_APPID);xml = pc.decryptMsg(msgSignature, timestamp, nonce, xml);log.info("第三方平台全网发布-----------------------解密后 Xml="+xml);ComponentReceiveXML com = XMLConverUtil.convertToObject(ComponentReceiveXML.class, xml);session.setAttribute("com",com);processAuthorizationEvent(xml);}}/*** 保存Ticket* @param xml*/void processAuthorizationEvent(String xml) {Document doc;try {doc = DocumentHelper.parseText(xml);Element rootElt = doc.getRootElement();String ticket = rootElt.elementText("ComponentVerifyTicket");if(ticket!=null){Wxticket wxticket = new Wxticket();wxticket.setAppid(APPID);wxticket.setAddtime(new Date());;wxticket.setId(1l);wxticket.setTicket(ticket);wxticketService.updateNotNull(wxticket);}} catch (DocumentException e) {e.printStackTrace();}}String getAuthorizerAppidFromXml(String xml) {Document doc;try {doc = DocumentHelper.parseText(xml);Element rootElt = doc.getRootElement();String toUserName = rootElt.elementText("ToUserName");return toUserName;} catch (DocumentException e) {// TODO Auto-generated catch blocke.printStackTrace();}return null;}/*** 判断消息是否加密* @param token* @param signature* @param timestamp* @param nonce* @return*/public static boolean checkSignature(String token, String signature, String timestamp, String nonce) {System.out.println("###token:" + token + ";signature:" + signature + ";timestamp:" + timestamp + "nonce:" + nonce);boolean flag = false;if (signature != null && !signature.equals("") && timestamp != null && !timestamp.equals("") && nonce != null&& !nonce.equals("")) {String sha1 = "";String[] ss = new String[] { token, timestamp, nonce };Arrays.sort(ss);for (String s : ss) {sha1 += s;}sha1 = AddSHA1.SHA1(sha1);if (sha1.equals(signature)) {flag = true;}}return flag;}/*** 工具类:回复微信服务器"文本消息"* @param response* @param returnvaleue*/public void output(HttpServletResponse response, String returnvaleue) {try {PrintWriter pw = response.getWriter();pw.write(returnvaleue);System.out.println("****************returnvaleue***************="+returnvaleue);pw.flush();} catch (IOException e) {e.printStackTrace();}}}class AddSHA1 {public static String SHA1(String inStr) {MessageDigest md = null;String outStr = null;try {md = MessageDigest.getInstance("SHA-1"); // 选择SHA-1,也可以选择MD5byte[] digest = md.digest(inStr.getBytes()); // 返回的是byet[],要转化为String存储比较方便outStr = bytetoString(digest);} catch (NoSuchAlgorithmException nsae) {nsae.printStackTrace();}return outStr;}public static String bytetoString(byte[] digest) {String str = "";String tempStr = "";for (int i = 0; i < digest.length; i++) {tempStr = (Integer.toHexString(digest[i] & 0xff));if (tempStr.length() == 1) {str = str + "0" + tempStr;} else {str = str + tempStr;}}return str.toLowerCase();}
}

提供一个xml 解析工具类


import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;import com.sun.xml.bind.marshaller.CharacterEscapeHandler;/*** XML 数据接收对象转换工具类* @author LiYi**/
public class XMLConverUtil{private static final ThreadLocal<Map<Class<?>,Marshaller>> mMapLocal = new ThreadLocal<Map<Class<?>,Marshaller>>() {@Overrideprotected Map<Class<?>, Marshaller> initialValue() {return new HashMap<Class<?>, Marshaller>();}};private static final ThreadLocal<Map<Class<?>,Unmarshaller>> uMapLocal = new ThreadLocal<Map<Class<?>,Unmarshaller>>(){@Overrideprotected Map<Class<?>, Unmarshaller> initialValue() {return new HashMap<Class<?>, Unmarshaller>();}};/*** XML to Object* @param <T> T* @param clazz clazz* @param xml xml* @return T*/public static <T> T convertToObject(Class<T> clazz,String xml){return convertToObject(clazz,new StringReader(xml));}/*** XML to Object* @param <T> T* @param clazz clazz* @param inputStream  inputStream* @return T*/public static <T> T convertToObject(Class<T> clazz,InputStream inputStream){return convertToObject(clazz,new InputStreamReader(inputStream));}/*** XML to Object* @param <T> T* @param clazz clazz* @param reader reader* @return T*/@SuppressWarnings("unchecked")public static <T> T convertToObject(Class<T> clazz,Reader reader){try {Map<Class<?>, Unmarshaller> uMap = uMapLocal.get();if(!uMap.containsKey(clazz)){JAXBContext jaxbContext = JAXBContext.newInstance(clazz);Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();uMap.put(clazz, unmarshaller);}return (T) uMap.get(clazz).unmarshal(reader);} catch (JAXBException e) {e.printStackTrace();}return null;}/*** Object to XML* @param object object* @return xml*/public static String convertToXML(Object object){try {Map<Class<?>, Marshaller> mMap = mMapLocal.get();if(!mMap.containsKey(object.getClass())){JAXBContext jaxbContext = JAXBContext.newInstance(object.getClass());Marshaller marshaller = jaxbContext.createMarshaller();marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);//设置CDATA输出字符marshaller.setProperty(CharacterEscapeHandler.class.getName(), new CharacterEscapeHandler() {public void escape(char[] ac, int i, int j, boolean flag, Writer writer) throws IOException {writer.write(ac, i, j);}});mMap.put(object.getClass(), marshaller);}StringWriter stringWriter = new StringWriter();mMap.get(object.getClass()).marshal(object,stringWriter);return stringWriter.getBuffer().toString();} catch (JAXBException e) {e.printStackTrace();}return null;}/*** 转换简单的xml to map* @param xml xml* @return map*/public static Map<String,String> convertToMap(String xml){Map<String, String> map = new LinkedHashMap<String,String>();try {DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();DocumentBuilder db = dbf.newDocumentBuilder();StringReader sr = new StringReader(xml);InputSource is = new InputSource(sr);Document document = db.parse(is);Element root = document.getDocumentElement();if(root != null){NodeList childNodes = root.getChildNodes();if(childNodes != null && childNodes.getLength()>0){for(int i = 0;i < childNodes.getLength();i++){Node node = childNodes.item(i); if( node != null && node.getNodeType() == Node.ELEMENT_NODE){map.put(node.getNodeName(), node.getTextContent());}}}}} catch (DOMException e) {e.printStackTrace();} catch (ParserConfigurationException e) {e.printStackTrace();} catch (SAXException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}return map;}
}

这一步结束后 第三方开放平台就可以审核通过了。然后就是进行代公众号实现业务了,相对来说简单了很多,微信提供的都有相关文档。直接调用接口就行了。需要注意的是在首先要确保公众号获取了这个权限,其次确保公众号把这个权限授权给了第三方平台。在开发中代公众号实现网页授权的接口 假如使用第三方开放平台的话,接口地址是有所改变的,参考第三方开放平台开发文档,其他的接口 只需将原来公众号的token 改变为 通过第三方开放平台token 获取的公众号授权给第三方开放平台的token 两个token是不一样的。有效期都是2小时 需要缓存。最后上一波成功图片

微信开发(4):微信第三方开放平台的搭建(java)相关推荐

  1. 微信公众帐号第三方服务平台源码

    微信公众帐号第三方服务平台源码,基于thinkphp3.2版本+DWZ进行开发.下载地址:http://down.qypangu.com 现在这个系统只能算是一个DEMO版,各位下载下来后可以根据自己 ...

  2. 微信小程序/公众号/开放平台账号被冻结后原始ID找回方法

    1. 问题: 微信小程序/公众号/开放平台账号长时间不用被冻结,想再次使用找回时需要原始ID,原始ID已忘记.(适用于所有原始ID忘记找回). 2. 解决办法 ##2. 1. 打开用于开发小程序/公众 ...

  3. 微信鉴权服务器地址,微信开发之微信授权登录

    本篇教程探讨了微信开发之微信授权登录,希望阅读本篇文章以后大家有所收获,帮助大家对相关内容的理解更加深入. < 应用场景是:用Hbuilder打包app,在app中点击微信授权登录或者某一操作, ...

  4. php 微信 语音,PHP语言微信开发:微信录音临时转永久存储

    本文主要向大家介绍了PHP语言微信开发:微信录音临时转永久存储,通过具体的内容向大家展示,希望对大家学习php语言有所帮助. 最近做开发的时候碰到了这个问题,甲方希望用户在微信端的录音能够一直有效.就 ...

  5. 微信开发:微信js_sdk 分享,前端部分(二)

    微信开发:微信js-sdk前端分享,代码如下: <script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"> ...

  6. 斗鱼第三方开放平台2.2版使用记录

    这是斗鱼第三方开放平台2.2版本的使用笔记 该文档在2018-08-25号亲测有效,开放文档 获取房间列表 获取所有直播房间列表,后面不跟任何参数 http://open.douyucdn.cn/ap ...

  7. 钉钉应用云开发之钉钉开放平台接入

    钉钉应用云开发之钉钉开放平台接入 简介:介绍服务端API及开发工具的使用,使用创建用户接口新建一个用户. 1.首先,我们在钉钉开放平台创建应用https://open-dev.dingtalk.com ...

  8. 微信开发 --- 调用微信上传图片接口,并保存到自己的服务器

    微信开发 - 调用微信上传图片接口,并保存到自己的服务器 整体思路是这样的: 1.先把手机上的图片上传到微信服务器,然后返回一个图片ID 2.在通过后台根据ID从微信后台拿到流,保存到服务器 前几个步 ...

  9. 微信 第三方开放平台 获取小程序授权并绑定小程序到开放平台(都是坑,留下帮助后人) 一

    接到需求,开发第三方平台的API对接,开始躺坑之路 第一步:获取小程序授权 看看官方给的流程图 OK,想获取授权就得获取 预授权码 看看预授权吧!! OK,想获取预授权码就得获取 令牌  OK OK  ...

最新文章

  1. ActiveMQ — 单节点 — 安装与配置
  2. go 类型 value 不支持索引_10分钟掌握PostgreSQL 5种索引的应用场景
  3. Microsoft和AWS推出免费的云优化服务
  4. 遇到的问题及解决方法
  5. armv8/arnv9的aarch64架构中系统寄存器的分类和总结
  6. C语言 课设 最新版 学生成绩管理系统
  7. 学生管理系统代码赏析
  8. 苹果WWDC前瞻之iOS 13更新最受关注;微软发布基于区块链的去中心化身份识别系统;小米成立了新集团质量办公室……...
  9. CSS环绕球体的旋转文字-3D效果
  10. 【实物】端到端自动驾驶搭建教程(一)附完整资料
  11. 电脑html动态桌面壁纸制作,动态桌面软件《Wallpaper Engine》 让你的电脑桌面动起来!...
  12. 原子结构示意图全部_原子结构示意图全部-原子结构示意图规律口诀-前20号元素的原子结构示意图...
  13. opencv 模板匹配形状匹配
  14. 团队作业9——项目验收与总结
  15. 2021年,阿里月薪50k招数据分析师,这个要求过分吗?
  16. php文章下一页,php实现文章上一页下一页的实例
  17. 【Java学习002】Java-ArrayList源码解析
  18. 武大教授计算机学院,武汉大学姬东鸿教授访问计算机科学学院和智能信息处理及应用实验室...
  19. 职场礼仪_举止_坐姿
  20. PC机上的COM1口和COM2口

热门文章

  1. IB-PYP幼儿十大素质培养目标
  2. 倍福TwinCAT CNC轴如何做NC轴的主轴
  3. 条件概率、全概率和贝叶斯公式
  4. 产品经理的介绍及提高
  5. 做事的科学-细节与流程》读书笔记第四章(变动性优化方案)
  6. python中iloc和loc的用法
  7. uvm环境中收集coverage的方法
  8. 工业交换机网管运维方案
  9. 【OpenCV(C++)快速入门】--上篇--计算机图像颜色基础理论
  10. Java中的二进制,八进制,十六进制