徐总多门店
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

908 lines
26 KiB

<?php
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2020 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
namespace crmeb\services\wechat;
use crmeb\services\wechat\config\WorkConfig;
use crmeb\services\wechat\groupChat\Client;
use crmeb\services\wechat\groupChat\ServiceProvider;
use crmeb\services\wechat\department\ServiceProvider as DepartmentServiceProvider;
use EasyWeChat\Factory;
use EasyWeChat\Kernel\Exceptions\BadRequestException;
use EasyWeChat\Kernel\Exceptions\InvalidArgumentException;
use EasyWeChat\Kernel\Exceptions\InvalidConfigException;
use GuzzleHttp\Exception\GuzzleException;
use Symfony\Component\HttpFoundation\Request;
use think\facade\Cache;
use think\Response;
use Yurun\Util\Swoole\Guzzle\SwooleHandler;
use EasyWeChat\Work\Application;
use EasyWeChat\Work\ExternalContact\MessageTemplateClient;
use Symfony\Component\Cache\Adapter\RedisAdapter;
/**
* 企业微信
* Class Work
* @package crmeb\services\wechat
* @method Client groupChat() 加入群聊配置
* @method MessageTemplateClient groupChatWelcome() 入群欢迎语素材
*/
class Work extends BaseApplication
{
/**
* @var WorkConfig
*/
protected $config;
/**
* @var Application[]
*/
protected $application = [];
/**
* @var string
*/
protected $configHandler;
/**
* @var string[]
*/
protected static $property = [
'groupChat' => 'external_contact',
'groupChatWelcome' => 'external_contact_message_template'
];
/**
* Work constructor.
*/
public function __construct()
{
/** @var WorkConfig config */
$this->config = app()->make(WorkConfig::class);
$this->debug = DefaultConfig::value('logger');
}
/**
* 设置获取配置
* @param string $handler
* @return $this
*/
public function setConfigHandler(string $handler)
{
$this->configHandler = $handler;
return $this;
}
/**
* @return Work
*/
public static function instance()
{
return app()->make(static::class);
}
/**
* 获取实例化句柄
* @param string $type
* @return Application
*/
public function application(string $type = WorkConfig::TYPE_USER)
{
$config = $this->config->all();
$config = array_merge($config, $this->config->setHandler($this->configHandler)->getAppConfig($type));
if (!isset($this->application[$type])) {
$this->application[$type] = Factory::work($config);
$this->application[$type]['guzzle_handler'] = SwooleHandler::class;
$request = request();
$this->application[$type]->rebind('request', new Request($request->get(), $request->post(), [], [], [], $request->server(), $request->getContent()));
$this->application[$type]->register(new ServiceProvider());
$this->application[$type]->register(new DepartmentServiceProvider());
$this->application[$type]->rebind('cache', new RedisAdapter(Cache::store('redis')->handler()));
}
return $this->application[$type];
}
/**
* 服务端
* @return Response
* @throws BadRequestException
* @throws InvalidArgumentException
* @throws InvalidConfigException
* @throws \ReflectionException
*/
public static function serve(): Response
{
$make = self::instance();
$make->application()->server->push($make->pushMessageHandler);
$response = $make->application()->server->serve();
return response($response->getContent());
}
/**
* 获取用户授权信息
* @param string $code
* @return array
*/
public static function getAuthUserInfo(string $code = '')
{
$code = $code ?: request()->param('code');
if (!$code) {
throw new WechatException('缺少CODE');
}
try {
$userInfo = self::instance()->application(WorkConfig::TYPE_USER_APP)->oauth->detailed()->userFromCode($code);
self::logger('获取用户授权信息', compact('code'), $userInfo);
} catch (\Throwable $e) {
throw new WechatException($e->getMessage());
}
return $userInfo->getRaw();
}
/**
* 创建联系我二维码
* @param int $channelCodeId
* @param array $users
* @param bool $skipVerify
* @return array
* @throws InvalidConfigException
* @throws GuzzleException
*/
public static function createQrCode(int $channelCodeId, array $users, bool $skipVerify = true)
{
$config = [
'skip_verify' => $skipVerify,
'state' => 'channelCode-' . $channelCodeId,
'user' => $users,
];
$response = self::instance()->application(WorkConfig::TYPE_USER_APP)->contact_way->create(2, 2, $config);
self::logger('创建联系我二维码', $config, $response);
return $response;
}
/**
* 更新联系我二维码
* @param int $channelCodeId
* @param array $users
* @param string $wxConfigId
* @param bool $skipVerify
* @return array
* @throws InvalidConfigException
* @throws GuzzleException
*/
public static function updateQrCode(int $channelCodeId, array $users, string $wxConfigId, bool $skipVerify = true)
{
$config = [
'skip_verify' => $skipVerify,
'state' => 'channelCode-' . (string)$channelCodeId,
'user' => $users,
];
$response = self::instance()->application(WorkConfig::TYPE_USER_APP)->contact_way->update($wxConfigId, $config);
self::logger('更新联系我二维码', compact('config', 'wxConfigId'), $response);
return $response;
}
/**
* 删除联系我二维码
* @param string $wxConfigId
* @return array
* @throws InvalidConfigException
* @throws GuzzleException
*/
public static function deleteQrCode(string $wxConfigId)
{
$response = self::instance()->application(WorkConfig::TYPE_USER_APP)->contact_way->delete($wxConfigId);
self::logger('删除联系我二维码', compact('wxConfigId'), $response);
return $response;
}
/**
* 添加企业群发消息模板
* @param array $msg
* @return WechatResponse
*/
public static function addMsgTemplate(array $msg)
{
$response = self::instance()->application(WorkConfig::TYPE_USER_APP)->external_contact_message->submit($msg);
self::logger('添加企业群发消息模板', compact('msg'), $response);
return new WechatResponse($response);
}
/**
* 获取群发成员发送任务列表
* @param string $msgId
* @param int|null $limit
* @param string|null $cursor
* @return WechatResponse
* @throws GuzzleException
* @throws InvalidArgumentException
* @throws InvalidConfigException
*/
public static function getGroupmsgTask(string $msgId, ?int $limit = null, ?string $cursor = null)
{
$response = self::instance()->application(WorkConfig::TYPE_USER_APP)->external_contact_message->getGroupmsgTask($msgId, $limit, $cursor);
self::logger('获取群发成员发送任务列表', compact('msgId', 'limit', 'cursor'), $response);
return new WechatResponse($response);
}
/**
* 获取企业群发成员执行结果
* @param string $msgId
* @param string $userid
* @param int|null $limit
* @param string|null $cursor
* @return WechatResponse
* @throws GuzzleException
* @throws InvalidArgumentException
* @throws InvalidConfigException
*/
public static function getGroupmsgSendResult(string $msgId, string $userid, ?int $limit = null, ?string $cursor = null)
{
$response = self::instance()->application(WorkConfig::TYPE_USER_APP)->external_contact_message->getGroupmsgSendResult($msgId, $userid, $limit, $cursor);
self::logger('获取企业群发成员执行结果', compact('msgId', 'userid', 'limit', 'cursor'), $response);
return new WechatResponse($response);
}
/**
* 创建发送朋友圈任务
* @param array $param
* @return WechatResponse
*/
public static function addMomentTask(array $param)
{
$response = self::instance()->application(WorkConfig::TYPE_USER_APP)->external_contact_moment->createTask($param);
self::logger('创建发送朋友圈任务', compact('param'), $response);
return new WechatResponse($response);
}
/**
* 获取发送朋友圈任务创建结果
* @param string $jobId
* @return WechatResponse
*/
public static function getMomentTask(string $jobId)
{
$response = self::instance()->application(WorkConfig::TYPE_USER_APP)->external_contact_moment->getTask($jobId);
self::logger('获取发送朋友圈任务创建结果', compact('jobId'), $response);
return new WechatResponse($response);
}
/**
* 获取客户朋友圈企业发表的列表
* @param string $momentId
* @param string $cursor
* @param int $limit
* @return WechatResponse
*/
public static function getMomentTaskInfo(string $momentId, string $cursor = '', int $limit = 500)
{
$response = self::instance()->application(WorkConfig::TYPE_USER_APP)->external_contact_moment->getTasks($momentId, $cursor, $limit);
self::logger('获取客户朋友圈企业发表的列表', compact('momentId', 'cursor', 'limit'), $response);
return new WechatResponse($response);
}
/**
* 获取客户朋友圈发表时选择的可见范围
* @param string $momentId
* @param string $userId
* @param string $cursor
* @param int $limit
* @return WechatResponse
*/
public static function getMomentCustomerList(string $momentId, string $userId, string $cursor, int $limit = 500)
{
$response = self::instance()->application(WorkConfig::TYPE_USER_APP)->external_contact_moment->getCustomers($momentId, $userId, $cursor, $limit);
self::logger('获取客户朋友圈发表时选择的可见范围', compact('momentId', 'cursor', 'userId', 'limit'), $response);
return new WechatResponse($response);
}
/**
* 发送应用消息
* @param array $message
* @return WechatResponse
* @throws GuzzleException
* @throws InvalidConfigException
*/
public static function sendMessage(array $message)
{
$instance = self::instance();
if (empty($message['agentid'])) {
$config = $instance->config->getAppConfig(WorkConfig::TYPE_USER_APP);
if (empty($config['agent_id'])) {
throw new WechatException('请先配置agent_id');
}
$message['agentid'] = $config['agent_id'];
}
$response = $instance->application(WorkConfig::TYPE_USER_APP)->message->send($message);
self::logger('发送应用消息', compact('message'), $response);
return new WechatResponse($response);
}
/**
* 获取部门列表
* @return mixed
*/
public static function getDepartment()
{
try {
$response = self::instance()->application(WorkConfig::TYPE_USER_APP)->department->list();
self::logger('获取部门列表', [], $response);
return $response;
} catch (\Throwable $e) {
self::error($e);
return [];
}
}
/**
* 获取子部门ID列表
* @return array|mixed
* @author 等风来
* @email 136327134@qq.com
* @date 2022/10/9
*/
public static function simpleList()
{
try {
$response = self::instance()->application(WorkConfig::TYPE_USER_APP)->department->simpleList();
self::logger('获取子部门ID列表', [], $response);
return $response;
} catch (\Throwable $e) {
self::error($e);
return [];
}
}
/**
* 获取成员ID列表
* @return array|mixed
* @author 等风来
* @email 136327134@qq.com
* @date 2022/10/9
*/
public static function getUserListIds(int $limit, string $cursor = '')
{
try {
$response = self::instance()->application(WorkConfig::TYPE_USER_APP)->department->getUserListIds($limit, $cursor);
self::logger('获取成员ID列表', [], $response);
return $response;
} catch (\Throwable $e) {
self::error($e);
return [];
}
}
/**
* 获取部门详细信息
* @param int $id
* @return array|mixed
* @author 等风来
* @email 136327134@qq.com
* @date 2022/10/10
*/
public static function getDepartmentInfo(int $id)
{
try {
$response = self::instance()->application(WorkConfig::TYPE_USER_APP)->department->get($id);
self::logger('获取部门详细信息', [], $response);
return $response;
} catch (\Throwable $e) {
self::error($e);
return [];
}
}
/**
* 获取部门成员详细信息
* @param int $departmentId
* @return array
*/
public static function getDetailedDepartmentUsers(int $departmentId)
{
try {
$response = self::instance()->application(WorkConfig::TYPE_USER_APP)->user->getDetailedDepartmentUsers($departmentId, true);
self::logger('获取部门成员详细信息', compact('departmentId'), $response);
return $response;
} catch (\Throwable $e) {
self::error($e);
return [];
}
}
/**
* 获取通讯录成员详情
* @param string $userId
* @return array
*/
public static function getMemberInfo(string $userId)
{
try {
$response = self::instance()->application(WorkConfig::TYPE_USER_APP)->user->get($userId);
self::logger('获取通讯录成员详情', compact('userId'), $response);
return $response;
} catch (\Throwable $e) {
self::error($e);
return [];
}
}
/**
* userid转openid
* @param string $userId
* @return mixed|null
*/
public static function useridByOpenid(string $userId)
{
try {
$response = self::instance()->application(WorkConfig::TYPE_USER_APP)->user->userIdToOpenid($userId);
self::logger('userid转openid', compact('userId'), $response);
return $response['openid'] ?? null;
} catch (\Throwable $e) {
self::error($e);
return null;
}
}
/**
* 获取某个成员下的客户信息
* @param string $externalUserID
* @return array
*/
public static function getClientInfo(string $externalUserID)
{
try {
$response = self::instance()->application(WorkConfig::TYPE_USER_APP)->external_contact->get($externalUserID);
self::logger('获取某个成员下的客户信息', compact('externalUserID'), $response);
return $response;
} catch (\Throwable $e) {
self::error($e);
return [];
}
}
/**
* 批量获取客户详情
* @param array $userids
* @param string $cursor
* @param int $limit
* @return array|mixed|null
*/
public static function getBatchClientList(array $userids, string $cursor = '', int $limit = 100)
{
if ($limit > 100) {
$limit = 100;
}
try {
$response = self::instance()->application(WorkConfig::TYPE_USER_APP)->external_contact->batchGet($userids, $cursor, $limit);
self::logger('批量获取客户详情', compact('userids', 'cursor', 'limit'), $response);
return $response;
} catch (\Throwable $e) {
self::error($e);
return [];
}
}
/**
* 获取客户标签
* @param array $tagIds
* @param array $groupIds
* @return array
*/
public static function getCorpTags(array $tagIds = [], array $groupIds = [])
{
try {
$response = self::instance()->application(WorkConfig::TYPE_USER_APP)->external_contact->getCorpTags($tagIds, $groupIds);
self::logger('获取客户标签', compact('tagIds', 'groupIds'), $response);
return $response;
} catch (\Throwable $e) {
self::error($e);
return [];
}
}
/**
* 添加客户标签
* @param string $groupName
* @param array $tag
* @return array
*/
public static function addCorpTag(string $groupName, array $tag = [])
{
$params = [
"group_name" => $groupName,
"tag" => $tag
];
try {
$response = self::instance()->application(WorkConfig::TYPE_USER_APP)->external_contact->addCorpTag($params);
self::logger('添加客户标签', compact('groupName', 'tag'), $response);
return $response;
} catch (\Throwable $e) {
self::error($e);
return [];
}
}
/**
* 编辑客户标签
* @param string $id
* @param string $name
* @param int $order
* @return array
*/
public static function updateCorpTag(string $id, string $name, int $order = 1)
{
try {
$response = self::instance()->application(WorkConfig::TYPE_USER_APP)->external_contact->updateCorpTag($id, $name, $order);
self::logger('编辑客户标签', compact('id', 'name', 'order'), $response);
return $response;
} catch (\Throwable $e) {
self::error($e);
return [];
}
}
/**
* 删除客户标签
* @param array $tagId
* @param array $groupId
* @return array
*/
public static function deleteCorpTag(array $tagId, array $groupId)
{
try {
$response = self::instance()->application(WorkConfig::TYPE_USER_APP)->external_contact->deleteCorpTag($tagId, $groupId);
self::logger('删除客户标签', compact('tagId', 'groupId'), $response);
return $response;
} catch (\Throwable $e) {
self::error($e);
return [];
}
}
/**
* 编辑客户标签
* @param string $userid
* @param string $externalUserid
* @param array $addTag
* @param array $removeTag
* @return array
*/
public static function markTags(string $userid, string $externalUserid, array $addTag = [], array $removeTag = [])
{
$params = [
"userid" => $userid,
"external_userid" => $externalUserid,
"add_tag" => $addTag,
"remove_tag" => $removeTag
];
try {
$response = self::instance()->application(WorkConfig::TYPE_USER_APP)->external_contact->markTags($params);
self::logger('编辑客户标签', compact('params'), $response);
return $response;
} catch (\Throwable $e) {
self::error($e);
return [];
}
}
/**
* 获取客户群列表
* @param array $useridList
* @param string $offset
* @return array
*/
public static function getGroupChats(array $useridList = [], int $limit = 100, string $offset = null)
{
$params = [
"status_filter" => 0,
"owner_filter" => [
"userid_list" => $useridList,
],
"limit" => $limit
];
if ($offset) {
$params['cursor'] = $offset;
}
try {
$response = self::instance()->application(WorkConfig::TYPE_USER_APP)->external_contact->getGroupChats($params);
self::logger('获取客户群列表', compact('params'), $response);
return $response;
} catch (\Throwable $e) {
self::error($e);
return [];
}
}
/**
* 获取群详情
* @param string $chatId
* @return array
*/
public static function getGroupChat(string $chatId)
{
try {
$response = self::instance()->application(WorkConfig::TYPE_USER_APP)->external_contact->getGroupChat($chatId);
self::logger('获取群详情', compact('chatId'), $response);
return $response;
} catch (\Throwable $e) {
self::error($e);
return [];
}
}
/**
* 获取群聊数据统计
* @param int $dayBeginTime
* @param int $dayEndTime
* @param array $userIds
* @return array
*/
public static function groupChatStatisticGroupByDay(int $dayBeginTime, int $dayEndTime, array $userIds)
{
try {
$response = self::instance()->application(WorkConfig::TYPE_USER_APP)->external_contact_statistics->groupChatStatisticGroupByDay($dayBeginTime, $dayEndTime, $userIds);
self::logger('获取群聊数据统计', compact('dayBeginTime', 'dayEndTime', 'userIds'), $response);
return $response;
} catch (\Throwable $e) {
self::error($e);
return [];
}
}
/**
* 发送欢迎语
* @param string $welcomeCode
* @param array $message
* @return array|WechatResponse
* @throws InvalidArgumentException
* @throws InvalidConfigException
* @throws GuzzleException
*/
public static function sendWelcome(string $welcomeCode, array $message)
{
$response = self::instance()->application(WorkConfig::TYPE_USER_APP)->external_contact_message->sendWelcome($welcomeCode, $message);
self::logger('发送欢迎语', compact('welcomeCode', 'message'), $response);
return new WechatResponse($response);
}
/**
* 上传临时素材
* @param string $path
* @param string $type
* @return WechatResponse
* @throws InvalidConfigException
* @throws GuzzleException
*/
public static function mediaUpload(string $path, string $type = 'image')
{
$response = self::instance()->application()->media->upload($type, $path);
self::logger('上传临时素材', compact('type', 'path'), $response);
return new WechatResponse($response);
}
/**
* 上传附件资源
* @param string $path
* @param string $mediaType
* @param string $attachmentType
* @return WechatResponse
* @throws GuzzleException
* @throws InvalidConfigException
*/
public static function mediaUploadAttachment(string $path, string $mediaType = 'image', string $attachmentType = '1')
{
if (in_array($mediaType, ['video', 'file', 'voice'])) {
$url = 'https://qyapi.weixin.qq.com/cgi-bin/media/upload_attachment';
$url .= '?access_token=' . self::instance()->application()->external_contact->getAccessToken()->getToken()['access_token'];
$url .= '&media_type=' . $mediaType . '&attachment_type=' . $attachmentType;
$pathAtt = explode('/', $path);
$filename = $pathAtt[count($pathAtt) - 1];
$file = new \think\File($path);
$request = new \Yurun\Util\HttpRequest();
$request->header('Content-Type', 'multipart/form-data');
$fileuploade = new \Yurun\Util\YurunHttp\Http\Psr7\UploadedFile($filename, $file->getMime(), $path);
$res = $request->requestBody([$filename => $fileuploade])->post($url);
$response = json_decode($res->body(), true);
} else {
$response = self::instance()->application()->external_contact->uploadAttachment($path, $mediaType, $attachmentType);
}
self::logger('上传附件资源', compact('path', 'mediaType', 'attachmentType'), $response);
return new WechatResponse($response);
}
/**
* 获取临时素材
* @param string $mediaId
* @return array
* @throws InvalidConfigException
* @throws GuzzleException
*/
public static function getMedia(string $mediaId)
{
$response = self::instance()->application()->media->get($mediaId);
self::logger('获取临时素材', compact('mediaId'), $response);
return new WechatResponse($response);
}
/**
* 获取jsSDK权限配置
* @return array|object
* @throws \Psr\SimpleCache\InvalidArgumentException
*/
public static function getJsSDK(string $url = '')
{
try {
$jsSDK = self::instance()->application(WorkConfig::TYPE_USER_APP)->jssdk;
if ($url) {
$jsSDK->setUrl($url);
}
return $jsSDK->buildConfig(['getCurExternalContact', 'getCurExternalChat', 'getContext', 'chooseImage'], false, false, false);
} catch (\Throwable $e) {
return (object)[];
}
}
/**
* 获取应用配置信息
* @param string|null $url
* @return array|string
* @throws \Psr\SimpleCache\InvalidArgumentException
*/
public static function getAgentConfig(string $url = null)
{
$instance = self::instance();
$jsSDK = $instance->application(WorkConfig::TYPE_USER_APP)->jssdk;
$config = $instance->config->getAppConfig(WorkConfig::TYPE_USER_APP);
if (empty($config['agent_id'])) {
throw new WechatException('请先配置agent_id');
}
try {
return $jsSDK->getAgentConfigArray(['getCurExternalContact', 'getCurExternalChat', 'getContext', 'chooseImage'], $config['agent_id'], false, false, [], $url);
} catch (\Throwable $e) {
return (object)[];
}
}
}