HEX
Server: nginx/1.24.0
System: Linux DGT-WORDPRESS-VM-SERVER 6.14.0-1017-azure #17~24.04.1-Ubuntu SMP Mon Dec 1 20:10:50 UTC 2025 x86_64
User: ubuntu (1000)
PHP: 8.4.12
Disabled: NONE
Upload Files
File: /mnt/data/ghayatcom/ghayatcom-api/app/Http/Controllers/Api/SumsubController.php
<?php

namespace App\Http\Controllers\Api;

// namespace App\Http\Controllers;

use App\Country;
use App\Http\Controllers\Controller;
use App\Http\Requests\SumsubProfileRequest;
use App\Http\Requests\SumsubUploadRequest;
use App\Http\Requests\UserIdRequest;
use App\Http\Requests\SumsubTokenRequest;
use App\Http\Requests\AddSumsubDocumentRequest;
use App\Library\S3Library;
use App\Sumsub;
use App\User;
use Config;
use DB;
use Exception;
use GuzzleHttp;
use GuzzleHttp\Client;
use GuzzleHttp\Psr7;
use GuzzleHttp\Psr7\MultipartStream;
use GuzzleHttp\Stream\Stream;
use Illuminate\Database\QueryException;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;
use Storage;
use Throwable;

/**
 * App\Http\Controllers\Api
 *
 * @property mixed $sumsub_test_base_url
 * @property mixed $sumsub_app_token
 * @property mixed $secret_key
 * @property mixed $level_name
 */
class SumsubController extends Controller
{
    public function __construct()
    {
        $this->sumsub_test_base_url = Config::get('sumsub.sumsub_test_base_url');
        $this->sumsub_app_token = Config::get('sumsub.sumsub_app_token');
        $this->secret_key = Config::get('sumsub.sumsub_secret_key');
        $this->level_name = Config::get('sumsub.level_name');
    }

    public function webhook(Request $request)
    {
        $input = file_get_contents("php://input");
        $events = (array) json_decode($input, true);

        // $url = '/resources/applicants/'.$events['applicantId'].'/one';
        // $request = new GuzzleHttp\Psr7\Request('GET', $this->sumsub_test_base_url.$url);
        // $responseBody = $this->sendHttpRequest($request, $url)->getBody();
        // $data = json_decode($responseBody);

        $status = '0';
        if(isset($events['reviewResult'])) {
            /**
             * @var array $events
             */
            if(isset($events['reviewResult']['reviewAnswer'])) {
                if($events['reviewResult']['reviewAnswer'] == 'GREEN') {
                    $status = '1';
                }
                if($events['reviewResult']['reviewAnswer'] == 'RED') {
                    $status = '2';
                }
            }
        }

        $sumsub = Sumsub::firstOrNew([
            'application_id' => $events['applicantId']
        ]);

        $sumsub->type = 'PASSPORT';
        $sumsub->external_user_id = $events['externalUserId'];
        // $sumsub->file_name = $events['reviewStatus'].' - '.$events['reviewResult'];
        $sumsub->status = $status;
        $sumsub->response_json = json_encode($events);
        $sumsub->save();

        return true;
    }

    public function getProfileDetails(SumsubProfileRequest $request)
    {
        $validated = $request->validated();
        try {
            $status = Sumsub::where('user_id', $request->user_id)->orderBy('id', 'desc')->first();
            if ($status) {
                $applicantId = $status->application_id;
                $upload_id = $status->upload_id;
                $url = '/resources/applicants/'.$applicantId.'/one';
                $request = new GuzzleHttp\Psr7\Request('GET', $this->sumsub_test_base_url.$url);
                $responseBody = $this->sendHttpRequest($request, $url)->getBody();
                $data = json_decode($responseBody);
                $first_name = '';
                $last_name = '';
                $gender = '';
                $dob = '';
                $idcard_number = '';
                $country = '';
                $country_data = [];
                /**
                 * @var object $data
                 */
                if (isset($data->info)) {
                    $first_name = isset($data->info->firstNameEn) ? $data->info->firstNameEn : '';
                    $last_name = isset($data->info->lastNameEn) ? $data->info->lastNameEn : '';
                    $gender = isset($data->info->gender) ? $data->info->gender : '';
                    $dob = isset($data->info->dob) ? $data->info->dob : '';
                    $idcard_number = isset($data->info->idDocs[0]->number) ? $data->info->idDocs[0]->number : '';
                    $country = isset($data->info->country) ? $data->info->country : '';
                    if ($country != '') {
                        $country_data = Country::select('id', 'name')->where('iso3', $country)->first();
                    }
                }

                $response_array = ['first_name' =>$first_name, 'last_name'=>$last_name, 'gender'=>$gender, 'dob'=>$dob, 'idcard_number'=>$idcard_number, 'country'=>$country, 'country_name'=>$country_data];

                return self::sentResponse(200, $response_array, __('digimed_validation.success_response.sumsub_status'));
            } else {
                return self::sentResponse(401, [], __('digimed_validation.error_response.user_not_found'));
            }
        } catch (Exception | Throwable | QueryException $e) {
            return self::sentResponse(500, [], $e->getMessage());
        }
    }

