关于 payment-method-development
为 Bagisto 开发者提供自定义支付方式的实现指南,涵盖支付类、配置和服务提供者的创建与注册。适用于接入支付网关或扩展结账选项。
主要功能
- 01配置支付方式与系统设置
- 02实现支付处理类
- 03注册服务提供者与软件包
- 04支持按销售渠道配置
- 05参考内置支付方式示例
适用场景
- 01为结账添加自定义支付方式
- 02接入支付网关或专用支付流程
- 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:注册软件包
- 添加到 composer.json(位于 Bagisto 根目录):
{
"autoload": {
"psr-4": {
"Webkul\\CustomStripePayment\\": "packages/Webkul/CustomStripePayment/src"
}
}
}
- 更新自动加载器:
composer dump-autoload
- 在
bootstrap/providers.php中注册服务提供者:
<?php
return [
App\Providers\AppServiceProvider::class,
// ... other providers ...
Webkul\CustomStripePayment\Providers\CustomStripePaymentServiceProvider::class,
];
- 清除缓存:
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 约定并使用正确的标点