记微信开放平台之第三方平台开发流程

背景

大家知道,微信网页开发的时候,诸如静默授权,分享朋友圈等操作,会使用到公众号的appId跟appSecret,其中会存在accessToken这个有效期凭证的使用,那么假如我们在开发中有两个项目同时都需要用到这个公众号,或者我们需要将两个项目中的用户数据,根据openId进行打通,那么就需要用到同一个公众号进行开发(注:不同公众号同一个用户的openId是不一样的),但是根据传统开发,除非使用中继服务器,否则两个独立的项目会互刷accessToken,导致达到接口使用次数,这种是不可取的。又或者是另外一种场景,一套项目想给N个公众号接入使用逻辑,为了减少重复开发量,接入微信第三方平台这个概念。

微信第三方平台官方解释

微信公众平台-第三方平台(简称第三方平台)开放给所有通过开发者资质认证后的开发者使用。在得到公众号或小程序运营者(简称运营者)授权后,第三方平台开发者可以通过调用微信开放平台的接口能力,为公众号或小程序的运营者提供账号申请、小程序创建、技术开发、行业方案、活动营销、插件能力等全方位服务。同一个账号的运营者可以选择多家适合自己的第三方为其提供产品能力或委托运营。

正文

微信第三方平台地址:微信开放平台
1.注册登录等操作我就不说了,随后我们点击管理中心,第三方平台,创建第三方平台,在这里创建一个第三方平台
在这里插入图片描述
第一步为输入基本信息,我们选择的是平台型服务商,这里我就不多介绍,根据实际情况即可
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

根据实际情况挑选权限,一般网页服务权限都是必须的
进入下一步
在这里插入图片描述
在这里插入图片描述
最后一步是最重要的一步,需要根据情况填写,在这里我解释下

  1. 授权发起页域名,这个指的是你的开发域名了,也就是网页授权等业务发起授权时,我们所使用的域名(没有域名的可以自己使用内网穿透,具体操作自己搜下啦)
  2. 授权测试公众号/小程序列表:这个的意思其实很简单,在这个平台还没有全网发布的时候,我们只能使用在这个选项填写的公众号进行测试,全网发布后,所有的公众号都可以接入到你的平台,没有全网发布的时候仅可以授权给当前的这个测试公众号或者小程序啦,但这里填写的并不是公众号的appId哦,切记,而是公众号或小程序的原始ID(可在公众平台网站的公众号设置页或小程序设置页找到)
  3. 授权事件接收URL:用于接收取消授权通知、授权成功通知、授权更新通知,也用于接收ticket,ticket是验证平台方的重要凭据,这个是比较重要的一个url,是微信主动推送事件到我们服务器的一个接口地址,票据ticket是每十分钟都会推送的哦,根据实际情况进行填写
  4. 消息校验Token和消息加解密Key是自己随意填写的哦,但是这里要注意的是消息加解密Key这个必须为43位长度的字符串,我都是随机码生成的,自己保管好,后续会用到
  5. 这个是用户发送给公众号消息时,微信会将该信息推送到你服务器的一个接口路径,根据场景进行回复
  6. 做网页授权、调用JS SDK等网页开发工作时所用的域名,但同时这个在提交的时候,需要下载下方那个验证文件,你放在服务器上,用nginx指向它即可,鉴权使用
  7. ip白名单不多说啦

提交审核,一般是秒过。然后就开始进行开发了

开发及踩坑

