微信开放平台授权流程

创建公众号第三方平台步骤
(一)用户登录后,依次进入管理中心、公众号第三方平台、创建公众号第三方平台。
在这里插入图片描述

(二)、输入基本信息
输入基本信息中要特别注意,平台名称是不可以改变的,所以一定要慎重填写,一个账户只能创建5个第三方平台,如果你要是填写错了,资源就浪费了,所有资源浪费之后你只能再掏腰包300大元。
平台简介和平台图片都是后续可以改的,但是也建议不要随便填写,每次更改信息都需要再一次的审核,很麻烦。
在这里插入图片描述

(三)、选择权限集
权限集这部分就根据你的实际需要选择了,建议不要选择太多,权限集选择的越多,被客户取消的可能性就越大。另外第一个权限集轻易不要选择,因为此权限集选择之后,微信公众号后台的菜单和自动回复等功能将全部无效。如果你有提供不了相关的功能,那么你的授权一定会被取消。慎重选择。

在这里插入图片描述

(四)、填写开发资料
开发资料包含两部分:登录授权相关、授权后代替公众号实现业务。详细的说明都很清晰。

在这里插入图片描述
在这里插入图片描述

(五)、提交 等待审核
提交之后耐心等待。

四、第三方平台授权 技术 流程图

在这里插入图片描述

五 授权流程详解
1、推送component_verify_ticket协议
第三方平台创建审核通过后,微信服务器会向其“授权事件接收URL”每隔10分钟定时推送component_verify_ticket,向第三方的消息接收地址推送一次component_verify_ticket,第三方服务器 收到ticket进行解密,接收到后必须直接返回字符串success

POST数据示例


1413192605


注意:component_verify_ticket的有效时间较component_access_token更长,建议保存最近可用的component_verify_ticket,在component_access_token过期之前使用该ticket进行更新,避免出现因为ticket接收失败而无法更新component_access_token的情况。

2、获取第三方平台component_access_token
第三方平台component_access_token是第三方平台的下文中接口的调用凭据,也叫做令牌(component_access_token)。每个令牌是存在有效期(2小时)的,且令牌的调用不是无限制的,请第三方平台做好令牌的管理,在令牌快过期时(比如1小时50分)再进行刷新。
接口调用请求说明
http请求方式: POST(请使用https协议)
https://api.weixin.qq.com/cgi-bin/component/api_component_token
POST数据示例:
{
“component_appid”:“appid_value” ,
“component_appsecret”: “appsecret_value”,
“component_verify_ticket”: “ticket_value”
}

返回结果示例
{“component_access_token”:“61W3mEpU66027wgNZ_MhGHNQDHnFATkDa9-2llqrMBjUwxRSNPbVsMmyD-yq8wZETSoE5NQgecigDrSHkPtIYA”, “expires_in”:7200}

3、获取预授权码pre_auth_code
该API用于获取预授权码。预授权码pre_auth_code用于公众号或小程序授权时的第三方平台方安全验证。
接口调用请求说明
http请求方式: POST(请使用https协议)
https://api.weixin.qq.com/cgi-bin/component/api_create_preauthcode?component_access_token=xxx
POST数据示例:
{
“component_appid”:“appid_value”
}
返回结果示例
{“pre_auth_code”:“Cx_Dk6qiBE0Dmx4EmlT3oRfArPvwSQ-oa3NL_fwHM7VI08r52wazoZX2Rhpz1dEw”,“expires_in”:600}

引入用户进入授权页
第三方平台方可以在自己的网站中放置“微信公众号授权”或者“小程序授权”的入口,引导公众号和小程序管理员进入授权页。
授权页网址为:
https://mp.weixin.qq.com/cgi-bin/componentloginpage?component_appid=xxxx&pre_auth_code=xxxxx&redirect_uri=xxxx&auth_type=xxx。
参数 是否必填 参数说明
component_appid 是 第三方平台方appid
pre_auth_code 是 预授权码
redirect_uri 是 回调URI
auth_type 否 要授权的帐号类型, 1则商户扫码后,手机端仅展示公众号、2表示仅展示小程序,3表示公众号和小程序都展示。如果为未制定,则默认小程序和公众号都展示。第三方平台开发者可以使用本字段来控制授权的帐号类型。

4、使用授权码换取公众号或小程序的接口调用凭据和授权信息
该API用于使用授权码换取授权公众号或小程序的授权信息,并换取authorizer_access_token和authorizer_refresh_token。 授权码的获取,需要在用户在第三方平台授权页中完成授权流程后,在回调URI中通过URL参数提供给第三方平台方。请注意,由于现在公众号或小程序可以自定义选择部分权限授权给第三方平台,因此第三方平台开发者需要通过该接口来获取公众号或小程序具体授权了哪些权限,而不是简单地认为自己声明的权限就是公众号或小程序授权的权限。
接口调用请求说明
http请求方式: POST(请使用https协议)
https://api.weixin.qq.com/cgi-bin/component/api_query_auth?component_access_token=xxxx
POST数据示例:
{
“component_appid”:“appid_value” ,
“authorization_code”: “auth_code_value”
}

返回结果示例
{
“authorization_info”: {
“authorizer_appid”: “wxf8b4f85f3a794e77”,
“authorizer_access_token”: “QXjUqNqfYVH0yBE1iI_7vuN_9gQbpjfK7hYwJ3P7xOa88a89-Aga5x1NMYJyB8G2yKt1KCl0nPC3W9GJzw0Zzq_dBxc8pxIGUNi_bFes0qM”,
“expires_in”: 7200,
“authorizer_refresh_token”: “dTo-YCXPL4llX-u1W1pPpnp8Hgm4wpJtlR6iV0doKdY”,
“func_info”: [
{
“funcscope_category”: {
“id”: 1
}
},
{
“funcscope_category”: {
“id”: 2
}
},
{
“funcscope_category”: {
“id”: 3
}
}
]
}}

5、获取(刷新)授权公众号或小程序的接口调用凭据(令牌)
该API用于在授权方令牌(authorizer_access_token)失效时,可用刷新令牌(authorizer_refresh_token)获取新的令牌。请注意,此处token是2小时刷新一次,开发者需要自行进行token的缓存,避免token的获取次数达到每日的限定额度。缓存方法可以参考:http://mp.weixin.qq.com/wiki/2/88b2bf1265a707c031e51f26ca5e6512.html
当换取authorizer_refresh_token后建议保存。
接口调用请求说明
http请求方式: POST(请使用https协议)
https:// api.weixin.qq.com /cgi-bin/component/api_authorizer_token?component_access_token=xxxxx
POST数据示例:
{
“component_appid”:“appid_value”,
“authorizer_appid”:“auth_appid_value”,
“authorizer_refresh_token”:“refresh_token_value”,
}

返回结果示例
{
“authorizer_access_token”: “aaUl5s6kAByLwgV0BhXNuIFFUqfrR8vTATsoSHukcIGqJgrc4KmMJ-JlKoC_-NKCLBvuU1cWPv4vDcLN8Z0pn5I45mpATruU0b51hzeT1f8”,
“expires_in”: 7200,
“authorizer_refresh_token”:
“BstnRqgTJBXb9N2aJq6L5hzfJwP406tpfahQeLNxX0w”
}
6、获取授权方的帐号基本信息
该API用于获取授权方的基本信息,包括头像、昵称、帐号类型、认证类型、微信号、原始ID和二维码图片URL。
需要特别记录授权方的帐号类型,在消息及事件推送时,对于不具备客服接口的公众号,需要在5秒内立即响应;而若有客服接口,则可以选择暂时不响应,而选择后续通过客服接口来发送消息触达粉丝。
(1)公众号获取方法如下:
接口调用请求说明
http请求方式: POST(请使用https协议)
https://api.weixin.qq.com/cgi-bin/component/api_get_authorizer_info?component_access_token=xxxx
POST数据示例:
{
“component_appid”:“appid_value” ,
“authorizer_appid”: “auth_appid_value”
}

