PHP项目企业微信与钉钉

wen PHP项目 2

本文目录导读:

PHP项目企业微信与钉钉

  1. 企业微信集成
  2. 钉钉集成
  3. 统一控制器
  4. Webhook处理
  5. 使用示例
  6. 依赖安装

我来为你详细介绍PHP项目中集成企业微信和钉钉的完整方案。

企业微信集成

1 基础配置

<?php
// config/wechat_work.php
return [
    'corp_id' => '你的企业ID',
    'agent_id' => '应用AgentID',
    'secret' => '应用Secret',
    'token' => '回调Token',
    'encoding_aes_key' => '消息加解密密钥',
    'oauth_redirect_uri' => 'https://yourdomain.com/oauth/callback'
];

2 核心SDK类

<?php
namespace App\Services;
use GuzzleHttp\Client;
class WechatWorkService
{
    private $corpId;
    private $agentId;
    private $secret;
    private $accessToken;
    private $httpClient;
    public function __construct()
    {
        $config = config('wechat_work');
        $this->corpId = $config['corp_id'];
        $this->agentId = $config['agent_id'];
        $this->secret = $config['secret'];
        $this->httpClient = new Client([
            'base_uri' => 'https://qyapi.weixin.qq.com/cgi-bin/',
            'timeout' => 10.0
        ]);
    }
    // 获取Access Token
    public function getAccessToken()
    {
        $cacheKey = 'wechat_work_access_token_' . $this->agentId;
        // 从缓存获取
        if ($token = cache()->get($cacheKey)) {
            return $token;
        }
        $response = $this->httpClient->get('gettoken', [
            'query' => [
                'corpid' => $this->corpId,
                'corpsecret' => $this->secret
            ]
        ]);
        $result = json_decode($response->getBody(), true);
        if ($result['errcode'] === 0) {
            // 缓存token(提前5分钟过期)
            cache()->put($cacheKey, $result['access_token'], $result['expires_in'] - 300);
            return $result['access_token'];
        }
        throw new \Exception('获取AccessToken失败:' . $result['errmsg']);
    }
    // 获取OAuth授权URL
    public function getOAuthUrl($redirectUri, $state = '')
    {
        $redirectUri = urlencode($redirectUri);
        return "https://open.weixin.qq.com/connect/oauth2/authorize?" .
               "appid={$this->corpId}&" .
               "redirect_uri={$redirectUri}&" .
               "response_type=code&" .
               "scope=snsapi_base&" .
               "state={$state}#wechat_redirect";
    }
    // 获取用户信息
    public function getUserInfo($code)
    {
        $token = $this->getAccessToken();
        // 获取访问Token
        $response = $this->httpClient->get('user/getuserinfo', [
            'query' => [
                'access_token' => $token,
                'code' => $code
            ]
        ]);
        $result = json_decode($response->getBody(), true);
        if ($result['errcode'] === 0) {
            // 获取用户详细信息
            return $this->getUserDetail($result['UserId']);
        }
        throw new \Exception('获取用户信息失败:' . $result['errmsg']);
    }
    // 获取用户详细信息
    public function getUserDetail($userId)
    {
        $token = $this->getAccessToken();
        $response = $this->httpClient->post('user/get', [
            'query' => ['access_token' => $token],
            'json' => ['userid' => $userId]
        ]);
        return json_decode($response->getBody(), true);
    }
    // 发送应用消息
    public function sendMessage($toUser, $content, $msgType = 'text')
    {
        $token = $this->getAccessToken();
        $message = [
            'touser' => is_array($toUser) ? implode('|', $toUser) : $toUser,
            'msgtype' => $msgType,
            'agentid' => $this->agentId
        ];
        switch ($msgType) {
            case 'text':
                $message['text'] = ['content' => $content];
                break;
            case 'markdown':
                $message['markdown'] = ['content' => $content];
                break;
            case 'news':
                $message['news'] = $content;
                break;
        }
        $response = $this->httpClient->post('message/send', [
            'query' => ['access_token' => $token],
            'json' => $message
        ]);
        return json_decode($response->getBody(), true);
    }
}

钉钉集成

1 基础配置

<?php
// config/dingtalk.php
return [
    'app_key' => '你的AppKey',
    'app_secret' => '你的AppSecret',
    'agent_id' => '应用AgentId',
    'corp_id' => '企业CorpId',
    'oauth_redirect_uri' => 'https://yourdomain.com/dingtalk/callback'
];

2 核心SDK类

