百木园-与人分享,
就是让自己快乐。

企业微信第三方应用(三)基于springboot开发(获取Ticket,auth_code)

一、构建spring boot项目
1、新建项目
新建一个模块(module):enterprise-wechat
新建一个子模块(module):wechat
目录结构如下:

结构描述:
common
-> WeChatConstants:存放企业微信一些常量,公用参数
-> WeChatUtils:存放企业微信第三方应用api
controller
-> SystemController:控制层,接收请求
entity
-> aes:目录下文件企业微信加解密包
service
-> IConfigService:调用企业微信服务层
pom.xml
-> 导入所需要的jar包

pom.xml中需要导入commons.codec包

<dependency>
   <groupId>commons-codec</groupId>
   <artifactId>commons-codec</artifactId>
   <version>1.9</version>
</dependency>

2、方法描述
1)doGetCallback:
① 接收验证请求,用于验证通用开发参数系统事件接收URL、数据回调URL、指令回调URL。
② 企业微信后台录入回调URL点击保存时,微信服务器会立即发送一条GET请求到对应URL,该函数就对URL的signature进行验证。

2)doPostCallback:
① 用于获取 suite_ticket,安装应用时企业微信传递过来的auth_code:指令回调URL
② 当刷新ticket传递【SuitID】:指令回调URL
③ 当打开应用时传递【CorpID】:数据回调URL

3、代码编写
1)企业微信配置类:WeChatConstants

package com.wechat.common;

/**
 * 企业微信
 */
public class WeChatConstants {

    // 企业微信授权码获取时间
    public static final Long EXPIRES_IN = 24 * 60 * 60 * 1000L;
    //24 * 60 * 60 * 1000L 7200L * 1000

    /**
     * 服务商CorpID
     */
    public static final String CORP_ID = \"ww14438c6c07a317f2\";
    /**
     * 服务商身份的调用凭证
     */
    public static final String PROVIDER_SECRET = \"RH7PehRJX3LIcw4axad_H2T9HSUG1finOBEpnLTVIioBrP-zgZrGsqJ9pHVw5vVj\";

    /**
     * 应用的唯一身份标识
     */
    public static final String SUITE_ID = \"ww4f66fa544a32f920\";
    /**
     * 应用的调用身份密钥
     */
    public static final String SUITE_SECRET = \"vVv8JzaBlEVCTQkHKqmr57EAMs65AILWiI_4ANc25T4\";

    // 回调相关
    /**
     * 回调/通用开发参数Token, 两者解密算法一样,所以为方便设为一样
     */
    public static final String TOKENS = \"E0sOXx4LqeE5BmDvMTAz3x\";

    /**
     * 回调/通用开发参数EncodingAESKey, 两者解密算法一样,所以为方便设为一样
     */
    public static final String ENCODING_AES_KEY = \"IESLPSyW4vyBB90jkzfwfYRtcMky6LIOevr4SVefz7I\";

}

2)企业微信api:WeChatUtils

package com.wechat.common;

/**
 * 企业微信工具类
 */
public class WeChatUtils {
    /**
     * 第三方应用api start
     */
    // 获取第三方应用凭证
    public final static String THIRD_BUS_WECHAT_SUITE_TOKEN = \"https://qyapi.weixin.qq.com/cgi-bin/service/get_suite_token\";

    // 获取企业永久授权码
    public final static String THIRD_BUS_WECHAT_ACCESS_TOKEN = \"https://qyapi.weixin.qq.com/cgi-bin/service/get_permanent_code?suite_access_token=SUITE_ACCESS_TOKEN\";

    // 第三方 构造扫码登录链接
    public final static String THIRD_BUS_WECHAT_LOGIN = \"https://open.work.weixin.qq.com/wwopen/sso/3rd_qrConnect?appid=CORPID&redirect_uri=REDIRECT_URI&state=web_login&usertype=member\";

    // 第三方 获取登录用户信息 POST
    public final static String THIRD_BUS_WECHAT_GET_LOGIN_INFO = \"https://qyapi.weixin.qq.com/cgi-bin/service/get_login_info?access_token=PROVIDER_ACCESS_TOKEN\";

    // 第三方 构造网页授权链接
    public final static String THIRD_BUS_WECHAT_AUTHORIZE_URL = \"https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=snsapi_privateinfo&state=STATE#wechat_redirect\";

    // 第三方 获取访问用户身份 GET
    public final static String THIRD_BUS_WECHAT_GET_USER_INFO = \"https://qyapi.weixin.qq.com/cgi-bin/service/getuserinfo3rd?suite_access_token=SUITE_TOKEN&code=CODE\";

    // 第三方 获取访问用户敏感信息 post
    public final static String THIRD_BUS_WECHAT_GET_USER_DETAIL3RD = \"https://qyapi.weixin.qq.com/cgi-bin/service/getuserdetail3rd?suite_access_token=SUITE_ACCESS_TOKEN\";

    // 第三方 获取部门列表
    public final static String THIRD_BUS_WECHAT_DEPART_LIST = \"https://qyapi.weixin.qq.com/cgi-bin/department/list?access_token=ACCESS_TOKEN&id=ID\";

