对接微信第三方平台

对接微信第三方平台

首先本人是刚入职场的小菜鸟,因工作需要本次进行了对接微信第三方平台的项目开发。

项目主要实现任务:获取所有已授权小程序的昵称,授权时间和小程序的id

本文主要参考『做一个安静的美男子』阿·成人类电影精华丶的文章

首先将所需的url放入到一个常量类中

package com.xye.core.thirdpartyplug.constant;

public class WxPostUrlConstant {
    private WxPostUrlConstant(){

    }
    /**
     * 微信调用接口url
     */
    public static final String API_COMPONENT_TOKEN_URl="https://api.weixin.qq.com/cgi-bin/component/api_component_token";
    /*
     * 预授权码url*/
    public static final String API_CREATE_PREAUTHCODE_URL="https://api.weixin.qq.com/cgi-bin/component/api_create_preauthcode?component_access_token=";
    /*
     * 获取授权信息url*/
    public static final String API_QUERY_AUTH_URL="https://api.weixin.qq.com/cgi-bin/component/api_query_auth?component_access_token=";
    /*
     * 获取或刷新调用令牌url*/
    public static final String API_AUTHORIZER_TOKEN_URL="https://api.weixin.qq.com/cgi-bin/component/api_authorizer_token?component_access_token=";
    /*
     * 获取授权方的帐号基本信息url*/
    public static final String API_GET_AUTHORIZER_INFO_URL="https://api.weixin.qq.com/cgi-bin/component/api_get_authorizer_info?component_access_token=";
     /*
     * 设置授权方选项信息url*/
    public static final String API_GET_AUTHORIZER_List="https://api.weixin.qq.com/cgi-bin/component/api_get_authorizer_list?component_access_token=";

}

一、获取验证票据 component_verify_ticket

主要用到官方提供的解密加密的工具类

Controller类


@RestController
@RequestMapping("/wechatAuth")
@Slf4j
public class WeChatAuthController {
    @Autowired
    private WeChatAuthService weChatAuthService;


    @PostMapping(path = "/parseRequest")
    @ApiOperation(value = "获得授权事件的票据", httpMethod = "POST", notes = "获得授权事件的票据", code = 200)
    public String parseRequest(HttpServletRequest request, HttpServletResponse response){
        log.info("接收微信服务器发送的component_verify_ticket  begin");
        try {
            request.setCharacterEncoding("UTF-8");
            response.setCharacterEncoding("UTF-8");
            // 微信加密签名
            String msgSignature = request.getParameter("msg_signature");
            // 时间戳
            String timestamp = request.getParameter("timestamp");
            // 随机数
            String nonce = request.getParameter("nonce");
            // 从请求中读取整个post数据
            InputStream inputStream;
            String postData = null;
            inputStream = request.getInputStream();
            postData= IOUtils.toString(inputStream, "UTF-8");    //获取接收到消息里的XML密文,存放在postData中
            log.info("postData:"+postData);
            weChatAuthService.parseRequest (timestamp,nonce,msgSignature,postData);
        } catch (Exception e) {
            log.error("Exception",e);
        }
        return "success";
    }

weChatAuthService

/**
  * 获取票据
  * @param timestamp
  * @param nonce
  * @param msgSignature
  * @param postdata
  * @return
  */
 String parseRequest (String timestamp,String nonce,String msgSignature,String postdata);

weChatAuthServiceImpl

本项目的appId存放在数据库中,为了实现动态获取不同appId的信息,所以在配置文件中配置唯一标识mallCode进行实现

主要使用到的工具类是从『做一个安静的美男子』获取

@Slf4j
@Service
@Configuration
public class WeChatAuthServiceImpl implements WeChatAuthService {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private AuthService authService;