    public function createApplicant($external_user_id)
    {
        $levelName = $this->level_name;
        $requestBody = [
            'externalUserId' => $external_user_id, //$request->externalUserId
        ];

        $url = '/resources/applicants?levelName='.$levelName;
        $request = new GuzzleHttp\Psr7\Request('POST', $this->sumsub_test_base_url.$url);
        $request = $request->withHeader('Content-Type', 'application/json');
        $request = $request->withBody(GuzzleHttp\Psr7\Utils::streamFor(json_encode($requestBody)));

        $responseBody = $this->sendHttpRequest($request, $url)->getBody();
        $final = json_decode($responseBody);
        /** @var object $final */
        return $final->id;
    }

    public function sendHttpRequest($request, $url)
    {
        $client = new GuzzleHttp\Client();
        $ts = time();

        $request = $request->withHeader('X-App-Token', $this->sumsub_app_token);
        $request = $request->withHeader('X-App-Access-Sig', $this->createSignature($ts, $request->getMethod(), $url, $request->getBody()));
        $request = $request->withHeader('X-App-Access-Ts', $ts);

        // Reset stream offset to read body in `send` method from the start
        $request->getBody()->rewind();

        try {
            $response = $client->send($request);
            if ($response->getStatusCode() != 200 && $response->getStatusCode() != 201) {
                // https://developers.sumsub.com/api-reference/#errors
                // If an unsuccessful answer is received, please log the value of the "correlationId" parameter.
                // Then perhaps you should throw the exception. (depends on the logic of your code)
            }
        } catch (GuzzleHttp\Exception\GuzzleException $e) {
            $response = $e->getMessage();
            error_log($e);
        }

        return $response;
    }

    private function createSignature($ts, $httpMethod, $url, $httpBody)
    {
        /**
         * @var string $secret_key
         */
        $secret_key = $this->secret_key;

        return hash_hmac('sha256', $ts.strtoupper($httpMethod).$url.$httpBody, $secret_key);
    }

    public function addNewDocument($application_id, $file_path, $type)
    {
        try {
            $metadata = ['idDocType' => $type, 'country' => 'MLT'];

            $multipart = new MultipartStream([
                [
                    'name' => 'metadata',
                    'contents' => json_encode($metadata),
                ],
                [
                    'name' => 'content',
                    'contents' => (Config::get('filesystems.default') == 's3') ? file_get_contents($file_path, true) : fopen($file_path, 'r'),
                ],
            ]);

            $url = '/resources/applicants/'.$application_id.'/info/idDoc';
            $request = new GuzzleHttp\Psr7\Request('POST', $this->sumsub_test_base_url.$url);
            $request = $request->withBody($multipart);

            return $this->sendHttpRequest($request, $url)->getHeader('X-Image-Id')[0];
        } catch (Exception | Throwable | QueryException $e) {
            return '';
        }
    }

    public function getApplicantStatus($applicantId)
    {
        $applicantId = $applicantId; //'61a0c1437b606d000185157d';
        $url = '/resources/applicants/'.$applicantId.'/requiredIdDocsStatus';
        $request = new GuzzleHttp\Psr7\Request('GET', $this->sumsub_test_base_url.$url);
        $responseBody = $this->sendHttpRequest($request, $url)->getBody();
        // dd(json_decode($responseBody));
        return json_decode($responseBody);
    }

    public function getAccessToken($externalUserId, $levelName)
    {
        $url = '/resources/accessTokens?userId='.$externalUserId.'&levelName='.$levelName;
        $request = new GuzzleHttp\Psr7\Request('POST', $this->sumsub_test_base_url.$url);

        return $this->sendHttpRequest($request, $url)->getBody();
    }