    // 第三方 获取部门成员
    public final static String THIRD_BUS_WECHAT_DEPART_USER = \"https://qyapi.weixin.qq.com/cgi-bin/user/simplelist?access_token=ACCESS_TOKEN&department_id=DEPARTMENT_ID&fetch_child=FETCH_CHILD\";

    // 第三方 获取部门成员详情
    public final static String THIRD_BUS_WECHAT_DEPART_USER_DETAIL = \"https://qyapi.weixin.qq.com/cgi-bin/user/list?access_token=ACCESS_TOKEN&department_id=DEPARTMENT_ID&fetch_child=FETCH_CHILD\";

    // 第三方 读取成员 GET
    public final static String THIRD_BUS_WECHAT_GET_USER = \"https://qyapi.weixin.qq.com/cgi-bin/user/get?access_token=ACCESS_TOKEN&userid=USERID\";

    // 服务商的token
    public final static String THIRD_BUS_WECHAT_GET_PROVIDER_TOKEN = \"https://qyapi.weixin.qq.com/cgi-bin/service/get_provider_token\";

    // 获取企业凭证
    public final static String THIRD_BUS_WECHAT_GET_CORP_TOKEN = \"https://qyapi.weixin.qq.com/cgi-bin/service/get_corp_token?suite_access_token=SUITE_ACCESS_TOKEN\";

    // 发送应用消息
    public final static String THIRD_BUS_WECHAT_SEND = \"https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=ACCESS_TOKEN\";

    // 获取应用的jsapi_ticket
    public final static String THIRD_BUS_GET_JSAPI_TICKET = \"https://qyapi.weixin.qq.com/cgi-bin/ticket/get?access_token=ACCESS_TOKEN&type=agent_config\";

    // 获取企业的jsapi_ticket
    public final static String THIRD_BUS_GET_JSAPI_TICKET_BUS = \"https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=ACCESS_TOKEN\";
    /**
     * 第三方应用api end
     */

}

3)controller层:SystemController

package com.wechat.controller;

import com.wechat.service.IConfigService;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;

/**
 * 控制层
 */
