企业微信授权登录(uniapp项目)
开发之前必须把这张图了解透了,不然会容易做着做着懵,没有思路。
官方地址:https://developer.work.weixin.qq.com/document/path/98151
一、前端页面
login登录页,
<template><view class="login-container"><button class="form-button wecom" @click="handleWecomLogin">企业微信登录</button></view>
</template>function handleWecomLogin() {const CORPID = 'ww7981ebca139e75f9'const REDIRECT_URI='https://datalab.ffep.online:20093/web/pages/index/callback' // 返回授权登录码const AGENTID='1000086'// 生成授权URL// const authUrl = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${CORPID}&redirect_uri=${REDIRECT_URI}&response_type=code&scope=snsapi_base&agentid=${AGENTID}&state=login`;const authUrl = `https://login.work.weixin.qq.com/wwlogin/sso/login?login_type=CorpApp&appid=${CORPID}&redirect_uri=${REDIRECT_URI}&state=STATE&agentid=${AGENTID}`// 跳转到企业微信授权页面window.location.href = authUrl;}</script><style lang="scss" scoped>/*省略*/
</style>
callback回调页
<template><view></view>
</template><script setup lang="ts">
import { onLoad } from '@dcloudio/uni-app';
import request from '../../utils/hrAPI';onLoad(async (options) => {if (options.code) {try {// 使用授权码换取用户信息并登录// const res = await loginWithWecomCode(options.code);const res = await request({url: '/ffep/Wecom/loginWithWecomCode',method: 'POST',data: {code:options.code},requiresAuth:false});if (res.code === 1) {uni.setStorageSync('staffinfo', res.data.staffinfo);uni.showToast({ title: '登录成功', icon: 'success' });uni.reLaunch({ url: '/pages/index/index' });} else {uni.showToast({ title: res.msg, icon: 'none' });// uni.navigateBack();}} catch (error) {console.error('企业微信登录失败:', error);uni.showToast({ title: '网络错误,请重试', icon: 'none' });// uni.navigateBack();}} else {// uni.navigateBack();}
});
</script>
二、后端准备
准备一个控制器
<?php
namespace app\api\controller\ffep;use app\common\controller\Api;
use think\Db;
use think\Request;
use addons\wecom\library\Wecom as wecomService;
use think\Exception;
use think\Cache;
use app\admin\model\wecom\Staff;class Wecom extends Api
{protected $noNeedLogin = ['*'];protected $noNeedRight = ['*'];// IT尊享服务protected $app_id = "1000086";protected $app_secret = "T3jVYGDudwKnz3k1u50EXT3LhcOnUm5Z3cN-mXRutlo";protected $corpid;protected $corpsecret;public function __construct(){parent::__construct();// 企微的公司id和密钥$this->corpid = $config['corpid']; $this->corpsecret = $config['secret']; }// callback回调页面会访问这个方法,请求用户idpublic function loginWithWecomCode(){// 注意这里要拿应用的accesstoken,查看token的权限地址https://developer.work.weixin.qq.com/devtool/query$accessToken = $this->getAppAccessToken($this->app_id,$this->app_secret);$code = $this->request->param('code',false);if($code){$url = "https://qyapi.weixin.qq.com/cgi-bin/auth/getuserinfo?access_token=$accessToken&code=$code";//发送一个POST请求并获取返回结果$result = \fast\Http::get($url);$result = json_decode($result);// dump($result);exit;if(isset($result->userid)){// 拿到用户userid的业务逻辑$userid = $result->userid;$staffinfo = Staff::where('userid',$userid)->find();if(!$staffinfo){$this->error('企业微信信息获取失败。请联系管理员');}else{// 获取成功的流程$this->success('授权成功',['staffinfo'=>$staffinfo]);}}else{$this->error('企业微信授权登录失败。请重试');}}}/*** 获取JS-SDK配置*/public function jssdkConfig(){// dump(Request::instance());exit;$url = $this->request->post('url');if (!$url) {$this->error('缺少URL参数');}try {$config = $this->getJssdkConfig($url);$this->success('获取成功', $config);} catch (Exception $e) {$this->error('获取失败: ' . $e->getMessage());}}/*** 生成JS-SDK配置*/private function getJssdkConfig($url){$corpid = $this->corpid;$corpsecret = $this->corpsecret;// 获取access_token$accessToken = $this->getAccessToken();// 获取jsapi_ticket$jsapiTicket = $this->getJsapiTicket($accessToken);// 生成签名$nonceStr = $this->createNonceStr();$timestamp = time();$signature = $this->generateSignature($jsapiTicket, $nonceStr, $timestamp, $url);return ['appId' => $corpid,'nonceStr' => $nonceStr,'timestamp' => $timestamp,'signature' => $signature,'jsApiList' => ['checkJsApi', 'scanQRCode'] // 需要使用的接口列表];}// 获取应用的accesstokenpublic function getAppAccessToken($agentid,$appsecret){$token = Cache::get($agentid.'_wecom_access_token');if (!$token) {$config = get_addon_config('wecom');$corpid = $this->corpid;$corpsecret = $appsecret;$url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={$corpid}&corpsecret={$corpsecret}";$result = $this->httpGet($url);$result = json_decode($result, true);if (isset($result['access_token'])) {$accessToken = $result['access_token'];Cache::set($agentid.'_wecom_access_token', $accessToken, 7100); // 提前100秒过期} else {throw new Exception('获取access_token失败: ' . json_encode($result));}}return $token;}/*** 获取access_token*/private function getAccessToken(){// 从缓存获取或重新请求$accessToken = Cache::get('wecom_access_token');if (!$accessToken) {$corpid = $this->corpid;$corpsecret = $this->corpsecret;$url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={$corpid}&corpsecret={$corpsecret}";$result = $this->httpGet($url);$result = json_decode($result, true);if (isset($result['access_token'])) {$accessToken = $result['access_token'];Cache::set('wecom_access_token', $accessToken, 7100); // 提前100秒过期} else {throw new Exception('获取access_token失败: ' . json_encode($result));}}return $accessToken;}/*** 获取jsapi_ticket*/private function getJsapiTicket($accessToken){// 从缓存获取或重新请求$jsapiTicket = Cache::get('wecom_jsapi_ticket');if (!$jsapiTicket) {$url = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token={$accessToken}";$result = $this->httpGet($url);$result = json_decode($result, true);if (isset($result['ticket'])) {$jsapiTicket = $result['ticket'];Cache::set('wecom_jsapi_ticket', $jsapiTicket, 7100); // 提前100秒过期} else {throw new Exception('获取jsapi_ticket失败: ' . json_encode($result));}}return $jsapiTicket;}/*** 生成签名*/private function generateSignature($jsapiTicket, $nonceStr, $timestamp, $url){$string = "jsapi_ticket={$jsapiTicket}&noncestr={$nonceStr}×tamp={$timestamp}&url={$url}";return sha1($string);}/*** 创建随机字符串*/private function createNonceStr($length = 16){$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";$str = "";for ($i = 0; $i < $length; $i++) {$str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);}return $str;}/*** HTTP GET请求*/private function httpGet($url){$ch = curl_init();curl_setopt($ch, CURLOPT_URL, $url);curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);$output = curl_exec($ch);curl_close($ch);return $output;}
}
三、实践过程中遇到的问题&解决办法
解决:
not allow to access from your ip