企微登录功能对接

基本参数说明

官方文档参考:developer.work.weixin.qq.com/docum...

参数 定义 说明
corpid 企业唯一的corpid 获取此信息:管理后台 “我的企业-企业信息 - 企业ID”(需要有管理员权限)
userid 成员唯一的userid 所谓“账号”
partyid 部门id 管理后台 - 通讯录 - 组织架构 - 部门
tagid 标签id 管理后台 - 通讯录 - 标签
external_userid 企业外部联系人的id 可能是微信用户,也可能是企业微信用户
agentid 每个应用唯一的agentid 管理后台 - 应用管理 - 应用,点进应用,即可看到agentid
secret secret每个应用的访问密钥都是独立的 secret是企业应用保障数据安全的“钥匙”,管理后台-应用管理-应用,点进应用,即可看到

自建应用配置

在创建应用之后,为避免踩坑。优先配置:可信域名+可信IP+可见范围,可让你的开发调试更加流畅。。。

  1. “可信域名”:在管理后台->“应用管理”->“应用”,点进某个应用,开发者接口模块即可配置
  2. “可信IP”:同上。从2022年6月20号20点之后必须配置,所以开发前都先配上
  3. “可见范围”:非必要情况也配置为全部,需权限管控的列外

获取access_token

access_token是所有接口在通信时都需要携带此信息用于验证接口的访问权限。

企业微信的一些功能对接

核心代码:

<?php


namespace App\Service;


use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;

class OpenWeChatService
{
    /**
     * 企微Id
     * @var string
     */
    public $corpid;

    /**
     * 应用唯一id
     * @var string
     */
    public $agentid;

    /**
     * 应用密钥
     * @var string
     */
    public $secret;

    /**
     * access_token 本地缓存key
     */
    const OPEN_ACCESS_TOKEN_CACHE_KEY = 'OpenWeChat-AccessToken-';

    /**
     * access_token 本地缓存时间,不可大于7200
     */
    const OPEN_ACCESS_TOKEN_CACHE_TIME = 3600;

    public function __construct()
    {
        $this->corpid = config('openwechat.corpid');
        $this->agentid = config('openwechat.agentid');
        $this->secret = config('openwechat.secret');
    }

    /**
     * 获取企微openApi的 access_token,通过【access_token + 消息请求】获取【请求结果】
     * 无需每次获取。通常设置一个过期周期,一般2小时【官方默认】,失效后才获取
     * 【GET】https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=ID&corpsecret=SECRET
     * @return string
     * @throws \Exception
     */
    public function _getAccessToken(): string
    {
        $url = 'https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=' . $this->corpid . '&corpsecret=' . $this->secret;
        try {
            $response = Http::get($url)->json();
        } catch (\Exception $e) {
            throw  new \Exception('获取access_token,请求失败:' . $url);
        }
        if (isset($response['errcode']) && $response['errcode'] <> 0) {
            throw  new \Exception('获取access_token失败,errcode:' . $response['errcode'] ?? '');
        }
        $accessToken = $response['access_token'];

        return $accessToken;
    }

    /**
     * 本地缓存:获取企微openApi的 access_token
     * @param $cache
     * @return mixed|string
     * @throws \Exception
     */
    public function getAccessToken($cache = true): string
    {
        if ($cache) {
            $openAccessTokenCacheKey = self::OPEN_ACCESS_TOKEN_CACHE_KEY . $this->corpid;
            $openAccessTokenCache = Cache::get($openAccessTokenCacheKey);
            if ($openAccessTokenCache) {
                return $openAccessTokenCache;
            }
            $accessToken = $this->_getAccessToken();
            Cache::put($openAccessTokenCacheKey, $accessToken, self::OPEN_ACCESS_TOKEN_CACHE_TIME);
        } else {
            $accessToken = $this->_getAccessToken();
        }

        return $accessToken;
    }

}

config文件:

<?php

return [
    'app' => 'openwechat',
    'name' => '企业名称',
    'corpid' => 'xxxxx',
    'agentid' => '1000002',
    'secret' => 'xxxxxx',
    'redirect_uri' => 'http://www.xxxx.com/api/login', //登录跳转url

    'robotKey' => '693axxx6-7aoc-4bc4-97a0-0ec2sifa5aaa',   //机器人Key
    'toUser' => 'user1|user2',  //多人用“|”分割

];

企微登录

企业微信的授权登录可大致分为:OAuth2.0授权和网页授权。这里主要记录网页登录授权功能的对接,以供下次参考!
官方文档参考:developer.work.weixin.qq.com/docum...

简要流程图:
企微登录流程