    @Value ( "${wx.mallCode}" )
    private String mallCode;

/*
* 每隔10分钟推送一次,进行一次被迫接收*/
   @Override
   public String  parseRequest (String timestamp,String nonce,String msgSignature,String postData){
       log.info ( "开始授权事件接收URL--->入参{}:"+mallCode );
    try {
        //ThirdpartyInfo是一个实体类主要是将第三方平台appId、第三方平台 secret、第三方平台 消息加解密Key、第三方平台 消息校验Token从数据库中取出来
        ThirdpartyInfo thirdpartyInfo=authService.queryAppId ( mallCode ).getData ();
        String appId=  thirdpartyInfo.getAppId ();
        String appKey= thirdpartyInfo.getAppKey ();
        String componentToken=thirdpartyInfo.getComponentToken ();
        log.info ( "appId--->{}:"+appId );
       // 这个类是微信官网提供的解密类,需要用到消息校验Token 消息加密Key和服务平台appid
        WXBizMsgCrypt pc = new WXBizMsgCrypt(componentToken, appKey, appId);
        String xml = pc.decryptMsg(msgSignature,timestamp,nonce, postData);
        // 将xml转为map
        Map<String, String> result = WXXmlToMapUtil.xmlToMap(xml);
        String infotype=MapUtils.getString ( result,"InfoType" );
        log.info(infotype);
        switch (infotype){
            case "component_verify_ticket":   //验证票据
                String componentVerifyTicket = MapUtils.getString(result, "ComponentVerifyTicket");
                if (StringUtils.isNotEmpty(componentVerifyTicket)) {
                    // 存储平台授权票据,保存ticket
                    redisTemplate.opsForValue ().set ( "component_verify_ticket", componentVerifyTicket, 60 * 60, TimeUnit.SECONDS );
                    String verifyTicket = redisTemplate.opsForValue ().get ( "component_verify_ticket" ).toString ();
                   log.info ( "授权票据ComponentVerifyTicket---->{}:" ,verifyTicket  );
                }
                break;
            case "unauthorized"://用户取消授权
                log.info ( "用户取消授权" );
                break;
            case"updateauthorized"://用户更新授权
                log.info("用户更新授权");
                break;
            case"authorized"://授权成功
                log.info ( "授权成功" );
                break;
        }
    } catch (Exception e) {
        log.error(e.getMessage());
        return "success";
    }
    log.info("==============================结束授权事件接收URL=================================");
    return "success";
   }

二、获取令牌

  //2.获取令牌
    
     @Override
    public String getAccessToken(String mallCode) {//mallCode根据自己需求来,不是必须的
         String accessToken = getCache("component_access_token");
         if (accessToken != null) {
             log.info("缓存获取令牌component_access_token");
             return accessToken;
         }
            String componentVerifyTicket = getCache("component_verify_ticket");
           // String componentVerifyTicket = redisTemplate.opsForValue().get("component_verify_ticket").toString();
            log.info("获取到的票据--->{}:",componentVerifyTicket);
            ThirdpartyInfo thirdpartyInfo=authService.queryAppId ( mallCode );
            String appId=thirdpartyInfo.getAppId ();
            String appSecret=thirdpartyInfo.getAppSecret ();
            log.info ( "appSecret--->{}:",appSecret );
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("component_appid", appId);
            jsonObject.put("component_appsecret", appSecret);
            jsonObject.put("component_verify_ticket", componentVerifyTicket);
            String post = OKHttpUtil.post( WxPostUrlConstant.API_COMPONENT_TOKEN_URl, jsonObject, String.class);
            log.info ("====================返回post结果:" + post);
            HashMap<String, String> hashMap = JSON.parseObject(post, HashMap.class);
            String componentAccessToken = hashMap.get("component_access_token");
            Long expires=6600L;
            if (StringUtils.isNotEmpty(componentAccessToken)) {
                redisTemplate.opsForValue().set("component_access_token", componentAccessToken, expires, TimeUnit.SECONDS);
            } else {
                throw new RuntimeException("微信开放平台,第三方平台获取令牌失败");
            }
            return componentAccessToken;
    }

三、获取预授权码

 @Override
    public String getPreAuthCode(String mallCode) {
        try {
            String preAuthCode = getCache("pre_auth_code");
            if (preAuthCode != null) {
                log.info("缓存获取pre_auth_code");
                return preAuthCode;
            }
            String accessToken =getAccessToken (mallCode);
            ThirdpartyInfo thirdpartyInfo=authService.queryAppId ( mallCode );
            String appId=thirdpartyInfo.getAppId ();
            log.info ( "appId---->{}:",appId );
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("component_appid", appId);
            String post = OKHttpUtil.post(WxPostUrlConstant.API_CREATE_PREAUTHCODE_URL + accessToken,jsonObject, String.class );
            log.info ("====================返回post结果:" + post);
            HashMap<String, String> hashMap = JSON.parseObject(post, HashMap.class);
            String pAuthCode = hashMap.get("pre_auth_code");
            if (StringUtils.isNotEmpty(pAuthCode)) {
                redisTemplate.opsForValue().set("pre_auth_code", pAuthCode, 60 * 10, TimeUnit.SECONDS);
            } else {
                throw new RuntimeException("微信开放平台,第三方平台获取预授权码失败");
            }
            return pAuthCode;
        } catch (Exception e) {
            e.printStackTrace();
        }
       return null;
    }

四、进行授权,获取授权页面

Controller

