企业微信web登录实现

企业微信登录流程

 

实现方式

使用js-sdk

使用 @wecom/jssdk 初始化企业微信登录组件。

为了满足网站定制化的需求,我们支持将企业微信登录组件内嵌到开发者的网站中。用户使用企业微信登录授权后,登录组件将 auth code 返回给网站。

企业微信登录组件主要用途:网站希望用户在网站内就能完成登录,无需跳转到企业微信域下登录后再返回,提升登录的流畅性与成功率。

使用:

使用企业微信 JS-SDK可查看官方文档,@wecom/jssdk >=1.3.1;

不再详述本篇主要介绍另一种实现方式。

效果如下:

扫码后就可获取到auth_code。

构造登录链接

同时支持通过构造链接的方式,在新窗口中打开企业微信登录页面,用户使用企业微信登录授权后通过将携带 auth code 跳转至指定的 redirect_uri。

开发流程

这里是我使用构造登录链接的开发流程。

登录授权

服务商登录授权

位置:服务商后台【开发配置】->【登录授权】。

登录授权与之前配置的应用指令回调和数据回调配置相同;但是不要使用同一个路由和方法。

登录授权回调解析

这里需要处理的是指令回调url的get和post处理响应。

Get回调处理把回调内容进行解密后返回给微信服务器,表示正确接收到回调。

Post回调处理接收登录授权各种事件回调的解析和处理:目前主要处理登录授权的ticket解密和保存。

控制器端

可以设置为同一入口,通过请求方法的不同,进行分别处理。

代码如下:

public function companyWxNotify()
{
    $all = request()->all();
    writeRecordLog('companyWechat.log', '数据回调' . request()->method());
    writeRecordLog('companyWechat.log', var_export($all, true));
    if (request()->isMethod('POST')) {
        $msg_signature = request()->input('msg_signature');
        $timeStamp = request()->input('timestamp');
        $nonce = request()->input('nonce');
        // post请求的密文数据
        $sReqData = file_get_contents('php://input');
        echo $this->wxService->notifyPOST($msg_signature, $timeStamp, $nonce, $sReqData);
    } else {
        // 获取参数
        $msg_signature = request()->input('msg_signature');
        $timeStamp = request()->input('timestamp');
        $nonce = request()->input('nonce');
        $echoStr = request()->input('echostr');
        echo $this->wxService->callbackGET($msg_signature, $timeStamp, $nonce, $echoStr);
    }
    die();
}

业务层

Get回调处理把回调内容进行解密后返回给微信服务器,表示正确接收到回调。

Post回调处理接收登录授权各种事件回调的解析和处理:

目前主要处理登录授权的ticket解密和保存。

代码如下:

/**
 * 企业微信GET回调处理(URL地址校验)
 * @param $sVerifyMsgSig
 * @param $sVerifyTimeStamp
 * @param $sVerifyNonce
 * @param $sVerifyEchoStr
 * @return string
 */
public function callbackGET($sVerifyMsgSig, $sVerifyTimeStamp, $sVerifyNonce, $sVerifyEchoStr)
{
    $sVerifyEchoStr = str_replace(" ", "+", $sVerifyEchoStr);
    $wxcpt = new \WXBizMsgCrypt(‘Token’, ‘EncodingAESKey’, ‘通用开发参数-CorpID’);
    // 调用验证函数
    $sEchoStr = "";
    $errCode = $wxcpt->VerifyURL($sVerifyMsgSig, $sVerifyTimeStamp, $sVerifyNonce, $sVerifyEchoStr, $sEchoStr);
    writeRecordLog('companyWechat.log', $sEchoStr);
    if ($errCode == 0) {
        return $sEchoStr;
    } else {
        return "ERR: " . $errCode;
    }
}

/**
 * 企业微信-登录授权post回调解析
 * @param $sReqMsgSig
 * @param $sReqTimeStamp
 * @param $sReqNonce
 * @param $sReqData
 * @return string
 */