1.开发票据接收接口,也就是授权事件接收URL,在这边其余事件我就不赘述,自己根据实际情况,我贴上接收票据的代码


    @ApiOperation(httpMethod = "POST", value = "微信主动十分钟推送票据")
    @PostMapping(value = "/getTicket")
    @MethodLog(description = "微信主动十分钟推送票据")
    public String getCompanyIntroduce(HttpServletRequest request) {
        log.info("微信推送票据");
        try {
            // 微信加密签名
            String msgSignature = request.getParameter("msg_signature");
            // 时间戳
            String timeStamp = request.getParameter("timestamp");
            // 随机数
            String nonce = request.getParameter("nonce");
            log.info("msgSignature:{},timeStamp:{},nonce:{}", msgSignature, timeStamp, nonce);
            // 从请求中读取整个post数据
            InputStream inputStream;
            String postData;
            inputStream = request.getInputStream();
            postData = IOUtils.toString(inputStream, Charset.forName("UTF-8"));
            log.info("postData:{}", postData);

            WXBizMsgCrypt wxBizMsgCrypt = new WXBizMsgCrypt(wxThirdConfig.getComponentToken(),
                    wxThirdConfig.getComponentAesKey(),
                    wxThirdConfig.getComponentAppId());
            String msg = wxBizMsgCrypt.decryptMsg(msgSignature, timeStamp, nonce, postData);
            log.info("解密后: {}", msg);
            Map<String, Object> result = XmlUtil.xmlToMap(msg);
            String infoType = result.get("InfoType").toString();
            switch (infoType) {
                case "component_verify_ticket":   //接收票据 【component_verify_ticket】
                    Object componentVerifyTicket = result.get("ComponentVerifyTicket");
                    log.info("ComponentVerifyTicket值为:{}", componentVerifyTicket);
                    //存入redis
                    String redisKey = String.format(CacheConstant.THIRD_COMPONENT_VERIFY_TICKET, wxThirdConfig.getComponentAppId());
                    stringRedisTemplate.opsForValue().set(redisKey, componentVerifyTicket.toString(), 60 * 60 * 10, TimeUnit.SECONDS);
                    break;
                default:
                    break;
            }
        } catch (Exception e) {
            log.error("报错:{}", e.getMessage());
        }

        return "success";
    }

WXBizMsgCrypt 这些类都是微信官方解密工具类,不过这边有坑,就是他的Base64解密方式,请自主替换,否则可能会出现解密错误,这是一个坑点。第二个坑点,除了替换Base64解密方法,XML解密的时候会出现空指针的情况,这边我直接给替换的代码,XMLParse类下的extract方法

public static Object[] extract(String xmltext) throws AesException     {
		Object[] result = new Object[3];
		try {
			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
			DocumentBuilder db = dbf.newDocumentBuilder();
			StringReader sr = new StringReader(xmltext);
			InputSource is = new InputSource(sr);
			Document document = db.parse(is);

			Element root = document.getDocumentElement();
			NodeList nodelist1 = root.getElementsByTagName("Encrypt");
			NodeList nodelist2 = root.getElementsByTagName("ToUserName");
			result[0] = 0;
			result[1] = nodelist1.item(0).getTextContent();
			//注意这里,获取ticket中的xml里面没有ToUserName这个元素,官网原示例代码在这里会报空
			//空指针,所以需要处理一下
			if (nodelist2 != null) {
				if (nodelist2.item(0) != null) {
					result[2] = nodelist2.item(0).getTextContent();
				}
			}
			return result;
		} catch (Exception e) {
			e.printStackTrace();
			throw new AesException(AesException.ParseXmlError);
		}
	}

会报空指针的就是nodelist2那里了,已做注释
我使用的是redis,这边保存好票据,然后微信十分钟推送一次,但是票据有效期是两个小时的,为了保证在获取下面的凭证时不过期,但是请及时更新最新票据。
2.获取令牌component_access_token,该令牌只跟当前的第三方平台有关,不与接入的公众号有关哦。这边获取比较简单,post参数过去获取结果即可,不再赘述,component_appid,component_appsecret均可在你第三方平台审核通过后查看
在这里插入图片描述
3.预授权码。这一步是相对比较重要的,这一步是为了生成授权链接给你所需要接入的公众号管理员授权使用。不过需要注意的时,说一下令牌的使用方式,令牌一般作为被调用接口的 GET 参数 component_access_token 的值使用。所以我们一般都需要在调用地址上拼接上get参数去调用,也就是http://www.xxx.com?component_access_token=xxxx这种方式作为调用地址
在这里插入图片描述
4.获取到预授权码后,我们可以生成授权地址了,这里我采用直接生成授权链接的方式给公众号管理员使用,代码如下:

  @ApiOperation(httpMethod = "GET", value = "生成授权Url")
    @GetMapping("generateAuthUrl")
    @MethodLog(description = "生成授权Url")
    public ResultData generateAuthUrl(@RequestParam("channel") String channel) throws UnsupportedEncodingException {
        MediaChannel mediaChannel = channelService.getChannelByAbbreviation(channel);
        if (mediaChannel == null) {
            return RespUtils.responseFail("channel不存在啊,靓仔!");
        }
        String url = "https://mp.weixin.qq.com/safe/bindcomponent?action=bindcomponent&no_scan=1&component_appid="
                + wxThirdConfig.getComponentAppId() + "&pre_auth_code="
                + WeChatUtils.getPreAuthCode() + "&redirect_uri="
                + URLEncoder.encode("http://xxxxxxxx.com/media/auth/getAuthCode/" + channel, "UTF-8")
                + "&auth_type=3";
        return RespUtils.responseOk(url);
    }

