mirror of
https://gitee.com/technical-laohu/mpay_v2_webman.git
synced 2026-03-25 04:14:26 +08:00
丰富基础代码
This commit is contained in:
@@ -41,6 +41,30 @@ class BaseController
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一分页返回结构
|
||||
*
|
||||
* @param mixed $paginator Laravel/Eloquent paginator
|
||||
*/
|
||||
protected function page(mixed $paginator): Response
|
||||
{
|
||||
if (!is_object($paginator) || !method_exists($paginator, 'items')) {
|
||||
return $this->success([
|
||||
'list' => [],
|
||||
'total' => 0,
|
||||
'page' => 1,
|
||||
'size' => 10,
|
||||
]);
|
||||
}
|
||||
|
||||
return $this->success([
|
||||
'list' => $paginator->items(),
|
||||
'total' => $paginator->total(),
|
||||
'page' => $paginator->currentPage(),
|
||||
'size' => $paginator->perPage(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前登录用户的 token 载荷
|
||||
*
|
||||
|
||||
@@ -62,11 +62,8 @@ abstract class BaseRepository
|
||||
{
|
||||
$query = $this->model->newQuery();
|
||||
|
||||
foreach ($where as $field => $value) {
|
||||
if ($value === null || $value === '') {
|
||||
continue;
|
||||
}
|
||||
$query->where($field, $value);
|
||||
if (!empty($where)) {
|
||||
$query->where($where);
|
||||
}
|
||||
|
||||
return $query->paginate($pageSize, $columns, 'page', $page);
|
||||
|
||||
177
app/http/admin/controller/MerchantAppController.php
Normal file
177
app/http/admin/controller/MerchantAppController.php
Normal file
@@ -0,0 +1,177 @@
|
||||
<?php
|
||||
|
||||
namespace app\http\admin\controller;
|
||||
|
||||
use app\common\base\BaseController;
|
||||
use app\repositories\MerchantAppRepository;
|
||||
use app\repositories\MerchantRepository;
|
||||
use support\Request;
|
||||
|
||||
/**
|
||||
* 商户应用管理
|
||||
*/
|
||||
class MerchantAppController extends BaseController
|
||||
{
|
||||
public function __construct(
|
||||
protected MerchantAppRepository $merchantAppRepository,
|
||||
protected MerchantRepository $merchantRepository,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /adminapi/merchant-app/list
|
||||
*/
|
||||
public function list(Request $request)
|
||||
{
|
||||
$page = (int)$request->get('page', 1);
|
||||
$pageSize = (int)$request->get('page_size', 10);
|
||||
|
||||
$filters = [
|
||||
'merchant_id' => (int)$request->get('merchant_id', 0),
|
||||
'status' => $request->get('status', ''),
|
||||
'app_id' => trim((string)$request->get('app_id', '')),
|
||||
'app_name' => trim((string)$request->get('app_name', '')),
|
||||
'api_type' => trim((string)$request->get('api_type', '')),
|
||||
];
|
||||
|
||||
$paginator = $this->merchantAppRepository->searchPaginate($filters, $page, $pageSize);
|
||||
return $this->page($paginator);
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /adminapi/merchant-app/detail?id=1
|
||||
*/
|
||||
public function detail(Request $request)
|
||||
{
|
||||
$id = (int)$request->get('id', 0);
|
||||
if ($id <= 0) {
|
||||
return $this->fail('应用ID不能为空', 400);
|
||||
}
|
||||
|
||||
$row = $this->merchantAppRepository->find($id);
|
||||
if (!$row) {
|
||||
return $this->fail('应用不存在', 404);
|
||||
}
|
||||
|
||||
return $this->success($row);
|
||||
}
|
||||
|
||||
/**
|
||||
* POST /adminapi/merchant-app/save
|
||||
*/
|
||||
public function save(Request $request)
|
||||
{
|
||||
$data = $request->post();
|
||||
$id = (int)($data['id'] ?? 0);
|
||||
|
||||
$merchantId = (int)($data['merchant_id'] ?? 0);
|
||||
$apiType = trim((string)($data['api_type'] ?? 'epay'));
|
||||
$appId = trim((string)($data['app_id'] ?? ''));
|
||||
$appName = trim((string)($data['app_name'] ?? ''));
|
||||
$status = (int)($data['status'] ?? 1);
|
||||
|
||||
if ($merchantId <= 0 || $appId === '' || $appName === '') {
|
||||
return $this->fail('商户、应用ID、应用名称不能为空', 400);
|
||||
}
|
||||
|
||||
$merchant = $this->merchantRepository->find($merchantId);
|
||||
if (!$merchant) {
|
||||
return $this->fail('商户不存在', 404);
|
||||
}
|
||||
|
||||
if (!in_array($apiType, ['openapi', 'epay', 'custom', 'default'], true)) {
|
||||
return $this->fail('api_type 不合法', 400);
|
||||
}
|
||||
|
||||
if ($id > 0) {
|
||||
$row = $this->merchantAppRepository->find($id);
|
||||
if (!$row) {
|
||||
return $this->fail('应用不存在', 404);
|
||||
}
|
||||
|
||||
// app_id 变更需校验唯一
|
||||
if ($row->app_id !== $appId) {
|
||||
$exists = $this->merchantAppRepository->findAnyByAppId($appId);
|
||||
if ($exists) {
|
||||
return $this->fail('应用ID已存在', 400);
|
||||
}
|
||||
}
|
||||
|
||||
$update = [
|
||||
'merchant_id' => $merchantId,
|
||||
'api_type' => $apiType,
|
||||
'app_id' => $appId,
|
||||
'app_name' => $appName,
|
||||
'status' => $status,
|
||||
];
|
||||
|
||||
// 可选:前端传入 app_secret 才更新
|
||||
if (!empty($data['app_secret'])) {
|
||||
$update['app_secret'] = (string)$data['app_secret'];
|
||||
}
|
||||
|
||||
$this->merchantAppRepository->updateById($id, $update);
|
||||
} else {
|
||||
$exists = $this->merchantAppRepository->findAnyByAppId($appId);
|
||||
if ($exists) {
|
||||
return $this->fail('应用ID已存在', 400);
|
||||
}
|
||||
|
||||
$secret = !empty($data['app_secret']) ? (string)$data['app_secret'] : $this->generateSecret();
|
||||
$this->merchantAppRepository->create([
|
||||
'merchant_id' => $merchantId,
|
||||
'api_type' => $apiType,
|
||||
'app_id' => $appId,
|
||||
'app_secret' => $secret,
|
||||
'app_name' => $appName,
|
||||
'status' => $status,
|
||||
]);
|
||||
}
|
||||
|
||||
return $this->success(null, '保存成功');
|
||||
}
|
||||
|
||||
/**
|
||||
* POST /adminapi/merchant-app/reset-secret
|
||||
*/
|
||||
public function resetSecret(Request $request)
|
||||
{
|
||||
$id = (int)$request->post('id', 0);
|
||||
if ($id <= 0) {
|
||||
return $this->fail('应用ID不能为空', 400);
|
||||
}
|
||||
|
||||
$row = $this->merchantAppRepository->find($id);
|
||||
if (!$row) {
|
||||
return $this->fail('应用不存在', 404);
|
||||
}
|
||||
|
||||
$secret = $this->generateSecret();
|
||||
$this->merchantAppRepository->updateById($id, ['app_secret' => $secret]);
|
||||
|
||||
return $this->success(['app_secret' => $secret], '重置成功');
|
||||
}
|
||||
|
||||
/**
|
||||
* POST /adminapi/merchant-app/toggle
|
||||
*/
|
||||
public function toggle(Request $request)
|
||||
{
|
||||
$id = (int)$request->post('id', 0);
|
||||
$status = $request->post('status', null);
|
||||
|
||||
if ($id <= 0 || $status === null) {
|
||||
return $this->fail('参数错误', 400);
|
||||
}
|
||||
|
||||
$ok = $this->merchantAppRepository->updateById($id, ['status' => (int)$status]);
|
||||
return $ok ? $this->success(null, '操作成功') : $this->fail('操作失败', 500);
|
||||
}
|
||||
|
||||
private function generateSecret(): string
|
||||
{
|
||||
$raw = random_bytes(24);
|
||||
return rtrim(strtr(base64_encode($raw), '+/', '-_'), '=');
|
||||
}
|
||||
}
|
||||
|
||||
116
app/http/admin/controller/MerchantController.php
Normal file
116
app/http/admin/controller/MerchantController.php
Normal file
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
namespace app\http\admin\controller;
|
||||
|
||||
use app\common\base\BaseController;
|
||||
use app\repositories\MerchantRepository;
|
||||
use support\Request;
|
||||
|
||||
/**
|
||||
* 商户管理
|
||||
*/
|
||||
class MerchantController extends BaseController
|
||||
{
|
||||
public function __construct(
|
||||
protected MerchantRepository $merchantRepository,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /adminapi/merchant/list
|
||||
*/
|
||||
public function list(Request $request)
|
||||
{
|
||||
$page = (int)$request->get('page', 1);
|
||||
$pageSize = (int)$request->get('page_size', 10);
|
||||
|
||||
$filters = [
|
||||
'status' => $request->get('status', ''),
|
||||
'merchant_no' => trim((string)$request->get('merchant_no', '')),
|
||||
'merchant_name' => trim((string)$request->get('merchant_name', '')),
|
||||
];
|
||||
|
||||
$paginator = $this->merchantRepository->searchPaginate($filters, $page, $pageSize);
|
||||
return $this->page($paginator);
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /adminapi/merchant/detail?id=1
|
||||
*/
|
||||
public function detail(Request $request)
|
||||
{
|
||||
$id = (int)$request->get('id', 0);
|
||||
if ($id <= 0) {
|
||||
return $this->fail('商户ID不能为空', 400);
|
||||
}
|
||||
|
||||
$row = $this->merchantRepository->find($id);
|
||||
if (!$row) {
|
||||
return $this->fail('商户不存在', 404);
|
||||
}
|
||||
|
||||
return $this->success($row);
|
||||
}
|
||||
|
||||
/**
|
||||
* POST /adminapi/merchant/save
|
||||
*/
|
||||
public function save(Request $request)
|
||||
{
|
||||
$data = $request->post();
|
||||
$id = (int)($data['id'] ?? 0);
|
||||
|
||||
$merchantNo = trim((string)($data['merchant_no'] ?? ''));
|
||||
$merchantName = trim((string)($data['merchant_name'] ?? ''));
|
||||
$fundsMode = trim((string)($data['funds_mode'] ?? 'direct'));
|
||||
$status = (int)($data['status'] ?? 1);
|
||||
|
||||
if ($merchantNo === '' || $merchantName === '') {
|
||||
return $this->fail('商户号与商户名称不能为空', 400);
|
||||
}
|
||||
|
||||
if (!in_array($fundsMode, ['direct', 'wallet', 'hybrid'], true)) {
|
||||
return $this->fail('资金模式不合法', 400);
|
||||
}
|
||||
|
||||
if ($id > 0) {
|
||||
$this->merchantRepository->updateById($id, [
|
||||
'merchant_no' => $merchantNo,
|
||||
'merchant_name' => $merchantName,
|
||||
'funds_mode' => $fundsMode,
|
||||
'status' => $status,
|
||||
]);
|
||||
} else {
|
||||
$exists = $this->merchantRepository->findByMerchantNo($merchantNo);
|
||||
if ($exists) {
|
||||
return $this->fail('商户号已存在', 400);
|
||||
}
|
||||
|
||||
$this->merchantRepository->create([
|
||||
'merchant_no' => $merchantNo,
|
||||
'merchant_name' => $merchantName,
|
||||
'funds_mode' => $fundsMode,
|
||||
'status' => $status,
|
||||
]);
|
||||
}
|
||||
|
||||
return $this->success(null, '保存成功');
|
||||
}
|
||||
|
||||
/**
|
||||
* POST /adminapi/merchant/toggle
|
||||
*/
|
||||
public function toggle(Request $request)
|
||||
{
|
||||
$id = (int)$request->post('id', 0);
|
||||
$status = $request->post('status', null);
|
||||
|
||||
if ($id <= 0 || $status === null) {
|
||||
return $this->fail('参数错误', 400);
|
||||
}
|
||||
|
||||
$ok = $this->merchantRepository->updateById($id, ['status' => (int)$status]);
|
||||
return $ok ? $this->success(null, '操作成功') : $this->fail('操作失败', 500);
|
||||
}
|
||||
}
|
||||
|
||||
100
app/http/admin/controller/OrderController.php
Normal file
100
app/http/admin/controller/OrderController.php
Normal file
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
namespace app\http\admin\controller;
|
||||
|
||||
use app\common\base\BaseController;
|
||||
use app\repositories\PaymentMethodRepository;
|
||||
use app\repositories\PaymentOrderRepository;
|
||||
use app\services\PayOrderService;
|
||||
use support\Request;
|
||||
|
||||
/**
|
||||
* 订单管理
|
||||
*/
|
||||
class OrderController extends BaseController
|
||||
{
|
||||
public function __construct(
|
||||
protected PaymentOrderRepository $orderRepository,
|
||||
protected PaymentMethodRepository $methodRepository,
|
||||
protected PayOrderService $payOrderService,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /adminapi/order/list
|
||||
*/
|
||||
public function list(Request $request)
|
||||
{
|
||||
$page = (int)$request->get('page', 1);
|
||||
$pageSize = (int)$request->get('page_size', 10);
|
||||
|
||||
$methodCode = trim((string)$request->get('method_code', ''));
|
||||
$methodId = 0;
|
||||
if ($methodCode !== '') {
|
||||
$method = $this->methodRepository->findAnyByCode($methodCode);
|
||||
$methodId = $method ? (int)$method->id : 0;
|
||||
}
|
||||
|
||||
$filters = [
|
||||
'merchant_id' => (int)$request->get('merchant_id', 0),
|
||||
'merchant_app_id' => (int)$request->get('merchant_app_id', 0),
|
||||
'method_id' => $methodId,
|
||||
'channel_id' => (int)$request->get('channel_id', 0),
|
||||
'status' => $request->get('status', ''),
|
||||
'order_id' => trim((string)$request->get('order_id', '')),
|
||||
'mch_order_no' => trim((string)$request->get('mch_order_no', '')),
|
||||
'created_from' => trim((string)$request->get('created_from', '')),
|
||||
'created_to' => trim((string)$request->get('created_to', '')),
|
||||
];
|
||||
|
||||
$paginator = $this->orderRepository->searchPaginate($filters, $page, $pageSize);
|
||||
return $this->page($paginator);
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /adminapi/order/detail?id=1 或 order_id=P...
|
||||
*/
|
||||
public function detail(Request $request)
|
||||
{
|
||||
$id = (int)$request->get('id', 0);
|
||||
$orderId = trim((string)$request->get('order_id', ''));
|
||||
|
||||
if ($id > 0) {
|
||||
$row = $this->orderRepository->find($id);
|
||||
} elseif ($orderId !== '') {
|
||||
$row = $this->orderRepository->findByOrderId($orderId);
|
||||
} else {
|
||||
return $this->fail('参数错误', 400);
|
||||
}
|
||||
|
||||
if (!$row) {
|
||||
return $this->fail('订单不存在', 404);
|
||||
}
|
||||
|
||||
return $this->success($row);
|
||||
}
|
||||
|
||||
/**
|
||||
* POST /adminapi/order/refund
|
||||
* - order_id: 系统订单号
|
||||
* - refund_amount: 退款金额
|
||||
*/
|
||||
public function refund(Request $request)
|
||||
{
|
||||
$orderId = trim((string)$request->post('order_id', ''));
|
||||
$refundAmount = (float)$request->post('refund_amount', 0);
|
||||
$refundReason = trim((string)$request->post('refund_reason', ''));
|
||||
|
||||
try {
|
||||
$result = $this->payOrderService->refundOrder([
|
||||
'order_id' => $orderId,
|
||||
'refund_amount' => $refundAmount,
|
||||
'refund_reason' => $refundReason,
|
||||
]);
|
||||
return $this->success($result, '退款发起成功');
|
||||
} catch (\Throwable $e) {
|
||||
return $this->fail($e->getMessage(), 400);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
96
app/http/admin/controller/PayMethodController.php
Normal file
96
app/http/admin/controller/PayMethodController.php
Normal file
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
namespace app\http\admin\controller;
|
||||
|
||||
use app\common\base\BaseController;
|
||||
use app\repositories\PaymentMethodRepository;
|
||||
use support\Request;
|
||||
|
||||
/**
|
||||
* 支付方式管理
|
||||
*/
|
||||
class PayMethodController extends BaseController
|
||||
{
|
||||
public function __construct(
|
||||
protected PaymentMethodRepository $methodRepository,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /adminapi/pay-method/list
|
||||
*/
|
||||
public function list(Request $request)
|
||||
{
|
||||
$page = (int)$request->get('page', 1);
|
||||
$pageSize = (int)$request->get('page_size', 10);
|
||||
|
||||
$filters = [
|
||||
'status' => $request->get('status', ''),
|
||||
'method_code' => trim((string)$request->get('method_code', '')),
|
||||
'method_name' => trim((string)$request->get('method_name', '')),
|
||||
];
|
||||
|
||||
$paginator = $this->methodRepository->searchPaginate($filters, $page, $pageSize);
|
||||
return $this->page($paginator);
|
||||
}
|
||||
|
||||
/**
|
||||
* POST /adminapi/pay-method/save
|
||||
*/
|
||||
public function save(Request $request)
|
||||
{
|
||||
$data = $request->post();
|
||||
$id = (int)($data['id'] ?? 0);
|
||||
|
||||
$code = trim((string)($data['method_code'] ?? ''));
|
||||
$name = trim((string)($data['method_name'] ?? ''));
|
||||
$icon = trim((string)($data['icon'] ?? ''));
|
||||
$sort = (int)($data['sort'] ?? 0);
|
||||
$status = (int)($data['status'] ?? 1);
|
||||
|
||||
if ($code === '' || $name === '') {
|
||||
return $this->fail('支付方式编码与名称不能为空', 400);
|
||||
}
|
||||
|
||||
if ($id > 0) {
|
||||
$this->methodRepository->updateById($id, [
|
||||
'method_code' => $code,
|
||||
'method_name' => $name,
|
||||
'icon' => $icon,
|
||||
'sort' => $sort,
|
||||
'status' => $status,
|
||||
]);
|
||||
} else {
|
||||
$exists = $this->methodRepository->findAnyByCode($code);
|
||||
if ($exists) {
|
||||
return $this->fail('支付方式编码已存在', 400);
|
||||
}
|
||||
$this->methodRepository->create([
|
||||
'method_code' => $code,
|
||||
'method_name' => $name,
|
||||
'icon' => $icon,
|
||||
'sort' => $sort,
|
||||
'status' => $status,
|
||||
]);
|
||||
}
|
||||
|
||||
return $this->success(null, '保存成功');
|
||||
}
|
||||
|
||||
/**
|
||||
* POST /adminapi/pay-method/toggle
|
||||
*/
|
||||
public function toggle(Request $request)
|
||||
{
|
||||
$id = (int)$request->post('id', 0);
|
||||
$status = $request->post('status', null);
|
||||
|
||||
if ($id <= 0 || $status === null) {
|
||||
return $this->fail('参数错误', 400);
|
||||
}
|
||||
|
||||
$ok = $this->methodRepository->updateById($id, ['status' => (int)$status]);
|
||||
return $ok ? $this->success(null, '操作成功') : $this->fail('操作失败', 500);
|
||||
}
|
||||
}
|
||||
|
||||
85
app/http/admin/controller/PayPluginController.php
Normal file
85
app/http/admin/controller/PayPluginController.php
Normal file
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
namespace app\http\admin\controller;
|
||||
|
||||
use app\common\base\BaseController;
|
||||
use app\repositories\PaymentPluginRepository;
|
||||
use support\Request;
|
||||
|
||||
/**
|
||||
* 插件注册表管理(ma_pay_plugin)
|
||||
*
|
||||
* 注意:与 /channel/plugin/* 的“插件能力读取(schema/products)”不同,这里负责维护插件注册表本身。
|
||||
*/
|
||||
class PayPluginController extends BaseController
|
||||
{
|
||||
public function __construct(
|
||||
protected PaymentPluginRepository $pluginRepository,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /adminapi/pay-plugin/list
|
||||
*/
|
||||
public function list(Request $request)
|
||||
{
|
||||
$page = (int)$request->get('page', 1);
|
||||
$pageSize = (int)$request->get('page_size', 10);
|
||||
|
||||
$filters = [
|
||||
'status' => $request->get('status', ''),
|
||||
'plugin_code' => trim((string)$request->get('plugin_code', '')),
|
||||
'plugin_name' => trim((string)$request->get('plugin_name', '')),
|
||||
];
|
||||
|
||||
$paginator = $this->pluginRepository->searchPaginate($filters, $page, $pageSize);
|
||||
return $this->page($paginator);
|
||||
}
|
||||
|
||||
/**
|
||||
* POST /adminapi/pay-plugin/save
|
||||
*/
|
||||
public function save(Request $request)
|
||||
{
|
||||
$data = $request->post();
|
||||
|
||||
$pluginCode = trim((string)($data['plugin_code'] ?? ''));
|
||||
$pluginName = trim((string)($data['plugin_name'] ?? ''));
|
||||
$className = trim((string)($data['class_name'] ?? ''));
|
||||
$status = (int)($data['status'] ?? 1);
|
||||
|
||||
if ($pluginCode === '' || $pluginName === '') {
|
||||
return $this->fail('插件编码与名称不能为空', 400);
|
||||
}
|
||||
|
||||
if ($className === '') {
|
||||
// 默认约定类名
|
||||
$className = 'app\\common\\payment\\' . ucfirst($pluginCode) . 'Payment';
|
||||
}
|
||||
|
||||
$this->pluginRepository->upsertByCode($pluginCode, [
|
||||
'plugin_name' => $pluginName,
|
||||
'class_name' => $className,
|
||||
'status' => $status,
|
||||
]);
|
||||
|
||||
return $this->success(null, '保存成功');
|
||||
}
|
||||
|
||||
/**
|
||||
* POST /adminapi/pay-plugin/toggle
|
||||
*/
|
||||
public function toggle(Request $request)
|
||||
{
|
||||
$pluginCode = trim((string)$request->post('plugin_code', ''));
|
||||
$status = $request->post('status', null);
|
||||
|
||||
if ($pluginCode === '' || $status === null) {
|
||||
return $this->fail('参数错误', 400);
|
||||
}
|
||||
|
||||
$ok = $this->pluginRepository->updateStatus($pluginCode, (int)$status);
|
||||
return $ok ? $this->success(null, '操作成功') : $this->fail('操作失败', 500);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,5 +37,43 @@ class MerchantAppRepository extends BaseRepository
|
||||
->where('status', 1)
|
||||
->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* 后台按 app_id 查询(不过滤状态)
|
||||
*/
|
||||
public function findAnyByAppId(string $appId): ?MerchantApp
|
||||
{
|
||||
return $this->model->newQuery()
|
||||
->where('app_id', $appId)
|
||||
->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* 后台列表:支持筛选与模糊搜索
|
||||
*/
|
||||
public function searchPaginate(array $filters = [], int $page = 1, int $pageSize = 10)
|
||||
{
|
||||
$query = $this->model->newQuery();
|
||||
|
||||
if (!empty($filters['merchant_id'])) {
|
||||
$query->where('merchant_id', (int)$filters['merchant_id']);
|
||||
}
|
||||
if (($filters['status'] ?? '') !== '' && $filters['status'] !== null) {
|
||||
$query->where('status', (int)$filters['status']);
|
||||
}
|
||||
if (!empty($filters['app_id'])) {
|
||||
$query->where('app_id', 'like', '%' . $filters['app_id'] . '%');
|
||||
}
|
||||
if (!empty($filters['app_name'])) {
|
||||
$query->where('app_name', 'like', '%' . $filters['app_name'] . '%');
|
||||
}
|
||||
if (!empty($filters['api_type'])) {
|
||||
$query->where('api_type', (string)$filters['api_type']);
|
||||
}
|
||||
|
||||
$query->orderByDesc('id');
|
||||
|
||||
return $query->paginate($pageSize, ['*'], 'page', $page);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,5 +24,27 @@ class MerchantRepository extends BaseRepository
|
||||
->where('merchant_no', $merchantNo)
|
||||
->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* 后台列表:支持模糊搜索
|
||||
*/
|
||||
public function searchPaginate(array $filters = [], int $page = 1, int $pageSize = 10)
|
||||
{
|
||||
$query = $this->model->newQuery();
|
||||
|
||||
if (($filters['status'] ?? '') !== '' && $filters['status'] !== null) {
|
||||
$query->where('status', (int)$filters['status']);
|
||||
}
|
||||
if (!empty($filters['merchant_no'])) {
|
||||
$query->where('merchant_no', 'like', '%' . $filters['merchant_no'] . '%');
|
||||
}
|
||||
if (!empty($filters['merchant_name'])) {
|
||||
$query->where('merchant_name', 'like', '%' . $filters['merchant_name'] . '%');
|
||||
}
|
||||
|
||||
$query->orderByDesc('id');
|
||||
|
||||
return $query->paginate($pageSize, ['*'], 'page', $page);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,4 +31,36 @@ class PaymentMethodRepository extends BaseRepository
|
||||
->where('status', 1)
|
||||
->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* 后台按 code 查询(不过滤状态)
|
||||
*/
|
||||
public function findAnyByCode(string $methodCode): ?PaymentMethod
|
||||
{
|
||||
return $this->model->newQuery()
|
||||
->where('method_code', $methodCode)
|
||||
->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* 后台列表:支持筛选与排序
|
||||
*/
|
||||
public function searchPaginate(array $filters = [], int $page = 1, int $pageSize = 10)
|
||||
{
|
||||
$query = $this->model->newQuery();
|
||||
|
||||
if (($filters['status'] ?? '') !== '' && $filters['status'] !== null) {
|
||||
$query->where('status', (int)$filters['status']);
|
||||
}
|
||||
if (!empty($filters['method_code'])) {
|
||||
$query->where('method_code', 'like', '%' . $filters['method_code'] . '%');
|
||||
}
|
||||
if (!empty($filters['method_name'])) {
|
||||
$query->where('method_name', 'like', '%' . $filters['method_name'] . '%');
|
||||
}
|
||||
|
||||
$query->orderBy('sort', 'asc')->orderByDesc('id');
|
||||
|
||||
return $query->paginate($pageSize, ['*'], 'page', $page);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,4 +53,43 @@ class PaymentOrderRepository extends BaseRepository
|
||||
}
|
||||
return $this->updateById($order->id, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 后台订单列表:支持筛选与模糊搜索
|
||||
*/
|
||||
public function searchPaginate(array $filters = [], int $page = 1, int $pageSize = 10)
|
||||
{
|
||||
$query = $this->model->newQuery();
|
||||
|
||||
if (!empty($filters['merchant_id'])) {
|
||||
$query->where('merchant_id', (int)$filters['merchant_id']);
|
||||
}
|
||||
if (!empty($filters['merchant_app_id'])) {
|
||||
$query->where('merchant_app_id', (int)$filters['merchant_app_id']);
|
||||
}
|
||||
if (!empty($filters['method_id'])) {
|
||||
$query->where('method_id', (int)$filters['method_id']);
|
||||
}
|
||||
if (!empty($filters['channel_id'])) {
|
||||
$query->where('channel_id', (int)$filters['channel_id']);
|
||||
}
|
||||
if (($filters['status'] ?? '') !== '' && $filters['status'] !== null) {
|
||||
$query->where('status', (int)$filters['status']);
|
||||
}
|
||||
if (!empty($filters['order_id'])) {
|
||||
$query->where('order_id', 'like', '%' . $filters['order_id'] . '%');
|
||||
}
|
||||
if (!empty($filters['mch_order_no'])) {
|
||||
$query->where('mch_order_no', 'like', '%' . $filters['mch_order_no'] . '%');
|
||||
}
|
||||
if (!empty($filters['created_from'])) {
|
||||
$query->where('created_at', '>=', $filters['created_from']);
|
||||
}
|
||||
if (!empty($filters['created_to'])) {
|
||||
$query->where('created_at', '<=', $filters['created_to']);
|
||||
}
|
||||
|
||||
$query->orderByDesc('id');
|
||||
return $query->paginate($pageSize, ['*'], 'page', $page);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,4 +29,61 @@ class PaymentPluginRepository extends BaseRepository
|
||||
->where('status', 1)
|
||||
->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* 后台按编码查询(不过滤状态)
|
||||
*/
|
||||
public function findByCode(string $pluginCode): ?PaymentPlugin
|
||||
{
|
||||
return $this->model->newQuery()
|
||||
->where('plugin_code', $pluginCode)
|
||||
->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* 后台列表:支持筛选与模糊搜索
|
||||
*/
|
||||
public function searchPaginate(array $filters = [], int $page = 1, int $pageSize = 10)
|
||||
{
|
||||
$query = $this->model->newQuery();
|
||||
|
||||
if (($filters['status'] ?? '') !== '' && $filters['status'] !== null) {
|
||||
$query->where('status', (int)$filters['status']);
|
||||
}
|
||||
if (!empty($filters['plugin_code'])) {
|
||||
$query->where('plugin_code', 'like', '%' . $filters['plugin_code'] . '%');
|
||||
}
|
||||
if (!empty($filters['plugin_name'])) {
|
||||
$query->where('plugin_name', 'like', '%' . $filters['plugin_name'] . '%');
|
||||
}
|
||||
|
||||
$query->orderByDesc('created_at');
|
||||
return $query->paginate($pageSize, ['*'], 'page', $page);
|
||||
}
|
||||
|
||||
/**
|
||||
* 后台保存:存在则更新,不存在则创建
|
||||
*/
|
||||
public function upsertByCode(string $pluginCode, array $data): PaymentPlugin
|
||||
{
|
||||
$row = $this->findByCode($pluginCode);
|
||||
if ($row) {
|
||||
$this->model->newQuery()
|
||||
->where('plugin_code', $pluginCode)
|
||||
->update($data);
|
||||
return $this->findByCode($pluginCode) ?: $row;
|
||||
}
|
||||
|
||||
$data['plugin_code'] = $pluginCode;
|
||||
/** @var PaymentPlugin $created */
|
||||
$created = $this->create($data);
|
||||
return $created;
|
||||
}
|
||||
|
||||
public function updateStatus(string $pluginCode, int $status): bool
|
||||
{
|
||||
return (bool)$this->model->newQuery()
|
||||
->where('plugin_code', $pluginCode)
|
||||
->update(['status' => $status]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,11 @@ use app\http\admin\controller\MenuController;
|
||||
use app\http\admin\controller\SystemController;
|
||||
use app\http\admin\controller\ChannelController;
|
||||
use app\http\admin\controller\PluginController;
|
||||
use app\http\admin\controller\MerchantController;
|
||||
use app\http\admin\controller\MerchantAppController;
|
||||
use app\http\admin\controller\PayMethodController;
|
||||
use app\http\admin\controller\PayPluginController;
|
||||
use app\http\admin\controller\OrderController;
|
||||
use app\common\middleware\Cors;
|
||||
use app\http\admin\middleware\AuthMiddleware;
|
||||
|
||||
@@ -47,5 +52,33 @@ Route::group('/adminapi', function () {
|
||||
Route::get('/channel/plugins', [PluginController::class, 'plugins'])->name('plugins')->setParams(['real_name' => '获取插件列表']);
|
||||
Route::get('/channel/plugin/config-schema', [PluginController::class, 'configSchema'])->name('configSchema')->setParams(['real_name' => '获取插件配置schema']);
|
||||
Route::get('/channel/plugin/products', [PluginController::class, 'products'])->name('products')->setParams(['real_name' => '获取插件产品列表']);
|
||||
|
||||
// 商户管理
|
||||
Route::get('/merchant/list', [MerchantController::class, 'list'])->name('merchantList')->setParams(['real_name' => '商户列表']);
|
||||
Route::get('/merchant/detail', [MerchantController::class, 'detail'])->name('merchantDetail')->setParams(['real_name' => '商户详情']);
|
||||
Route::post('/merchant/save', [MerchantController::class, 'save'])->name('merchantSave')->setParams(['real_name' => '保存商户']);
|
||||
Route::post('/merchant/toggle', [MerchantController::class, 'toggle'])->name('merchantToggle')->setParams(['real_name' => '启用禁用商户']);
|
||||
|
||||
// 商户应用管理
|
||||
Route::get('/merchant-app/list', [MerchantAppController::class, 'list'])->name('merchantAppList')->setParams(['real_name' => '商户应用列表']);
|
||||
Route::get('/merchant-app/detail', [MerchantAppController::class, 'detail'])->name('merchantAppDetail')->setParams(['real_name' => '商户应用详情']);
|
||||
Route::post('/merchant-app/save', [MerchantAppController::class, 'save'])->name('merchantAppSave')->setParams(['real_name' => '保存商户应用']);
|
||||
Route::post('/merchant-app/reset-secret', [MerchantAppController::class, 'resetSecret'])->name('merchantAppResetSecret')->setParams(['real_name' => '重置应用密钥']);
|
||||
Route::post('/merchant-app/toggle', [MerchantAppController::class, 'toggle'])->name('merchantAppToggle')->setParams(['real_name' => '启用禁用商户应用']);
|
||||
|
||||
// 支付方式管理
|
||||
Route::get('/pay-method/list', [PayMethodController::class, 'list'])->name('payMethodList')->setParams(['real_name' => '支付方式列表']);
|
||||
Route::post('/pay-method/save', [PayMethodController::class, 'save'])->name('payMethodSave')->setParams(['real_name' => '保存支付方式']);
|
||||
Route::post('/pay-method/toggle', [PayMethodController::class, 'toggle'])->name('payMethodToggle')->setParams(['real_name' => '启用禁用支付方式']);
|
||||
|
||||
// 插件注册表管理
|
||||
Route::get('/pay-plugin/list', [PayPluginController::class, 'list'])->name('payPluginList')->setParams(['real_name' => '支付插件注册表列表']);
|
||||
Route::post('/pay-plugin/save', [PayPluginController::class, 'save'])->name('payPluginSave')->setParams(['real_name' => '保存支付插件注册表']);
|
||||
Route::post('/pay-plugin/toggle', [PayPluginController::class, 'toggle'])->name('payPluginToggle')->setParams(['real_name' => '启用禁用支付插件']);
|
||||
|
||||
// 订单管理
|
||||
Route::get('/order/list', [OrderController::class, 'list'])->name('orderList')->setParams(['real_name' => '订单列表']);
|
||||
Route::get('/order/detail', [OrderController::class, 'detail'])->name('orderDetail')->setParams(['real_name' => '订单详情']);
|
||||
Route::post('/order/refund', [OrderController::class, 'refund'])->name('orderRefund')->setParams(['real_name' => '订单退款']);
|
||||
})->middleware([AuthMiddleware::class]);
|
||||
})->middleware([Cors::class]);
|
||||
@@ -39,7 +39,8 @@
|
||||
"workerman/crontab": "^1.0",
|
||||
"webman/redis-queue": "^2.1",
|
||||
"firebase/php-jwt": "^7.0",
|
||||
"webman/validation": "^2.2"
|
||||
"webman/validation": "^2.2",
|
||||
"illuminate/pagination": "^12.53"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-event": "For better performance. "
|
||||
|
||||
52
composer.lock
generated
52
composer.lock
generated
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "c9b20b999efb47e639901ded2ade0fdb",
|
||||
"content-hash": "49b81bfe43345cf72dbd33c88720b5a2",
|
||||
"packages": [
|
||||
{
|
||||
"name": "brick/math",
|
||||
@@ -1547,6 +1547,56 @@
|
||||
},
|
||||
"time": "2024-07-23T16:31:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "illuminate/pagination",
|
||||
"version": "v12.53.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/illuminate/pagination.git",
|
||||
"reference": "87e7e3e7b02d6809b1bcd41782e1ca2c6d2a413b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/illuminate/pagination/zipball/87e7e3e7b02d6809b1bcd41782e1ca2c6d2a413b",
|
||||
"reference": "87e7e3e7b02d6809b1bcd41782e1ca2c6d2a413b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-filter": "*",
|
||||
"illuminate/collections": "^12.0",
|
||||
"illuminate/contracts": "^12.0",
|
||||
"illuminate/support": "^12.0",
|
||||
"php": "^8.2"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "12.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Illuminate\\Pagination\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Taylor Otwell",
|
||||
"email": "taylor@laravel.com"
|
||||
}
|
||||
],
|
||||
"description": "The Illuminate Pagination package.",
|
||||
"homepage": "https://laravel.com",
|
||||
"support": {
|
||||
"issues": "https://github.com/laravel/framework/issues",
|
||||
"source": "https://github.com/laravel/framework"
|
||||
},
|
||||
"time": "2025-11-16T14:36:17+00:00"
|
||||
},
|
||||
{
|
||||
"name": "illuminate/pipeline",
|
||||
"version": "v12.49.0",
|
||||
|
||||
@@ -17,6 +17,12 @@ use Webman\Route;
|
||||
use support\Response;
|
||||
use support\Request;
|
||||
|
||||
// 管理后台路由
|
||||
require_once base_path() . '/app/routes/admin.php';
|
||||
|
||||
// API 路由
|
||||
require_once base_path() . '/app/routes/api.php';
|
||||
|
||||
// 匹配所有options路由(CORS 预检请求)
|
||||
Route::options('[{path:.+}]', function (Request $request){
|
||||
$response = response('', 204);
|
||||
@@ -27,13 +33,6 @@ Route::options('[{path:.+}]', function (Request $request){
|
||||
'Access-Control-Allow-Headers' => $request->header('access-control-request-headers', '*'),
|
||||
]);
|
||||
});
|
||||
|
||||
// 管理后台路由
|
||||
require_once base_path() . '/app/routes/admin.php';
|
||||
|
||||
// API 路由
|
||||
require_once base_path() . '/app/routes/api.php';
|
||||
|
||||
/**
|
||||
* 关闭默认路由
|
||||
*/
|
||||
|
||||
51
database/dev_seed.sql
Normal file
51
database/dev_seed.sql
Normal file
@@ -0,0 +1,51 @@
|
||||
-- 开发环境初始化数据(可重复执行)
|
||||
SET NAMES utf8mb4;
|
||||
|
||||
-- 1) 管理员(若已有则跳过)
|
||||
INSERT INTO `ma_admin` (`user_name`, `password`, `nick_name`, `status`, `created_at`)
|
||||
VALUES ('admin', NULL, '超级管理员', 1, NOW())
|
||||
ON DUPLICATE KEY UPDATE
|
||||
`nick_name` = VALUES(`nick_name`),
|
||||
`status` = VALUES(`status`);
|
||||
|
||||
-- 2) 商户
|
||||
INSERT INTO `ma_merchant` (`merchant_no`, `merchant_name`, `funds_mode`, `status`, `created_at`, `updated_at`)
|
||||
VALUES ('M001', '测试商户', 'direct', 1, NOW(), NOW())
|
||||
ON DUPLICATE KEY UPDATE
|
||||
`merchant_name` = VALUES(`merchant_name`),
|
||||
`funds_mode` = VALUES(`funds_mode`),
|
||||
`status` = VALUES(`status`),
|
||||
`updated_at` = NOW();
|
||||
|
||||
-- 3) 商户应用(pid=app_id 约定:这里 app_id 使用纯数字字符串,方便易支付测试)
|
||||
INSERT INTO `ma_merchant_app` (`merchant_id`, `api_type`, `app_id`, `app_secret`, `app_name`, `status`, `created_at`, `updated_at`)
|
||||
SELECT m.id, 'epay', '1001', 'dev_secret_1001', '测试应用-易支付', 1, NOW(), NOW()
|
||||
FROM `ma_merchant` m
|
||||
WHERE m.merchant_no = 'M001'
|
||||
ON DUPLICATE KEY UPDATE
|
||||
`app_secret` = VALUES(`app_secret`),
|
||||
`app_name` = VALUES(`app_name`),
|
||||
`status` = VALUES(`status`),
|
||||
`updated_at` = NOW();
|
||||
|
||||
-- 4) 支付方式
|
||||
INSERT INTO `ma_pay_method` (`method_code`, `method_name`, `icon`, `sort`, `status`, `created_at`, `updated_at`) VALUES
|
||||
('alipay', '支付宝', '', 1, 1, NOW(), NOW()),
|
||||
('wechat', '微信支付', '', 2, 1, NOW(), NOW()),
|
||||
('unionpay','云闪付', '', 3, 1, NOW(), NOW())
|
||||
ON DUPLICATE KEY UPDATE
|
||||
`method_name` = VALUES(`method_name`),
|
||||
`icon` = VALUES(`icon`),
|
||||
`sort` = VALUES(`sort`),
|
||||
`status` = VALUES(`status`),
|
||||
`updated_at` = NOW();
|
||||
|
||||
-- 5) 插件注册表(按项目约定:app\\common\\payment\\{Code}Payment)
|
||||
INSERT INTO `ma_pay_plugin` (`plugin_code`, `plugin_name`, `class_name`, `status`, `created_at`, `updated_at`)
|
||||
VALUES ('lakala', '拉卡拉(示例)', 'app\\\\common\\\\payment\\\\LakalaPayment', 1, NOW(), NOW())
|
||||
ON DUPLICATE KEY UPDATE
|
||||
`plugin_name` = VALUES(`plugin_name`),
|
||||
`class_name` = VALUES(`class_name`),
|
||||
`status` = VALUES(`status`),
|
||||
`updated_at` = NOW();
|
||||
|
||||
Reference in New Issue
Block a user