This commit is contained in:
Your Name
2026-03-11 14:33:49 +08:00
parent 38ad60f4bb
commit 08dd9cd307
57 changed files with 9547 additions and 379 deletions
@@ -0,0 +1,99 @@
<?php
declare(strict_types=1);
namespace app\adminapi\controller\order;
use app\common\model\Order;
use think\response\Json;
/**
* 支付宝支付回调控制器
* Class AlipayNotifyController
* @package app\adminapi\controller\order
*/
class AlipayNotifyController
{
/**
* @notes 支付宝异步通知
* @return string
*/
public function notify()
{
try {
// 获取支付宝配置
$alipayConfig = config('pay.alipay');
// 获取POST数据
$data = request()->post();
// 验证签名
if (!$this->verifyAlipaySign($data, $alipayConfig['alipay_public_key'])) {
return 'fail';
}
// 验证金额
$order = Order::where('order_no', $data['out_trade_no'])->find();
if (!$order) {
return 'fail';
}
if ((float)$data['total_amount'] != (float)$order->amount) {
return 'fail';
}
// 验证交易状态
if ($data['trade_status'] == 'TRADE_SUCCESS' || $data['trade_status'] == 'TRADE_FINISHED') {
// 更新订单状态
if ($order->status == 1) { // 只有待支付的订单才能更新
$order->status = 2; // 已支付
$order->payment_method = 'alipay';
$order->payment_time = date('Y-m-d H:i:s');
$order->trade_no = $data['trade_no'];
$order->save();
}
}
return 'success';
} catch (\Exception $e) {
return 'fail';
}
}
/**
* @notes 验证支付宝签名
* @param array $data
* @param string $publicKey
* @return bool
*/
private function verifyAlipaySign(array $data, string $publicKey): bool
{
try {
// 获取签名
$sign = $data['sign'] ?? '';
unset($data['sign']);
unset($data['sign_type']);
// 按键排序
ksort($data);
// 构建签名字符串
$signStr = '';
foreach ($data as $key => $value) {
if ($value !== '' && $value !== null) {
$signStr .= $key . '=' . $value . '&';
}
}
$signStr = rtrim($signStr, '&');
// 验证签名
$publicKeyResource = openssl_pkey_get_public($publicKey);
$result = openssl_verify($signStr, base64_decode($sign), $publicKeyResource, OPENSSL_ALGO_SHA256);
openssl_free_key($publicKeyResource);
return $result === 1;
} catch (\Exception $e) {
return false;
}
}
}
@@ -32,7 +32,7 @@ class OrderController extends BaseAdminController
public function detail()
{
$params = (new OrderValidate())->post()->goCheck('detail');
$detail = OrderLogic::detail($params['id']);
$detail = OrderLogic::detail((int)$params['id']);
if (!$detail) {
return $this->fail('订单不存在');
@@ -66,7 +66,7 @@ class OrderController extends BaseAdminController
{
$params = (new OrderValidate())->post()->goCheck('edit');
$result = OrderLogic::edit($params['id'], $params);
$result = OrderLogic::edit((int)$params['id'], $params);
if (!$result) {
return $this->fail(OrderLogic::getError());
}
@@ -82,7 +82,26 @@ class OrderController extends BaseAdminController
{
$params = (new OrderValidate())->post()->goCheck('pay');
$result = OrderLogic::pay($params['id'], $params['payment_method']);
// 判断是否是补单支付
if (!empty($params['is_supplement']) && $params['is_supplement'] == 1) {
// 补单支付:通过订单号查找订单
if (empty($params['order_no'])) {
return $this->fail('补单支付需要提供订单号');
}
$order = \app\common\model\Order::where('order_no', $params['order_no'])->find();
if (!$order) {
return $this->fail('订单不存在');
}
$orderId = $order->id;
} else {
// 正常支付:通过订单ID
if (empty($params['id'])) {
return $this->fail('订单ID不能为空');
}
$orderId = (int)$params['id'];
}
$result = OrderLogic::pay($orderId, $params['payment_method']);
if (!$result) {
return $this->fail(OrderLogic::getError());
}
@@ -98,7 +117,7 @@ class OrderController extends BaseAdminController
{
$params = (new OrderValidate())->post()->goCheck('cancel');
$result = OrderLogic::cancel($params['id']);
$result = OrderLogic::cancel((int)$params['id']);
if (!$result) {
return $this->fail(OrderLogic::getError());
}
@@ -114,7 +133,7 @@ class OrderController extends BaseAdminController
{
$params = (new OrderValidate())->post()->goCheck('refund');
$result = OrderLogic::refund($params['id']);
$result = OrderLogic::refund((int)$params['id']);
if (!$result) {
return $this->fail(OrderLogic::getError());
}
@@ -130,7 +149,7 @@ class OrderController extends BaseAdminController
{
$params = (new OrderValidate())->post()->goCheck('delete');
$result = OrderLogic::delete($params['id']);
$result = OrderLogic::delete((int)$params['id']);
if (!$result) {
return $this->fail(OrderLogic::getError());
}
@@ -146,4 +165,92 @@ class OrderController extends BaseAdminController
{
return $this->dataLists(new OrderLists());
}
/**
* @notes 支付宝支付
* @return \think\response\Json
*/
public function alipay()
{
$params = (new OrderValidate())->post()->goCheck('pay');
// 补单支付不需要校验订单是否存在
if (!empty($params['is_supplement']) && $params['is_supplement'] == 1) {
// 补单支付:直接返回支付URL,不校验订单
$payUrl = OrderLogic::alipayPay(['order_no' => $params['order_no']]);
if (!$payUrl) {
return $this->fail(OrderLogic::getError());
}
return $this->data(['pay_url' => $payUrl]);
}
// 正常支付需要校验订单
$order = $this->getOrderByParams($params);
if (!$order) {
return $this->fail('订单不存在');
}
// 调用支付宝支付接口
$payUrl = OrderLogic::alipayPay($order);
if (!$payUrl) {
return $this->fail(OrderLogic::getError());
}
return $this->data(['pay_url' => $payUrl]);
}
/**
* @notes 微信支付
* @return \think\response\Json
*/
public function wechat()
{
$params = (new OrderValidate())->post()->goCheck('pay');
// 补单支付不需要校验订单是否存在
if (!empty($params['is_supplement']) && $params['is_supplement'] == 1) {
// 补单支付:直接返回支付数据,不校验订单
$payData = OrderLogic::wechatPay(['order_no' => $params['order_no']]);
if (!$payData) {
return $this->fail(OrderLogic::getError());
}
return $this->data($payData);
}
// 正常支付需要校验订单
$order = $this->getOrderByParams($params);
if (!$order) {
return $this->fail('订单不存在');
}
// 调用微信支付接口
$payData = OrderLogic::wechatPay($order);
if (!$payData) {
return $this->fail(OrderLogic::getError());
}
return $this->data($payData);
}
/**
* @notes 根据参数获取订单
* @param array $params
* @return mixed
*/
private function getOrderByParams(array $params)
{
if (!empty($params['is_supplement']) && $params['is_supplement'] == 1) {
// 补单支付:通过订单号查找
if (empty($params['order_no'])) {
return null;
}
return \app\common\model\Order::where('order_no', $params['order_no'])->find();
} else {
// 正常支付:通过订单ID
if (empty($params['id'])) {
return null;
}
return \app\common\model\Order::find((int)$params['id']);
}
}
}
@@ -0,0 +1,128 @@
<?php
declare(strict_types=1);
namespace app\adminapi\controller\order;
use app\common\model\Order;
use think\response\Xml;
/**
* 微信支付回调控制器
* Class WechatNotifyController
* @package app\adminapi\controller\order
*/
class WechatNotifyController
{
/**
* @notes 微信异步通知
* @return Xml
*/
public function notify()
{
try {
// 获取微信配置
$wechatConfig = config('pay.wechat');
// 获取XML数据
$xmlData = file_get_contents('php://input');
$data = $this->xmlToArray($xmlData);
// 验证签名
if (!$this->verifyWechatSign($data, $wechatConfig['api_key'])) {
return $this->xmlResponse('FAIL', '签名验证失败');
}
// 验证金额
$order = Order::where('order_no', $data['out_trade_no'])->find();
if (!$order) {
return $this->xmlResponse('FAIL', '订单不存在');
}
if ((int)$data['total_fee'] != (int)($order->amount * 100)) {
return $this->xmlResponse('FAIL', '金额不匹配');
}
// 验证交易状态
if ($data['result_code'] == 'SUCCESS') {
// 更新订单状态
if ($order->status == 1) { // 只有待支付的订单才能更新
$order->status = 2; // 已支付
$order->payment_method = 'wechat';
$order->payment_time = date('Y-m-d H:i:s');
$order->trade_no = $data['transaction_id'];
$order->save();
}
}
return $this->xmlResponse('SUCCESS', '支付成功');
} catch (\Exception $e) {
return $this->xmlResponse('FAIL', $e->getMessage());
}
}
/**
* @notes 验证微信签名
* @param array $data
* @param string $apiKey
* @return bool
*/
private function verifyWechatSign(array $data, string $apiKey): bool
{
try {
// 获取签名
$sign = $data['sign'] ?? '';
unset($data['sign']);
// 按键排序
ksort($data);
// 构建签名字符串
$signStr = '';
foreach ($data as $key => $value) {
if ($value !== '' && $value !== null) {
$signStr .= $key . '=' . $value . '&';
}
}
$signStr .= 'key=' . $apiKey;
// MD5签名
$computedSign = strtoupper(md5($signStr));
return $computedSign === $sign;
} catch (\Exception $e) {
return false;
}
}
/**
* @notes XML转数组
* @param string $xml
* @return array
*/
private function xmlToArray(string $xml): array
{
try {
$data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
return is_array($data) ? $data : [];
} catch (\Exception $e) {
return [];
}
}
/**
* @notes 返回XML响应
* @param string $returnCode
* @param string $returnMsg
* @return Xml
*/
private function xmlResponse(string $returnCode, string $returnMsg): Xml
{
$xml = '<xml>';
$xml .= '<return_code><![CDATA[' . $returnCode . ']]></return_code>';
$xml .= '<return_msg><![CDATA[' . $returnMsg . ']]></return_msg>';
$xml .= '</xml>';
return response($xml, 200, ['Content-Type' => 'application/xml']);
}
}
@@ -233,7 +233,24 @@ class DiagnosisController extends BaseAdminController
$result = DiagnosisLogic::getCallRecords($params);
return $this->data($result);
}
/**
* @notes 获取患者通话签名(用于测试)
* @return \think\response\Json
*/
public function getDoctorSignature()
{
$params = $this->request->get();
if (empty($params['patient_id'])) {
return $this->fail('医助理ID不能为空');
}
$result = DiagnosisLogic::getDoctorSignature((int)$params['patient_id']);
if ($result) {
return $this->data($result);
}
return $this->fail(DiagnosisLogic::getError());
}
/**
* @notes 获取患者通话签名(用于测试)
* @return \think\response\Json
@@ -300,14 +317,14 @@ class DiagnosisController extends BaseAdminController
$offset = ($page_no - 1) * $page_size;
$lists = \app\common\model\tcm\Diagnosis::where('patient_name|patient_phone|patient_id_card', 'like', '%' . $keyword . '%')
->field(['id', 'patient_name', 'patient_phone', 'patient_id_card', 'gender', 'age'])
$lists = \app\common\model\tcm\Diagnosis::where('patient_name|phone|id_card', 'like', '%' . $keyword . '%')
->field(['id', 'patient_name', 'phone', 'id_card', 'gender', 'age'])
->limit($offset, $page_size)
->order('id desc')
->select()
->toArray();
$count = \app\common\model\tcm\Diagnosis::where('patient_name|patient_phone|patient_id_card', 'like', '%' . $keyword . '%')
$count = \app\common\model\tcm\Diagnosis::where('patient_name|phone|id_card', 'like', '%' . $keyword . '%')
->count();
return $this->success('', [