<?php
namespace App\Services;
use GuzzleHttp\Client;
class DingTalkService
{
    private $appKey;
    private $appSecret;
    private $agentId;
    private $accessToken;
    private $httpClient;
    public function __construct()
    {
        $config = config('dingtalk');
        $this->appKey = $config['app_key'];
        $this->appSecret = $config['app_secret'];
        $this->agentId = $config['agent_id'];
        $this->httpClient = new Client([
            'base_uri' => 'https://oapi.dingtalk.com/',
            'timeout' => 10.0
        ]);
    }
    // 获取Access Token
    public function getAccessToken()
    {
        $cacheKey = 'dingtalk_access_token';
        if ($token = cache()->get($cacheKey)) {
            return $token;
        }
        $response = $this->httpClient->post('gettoken', [
            'query' => [
                'appkey' => $this->appKey,
                'appsecret' => $this->appSecret
            ]
        ]);
        $result = json_decode($response->getBody(), true);
        if ($result['errcode'] === 0) {
            cache()->put($cacheKey, $result['access_token'], $result['expires_in'] - 300);
            return $result['access_token'];
        }
        throw new \Exception('获取AccessToken失败:' . $result['errmsg']);
    }
    // 获取免登录授权码
    public function getAuthCodeUrl($redirectUri)
    {
        $redirectUri = urlencode($redirectUri);
        return "https://oapi.dingtalk.com/connect/oauth2/sns_authorize?" .
               "appid={$this->appKey}&" .
               "response_type=code&" .
               "scope=snsapi_auth&" .
               "state=STATE&" .
               "redirect_uri={$redirectUri}";
    }
    // 获取用户信息
    public function getUserInfo($authCode)
    {
        $token = $this->getAccessToken();
        // 获取用户Token
        $response = $this->httpClient->post('user/getuserinfo', [
            'query' => ['access_token' => $token],
            'json' => ['code' => $authCode]
        ]);
        $result = json_decode($response->getBody(), true);
        if ($result['errcode'] === 0) {
            $userId = $result['userid'];
            return $this->getUserDetail($userId);
        }
        throw new \Exception('获取用户信息失败:' . $result['errmsg']);
    }
    // 获取用户详细信息
    public function getUserDetail($userId)
    {
        $token = $this->getAccessToken();
        $response = $this->httpClient->post('user/get', [
            'query' => ['access_token' => $token],
            'json' => ['userid' => $userId]
        ]);
        return json_decode($response->getBody(), true);
    }
    // 发送工作通知消息
    public function sendMessage($userIds, $content, $msgType = 'text')
    {
        $token = $this->getAccessToken();
        $message = [
            'agent_id' => $this->agentId,
            'userid_list' => is_array($userIds) ? implode(',', $userIds) : $userIds,
            'msg' => [
                'msgtype' => $msgType
            ]
        ];
        switch ($msgType) {
            case 'text':
                $message['msg']['text'] = ['content' => $content];
                break;
            case 'markdown':
                $message['msg']['markdown'] = [
                    'title' => '通知',
                    'text' => $content
                ];
                break;
            case 'action_card':
                $message['msg']['action_card'] = $content;
                break;
        }
        $response = $this->httpClient->post('topapi/message/corpconversation/asyncsend_v2', [
            'query' => ['access_token' => $token],
            'json' => $message
        ]);
        return json_decode($response->getBody(), true);
    }
    // 创建审批实例
    public function createApproval($processCode, $formData, $approvers)
    {
        $token = $this->getAccessToken();
        $data = [
            'process_code' => $processCode,
            'form_component_values' => $formData,
            'approvers' => $approvers,
            'agent_id' => $this->agentId
        ];
        $response = $this->httpClient->post('topapi/processinstance/create', [
            'query' => ['access_token' => $token],
            'json' => $data
        ]);
        return json_decode($response->getBody(), true);
    }
}

统一控制器

