Thêm cổng thanh toán (Payment)
Sicommerce thiết kế hệ thống thanh toán theo mô hình Manager + Abstract Gateway (tương tự Omnipay). Mỗi cổng thanh toán gồm 2 class: Base (cấu hình/hiển thị) và Gateway (xử lý giao dịch). Bạn tạo cả hai rồi đăng ký vào PaymentManager.
Các Class Liên Quan
| Class | Namespace | Mô tả |
|---|---|---|
AbstractPaymentBase | Ecommerce\Gateway\Payment\Common | Abstract base class cho Payment Base |
AbstractPaymentGateway | Ecommerce\Gateway\Payment\Common | Abstract base class cho Payment Gateway |
AbstractRequest | Ecommerce\Gateway\Payment\Common\Message | Base cho Request Object |
AbstractResponse | Ecommerce\Gateway\Payment\Common\Message | Base cho Response Object |
PaymentManager | Ecommerce\Gateway\Payment\Common | Facade quản lý toàn bộ Payment Gateways |
Bước 1: Tạo Payment Base Class
Class này cung cấp thông tin hiển thị và form cấu hình trong trang Admin.
Tạo file: plugins/your-plugin/app/Gateway/VNPay/VNPay.php
<?php
namespace YourPlugin\Gateway\VNPay;
use Ecommerce\Gateway\Payment\Common\AbstractPaymentBase;
use SkillDo\Http\Request;
class VNPay extends AbstractPaymentBase
{
/**
* Key định danh (ID) – viết thường, không dấu, không khoảng trắng
*/
public function getName(): string
{
return 'vnpay';
}
/**
* Tên hiển thị trong trang cài đặt Admin
*/
public function getAdminName(): string
{
return 'Cổng thanh toán VNPay';
}
/**
* Mô tả ngắn trong trang cài đặt Admin
*/
public function getAdminDescription(): string
{
return 'Thanh toán qua ví điện tử VNPay';
}
/**
* URL hình icon hiển thị trong Admin và trang Checkout
*/
public function getAdminIcon(): string
{
return asset('your-plugin::images/vnpay-icon.png', true);
}
/**
* (Tuỳ chọn) Ghi đè form() để thêm trường cấu hình riêng (API Key, Secret...)
* Mặc định AbstractPaymentBase đã có form() với Icon + Checkout Name/Description đa ngôn ngữ
*/
public function form()
{
$form = parent::form(); // Lấy form mặc định
$key = $this->getName();
// Thêm trường API Key
$form->text($key.'[tmn_code]', ['label' => 'TMN Code (vnp_TmnCode)'],
PaymentManager::getConfig($key)['tmn_code'] ?? '');
$form->password($key.'[hash_secret]', ['label' => 'Hash Secret Key'],
PaymentManager::getConfig($key)['hash_secret'] ?? '');
return $form;
}
/**
* (Tuỳ chọn) Ghi đè saveConfig() để lưu thêm các trường tuỳ chỉnh
*/
public function saveConfig(Request $request)
{
$payment = parent::saveConfig($request); // Lưu các trường mặc định
$data = $request->input($this->getName());
$payment['tmn_code'] = $data['tmn_code'] ?? '';
$payment['hash_secret'] = $data['hash_secret'] ?? '';
return $payment;
}
}
Các method được kế thừa từ
AbstractPaymentBase:
form()– render form cấu hình mặc định (Icon + Checkout Name + Description đa ngôn ngữ)saveConfig(Request $request)– lưu config mặc địnhgetCheckoutName($locale)– tên hiển thị trên trang checkout theo ngôn ngữgetCheckoutDescription($locale)– mô tả trên trang checkoutgetCheckoutIcon()– icon trên trang checkoutuseGateway(): bool– kiểm tra gateway có được bật khônggetPosition(): int– vị trí ưu tiên hiển thịvalidate(Request $request)– validate trước khi lưu config
Bước 2: Tạo Payment Gateway Class
Class này xử lý luồng giao dịch thực tế (tạo request, nhận response).
Tạo file: plugins/your-plugin/app/Gateway/VNPay/VNPayGateway.php
<?php
namespace YourPlugin\Gateway\VNPay;
use Ecommerce\Gateway\Payment\Common\AbstractPaymentGateway;
use Ecommerce\Models\Order;
class VNPayGateway extends AbstractPaymentGateway
{
/**
* Khai báo các parameter mặc định của Gateway
*/
public function getDefaultParameters(): array
{
return [
'testMode' => false,
'tmn_code' => '',
'hash_secret'=> '',
];
}
// Getter/Setter cho các parameter tùy chỉnh
public function getTmnCode(): string { return $this->getParameter('tmn_code'); }
public function setTmnCode($value): static { return $this->setParameter('tmn_code', $value); }
public function getHashSecret(): string { return $this->getParameter('hash_secret'); }
public function setHashSecret($value): static { return $this->setParameter('hash_secret', $value); }
/**
* Tạo request thanh toán
* Được gọi khi khách xác nhận đặt hàng
*
* @param Order $order Đối tượng đơn hàng
* @return mixed URL redirect hoặc response
*/
public function purchase(Order $order)
{
// Cách 1: Tạo PurchaseRequest riêng (khuyến nghị cho tích hợp phức tạp)
return $this->createRequest(VNPayPurchaseRequest::class, [
'amount' => $order->total,
'order_id' => $order->id,
'order_code' => $order->code,
'return_url' => PaymentManager::getReturnUrl($order->id),
'cancel_url' => PaymentManager::getCancelUrl($order->id),
]);
// Cách 2: Xử lý trực tiếp và return URL redirect (đơn giản hơn)
// $params = [...];
// $paymentUrl = 'https://sandbox.vnpayment.vn/...' . '?' . http_build_query($params);
// return redirect($paymentUrl);
}
/**
* Xử lý callback/IPN từ VNPay sau khi thanh toán
*/
public function completePurchase(array $data)
{
return $this->createRequest(VNPayCompletePurchaseRequest::class, $data);
}
}