mcpField
P
payment-method-development

payment-method-development

github.com/bagisto开发13287 次安装2 周前更新
代码仓库

关于 payment-method-development

为 Bagisto 开发者提供自定义支付方式的实现指南,涵盖支付类、配置和服务提供者的创建与注册。适用于接入支付网关或扩展结账选项。

主要功能

  1. 01配置支付方式与系统设置
  2. 02实现支付处理类
  3. 03注册服务提供者与软件包
  4. 04支持按销售渠道配置
  5. 05参考内置支付方式示例

适用场景

  1. 01为结账添加自定义支付方式
  2. 02接入支付网关或专用支付流程
  3. 03为支付方式创建管理端设置

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/bagisto/agent-skills --skill payment-method-development

安装后在 Claude Code 中输入/payment-method-development确认已加载。

详细介绍

支付方式开发

概述

在 Bagisto 中创建自定义支付方式,可将任意支付网关或处理器集成到您的商店中。无论您需要本地支付方式、加密货币支付,还是专门的支付流程,自定义支付方式都能提供业务所需的灵活性。

在本教程中,我们将创建一个 Custom Stripe Payment 方式,演示构建各种支付解决方案所需的所有核心概念。

适用场景

在以下情况下启用此技能:

  • 创建新的支付方式
  • 集成支付网关(Stripe、PayPal、Razorpay 等)
  • 在结账时添加支付选项
  • 修改现有支付配置
  • 为支付方式创建管理后台配置

Bagisto 支付架构

Bagisto 的支付系统采用灵活的基于方式的架构,将配置与业务逻辑分离。

核心组件
组件用途位置
支付方式配置定义支付方式属性Config/payment-methods.php
支付类包含支付处理逻辑Payment/ClassName.php
系统配置管理后台界面表单Config/system.php
服务提供程序注册支付方式Providers/ServiceProvider.php
主要功能
  • 灵活的支付处理:支持重定向、API、webhook 或自定义流程。
  • 配置管理:便于管理员使用的设置界面。
  • 多渠道支持:为不同销售渠道设置不同配置。
  • 安全就绪:内置 CSRF 保护和安全处理机制。
  • 可扩展架构:轻松集成第三方网关。

分步指南

步骤 1:创建包目录结构
mkdir -p packages/Webkul/CustomStripePayment/src/{Payment,Config,Providers}
步骤 2:创建支付方式配置

文件: packages/Webkul/CustomStripePayment/src/Config/payment-methods.php

<?php

return [
    'custom_stripe_payment' => [
        'code'        => 'custom_stripe_payment',
        'title'       => 'Credit Card (Stripe)',
        'description' => 'Secure credit card payments powered by Stripe',
        'class'       => 'Webkul\CustomStripePayment\Payment\CustomStripePayment',
        'active'      => true,
        'sort'        => 1,
    ],
];
配置属性说明
属性类型用途说明
code字符串唯一标识符必须与数组键一致,并在支付方式中始终保持一致。
title字符串默认显示名称在结账时显示给客户(可在管理后台中覆盖)。
description字符串支付方式说明对支付方式的简要说明。
class字符串支付类命名空间指向支付处理类的完整路径。
active布尔值默认状态指定是否默认启用该支付方式。
sort整数显示顺序数值越小,在结账时越靠前(0 = 第一位)。

注意: 数组键(custom_stripe_payment)必须与 code 属性一致,并且在支付类的 $code 属性、系统配置键路径以及路由名称和标识符中始终保持一致。

步骤 3:创建支付类

文件: packages/Webkul/CustomStripePayment/src/Payment/CustomStripePayment.php

<?php

namespace Webkul\CustomStripePayment\Payment;

use Webkul\Payment\Payment\Payment;

class CustomStripePayment extends Payment
{
    /**
     * Payment method code - must match payment-methods.php key.
     *
     * @var string
     */
    protected $code = 'custom_stripe_payment';

    /**
     * Get redirect URL for payment processing.
     *
     * Note: You need to create this route in your Routes/web.php file
     * or return null if you don't need a redirect.
     *
     * @return string|null
     */
    public function getRedirectUrl()
    {
        // return route('custom_stripe_payment.process');
        return null; // No redirect needed for this basic example
    }

    /**
     * Get additional details for frontend display.
     *
     * @return array
     */
    public function getAdditionalDetails()
    {
        return [
            'title' => $this->getConfigData('title'),
            'description' => $this->getConfigData('description'),
            'requires_card_details' => true,
        ];
    }

    /**
     * Get payment method configuration data.
     *
     * @param  string  $field
     * @return mixed
     */
    public function getConfigData($field)
    {
        return core()->getConfigData('sales.payment_methods.custom_stripe_payment.' . $field);
    }
}
步骤 4:创建系统配置

文件: packages/Webkul/CustomStripePayment/src/Config/system.php

<?php