public function notifyPOST($sReqMsgSig, $sReqTimeStamp, $sReqNonce, $sReqData)
{
    try {
        $sMsg = "";  // 解析之后的明文
        $wxcpt = new \WXBizMsgCrypt(‘登录授权token’, ‘登录授权EncodingAESKey’,  ‘登录授权SuiteID’);
        $errCode = $wxcpt->DecryptMsg($sReqMsgSig, $sReqTimeStamp, $sReqNonce, $sReqData, $sMsg);
        if ($errCode == 0) {
            // 解密成功,sMsg即为xml格式的明文
            writeRecordLog('companyWechat.log', "解密成功:\r\n" . var_export($sMsg, true));
            // TODO: 对明文的处理
            // 解析该xml字符串,利用simpleXML
            libxml_disable_entity_loader(true);
            //禁止xml实体解析,防止xml注入
            $xml = simplexml_load_string($sMsg, 'SimpleXMLElement', LIBXML_NOCDATA);
            switch ($xml->InfoType) {
                case 'suite_ticket': // 存储suite_ticket
                    $log_desc = '登录授权-存储suite_ticket:' . $xml->SuiteTicket;
                    self::$redisWechat->setLoginTicket($xml->SuiteTicket);
                    break;
                default:
                    $log_desc = '未知的类型:' . $xml->InfoType;
                    break;
            }
            writeRecordLog('companyWechat.log', '解析日志:' . $log_desc);
            return 'success';
        } else {
            writeRecordLog('companyWechat.log', "ERR: " . $errCode . "\r\n");
            return "ERR: " . $errCode . "\r\n";
        }
    } catch (\Exception $e) {
        logUnit($e, 'wx_callback.log');
        return 'success';
    }
}

构造企业微信登录链接

同时支持通过构造链接的方式,在新窗口中打开企业微信登录页面,用户使用企业微信登录授权后通过将携带 auth code 跳转至指定的 redirect_uri 。

请求地址

企业微信

参数说明

参数名

类型

必填

说明

login_type

string

登录类型。

ServiceApp:服务商登录;CorpApp:企业自建/代开发应用登录。

appid

string

第三方登录时填登录授权 SuiteID

agentid

string

企业自建应用/服务商代开发应用 AgentID,当login_type=CorpApp时填写

redirect_uri

string

登录成功重定向 url

需进行 URLEncode

state

string

登录 state

用于保持请求和回调的状态,授权请求后原样带回给企业。该参数可用于防止CSRF 攻击(跨站请求伪造攻击),建议带上该参数,可设置为简单的随机数加 session 进行校验

需进行 URLEncode

lang

string

语言类型。zh:中文;en:英文。

返回说明

用户允许授权后,将会重定向到 redirect_uri 的网址上,并且在地址栏带上 code 和 state 参数可通过返回链接获取code。

示例

首先构造web登录链接,之后扫码同意登录;回调到设置的路由地址,并携带授权code。

代码如下:

/**
 * 测试登录授权-构造企业微信登录链接
 */
public function createLoginUrl()
{
    $backUrl = getSolveUrl('/api/getLoginCode');
    $url = "https://login.work.weixin.qq.com/wwlogin/sso/login?login_type=ServiceApp&appid=登录授权SuiteID&redirect_uri={$backUrl}&state=STATE";
    echo '<a href="' . $url . '">点击获取code</a>';
}

/**
 * 获取企业微信回调信息
 */
public function getLoginCode()
{
    print_r(request()->input());
}

登录流程模拟

1.首先访问登录链接

2.点击后出现授权二维码

3.同意登录获取授权code

企业微信扫码同意登录后,跳转至设置好路径,获取授权code。

4.获取用户身份信息实现登录

通过授权code获取登录用户身份信息然后再跟自定义网站的账号信息绑定,实现登录。

获取登录用户身份

