fix(payment): validate and filter unavailable methods

Filter user-visible payment methods to only include supported
providers and fail fast when a payment record or plugin cannot be
resolved.

This prevents invalid payment options from being returned by the
API and avoids constructing an undefined fallback payment class.
This commit is contained in:
yinjianm
2026-03-19 20:29:26 +08:00
parent dbffb0a7bd
commit 421844895e
2 changed files with 40 additions and 21 deletions
@@ -173,6 +173,8 @@ class OrderController extends Controller
public function getPaymentMethod()
{
$availableMethods = array_flip(PaymentService::getAllPaymentMethodNames());
$methods = Payment::select([
'id',
'name',
@@ -183,7 +185,11 @@ class OrderController extends Controller
])
->where('enable', 1)
->orderBy('sort', 'ASC')
->get();
->get()
->filter(function ($payment) use ($availableMethods) {
return isset($availableMethods[$payment->payment]);
})
->values();
return $this->success($methods);
}
+33 -20
View File
@@ -13,7 +13,6 @@ class PaymentService
protected $config;
protected $payment;
protected $pluginManager;
protected $class;
public function __construct($method, $id = NULL, $uuid = NULL)
{
@@ -24,36 +23,50 @@ class PaymentService
return;
}
$payment = null;
if ($id) {
$payment = Payment::find($id)->toArray();
$payment = Payment::find($id);
}
if ($uuid) {
$payment = Payment::where('uuid', $uuid)->first()->toArray();
if (!$payment && $uuid) {
$payment = Payment::where('uuid', $uuid)->first();
}
if (($id || $uuid) && !$payment) {
throw new ApiException(__('Payment method is not available'));
}
$this->config = [];
if (isset($payment)) {
$this->config = is_string($payment['config']) ? json_decode($payment['config'], true) : $payment['config'];
$this->config['enable'] = $payment['enable'];
$this->config['id'] = $payment['id'];
$this->config['uuid'] = $payment['uuid'];
$this->config['notify_domain'] = $payment['notify_domain'] ?? '';
if ($payment) {
$config = $payment->config;
$this->config = is_string($config) ? json_decode($config, true) : ($config ?? []);
if (!is_array($this->config)) {
$this->config = [];
}
$this->config['enable'] = $payment->enable;
$this->config['id'] = $payment->id;
$this->config['uuid'] = $payment->uuid;
$this->config['notify_domain'] = $payment->notify_domain ?? '';
}
$paymentMethods = $this->getAvailablePaymentMethods();
if (isset($paymentMethods[$this->method])) {
$pluginCode = $paymentMethods[$this->method]['plugin_code'];
$paymentPlugins = $this->pluginManager->getEnabledPaymentPlugins();
foreach ($paymentPlugins as $plugin) {
if ($plugin->getPluginCode() === $pluginCode) {
$plugin->setConfig($this->config);
$this->payment = $plugin;
return;
}
if (!isset($paymentMethods[$this->method])) {
throw new ApiException(__('Payment method is not available'));
}
$pluginCode = $paymentMethods[$this->method]['plugin_code'] ?? null;
if (!$pluginCode) {
throw new ApiException(__('Payment method is not available'));
}
$paymentPlugins = $this->pluginManager->getEnabledPaymentPlugins();
foreach ($paymentPlugins as $plugin) {
if ($plugin->getPluginCode() === $pluginCode) {
$plugin->setConfig($this->config);
$this->payment = $plugin;
return;
}
}
$this->payment = new $this->class($this->config);
throw new ApiException(__('Payment method is not available'));
}
public function notify($params)