emmanuelsiziba/zb-laravel-smilepay 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

emmanuelsiziba/zb-laravel-smilepay

Composer 安装命令:

composer require emmanuelsiziba/zb-laravel-smilepay

包简介

ZB Laravel package for SmilePay Payment Gateway integration (ZB Bank Zimbabwe)

README 文档

README

A comprehensive Laravel package for integrating SmilePay Payment Gateway (ZB Bank Zimbabwe) into your Laravel application. This package supports multiple payment methods including Ecocash, Innbucks, Omari, SmileCash, and Visa/Mastercard.

Latest Version Total Downloads License

Features

Multi-Payment Support – Ecocash, Innbucks, Omari, SmileCash, Visa/Mastercard ✅ Standard Checkout – Hosted payment page integration ✅ Express Checkout – Direct API integration for custom UIs ✅ Webhook Handling – Automatic payment status callbacks ✅ Auto-Configured Callbacks – No manual URL setup required; the package registers and wires its own routes ✅ Built-in Return Handler/smilepay/return polls status, fires events, and redirects the user ✅ Dual-App Return URLs – Route mobile deep-links and web redirects independently via a platform param ✅ Transaction Management – Check status, cancel payments ✅ Event System – Laravel events for payment notifications ✅ Sandbox & Production – Easy environment switching ✅ Comprehensive Logging – Debug and track all API interactions

Table of Contents

Requirements

  • PHP 8.0 or higher
  • Laravel 9.x, 10.x, or 11.x
  • Guzzle HTTP Client 7.x

Installation

Install the package via Composer:

composer require emmanuelsiziba/zb-laravel-smilepay

Publish Configuration

Publish the configuration file:

php artisan vendor:publish --tag=smilepay-config

This will create a config/smilepay.php configuration file.

Configuration

Environment Variables

The minimum configuration needed is just your credentials:

SMILEPAY_ENVIRONMENT=sandbox
SMILEPAY_API_KEY=your_api_key_here
SMILEPAY_API_SECRET=your_api_secret_here
SMILEPAY_DEFAULT_CURRENCY=840

The package automatically registers and wires its own callback routes (/smilepay/webhook and /smilepay/return), so you do not need to set SMILEPAY_RETURN_URL, SMILEPAY_RESULT_URL, SMILEPAY_CANCEL_URL, or SMILEPAY_FAILURE_URL unless you want to override the defaults.

Optional: App Return URLs

After the hosted checkout completes, the package's /smilepay/return route will redirect your user. Configure where to send them:

# Single app (web or mobile)
SMILEPAY_APP_RETURN_URL=https://yourapp.com/payments/return

# OR — separate URLs for mobile deep-links and web redirects
SMILEPAY_MOBILE_RETURN_URL=yourapp://payments/return
SMILEPAY_WEB_RETURN_URL=https://yourapp.com/payments/return

If none of these are set, the /smilepay/return route returns a JSON response instead of redirecting.

Optional: Override Callback URLs

Only set these if you need to point to a custom handler instead of the package's built-in routes:

SMILEPAY_RETURN_URL=https://yourdomain.com/custom/return
SMILEPAY_RESULT_URL=https://yourdomain.com/custom/webhook
SMILEPAY_CANCEL_URL=https://yourdomain.com/custom/cancel
SMILEPAY_FAILURE_URL=https://yourdomain.com/custom/failed

Logging (optional)

SMILEPAY_LOGGING=true
SMILEPAY_LOG_CHANNEL=stack

Currency Codes

  • 840 - USD (United States Dollar)
  • 924 - ZWG (Zimbabwean Dollar)

Getting API Credentials

  1. Sandbox: Register at https://zbnet.zb.co.zw/wallet_sandbox_merchant/
  2. Navigate to Settings > API Keys
  3. Click Generate New API Key
  4. Copy your API Key and API Secret

How Callbacks Work

When the package is installed, its service provider automatically:

  1. Registers two routes in your application:

    • POST /smilepay/webhook — ZB calls this server-to-server to notify you of a payment result
    • GET /smilepay/return — ZB redirects the customer here after the hosted checkout page
  2. Populates returnUrl, resultUrl, cancelUrl, and failureUrl on every payment request using url('/smilepay/return') and url('/smilepay/webhook') as defaults, so you never need to set them manually.