返回结果示例
{
“authorizer_info”: {
“nick_name”: “微信SDK Demo Special”,
“head_img”: “http://wx.qlogo.cn/mmopen/GPy”,
“service_type_info”: { “id”: 2 },
“verify_type_info”: { “id”: 0 },
“user_name”:“gh_eb5e3a772040”,

“principal_name”:“腾讯计算机系统有限公司”,

“business_info”: {“open_store”: 0, “open_scan”: 0, “open_pay”: 0, “open_card”: 0,
“open_shake”: 0},
“alias”:“paytest01”
“qrcode_url”:“URL”,
},
“authorization_info”: {
“authorization_appid”: “wxf8b4f85f3a794e77”,
“func_info”: [
{ “funcscope_category”: { “id”: 1 } },
{ “funcscope_category”: { “id”: 2 } },
{ “funcscope_category”: { “id”: 3 } }
]
}
}

(2)小程序获取方法如下
接口调用请求说明
http请求方式: POST(请使用https协议)
https://api.weixin.qq.com/cgi-bin/component/api_get_authorizer_info?component_access_token=xxxx
POST数据示例:
{
“component_appid”:“appid_value” ,
“authorizer_appid”: “auth_appid_value”
}

返回结果示例:
{
“authorizer_info”: {
“nick_name”: “微信SDK Demo Special”,
“head_img”: “http://wx.qlogo.cn/mmopen/GPy”,
“service_type_info”: { “id”: 2 },
“verify_type_info”: { “id”: 0 },
“user_name”:“gh_eb5e3a772040”,
“principal_name”:“腾讯计算机系统有限公司”,
“business_info”: {“open_store”: 0, “open_scan”: 0, “open_pay”: 0, “open_card”: 0, “open_shake”: 0},
“qrcode_url”:“URL”,
“signature”: “时间的水缓缓流去”,
“MiniProgramInfo”: {
“network”: {
“RequestDomain”:[“https://www.qq.com”,“https://www.qq.com”],
“WsRequestDomain”:[“wss://www.qq.com”,“wss://www.qq.com”],
“UploadDomain”:[“https://www.qq.com”,“https://www.qq.com”],
“DownloadDomain”:[“https://www.qq.com”,“https://www.qq.com”],
},
“categories”:[{“first”:“资讯”,“second”:“文娱”},{“first”:“工具”,“second”:“天气”}],
“visit_status”: 0,
}
},
“authorization_info”: {
“authorization_appid”: “wxf8b4f85f3a794e77”,
“func_info”: [
{ “funcscope_category”: { “id”: 17 } },
{ “funcscope_category”: { “id”: 18 } },
{ “funcscope_category”: { “id”: 19 } }
]
}
}

7、获取授权方的选项设置信息
该API用于获取授权方的公众号或小程序的选项设置信息,如:地理位置上报,语音识别开关,多客服开关。注意,获取各项选项设置信息,需要有授权方的授权,详见权限集说明。
接口调用请求说明
http请求方式: POST(请使用https协议)
https://api.weixin.qq.com/cgi-bin/component/api_get_authorizer_option?component_access_token=xxxx
POST数据示例
{
“component_appid”:“appid_value”,
“authorizer_appid”: " auth_appid_value ",
“option_name”: “option_name_value”
}
返回结果示例
{
“authorizer_appid”:“wx7bc5ba58cabd00f4”,
“option_name”:“voice_recognize”,
“option_value”:“1”
}
8、设置授权方的选项信息
该API用于设置授权方的公众号或小程序的选项信息,如:地理位置上报,语音识别开关,多客服开关。注意,设置各项选项设置信息,需要有授权方的授权,详见权限集说明。
接口调用请求说明
http请求方式: POST(请使用https协议)
https://api.weixin.qq.com/cgi-bin/component/ api_set_authorizer_option?component_access_token=xxxx
POST数据示例
{
“component_appid”:“appid_value”,
“authorizer_appid”: " auth_appid_value ",
“option_name”: “option_name_value”,
“option_value”:“option_value_value”
}
返回结果示例
{
“errcode”:0,
“errmsg”:“ok”
}

9、推送授权相关通知
当公众号对第三方平台进行授权、取消授权、更新授权后,微信服务器会向第三方平台方的授权事件接收URL(创建第三方平台时填写)推送相关通知。
POST数据示例(授权成功通知)

第三方平台appid
1413192760
authorized
公众号appid
授权码(code)
过期时间
预授权码

POST数据示例(取消授权通知) 第三方平台appid 1413192760 unauthorized 公众号appid POST数据示例(授权更新通知) 第三方平台appid 1413192760 updateauthorized 公众号appid 授权码(code) 过期时间 预授权码

由于需要用到加密算法,需要替换部分文件。
在java官方网站下载JCE无限制权限策略文件(JDK7的下载地址: * http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html)
下载后解压,可以看到local_policy.jar和US_export_policy.jar以及readme.txt。
如果安装了JRE,将两个jar文件放到%JRE_HOME%\lib\security目录下覆盖原来的文件。
如果安装了JDK,将两个jar文件放到%JDK_HOME%\jre\lib\security目录下覆盖原来文件。

|/**
* 处理授权事件的推送
*
* @param request
* @throws IOException
* @throws AesException
* @throws DocumentException
*/

public void processAuthorizeEventMessage(HttpServletRequest request) throws IOException, DocumentException, AesException,Exception{
    String nonce = request.getParameter("nonce");
    String timestamp = request.getParameter("timestamp");
    String signature = request.getParameter("signature");
    String msgSignature = request.getParameter("msg_signature");
    LogUtil.info("xml中的信息:"+nonce+","+timestamp+","+signature+","+msgSignature);
    ComponentToken componentTokenfore = componentTokenInfoQuery();
    COMPONENT_APPID=componentTokenfore.getComponent_appid();
    COMPONENT_APPSECRET=componentTokenfore.getComponent_appsecret();
    COMPONENT_TOKEN=componentTokenfore.getComponent_token();
    COMPONENT_ENCODINGAESKEY=componentTokenfore.getComponent_encodingaeskey();
 LogUtil.info("三方基本信息:"+COMPONENT_APPID+"------"+COMPONENT_APPSECRET+"------"+COMPONENT_TOKEN+"------"+COMPONENT_ENCODINGAESKEY);
    if (!StringUtils.isNotBlank(msgSignature))
        return;// 微信推送给第三方开放平台的消息一定是加过密的,无消息加密无法解密消息
    boolean isValid = checkSignature(COMPONENT_TOKEN, signature, timestamp, nonce);
LogUtil.info("-------------isValid:"+isValid+"-------------");
    if (isValid) {
        StringBuilder sb = new StringBuilder();
        BufferedReader in = request.getReader();
        String line;
        while ((line = in.readLine()) != null) {
            sb.append(line);
        }
        String xml = sb.toString();
        LogUtil.info("------------------------解密前:"+xml+"----------------------");
       LogUtil.info("第三方平台全网发布-----------------------原始 Xml="+xml);
       String encodingAesKey = COMPONENT_ENCODINGAESKEY;// 第三方平台组件加密密钥
        String appId = getAuthorizerAppidFromXml(xml);// 此时加密的xml数据中ToUserName是非加密的,解析xml获取即可
        LogUtil.info("第三方平台全网发布-------------appid----------getAuthorizerAppidFromXml(xml)-----------appId="+appId);
        WXBizMsgCrypt pc = new WXBizMsgCrypt(COMPONENT_TOKEN, COMPONENT_ENCODINGAESKEY, COMPONENT_APPID);
        WXBizMsgCrypt.AnotherElement.appId.setName("AppId");
        xml = pc.decryptMsg(msgSignature, timestamp, nonce, xml,WXBizMsgCrypt.AnotherElement.appId);

        LogUtil.info("第三方平台全网发布-----------------------解密后 Xml="+xml);
          saveTicketToTicket(xml);
      processAuthorizationEvent(xml);//保存Ticket操作!
        Document  doc = DocumentHelper.parseText(xml);
        Element rootElt = doc.getRootElement();
        String type = rootElt.elementText("InfoType"); 
         if("authorized".equals(type)){
       String ticket = rootElt.elementText("ComponentVerifyTicket");//是否保存数据库或者存入静态类变量
        	saveTicketToTicket(xml);//暂时缓存静态变量
        }else if ("unauthorized".equals(type)) {  
            //取消授权的通知
        	 String authorizer_appid = rootElt.elementText("AuthorizerAppid");//取消授权方公众号的appid
        	 TickService.authorizationInfoUpdateStatus(authorizer_appid);
        }else if("updateauthorized".equals(type)){
        	//更新授权,可以更新授权方令牌authorizer_access_token,刷新令牌authorizer_refresh_token,权限集列表等  
        	String component_appid=rootElt.elementText("AppId");
        	String authorizer_appid=rootElt.elementText("AuthorizerAppid");
        	String authorizer_refresh_token="";//刷新的token如何获取
        	ApiAuthorizerToken apiAuthorizerToken = new ApiAuthorizerToken();
        	apiAuthorizerToken.setComponent_appid(component_appid);
        	apiAuthorizerToken.setAuthorizer_appid(authorizer_appid);
        	apiAuthorizerToken.setAuthorizer_refresh_token(authorizer_refresh_token);
        	String componentVerifyTicket = WeixinOpenAccountEntity.getComponentVerifyTicket();
            ApiComponentToken apiComponentToken = new ApiComponentToken();
            apiComponentToken.setComponent_appid(COMPONENT_APPID);
            apiComponentToken.setComponent_appsecret(COMPONENT_APPSECRET);
            apiComponentToken.setComponent_verify_ticket(componentVerifyTicket);
			String component_access_token = getComponent_access_token(apiComponentToken);
			ApiAuthorizerTokenRet apiAuthorizerTokenRet = apiAuthorizerToken(apiAuthorizerToken,,component_access_token);//调用刷新token换取授权方token
			String Authorizer_access_token=apiAuthorizerTokenRet.getAuthorizer_access_token();
    		String Authorizer_refresh_token=apiAuthorizerTokenRet.getAuthorizer_refresh_token();
    		String Expires_in=String.valueOf(apiAuthorizerTokenRet.getExpires_in());
    		AuthorizationInfo authorizationInfo = new AuthorizationInfo();
    		authorizationInfo.setAuthorizer_access_token(Authorizer_access_token);
    		authorizationInfo.setAuthorizer_refresh_token(Authorizer_refresh_token);
    		authorizationInfo.setExpires_in(Expires_in);
    		authorizationInfo.setAuthorizer_appid(authorizer_appid);
    		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
	        String adtime = sdf.format(new Date());
    		authorizationInfo.setAdtime(adtime);//为得到的token再次设置时间
	LogUtil.info("==============刷新token所用时间:"+adtime+"====================");
    		TickService.authorizationInfo_update(authorizationInfo);//更新token及刷新token数据库保存
          }else{
        	saveTicketToTicket(xml);//暂时缓存静态变量
        }
        String componentVerifyTicket = WeixinOpenAccountEntity.getComponentVerifyTicket();//每十分钟获得一次
        ApiComponentToken apiComponentToken = new ApiComponentToken();
        apiComponentToken.setComponent_appid(COMPONENT_APPID);
        apiComponentToken.setComponent_appsecret(COMPONENT_APPSECRET);
        apiComponentToken.setComponent_verify_ticket(componentVerifyTicket);
        //更新ticket入库
        ComponentToken componentToken =null;
        componentToken = new ComponentToken();
        componentToken.setComponent_verify_ticket(componentVerifyTicket);
        TickService.updateComponentVerifyTicket(componentToken);//更新ticket
        String component_access_token = "";
        ComponentToken componentTokenSS=findComponentTokenInfo(COMPONENT_APPID);
        if(StringUtil.isEmpty(componentTokenSS.getComponent_verify_ticket())){
        	 component_access_token = getComponent_access_token(apiComponentToken);
        }else{
        	 component_access_token = checkComponentTokenExpiresIn();
			 LogUtil.info("component_access_token:"+component_access_token);//有效期为2小时(需要做好令牌的管理)
	  }
}

猜你喜欢

转载自blog.csdn.net/kiritolr/article/details/82782502
今日推荐