微信公众号通过第三方平台完成授权

微信公众号通过第三方平台完成授权前,第三方平台与公众号绑定关系。

为什么要使用第三方平台来完成授权,公众号本身授权也可以,但是微信平台会认为你具有开发能力,免费提供给你的自定义菜单以及其他功能将不能再使用(亲身经历的一个坑,开始使用公众号授权,结束后发现部分功能不能使用)。
在这里插入图片描述

这个地方就是公众号自己授权需要先向微信提供服务器地址,微信会把公众号的一些关注事件,推送的消息等。传递参数到这个地址,我们需要在5s内响应字符串:success给微信,否则微信认为该服务器有问题而不会推送参数过来。当然就是这个服务器地址启用后,会导致公众号本身提供的自定义菜单,消息回复功能等失效。

所以采用了第三方平台来完成公众号的授权,其实授权流程跟公众号授权差不多。首先需要跟公众号一样需要申请一个第三方平台账户(需要200块)。
在第三方平台创建审核通过后,微信服务器会向其 ”授权事件接收URL” 每隔 10 分钟以 POST 的方式推送 component_verify_ticket,
接收 POST 请求后,只需直接返回字符串 success。
第三方平台需要填写 :
1.授权事件接收URL
2.公众号的appid
3.ip白名单
其他需要填写的具体看需要那些。

授权事件接收URL会接收到微信推送的xml字符串,需要将xml解析成json:

public static JSONObject xml2Json(String xmlStr) throws DocumentException {
        Document doc= DocumentHelper.parseText(xmlStr);
        JSONObject json=new JSONObject();
        dom4j2Json(doc.getRootElement(), json);
        return json;
    }

    public static void dom4j2Json(Element element, JSONObject json) {
        //如果是属性
        for (Object o : element.attributes()) {
            Attribute attr = (Attribute) o;
            if (StringUtils.isNotEmpty(attr.getValue())) {
                json.put("@" + attr.getName(), attr.getValue());
            }
        }
        List<Element> childrenElement = element.elements();
        if (CollectionUtils.isEmpty(childrenElement) && StringUtils.isNotEmpty(element.getText())) {//如果没有子元素,只有一个值
            json.put(element.getName(), element.getText());
        }

        for (Element e : childrenElement) {//有子元素
            if (CollectionUtils.isNotEmpty(e.elements())) {//子元素也有子元素
                JSONObject childJson = new JSONObject();
                dom4j2Json(e, childJson);
                Object o = json.get(e.getName());
                if (o != null) {
                    JSONArray jsona = null;
                    if (o instanceof JSONObject) {//如果此元素已存在,则转为jsonArray
                        JSONObject jsono = (JSONObject) o;
                        json.remove(e.getName());
                        jsona = new JSONArray();
                        jsona.add(jsono);
                        jsona.add(childJson);
                    }
                    if (o instanceof JSONArray) {
                        jsona = (JSONArray) o;
                        jsona.add(childJson);
                    }
                    json.put(e.getName(), jsona);
                } else {
                    if (!childJson.isEmpty()) {
                        json.put(e.getName(), childJson);
                    }
                }
            } else {//子元素没有子元素
                for (Object o : element.attributes()) {
                    Attribute attr = (Attribute) o;
                    if (StringUtils.isNotEmpty(attr.getValue())) {
                        json.put("@" + attr.getName(), attr.getValue());
                    }
                }
                if (StringUtils.isNotEmpty(e.getText())) {
                    json.put(e.getName(), e.getText());
                }
            }
        }
    }

从解析的json中拿到字符串 Encrypt ,timestamp,nonce,msg_signature:
使用AES解密:

public class GetMsessage{
	public void getThridMse(JSONObject getData) {
        String encrypt = json.getString("Encrypt");
        String timeStamp = json.getString("timestamp");
        String nonce = json.getString("nonce");
        String msgSignature = json.getString("msg_signature");

        String componentAppId = "第三方平台appid";
        String appSecret = "第三方平台Secret";
        String encodingAesKey = "第三方平台的AES密钥";
        String token = "第三方平台认证服务时填写的一个字符串";


        JSONObject  resJson= getCryptMsg(token,encodingAesKey,componentAppId,encrypt,msgSignature,timeStamp,nonce);
        String verifyTicket = resJson.getString("ComponentVerifyTicket");
        String eventKey = resJson.getString("EventKey");
        String event = resJson.getString("Event");
        String toUserName = resJson.getString("ToUserName");
        String fromUserName = resJson.getString("FromUserName");
        String ticket = resJson.getString("Ticket");
	}
	