    public function getStatus(UserIdRequest $request)
    {
        $validated = $request->validated();
        try {
            $user_id = $request->user_id;
            $user = User::where('id', $user_id)->first();
            // $sumsub = Sumsub::where('user_id', $user_id)->orderBy('id', 'desc')->first();
            // if ($sumsub) {
            //     $sumsubId = $sumsub->id;
            //     $upload_id = $sumsub->upload_id;
            //     $application_id = $sumsub->application_id;
                // $status = $sumsub->status;
                // if($status == '1') {
                    User::where('id', $user_id)->where('user_completion', 1)->update(['user_completion' => Config::get('onboard_lists.for_patient_list.1.id')]);
                    $response_array = ['sumsub'=>'1', 'user_id'=>$user_id, 'status' => '1', 'status_value' =>'Approved', 'admin_approval'=>$user->status];
                    return self::sentResponse(200, $response_array, __('digimed_validation.success_response.sumsub_verified'));
                // } else if($status == '2') {
                //     User::where('id', $user_id)->update(['user_completion' => 1]);
                //     $response_array = ['sumsub'=>'2', 'user_id'=>$user_id, 'status' => '2', 'status_value' =>'Rejected', 'admin_approval'=>$user->status];
                //     return self::sentResponse(406, $response_array, __('digimed_validation.error_response.sumsub_rejected'));
                // } else {
                //     $response_array = ['sumsub' => '0', 'user_id'=>$user_id, 'status' => '0', 'status_value' =>'In Progress', 'admin_approval'=>$user->status];
                //     return self::sentResponse(202, $response_array, __('digimed_validation.error_response.awaiting_sumsub_approval'));
                // }
            // } else {
            //     $response_array = ['sumsub' => '-1', 'user_id'=>$user_id, 'status' =>'-1', 'status_value' =>'', 'admin_approval'=>$user->status];

            //     return self::sentResponse(404, $response_array, __('digimed_validation.error_response.sumsub_not_found'));
            // }
        } catch (Exception | Throwable | QueryException $e) {
            return self::sentResponse(500, [], $e->getMessage());
        }
    }

    public function accessToken(SumsubTokenRequest $request)
    {
        try {
            $validated = $request->validated();
            $user_id = $request->user_id;
            $rejected = $request->rejected;
            $external_user_id = substr(md5($request->user_id), 0, 10);
            if($rejected){
                $cnt = Sumsub::where("id",$user_id)->count();
                if($cnt > 0){
                    $external_user_id = substr(md5($request->user_id."-".$cnt), 0, 10);
                }
            }
            $sumsub_cnt = Sumsub::where('user_id', $user_id)->count();
            $externalUserId = $external_user_id;
            $levelName = $this->level_name;
            $url = "/resources/accessTokens?userId=" . $externalUserId . "&levelName=" . $levelName;
            $request = new GuzzleHttp\Psr7\Request('POST', $this->sumsub_test_base_url.$url);

            $output = $this->sendHttpRequest($request, $url)->getBody();
            $output = json_decode($output);
            return self::sentResponse(200, $output, __('digimed_validation.success_response.access_token'));
        } catch (Exception | Throwable | QueryException $e) {
            return self::sentResponse(500, [], $e->getMessage());
        }
    }
    public function addSumsubDocument(AddSumsubDocumentRequest $request){
        try {

            $validated = $request->validated();
            DB::beginTransaction();
            $status = $this->getApplicantStatus($request->application_id);
            if(isset($status->IDENTITY)){
                $identity = $status->IDENTITY;
                $doc_type = $identity->idDocType;
                $doc_status = 0;
                $doc_id = 0;
                if(isset($identity->reviewResult->reviewAnswer)){
                    $sumsub_status = $identity->reviewResult->reviewAnswer;
                    if($sumsub_status == "GREEN"){
                        $doc_status = '1';
                    }
                    else if($sumsub_status == "RED") {
                        $doc_status = '2';
                    }
                    else {
                        $doc_status = '0';
                    }
                }
                else {
                    $doc_status = '0';
                }
                if(!empty($identity->imageIds)){
                    $doc_id = end($identity->imageIds);
                }
            }
            else{
                $doc_type = '0';
                $doc_status = '0';
                $doc_id = 0;
            }
            $list = Sumsub::where('application_id',$request->application_id)->where('external_user_id', $request->external_user_id)->get();
            $cnt = $list->count();
            if($cnt != 0){
                $sumsub =  Sumsub::where('application_id',$request->application_id)->where('external_user_id', $request->external_user_id)->first();
            }
            else {
                $sumsub = new Sumsub();
            }

            $sumsub->user_id = $request->user_id;
            $sumsub->application_id = $request->application_id;
            $sumsub->type = $doc_type;
            $sumsub->external_user_id = $request->external_user_id;
            $sumsub->file_name = $request->file_name;
            $sumsub->upload_id = $doc_id;
            $sumsub->status = $doc_status;
            $sumsub->created_by = $request->user_id;
            $sumsub->save();
            DB::commit();
            $response_array = ['user_id' =>  $request->user_id,'application_id'=>$request->application_id];
            return self::sentResponse(200, $response_array, __('digimed_validation.success_response.sumsub_document_added'));
        } catch (Exception | Throwable | QueryException $e) {
            DB::rollback();
            return self::sentResponse(500, [], $e->getMessage());
        }
    }
}