andrepayone/payone-sdk-stream-client
PSR-18 stream-based HTTP client for the PAYONE Payment Integration SDK. Lightweight implementation to send requests to PAYONE APIs using PHP streams, suitable as a drop-in client for the php-payone-sdk.
Installation
composer require andrepayone/payone-sdk-stream-client
Ensure php-payone-sdk is also installed (this package extends it).
First Use Case: Basic Payment Request
use Andrepayone\PayoneSdk\StreamClient;
use Psr\Http\Message\RequestFactoryInterface;
use Psr\Http\Client\ClientInterface;
// Initialize with HTTP client and request factory (e.g., Guzzle)
$client = new StreamClient(
new \GuzzleHttp\Client(),
new \GuzzleHttp\Psr7\RequestFactory(),
new \GuzzleHttp\Psr7\UriFactory(),
new \GuzzleHttp\Psr7\StreamFactory()
);
// Configure PAYONE SDK (see php-payone-sdk docs)
$payone = new \Cakasim\PayoneSdk\Payone($client, [
'username' => 'your_username',
'password' => 'your_password',
'endpoint' => 'https://api.payone.com',
]);
// Execute a payment request
$response = $payone->payment->create([
'amount' => 1000, // 10.00 EUR
'currency' => 'EUR',
'transaction_id' => 'txn_123',
]);
Key Files to Review
StreamClient.php: Core implementation.StreamResponse.php: Response handling.README.md: Usage examples.PSR-18 Integration
$request = $client->createRequest('POST', '/api/v1/payment');
$request = $request->withBody(
$streamFactory->createStream(json_encode($paymentData))
);
$response = $client->sendRequest($request);
StreamFactory to handle file uploads (e.g., 3D-Secure data) without memory overload:
$stream = fopen('large_file.pdf', 'r');
$request = $request->withBody($streamFactory->createStreamFromResource($stream));
Error Handling
PayoneException:
try {
$response = $payone->payment->create($data);
} catch (\Cakasim\PayoneSdk\Exception\PayoneException $e) {
\Log::error('PAYONE Error:', ['code' => $e->getCode(), 'message' => $e->getMessage()]);
throw new \RuntimeException('Payment failed', 0, $e);
}
Configuration
$client = new StreamClient($httpClient, $requestFactory, $uriFactory, $streamFactory, [
'endpoint' => 'https://test.payone.com', // Sandbox
]);
$request = $request->withHeader('X-Custom-Header', 'value');
Testing
Psr\Http\Message\StreamInterface mocks (e.g., GuzzleHttp\Psr7\Stream) for unit tests:
$mockStream = new \GuzzleHttp\Psr7\Stream(fopen('data://text/plain;base64,...', 'r'));
$request = $request->withBody($mockStream);
Stream Resource Management
$stream = fopen('file.pdf', 'r');
try {
$request = $request->withBody($streamFactory->createStreamFromResource($stream));
$response = $client->sendRequest($request);
} finally {
fclose($stream);
}
PSR-18 Compliance
// Wrong: $request->setHeader(...); // Mutates!
// Right: $request = $request->withHeader(...);
Endpoint Configuration
$payone->setEndpoint('https://test.payone.com'); // Critical for sandbox testing!
Error Codes
400 (Bad Request) and 402 (Payment Failed) separately:
if ($e->getCode() === 402) {
// Retry or notify merchant
}
Logging
\Log::debug('PAYONE Request', [
'method' => $request->getMethod(),
'uri' => (string) $request->getUri(),
'body' => $request->getBody()->getContents(),
]);
Retry Logic
503 Service Unavailable):
use Symfony\Component\Retry\Retry;
$retry = new Retry(3, 100); // 3 retries, 100ms delay
$response = $retry->retry(fn() => $client->sendRequest($request));
Performance
ClientInterface (e.g., Guzzle) across requests to leverage HTTP/2 and connection reuse:
$httpClient = new \GuzzleHttp\Client(['http_version' => '2.0']);
$streamClient = new StreamClient($httpClient, ...);
Extending Functionality
$httpClient = new \GuzzleHttp\Client([
'middleware' => [
new \GuzzleHttp\Middleware(),
new class implements \GuzzleHttp\Promise\PromiseInterface {
// Custom logic
},
],
]);
Debugging
$httpClient = new \GuzzleHttp\Client([
'handler' => \GuzzleHttp\HandlerStack::create(
\GuzzleHttp\Middleware::tap(function ($request, $options) {
\Log::debug('Request:', ['request' => $request]);
})
),
]);
How can I help you explore Laravel packages today?