ws4934 / hyperf-paypal
Hyperf PayPal SDK component for processing payments through PayPal API. Compatible with Hyperf 3.1 framework with coroutine support.
v1.0.4
2025-06-03 14:10 UTC
Requires
- php: >=8.1
- ext-json: *
- hyperf/carbon: ^3.1
- hyperf/config: ~3.1.0
- hyperf/constants: ~3.1.0
- hyperf/guzzle: ~3.1.0
- hyperf/helper: ~3.1
- hyperf/redis: ~3.1.0
- psr/container: ^1.0|^2.0
- psr/http-message: ^1.0|^2.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.0
- hyperf/testing: ~3.1.0
- phpstan/phpstan: ^1.10
- phpunit/phpunit: ^10.0
README
本组件从 srmklive/paypal
Laravel 包移植而来,适配 Hyperf 框架的协程环境。
支持的 PayPal API
- ✅ 订单管理 (Orders)
- ✅ 支付授权/捕获 (Payment Authorizations/Captures)
- ✅ 退款管理 (Refunds)
- ✅ 订阅管理 (Subscriptions)
- ✅ 账单计划 (Billing Plans)
- ✅ 发票管理 (Invoices)
- ✅ 支付令牌 (Payment Method Tokens)
- ✅ Webhook 管理
- ✅ 争议处理 (Disputes)
- ✅ 身份验证 (Identity)
- ✅ 报告 (Reporting)
- ✅ 产品目录 (Catalog Products)
- ✅ 合作伙伴推荐 (Partner Referrals)
- ✅ 批量支付 (Payouts)
- ✅ 跟踪器 (Trackers)
环境要求
- PHP >= 8.1
- Hyperf >= 3.1
安装
使用 Composer 安装:
composer require ws4934/hyperf-paypal
在 Hyperf 框架中使用
发布配置文件:
php bin/hyperf.php vendor:publish ws4934/hyperf-paypal
配置
环境变量配置
在您的 .env
文件中添加以下配置:
# PayPal 配置 PAYPAL_MODE=sandbox PAYPAL_CURRENCY=USD PAYPAL_PAYMENT_ACTION=Sale # 沙盒环境配置 PAYPAL_SANDBOX_CLIENT_ID=your-sandbox-client-id PAYPAL_SANDBOX_CLIENT_SECRET=your-sandbox-client-secret # 生产环境配置 PAYPAL_LIVE_CLIENT_ID=your-live-client-id PAYPAL_LIVE_CLIENT_SECRET=your-live-client-secret # Webhook 配置 PAYPAL_NOTIFY_URL=https://your-domain.com/webhooks/paypal PAYPAL_RETURN_URL=https://your-domain.com/payment/success PAYPAL_CANCEL_URL=https://your-domain.com/payment/cancel # HTTP 配置 PAYPAL_VALIDATE_SSL=true PAYPAL_HTTP_TIMEOUT=30 PAYPAL_HTTP_CONNECT_TIMEOUT=10
基本使用
Token 缓存(推荐)
组件集成了 Redis 缓存来提高性能,避免频繁获取 PayPal 访问令牌。缓存功能是可选的,如果不配置Redis则自动禁用:
配置缓存
在 config/autoload/paypal.php
中配置:
return [ 'default' => [ // ... 其他配置 ... // Token缓存配置 'cache' => [ // Redis工厂类,如果为null则不使用缓存 'redis_factory' => \Hyperf\Redis\RedisFactory::class, // Redis连接池名称 'redis_pool' => 'default', // 缓存前缀 'prefix' => 'paypal:token', // Token过期安全缓冲时间(秒) 'safety_buffer' => 300, // 5分钟 ], ], ];
使用缓存
<?php use Ws4934\HyperfPayPal\Services\PayPalInterface; class PaymentService { public function __construct( private PayPalInterface $paypal ) {} public function processPayment() { $client = $this->paypal->getAuthenticatedClient(); $order = $client->createOrder([...]); // 查看缓存状态 if ($this->paypal->hasCachedToken()) { $cacheInfo = $this->paypal->getTokenCacheInfo(); echo "Token缓存剩余TTL: " . $cacheInfo['ttl'] . "秒\n"; } return $order; } public function refreshToken() { // 清除缓存并强制获取新token $this->paypal->clearTokenCache(); $response = $this->paypal->refreshAccessToken(); return $response; } }
缓存特性:
- ✅ 自动缓存 PayPal 访问令牌
- ✅ 支持多账户独立缓存(基于 client_id)
- ✅ 自动处理 token 过期(可配置安全缓冲时间)
- ✅ Redis 不配置或不可用时自动禁用缓存
- ✅ 支持自定义 Redis 连接池和工厂类
- ✅ 显著提高 API 调用性能
缓存配置选项:
redis_factory
: Redis工厂类名,设置为null
禁用缓存redis_pool
: Redis连接池名称,对应config/autoload/redis.php
配置prefix
: 缓存键前缀,用于区分不同应用safety_buffer
: 安全缓冲时间,提前多少秒认为token过期
在 Hyperf 控制器中使用
<?php declare(strict_types=1); namespace App\Controller; use Hyperf\HttpServer\Annotation\Controller; use Hyperf\HttpServer\Annotation\RequestMapping; use Ws4934\HyperfPayPal\Services\PayPalInterface; #[Controller] class PaymentController { public function __construct( private PayPalInterface $paypal ) {} #[RequestMapping(path: '/payment/create', methods: 'POST')] public function createPayment() { // 获取访问令牌并认证 $client = $this->paypal->getAuthenticatedClient(); // 创建订单 $order = $client->createOrder([ 'intent' => 'CAPTURE', 'purchase_units' => [ [ 'amount' => [ 'currency_code' => 'USD', 'value' => '100.00' ], 'description' => 'Test Payment' ] ], 'application_context' => [ 'return_url' => 'https://your-domain.com/payment/success', 'cancel_url' => 'https://your-domain.com/payment/cancel' ] ]); return $order; } #[RequestMapping(path: '/payment/capture/{orderId}', methods: 'POST')] public function capturePayment(string $orderId) { $client = $this->paypal->getAuthenticatedClient(); // 捕获支付 $result = $client->capturePaymentOrder($orderId, []); return $result; } }
订阅管理示例
<?php use Ws4934\HyperfPayPal\Services\PayPalInterface; class SubscriptionController { public function __construct( private PayPalInterface $paypal ) {} public function createSubscription() { $client = $this->paypal->getAuthenticatedClient(); // 创建产品 $product = $client->createProduct([ 'name' => 'Monthly Subscription', 'type' => 'SERVICE', 'category' => 'SOFTWARE' ]); // 创建计划 $plan = $client->createPlan([ 'product_id' => $product['id'], 'name' => 'Monthly Plan', 'status' => 'ACTIVE', 'billing_cycles' => [ [ 'frequency' => [ 'interval_unit' => 'MONTH', 'interval_count' => 1 ], 'tenure_type' => 'REGULAR', 'sequence' => 1, 'total_cycles' => 0, 'pricing_scheme' => [ 'fixed_price' => [ 'value' => '29.99', 'currency_code' => 'USD' ] ] ] ], 'payment_preferences' => [ 'auto_bill_outstanding' => true, 'setup_fee_failure_action' => 'CONTINUE', 'payment_failure_threshold' => 3 ] ]); // 创建订阅 $subscription = $client->createSubscription([ 'plan_id' => $plan['id'], 'subscriber' => [ 'email_address' => 'user@example.com', 'name' => [ 'given_name' => 'John', 'surname' => 'Doe' ] ], 'application_context' => [ 'brand_name' => 'Your Company', 'locale' => 'en-US', 'shipping_preference' => 'NO_SHIPPING', 'user_action' => 'SUBSCRIBE_NOW', 'payment_method' => [ 'payer_selected' => 'PAYPAL', 'payee_preferred' => 'IMMEDIATE_PAYMENT_REQUIRED' ], 'return_url' => 'https://your-domain.com/subscription/success', 'cancel_url' => 'https://your-domain.com/subscription/cancel' ] ]); return $subscription; } }
Webhook 处理
<?php use Hyperf\HttpServer\Annotation\Controller; use Hyperf\HttpServer\Annotation\RequestMapping; use Hyperf\HttpServer\Contract\RequestInterface; use Ws4934\HyperfPayPal\Services\PayPalInterface; #[Controller] class WebhookController { public function __construct( private PayPalInterface $paypal ) {} #[RequestMapping(path: '/webhooks/paypal', methods: 'POST')] public function handleWebhook(RequestInterface $request) { $client = $this->paypal->getAuthenticatedClient(); // 获取 webhook 数据 $webhookPayload = $request->getBody()->getContents(); $headers = $request->getHeaders(); // 验证 webhook 签名 $isValid = $client->verifyWebhookSignature([ 'webhook_id' => 'your-webhook-id', 'webhook_event' => json_decode($webhookPayload, true), 'headers' => $headers ]); if ($isValid) { $event = json_decode($webhookPayload, true); // 处理不同类型的事件 switch ($event['event_type']) { case 'PAYMENT.CAPTURE.COMPLETED': // 处理支付完成 break; case 'BILLING.SUBSCRIPTION.CREATED': // 处理订阅创建 break; case 'BILLING.SUBSCRIPTION.CANCELLED': // 处理订阅取消 break; default: // 处理其他事件 break; } } return ['status' => 'success']; } }
错误处理
<?php use Ws4934\HyperfPayPal\Services\PayPalInterface; use RuntimeException; class PaymentService { public function __construct( private PayPalInterface $paypal ) {} public function processPayment(array $data) { try { $client = $this->paypal->getAuthenticatedClient(); $order = $client->createOrder($data); return $order; } catch (RuntimeException $e) { // 获取详细错误信息 $lastError = $this->paypal->getLastError(); $lastRequest = $this->paypal->getLastRequest(); $lastResponse = $this->paypal->getLastResponse(); // 记录错误日志 logger()->error('PayPal API Error', [ 'error' => $e->getMessage(), 'last_error' => $lastError, 'request' => $lastRequest, 'response' => $lastResponse ]); throw $e; } finally { // 清理上下文 $this->paypal->clearContext(); } } }
协程上下文
组件使用 Hyperf 的协程上下文来存储请求和响应数据,这样在协程环境中不会出现数据混乱:
// 获取最后一次请求详情 $lastRequest = $paypal->getLastRequest(); // 获取最后一次响应详情 $lastResponse = $paypal->getLastResponse(); // 获取最后一次错误详情 $lastError = $paypal->getLastError(); // 清理上下文数据 $paypal->clearContext();
许可证
本项目基于 MIT 许可证开源。详情请见 LICENSE 文件。