IMCallbackController.php 8.2 KB
<?php

namespace App\Http\Container\ProviderSection\Controllers;

use App\Exceptions\TestCallbackException;
use App\Helpers\IMHelper;
use App\Jobs\ImMessageSaveJob;
use App\Models\ActivityGroup;
use App\Models\ActivityGroupUser;
use App\Models\User;
use GuzzleHttp\Promise\PromiseInterface;
use Hikoon\LaravelApi\Support\ApiController;
use Illuminate\Http\Client\Response;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Redis;
use Illuminate\Support\Str;

class IMCallbackController extends ApiController
{
    /**
     * @param string $key
     * @return bool
     */
    protected function gate(string $key): bool
    {
        return Str::of($key)->match('/^' . config('services.im.prefix') . '\d+$/')->isNotEmpty();
    }

    /**
     * @param \Illuminate\Http\Request $request
     * @return \GuzzleHttp\Promise\PromiseInterface|\Illuminate\Http\Client\Response|\Illuminate\Http\JsonResponse
     * @throws \Laravel\Octane\Exceptions\DdException
     */
    public function __invoke(Request $request): PromiseInterface|JsonResponse|Response
    {
        $method = Str::of($request->input('CallbackCommand'))->replace('.', '')->lcfirst()->toString();

        if (method_exists($this, $method)) {
            try {
                return $this->$method($request->except(['CallbackCommand']));
            } catch (TestCallbackException) {
                return App::isProduction() ?
                    Http::asJson()->timeout(2)->post('https://hi-sing-service-dev.hikoon.com/provider/imCallback', $request->all()) :
                    new JsonResponse(['ActionStatus' => 'OK', 'ErrorInfo' => '', 'ErrorCode' => 0]);
            }
        }

        return new JsonResponse(['ActionStatus' => 'OK', 'ErrorInfo' => '', 'ErrorCode' => 0]);
    }

    /**
     * @param array $data
     * @return \Illuminate\Http\JsonResponse
     * @throws \Throwable
     */
    protected function stateStateChange(array $data): JsonResponse
    {
        $platform = Arr::get($data, 'OptPlatform');
        $userId   = Arr::get($data, 'Info.To_Account');
        $action   = Arr::get($data, 'Info.Action');

        throw_unless($this->gate($userId), TestCallbackException::class);


        if ($action === 'Login') {
            User::query()->whereKey(IMHelper::accountToUserKey($userId))->update(['im_client' => $platform, 'im_status' => 1]);
            Redis::client()->hDel('imOfflineMsg', IMHelper::accountToUserKey($userId));
        } else {
            User::query()->whereKey(IMHelper::accountToUserKey($userId))->where('im_client', $platform)->update(['im_status' => 0]);
        }

        return new JsonResponse(['ActionStatus' => 'OK', 'ErrorInfo' => '', 'ErrorCode' => 0]);
    }

    /**
     * @throws \Throwable
     */
    protected function c2CCallbackAfterSendMsg(array $data): JsonResponse
    {
        $formId = Arr::get($data, 'From_Account');

        throw_unless($this->gate($formId), TestCallbackException::class);

        ImMessageSaveJob::dispatch($data);

        return new JsonResponse(['ActionStatus' => 'OK', 'ErrorInfo' => '', 'ErrorCode' => 0]);
    }

    /**
     * @param array $data
     * @return \Illuminate\Http\JsonResponse
     * @throws \Throwable
     */
    protected function groupCallbackAfterCreateGroup(array $data): JsonResponse
    {
        $groupId = Arr::get($data, 'GroupId');

        throw_unless($this->gate($groupId), TestCallbackException::class);

        $ownerId             = IMHelper::accountToUserKey(Arr::get($data, 'Owner_Account', 0));
        $userDefinedDataList = Arr::pluck($data['UserDefinedDataList'], 'Value', 'Key');

        $group      = ActivityGroup::query()->firstOrCreate(['im_group_id' => $groupId], ['user_id' => $ownerId, 'activity_id' => Arr::get($userDefinedDataList, 'ActivityKey', 0), 'name' => $data['Name']]);
        $memberList = Arr::map($data['MemberList'], static fn($item) => ['user_id' => IMHelper::accountToUserKey($item['Member_Account']), 'group_id' => $group->getKey()]);

        ActivityGroupUser::query()->upsert($memberList, ['user_id', 'guard_id']);

        IMHelper::sendGroupMessage($groupId, [
            "MsgBody" => [
                IMHelper::createCustomMessage([
                    "Data" => [
                        "businessID" => "group_inviter_user",
                        'inviter'    => User::query()->whereKey($ownerId)->value('nick_name'),
                        'memberList' => User::query()->whereIn('id', array_column($memberList, 'user_id'))->pluck('nick_name')->toArray(),
                        "Desc"       => ''
                    ]
                ])
            ]
        ]);

        return new JsonResponse(['ActionStatus' => 'OK', 'ErrorInfo' => '', 'ErrorCode' => 0]);
    }

