Skip to content

Quickstart (Laravel) ​

This walk-through takes a Laravel 12+ app from zero to a signed-in user and a first paid order, using the PHP SDK anikeen/id. Without Laravel, follow the same steps with the OAuth flow and the orders API.

1. Install the SDK ​

shell
composer require anikeen/id

2. Configure your credentials ​

Use the OAuth client of your app on staging while you develop:

ini
ANIKEEN_ID_MODE=staging
ANIKEEN_ID_KEY=your-client-id
ANIKEEN_ID_SECRET=your-client-secret
ANIKEEN_ID_CALLBACK_URL=http://localhost/auth/callback
ANIKEEN_ID_WEBHOOK_SECRET=whsec_...

and add them to config/services.php:

php
'anikeen' => [
    'mode' => env('ANIKEEN_ID_MODE'),
    'client_id' => env('ANIKEEN_ID_KEY'),
    'client_secret' => env('ANIKEEN_ID_SECRET'),
    'redirect' => env('ANIKEEN_ID_CALLBACK_URL'),
    'base_url' => env('ANIKEEN_ID_BASE_URL'),
    'webhook_secret' => env('ANIKEEN_ID_WEBHOOK_SECRET'),
],

3. Register the Socialite provider ​

In AppServiceProvider::boot():

php
use Illuminate\Support\Facades\Event;

Event::listen(function (\SocialiteProviders\Manager\SocialiteWasCalled $event) {
    $event->extendSocialite('anikeen', \Anikeen\Id\Socialite\Provider::class);
});

4. Prepare the user model ​

php
Schema::table('users', function (Blueprint $table) {
    $table->string('anikeen_id')->nullable()->unique();
    $table->text('anikeen_id_access_token')->nullable();
    $table->text('anikeen_id_refresh_token')->nullable();
});
php
use Anikeen\Id\Billable;

class User extends Authenticatable
{
    use Billable;

    protected $hidden = ['password', 'remember_token', 'anikeen_id_access_token', 'anikeen_id_refresh_token'];

    protected function casts(): array
    {
        return [
            'anikeen_id_access_token' => 'encrypted',
            'anikeen_id_refresh_token' => 'encrypted',
        ];
    }
}

5. Sign the user in ​

php
use Laravel\Socialite\Facades\Socialite;

Route::get('auth/redirect', fn () => Socialite::driver('anikeen')
    ->scopes(['user:read', 'addresses:read', 'orders', 'subscriptions'])
    ->redirect());

Route::get('auth/callback', function () {
    $account = Socialite::driver('anikeen')->user();

    $user = User::updateOrCreate(['anikeen_id' => $account->getId()], [
        'name' => $account->getName() ?: $account->getNickname(),
        'email' => $account->getEmail(),
        'anikeen_id_access_token' => $account->token,
        'anikeen_id_refresh_token' => $account->refreshToken,
    ]);

    Auth::login($user, remember: true);

    return redirect()->intended('/');
});

6. Sell something ​

Create the order as a draft and send the user to Anikeen ID to confirm and pay:

php
Route::post('checkout', function () {
    $user = auth()->user();

    $order = $user->orders()->create([
        'billing_address_id' => $user->getUserData()->billing_address_id,
        'items' => [
            ['type' => 'digital', 'name' => 'Sticker pack', 'unit' => 'piece', 'units' => 1, 'gross_price' => '9.99'],
        ],
    ]);

    return redirect()->away($order->confirmationUrl(route('checkout.return')));
});

Route::get('checkout/return', function (Request $request) {
    // never trust the query string: read the order through the API
    $order = auth()->user()->orders()->find($request->query('order'));

    return view('checkout.done', ['paid' => $order->status === 'completed']);
})->name('checkout.return');

7. Fulfil on the webhook ​

php
use Anikeen\Id\Exceptions\SignatureVerificationException;
use Anikeen\Id\Webhooks\EventType;
use Anikeen\Id\Webhooks\Webhook;

Route::post('webhooks/anikeen', function (Request $request) {
    try {
        $event = Webhook::constructEvent(
            $request->getContent(),
            $request->header('Anikeen-Signature'),
            config('services.anikeen.webhook_secret'),
        );
    } catch (SignatureVerificationException) {
        abort(400);
    }

    if ($event['type'] === EventType::ORDER_COMPLETED) {
        Shop::fulfil($event['data']['object']['id']);
    }

    return response()->noContent();
});

Exclude the route from CSRF protection in bootstrap/app.php:

php
->withMiddleware(function (Middleware $middleware) {
    $middleware->validateCsrfTokens(except: ['webhooks/*']);
})

Pay on staging with Stripe's test card 4242 4242 4242 4242.

Next steps ​

Anikeen ID developer documentation