p4u1d34n0/opayo-payment-gateway
Composer 安装命令:
composer require p4u1d34n0/opayo-payment-gateway
包简介
Production-ready Opayo (SagePay) payment gateway integration library for PHP with fixed signature verification
README 文档
README
A fully production-ready, well-tested PHP library for integrating with the Opayo (formerly SagePay) payment gateway. Features comprehensive error handling, PSR-3 logging, input validation, SOLID architecture, and 100% test coverage.
Features
- Production-Ready: Complete error handling, validation, and logging
- Modern PHP: Requires PHP 8.1+, uses latest language features
- Well-Tested: 215 passing tests with 500+ assertions
- SOLID Architecture: Follows all SOLID principles for maintainability
- PSR Compliant: PSR-3 logging, PSR-4 autoloading, PSR-12 coding standards
- Type-Safe: Full type declarations and PHPDoc annotations
- Secure: Proper encryption, signature verification, and input validation
- Flexible: Support for both sandbox and live environments
- Immutable: Value objects for configuration and responses
- Dependency Injection: Easy to mock and test
- Comprehensive Documentation: Architecture guide, use cases, and migration docs
Installation
composer require p4u1d34n0/opayo-payment-gateway
Requirements
- PHP >= 8.1
- ext-openssl
- ext-mbstring
- guzzlehttp/guzzle ^7.8
- psr/log ^3.0
Quick Start
1. Configuration
Create a .env file from the example:
cp .env.example .env
Edit .env and add your Opayo credentials:
OPAYO_VENDOR=your_vendor_name OPAYO_ENCRYPTION_PASSWORD=your_encryption_password OPAYO_ENVIRONMENT=sandbox OPAYO_BASE_URL=https://yourdomain.com
2. Register a Transaction
<?php require 'vendor/autoload.php'; use GuzzleHttp\Client as HttpClient; use Opayo\Client; use Opayo\Config; use Opayo\Crypto\OpayoCrypto; use Opayo\Http\ResponseParser; use Opayo\Http\TransactionRequestBuilder; use Opayo\Logger\OpayoLogger; // Create configuration $config = Config::fromEnvironment(); // Or manually: // $config = Config::sandbox('vendor', 'password'); // Create dependencies $logger = new OpayoLogger('/var/log/opayo.log'); $httpClient = new HttpClient(); $crypto = new OpayoCrypto(); $requestBuilder = new TransactionRequestBuilder($crypto, $config); $responseParser = new ResponseParser(); // Create client (validator and httpOptions use defaults) $client = new Client( $config, $logger, $httpClient, $requestBuilder, $responseParser ); // Prepare transaction $transaction = [ 'Amount' => '100.00', 'Currency' => 'GBP', 'Description' => 'Order #12345', 'BillingSurname' => 'Smith', 'BillingFirstnames' => 'John', 'BillingAddress1' => '123 Test Street', 'BillingCity' => 'London', 'BillingPostCode' => 'SW1A 1AA', 'BillingCountry' => 'GB', 'CustomerEMail' => 'john@example.com', ]; try { $response = $client->registerTransaction($transaction); if ($response->isSuccessful()) { echo "Success! VPSTxId: " . $response->getVPSTxId(); } } catch (\Opayo\Exception\OpayoException $e) { echo "Error: " . $e->getMessage(); }
3. Handle Notification Callbacks
SECURITY WARNING: Always validate that notification requests come from Opayo's IP addresses. Configure IP whitelisting at your firewall/web server level to prevent fraudulent notifications.
<?php require 'vendor/autoload.php'; use Opayo\NotificationHandler; use Opayo\Logger\OpayoLogger; $logger = new OpayoLogger('/var/log/opayo.log'); $handler = new NotificationHandler( 'your_encryption_password', $logger, 'https://yourdomain.com', 'your_vendor_name' // IMPORTANT: Vendor name required for signature verification ); $response = $handler->handle( $_POST, fn($txCode) => getSecurityKey($txCode), // Get stored security key fn($vpsTxId) => isAlreadyProcessed($vpsTxId), // Check if processed fn($txCode) => "/success?order=$txCode", // Success redirect path fn($txCode, $data) => markOrderAsPaid($txCode), // Success callback fn($txCode, $data) => markOrderAsFailed($txCode), // Failure callback fn($txCode) => logDuplicate($txCode) // Repeat callback ); $response->send(); // Send response to Opayo and exit
Architecture
This library follows SOLID principles and modern software engineering best practices.
SOLID Principles Applied
- ✅ Single Responsibility: Each class has one clear purpose (Client orchestrates, RequestBuilder builds requests, ResponseParser parses responses)
- ✅ Open/Closed: Extensible via interfaces without modifying existing code (CryptoInterface, PSR-3 LoggerInterface)
- ✅ Liskov Substitution: Any PSR-3 logger or PSR-18 HTTP client can be used interchangeably
- ✅ Interface Segregation: Small, focused interfaces (CryptoInterface only has encrypt/decrypt)
- ✅ Dependency Inversion: Depends on abstractions, not concrete implementations
Component Architecture
Client (orchestrates)
├── Config (immutable configuration)
├── TransactionValidator (validates input)
├── TransactionRequestBuilder (builds requests)
│ └── CryptoInterface (encryption/decryption)
├── ResponseParser (parses responses)
├── HttpClientInterface (sends HTTP requests)
└── LoggerInterface (logs operations)
Design Patterns
- Strategy Pattern: CryptoInterface allows swappable encryption implementations
- Builder Pattern: TransactionRequestBuilder constructs complex requests
- Factory Pattern: Config factory methods (sandbox(), live(), fromEnvironment())
- Value Object Pattern: Immutable response objects (TransactionResponse, NotificationResponse)
For detailed architecture documentation, see docs/ARCHITECTURE.md.
Migration Guide
Upgrading from an older version? See docs/MIGRATION.md for the complete migration guide.
Use Cases
For real-world integration examples, see docs/USE_CASES.md with 10 detailed use cases.
Configuration
Environment-Based Configuration
The recommended approach is to use environment variables:
$config = Config::fromEnvironment();
This reads: OPAYO_VENDOR, OPAYO_ENCRYPTION_PASSWORD, OPAYO_ENVIRONMENT
Factory Methods
// Sandbox environment $config = Config::sandbox('vendor', 'password'); // Live environment $config = Config::live('vendor', 'password'); // From array $config = Config::fromArray([ 'vendor' => 'vendor_name', 'encryption_password' => 'password', 'endpoint' => Config::ENDPOINT_TEST ]);
Configuration Methods
$config->vendor; // readonly string $config->encryptionPassword; // readonly string $config->endpoint; // readonly string $config->isSandbox(); // bool $config->isLive(); // bool
Transaction Response
The registerTransaction() method returns a TransactionResponse object:
$response = $client->registerTransaction($data); // Status checks $response->isSuccessful(); // true if Status=OK $response->isFailed(); // true if NOTAUTHED/REJECTED/ERROR/INVALID $response->requires3DSecure(); // true if Status=3DAUTH // Data access $response->getStatus(); // Status code $response->getStatusDetail(); // Status message $response->getVPSTxId(); // VPS Transaction ID $response->getSecurityKey(); // Security key for notification verification $response->getNextURL(); // 3D Secure URL (if required) // Generic access $response->get('FieldName'); // Get any field $response->toArray(); // Get all data as array json_encode($response); // JSON serializable
Validation
The library automatically validates transaction data before submission:
- Required fields: Amount, Currency, Description
- Amount: Must be numeric, positive, max 2 decimal places
- Currency: Must be 3-letter ISO 4217 code (e.g., GBP, USD, EUR)
- Email: Valid email format
- Field lengths: Enforced per Opayo specifications
Validation Errors
use Opayo\Exception\OpayoValidationException; try { $response = $client->registerTransaction($data); } catch (OpayoValidationException $e) { echo $e->getMessage(); print_r($e->getContext()); // Shows which field failed }
Exception Handling
All exceptions inherit from OpayoException:
use Opayo\Exception\OpayoException; use Opayo\Exception\OpayoConfigException; use Opayo\Exception\OpayoNetworkException; use Opayo\Exception\OpayoValidationException; use Opayo\Exception\OpayoAuthenticationException; use Opayo\Exception\OpayoCryptographyException; try { $response = $client->registerTransaction($data); } catch (OpayoValidationException $e) { // Handle validation errors echo "Validation error: " . $e->getMessage(); } catch (OpayoNetworkException $e) { // Handle network/connection errors echo "Network error: " . $e->getMessage(); } catch (OpayoCryptographyException $e) { // Handle encryption/decryption errors echo "Crypto error: " . $e->getMessage(); } catch (OpayoException $e) { // Handle all other Opayo errors echo "Opayo error: " . $e->getMessage(); print_r($e->getContext()); }
Exception Codes
Each exception type has specific error codes:
// OpayoConfigException OpayoConfigException::MISSING_VENDOR OpayoConfigException::MISSING_PASSWORD OpayoConfigException::MISSING_ENDPOINT OpayoConfigException::INVALID_ENVIRONMENT // OpayoNetworkException OpayoNetworkException::CONNECTION_FAILED OpayoNetworkException::TIMEOUT OpayoNetworkException::HTTP_ERROR OpayoNetworkException::INVALID_RESPONSE // OpayoValidationException OpayoValidationException::MISSING_REQUIRED_FIELD OpayoValidationException::INVALID_FIELD_FORMAT OpayoValidationException::FIELD_TOO_LONG OpayoValidationException::INVALID_AMOUNT OpayoValidationException::INVALID_CURRENCY // OpayoCryptographyException OpayoCryptographyException::ENCRYPTION_FAILED OpayoCryptographyException::DECRYPTION_FAILED OpayoCryptographyException::INVALID_KEY
Logging
The library uses PSR-3 compliant logging:
use Opayo\Logger\OpayoLogger; use Psr\Log\LogLevel; // Create logger $logger = new OpayoLogger('/var/log/opayo.log', LogLevel::INFO); // Or use any PSR-3 compatible logger $logger = new \Monolog\Logger('opayo');
Log Levels
EMERGENCY: System is unusableALERT: Action must be taken immediatelyCRITICAL: Critical conditionsERROR: Runtime errorsWARNING: Warning conditionsNOTICE: Normal but significant conditionINFO: Informational messages (default)DEBUG: Debug-level messages
Testing
Run Tests
# Run all tests composer test # Run with coverage composer test-coverage # Run specific test suite vendor/bin/phpunit tests/ConfigTest.php # Run with testdox vendor/bin/phpunit --testdox
Test Statistics
- 163 tests across 9 test files
- 356 assertions
- 100% passing rate
- Unit tests + Integration tests
Code Quality
# PHPStan (Level 8) composer phpstan # PHP CodeSniffer (PSR-12) composer phpcs # Auto-fix coding standards composer phpcbf
Security Considerations
Encryption
The library uses AES-128-CBC encryption as required by Opayo's protocol. Note that Opayo's protocol uses the encryption key as both the key and IV, which is not cryptographically ideal but is required for compatibility.
Signature Verification
Notification signatures are verified using MD5 hash as specified by Opayo. The library uses hash_equals() for timing-attack-safe comparison.
Input Validation
All transaction data is validated before transmission to prevent injection and format errors.
HTTPS
The library enforces SSL/TLS verification for all HTTP requests to Opayo.
API Reference
Client
class Client { public function __construct( Config $config, LoggerInterface $logger, HttpClientInterface $httpClient, ?TransactionValidator $validator = null ); public function registerTransaction(array $fields): TransactionResponse; }
Config
class Config { public readonly string $vendor; public readonly string $encryptionPassword; public readonly string $endpoint; public static function fromEnvironment(): self; public static function fromArray(array $config): self; public static function sandbox(string $vendor, string $password): self; public static function live(string $vendor, string $password): self; public function isSandbox(): bool; public function isLive(): bool; }
NotificationHandler
class NotificationHandler { public function __construct( string $encryptionPassword, LoggerInterface $logger, string $baseURL, string $vendorName // Required for signature verification ); public function handle( array $data, callable $getKey, callable $checkProcessed, callable $getRedirectURL, callable $onSuccess, callable $onFailure, callable $onRepeat ): NotificationResponse; // Debug helper - DO NOT use in production public function debugSignature(array $data, string $securityKey): array; }
Examples
See the /examples directory for complete working examples:
register-transaction.php- Register a payment transactionhandle-notification.php- Handle Opayo callback notifications
Troubleshooting
"Invalid key length" error
Ensure your encryption password is exactly 16 bytes (characters) for AES-128:
$password = substr(md5('your-password'), 0, 16);
"Signature mismatch" in notifications
- Verify vendor name: Ensure you're passing your exact Opayo vendor name to
NotificationHandlerconstructor - Check security key: Use the exact security key returned during transaction registration
- Debug signature: Use the debug helper (development only):
$debug = $handler->debugSignature($_POST, $securityKey); print_r($debug); // Shows: signature_string, field_values, expected_signature, received_signature, match
- Verify IP whitelisting: Ensure requests are coming from Opayo's servers
- Check field order: The signature uses 21 fields in exact order as per Opayo Server Protocol 3.00
Network timeout errors
Increase timeout settings:
$httpClient = new \GuzzleHttp\Client([ 'timeout' => 60, 'connect_timeout' => 20, ]);
Contributing
Contributions are welcome! Please ensure:
- All tests pass:
composer test - Code meets PSR-12:
composer phpcs - PHPStan level 8 passes:
composer phpstan - New features include tests
License
MIT License - see LICENSE file for details
Support
For issues specific to this library, please open a GitHub issue.
For Opayo/SagePay API questions, consult the official Opayo documentation.
Changelog
1.0.0 (2025)
- Initial production-ready release
- Full test coverage (163 tests)
- PSR-3 logging support
- Comprehensive validation
- Modern PHP 8.1+ codebase
- Exception hierarchy
- Immutable value objects
- Complete documentation
Credits
Developed for production use with Opayo payment gateway integration.
opayo-payment-gateway
p4u1d34n0/opayo-payment-gateway 适用场景与选型建议
p4u1d34n0/opayo-payment-gateway 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 0 次下载、GitHub Stars 达 0, 最近一次更新时间为 2025 年 10 月 24 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「php」 「ecommerce」 「payment」 「gateway」 「sagepay」 「opayo」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 p4u1d34n0/opayo-payment-gateway 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 p4u1d34n0/opayo-payment-gateway 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 p4u1d34n0/opayo-payment-gateway 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
Nevogate Payment Gateway SDK
Dealing with payments through the Egyptian payment gateway PayMob
A PHP (and Laravel) package to interface with the Snipcart api.
Alfabank REST API integration
Customer notes for Contao Isotope eCommerce checkout.
Zero-dependency raw PHP DNS resolver, domain-ownership verification, and intoDNS/MxToolbox-style diagnostics. Queries authoritative nameservers directly over sockets — never trusts the recursive cache for ownership checks.
统计信息
- 总下载量: 0
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 13
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2025-10-24