What /smilepay/return Does

When ZB redirects the customer back to your server, this built-in controller:

  1. Reads the orderReference from the query string
  2. Polls ZB for the definitive payment status
  3. Fires the appropriate package event (PaymentReceived, PaymentFailed, or PaymentCanceled)
  4. Redirects the user to your configured app return URL (with ?status=&orderReference= appended), or returns JSON if no URL is configured

App Return URLs

Use app return URLs to send the customer back to your application after the hosted checkout.

Single Application

SMILEPAY_APP_RETURN_URL=https://yourapp.com/payments/return

The customer will be redirected to:

https://yourapp.com/payments/return?status=success&orderReference=SP-ABC123

Mobile App + Web App (Dual Platform)

If you serve both a mobile app (deep link) and a web app, configure separate URLs:

SMILEPAY_MOBILE_RETURN_URL=yourapp://payments/return
SMILEPAY_WEB_RETURN_URL=https://yourapp.com/payments/return

Then signal the platform when initiating a payment by appending ?platform=mobile or ?platform=web to the returnUrl, cancelUrl, and failureUrl:

$platform = 'mobile'; // or 'web', determined by your request context

SmilePay::standardCheckout()->initiate([
    'amount'            => 100.00,
    'itemName'          => 'Order #123',
    'returnUrl'         => url('/smilepay/return') . '?platform=' . $platform,
    'cancelUrl'         => url('/smilepay/return') . '?platform=' . $platform,
    'failureUrl'        => url('/smilepay/return') . '?platform=' . $platform,
    // resultUrl is always server-to-server — no platform param needed
]);

The ReturnController reads ?platform= and picks the matching configured URL:

?platform= Uses config key .env variable
mobile smilepay.mobile_return_url SMILEPAY_MOBILE_RETURN_URL
web smilepay.web_return_url SMILEPAY_WEB_RETURN_URL
(absent) smilepay.app_return_url SMILEPAY_APP_RETURN_URL

If none match, a JSON response is returned.

Return URL Query Parameters

Regardless of which URL is used, the following query parameters are always appended:

Parameter Values Description
status success, failed, cancelled, pending Payment outcome
orderReference string Your order reference
message string Human-readable status message (only on non-success)

Usage

Standard Checkout

Standard Checkout redirects customers to a SmilePay hosted payment page.

use Emmanuelsiziba\SmilePay\Facades\SmilePay;

$response = SmilePay::standardCheckout()->initiate([
    'amount' => 100.00,
    'itemName' => 'Premium Subscription',
    'itemDescription' => 'Monthly subscription',
    'email' => 'customer@example.com',
    'mobilePhoneNumber' => '0771234567',
    'firstName' => 'John',
    'lastName' => 'Doe',
]);

if ($response->isSuccessful()) {
    // Redirect customer to payment page
    return redirect($response->paymentUrl);
}

Express Checkout

Express Checkout allows you to build custom payment UIs.

Ecocash

use Emmanuelsiziba\SmilePay\Facades\SmilePay;

$response = SmilePay::expressCheckout()->ecocash([
    'amount' => 50.00,
    'itemName' => 'Product Purchase',
    'ecocashMobile' => '0771234567',
    'email' => 'customer@example.com',
]);

if ($response->isSuccessful()) {
    // Customer receives USSD push notification
    // Poll for payment status or wait for webhook
    echo "Payment initiated: {$response->transactionReference}";
}

Innbucks

$response = SmilePay::expressCheckout()->innbucks([
    'amount' => 75.00,
    'itemName' => 'Service Payment',
    'email' => 'customer@example.com',
]);

if ($response->isSuccessful()) {
    // Get payment code
    $paymentCode = $response->innbucksPaymentCode;

    // Get deep link for mobile app
    $deepLink = $response->getInnbucksDeepLink();

    // Display to customer or create QR code
    echo "Payment Code: {$paymentCode}";
    echo "Deep Link: <a href='{$deepLink}'>Pay with InnBucks</a>";
}

