alexeevdv/sumsub-client-bundle
composer require alexeevdv/sumsub-client-bundle
config/bundles.php:
return [
// ...
alexeevdv\Symfony\SumSub\SumSubClientBundle::class => ['all' => true],
];
.env:
SUMSUB_BASE_URI=https://api.sumsub.com
SUMSUB_APP_TOKEN=your_app_token
SUMSUB_SECRET_KEY=your_secret_key
config/packages/sumsub_client.yaml:
sumsub_client:
base_uri: '%env(SUMSUB_BASE_URI)%'
app_token: '%env(SUMSUB_APP_TOKEN)%'
secret_key: '%env(SUMSUB_SECRET_KEY)%'
Inject the SumSubClient service into a controller or service:
use alexeevdv\SumSub\Client\SumSubClientInterface;
class UserController extends AbstractController
{
public function verifyUser(SumSubClientInterface $sumsubClient, string $userId)
{
$verification = $sumsubClient->verifications()->create([
'token' => 'user_token_from_sumsub',
'flow_id' => 'flow_id_from_sumsub',
'metadata' => ['user_id' => $userId],
]);
return $this->json($verification);
}
}
User Verification Flow
verifications()->create() to initiate a verification.verifications()->get().config/routes.yaml):
sumsub_webhook:
path: /sumsub/webhook
controller: App\Controller\SumSubWebhookController::handle
Document Upload
documents()->upload() to send documents for verification:
$document = $sumsubClient->documents()->upload(
'path/to/document.pdf',
['type' => 'PASSPORT']
);
Webhook Handling
SumSubWebhookController to validate and process events:
public function handle(Request $request, SumSubClientInterface $sumsubClient)
{
$event = $sumsubClient->webhooks()->validateAndParse($request);
// Process $event->getType() and $event->getData()
}
SumSubClientInterface over instantiating the client directly.config/packages/override/sumsub_client.yaml for environments.sumsub_client.yaml for API request/response logging:
sumsub_client:
debug: '%kernel.debug%'
SumSubClientInterface mocks in tests:
$this->mockBuilder->getMockBuilder(SumSubClientInterface::class)
->disableOriginalConstructor()
->getMock();
Token Management
config/validator.yaml:
parameters:
env(SUMSUB_APP_TOKEN): 'not empty'
Webhook Validation
validateAndParse() can expose your app to spoofed requests.$event = $sumsubClient->webhooks()->validateAndParse($request);
if (!$event) {
throw new \RuntimeException('Invalid webhook signature');
}
Rate Limiting
use GuzzleHttp\Exception\RequestException;
use Symfony\Component\HttpKernel\Exception\HttpException;
try {
$response = $sumsubClient->verifications()->get($verificationId);
} catch (RequestException $e) {
if ($e->getCode() === 429) {
sleep(2); // Retry after delay
return $this->getVerification($verificationId);
}
throw new HttpException(500, 'SumSub API error');
}
Deprecated Methods
alexeevdv/sumsub-client package is lightly maintained (last release 2022).debug: true in sumsub_client.yaml to log API requests/responses.dump($event->getType(), $event->getData());
SumSubClientInterface mocks to test logic without hitting the API:
$mock = $this->createMock(SumSubClientInterface::class);
$mock->method('verifications')->willReturnSelf();
$mock->expects($this->once())
->method('create')
->with(['token' => 'test_token'])
->willReturn(['status' => 'pending']);
Custom Clients Extend the bundle’s client to add domain-specific methods:
namespace App\Service;
use alexeevdv\SumSub\Client\SumSubClientInterface;
class CustomSumSubClient extends SumSubClientInterface
{
public function verifyUserWithMetadata(string $userId, array $metadata)
{
return $this->verifications()->create([
'token' => 'user_token',
'metadata' => array_merge(['user_id' => $userId], $metadata),
]);
}
}
Register as a service in config/services.yaml:
services:
App\Service\CustomSumSubClient:
arguments:
$baseUri: '%sumsub_client.base_uri%'
$appToken: '%sumsub_client.app_token%'
$secretKey: '%sumsub_client.secret_key%'
Event Listeners Subscribe to SumSub events via Symfony’s event dispatcher:
namespace App\EventListener;
use alexeevdv\SumSub\Client\Event\WebhookEvent;
use Symfony\Component\HttpKernel\Event\ViewEvent;
class SumSubWebhookListener
{
public function onWebhook(ViewEvent $event, SumSubClientInterface $sumsubClient)
{
if ($event->getRequest()->getPathInfo() === '/sumsub/webhook') {
$event = $sumsubClient->webhooks()->validateAndParse($event->getRequest());
// Dispatch custom events or trigger logic
}
}
}
Register in config/services.yaml:
services:
App\EventListener\SumSubWebhookListener:
tags:
- { name: kernel.event_listener, event: kernel.view, method: onWebhook }
Command-Line Tools Create custom commands for bulk operations:
namespace App\Command;
use alexeevdv\SumSub\Client\SumSubClientInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class SumSubVerifyUsersCommand extends Command
{
protected static $defaultName = 'app:sumsub:verify-users';
public function __construct(private SumSubClientInterface $sumsubClient)
{
parent::__construct();
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$users = $this->fetchUsersFromDatabase();
foreach ($users as $user) {
$this->sumsubClient->verifications()->create([
'token' => $user->getSumsubToken(),
'metadata' => ['user_id' => $user->getId()],
]);
$output->writeln("Verified user: {$user->getId()}");
}
return Command::SUCCESS;
}
}
How can I help you explore Laravel packages today?