通过授权code获取登录用户身份。

请求方式

GET(HTTPS)

请求地址

https://qyapi.weixin.qq.com/cgi-bin/service/auth/getuserinfo3rd?suite_access_token=SUITE_ACCESS_TOKEN&code=CODE

参数说明

参数

必须

说明

suite_access_token

服务商登录授权SuiteId对应的suite_access_token,参见“获取第三方应用凭证” 。不允许代开发自建应用调用。代开发自建应用获取用户身份参考“获取访问用户身份”

code

通过成员授权获取到的code,最大为512字节。每次成员授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期。

业务代码

获取access_token加上前端传递的code去获取登录用户信息。

代码如下:

public function loginAccessToken()
{
    
        $url = "https://qyapi.weixin.qq.com/cgi-bin/service/get_suite_token";
        $params = json([
            'suite_id' => ‘登录授权suiteId’,
            'suite_secret' => ‘登录授权secret’,
            'suite_ticket' => self::$redisWechat->getLoginTicket()
        ]);
        $info = $this->linkCurl($url, 'POST', $params);
        $res = djson($info);
        if (isset($res['errcode'])) {
            return toFail('error', $res);
        }
        $access_token = $res['suite_access_token'];
        
    return toSuccess('success', [
        'access_token' => $access_token
    ]);
}

/**
 * 请求接口返回内容
 * @param $url : 请求的URL地址
 * @param $method : 请求方式POST|GET
 * @param bool $params : 请求的参数
 * @param bool $header : 请求头
 * @return bool|string
 */
protected function linkCurl($url, $method, $params = false, $header = false)
{
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
    curl_setopt($ch, CURLOPT_URL, $url);
    //curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
    curl_setopt($ch, CURLOPT_FAILONERROR, false);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    if (strpos("$" . $url, "https://") == 1) {
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    }
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 60);
    curl_setopt($ch, CURLOPT_TIMEOUT, 60);
    if ($method == "POST") {
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
    } else if ($params) {
        curl_setopt($ch, CURLOPT_URL, $url . '?' . http_build_query($params));
    }
    $response = curl_exec($ch);
    if ($response === FALSE) return false;

    curl_close($ch);
    return $response;
}

/**
 * 获取企业微信用户信息
 * @param $code
 * @return array|mixed
 */
public function getWxUserInfo($code,)
{
    if (empty($code)) {
        return toFail('请输入code参数!');
    }
        $get_access_token = $this->loginAccessToken();
 
    if ($get_access_token['status'] != 1) {
        return $get_access_token;
    }
    $access_token = $get_access_token['data']['access_token'];
    $url = "https://qyapi.weixin.qq.com/cgi-bin/service/auth/getuserinfo3rd?suite_access_token={$access_token}&code={$code}";
    $info = $this->linkCurl($url, 'GET');
    $res = djson($info);
    if ($res['errcode'] != 0) {
        return toFail($res['errmsg'], $res);
    }

    return toSuccess('success', $res);
}

返回参数说明

参数

说明

errcode

返回码

errmsg

对返回码的文本描述内容

corpid

用户所属企业的corpid

userid

用户在企业内的UserID,如果该企业与第三方应用没有授权关系时,返回密文UserId,有授权关系时,按照升级后的ID策略返回明文或密文

open_userid

全局唯一。对于同一个服务商,不同应用获取到企业内同一个成员的open_userid是相同的,最多64个字节。仅第三方应用可获取

注意:返回与网页授权登录内容相同,只是获取方式为登录授权的参数。

总结

企业微信web登录使用构建授权登录链接实现的全过程。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/184714.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Android开发从0开始(广播)

应用广播 发送标准广播的三步骤 发送标准广播&#xff1a; //发送标准广播 Intent intent new Intent("com.dongnaoedu.chapter09.standard"); sendBroadcast(intent); 定义广播接受者: public class StanderdReceiver extends BroadcastReceiver { public s…