Omari (Two-Step Process)

// Step 1: Initiate payment (sends OTP)
$response = SmilePay::expressCheckout()->omari([
    'amount' => 100.00,
    'itemName' => 'Order #12345',
    'omariMobile' => '0771234567',
]);

$transactionRef = $response->transactionReference;

// Step 2: Confirm with OTP (customer enters OTP from SMS)
$confirmResponse = SmilePay::expressCheckout()->omariConfirm(
    $transactionRef,
    '123456', // OTP from customer
    '0771234567' // Same mobile number
);

if ($confirmResponse->isSuccessful()) {
    echo "Payment confirmed!";
}

SmileCash (Two-Step Process)

// Step 1: Initiate payment
$response = SmilePay::expressCheckout()->smileCash([
    'amount' => 200.00,
    'itemName' => 'Shopping Cart',
    'smileCashMobile' => '0771234567',
]);

$transactionRef = $response->transactionReference;

// Step 2: Confirm with OTP
$confirmResponse = SmilePay::expressCheckout()->smileCashConfirm(
    $transactionRef,
    '000000', // OTP (use '000000' in sandbox)
    '0771234567'
);

Visa/Mastercard

$response = SmilePay::expressCheckout()->card([
    'amount' => 150.00,
    'itemName' => 'Product Purchase',
    'pan' => '5123450000000008',
    'expMonth' => '01',
    'expYear' => '39',
    'securityCode' => '100',
    'email' => 'customer@example.com',
]);

if ($response->requires3DS()) {
    // Redirect to 3D Secure authentication
    $redirectHtml = $response->redirectHtml;
    echo $redirectHtml; // Renders 3DS form
}

Transaction Management

Check Payment Status

use Emmanuelsiziba\SmilePay\Facades\SmilePay;

$status = SmilePay::utility()->checkStatus('SP-ABC123-1234567890');

if ($status->isPaid()) {
    echo "Payment successful!";
    echo "Amount: {$status->amount}";
    echo "Payment Method: {$status->paymentOption}";
}

// Other status methods
$status->isPending();   // Returns true if pending
$status->isFailed();    // Returns true if failed
$status->isCanceled();  // Returns true if canceled

Cancel Payment

$result = SmilePay::utility()->cancel('SP-ABC123-1234567890');

if ($result['success']) {
    echo "Payment canceled successfully";
}

Helper Methods

// Quick boolean checks
$isPaid = SmilePay::utility()->isPaymentSuccessful('ORDER-REF');
$isPending = SmilePay::utility()->isPaymentPending('ORDER-REF');
$isFailed = SmilePay::utility()->isPaymentFailed('ORDER-REF');

Webhook Handling

The package automatically registers a webhook route at /smilepay/webhook and sets it as the default resultUrl on every payment request — no manual configuration required.

To verify the route is registered:

php artisan route:list --name=smilepay

Listen to Payment Events

Create event listeners in app/Listeners:

// app/Listeners/HandlePaymentReceived.php
namespace App\Listeners;

use Emmanuelsiziba\SmilePay\Events\PaymentReceived;

class HandlePaymentReceived
{
    public function handle(PaymentReceived $event)
    {
        $transaction = $event->transaction;

        // Update order status
        $order = Order::where('reference', $transaction->orderReference)->first();
        $order->update(['status' => 'paid']);

        // Send confirmation email
        Mail::to($order->email)->send(new PaymentConfirmation($order));
    }
}

Register the listener in app/Providers/EventServiceProvider.php:

use Emmanuelsiziba\SmilePay\Events\PaymentReceived;
use Emmanuelsiziba\SmilePay\Events\PaymentFailed;
use Emmanuelsiziba\SmilePay\Events\PaymentCanceled;

protected $listen = [
    PaymentReceived::class => [
        HandlePaymentReceived::class,
    ],
    PaymentFailed::class => [
        HandlePaymentFailed::class,
    ],
    PaymentCanceled::class => [
        HandlePaymentCanceled::class,
    ],
];

Events

The package dispatches the following events:

Event Description
PaymentReceived Fired when payment is successful (status: PAID)
PaymentFailed Fired when payment fails (status: FAILED)
PaymentCanceled Fired when payment is canceled (status: CANCELED)

Each event contains a $transaction property of type TransactionStatus.

Testing

Sandbox Environment

Use the following test credentials in sandbox mode:

SmileCash

  • Mobile: 0711111111
  • OTP: 000000

Visa/Mastercard

  • Card Number: 5123450000000008
  • Expiry: 01/39
  • CVV: 100

Ecocash

  • Use any valid Zimbabwe mobile number
  • Approve the USSD prompt in sandbox

Innbucks

  • Any payment code generated will work in sandbox

Running Tests

composer test

API Reference

Payment Methods

Method Description
WALLETPLUS Combined wallet option
ECOCASH Ecocash mobile money
INNBUCKS Innbucks digital wallet
CARD Visa/Mastercard
OMARI Omari payment platform
ONEMONEY OneMoney mobile money

Payment Statuses

Status Description
PAID Payment successful
PENDING Payment pending confirmation
FAILED Payment failed
CANCELED Payment canceled

Advanced Usage

Custom Order Reference

$response = SmilePay::standardCheckout()->initiate([
    'orderReference' => 'CUSTOM-ORDER-' . time(),
    'amount' => 100.00,
    'itemName' => 'Product',
    // ... other fields
]);

Using Dependency Injection

use Emmanuelsiziba\SmilePay\Services\StandardCheckout;
use Emmanuelsiziba\SmilePay\Services\ExpressCheckout;

class PaymentController extends Controller
{
    public function __construct(
        protected StandardCheckout $standardCheckout,
        protected ExpressCheckout $expressCheckout
    ) {}

    public function processPayment()
    {
        $response = $this->expressCheckout->ecocash([...]);
    }
}

Error Handling

The package provides comprehensive error handling with user-friendly error messages:

use Emmanuelsiziba\SmilePay\Exceptions\SmilePayException;
use Emmanuelsiziba\SmilePay\Exceptions\PaymentException;

try {
    $response = SmilePay::expressCheckout()->ecocash([
        'amount' => 50.00,
        'itemName' => 'Product Purchase',
        'ecocashMobile' => '0771234567',
    ]);

    if ($response->isSuccessful()) {
        // Handle successful initiation
    }
} catch (PaymentException $e) {
    // Payment validation or business logic errors
    Log::error('Payment validation failed: ' . $e->getMessage());

    // Get additional context (API response details)
    $context = $e->getContext();

    return back()->withErrors([
        'payment' => $e->getMessage()
    ]);
} catch (SmilePayException $e) {
    // API communication errors (network, authentication, etc.)
    Log::error('SmilePay API error', [
        'message' => $e->getMessage(),
        'code' => $e->getCode(),
        'context' => $e->getContext(),
    ]);

    return back()->withErrors([
        'payment' => 'Unable to process payment. Please try again later.'
    ]);
}

Common Error Scenarios

404 Not Found Error

try {
    $response = SmilePay::expressCheckout()->ecocash([...]);
} catch (SmilePayException $e) {
    // User-friendly message:
    // "Endpoint not found: The payment method or endpoint '/payments/express-checkout/ecocash'
    // is not available. Please verify the API endpoint or contact support."

    if ($e->getCode() === 404) {
        // Check if you're using the correct environment
        // Verify the endpoint is available in your environment
        Log::warning('Payment endpoint not available', $e->getContext());
        return back()->with('warning', 'This payment method is currently unavailable.');
    }
}

Authentication Error (401)

try {
    $response = SmilePay::expressCheckout()->innbucks([...]);
} catch (SmilePayException $e) {
    if ($e->getCode() === 401) {
        // "Authentication failed: Invalid API credentials.
        // Please check your SmilePay configuration."

        Log::critical('Invalid SmilePay credentials');
        return back()->withErrors(['payment' => 'Payment system configuration error.']);
    }
}

Network/Connection Error