 @PostMapping(path = "/queryUrl")
    @ApiOperation(value = "授权地址", httpMethod = "POST", notes = "授权地址", code = 200)
    public String authUrl(HttpServletRequest request) {
        return authService.queryAuthUrl (mallCode);
    }

AuthServiceImpl 


@Service
@Slf4j
public class AuthServiceImpl implements AuthService {
    
    @Autowired
    private ThirdpartyInfoMapper mapper;
    @Autowired
    private WeChatAuthService weChatAuthService;

    @Value("${wx.redirectUrl}")
    private String wxRedirectUrl;

 @Override
    public String queryAuthUrl(String mallCode) {
        log.info("获取授权url---->入参{}:",mallCode);
        //获取预授权码
        String preAuthCode =weChatAuthService.getPreAuthCode (mallCode);
        //授权页网址
        ThirdpartyInfo thirdpartyInfo=queryAppId ( mallCode ).getData ();
        String appId=thirdpartyInfo.getAppId ();
        try {
            String redirectUrl = URLEncoder.encode(wxRedirectUrl, "utf-8");
            log.info ( "=======redirectUrl===",redirectUrl );
            String url = "https://mp.weixin.qq.com/cgi-bin/componentloginpage?component_appid=" + appId + "&pre_auth_code=" + preAuthCode + "&redirect_uri="+redirectUrl  + "&auth_type=2";
            return url;
        } catch (Exception e) {
            log.error("获取微信授权地址异常", e);
            return "获取微信授权地址异常";
        }

五、获取授权方的帐号基本信息

@Override
    public String getAuthorizerInfo(String authorizerAppid,String mallCode ) {
        log.info("获取授权方的帐号基本信息---->入参{}:",mallCode);
            ThirdpartyInfo thirdpartyInfo=authService.queryAppId ( mallCode ).getData ();
            String appId= thirdpartyInfo.getAppId ();
            log.info ( "appId--->{}:",appId );
            String accessToken=getAccessToken ( mallCode );
            log.info ( "accessToken---->{}:",accessToken );
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("component_appid", appId);
            jsonObject.put("authorizer_appid",authorizerAppid);
            String post = OKHttpUtil.post(WxPostUrlConstant.API_GET_AUTHORIZER_INFO_URL + accessToken,jsonObject, String.class);
            log.info ("====================返回post结果:" + post);
            JSONObject jsonObj=JSON.parseObject ( post );
            JSONObject authorizerInfo=jsonObj.getJSONObject ( "authorizer_info" );
            String  nickName=authorizerInfo.getString ( "nick_name" );
            log.info ( "nickName---->{}:",nickName );
            return nickName;//因为只需要昵称所以返回了昵称

    }

六、拉取所有已授权的帐号信息

@Override
    public List<RespAuthorizerInfo>  getAuthorizerAppid(String mallCode) {
        log.info("获取所有已授权账号的id---->入参{}:",mallCode);
        try {
            ThirdpartyInfo thirdpartyInfo=authService.queryAppId ( mallCode );
            String appId=thirdpartyInfo.getAppId ();
            String accessToken=getAccessToken ( mallCode );
            log.info ( "appId---->{}:",appId );
            log.info ( "令牌--->{}:",accessToken );
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("component_appid", appId);
            jsonObject.put("offset", 0);
            jsonObject.put("count",100);
            String post = OKHttpUtil.post(WxPostUrlConstant.API_GET_AUTHORIZER_List + accessToken, jsonObject, String.class);
            log.info ("====================返回post结果:" + post);
            JSONObject jsonObj=JSON.parseObject ( post );
            JSONArray jsonArray=jsonObj.getJSONArray ( "list" );
            String jsonString=JSONObject.toJSONString (jsonArray);
            List<AllTotalInfo> objectList=JSONObject.parseArray ( jsonString,AllTotalInfo.class );
            List<RespAuthorizerInfo> respAuthorizerInfos=new ArrayList<> ();
            SimpleDateFormat time=new SimpleDateFormat ( "yyyy-MM-dd HH:mm:ss" );
            for (int i=0;i<objectList.size ();i++){
                RespAuthorizerInfo respAuthorizerInfo=new RespAuthorizerInfo ();
                AllTotalInfo allTotalInfo=objectList.get ( i );
                String authorizerAppid=allTotalInfo.getAuthorizer_appid ();
                int authTimeL=allTotalInfo.getAuth_time ();
                String authTime=time.format ( new Date (authTimeL*1000L  ) );
                respAuthorizerInfo.setAuthTime (authTime);
                respAuthorizerInfo.setAuthorizerAppid ( authorizerAppid );
                respAuthorizerInfos.add ( respAuthorizerInfo );
            }
            log.info("获取到的所有已授权账号的id信息---->{}:",respAuthorizerInfos.toString ());
            return respAuthorizerInfos;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
   protected String getCache(String key) {
       Object o = redisTemplate.opsForValue().get(key);
       if (o == null) {
           return null;
       }
       return o.toString();
   }

七、获取所有已授权小程序的昵称,id,授权时间

@Override
   public List<RespAuthorizerInfo> getAllAuthInfos(String mallCode){
        List<RespAuthorizerInfo> respAuthorizerInfos=weChatAuthService.getAuthorizerAppid (mallCode);
    
        List<RespAuthorizerInfo> respAuthorizerInfoList = new ArrayList<> ();
            for (int i=0;i<respAuthorizerInfos.size ();i++){
                String authorizerAppid=respAuthorizerInfos.get ( i ).getAuthorizerAppid ();
                String authTime=respAuthorizerInfos.get ( i ).getAuthTime ();
                String nickName=weChatAuthService.getAuthorizerInfo (authorizerAppid, mallCode );
                RespAuthorizerInfo respAuthorizerInfo=new RespAuthorizerInfo ();
                respAuthorizerInfo.setAuthorizerAppid ( authorizerAppid );
                respAuthorizerInfo.setNickName ( nickName );
                respAuthorizerInfo.setAuthTime ( authTime );
                respAuthorizerInfoList.add ( respAuthorizerInfo );
            }
            return  respAuthorizerInfoList;
    }

其他模块目前没有使用到,但进行一个记录

八、使用授权码获取授权信息

Controller

 @GetMapping(path = "/getAuthInfo")
    @ApiOperation(value = "使用授权码获取授权信息", httpMethod = "GET", notes = "使用授权码获取授权信息", code = 200)
    public AuthorizationInfo getAuthInfo(@RequestParam("auth_code")String authorizationCode, @RequestParam("expires_in")Long expiresIn, HttpServletRequest request) {
        return  weChatAuthService.getAuthInfo(authorizationCode,expiresIn);
    }
WeChatAuthServiceImpl
 //4.获取授权信息
    @Override
    public AuthorizationInfo  getAuthInfo(String authorizationCode,Long expiresIn) {
            redisTemplate.opsForValue ().set ("authorization_code",authorizationCode, expiresIn-4,TimeUnit.SECONDS );
            ThirdpartyInfo thirdpartyInfo=authService.queryAppId ( mallCode );
            String appId= thirdpartyInfo.getAppId ();
            String accessToken = getAccessToken ( mallCode );
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("component_appid", appId);
            jsonObject.put ( "authorization_code",authorizationCode );
            String post = OKHttpUtil.post(WxPostUrlConstant.API_QUERY_AUTH_URL + accessToken, jsonObject, String.class);
            log.info ( "====================返回post结果:" + post);
            Map<String,Object> map= MapConvertUtil.jsonToMap ( post );
            ObjectMapper objectMapper=new ObjectMapper ();
            AuthorizationInfo authorizationInfo=objectMapper.convertValue ( map.get("authorization_info"),AuthorizationInfo.class );
            Long expires=authorizationInfo.getExpires_in ();
            if (authorizationInfo!=null) {
                redisTemplate.opsForValue().set("authorizer_refresh_token", authorizationInfo.getAuthorizer_refresh_token (),expires-4,TimeUnit.SECONDS);
                return authorizationInfo;
            } else {
                throw new RuntimeException("微信开放平台,第三方平台获取授权信息失败");
            }

    }

九、获取/刷新接口调用令牌

 //5.获取/刷新接口调用令牌
    @Override
    public String  getAuthorizerAccessToken() {
        try {
            String authorizerAccessToken = getCache("authorizer_access_token");
            if (authorizerAccessToken != null) {
                log.info("缓存获取pre_auth_code");
                return authorizerAccessToken;
            }
            String accessToken=getAccessToken ( mallCode );
            String authorizerAppid= redisTemplate.opsForValue().get("authorizer_appid").toString();
            String refreshToken= redisTemplate.opsForValue().get("authorizer_refresh_token").toString();
            String appId=  redisTemplate.opsForValue ().get ( "app_id").toString ();//没有使用上所以这样获取,可以修改
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("component_appid", appId);
            jsonObject.put("authorizer_appid", authorizerAppid);
            jsonObject.put("authorizer_refresh_token", refreshToken);
            String post = OKHttpUtil.post(WxPostUrlConstant.API_AUTHORIZER_TOKEN_URL + accessToken,jsonObject, String.class);
            log.info ("====================返回post结果:" + post);
            HashMap<String, String> hashMap = JSON.parseObject(post, HashMap.class);
            String authAccessToken = hashMap.get("authorizer_access_token");
            String authorizerRefreshToken = hashMap.get("authorizer_refresh_token");
            if (StringUtils.isNoneEmpty ( authAccessToken,authorizerRefreshToken )) {
                redisTemplate.opsForValue().set("authorizer_access_token", authAccessToken,7100,TimeUnit.SECONDS);
            } else {
                throw new RuntimeException("微信开放平台,第三方平台获取或刷新调用令牌失败");
            }
            return authAccessToken;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

十、有待验证,目前还存在问题

//7.获取授权方选项信息
    /*
    * 不太清楚option_name的来源
    * 需要Controller
    * */
    @Scheduled(cron = "0 50 1/2 * * ?")
    private void  getOptionInfo() {
        log.debug("====================开始执行定时任务获取授权方选项信息====================");
        try {
            String accessToken = redisTemplate.opsForValue().get("component_access_token").toString();
            String authorizerAppid= redisTemplate.opsForValue().get("authorizer_appid").toString();
            String appId=  redisTemplate.opsForValue ().get ( "app_id").toString ();
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("component_appid", appId);
            jsonObject.put("authorizer_appid", authorizerAppid);//从4来
            jsonObject.put("option_name", OptionNameEnum.LOCATION_REPORT.getMessage());//从哪来
            String post = OKHttpUtil.post(WxPostUrlConstant.API_GET_AUTHORIZER_OPTION + accessToken, jsonObject, String.class);
            log.debug("====================返回post结果:" + post);
            HashMap<String, String> hashMap = JSON.parseObject(post, HashMap.class);
            String authorizerAppidRet = hashMap.get("authorizer_appid");
            String optionName = hashMap.get("option_name");
            String optionValue = hashMap.get("option_value");
            if (!hashMap.isEmpty ()) {
                redisTemplate.opsForValue().set("authorizer_appid", authorizerAppidRet);
                redisTemplate.opsForValue().set("option_name", optionName);
                redisTemplate.opsForValue().set("option_value", optionValue);
            } else {
                throw new RuntimeException("微信开放平台,第三方平台获取授权方的帐号基本信息失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        log.debug("====================结束执行定时任务获取授权方选项信息====================");
    }
    //8.设置授权方选项信息
    public String  SetOptionInfo() {
        try {
            String accessToken = redisTemplate.opsForValue().get("component_access_token").toString();
            String authorizerAppid= redisTemplate.opsForValue().get("authorizer_appid").toString();
            String optionValue= redisTemplate.opsForValue().get("option_value").toString();
            String appId=  redisTemplate.opsForValue ().get ( "app_id").toString ();
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("component_appid", appId);
            jsonObject.put("authorizer_appid",authorizerAppid );//从4来
            jsonObject.put("option_name", OptionNameEnum.LOCATION_REPORT.getMessage () );
            jsonObject.put("option_value",optionValue);
            String post = OKHttpUtil.post(WxPostUrlConstant.API_SET_AUTHORIZER_OPTION + accessToken, jsonObject, String.class);
            log.debug("====================返回post结果:" + post);
            HashMap<String, String> hashMap = JSON.parseObject(post, HashMap.class);
            String errmsg = hashMap.get("errmsg");
            if (!hashMap.isEmpty ()) {
                if(errmsg=="ok"){
                    return "设置授权方选项信息成功";
                }
            } else {
                throw new RuntimeException("微信开放平台,第三方平台获取授权方选项信息失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

如果看到的小伙伴有什么好的建议可以告诉我哟,谢谢啦~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值