开发之前必须把这张图了解透了,不然会容易做着做着懵,没有思路。
官方地址: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回调页面会访问这个方法,请求用户id
public 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'] // 需要使用的接口列表
];
}
// 获取应用的accesstoken
public 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