return [
    [
        'key'    => 'sales.payment_methods.custom_stripe_payment',
        'name'   => 'Custom Stripe Payment',
        'info'   => 'Custom Stripe Payment Method Configuration',
        'sort'   => 1,
        'fields' => [
            [
                'name'          => 'active',
                'title'         => 'Status',
                'type'          => 'boolean',
                'default_value' => true,
                'channel_based' => true,
            ],
            [
                'name'          => 'title',
                'title'         => 'Title',
                'type'          => 'text',
                'default_value' => 'Credit Card (Stripe)',
                'channel_based' => true,
                'locale_based'  => true,
            ],
            [
                'name'          => 'description',
                'title'         => 'Description',
                'type'          => 'textarea',
                'default_value' => 'Secure credit card payments',
                'channel_based' => true,
                'locale_based'  => true,
            ],
            [
                'name'          => 'sort',
                'title'         => 'Sort Order',
                'type'          => 'text',
                'default_value' => '1',
            ],
        ],
    ],
];
系统配置字段属性
属性用途说明
name字段标识符用于存储和读取配置值。
title字段标签在管理后台表单中显示的标签。
type输入类型text、textarea、boolean、select、password 等。
default_value默认设置首次配置时的初始值。
channel_based多店铺支持为不同销售渠道设置不同的值。
locale_based多语言支持可按语言翻译内容。
validation字段验证required、numeric、email 等规则。
步骤 5:创建服务提供者

文件: packages/Webkul/CustomStripePayment/src/Providers/CustomStripePaymentServiceProvider.php

<?php

namespace Webkul\CustomStripePayment\Providers;

use Illuminate\Support\ServiceProvider;

class CustomStripePaymentServiceProvider extends ServiceProvider
{
    /**
     * Register services.
     *
     * @return void
     */
    public function register(): void
    {
        // Merge payment method configuration.
        $this->mergeConfigFrom(
            dirname(__DIR__) . '/Config/payment-methods.php',
            'payment_methods'
        );

        // Merge system configuration.
        $this->mergeConfigFrom(
            dirname(__DIR__) . '/Config/system.php',
            'core'
        );
    }

    /**
     * Bootstrap services.
     *
     * @return void
     */
    public function boot(): void
    {
        //
    }
}
步骤 6:注册软件包
  1. 添加到 composer.json(位于 Bagisto 根目录):
{
    "autoload": {
        "psr-4": {
            "Webkul\\CustomStripePayment\\": "packages/Webkul/CustomStripePayment/src"
        }
    }
}
  1. 更新自动加载器:
composer dump-autoload
  1. 在 bootstrap/providers.php 中注册服务提供者:
<?php

return [
    App\Providers\AppServiceProvider::class,

    // ... other providers ...

    Webkul\CustomStripePayment\Providers\CustomStripePaymentServiceProvider::class,
];
  1. 清除缓存:
php artisan optimize:clear

支付基础类参考

位置: packages/Webkul/Payment/src/Payment/Payment.php

所有支付方式都扩展 Webkul\Payment\Payment\Payment 抽象类:

<?php

namespace Webkul\Payment\Payment;

use Webkul\Checkout\Facades\Cart;

abstract class Payment
{
    /**
     * Cart.
     *
     * @var \Webkul\Checkout\Contracts\Cart
     */
    protected $cart;

    /**
     * Checks if payment method is available.
     *
     * @return bool
     */
    public function isAvailable()
    {
        return $this->getConfigData('active');
    }

    /**
     * Get payment method code.
     *
     * @return string
     */
    public function getCode()
    {
        if (empty($this->code)) {
            // throw exception
        }

        return $this->code;
    }

    /**
     * Get payment method title.
     *
     * @return string
     */
    public function getTitle()
    {
        return $this->getConfigData('title');
    }

    /**
     * Get payment method description.
     *
     * @return string
     */
    public function getDescription()
    {
        return $this->getConfigData('description');
    }

    /**
     * Get payment method image.
     *
     * @return string
     */
    public function getImage()
    {
        return $this->getConfigData('image');
    }

    /**
     * Retrieve information from payment configuration.
     *
     * @param  string  $field
     * @return mixed
     */
    public function getConfigData($field)
    {
        return core()->getConfigData('sales.payment_methods.'.$this->getCode().'.'.$field);
    }

    /**
     * Abstract method to get the redirect URL.
     *
     * @return string The redirect URL.
     */
    abstract public function getRedirectUrl();

    /**
     * Set cart.
     *
     * @return void
     */
    public function setCart()
    {
        if (! $this->cart) {
            $this->cart = Cart::getCart();
        }
    }

    /**
     * Get cart.
     *
     * @return \Webkul\Checkout\Contracts\Cart
     */
    public function getCart()
    {
        if (! $this->cart) {
            $this->setCart();
        }

        return $this->cart;
    }

    /**
     * Return cart items.
     *
     * @return \Illuminate\Database\Eloquent\Collection
     */
    public function getCartItems()
    {
        if (! $this->cart) {
            $this->setCart();
        }

        return $this->cart->items;
    }

    /**
     * Get payment method sort order.
     *
     * @return string
     */
    public function getSortOrder()
    {
        return $this->getConfigData('sort');
    }

