Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Pay Laravel Package

yansongda/laravel-pay

yansongda/laravel-pay 是 Laravel/Lumen 的聚合支付扩展,基于 yansongda/pay,支持支付宝、微信、抖音支付、江苏银行(e融支付)等。提供 Facade 调用与统一配置,快速创建订单、发起网页/公众号/小程序等支付。

View on GitHub
Deep Wiki
Context7
## Getting Started

### Minimal Setup
1. **Installation**:
   ```bash
   composer require yansongda/laravel-pay:~3.7.0
  1. Publish Config:

    php artisan vendor:publish --provider="Yansongda\LaravelPay\PayServiceProvider" --tag=laravel-pay
    

    (For Lumen, manually copy config and register the provider.)

  2. Configure .env: Add your gateway credentials (e.g., ALIPAY_APP_ID, WECHAT_APP_ID) under the PAY_* section in .env.

  3. First Use Case: Generate a Alipay Web Pay link:

    use Yansongda\LaravelPay\Facades\Pay;
    
    $order = [
        'out_trade_no' => time(),
        'total_amount' => '1.00',
        'subject' => 'Order #' . time(),
    ];
    
    return Pay::alipay()->web($order);
    

    (Shortcut: Pay::web($order) also works.)


Implementation Patterns

1. Gateway-Specific Workflows

Alipay (支付宝)

  • Web Pay: Redirect users to Alipay for payment.
    Pay::alipay()->web($order);
    
  • App Pay: Generate a QR code for mobile apps.
    Pay::alipay()->app($order);
    
  • Refunds: Process refunds via refund().
    Pay::alipay()->refund(['out_trade_no' => $orderId, 'refund_amount' => '0.50']);
    

WeChat Pay (微信支付)

  • Mini Program Pay: Use mp() for WeChat Mini Programs.
    Pay::wechat()->mp($order);
    
  • Native Pay (Scan): Generate a QR code for native apps.
    Pay::wechat()->native($order);
    
  • JSAPI Pay: For web pages integrated with WeChat.
    Pay::wechat()->jsapi($order);
    

Unified API (统一支付)

  • Switch gateways dynamically:
    $gateway = request()->input('gateway') === 'alipay' ? 'alipay' : 'wechat';
    Pay::$gateway()->web($order);
    

2. Order Management

  • Generate Unique out_trade_no: Use Laravel’s Str::uuid() or time() + random() to avoid collisions.

    $order['out_trade_no'] = Str::uuid()->toString();
    
  • Store Orders in DB: Save $order to orders table before processing, then reference it in callbacks.

    $order = Order::create([...]);
    Pay::alipay()->web($order->toArray());
    
  • Async Notifications: Use Laravel Queues to handle async webhook notifications:

    Pay::alipay()->web($order)->setNotifyUrl(route('pay.notify'))->execute();
    

3. Webhook Handling

  • Notify URL: Configure in .env (e.g., ALIPAY_NOTIFY_URL) and handle notifications in a controller:

    public function handleNotify(Request $request)
    {
        $result = Pay::alipay()->verifyNotify($request->all());
        if ($result->success()) {
            // Update order status, etc.
        }
        return $result->success() ? 'success' : 'fail';
    }
    
  • Verify Signatures: Always verify signatures in notifications to prevent fraud:

    $result = Pay::alipay()->verifyNotify($data);
    

4. Testing

  • Sandbox Mode: Enable in config (sandbox => true) and use test credentials from gateways (e.g., Alipay’s sandbox app ID).

    'alipay' => [
        'sandbox' => env('PAY_ALIPAY_SANDBOX', true),
        'app_id' => env('PAY_ALIPAY_APP_ID', '202100****'),
    ],
    
  • Mock Responses: Use Pay::alipay()->mock() to simulate successful/failure responses during testing:

    $mock = Pay::alipay()->mock()->web($order);
    

Gotchas and Tips

1. Configuration Pitfalls

  • Missing .env Keys: Ensure all required keys (e.g., ALIPAY_APP_ID, WECHAT_MCH_ID) are set in .env. The package won’t throw errors if they’re missing—it’ll fail silently during execution. Fix: Validate config in a service provider’s boot() method:

    if (empty(config('pay.alipay.app_id'))) {
        throw new \RuntimeException('Alipay app_id not configured.');
    }
    
  • Sandbox vs. Production: Forgetting to switch between sandbox and production modes can lead to failed payments. Always double-check:

    'alipay' => [
        'sandbox' => env('APP_ENV') === 'local', // Toggle based on environment
    ],
    

2. Order ID Collisions

  • Race Conditions: If multiple orders are created simultaneously with time() as out_trade_no, collisions may occur. Fix: Use UUIDs or a database sequence:
    $order['out_trade_no'] = (string) Str::orderedUuid();
    

3. Webhook Debugging

  • Signature Mismatches: If notifications fail verification, check:

    1. Time Sync: Ensure your server time matches the gateway’s (e.g., Alipay requires time sync within 30 seconds).
    2. Key Configuration: Verify ALIPAY_APP_PRIVATE_KEY and ALIPAY_APP_PUBLIC_KEY are correct.
    3. Data Order: Alipay/WeChat expect parameters in a specific order. Use Pay::alipay()->verifyNotify() to debug.
  • Logging Notifications: Log raw notification data for debugging:

    \Log::debug('Alipay Notify', $request->all());
    

4. Gateway-Specific Quirks

Alipay

  • Subject/Body Limits: subject and body must be ≤ 128 characters. Truncate long descriptions:

    $order['subject'] = Str::limit($subject, 128);
    
  • Currency: Defaults to CNY. Explicitly set if needed:

    $order['currency'] = 'USD';
    

WeChat Pay

  • OpenID Requirements: For mp() and jsapi, openid is mandatory. Fetch it via WeChat’s OAuth:

    $openid = session('wechat_openid'); // Store during OAuth flow
    $order['openid'] = $openid;
    
  • Total Fee: Must be an integer (e.g., 100 for ¥1.00). Convert floats:

    $order['total_fee'] = (int) ($amount * 100);
    

Douyin (抖音支付)

  • Valid Time: valid_time (in seconds) must be ≥ 60 and ≤ 7200 (2 hours). Default to 3600 (1 hour):
    $order['valid_time'] = 3600;
    

5. Extending the Package

Custom Gateways

  • Create a new gateway class by extending Yansongda\Pay\Gateway:
    namespace App\Pay;
    
    use Yansongda\Pay\Gateway;
    
    class CustomGateway extends Gateway
    {
        protected $code = 'custom';
        protected $name = 'Custom Pay';
    
        public function pay(array $data)
        {
            // Custom logic
            return $this->response()->success($data);
        }
    }
    
  • Register it in config/pay.php:
    'gateways' => [
        'custom' => [
            'driver' => \App\Pay\CustomGateway::class,
        ],
    ],
    

Custom Responses

  • Override default responses by binding a custom response class:
    Pay::extend('alipay', function () {
        return new \App\Pay\CustomAlipayResponse();
    });
    

6. Performance Tips

  • Caching Config: Avoid loading config files repeatedly by caching the Pay facade’s config:

    $config = config('pay');
    Pay::setConfig($config); // Cache config if modified rarely
    
  • Batch Refunds: For multiple refunds, use batch processing:

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
graham-campbell/flysystem
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
directorytree/opensearch-client
directorytree/opensearch-adapter
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin