SDK-SPEC-PHP — PHP SDK Specification¶
Status: Draft
Owner: Platform Engineering
Package: simpaisa/sdk
Runtime: PHP 8.1+
Last Updated: 2026-04-03
1. Overview¶
Official PHP SDK for the Simpaisa Payment Gateway. Provides typed access to Pay-Ins, Pay-Outs, Remittances, and Cards across PK, BD, NP, and IQ corridors. Handles 270M+ annual transactions at $1B+ volume. Published to Packagist as simpaisa/sdk.
2. Composer Configuration¶
{
"name": "simpaisa/sdk",
"require": {
"php": "^8.1",
"guzzlehttp/guzzle": "^7.0",
"psr/http-client": "^1.0"
}
}
3. Namespace Structure¶
simpaisa/sdk/
├── src/
│ ├── SimPaisaClient.php # Main client entry point
│ ├── Config.php # Configuration value object
│ ├── PayIn/
│ │ ├── PayInClient.php # initiate, verify, status, list
│ │ ├── PayInRequest.php
│ │ └── PayInResponse.php
│ ├── PayOut/
│ │ ├── PayOutClient.php # initiate, status, batch, cancel
│ │ ├── PayOutRequest.php
│ │ └── PayOutResponse.php
│ ├── Remittance/
│ │ ├── RemittanceClient.php # quote, initiate, status, beneficiaries
│ │ ├── RemittanceRequest.php
│ │ └── RemittanceResponse.php
│ ├── Cards/
│ │ ├── CardsClient.php # pay, capture, void, refund, tokenise
│ │ ├── CardPaymentRequest.php
│ │ └── CardPaymentResponse.php
│ ├── Webhook/
│ │ ├── WebhookVerifier.php # HMAC-SHA256 verification
│ │ └── WebhookEvent.php
│ ├── Auth/
│ │ ├── RSAAuthProvider.php # RSA-SHA256 request signing
│ │ └── AuthProviderInterface.php
│ ├── Exception/
│ │ ├── SimPaisaException.php # Base exception
│ │ ├── AuthenticationException.php
│ │ ├── ValidationException.php
│ │ ├── RateLimitException.php
│ │ └── WebhookVerificationException.php
│ ├── Retry/
│ │ └── RetryPolicy.php # Exponential backoff
│ ├── Idempotency/
│ │ └── IdempotencyKeyGenerator.php # UUID v7
│ └── Generated/
│ └── Models/ # OpenAPI-generated models
├── tests/
├── composer.json
└── phpstan.neon
Namespace root: Simpaisa\
4. Authentication — RSAAuthProvider¶
- Load merchant private key from PEM file via
openssl_pkey_get_private() - Sign request body with RSA-SHA256 via
openssl_sign() - Attach
X-Simpaisa-SignatureandX-Simpaisa-Merchant-Idheaders - Requires
ext-openssl - Support key rotation via array of key paths
$auth = new RSAAuthProvider(
merchantId: 'MCH-001',
privateKeyPath: './keys/merchant.pem',
);
5. WebhookVerifier¶
- Verify
X-Simpaisa-Webhook-Signatureusing HMAC-SHA256 viahash_hmac() verify(string $payload, string $signature): bool- Timing-safe comparison via
hash_equals() - Replay protection: validate timestamp header within tolerance (default 300s)
- Throw
WebhookVerificationExceptionon failure
6. RetryPolicy¶
- Exponential backoff with jitter (base 200ms, max 30s)
- Configurable max retries (default 3)
- Retry on: 429, 502, 503, 504, connection errors
- Never retry: 400, 401, 403, 404, 409, 422
- Respect
Retry-Afterheader onRetrycallback for observability
7. Error Handling¶
SimPaisaException (base, extends \RuntimeException)
├── AuthenticationException — 401/403 responses
├── ValidationException — 400/422 with field-level details
├── RateLimitException — 429 with retryAfter
├── TimeoutException — request/connection timeout
├── IdempotencyException — conflicting idempotency key
├── NetworkException — connection/DNS failures
└── WebhookVerificationException — signature mismatch
All exceptions include: getErrorCode(), getStatusCode(), getRequestId(), isRetryable().
8. PSR-18 Compatibility¶
- SDK SHALL implement PSR-18 (HTTP Client) interface
- Default: Guzzle 7.x as transport
- Merchants MAY inject any PSR-18 compatible client
- PSR-7 (HTTP Message) for request/response objects
- PSR-17 (HTTP Factories) for message creation
$client = new SimPaisaClient(
config: $config,
httpClient: $customPsr18Client,
);
9. Laravel Service Provider¶
SimPaisaServiceProviderauto-discovered viaextra.laravel.providers- Publishes config:
php artisan vendor:publish --tag=simpaisa-config - Config file:
config/simpaisa.php - Facade:
Simpaisa::payIn()->initiate(...) - Binds
SimPaisaClientas singleton in container - Reads credentials from
.env:SIMPAISA_MERCHANT_ID,SIMPAISA_PRIVATE_KEY_PATH,SIMPAISA_ENVIRONMENT
// config/simpaisa.php
return [
'environment' => env('SIMPAISA_ENVIRONMENT', 'sandbox'),
'merchant_id' => env('SIMPAISA_MERCHANT_ID'),
'private_key_path' => env('SIMPAISA_PRIVATE_KEY_PATH'),
'timeout' => 30,
'retries' => 3,
];
10. Configuration¶
$client = new SimPaisaClient(
config: new Config(
environment: 'sandbox', // 'sandbox' | 'production'
merchantId: 'MCH-001',
privateKeyPath: './keys/merchant.pem',
timeout: 30, // seconds, default 30
retries: 3, // default 3
),
);
11. Example Usage¶
use Simpaisa\SimPaisaClient;
use Simpaisa\Config;
$client = new SimPaisaClient(
config: new Config(
environment: 'sandbox',
merchantId: 'MCH-001',
privateKeyPath: './keys/merchant.pem',
),
);
// Pay-In
$payIn = $client->payIn()->initiate(
amount: 5000,
currency: 'PKR',
channel: 'EASYPAISA',
customerMsisdn: '03001234567',
callbackUrl: 'https://merchant.com/webhook',
);
// Webhook
$verifier = new \Simpaisa\Webhook\WebhookVerifier(secret: 'whsec_...');
$valid = $verifier->verify($rawBody, $signatureHeader);
12. Build and Publish¶
- Test runner: PHPUnit 10+
- Static analysis: PHPStan level 9
- Linting: PHP-CS-Fixer (PSR-12)
- CI: Bitbucket Pipelines — lint → analyse → test → publish
- Publish: Packagist (auto-updated via webhook)
- Versioning: Semantic versioning
- PHP compatibility: Tested on 8.1, 8.2, 8.3, 8.4
13. Testing Requirements¶
- Unit tests for every public method (>90% coverage)
- Integration tests against sandbox environment
- Contract tests validating against OpenAPI spec
- Webhook verification round-trip tests
- Retry behaviour tests with mock handlers
- Laravel service provider integration tests
14. Documentation¶
- PHPDoc on all public classes and methods
- README with quickstart, Laravel integration, and corridor-specific examples
- CHANGELOG following Keep a Changelog format