    /**
     * Get payment method additional information.
     *
     * @return array
     */
    public function getAdditionalDetails()
    {
        if (empty($this->getConfigData('instructions'))) {
            return [];
        }

        return [
            'title' => trans('admin::app.configuration.index.sales.payment-methods.instructions'),
            'value' => $this->getConfigData('instructions'),
        ];
    }
}

要实现的关键方法

方法用途必需
getRedirectUrl()返回重定向支付方式的 URL是(抽象方法)
getImage()返回支付方式的徽标 URL否(使用默认值)
getAdditionalDetails()返回附加信息(说明等)否(使用默认值)
isAvailable()重写以添加自定义可用性逻辑否(使用默认值)
getConfigData($field)如果代码不符合约定,则重写否(使用默认值)

实现说明: 通常,无需显式设置 $code 属性,因为只要代码设置正确,配置数据就能正确获取。不过,如果代码不符合约定,则可能需要使用此属性来重写默认行为。

内置支付方式

  • CashOnDelivery:packages/Webkul/Payment/src/Payment/CashOnDelivery.php
  • MoneyTransfer:packages/Webkul/Payment/src/Payment/MoneyTransfer.php
  • PaypalStandard:packages/Webkul/Paypal/src/Payment/Standard.php
  • PaypalSmartButton:packages/Webkul/Paypal/src/Payment/SmartButton.php

支付类最佳实践

错误处理

始终在支付方式中实现全面的错误处理:

/**
 * Handle payment errors gracefully.
 *
 * @param  \Exception  $e
 * @return array
 */
protected function handlePaymentError(\Exception $e)
{
    // Log the error for debugging.
    \Log::error('Payment error in ' . $this->code, [
        'error' => $e->getMessage(),
        'trace' => $e->getTraceAsString(),
    ]);

    // Return user-friendly error message.
    return [
        'success' => false,
        'error'   => 'Payment processing failed. Please try again or contact support.',
    ];
}
安全注意事项

处理支付前,始终验证并清理数据,以保护应用和客户:

/**
 * Validate payment data before processing.
 *
 * @param  array  $data
 * @return bool
 *
 * @throws \InvalidArgumentException
 */
protected function validatePaymentData($data)
{
    $validator = validator($data, [
        'amount'        => 'required|numeric|min:0.01',
        'currency'      => 'required|string|size:3',
        'customer_email'=> 'required|email',
    ]);

    if ($validator->fails()) {
        throw new \InvalidArgumentException($validator->errors()->first());
    }

    return true;
}
日志记录与调试

恰当的日志记录有助于跟踪支付活动并排查问题,同时避免泄露敏感信息:

/**
 * Log payment activities for debugging and audit.
 *
 * @param  string  $action
 * @param  array   $data
 * @return void
 */
protected function logPaymentActivity($action, $data = [])
{
    // Remove sensitive data before logging.
    $sanitizedData = array_diff_key($data, [
        'api_key'      => '',
        'secret_key'   => '',
        'card_number'  => '',
        'cvv'          => '',
    ]);

    \Log::info("Payment {$action} for {$this->code}", $sanitizedData);
}

实现说明: 本节展示的方法是最佳实践的演示示例。在实际应用中,你需要根据具体的支付网关要求和业务逻辑来实现这些方法。请将这些示例用作参考,并根据具体用例进行调整。

示例:PayPal Smart Button(复杂集成)

对于 PayPal 等复杂支付集成,请参阅 packages/Webkul/Paypal/src/Payment/SmartButton.php:

  • 扩展 PayPal 基础类,该类扩展了 Payment。
  • 使用 PayPal SDK 调用 API。
  • 实现 createOrder、captureOrder、getOrder、refundOrder。
  • 处理沙盒/正式环境切换。

软件包结构

packages
└── Webkul
    └── CustomStripePayment
        └── src
            ├── Payment
            │   └── CustomStripePayment.php                 # Payment processing logic
            ├── Config
            │   ├── payment-methods.php                     # Payment method definition
            │   └── system.php                              # Admin configuration
            └── Providers
                └── CustomStripePaymentServiceProvider.php  # Registration

测试

可以使用 packages/Webkul/Shop/tests/Feature/Checkout/CheckoutTest.php 中的结账测试来测试支付方式。

关键文件参考

文件用途
packages/Webkul/Payment/src/Payment/Payment.php基础抽象类
packages/Webkul/Payment/src/Payment.php支付门面方法
packages/Webkul/Payment/src/Config/payment-methods.php默认支付方式配置
packages/Webkul/Paypal/src/Payment/SmartButton.php复杂支付示例
packages/Webkul/Paypal/src/Providers/PaypalServiceProvider.php服务提供者示例
packages/Webkul/Payment/src/Payment/CashOnDelivery.php简单支付示例
packages/Webkul/Payment/src/Payment/MoneyTransfer.php带附加详情的支付

常见问题

  • 忘记在服务提供程序中合并配置
  • $code 属性与配置数组键不匹配
  • 未在 bootstrap/providers.php 中注册服务提供程序
  • 添加软件包后忘记运行 composer dump-autoload
  • 配置更改后未清除缓存
  • 未遵循 PHPDoc 约定并使用正确的标点

评论

支持 Markdown