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

举报
悟空码字 发表于 2023/04/15 12:35:38 2023/04/15
【摘要】 不管是自己在创业或学习也好,还是公司的开发任务也罢,有很多小伙伴在开发多小程序管理或多公众号管理的功能,这就不得不去对接微信开放平台里面的第三方平台接口。

大家好,我是小悟

不管是自己在创业或学习也好,还是公司的开发任务也罢,有很多小伙伴在开发多小程序管理或多公众号管理的功能,这就不得不去对接微信开放平台里面的第三方平台接口。

你别说,这个功能确实好用,我们就拿代商家管理小程序来说,对于有批量孵化小程序需求的业务来说,拥有了这样的功能,能节省不少成本嘞。除了这个,关键还有一个好处,就是只需收集极少数个参数信息,通过接口注册很多个已认证的小程序,目前没有上限的限制。注意,是已认证的,也就是免认证费的,还是永久的哦。


在看官方文档之前,你可能会想,接口嘛,对我们后端同学来说,我们就是专门造接口的,开什么玩笑,根本不在话下。不过,当你去翻了接口文档之后你就不会有这么嚣张的想法了,来,简单瞜一眼,

微信开放平台之第三方平台开发之流程攻略_代小程序实现业务_02

接口多的很,多也就算了,关键看不懂,不知道先从哪里入手啊。插一句,其实现在再去看官方文档,已经整理的更整洁了,比起我对接的那会啊,不知道好多少,我对接的那时候文档可以用杂乱无章来形容不为过,没办法,人总要成长,接口文档也是。

扯远了,文档确实变好了,但对于新手来说第一次看还是一头雾水,真的是不知道该从哪里入手啊。最重要的其实就是获取到component_access_token和授权帐号的authorizer_access_token,别担心,悟空帮你理一下如何入手,按照如下顺序进行开发。

【验证票据】:首先就是验证票据,也就是这个component_verify_ticket,在第三方平台创建审核通过后,微信服务器会向其 ”授权事件接收URL” 每隔 10 分钟以 POST 的方式推送 component_verify_ticket。
微信开放平台之第三方平台开发之流程攻略_代小程序实现业务_04

public void saveTicket(HttpServletRequest request, HttpServletResponse response) throws IOException {
  String msgSignature = request.getParameter("msg_signature");// 微信加密签名
  String timeStamp = request.getParameter("timestamp");// 时间戳    
  String nonce = request.getParameter("nonce"); // 随机数  
  BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream(),"UTF-8"));
  StringBuffer sb = new StringBuffer();
  String line = null;
  while ((line = br.readLine()) != null) {
    sb = sb.append(line);
  }
  String postData = sb.toString();
  try {
    AuthorizedUtils.saveComponentVerifyTicket(msgSignature, timeStamp, nonce, postData);
  } catch (Exception e) {
    logger.error("系统异常", e);
  } finally {
    // 响应消息
    PrintWriter out = response.getWriter();
    out.print("success");
  }
}

这个不是API接口,是微信主动向我们的服务器推送的一个参数数据。至于第三方平台怎么配置,这个应该不难,如果不会的同学多了,以后就抽空写一篇介绍一下怎么配置。

【获取令牌】:我们拿到component_verify_ticket之后,接着就要去调用获取令牌的接口,获取到第三方平台接口的调用凭据component_access_token的值。令牌的获取是有限制的,每个令牌的有效期为 2 小时,请自行做好令牌的管理,在令牌快过期时(比如1小时50分),重新调用接口获取。

微信开放平台之第三方平台开发之流程攻略_代小程序实现业务_05

