nexgenspin / coordinator
PHP client for the NexGenSpin Coordinator API with Ed25519 request signing
Requires
- php: ^7.4 || ^8.0
- ext-sodium: *
This package is not auto-updated.
Last update: 2026-05-15 18:18:37 UTC
README
Minimal PHP client for the NexGenSpin Coordinator API with Ed25519 request signing via ext-sodium.
Overview
This package demonstrates how to:
- Sign Coordinator requests as
timestamp + exact JSON body - Send the required authentication headers
- Query games, currencies, and languages
- Create demo and real-money sessions
The client itself accepts a single private key format:
- PKCS#8 DER encoded private key represented as hex
For convenience, the example script can read a PEM file and convert it into PKCS#8 DER hex before constructing the client.
Requirements
- PHP 7.4+
ext-sodium
Compatibility has been verified with a live request in Docker using php:7.4-cli.
Repository Layout
src/NexGenSpinCoordinatorClient.php— Coordinator clientsrc/KeyLoader.php— PEM to PKCS#8 DER hex helperexamples/smoke_test.php— runnable staging smoke testexamples/compose.yaml— local Docker/OrbStack smoke test
Installation
Install the package with Composer:
composer require nexgenspin/coordinator
Then autoload it through Composer:
require __DIR__ . '/vendor/autoload.php';
Quick Start
The bundled example uses:
- Staging environment
- A hardcoded operator caller ID in
examples/smoke_test.php - A local PEM file at
./operator.pem
Run it with:
docker compose -f examples/compose.yaml run --rm php
Before running the example, place your own private key at ./operator.pem or update the path in examples/smoke_test.php.
Client Construction
From PKCS#8 DER hex
require __DIR__ . '/vendor/autoload.php'; use NexGenSpin\Coordinator\NexGenSpinCoordinatorClient; $client = NexGenSpinCoordinatorClient::staging( '019d4f70-2dfa-781a-9de6-39503e63c0f4', '302e020100300506032b65700422042033a9b1b71e0deb2e8354098106c9d349bac6f46ae486303b4cf974a94fc7a2fb' );
From PEM file
require __DIR__ . '/vendor/autoload.php'; use NexGenSpin\Coordinator\KeyLoader; use NexGenSpin\Coordinator\NexGenSpinCoordinatorClient; $pkcs8DerHex = KeyLoader::pkcs8DerHexFromPemFile(__DIR__ . '/operator.pem'); $client = NexGenSpinCoordinatorClient::staging( '019d4f70-2dfa-781a-9de6-39503e63c0f4', $pkcs8DerHex );
Example
require __DIR__ . '/vendor/autoload.php'; use NexGenSpin\Coordinator\KeyLoader; use NexGenSpin\Coordinator\NexGenSpinCoordinatorClient; $pemPath = __DIR__ . '/operator.pem'; $pkcs8DerHex = KeyLoader::pkcs8DerHexFromPemFile($pemPath); $client = NexGenSpinCoordinatorClient::staging( '019d4f70-2dfa-781a-9de6-39503e63c0f4', $pkcs8DerHex ); $games = $client->games(); print_r($games['response']['json']);
Available Methods
games()
Fetches the list of games available to the operator.
$games = $client->games(); print_r($games['response']['json']);
currencies()
Fetches the list of supported currencies.
$currencies = $client->currencies(); print_r($currencies['response']['json']);
languages()
Fetches the list of supported languages.
$languages = $client->languages(); print_r($languages['response']['json']);
createSession(array $input)
Creates a game session.
Demo session
For a demo session, omit the operator session and customer identifiers.
$demoSession = $client->createSession([ // Game identifier from the games query 'game' => ['id' => '019d2822-20ed-7212-95a9-def642d50ddf'], // Currency for all transactions within this session (immutable) 'currency' => ['code' => 'USD'], // Preferred language (BCP 47) 'languageTag' => 'en', // IP address of the customer — supports both IPv4 and IPv6 formats 'ipAddress' => '203.0.113.42', ]); print_r($demoSession['response']['json']);
Real-money session
$session = $client->createSession([ // Session ID on the Operator's platform 'id' => 'SESSION_ID_ON_OPERATOR_SIDE', // Game identifier from the games query 'game' => ['id' => '019d2822-20ed-7212-95a9-def642d50ddf'], // Customer on the Operator's platform 'customer' => [ // Customer ID on the Operator's platform 'id' => 'CUSTOMER_ID_ON_OPERATOR_SIDE', // Name is optional — displayed in the game interface, auto-generated if omitted 'name' => 'John', // ISO 3166-1 alpha-2 country code 'countryCode' => 'US', ], // Currency for all transactions within this session (immutable) 'currency' => ['code' => 'USD'], // Preferred language (BCP 47) 'languageTag' => 'en', // IP address of the customer — supports both IPv4 and IPv6 formats 'ipAddress' => '203.0.113.42', ]); print_r($session['response']['json']);
Response Shape
Each client method returns an array with:
request.timestamprequest.bodyrequest.signatureresponse.headersresponse.body_rawresponse.json
The response structure is intentionally verbose to support debugging and integration testing.
Integration Notes
- Coordinator signatures are computed as
timestamp + exact JSON body - There is no delimiter between the timestamp and the body
- The body you sign must be byte-for-byte identical to the body you send
- GraphQL requests with no variables must send
{}rather than[]