try {
    $response = SmilePay::standardCheckout()->initiate([...]);
} catch (SmilePayException $e) {
    // "Connection error: Unable to connect to SmilePay API.
    // Please check your internet connection and try again."

    Log::error('SmilePay connection failed', [
        'message' => $e->getMessage(),
        'context' => $e->getContext(),
    ]);

    return back()->withErrors([
        'payment' => 'Connection issue. Please check your internet and try again.'
    ]);
}

Error Context

All exceptions include a context array with debugging information:

try {
    $response = SmilePay::expressCheckout()->ecocash([...]);
} catch (SmilePayException $e) {
    $context = $e->getContext();

    // Context includes:
    // - endpoint: The API endpoint that failed
    // - method: HTTP method (GET/POST)
    // - status_code: HTTP status code (if available)
    // - raw_response: Full API response (if available)

    Log::error('SmilePay error details', [
        'endpoint' => $context['endpoint'] ?? 'unknown',
        'status' => $context['status_code'] ?? 'N/A',
        'response' => $context['raw_response'] ?? 'No response',
    ]);
}

Best Practices

  1. Always catch exceptions when initiating payments
  2. Log errors with context for debugging
  3. Show user-friendly messages to customers
  4. Handle specific error codes differently (404, 401, 500, etc.)
  5. Enable logging in config/smilepay.php for production debugging

Troubleshooting

404 Not Found Error

If you encounter a 404 error when initiating payments:

Endpoint not found: The payment method or endpoint '/payments/express-checkout/ecocash'
is not available. Please verify the API endpoint or contact support.

Possible causes:

  • Wrong environment: You may be using sandbox credentials with a production base URL (or vice versa)
  • Endpoint not available: The specific payment method may not be enabled for your account
  • Incorrect base URL: Check your SMILEPAY_ENVIRONMENT setting in .env
  • Outdated package version: Versions prior to v0.1.5 had URL construction issues with Guzzle

Solutions:

  1. Update to the latest version (recommended):

    composer update emmanuelsiziba/zb-laravel-smilepay

    This fixes a critical bug where leading slashes in endpoints caused Guzzle to treat them as absolute paths when the base URL has a trailing slash.

  2. Verify your environment setting:

    SMILEPAY_ENVIRONMENT=sandbox  # or 'production'
  3. Ensure your API credentials match the environment

  4. Check if the payment method is enabled in your SmilePay merchant dashboard

  5. Enable logging to see the full request details:

    SMILEPAY_LOGGING=true

API Credentials Not Working

  • Ensure you're using the correct environment (sandbox/production)
  • Verify API keys are generated from the correct environment
  • Check for any whitespace in your .env file
  • Confirm credentials have the required permissions

Webhook Not Receiving Callbacks

  • The resultUrl is auto-set to {APP_URL}/smilepay/webhook — ensure your APP_URL in .env is publicly accessible (use ngrok for local testing)
  • Verify both routes are registered: php artisan route:list --name=smilepay
  • Check webhook middleware in config/smilepay.php
  • Check your server's firewall allows incoming POST requests

Payment Status Not Updating

  • Always poll the status API in addition to webhook callbacks
  • Implement retry logic for failed webhook deliveries
  • Use Laravel queues for webhook processing
  • Check your application logs for webhook processing errors

Changelog

Please see CHANGELOG for recent changes.

Contributing

Contributions are welcome! Please see CONTRIBUTING for details.

Security

If you discover any security-related issues, please email security@example.com instead of using the issue tracker.

Credits

License

The MIT License (MIT). Please see License File for more information.

Support

Made with ❤️ for the Laravel community

emmanuelsiziba/zb-laravel-smilepay 适用场景与选型建议

emmanuelsiziba/zb-laravel-smilepay 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 2 次下载、GitHub Stars 达 0, 最近一次更新时间为 2026 年 05 月 03 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「payment」 「laravel」 「payment gateway」 「zimbabwe」 「smilepay」 「zb bank」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 emmanuelsiziba/zb-laravel-smilepay 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 emmanuelsiziba/zb-laravel-smilepay 我们能提供哪些服务?
定制开发 / 二次开发

基于 emmanuelsiziba/zb-laravel-smilepay 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 2
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 32
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-05-03