public static ComponentToken getComponentToken(String ticket) {
RedisService<ComponentToken> redisService = RedisService.load();
ComponentToken componentToken = redisService.load(ComponentToken.COMPONENTTOKEN_ID, ComponentToken.class);  
if (componentToken == null) {
  String encryptAppId = ThirdPlat.PLAT_APPID;
  String appId = EnDecryptUtil.d3esDecode(encryptAppId);
  String encryptSecret = ThirdPlat.PLAT_SECRET;
  String secret = EnDecryptUtil.d3esDecode(encryptSecret); 
  String requestUrl = AuthAccessUrl.COMPONENT_ACCESS_URL;
  Map<String, String> map = new HashMap<>(); 
  map.put("component_appid", appId); //第三方平台appid
  map.put("component_appsecret", secret); //第三方平台appsecret
  map.put("component_verify_ticket", ticket); 
  String outputStr = JSONObject.toJSONString(map);
  logger.warn("请求数据"+outputStr);
  JSONObject jsonObject = HttpRequestUtils.httpRequest(requestUrl, "POST", outputStr);
    if (null != jsonObject) {
    long expires = System.currentTimeMillis() + 7200;
    try{
      expires = System.currentTimeMillis() + jsonObject.getIntValue("expires_in");        
    }catch (Exception e) {
    }
    try {
      componentToken = new ComponentToken();
      componentToken.setComponentAccessToken(jsonObject.getString("component_access_token"));
      componentToken.setExpiresIn(expires);
      redisService.save(componentToken, ComponentToken.class);
    } catch (Exception e) {
      componentToken = null;
      logger.error("系统异常", e);
    }
  }
} else {
  long sysTime = System.currentTimeMillis();
  if (sysTime >= componentToken.getExpiresIn()) {
    redisService.delete(ComponentToken.COMPONENTTOKEN_ID, ComponentToken.class);
    componentToken = getComponentToken(ticket);
  }else{
  }
}
return componentToken;
}

【获取预授权码】:我们拿到component_access_token之后,接着就要去调用获取预授权码的接口,获取到pre_auth_code的值。这个是第三方平台方实现授权托管的必备信息,每个预授权码有效期为 1800秒。

微信开放平台之第三方平台开发之流程攻略_微信第三方开放平台_06

public static String getPreAuthCode(String ticket) {
ComponentToken componentToken = getComponentToken(ticket);
String encryptAppId = ThirdPlat.PLAT_APPID;
String appId = EnDecryptUtil.d3esDecode(encryptAppId);
String url = AuthAccessUrl.PRE_AUTH_CODE_URL + componentToken.getComponentAccessToken();
Map<String, String> map = new HashMap<String, String>();
map.put("component_appid", appId);
    JSONObject jsonObject = HttpRequestUtils.httpRequest(url, "POST", JSONObject.toJSONString(map));   
return jsonObject.getString("pre_auth_code");
}

【拼接授权链接】:我们拿到pre_auth_code之后,这一步不需要调用接口,而是拼接授权链接。准备“授权回调 URI”,公众号/小程序管理员扫码或者访问移动端授权链接,确认同意授权给第三方平台。管理员授权确认之后,授权页会自动跳转进入回调 URI,并在 URL 参数中返回授权码和过期时间(redirect_url?auth_code=xxx&expires_in=600)。微信开放平台之第三方平台开发之流程攻略_微信第三方开放平台_07

public AjaxResult getMchWebAuthUrl(@PathVariable("id") String id) {
RedisService<ComponentVerifyTicket> redisService = RedisService.load();
ComponentVerifyTicket componentVerifyTicket = redisService.load(ComponentVerifyTicket.COMPONENT_VERIFY_TICKET_ID,
    ComponentVerifyTicket.class);
if(componentVerifyTicket == null){
  return AjaxResult.error("引入用户进入授权页失败,component_verify_ticket为null",null);
}else{
  String preAuthCode = AuthorizedUtils.getPreAuthCode(componentVerifyTicket.getComponentVerifyTicket());
  String encryptAppId = ThirdPlat.PLAT_APPID;
  String appId = EnDecryptUtil.d3esDecode(encryptAppId);
  String auth_type = ThirdPlat.AUTH_TYPE;
  String requestUrl = AuthAccessUrl.WEB_AUTH_URL;
  try {
    requestUrl = requestUrl.replace("COMPONENT_APPID", appId).replace("PRE_AUTH_CODE", preAuthCode)
        .replace("REDIRECT_URI", URLEncoder.encode(ThirdPlat.REDIRECT_URI.replace("MERCHANTID", id),"UTF-8")).replace("AUTH_TYPE", auth_type);
  } catch (UnsupportedEncodingException e) {
    e.printStackTrace();
  }
  return AjaxResult.success("操作成功",requestUrl);
}
}

【获取刷新令牌】:我们拿到auth_code之后,接着就要去调用获取刷新令牌的接口,当用户在第三方平台授权页中完成授权流程后,第三方平台开发者可以在回调 URI 中通过 URL 参数获取授权码(authorization_code)。然后使用该接口可以换取公众号/小程序的接口调用令牌(authorizer_access_token),然后以该 token 调用公众号或小程序的相关 API。

微信开放平台之第三方平台开发之流程攻略_代小程序实现业务_08

public static AuthorizationInfo initAuthorizationInfo(String code) {
		RedisService<ComponentVerifyTicket> redisService = RedisService.load();
		ComponentVerifyTicket componentVerifyTicket = redisService.load(ComponentVerifyTicket.COMPONENT_VERIFY_TICKET_ID,
				ComponentVerifyTicket.class);
		ComponentToken componentToken = getComponentToken(componentVerifyTicket.getComponentVerifyTicket());
		String encryptAppId = ThirdPlat.PLAT_APPID;
		String se_appId = EnDecryptUtil.d3esDecode(encryptAppId);
		String requestUrl = AuthAccessUrl.API_QUERY_AUTHAPI.replace("COMPONENT_ACCESS_TOKEN", componentToken.getComponentAccessToken());
		Map<String, String> map = new HashMap<String, String>();
		map.put("component_appid", se_appId);
		map.put("authorization_code", code);
		String outputStr = JSONObject.toJSONString(map);
		JSONObject jsonObject = HttpRequestUtils.httpRequest(requestUrl, "POST", outputStr);
		AuthorizationInfo authorizationInfo = null;
		if (jsonObject != null && jsonObject.getJSONObject("authorization_info") != null) {
			long sys_time = System.currentTimeMillis();
			authorizationInfo = jsonObject.getJSONObject("authorization_info").toJavaObject(AuthorizationInfo.class);
			long expires = sys_time + 6600000;
			authorizationInfo.setExpires_in(expires);
			RedisService<AuthorizationInfo> redisService2 = RedisService.load();
			redisService2.save(authorizationInfo, AuthorizationInfo.class);
		}
		return authorizationInfo;
	}

【获取授权帐号调用令牌】:公众号/小程序的接口调用令牌authorizer_access_token 有效期为 2 小时,authorizer_access_token 失效时,可以使用 authorizer_refresh_token 获取新的 authorizer_access_token。

微信开放平台之第三方平台开发之流程攻略_微信第三方开放平台_09


private static AuthorizationInfo refreshAuthorizerToken(AuthorizationInfo authorizationInfo) {
		RedisService<ComponentVerifyTicket> redisService = RedisService.load();
		ComponentVerifyTicket componentVerifyTicket = redisService.load(ComponentVerifyTicket.COMPONENT_VERIFY_TICKET_ID,
				ComponentVerifyTicket.class);
		ComponentToken componentToken = getComponentToken(componentVerifyTicket.getComponentVerifyTicket());
		String encryptAppId = ThirdPlat.PLAT_APPID;
		String se_appId = EnDecryptUtil.d3esDecode(encryptAppId);
		String requestUrl = AuthAccessUrl.API_AUTHORIZER_TOKEN.replace("COMPONENT_ACCESS_TOKEN", componentToken.getComponentAccessToken());
		Map<String, String> map = new HashMap<>();
		map.put("component_appid", se_appId);
		map.put("authorizer_appid", authorizationInfo.getAuthorizer_appid());
		map.put("authorizer_refresh_token", authorizationInfo.getAuthorizer_refresh_token());
		String outputStr = JSONObject.toJSONString(map);
		JSONObject jsonObject = HttpRequestUtils.httpRequest(requestUrl, "POST", outputStr);
		if(jsonObject != null) {
			authorizationInfo.setAuthorizer_access_token(jsonObject.getString("authorizer_access_token"));
			authorizationInfo.setAuthorizer_refresh_token(jsonObject.getString("authorizer_refresh_token"));
			authorizationInfo.setExpires_in(System.currentTimeMillis() + 6600000);
			RedisService<AuthorizationInfo> redisService2 = RedisService.load();
			redisService2.save(authorizationInfo, AuthorizationInfo.class);
		}
		return authorizationInfo;
	}

大概的入手开发顺序就是这样,只要能拿到component_access_token和authorizer_access_token,那就事半功倍了。至于写代码,当然,那又是一件大工程的事,想到这,头顶又秃了一大片。


您的一键三连,是我更新的最大动力,谢谢

山水有相逢,来日皆可期,谢谢阅读,我们再会

我手中的金箍棒,上能通天,下能探海

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。