ECharts与DataV:数据可视化的得力助手

文章目录 引言一、ECharts简介优势&#xff1a;劣势&#xff1a; 二、DataV简介优势&#xff1a;劣势&#xff1a; 三、ECharts与DataV的联系四、区别与选择五、如何选择根据需求选择技术栈考虑预算和商业考虑 结论我是将军&#xff0c;我一直都在&#xff0c;。&#xff01; 引…

关于进制的转化

二进制转十进制&#xff1a; &#x1f530; 方法一&#xff1a;二进制转十进制&#xff0c;用各数的码位与位权的乘积之和&#xff0c;说白了就是用从右到左的每个数去乘以2的幂次方&#xff08;最右边是0&#xff09;&#xff0c;然后就所有的数相加。 补充&#xff1a;位权是…

多模态常见任务介绍

视觉问答&#xff08;VQA&#xff0c; Visual Question Answer&#xff09; 目标&#xff1a;给定一个图片以及问题&#xff0c;需要理解图片的内容并基于此用自然语言回答问题。 例如&#xff0c;图像中发生什么事&#xff0c;人物穿的衣服是什么颜色&#xff0c;图像中有多…

在Windows系统上安装git-Git的过程记录

01-上git的官网下载git的windows安装版本 下载页面链接&#xff1a; https://git-scm.com/downloads 选择Standalone Installer的版本进行下载&#xff1a; 这里给大家一全git-2.43.0的百度网盘下载链接&#xff1a; https://pan.baidu.com/s/11HwNTCZmtSWj0VG2x60HIA?pwdut…

【DDS】OpenDDS配置与使用

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍OpenDDS配置与使用。 无专精则不能成&#xff0c;无涉猎则不能通。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一下&#xff0c;下次更…

【译】Spring 6 入参数据校验: 综合指南

原文地址&#xff1a;Spring 6 Programmatic Validator: A Comprehensive Guide 一、前言 在 Spring 6.1 中&#xff0c;有一个非常值得注意的重要改进——编程式验证器实现。Spring 长期以来一直通过注解支持声明式验证&#xff0c;而 Spring 6.1 则通过提供专用的编程式验证…

【挑战业余一周拿证】AWS 认证云从业者 - 基础(AWS Certified Cloud Practitioner- Foundational)

一、前言 二、开支记录 三、活动时间 四、活动任务 五、关注订阅号 六、如何报名 Q: 我想参加CSDN 孵化器活动&#xff0c;如何报名&#xff1f; Q: 我想正式报考AWS认证考试&#xff0c;该怎么办&#xff1f; Q: 如何领取考试券&#xff1f; Q: 本次活动考试的费用是…

功率半导体器件CV测试系统

概述 电容-电压(C-V)测量广泛用于测量半导体参数&#xff0c;尤其是MOS CAP和MOSFET结构。MOS(金属-氧化物-半导体)结构的电容是外加电压的函数&#xff0c;MOS电容随外加电压变化的曲线称之为C-V曲线&#xff08;简称C-V特性&#xff09;&#xff0c;C-V 曲线测试可以方便的确…

申请二级域名

1、登录腾讯云 腾讯云 产业智变云启未来 - 腾讯 (tencent.com) 2、进入我的域名&#xff0c;点击主域名 3、点击前往DNSPod管理 4、点击我的域名&#xff0c;然后点击主域名 5、点击添加记录&#xff0c;进行添加二级域名信息 6、添加相应二级域名信息 7、添加后需要进行验证…

ThreeJs实现简单的动画

上一节实现可用鼠标控制相机的方式实现动态效果&#xff0c;但很多时候是需要场景自己产恒动态效果&#xff0c;而不是通过鼠标拖动&#xff0c;此时引入一个requestAnimationFrame方法&#xff0c;它实际上是通过定时任务的方式&#xff0c;每隔一点时间改变场景中内容后重新渲…