    /**
     * @param array $data
     * @return \Illuminate\Http\JsonResponse
     * @throws \Throwable
     */
    protected function groupCallbackAfterGroupInfoChanged(array $data): JsonResponse
    {
        $groupId = Arr::get($data, 'GroupId');

        throw_unless($this->gate($groupId), TestCallbackException::class);

        if (isset($data['Name'])) {
            ActivityGroup::query()->where('im_group_id', $groupId)->update(['name' => $data['Name']]);
        }

        return new JsonResponse(['ActionStatus' => 'OK', 'ErrorInfo' => '', 'ErrorCode' => 0]);
    }

    /**
     * @param array $data
     * @return \Illuminate\Http\JsonResponse
     * @throws \Throwable
     */
    protected function groupCallbackAfterNewMemberJoin(array $data): JsonResponse
    {
        $groupId = Arr::get($data, 'GroupId');

        throw_unless($this->gate($groupId), TestCallbackException::class);

        if ($group = ActivityGroup::query()->where('im_group_id', $groupId)->value('id')) {
            $inviterUser = IMHelper::accountToUserKey(Arr::get($data, 'Operator_Account', 0));
            $memberList  = Arr::map($data['NewMemberList'], static fn($item) => ['user_id' => IMHelper::accountToUserKey($item['Member_Account']), 'group_id' => $group]);
            ActivityGroupUser::query()->upsert($memberList, ['user_id', 'group_id']);

            IMHelper::sendGroupMessage($groupId, [
                "MsgBody" => [
                    IMHelper::createCustomMessage([
                        "Data" => [
                            "businessID" => "group_inviter_user",
                            'inviter'    => User::query()->whereKey($inviterUser)->value('nick_name'),
                            'memberList' => User::query()->whereIn('id', array_column($memberList, 'user_id'))->pluck('nick_name')->toArray(),
                            "Desc"       => ''
                        ]
                    ])
                ]
            ]);
        }
        return new JsonResponse(['ActionStatus' => 'OK', 'ErrorInfo' => '', 'ErrorCode' => 0]);
    }

    /**
     * @param array $data
     * @return \Illuminate\Http\JsonResponse
     * @throws \Throwable
     */
    protected function groupCallbackAfterMemberExit(array $data): JsonResponse
    {
        $groupId = Arr::get($data, 'GroupId');

        throw_unless($this->gate($groupId), TestCallbackException::class);

        if ($group = ActivityGroup::query()->where('im_group_id', $groupId)->value('id')) {
            $memberList = Arr::map($data['ExitMemberList'], static fn($item) => IMHelper::accountToUserKey($item['Member_Account']));
            ActivityGroupUser::query()->where('group_id', $group)->whereIn('user_id', $memberList)->delete();
        }

        return new JsonResponse(['ActionStatus' => 'OK', 'ErrorInfo' => '', 'ErrorCode' => 0]);
    }

    /**
     * @param array $data
     * @return \Illuminate\Http\JsonResponse
     * @throws \Throwable
     */
    protected function groupCallbackAfterGroupDestroyed(array $data): JsonResponse
    {
        $groupId = Arr::get($data, 'GroupId');

        throw_unless($this->gate($groupId), TestCallbackException::class);

        if ($group = ActivityGroup::query()->where('im_group_id', $groupId)->value('id')) {
            ActivityGroup::query()->whereKey($group)->delete();
            ActivityGroupUser::query()->where('group_id', $group)->delete();
        }

        return new JsonResponse(['ActionStatus' => 'OK', 'ErrorInfo' => '', 'ErrorCode' => 0]);
    }
}