<?php
namespace App\Http\Controllers;
use App\Services\WechatWorkService;
use App\Services\DingTalkService;
use Illuminate\Http\Request;
class PlatformController extends Controller
{
    private $wechatWorkService;
    private $dingTalkService;
    public function __construct(
        WechatWorkService $wechatWorkService,
        DingTalkService $dingTalkService
    ) {
        $this->wechatWorkService = $wechatWorkService;
        $this->dingTalkService = $dingTalkService;
    }
    // 企业微信登录
    public function wechatLogin(Request $request)
    {
        $state = $request->input('state', 'wechat_work');
        $url = $this->wechatWorkService->getOAuthUrl(
            route('wechat.oauth.callback'),
            $state
        );
        return redirect($url);
    }
    // 企业微信回调
    public function wechatCallback(Request $request)
    {
        try {
            $code = $request->input('code');
            $userInfo = $this->wechatWorkService->getUserInfo($code);
            // 处理用户登录逻辑
            $user = User::where('wechat_work_id', $userInfo['userid'])->first();
            if (!$user) {
                // 创建新用户
                $user = User::create([
                    'name' => $userInfo['name'],
                    'wechat_work_id' => $userInfo['userid'],
                    'email' => $userInfo['email'] ?? '',
                    'avatar' => $userInfo['avatar'] ?? ''
                ]);
            }
            auth()->login($user);
            return redirect('/dashboard');
        } catch (\Exception $e) {
            return redirect('/login')->with('error', '企业微信登录失败');
        }
    }
    // 钉钉登录
    public function dingtalkLogin()
    {
        $url = $this->dingTalkService->getAuthCodeUrl(
            route('dingtalk.oauth.callback')
        );
        return redirect($url);
    }
    // 钉钉回调
    public function dingtalkCallback(Request $request)
    {
        try {
            $authCode = $request->input('authCode');
            $userInfo = $this->dingTalkService->getUserInfo($authCode);
            // 处理用户登录逻辑
            $user = User::where('dingtalk_id', $userInfo['userid'])->first();
            if (!$user) {
                // 创建新用户
                $user = User::create([
                    'name' => $userInfo['name'],
                    'dingtalk_id' => $userInfo['userid'],
                    'email' => $userInfo['email'] ?? '',
                    'avatar' => $userInfo['avatar'] ?? ''
                ]);
            }
            auth()->login($user);
            return redirect('/dashboard');
        } catch (\Exception $e) {
            return redirect('/login')->with('error', '钉钉登录失败');
        }
    }
    // 发送消息(统一接口)
    public function sendNotification(Request $request)
    {
        $validated = $request->validate([
            'platform' => 'required|in:wechat,dingtalk',
            'user_id' => 'required',
            'content' => 'required',
            'type' => 'required|in:text,markdown,news'
        ]);
        try {
            if ($validated['platform'] === 'wechat') {
                $result = $this->wechatWorkService->sendMessage(
                    $validated['user_id'],
                    $validated['content'],
                    $validated['type']
                );
            } else {
                $result = $this->dingTalkService->sendMessage(
                    $validated['user_id'],
                    $validated['content'],
                    $validated['type']
                );
            }
            return response()->json([
                'success' => true,
                'message' => '消息发送成功',
                'data' => $result
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => $e->getMessage()
            ], 500);
        }
    }
}

Webhook处理

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class WebhookController extends Controller
{
    // 企业微信回调
    public function wechatWebhook(Request $request)
    {
        // 验证签名
        $signature = $request->input('msg_signature');
        $timestamp = $request->input('timestamp');
        $nonce = $request->input('nonce');
        $echostr = $request->input('echostr');
        // 处理回调验证
        if ($echostr) {
            return $this->verifyUrl($signature, $timestamp, $nonce, $echostr);
        }
        // 处理消息
        $xmlData = $request->getContent();
        $message = simplexml_load_string($xmlData, 'SimpleXMLElement', LIBXML_NOCDATA);
        return $this->handleMessage($message);
    }
    // 钉钉回调
    public function dingtalkWebhook(Request $request)
    {
        $data = $request->all();
        // 验证回调
        $signature = $data['signature'];
        $timestamp = $data['timestamp'];
        $nonce = $data['nonce'];
        // 处理回调
        $eventType = $data['EventType'];
        switch ($eventType) {
            case 'check_url':
                return 'success';
            case 'user_add_org':
                return $this->handleUserAdd($data);
            case 'user_leave_org':
                return $this->handleUserLeave($data);
            default:
                return 'success';
        }
    }
}

使用示例

// 路由配置
Route::prefix('oauth')->group(function () {
    Route::get('wechat/login', [PlatformController::class, 'wechatLogin'])->name('wechat.oauth.login');
    Route::get('wechat/callback', [PlatformController::class, 'wechatCallback'])->name('wechat.oauth.callback');
    Route::get('dingtalk/login', [PlatformController::class, 'dingtalkLogin'])->name('dingtalk.oauth.login');
    Route::get('dingtalk/callback', [PlatformController::class, 'dingtalkCallback'])->name('dingtalk.oauth.callback');
});
// Webhook路由
Route::post('webhook/wechat', [WebhookController::class, 'wechatWebhook'])->name('webhook.wechat');
Route::post('webhook/dingtalk', [WebhookController::class, 'dingtalkWebhook'])->name('webhook.dingtalk');
// 发送通知
Route::post('notification/send', [PlatformController::class, 'sendNotification'])->name('notification.send');

依赖安装

composer require guzzlehttp/guzzle
composer require illuminate/cache

这个方案提供了完整的企业微信和钉钉集成功能,包括用户认证、消息推送、Webhook处理等,你可以根据实际需求进行调整和扩展。

抱歉,评论功能暂时关闭!