This commit is contained in:
2026-04-10 13:31:15 +08:00
parent 6c59e41b32
commit c092662ebe
56 changed files with 4362 additions and 684 deletions
+731
View File
@@ -0,0 +1,731 @@
<?php
namespace app\api\controller;
use support\Request;
use support\Response;
use Yansongda\Pay\Pay;
use Yansongda\Pay\Log;
use think\facade\Db;
use support\Log as WebmanLog;
use hg\apidoc\annotation as Apidoc;
use app\enum\Payment\Method;
use app\enum\Payment\Status;
use app\enum\Payment\Type;
/**
* 支付控制器
* @Apidoc\Title("支付管理")
* @Apidoc\Group("payment")
*/
class PaymentController extends BaseController
{
/**
* 支付宝支付下单
* @Apidoc\Title("支付宝支付下单")
* @Apidoc\Url("/api/payment/alipay/order")
* @Apidoc\Method("POST")
* @Apidoc\Param("amount", "float", "支付金额", true, "0.01")
* @Apidoc\Param("order_no", "string", "订单号", true, "20260409001")
* @Apidoc\Param("subject", "string", "订单标题", true, "测试商品")
* @Apidoc\Param("body", "string", "订单描述", false, "测试商品描述")
* @Apidoc\Param("type", "string", "订单类型: recharge(充值), goods(商品), service(服务), other(其他)", false, "goods")
* @Apidoc\Return("success", "object", "成功响应", "pay_url|string|支付链接,order_no|string|订单号")
* @Apidoc\Return("error", "object", "失败响应", "code|int|错误码,msg|string|错误信息")
* @param Request $request
* @return Response
*/
public function alipay_order(Request $request): Response
{
try {
$params = $request->post();
// 验证参数
if (!isset($params['amount']) || !isset($params['order_no']) || !isset($params['subject'])) {
return $this->error('缺少必要参数');
}
$amount = $params['amount'];
$orderNo = $params['order_no'];
$subject = $params['subject'];
$body = $params['body'] ?? $subject;
$type = $params['type'] ?? 'goods';
// 获取支付宝配置
$config = config('payment.alipay.default');
// 构建支付参数
$payOrder = [
'out_trade_no' => $orderNo,
'total_amount' => $amount,
'subject' => $subject,
'body' => $body,
];
// 发起支付
$result = Pay::alipay($config)->web($payOrder);
// 记录支付订单
$this->record_payment_order($orderNo, 'alipay', $amount, $subject, $type);
return $this->success('ok',[
'pay_url' => $result->getTargetUrl(),
'order_no' => $orderNo
]);
} catch (\Exception $e) {
WebmanLog::error('支付宝支付下单失败: ' . $e->getMessage());
return $this->error('支付下单失败: ' . $e->getMessage());
}
}
/**
* 支付宝同步回调
* @Apidoc\Title("支付宝同步回调")
* @Apidoc\Url("/api/payment/alipay/return")
* @Apidoc\Method("GET")
* @Apidoc\Param("out_trade_no", "string", "订单号", true)
* @Apidoc\Param("trade_no", "string", "支付宝交易号", true)
* @Apidoc\Param("trade_status", "string", "交易状态", true)
* @Apidoc\Return("redirect", "string", "跳转到成功或失败页面")
* @param Request $request
* @return Response
*/
public function alipay_return(Request $request): Response
{
try {
$config = config('payment.alipay.default');
$data = $request->all();
// 验证回调数据
$result = Pay::alipay($config)->verify($data);
// 处理支付结果
$orderNo = $result->out_trade_no;
$tradeNo = $result->trade_no;
$status = $result->trade_status;
// 更新订单状态
$this->update_payment_order($orderNo, $tradeNo, $status);
// 跳转到成功页面
return redirect('/api/payment/success?order_no=' . $orderNo);
} catch (\Exception $e) {
WebmanLog::error('支付宝同步回调失败: ' . $e->getMessage());
return redirect('/api/payment/fail?error=' . urlencode($e->getMessage()));
}
}
/**
* 支付宝异步回调
* @Apidoc\Title("支付宝异步回调")
* @Apidoc\Url("/api/payment/alipay/notify")
* @Apidoc\Method("POST")
* @Apidoc\Param("out_trade_no", "string", "订单号", true)
* @Apidoc\Param("trade_no", "string", "支付宝交易号", true)
* @Apidoc\Param("trade_status", "string", "交易状态", true)
* @Apidoc\Return("string", "string", "返回success或fail")
* @param Request $request
* @return string
*/
public function alipay_notify(Request $request): string
{
try {
$config = config('payment.alipay.default');
$data = $request->all();
// 验证回调数据
$result = Pay::alipay($config)->verify($data);
// 处理支付结果
$orderNo = $result->out_trade_no;
$tradeNo = $result->trade_no;
$status = $result->trade_status;
// 更新订单状态
$this->update_payment_order($orderNo, $tradeNo, $status);
// 返回成功
return 'success';
} catch (\Exception $e) {
WebmanLog::error('支付宝异步回调失败: ' . $e->getMessage());
return 'fail';
}
}
/**
* 微信支付下单
* @Apidoc\Title("微信支付下单")
* @Apidoc\Url("/api/payment/wechat/order")
* @Apidoc\Method("POST")
* @Apidoc\Param("amount", "float", "支付金额", true, "0.01")
* @Apidoc\Param("order_no", "string", "订单号", true, "20260409001")
* @Apidoc\Param("body", "string", "订单描述", true, "测试商品描述")
* @Apidoc\Param("trade_type", "string", "交易类型: JSAPI, NATIVE, APP, MWEB", false, "JSAPI")
* @Apidoc\Param("openid", "string", "微信用户openid(JSAPI模式需要)", false, "o123456")
* @Apidoc\Param("type", "string", "订单类型: recharge(充值), goods(商品), service(服务), other(其他)", false, "goods")
* @Apidoc\Return("success", "object", "成功响应", "pay_data|object|支付数据,order_no|string|订单号")
* @Apidoc\Return("error", "object", "失败响应", "code|int|错误码,msg|string|错误信息")
* @param Request $request
* @return Response
*/
public function wechat_order(Request $request): Response
{
try {
$params = $request->post();
// 验证参数
if (!isset($params['amount']) || !isset($params['order_no']) || !isset($params['body'])) {
return $this->error('缺少必要参数');
}
$amount = $params['amount'];
$orderNo = $params['order_no'];
$body = $params['body'];
$tradeType = $params['trade_type'] ?? 'JSAPI';
$openid = $params['openid'] ?? '';
$type = $params['type'] ?? 'goods';
// 获取微信支付配置
$config = config('payment.wechat.default');
// 构建支付参数
$payOrder = [
'out_trade_no' => $orderNo,
'total_fee' => $amount * 100, // 微信支付金额单位为分
'body' => $body,
'trade_type' => $tradeType,
];
// JSAPI支付需要openid
if ($tradeType === 'JSAPI' && $openid) {
$payOrder['openid'] = $openid;
}
// 发起支付
$result = Pay::wechat($config)->order($payOrder);
// 记录支付订单
$this->record_payment_order($orderNo, 'wechat', $amount, $body, $type);
return $this->success('ok',[
'pay_data' => $result->toArray(),
'order_no' => $orderNo
]);
} catch (\Exception $e) {
WebmanLog::error('微信支付下单失败: ' . $e->getMessage());
return $this->error('支付下单失败: ' . $e->getMessage());
}
}
/**
* 微信支付回调
* @Apidoc\Title("微信支付回调")
* @Apidoc\Url("/api/payment/wechat/notify")
* @Apidoc\Method("POST")
* @Apidoc\Param("out_trade_no", "string", "订单号", true)
* @Apidoc\Param("transaction_id", "string", "微信交易号", true)
* @Apidoc\Param("result_code", "string", "业务结果", true)
* @Apidoc\Return("xml", "string", "返回XML格式的成功或失败响应")
* @param Request $request
* @return string
*/
public function wechat_notify(Request $request): string
{
try {
$config = config('payment.wechat.default');
$data = $request->all();
// 验证回调数据
$result = Pay::wechat($config)->verify($data);
// 处理支付结果
$orderNo = $result->out_trade_no;
$tradeNo = $result->transaction_id;
$status = $result->result_code === 'SUCCESS' ? 'SUCCESS' : 'FAIL';
// 更新订单状态
$this->update_payment_order($orderNo, $tradeNo, $status);
// 返回成功
return Pay::wechat($config)->success();
} catch (\Exception $e) {
WebmanLog::error('微信支付回调失败: ' . $e->getMessage());
return Pay::wechat(config('payment.wechat.default'))->fail();
}
}
/**
* 记录支付订单
* @param string $orderNo
* @param string $payType
* @param float $amount
* @param string $subject
* @param string $type
*/
private function record_payment_order(string $orderNo, string $payType, float $amount, string $subject, string $type = 'goods'): void
{
try {
Db::name('payment_order')->insert([
'order_no' => $orderNo,
'pay_type' => $payType,
'type' => $type,
'amount' => $amount,
'subject' => $subject,
'status' => Status::CREATED->value,
'created_at' => time(),
'updated_at' => time()
]);
} catch (\Exception $e) {
WebmanLog::error('记录支付订单失败: ' . $e->getMessage());
}
}
/**
* 更新支付订单状态
* @param string $orderNo
* @param string $tradeNo
* @param string $status
*/
private function update_payment_order(string $orderNo, string $tradeNo, string $status): void
{
try {
// 映射支付状态到我们的状态枚举
$mappedStatus = $this->map_payment_status($status);
Db::name('payment_order')->where('order_no', $orderNo)->update([
'trade_no' => $tradeNo,
'status' => $mappedStatus,
'updated_at' => time()
]);
} catch (\Exception $e) {
WebmanLog::error('更新支付订单状态失败: ' . $e->getMessage());
}
}
/**
* 映射支付状态到枚举
* @param string $status
* @return string
*/
private function map_payment_status(string $status): string
{
// 支付宝状态映射
$alipayStatusMap = [
'TRADE_SUCCESS' => Status::SUCCESS->value,
'TRADE_FINISHED' => Status::COMPLETE->value,
'TRADE_CLOSED' => Status::FAIL->value,
'WAIT_BUYER_PAY' => Status::CREATED->value
];
// 微信支付状态映射
$wechatStatusMap = [
'SUCCESS' => Status::SUCCESS->value,
'FAIL' => Status::FAIL->value,
'REFUND' => Status::REFUNDED->value
];
// 先尝试支付宝映射
if (isset($alipayStatusMap[$status])) {
return $alipayStatusMap[$status];
}
// 再尝试微信映射
if (isset($wechatStatusMap[$status])) {
return $wechatStatusMap[$status];
}
// 默认返回成功
return Status::SUCCESS->value;
}
/**
* 查询支付订单状态
* @Apidoc\Title("查询支付订单状态")
* @Apidoc\Url("/api/payment/order/query")
* @Apidoc\Method("GET")
* @Apidoc\Param("order_no", "string", "订单号", true, "20260409001")
* @Apidoc\Param("pay_type", "string", "支付类型: alipay, wechat", true, "alipay")
* @Apidoc\Return("success", "object", "成功响应", "order|object|订单信息,pay_status|object|支付状态")
* @Apidoc\Return("error", "object", "失败响应", "code|int|错误码,msg|string|错误信息")
* @param Request $request
* @return Response
*/
public function query_order(Request $request): Response
{
try {
$orderNo = $request->get('order_no');
$payType = $request->get('pay_type');
if (!$orderNo || !$payType) {
return $this->error('缺少必要参数');
}
// 查询订单
$order = Db::name('payment_order')->where('order_no', $orderNo)->find();
if (!$order) {
return $this->error('订单不存在');
}
// 根据支付类型查询支付状态
if ($payType === \app\enum\Payment\Method::ALIPAY->value) {
$config = config('payment.alipay.default');
$result = Pay::alipay($config)->find($orderNo);
} elseif ($payType === \app\enum\Payment\Method::WECHAT->value) {
$config = config('payment.wechat.default');
$result = Pay::wechat($config)->find($orderNo);
} else {
return $this->error('不支持的支付类型');
}
return $this->success('ok',[
'order' => $order,
'pay_status' => $result->toArray()
]);
} catch (\Exception $e) {
WebmanLog::error('查询支付订单失败: ' . $e->getMessage());
return $this->error('查询失败: ' . $e->getMessage());
}
}
/**
* 关闭支付订单
* @Apidoc\Title("关闭支付订单")
* @Apidoc\Url("/api/payment/order/close")
* @Apidoc\Method("POST")
* @Apidoc\Param("order_no", "string", "订单号", true, "20260409001")
* @Apidoc\Param("pay_type", "string", "支付类型: alipay, wechat", true, "alipay")
* @Apidoc\Return("success", "object", "成功响应", "msg|string|成功信息")
* @Apidoc\Return("error", "object", "失败响应", "code|int|错误码,msg|string|错误信息")
* @param Request $request
* @return Response
*/
public function close_order(Request $request): Response
{
try {
$orderNo = $request->post('order_no');
$payType = $request->post('pay_type');
if (!$orderNo || !$payType) {
return $this->error('缺少必要参数');
}
// 关闭订单
if ($payType === 'alipay') {
$config = config('payment.alipay.default');
$result = Pay::alipay($config)->close($orderNo);
} elseif ($payType === 'wechat') {
$config = config('payment.wechat.default');
$result = Pay::wechat($config)->close($orderNo);
} else {
return $this->error('不支持的支付类型');
}
// 更新订单状态
Db::name('payment_order')->where('order_no', $orderNo)->update([
'status' => \app\enum\Payment\Status::COMPLETE->value,
'updated_at' => time()
]);
return $this->success('订单关闭成功');
} catch (\Exception $e) {
WebmanLog::error('关闭支付订单失败: ' . $e->getMessage());
return $this->error('关闭失败: ' . $e->getMessage());
}
}
/**
* 退款
* @Apidoc\Title("退款")
* @Apidoc\Url("/api/payment/refund")
* @Apidoc\Method("POST")
* @Apidoc\Param("order_no", "string", "订单号", true, "20260409001")
* @Apidoc\Param("pay_type", "string", "支付类型: alipay, wechat", true, "alipay")
* @Apidoc\Param("amount", "float", "退款金额", true, "0.01")
* @Apidoc\Param("refund_no", "string", "退款单号", false, "20260409001_refund")
* @Apidoc\Param("reason", "string", "退款原因", false, "退款")
* @Apidoc\Return("success", "object", "成功响应", "msg|string|成功信息")
* @Apidoc\Return("error", "object", "失败响应", "code|int|错误码,msg|string|错误信息")
* @param Request $request
* @return Response
*/
public function refund(Request $request): Response
{
try {
$params = $request->post();
if (!isset($params['order_no']) || !isset($params['pay_type']) || !isset($params['amount'])) {
return $this->error('缺少必要参数');
}
$orderNo = $params['order_no'];
$payType = $params['pay_type'];
$amount = $params['amount'];
$refundNo = $params['refund_no'] ?? $orderNo . '_' . time();
$reason = $params['reason'] ?? '退款';
// 发起退款
if ($payType === Method::ALIPAY->value) {
$config = config('payment.alipay.default');
$result = Pay::alipay($config)->refund([
'out_trade_no' => $orderNo,
'refund_amount' => $amount,
'out_request_no' => $refundNo,
'refund_reason' => $reason,
]);
} elseif ($payType === Method::WECHAT->value) {
$config = config('payment.wechat.default');
$result = Pay::wechat($config)->refund([
'out_trade_no' => $orderNo,
'out_refund_no' => $refundNo,
'total_fee' => $amount * 100,
'refund_fee' => $amount * 100,
'refund_desc' => $reason,
]);
} else {
return $this->error('不支持的支付类型');
}
// 记录退款信息
Db::name('payment_refund')->insert([
'order_no' => $orderNo,
'refund_no' => $refundNo,
'pay_type' => $payType,
'amount' => $amount,
'reason' => $reason,
'status' => 'SUCCESS',
'created_at' => time()
]);
// 更新订单状态
Db::name('payment_order')->where('order_no', $orderNo)->update([
'status' => Status::REFUNDED->value,
'updated_at' => time()
]);
return $this->success('退款成功');
} catch (\Exception $e) {
WebmanLog::error('退款失败: ' . $e->getMessage());
return $this->error('退款失败: ' . $e->getMessage());
}
}
/**
* 统一支付接口
* @Apidoc\Title("统一支付接口")
* @Apidoc\Url("/api/payment/unified/order")
* @Apidoc\Method("POST")
* @Apidoc\Param("payment", "string", "支付方式: alipay, wechat", true, "alipay")
* @Apidoc\Param("amount", "float", "支付金额", true, "0.01")
* @Apidoc\Param("order_no", "string", "订单号", true, "20260409001")
* @Apidoc\Param("subject", "string", "订单标题", true, "测试商品")
* @Apidoc\Param("body", "string", "订单描述", false, "测试商品描述")
* @Apidoc\Param("type", "string", "订单类型: recharge(充值), goods(商品), service(服务), other(其他)", false, "goods")
* @Apidoc\Param("trade_type", "string", "交易类型(微信支付需要): JSAPI, NATIVE, APP, MWEB", false, "JSAPI")
* @Apidoc\Param("openid", "string", "微信用户openid(JSAPI模式需要)", false, "o123456")
* @Apidoc\Return("success", "object", "成功响应", "pay_url|string|支付宝支付链接,pay_data|object|微信支付数据,order_no|string|订单号")
* @Apidoc\Return("error", "object", "失败响应", "code|int|错误码,msg|string|错误信息")
* @param Request $request
* @return Response
*/
public function unified_order(Request $request): Response
{
try {
$params = $request->post();
// 验证必要参数
if (!isset($params['payment']) || !isset($params['amount']) || !isset($params['order_no']) || !isset($params['subject'])) {
return $this->error('缺少必要参数');
}
$payment = strtolower($params['payment']);
$amount = $params['amount'];
$orderNo = $params['order_no'];
$subject = $params['subject'];
$body = $params['body'] ?? $subject;
$type = $params['type'] ?? 'goods';
// 根据payment参数选择支付方式
switch ($payment) {
case Method::ALIPAY->value:
// 调用支付宝支付
return $this->alipay_order($request);
case Method::WECHAT->value:
// 调用微信支付
return $this->wechat_order($request);
default:
return $this->error('不支持的支付方式');
}
} catch (\Exception $e) {
WebmanLog::error('统一支付接口失败: ' . $e->getMessage());
return $this->error('支付失败: ' . $e->getMessage());
}
}
/**
* 统一支付回调接口
* @Apidoc\Title("统一支付回调接口")
* @Apidoc\Url("/api/payment/unified/notify")
* @Apidoc\Method("ANY")
* @Apidoc\Param("payment", "string", "支付方式: alipay, wechat", false)
* @Apidoc\Param("out_trade_no", "string", "订单号", true)
* @Apidoc\Param("trade_no|transaction_id", "string", "支付交易号", true)
* @Apidoc\Param("trade_status|result_code", "string", "交易状态", true)
* @Apidoc\Return("string", "string", "返回success/fail或XML格式响应")
* @param Request $request
* @return Response
*/
public function unified_notify(Request $request): Response
{
try {
$payment = $request->get('payment') ?? $request->post('payment');
if (!$payment) {
// 尝试从请求参数中自动识别
$data = $request->all();
if (isset($data['app_id']) && strpos($data['app_id'], '20') === 0) {
$payment = 'alipay';
} elseif (isset($data['mch_id'])) {
$payment = 'wechat';
} else {
return $this->error('无法识别支付方式');
}
}
$payment = strtolower($payment);
// 根据payment参数选择回调处理
switch ($payment) {
case Method::ALIPAY->value:
// 调用支付宝回调
return $this->alipay_notify($request);
case Method::WECHAT->value:
// 调用微信回调
return $this->wechat_notify($request);
default:
return $this->error('不支持的支付方式');
}
} catch (\Exception $e) {
WebmanLog::error('统一支付回调接口失败: ' . $e->getMessage());
return $this->error('回调处理失败: ' . $e->getMessage());
}
}
/**
* 统一支付查询接口
* @Apidoc\Title("统一支付查询接口")
* @Apidoc\Url("/api/payment/unified/query")
* @Apidoc\Method("GET")
* @Apidoc\Param("order_no", "string", "订单号", true, "20260409001")
* @Apidoc\Param("payment", "string", "支付方式: alipay, wechat", true, "alipay")
* @Apidoc\Return("success", "object", "成功响应", "order|object|订单信息,pay_status|object|支付状态")
* @Apidoc\Return("error", "object", "失败响应", "code|int|错误码,msg|string|错误信息")
* @param Request $request
* @return Response
*/
public function unified_query(Request $request): Response
{
try {
$params = $request->all();
// 验证必要参数
if (!isset($params['order_no']) || !isset($params['payment'])) {
return $this->error('缺少必要参数');
}
// 设置pay_type参数
$request->withAddedHeader('pay_type', $params['payment']);
// 调用查询接口
return $this->query_order($request);
} catch (\Exception $e) {
WebmanLog::error('统一支付查询接口失败: ' . $e->getMessage());
return $this->error('查询失败: ' . $e->getMessage());
}
}
/**
* 统一支付关闭接口
* @Apidoc\Title("统一支付关闭接口")
* @Apidoc\Url("/api/payment/unified/close")
* @Apidoc\Method("POST")
* @Apidoc\Param("order_no", "string", "订单号", true, "20260409001")
* @Apidoc\Param("payment", "string", "支付方式: alipay, wechat", true, "alipay")
* @Apidoc\Return("success", "object", "成功响应", "msg|string|成功信息")
* @Apidoc\Return("error", "object", "失败响应", "code|int|错误码,msg|string|错误信息")
* @param Request $request
* @return Response
*/
public function unified_close(Request $request): Response
{
try {
$params = $request->post();
// 验证必要参数
if (!isset($params['order_no']) || !isset($params['payment'])) {
return $this->error('缺少必要参数');
}
// 设置pay_type参数
$request->withAddedHeader('pay_type', $params['payment']);
// 调用关闭接口
return $this->close_order($request);
} catch (\Exception $e) {
WebmanLog::error('统一支付关闭接口失败: ' . $e->getMessage());
return $this->error('关闭失败: ' . $e->getMessage());
}
}
/**
* 统一退款接口
* @Apidoc\Title("统一退款接口")
* @Apidoc\Url("/api/payment/unified/refund")
* @Apidoc\Method("POST")
* @Apidoc\Param("order_no", "string", "订单号", true, "20260409001")
* @Apidoc\Param("payment", "string", "支付方式: alipay, wechat", true, "alipay")
* @Apidoc\Param("amount", "float", "退款金额", true, "0.01")
* @Apidoc\Param("refund_no", "string", "退款单号", false, "20260409001_refund")
* @Apidoc\Param("reason", "string", "退款原因", false, "退款")
* @Apidoc\Return("success", "object", "成功响应", "msg|string|成功信息")
* @Apidoc\Return("error", "object", "失败响应", "code|int|错误码,msg|string|错误信息")
* @param Request $request
* @return Response
*/
public function unified_refund(Request $request): Response
{
try {
$params = $request->post();
// 验证必要参数
if (!isset($params['order_no']) || !isset($params['payment']) || !isset($params['amount'])) {
return $this->error('缺少必要参数');
}
// 设置pay_type参数
$params['pay_type'] = $params['payment'];
$request->withAddedHeader('pay_type', $params['payment']);
// 调用退款接口
return $this->refund($request);
} catch (\Exception $e) {
WebmanLog::error('统一退款接口失败: ' . $e->getMessage());
return $this->error('退款失败: ' . $e->getMessage());
}
}
}
+1324 -526
View File
File diff suppressed because it is too large Load Diff
+6 -20
View File
@@ -40,26 +40,12 @@ class User extends Command
cp('操作不存在:'.$action);
return 0;
}
function test(InputInterface $input, OutputInterface $output)
{
$user_id = 104864;
$_user = Db::name('user')->where('id',$user_id)->find();
Db::query('delete FROM `wa_user_team` WHERE descendant_id='.$user_id.' or ancestor_id='.$user_id.';');
Hook('user.register_successed',$_user);
//管理团队人数
// $team_user_ids = Db::name('user_team')->where('descendant_id',$_user['id'])
// ->where('depth','>',0)
// ->order('depth','ASC')
// ->column('ancestor_id');
// Db::name('user_extend')->whereIn('user_id',$team_user_ids)->data([
// 'team_total'=> Db::raw('team_total+1')
// ])->save();
// $list = Db::name('user_extend')->whereIn('user_id',$team_user_ids)->field('user_id,team_total')->select();
// foreach($list as $v){
// cache('team_user_count_'.$v['user_id'],$v['team_total']);
// }
// cp($team_user_ids);
function update_password(InputInterface $input, OutputInterface $output){
$newpassword = \plugin\admin\app\common\Util::passwordHash(MD5('qwe123'));
Db::name('User')->where('id','>',0)->save([
'loginfailure' => 0,
'password' => $newpassword
]);
return 0;
}
function login(InputInterface $input, OutputInterface $output){
+24
View File
@@ -0,0 +1,24 @@
<?php
namespace app\Enum;
trait BaseEnum {
public static function toArray(): array
{
return [
];
}
/**
* 获取当前状态的描述文本
*/
public function getDescription(): string
{
return self::toArray()[$this->value];
}
/**
* 安全地从值创建枚举实例
*/
public static function tryFromValue(int $value): ?self
{
return self::tryFrom($value);
}
}
+32
View File
@@ -0,0 +1,32 @@
<?php
namespace app\enum\Payment;
use app\enum\BaseEnum;
/**
* 支付方式
*/
enum Method: string
{
use BaseEnum;
/**
* 微信
*/
case WECHAT = 'weichat';
/**
* 支付宝
*/
case ALIPAY = 'alipay';
/**
* 获取所有状态映射数组
*/
public static function toArray(): array
{
return [
self::WECHAT->value => __('微信'),
self::ALIPAY->value => __('支付宝')
];
}
}
+61
View File
@@ -0,0 +1,61 @@
<?php
namespace app\enum\Payment;
use app\enum\BaseEnum;
/**
* 支付状态常量
*/
enum Status: string
{
/**
* 等待支付
*/
case CREATED = 'created';
/**
* 成功
*/
case SUCCESS = 'success';
/**
* 完成
*/
case COMPLETE = 'complete';
/**
* 失败
*/
case FAIL = 'fail';
/**
* 退款
*/
case REFUNDED = 'refunded';
/**
* 获取所有状态映射数组
*/
public static function toArray(): array
{
return [
self::CREATED->value => __('等待支付'),
self::SUCCESS->value => __('成功'),
self::FAIL->value => __('失败'),
self::COMPLETE->value => __('完成'),
self::REFUNDED->value => __('退款'),
];
}
/**
* 获取当前状态的描述文本
*/
public function getDescription(): string
{
return self::toArray()[$this->value];
}
/**
* 安全地从值创建枚举实例
*/
public static function tryFromValue(int $value): ?self
{
return self::tryFrom($value);
}
}
+42
View File
@@ -0,0 +1,42 @@
<?php
namespace app\enum\Payment;
use app\enum\BaseEnum;
/**
* 支付用途
*/
enum Type: string
{
use BaseEnum;
/**
* 充值
*/
case RECHARGE = 'recharge';
/**
* 商品
*/
case GOODS = 'goods';
/**
* 服务
*/
case SERVICE = 'service';
/**
* 其他
*/
case OTHER = 'other';
/**
* 获取所有状态映射数组
*/
public static function toArray(): array
{
return [
self::RECHARGE->value => __('充值'),
self::GOODS->value => __('商品'),
self::SERVICE->value => __('服务'),
self::OTHER->value => __('其他')
];
}
}
+297 -84
View File
@@ -2,13 +2,14 @@
namespace app\mcp;
use PhpMcp\Server\Server;
use PhpMcp\Server\ServerBuilder;
use PhpMcp\Server\Transports\StdioServerTransport;
use PhpMcp\Server\Transports\StreamableHttpServerTransport;
use PhpMcp\Server\Transports\HttpServerTransport;
use PhpMcp\Server\Attributes\McpTool;
use PhpMcp\Server\Attributes\McpResource;
use PhpMcp\Server\Attributes\McpPrompt;
use PhpMcp\Server\Attributes\Schema;
use PhpMcp\Server\Defaults\BasicContainer;
use PhpMcp\Schema\Tool;
use PhpMcp\Schema\Resource;
use PhpMcp\Schema\ToolAnnotations;
use PhpMcp\Schema\Annotations;
use think\facade\Db;
use support\Log;
@@ -116,14 +117,21 @@ class McpService
{
// 确保 logger 不为 null
try {
// 尝试获取 mcp 通道
$this->logger = Log::channel('mcp');
if (!$this->logger) {
// 如果 mcp 通道不存在,使用默认通道
$this->logger = Log::channel('default');
}
} catch (\Throwable $e) {
// 如果所有通道都失败,创建一个简单的 logger
$this->logger = Log::channel('default');
try {
// 如果 mcp 通道不存在,尝试使用默认通道
$this->logger = Log::channel('default');
} catch (\Throwable $e) {
// 如果所有通道都失败,创建一个简单的 logger
$this->logger = new class {
public function info($message, $context = []) {}
public function error($message, $context = []) {}
public function warning($message, $context = []) {}
public function addRecord($level, $message, $context = []) {}
};
}
}
// 读取MCP配置文件
@@ -193,18 +201,24 @@ class McpService
$this->heartbeatInterval = $mcpConfig['heartbeat_interval'];
}
Log::channel('mcp')->info('MCP配置加载成功', [
'timeout' => $this->timeout,
'connect_timeout' => $this->connectTimeout,
'read_timeout' => $this->readTimeout,
'retry_attempts' => $this->retryAttempts,
'retry_delay' => $this->retryDelay,
'heartbeat_enabled' => $this->heartbeatEnabled ?? false,
'heartbeat_interval' => $this->heartbeatInterval ?? 30
]);
// 安全地记录日志
if (method_exists($this->logger, 'info')) {
$this->logger->info('MCP配置加载成功', [
'timeout' => $this->timeout,
'connect_timeout' => $this->connectTimeout,
'read_timeout' => $this->readTimeout,
'retry_attempts' => $this->retryAttempts,
'retry_delay' => $this->retryDelay,
'heartbeat_enabled' => $this->heartbeatEnabled ?? false,
'heartbeat_interval' => $this->heartbeatInterval ?? 30
]);
}
} catch (\Exception $e) {
Log::warning('MCP配置加载失败,使用默认配置: ' . $e->getMessage());
// 安全地记录警告
if (method_exists($this->logger, 'warning')) {
$this->logger->warning('MCP配置加载失败,使用默认配置: ' . $e->getMessage());
}
}
}
@@ -291,29 +305,44 @@ class McpService
while ($attempts < $this->retryAttempts) {
try {
$attempts++;
Log::channel('mcp')->info("执行{$operationName},第{$attempts}次尝试");
// 安全地记录日志
if (method_exists($this->logger, 'info')) {
$this->logger->info("执行{$operationName},第{$attempts}次尝试");
}
$result = $operation();
if ($attempts > 1) {
Log::channel('mcp')->info("{$operationName}在第{$attempts}次尝试后成功");
// 安全地记录日志
if (method_exists($this->logger, 'info')) {
$this->logger->info("{$operationName}在第{$attempts}次尝试后成功");
}
}
return $result;
} catch (\Exception $e) {
$lastException = $e;
Log::warning("{$operationName}{$attempts}次尝试失败: " . $e->getMessage());
// 安全地记录警告
if (method_exists($this->logger, 'warning')) {
$this->logger->warning("{$operationName}{$attempts}次尝试失败: " . $e->getMessage());
}
if ($attempts < $this->retryAttempts) {
$delay = $this->retryDelay * pow(1.5, $attempts - 1); // 指数退避
Log::channel('mcp')->info("等待{$delay}ms后重试");
// 安全地记录日志
if (method_exists($this->logger, 'info')) {
$this->logger->info("等待{$delay}ms后重试");
}
usleep($delay * 1000);
}
}
}
Log::channel('mcp')->error("{$operationName}{$this->retryAttempts}次尝试后仍然失败");
// 安全地记录错误
if (method_exists($this->logger, 'error')) {
$this->logger->error("{$operationName}{$this->retryAttempts}次尝试后仍然失败");
}
throw $lastException;
}
@@ -343,27 +372,11 @@ class McpService
}
$this->server = $builder->withContainer($container)
->withTool([self::class, 'handleDbQuery'], 'db-query', '执行数据库查询操作(仅支持SELECT语句)')
->withTool([self::class, 'handleSysConfig'], 'sys-config', '获取系统配置信息')
->withTool([self::class, 'handleWriteLog'], 'write-log', '写入系统日志')
->withTool([self::class, 'handleFileOperation'], 'file-operation', '文件读写操作')
->withTool([self::class, 'handleUserManagement'], 'user-management', '用户管理相关操作')
->withTool([self::class, 'handleSystemInfo'], 'system-info', '获取系统运行信息')
->withTool([self::class, 'handleCreateController'], 'controller', '生成webman控制器文件')
->withTool([self::class, 'handleCreateModel'], 'model', '生成webman模型文件')
->withTool([self::class, 'handleCreateView'], 'view', '生成webman视图文件')
->withTool([self::class, 'handleCreateJs'], 'js', '生成webman JS文件')
->withTool([self::class, 'handleCreateApi'], 'api', '生成webman API接口文件')
->withTool([self::class, 'handleCurd'], 'curd', '生成webman CURD模块')
->withTool([self::class, 'handleAddon'], 'addon', '生成webman 插件模块')
->withTool([self::class, 'handleMenu'], 'menu', '生成webman 菜单模块')
->withTool([self::class, 'handleCreateTable'], 'table', '创建数据库表格, 支持字段信息、类型、注释等')
->withTool([self::class, 'handleThinkCommand'], 'think-command', '执行webman框架命令')
->withTool([self::class, 'handleMcpCommand'], 'mcp-command', '执行MCP专用命令')
->withTool([self::class, 'handleWebmanCommand'], 'webman-command', '执行webman框架命令')
->withPrompt([self::class, 'handleWithPrompt'], 'with-prompt', '通过自然语言描述生成数据库表、控制器、模型等')
->withResource([self::class, 'handleConfigResource'], 'config://system', 'config-system', '系统配置信息资源', 'application/json')
->withResource([self::class, 'handleSchemaResource'], 'schema://database', 'schema-database', '数据库表结构信息资源', 'application/json')
// 使用属性发现自动注册工具、资源和提示
->discover(
basePath: __DIR__ . '/..',
scanDirs: ['mcp']
)
->build();
return $this->server;
}
@@ -376,7 +389,13 @@ class McpService
* @param array $params 查询参数
* @return array
*/
public function handleDbQuery(string $query, array $params = []): array
#[McpTool(name: 'db-query', description: '执行数据库查询操作(仅支持SELECT语句)')]
public function handleDbQuery(
#[Schema(type: 'string', description: 'SQL查询语句')]
string $query,
#[Schema(type: 'array', description: '查询参数')]
array $params = []
): array
{
try {
if (empty($query)) {
@@ -400,7 +419,10 @@ class McpService
];
} catch (\Exception $e) {
Log::channel('mcp')->error('MCP数据库查询错误: ' . $e->getMessage());
// 安全地记录错误
if (method_exists($this->logger, 'error')) {
$this->logger->error('MCP数据库查询错误: ' . $e->getMessage());
}
return [
'success' => false,
'error' => $e->getMessage()
@@ -413,7 +435,11 @@ class McpService
* @param string $key 配置键名(可选)
* @return array
*/
public function handleSysConfig(string $key = ''): array
#[McpTool(name: 'sys-config', description: '获取系统配置信息')]
public function handleSysConfig(
#[Schema(type: 'string', description: '配置键名(可选)')]
string $key = ''
): array
{
try {
if (empty($key)) {
@@ -451,7 +477,15 @@ class McpService
* @param array $context 上下文数据
* @return string
*/
public function handleWriteLog(string $message, string $level = 'info', array $context = []): string
#[McpTool(name: 'write-log', description: '写入系统日志')]
public function handleWriteLog(
#[Schema(type: 'string', description: '日志消息')]
string $message,
#[Schema(type: 'string', description: '日志级别')]
string $level = 'info',
#[Schema(type: 'array', description: '上下文数据')]
array $context = []
): string
{
try {
if (empty($message)) {
@@ -469,7 +503,10 @@ class McpService
return "日志记录成功 [级别: {$level}]";
} catch (\Exception $e) {
Log::channel('mcp')->error('MCP日志写入错误: ' . $e->getMessage());
// 安全地记录错误
if (method_exists($this->logger, 'error')) {
$this->logger->error('MCP日志写入错误: ' . $e->getMessage());
}
throw $e;
}
}
@@ -480,7 +517,13 @@ class McpService
* @param string $filepath 文件路径
* @return array
*/
public function handleFileOperation(string $operation, string $filepath): array
#[McpTool(name: 'file-operation', description: '文件读写操作')]
public function handleFileOperation(
#[Schema(type: 'string', description: '操作类型')]
string $operation,
#[Schema(type: 'string', description: '文件路径')]
string $filepath
): array
{
try {
if (empty($operation) || empty($filepath)) {
@@ -541,7 +584,10 @@ class McpService
}
} catch (\Exception $e) {
Log::channel('mcp')->error('MCP文件操作错误: ' . $e->getMessage());
// 安全地记录错误
if (method_exists($this->logger, 'error')) {
$this->logger->error('MCP文件操作错误: ' . $e->getMessage());
}
throw $e;
}
}
@@ -553,7 +599,15 @@ class McpService
* @param int $limit 返回数量限制(可选)
* @return array
*/
public function handleUserManagement(string $action, int $userId = 0, int $limit = 10): array
#[McpTool(name: 'user-management', description: '用户管理相关操作')]
public function handleUserManagement(
#[Schema(type: 'string', description: '操作类型')]
string $action,
#[Schema(type: 'integer', description: '用户ID(可选)')]
int $userId = 0,
#[Schema(type: 'integer', description: '返回数量限制(可选)')]
int $limit = 10
): array
{
try {
switch ($action) {
@@ -599,7 +653,10 @@ class McpService
}
} catch (\Exception $e) {
Log::channel('mcp')->error('MCP用户管理错误: ' . $e->getMessage());
// 安全地记录错误
if (method_exists($this->logger, 'error')) {
$this->logger->error('MCP用户管理错误: ' . $e->getMessage());
}
throw $e;
}
}
@@ -609,7 +666,11 @@ class McpService
* @param string $type 信息类型
* @return array
*/
public function handleSystemInfo(string $type = 'general'): array
#[McpTool(name: 'system-info', description: '获取系统运行信息')]
public function handleSystemInfo(
#[Schema(type: 'string', description: '信息类型')]
string $type = 'general'
): array
{
try {
switch ($type) {
@@ -661,7 +722,10 @@ class McpService
}
} catch (\Exception $e) {
Log::channel('mcp')->error('MCP系统信息错误: ' . $e->getMessage());
// 安全地记录错误
if (method_exists($this->logger, 'error')) {
$this->logger->error('MCP系统信息错误: ' . $e->getMessage());
}
throw $e;
}
}
@@ -688,6 +752,7 @@ class McpService
* 处理配置资源
* @return string
*/
#[McpResource(uri: 'config://system', name: 'config-system', description: '系统配置信息资源', contentType: 'application/json')]
public function handleConfigResource(): string
{
$configs = [
@@ -709,6 +774,7 @@ class McpService
* 处理数据库模式资源
* @return string
*/
#[McpResource(uri: 'schema://database', name: 'schema-database', description: '数据库表结构信息资源', contentType: 'application/json')]
public function handleSchemaResource(): string
{
try {
@@ -727,7 +793,10 @@ class McpService
return json_encode($schema, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
} catch (\Exception $e) {
Log::channel('mcp')->error('MCP数据库模式获取错误: ' . $e->getMessage());
// 安全地记录错误
if (method_exists($this->logger, 'error')) {
$this->logger->error('MCP数据库模式获取错误: ' . $e->getMessage());
}
return json_encode(['error' => $e->getMessage()], JSON_UNESCAPED_UNICODE);
}
}
@@ -772,11 +841,17 @@ class McpService
$server = $this->buildServer();
$transport = new StdioServerTransport();
Log::channel('mcp')->info('MCP STDIO服务器启动成功');
// 安全地记录日志
if (method_exists($this->logger, 'info')) {
$this->logger->info('MCP STDIO服务器启动成功');
}
$server->listen($transport);
} catch (\Exception $e) {
Log::channel('mcp')->error('MCP STDIO服务器启动失败: ' . $e->getMessage());
// 安全地记录错误
if (method_exists($this->logger, 'error')) {
$this->logger->error('MCP STDIO服务器启动失败: ' . $e->getMessage());
}
throw $e;
}
}
@@ -793,10 +868,16 @@ class McpService
$server = $this->buildServer();
$server->listen($transport);
Log::channel('mcp')->info('MCP服务器启动成功');
// 安全地记录日志
if (method_exists($this->logger, 'info')) {
$this->logger->info('MCP服务器启动成功');
}
} catch (\Exception $e) {
Log::channel('mcp')->error('MCP服务器启动失败: ' . $e->getMessage());
// 安全地记录错误
if (method_exists($this->logger, 'error')) {
$this->logger->error('MCP服务器启动失败: ' . $e->getMessage());
}
throw $e;
}
}
@@ -811,13 +892,19 @@ class McpService
$this->startHeartbeat();
$server = $this->buildServer();
$transport = new \PhpMcp\Server\Transports\StreamableHttpServerTransport($host, $port, $mcpPath);
$transport = new StreamableHttpServerTransport($host, $port, $mcpPath);
Log::channel('mcp')->info("MCP SSE服务器启动成功,监听地址: http://{$host}:{$port}/{$mcpPath}");
// 安全地记录日志
if (method_exists($this->logger, 'info')) {
$this->logger->info("MCP SSE服务器启动成功,监听地址: http://{$host}:{$port}/{$mcpPath}");
}
$server->listen($transport);
} catch (\Exception $e) {
Log::channel('mcp')->error('MCP SSE服务器启动失败: ' . $e->getMessage());
// 安全地记录错误
if (method_exists($this->logger, 'error')) {
$this->logger->error('MCP SSE服务器启动失败: ' . $e->getMessage());
}
throw $e;
}
}
@@ -832,13 +919,19 @@ class McpService
$this->startHeartbeat();
$server = $this->buildServer();
$transport = new \PhpMcp\Server\Transports\HttpServerTransport($host, $port, $mcpPath);
$transport = new HttpServerTransport($host, $port, $mcpPath);
Log::channel('mcp')->info("MCP HTTP服务器启动成功,监听地址: http://{$host}:{$port}/{$mcpPath}");
// 安全地记录日志
if (method_exists($this->logger, 'info')) {
$this->logger->info("MCP HTTP服务器启动成功,监听地址: http://{$host}:{$port}/{$mcpPath}");
}
$server->listen($transport);
} catch (\Exception $e) {
Log::channel('mcp')->error('MCP HTTP服务器启动失败: ' . $e->getMessage());
// 安全地记录错误
if (method_exists($this->logger, 'error')) {
$this->logger->error('MCP HTTP服务器启动失败: ' . $e->getMessage());
}
throw $e;
}
}
@@ -877,7 +970,17 @@ class McpService
* @param string $description 控制器描述 (可选)
* @return array
*/
public function handleCreateController(string $module, string $controller, array $fields = [], string $description = ''): array
#[McpTool(name: 'controller', description: '生成webman控制器文件')]
public function handleCreateController(
#[Schema(type: 'string', description: '模块名称 (admin/api/frontend等)')]
string $module,
#[Schema(type: 'string', description: '控制器名称')]
string $controller,
#[Schema(type: 'array', description: '字段信息 (可选)')]
array $fields = [],
#[Schema(type: 'string', description: '控制器描述 (可选)')]
string $description = ''
): array
{
try {
// 生成控制器类名
@@ -934,7 +1037,17 @@ class McpService
* @param string $description 模型描述 (可选)
* @return array
*/
public function handleCreateModel(string $modelName, array $fields = [], string $tableName = '', string $description = ''): array
#[McpTool(name: 'model', description: '生成webman模型文件')]
public function handleCreateModel(
#[Schema(type: 'string', description: '模型名称')]
string $modelName,
#[Schema(type: 'array', description: '字段信息 (可选)')]
array $fields = [],
#[Schema(type: 'string', description: '表名 (可选,默认使用模型名)')]
string $tableName = '',
#[Schema(type: 'string', description: '模型描述 (可选)')]
string $description = ''
): array
{
try {
// 生成模型类名
@@ -1078,7 +1191,19 @@ class {$modelClass} extends Base
* @param string $charset 字符集 (默认 utf8mb4)
* @return array
*/
public function handleCreateTable(string $tableName, array $fields, string $tableComment = '', string $engine = 'InnoDB', string $charset = 'utf8mb4'): array
#[McpTool(name: 'table', description: '创建数据库表格,支持字段信息、类型、注释等')]
public function handleCreateTable(
#[Schema(type: 'string', description: '表名')]
string $tableName,
#[Schema(type: 'array', description: '字段信息数组')]
array $fields,
#[Schema(type: 'string', description: '表注释')]
string $tableComment = '',
#[Schema(type: 'string', description: '存储引擎 (默认 InnoDB)')]
string $engine = 'InnoDB',
#[Schema(type: 'string', description: '字符集 (默认 utf8mb4)')]
string $charset = 'utf8mb4'
): array
{
try {
// 验证表名
@@ -1293,7 +1418,19 @@ class {$modelClass} extends Base
* @param array $options 其他选项
* @return array
*/
public function handleCurd(string $tableName, string $module = 'admin', array $fields = [], string $description = '', array $options = []): array
#[McpTool(name: 'curd', description: '生成webman CURD模块')]
public function handleCurd(
#[Schema(type: 'string', description: '表名')]
string $tableName,
#[Schema(type: 'string', description: '模块名称 (默认 admin)')]
string $module = 'admin',
#[Schema(type: 'array', description: '字段信息 (可选)')]
array $fields = [],
#[Schema(type: 'string', description: '描述 (可选)')]
string $description = '',
#[Schema(type: 'array', description: '选项 (可选)')]
array $options = []
): array
{
try {
// 构建命令行参数
@@ -1359,7 +1496,15 @@ class {$modelClass} extends Base
* @param array $options 其他选项
* @return array
*/
public function handleAddon(string $action, string $addonName = '', array $options = []): array
#[McpTool(name: 'addon', description: '生成webman 插件模块')]
public function handleAddon(
#[Schema(type: 'string', description: '操作类型')]
string $action,
#[Schema(type: 'string', description: '插件名称 (可选)')]
string $addonName = '',
#[Schema(type: 'array', description: '选项 (可选)')]
array $options = []
): array
{
try {
// 构建命令行参数
@@ -1459,7 +1604,15 @@ class {$modelClass} extends Base
* @param array $options 其他选项
* @return array
*/
public function handleMenu(string $action, array $menuData = [], array $options = []): array
#[McpTool(name: 'menu', description: '生成webman 菜单模块')]
public function handleMenu(
#[Schema(type: 'string', description: '操作类型')]
string $action,
#[Schema(type: 'array', description: '菜单数据 (可选)')]
array $menuData = [],
#[Schema(type: 'array', description: '选项 (可选)')]
array $options = []
): array
{
try {
// 构建命令行参数
@@ -1533,7 +1686,13 @@ class {$modelClass} extends Base
* @param string $type 生成类型 (table/controller/model/js/api/view/all)
* @return array
*/
public function handleWithPrompt(string $prompt, string $type = 'all'): array
#[McpPrompt(name: 'with-prompt', description: '通过自然语言描述生成数据库表、控制器、模型等')]
public function handleWithPrompt(
#[Schema(type: 'string', description: '自然语言描述')]
string $prompt,
#[Schema(type: 'string', description: '生成类型')]
string $type = 'all'
): array
{
try {
if (empty($prompt)) {
@@ -2181,11 +2340,21 @@ class {$modelClass} extends Base
* @param string $description 描述 (可选)
* @return array
*/
public function handleCreateJs(string $module, string $controller, array $fields = [], string $description = ''): array
#[McpTool(name: 'js', description: '生成webman JS文件')]
public function handleCreateJs(
#[Schema(type: 'string', description: '模块名称')]
string $module,
#[Schema(type: 'string', description: 'JS文件名')]
string $name,
#[Schema(type: 'array', description: 'JS数据 (可选)')]
array $data = [],
#[Schema(type: 'string', description: 'JS描述 (可选)')]
string $description = ''
): array
{
try {
// 生成JS文件名
$jsFileName = strtolower($controller);
$jsFileName = strtolower($name);
$jsPath = "plugin/admin/public/js/{$jsFileName}.js";
if ($module == 'frontend') {
@@ -2200,7 +2369,7 @@ class {$modelClass} extends Base
}
// 生成JS内容
$jsContent = $this->generateJsContent($module, $controller, $fields, $description);
$jsContent = $this->generateJsContent($module, $name, $data, $description);
// 确保目录存在
$dir = dirname($jsPath);
@@ -2238,7 +2407,17 @@ class {$modelClass} extends Base
* @param string $description 描述 (可选)
* @return array
*/
public function handleCreateApi(string $controller, string $module = 'api', array $fields = [], string $description = ''): array
#[McpTool(name: 'api', description: '生成webman API接口文件')]
public function handleCreateApi(
#[Schema(type: 'string', description: '控制器名称')]
string $controller,
#[Schema(type: 'string', description: '模块名称 (默认 api)')]
string $module = 'api',
#[Schema(type: 'array', description: '字段信息 (可选)')]
array $fields = [],
#[Schema(type: 'string', description: 'API描述 (可选)')]
string $description = ''
): array
{
try {
// 生成API控制器类名
@@ -2455,7 +2634,17 @@ class {$modelClass} extends Base
* @param string $description 描述 (可选)
* @return array
*/
public function handleCreateView(string $module, string $controller, array $fields = [], string $description = ''): array
#[McpTool(name: 'view', description: '生成webman视图文件')]
public function handleCreateView(
#[Schema(type: 'string', description: '模块名称')]
string $module,
#[Schema(type: 'string', description: '控制器名称')]
string $controller,
#[Schema(type: 'array', description: '字段信息 (可选)')]
array $fields = [],
#[Schema(type: 'string', description: '视图描述 (可选)')]
string $description = ''
): array
{
try {
// 生成视图文件名
@@ -3143,7 +3332,15 @@ class {$modelClass} extends Base
* @param array $options 命令选项 (可选)
* @return array
*/
public function handleThinkCommand(string $command, array $params = [], array $options = []): array
#[McpTool(name: 'think-command', description: '执行webman框架命令')]
public function handleThinkCommand(
#[Schema(type: 'string', description: '命令名称')]
string $command,
#[Schema(type: 'array', description: '命令参数 (可选)')]
array $params = [],
#[Schema(type: 'array', description: '命令选项 (可选)')]
array $options = []
): array
{
try {
// 验证命令是否为安全的内置命令
@@ -3283,7 +3480,15 @@ class {$modelClass} extends Base
* @param array $options 选项
* @return array
*/
public function handleMcpCommand(string $command, array $params = [], array $options = []): array
#[McpTool(name: 'mcp-command', description: '执行MCP专用命令')]
public function handleMcpCommand(
#[Schema(type: 'string', description: '命令名称')]
string $command,
#[Schema(type: 'array', description: '命令参数 (可选)')]
array $params = [],
#[Schema(type: 'array', description: '命令选项 (可选)')]
array $options = []
): array
{
try {
// MCP 专用命令列表
@@ -3374,7 +3579,15 @@ class {$modelClass} extends Base
* @param array $options 选项
* @return array
*/
public function handleWebmanCommand(string $command, array $params = [], array $options = []): array
#[McpTool(name: 'webman-command', description: '执行webman框架命令')]
public function handleWebmanCommand(
#[Schema(type: 'string', description: '命令名称')]
string $command,
#[Schema(type: 'array', description: '命令参数 (可选)')]
array $params = [],
#[Schema(type: 'array', description: '命令选项 (可选)')]
array $options = []
): array
{
try {
// webman 框架命令列表
+102
View File
@@ -0,0 +1,102 @@
<?php
namespace app\model;
/**
* 支付订单模型
*/
class PaymentOrder extends Base
{
/**
* 数据表名
* @var string
*/
protected $name = 'payment_order';
/**
* 获取状态列表
* @return array
*/
public static function getStatusList(): array
{
return \app\enum\Payment\Status::toArray();
}
/**
* 获取类型列表
* @return array
*/
public static function getTypeList(): array
{
return \app\enum\Payment\Type::toArray();
}
/**
* 获取支付类型列表
* @return array
*/
public static function getPayTypeList(): array
{
return \app\enum\Payment\Method::toArray();
}
/**
* 根据订单号查询
* @param string $orderNo
* @return array|null
*/
public static function findByOrderNo(string $orderNo): ?array
{
return self::where('order_no', $orderNo)->find();
}
/**
* 更新订单状态
* @param string $orderNo
* @param string $status
* @param array $data
* @return bool
*/
public static function updateStatus(string $orderNo, string $status, array $data = []): bool
{
$updateData = array_merge([
'status' => $status,
'updated_at' => time(),
], $data);
return self::where('order_no', $orderNo)->update($updateData);
}
/**
* 获取状态文本
* @param string $status
* @return string
*/
public static function getStatusText(string $status): string
{
$list = self::getStatusList();
return $list[$status] ?? $status;
}
/**
* 获取类型文本
* @param string $type
* @return string
*/
public static function getTypeText(string $type): string
{
$list = self::getTypeList();
return $list[$type] ?? $type;
}
/**
* 获取支付类型文本
* @param string $payType
* @return string
*/
public static function getPayTypeText(string $payType): string
{
$list = self::getPayTypeList();
return $list[$payType] ?? $payType;
}
}
+72
View File
@@ -0,0 +1,72 @@
<?php
namespace app\model;
/**
* 退款模型
*/
class PaymentRefund extends Base
{
/**
* 获取状态列表
* @return array
*/
public static function getStatusList(): array
{
return [
'success' => '退款成功',
'fail' => '退款失败',
];
}
/**
* 获取支付类型列表
* @return array
*/
public static function getPayTypeList(): array
{
return \app\enum\Payment\Method::toArray();
}
/**
* 根据订单号查询
* @param string $orderNo
* @return array
*/
public static function findByOrderNo(string $orderNo): array
{
return self::where('order_no', $orderNo)->select()->toArray();
}
/**
* 根据退款单号查询
* @param string $refundNo
* @return array|null
*/
public static function findByRefundNo(string $refundNo): ?array
{
return self::where('refund_no', $refundNo)->find();
}
/**
* 获取状态文本
* @param string $status
* @return string
*/
public static function getStatusText(string $status): string
{
$list = self::getStatusList();
return $list[$status] ?? $status;
}
/**
* 获取支付类型文本
* @param string $payType
* @return string
*/
public static function getPayTypeText(string $payType): string
{
$list = self::getPayTypeList();
return $list[$payType] ?? $payType;
}
}