根据需要替换相应的参数即可,这边使用了Restful的方式去接受我们所需要的额外参数,生成地址后,给到公众号管理员去授权即可,但是测试阶段只能授权给你在提交审核时所填写的测试公众号哦。管理员授权后,微信会将授权码推送到我们的重定向地址的,
5.获取到授权信息

 @ApiOperation(httpMethod = "POST", value = "获取授权码")
    @RequestMapping(value = "/getAuthCode/{channel}")
    public String getAuthCode(@PathVariable("channel") String channel, @RequestParam("auth_code") String auth_code) {
        log.info("授权码为:{},渠道号:{}", auth_code, channel);
        //使用授权码获取授权信息
        String apiQueryAuthUrl = WeChatUtils.setAccessToken(WxThirdConstant.API_QUERY_AUTH_URL);

        JSONObject requestJson = new JSONObject();
        requestJson.put("component_access_token", WeChatUtils.getComponentAccessToken());
        requestJson.put("component_appid", wxThirdConfig.getComponentAppId());
        requestJson.put("authorization_code", auth_code);
        String result = HttpUtil.post(apiQueryAuthUrl, requestJson.toJSONString());
        log.info("获取授权信息:{}", result);
        JSONObject resultJson = JSONObject.parseObject(result);
        RespApiQueryAuthBo respApiQueryAuthBo = JSONObject.parseObject(resultJson.getString("authorization_info"), RespApiQueryAuthBo.class);
		//todo 这边就进行你自己的业务逻辑,
		//比如你携带过来的channel参数逻辑处理

        //设置重刷token
        String refreshTokenKey = String.format(CacheConstant.THIRD_API_QUERY_AUTH_REFRESH_TOKEN, respApiQueryAuthBo.getAuthorizer_appid());
        CacheRefreshAccessToken cacheRefreshAccessToken = new CacheRefreshAccessToken();
        BeanUtils.copyProperties(respApiQueryAuthBo, cacheRefreshAccessToken);
        stringRedisTemplate.opsForValue().set(refreshTokenKey, JSONObject.toJSONString(cacheRefreshAccessToken));
        //设置token
        String authAccessTokenKey = String.format(CacheConstant.THIRD_AUTHORIZER_ACCESS_TOKEN, respApiQueryAuthBo.getAuthorizer_appid());
        stringRedisTemplate.opsForValue().set(authAccessTokenKey,
                respApiQueryAuthBo.getAuthorizer_access_token(),
                6000, TimeUnit.SECONDS);
        return "success";
    }

这边可以获取到公众号的appId之类的,还有授权方Id authorizer_appid跟重刷凭据authorizer_refresh_token以及接口调用令牌authorizer_access_token,这边请妥善保管好重刷令牌,一旦重刷令牌丢失,只能重新授权,而重刷令牌是用来刷新调用令牌authorizer_access_token的,而调用令牌是用来用以第三方平台代公众号业务开发的凭据,两小时过期哦,过期后用重刷令牌获取最新凭据。

结束

好啦,大体流程记录如下,其余接口开发请参照接口文档啦,官方接口文档在这哦:微信第三方平台开放文档

需要我那个微信开发加解密的地址在这啦微信第三方平台加解密工具类

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值