复亚智能交通无人机:智慧交通解决方案大公开

城市的现代化发展离不开高效的交通管理规划。传统的交通管理系统庞大繁琐&#xff0c;交警在执行任务时存在安全隐患。在这一背景下&#xff0c;复亚智能交通无人机应运而生&#xff0c;成为智慧交通管理中的重要组成部分。交通无人机凭借其高灵活性、低成本、高安全性等特点&a…

前装标配搭载率突破30%,数字钥匙赛道进入「纵深战」周期

在汽车智能化进程中&#xff0c;作为传统高频应用的车钥匙&#xff0c;也在加速数字化升级。同时&#xff0c;在硬件端&#xff0c;从蓝牙、NFC到UWB等多种通讯方式的叠加效应&#xff0c;也在大幅度提升数字钥匙的用户体验。 目前&#xff0c;部分市场在售车型&#xff0c;车企…

蓄电池监控技巧,节省了我80%的无效工作!

在当今社会&#xff0c;蓄电池作为能源存储和备用电源的关键组件&#xff0c;已经在各行各业中扮演着愈发重要的角色。 然而&#xff0c;蓄电池在使用过程中面临着一系列的挑战&#xff0c;包括性能衰减、安全隐患和能源效率等问题。在这种背景下&#xff0c;蓄电池监控技术应运…

系列三、事务

一、事务 1.1、概述 事务是数据库操作的基本单元&#xff0c;它是指逻辑上的一组操作&#xff0c;要么都成功&#xff0c;要么都失败。典型场景&#xff1a;转账&#xff0c;例如Jack给Rose转账1000元&#xff0c;转账成功&#xff1a;Jack账户的余额少1000元&#xff0c;Rose…

实用高效 无人机光伏巡检系统助力电站可持续发展

近年来&#xff0c;我国光伏发电行业规模日益壮大&#xff0c;全球领先地位愈发巩固。为解决光伏电站运维中的难题&#xff0c;浙江某光伏电站与复亚智能达成战略合作&#xff0c;共同推出全自动无人机光伏巡检系统&#xff0c;旨在提高发电效率、降低运维成本&#xff0c;最大…

NX二次开发UF_CSYS_create_csys 函数介绍

文章作者&#xff1a;里海 来源网站&#xff1a;https://blog.csdn.net/WangPaiFeiXingYuan UF_CSYS_create_csys Defined in: uf_csys.h int UF_CSYS_create_csys(const double csys_origin [ 3 ] , tag_t matrix_id, tag_t * csys_id ) overview 概述 Creates a CSYS. 创…

算法:给出指定整数区间、期望值,得到最终结果

1&#xff0c;问题&#xff1a; 在游戏中&#xff0c;我们经常会遇到以下情况&#xff1a;打开宝箱&#xff0c;获得x个卡牌碎片。 但通常策划只会给一个既定的数值空间&#xff0c;和一个期望得到的值&#xff0c;然后让我们去随机。比如&#xff1a; 问题A&#xff1a;在1~…

用栈实现队列的功能,用队列实现栈的功能?

我们知道队列的特点是先入先出&#xff0c;栈的特点是后入先出&#xff0c;那么如何用栈实现队列的功能&#xff0c;又如何用队列实现栈的功能呢&#xff0c;且听我一一道来 我们首先来看用栈实现队列的功能&#xff0c;首先大伙儿要知道队列和栈的特点其实是“相反”&#xf…

氮化镓的晶体学湿式化学蚀刻法

引言 目前&#xff0c;大多数III族氮化物的加工都是通过干法等离子体蚀刻完成的。干法蚀刻有几个缺点&#xff0c;包括产生离子诱导损伤和难以获得激光器所需的光滑蚀刻侧壁。干法蚀刻产生的侧壁典型均方根(rms)粗糙度约为50纳米&#xff0c;虽然已经发现KOH基溶液可以蚀刻AlN…