	public JSONObject getCryptMsg(String token,String encodingAesKey,String appId,String encrypt,String msgSignature,String timeStamp,String nonce){

        BaseLog.getDailyLog().info("token[{}] encodingAesKey[{}] appId[{}] encrypt[{}] msgSignature[{}] timeStamp[{}] nonce[{}]",
                token, encodingAesKey, appId, encrypt, msgSignature, timeStamp, nonce);

        WXBizMsgCrypt wxBizMsgCrypt = null;
        try {
            wxBizMsgCrypt = new WXBizMsgCrypt(token,encodingAesKey,appId);
        } catch (Exception e) {
            e.printStackTrace();
        }
        JSONObject json = new JSONObject();
        try {
            String xml = wxBizMsgCrypt.decryptMsg(msgSignature,timeStamp,nonce,encrypt);
            try {
                json = xml2Json(xml);
            } catch (DocumentException e) {
                e.printStackTrace();
            }
            BaseLog.getDailyLog().error("解析xml为Json的内容为:"+json.toJSONString());
            return json;
        } catch (AesException e) {
            e.printStackTrace();
            BaseLog.getErrorLog().error(e.getMessage(), e);
            throw new ServiceException(OAuth2ErrorCodeEnum.FAILED_TO_PARSING_XML.getCode(), OAuth2ErrorCodeEnum.FAILED_TO_PARSING_XML.getMsg());
        }
    }
}	

String verifyTicket = resJson.getString(“ComponentVerifyTicket”);
拿到票据后去拿第三方平台的令牌

 public JSONObject getComponentAccessToken(String appId,String appSecret,String componentVerifyTicket,String componentAccessTokenUrl){
       /*  https://api.weixin.qq.com/cgi-bin/component/api_component_token  */

        JSONObject object = new JSONObject();
        object.put("component_appid",appId);
        object.put("component_appsecret",appSecret);
        object.put("component_verify_ticket",componentVerifyTicket);
        String result = doPost(componentAccessTokenUrl, object.toString(), "utf-8");
        BaseLog.getDailyLog().error("获取第三方令牌结果;"+result);
        JSONObject resultJson=JSONObject.parseObject(result);
        return resultJson;
    }

component_appid是第三方平台的appid,component_appsecret是第三平台的secret。

上面post请求返回的结果里面有 component_access_token,第三方平台 access_token用来获取预授权码:

 public JSONObject getPreAuthCode(String preAuthCodeUrl,String componentToken,String appId){
       /*
         POST https://api.weixin.qq.com/cgi-bin/component/api_create_preauthcode
         ?component_access_token=COMPONENT_ACCESS_TOKEN
        */
        StringBuilder sb = new StringBuilder(preAuthCodeUrl);
        String url = sb.append("?").append("component_access_token=").append(componentToken).toString();
        JSONObject object = new JSONObject();
        object.put("component_appid",appId);
        String result = doPost(url, object.toString(), "utf-8");
        BaseLog.getDailyLog().error("获取第三方预授码结果;"+result);
        JSONObject resultJson=JSONObject.parseObject(result);
        return resultJson;
    }

从上面拿到的预授权码 pre_auth_code 后:
在这里插入图片描述
组装一个授权的链接,访问这个链接会生成一个二维码,用公众号拥有者扫描去给第三方平台授权。
然后登录公众号里面在这个地方给第三方平台需要用到的权限。
在这里插入图片描述
到此,是把公众号跟第三方平台绑定成功,给第三方平台授权完成(并不是真正的公众号授权拿到用户信息)。
从上面可以看出,整个代码过程没有用到公众号的信息,所以第三方平台可以给跟个公众号绑定,完成授权。
再后面就是授权了,按公众号授权一样了,先拿到code,再拿token,就有openid然后就可以拿用户信息了。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值