@Slf4j
@RestController
@RequestMapping(value = \"system\")
public class SystemController {

    @Autowired
    private IConfigService configService;

    /**
     * 验证通用开发参数及应用回调
     * @param: request
     * @param: response
     * @returns: void
     */
    @ApiOperation(value = \"验证通用开发参数及应用回调\")
    @GetMapping(value = \"getEchostr\")
    public void doGetCallback(HttpServletRequest request, HttpServletResponse response) throws Exception {
        // 微信加密签名
        String msgSignature = request.getParameter(\"msg_signature\");
        // 时间戳
        String timestamp = request.getParameter(\"timestamp\");
        // 随机数
        String nonce = request.getParameter(\"nonce\");
        // 随机字符串
        // 如果是刷新,需返回原echostr
        String echoStr = request.getParameter(\"echostr\");
        String sEchoStr=  \"\";
        PrintWriter out;
        log.debug(\"msgSignature: \" + msgSignature+\"timestamp=\"+timestamp+\"nonce=\"+nonce+\"echoStr=\"+echoStr);
        try {
            sEchoStr = configService.doGetCallback(msgSignature,timestamp,nonce,echoStr); //需要返回的明文;
            log.debug(\"doGetCallback-> echostr: \" + sEchoStr);
            // 验证URL成功,将sEchoStr返回
            out = response.getWriter();
            out.print(sEchoStr);
        } catch (Exception e) {
            //验证URL失败,错误原因请查看异常
            e.printStackTrace();
        }
    }

    /**
     * 刷新ticket,AuthCode
     */
    @ApiOperation(value = \"刷新ticket,AuthCode\")
    @PostMapping(value = \"getEchostr\")
    public String doPostCallback(HttpServletRequest request) throws Exception {
        // 微信加密签名
        String msgSignature = request.getParameter(\"msg_signature\");
        // 时间戳
        String timestamp = request.getParameter(\"timestamp\");
        // 随机数
        String nonce = request.getParameter(\"nonce\");
        // 类型
        String type = request.getParameter(\"type\");
        // 企业id
        String corpId = request.getParameter(\"corpid\");
        ServletInputStream in = request.getInputStream();
        // 刷新ticket,AuthCode
        String success = configService.doPostCallback(msgSignature, timestamp, nonce, type, corpId, in);
        return success;
    }
}

4)Service层:IConfigService

package com.wechat.service;

import javax.servlet.ServletInputStream;

/**
 * 企业微信第三方服务service
 */
public interface IConfigService {

    /**
     * 验证通用开发参数及应用回调
     * @returns: java.lang.String
     */
    String doGetCallback(String msgSignature, String timestamp, String nonce, String echoStr);

    /**
     * 获取SuiteTicket,AuthCode
     */
    String doPostCallback(String msgSignature, String timestamp, String nonce, String type, String corpId, ServletInputStream in);
}

5)service实现类:ConfigServiceImpl

package com.wechat.service.impl;

import com.alibaba.druid.support.json.JSONUtils;
import com.wechat.common.StringUtils;
import com.wechat.common.WeChatConstants;
import com.wechat.common.WxUtil;
import com.wechat.entity.aes.AesException;
import com.wechat.entity.aes.WXBizMsgCrypt;
import com.wechat.service.IConfigService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.servlet.ServletInputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Map;

/**
 * TODO 类描述
 */
@Slf4j
@Service
public class ConfigServiceImpl implements IConfigService {

    /**
     * 验证通用开发参数及应用回调
     * @returns: java.lang.String
     */
    @Override
    public String doGetCallback(String msgSignature, String timestamp, String nonce, String echoStr) {
        //需要返回的明文
        String sEchoStr=\"\";
        try {
            log.debug(WeChatConstants.TOKENS, WeChatConstants.ENCODING_AES_KEY, WeChatConstants.CORP_ID);
            WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(WeChatConstants.TOKENS, WeChatConstants.ENCODING_AES_KEY, WeChatConstants.CORP_ID);
            sEchoStr = wxcpt.VerifyURL(msgSignature, timestamp, nonce, echoStr);
        } catch (AesException e) {
            e.printStackTrace();
        }
        return sEchoStr;
    }

    /**
     * 获取SuiteTicket,AuthCode
     * @param: msgSignature 微信加密签名
     * @param: timestamp 时间戳
     * @param: nonce  随机数
     * @param: type 类型
     * @param: corpId 企业id
     * @param: in
     * @returns: java.lang.String
     */
    @Override
    public String doPostCallback(String msgSignature, String timestamp, String nonce, String type, String corpId, ServletInputStream in) {
        String id = \"\";
        // 访问应用和企业回调传不同的ID
        if(!StringUtils.isNull(type) && type.equals(\"data\")){
            id = corpId;
            log.debug(\"======corpId===\"+id);
        } else {
            id = WeChatConstants.SUITE_ID;
            log.debug(\"======SuiteId===\" + id);
        }
        try {
            WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(WeChatConstants.TOKENS, WeChatConstants.ENCODING_AES_KEY, id);
            String postData=\"\";   // 密文,对应POST请求的数据
            //1.获取加密的请求消息:使用输入流获得加密请求消息postData
            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
            String tempStr = \"\";   //作为输出字符串的临时串,用于判断是否读取完毕
            while(null != (tempStr=reader.readLine())){
                postData+=tempStr;
            }
            log.debug(\"====msg_signature====\"+msgSignature+\"====timestamp===\"+timestamp+\"====nonce===\"+nonce+\"====postData===\"+postData);
            String suiteXml = wxcpt.DecryptMsg(msgSignature, timestamp, nonce, postData);
            log.debug(\"suiteXml: \" + suiteXml);
            Map suiteMap = WxUtil.parseXml(suiteXml);
            log.debug(\"==suiteMap==\"+ JSONUtils.toJSONString(suiteMap));
            if(suiteMap.get(\"SuiteTicket\") != null) {
                String suiteTicket = (String) suiteMap.get(\"SuiteTicket\");
                log.debug(\"====SuiteTicket=====\" + suiteTicket);
            } else if(suiteMap.get(\"AuthCode\") != null){
                String authCode = (String) suiteMap.get(\"AuthCode\");
                log.debug(\"doPostValid->AuthCode:\" + authCode);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return \"success\";
    }
}

4、验证
以上代码编写完成后,就可以打包到环境上面进行测试验证:
①:echostr验证

返回结果:返回 echostr,并显示已验证

16:11:46.940 [http-nio-9205-exec-7] INFO  c.q.w.s.c.SystemController - [doGetValid,94] - doGetCallback->echostr: 577115934236344259
16:11:46.969 [http-nio-9205-exec-3] INFO  c.q.w.s.c.SystemController - [doGetValid,94] - doGetCallback->echostr: 5267604771365158379

②:刷新Ticket:获取Ticket有两种方式,一是点击按钮获取,二是企业微信每15分钟会调用回调接口获取一次

点击“刷新Ticket” 会弹出如下图,然后点击确定

Ticket 有效期为30分钟;建议把Ticket放到数据库或者redis中

③:获取auth_code
安装第三方应用的时候,会获取auth_code

④:安装测试流程


通过企业微信扫码进行安装


上面就是验证通过,及获取Ticket和auth_code

5、总结
在第三方应用开发中,主要围绕三种类型的access_token(见企业微信地方应用(二)https://www.cnblogs.com/why0703/p/15983925.html)

provider_access_token:服务商的token
suite_access_token:获取第三方应用凭证
access_token:授权方(企业)access_token

通过上面的代码及配置,我们获取到了suiteTicket和auth_code。
接下来我们要通过这些值获取到上面token,通过springboot开发实现“企业微信第三方应用(二)api使用测试”

代码后面同步到github


来源:https://www.cnblogs.com/why0703/p/15983995.html
本站部分图文来源于网络,如有侵权请联系删除。

未经允许不得转载:百木园 » 企业微信第三方应用(三)基于springboot开发(获取Ticket,auth_code)

相关推荐

  • 暂无文章