OAuth2.0登录

  1. 【忽略】按需参考。OAuth2.0正常流程。通常是企微终端内部,小程序的授权登录
  2. 【核心】构建网页授权链接:【open.weixin.qq.com/connect/oauth2/...
  3. 【snsapi_base:静默授权】可以通过此参数配合,实现业务系统在企微内的免密登录

Web登录

  1. 【配置】管理端后台创建一个具备“企业微信授权登录”能力的应用【企微管理后台-自建应用,可见范围设置为“全部”】
  2. 【配置】开启网页授权登录【企微管理后台-自建应用-企业微信授权登录-设置】。配置的授权回调域,必须与访问链接的域名完全一致!
  3. 【后端】按上图流程,首先构建“企业微信登录链接”,获取“code”【login.work.weixin.qq.com/wwlogin/s...】。注意:这里的配置的 redirect_uri 地址须带上协议头【http/https】
  4. 【前端】redirect_uri 说明,扫码/登录成功后,重定向到:redirect_uri?code=CODE&state=STATE
  5. 【后端】拿到code后,后端即可向企微认证消费code:【GET】qyapi.weixin.qq.com/cgi-bin/auth/g...,获取登录信息,生产登录状态,向前端颁发token

构建url参数说明:

参数 类型 必填 定义 说明
login_type string 登录类型 ServiceApp:服务商登录;CorpApp:企业自建/代开发应用登录
appid string 企业 CorpID或SuiteID login_type为CorpApp时填企业 CorpID,ServiceApp填登录授权 SuiteID
agentid string 应用 AgentID 企业自建应用/服务商代开发应用 AgentID,当login_type=CorpApp时填写
redirect_uri string 登录成功重定向 url 需进行 URLEncode。注意域名必须配置为可信域名【OAuth可信域名或者Web网页授权回调域名】
state string 登录 state 保持请求和回调的状态,原样返回。可用于防止CSRF 攻击,可设置校验
lang string 语言类型 zh:中文;en:英文。

核心代码:

<?php


namespace App\Service;


use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;

class OpenWeChatAuthService extends OpenWeChatService
{

    /**
     * 获取企业微信登录链接
     * @return string
     */
    public function getLoginUrl()
    {
        $queryData = [
            'login_type' => 'CorpApp',
            'appid' => $this->corpid,
            'redirect_uri' => config('openwechat.redirect_uri'),
            'agentid' => $this->agentid,
            'state' => 'STATE',
            'lang' => 'zh',
        ];
        $url = 'https://login.work.weixin.qq.com/wwlogin/sso/login?' . http_build_query($queryData);

        return $url;
    }

    /**
     * 消费code,获取登录用户信息
     * @param $code [授权链接登录后跳转自带的code]
     * @return mixed [企业成员:userid、user_ticket,非企业成员:openid、external_userid]
     * @throws \Exception
     */
    public function getUserInfo($code)
    {
        $url = 'https://qyapi.weixin.qq.com/cgi-bin/auth/getuserinfo?access_token=' . $this->getAccessToken() . '&code=' . $code;
        try {
            $response = Http::get($url)->json();
        } catch (\Exception $e) {
            throw  new \Exception('获取登录用户【/auth/getuserinfo】失败,请求失败:' . $url);
        }
        if (isset($response['errcode']) && $response['errcode'] <> 0) {
            throw new \Exception('获取登录用户【/auth/getuserinfo】失败,响应:' . json_encode($response, JSON_UNESCAPED_UNICODE));
        }

        return $response;
    }

    /**
     * 获取用户敏感信息
     * @param $userTicket [self::getUserInfo => user_ticket]
     * @return mixed
     * @throws \Exception
     */
    public function getUserDetail($userTicket)
    {
        $url = 'https://qyapi.weixin.qq.com/cgi-bin/auth/getuserdetail?access_token=' . $this->getAccessToken();
        $data = [
            'user_ticket' => $userTicket
        ];
        try {
            $response = Http::post($url, $data)->json();
            Log::info(__METHOD__, ['url' => $url, 'data' => $data]);
        } catch (\Exception $e) {
            throw new \Exception('获取用户敏感信息失败,url:' . $url . '|参数:' . json_encode($data, JSON_UNESCAPED_UNICODE));
        }
        if (isset($response['errcode']) && $response['errcode'] <> 0) {
            throw new \Exception('获取用户敏感信息失败,响应:' . json_encode($response, JSON_UNESCAPED_UNICODE));
        }

        return $response;
    }

}

备注说明

环境:php7.4 + laravel8

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 3

点赞,正需要这个 :+1:

1天前 评论

EasyWeChat一下就搞定了,花里胡哨

1天前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!