dionyyy / maya
Simple PHP SDK for Maya Mini App integration (Profile, Payments, Cash-in)
v1.0.0
2026-07-31 07:54 UTC
Requires
- php: ^8.1
- guzzlehttp/guzzle: ^7.0 || ^8.0
- web-token/jwt-library: ^3.4
Requires (Dev)
- phpunit/phpunit: ^10.0 || ^11.0
README
Simple PHP SDK for Maya Mini App integration — profile sharing, payments, and cash-in.
Requirements
- PHP 8.1+
- Guzzle 7+ (installed automatically)
Installation
composer require dionyyy/maya
Setup
use Dionyyy\Maya\Environment; use Dionyyy\Maya\Maya; use Dionyyy\Maya\MayaConfig; $config = new MayaConfig( environment: Environment::Sandbox, // or Environment::Production clientId: 'your-client-id', clientSecret: 'your-client-secret', // For Cash-in (optional) cashInSecretKey: 'sk-your-secret-key', // For Profile decryption (optional) jwePrivateKey: ['kty' => 'RSA', 'n' => '...', 'e' => '...', 'd' => '...'], jwsSecretKey: ['kty' => 'oct', 'k' => '...'], ); $maya = new Maya($config);
Get Customer Profile (Decrypted)
$profile = $maya->profile()->get($customerAccessToken); echo $profile->id; echo $profile->kycStatus; // "KYC0" or "KYC1" echo $profile->firstName(); // "Juan" echo $profile->lastName(); // "Dela Cruz" echo $profile->phone(); // "09171234567" echo $profile->email(); // "juan@example.com" // Raw data is also available $profile->name; // ['firstName' => '...', 'lastName' => '...', ...] $profile->contact; // [['type' => 'MSISDN', 'value' => '...'], ...] $profile->address; // [['type' => 'PRESENT', 'line1' => '...'], ...] $profile->birthDetails; // ['birthDate' => '...', 'city' => '...', ...] $profile->workDetails; // ['sourceOfIncome' => '...', ...]
Payments
use Dionyyy\Maya\DTO\Money; // Simple: create and execute in one call $result = $maya->payments()->pay($customerAccessToken, 'your-p2m-id', Money::php(150.00)); echo "Payment ID: {$result->id}"; echo "Fee: {$result->fee->value}"; // Or step by step (if you want to inspect the fee first) $created = $maya->payments()->create($customerAccessToken, 'your-p2m-id', Money::php(150.00)); echo "Fee will be: {$created->fee->value}"; $executed = $maya->payments()->execute($customerAccessToken, $created->id);
Cash-in (Send Money to Customer)
use Dionyyy\Maya\DTO\Money; use Dionyyy\Maya\Exception\TransferException; // Check your balance $balance = $maya->cashIn()->getBalance(); echo "Balance: {$balance->totalBalance->value}"; // Send money $transfer = $maya->cashIn()->initiate(Money::php(500.00), $customerAccessToken, 'Reward'); echo "Transfer ID: {$transfer->transferId}"; // status: CREATED // Execute the transfer try { $result = $maya->cashIn()->execute($transfer->transferId); echo "Done! Status: {$result->status}"; // APPROVED } catch (TransferException $e) { if ($e->isAmbiguous()) { // Timeout/server error — check what actually happened $status = $maya->cashIn()->retrieve($e->getTransferId()); echo "Actual status: {$status->status}"; } else { echo "Transfer failed: {$e->getMessage()}"; } }
Refresh Customer Token
use Dionyyy\Maya\Exception\AuthException; try { $newTokens = $maya->tokens()->refresh($customerRefreshToken); // Save the new tokens (old ones are now invalid) $newTokens->accessToken; $newTokens->refreshToken; $newTokens->expiresIn; } catch (AuthException $e) { // Refresh token expired — customer needs to re-authenticate }
Error Handling
use Dionyyy\Maya\MayaException; use Dionyyy\Maya\Exception\AuthException; use Dionyyy\Maya\Exception\ApiException; use Dionyyy\Maya\Exception\PaymentException; use Dionyyy\Maya\Exception\TransferException; try { $profile = $maya->profile()->get($token); } catch (AuthException $e) { // Token expired or invalid credentials } catch (ApiException $e) { // Maya API returned an error echo $e->getHttpStatusCode(); // 400, 404, 500, etc. echo $e->getErrorCode(); // Maya's error code echo $e->getResponseBody(); // Raw response for debugging } catch (MayaException $e) { // Catch-all for any SDK error }
Exception Hierarchy
MayaException (base — catch this to handle everything)
├── AuthException — authentication/token failures
├── ApiException — non-2xx API responses
├── PaymentException — payment declined or already processed
└── TransferException — transfer failed, declined, or ambiguous
Laravel Integration
Add to your .env:
MAYA_ENVIRONMENT=sandbox MAYA_CLIENT_ID=your-client-id MAYA_CLIENT_SECRET=your-client-secret MAYA_CASHIN_SECRET_KEY=sk-your-key MAYA_JWE_PRIVATE_KEY={"kty":"RSA","n":"...","e":"...","d":"..."} MAYA_JWS_SECRET_KEY={"kty":"oct","k":"..."}
Register in AppServiceProvider.php:
use Dionyyy\Maya\Environment; use Dionyyy\Maya\Maya; use Dionyyy\Maya\MayaConfig; public function register(): void { $this->app->singleton(Maya::class, function () { return new Maya(new MayaConfig( environment: config('services.maya.environment') === 'production' ? Environment::Production : Environment::Sandbox, clientId: config('services.maya.client_id'), clientSecret: config('services.maya.client_secret'), cashInSecretKey: config('services.maya.cashin_secret_key'), jwePrivateKey: json_decode(config('services.maya.jwe_private_key', '{}'), true), jwsSecretKey: json_decode(config('services.maya.jws_secret_key', '{}'), true), )); }); }
Add to config/services.php:
'maya' => [ 'environment' => env('MAYA_ENVIRONMENT', 'sandbox'), 'client_id' => env('MAYA_CLIENT_ID'), 'client_secret' => env('MAYA_CLIENT_SECRET'), 'cashin_secret_key' => env('MAYA_CASHIN_SECRET_KEY'), 'jwe_private_key' => env('MAYA_JWE_PRIVATE_KEY'), 'jws_secret_key' => env('MAYA_JWS_SECRET_KEY'), ],
Then use it anywhere:
use Dionyyy\Maya\Maya; class ProfileController extends Controller { public function show(Request $request, Maya $maya) { $profile = $maya->profile()->get($request->input('access_token')); return response()->json([ 'name' => $profile->firstName() . ' ' . $profile->lastName(), 'phone' => $profile->phone(), 'email' => $profile->email(), 'kyc' => $profile->kycStatus, ]); } }
Testing
composer test
License
MIT