hospital-applets-api/app/Controller/CallBackController.php
2023-03-10 14:53:50 +08:00

434 lines
18 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace App\Controller;
use App\Amqp\Producer\AssignDoctorProducer;
use App\Constants\DoctorTitleCode;
use App\Constants\HttpEnumCode;
use App\Exception\BusinessException;
use App\Model\Hospital;
use App\Model\OrderInquiry;
use App\Model\UserDoctor;
use App\Model\UserPatient;
use App\Services\BaseService;
use App\Services\ImService;
use App\Utils\Log;
use Extend\TencentIm\Account;
use Extend\TencentIm\Message;
use Extend\TencentIm\Profile;
use Extend\Wechat\WechatPay;
use Hyperf\Amqp\Producer;
use Hyperf\DbConnection\Db;
use Hyperf\HttpMessage\Stream\SwooleFileStream;
use Hyperf\HttpMessage\Stream\SwooleStream;
use Hyperf\Redis\Redis;
use Hyperf\Utils\ApplicationContext;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Psr\Http\Message\ResponseInterface;
class CallBackController extends AbstractController
{
/**
* 患者端微信支付回调
* @return ResponseInterface
* @throws \Throwable
*/
public function wxPaySuccessCallBack(): ResponseInterface
{
try {
// 处理支付结果事件
$WechatPay = new WechatPay(1);
$app = $WechatPay->createApp();
$server = $app->getServer();
$message = $server->getRequestMessage();
if (empty($message)){
return $this->response->withStatus(500)->withBody(new SwooleStream(strval(json_encode(['code' => 'ERROR', 'message' => "回调数据为空"], JSON_UNESCAPED_UNICODE))));
}
// 验证推送消息签名
$app->getValidator()->validate($app->getRequest());
Log::getInstance()->info("微信支付回调数据:" . json_encode($message->toArray(),JSON_UNESCAPED_UNICODE));
if (empty($message['out_trade_no'])){
Log::getInstance()->info("微信支付回调数据错误");
return $server->serve();
}
// 查询订单
$params = array();
$params['inquiry_no'] = $message['out_trade_no'];
$order_inquiry = OrderInquiry::getOne($params);
if (empty($order_inquiry)){
Log::getInstance()->info("非法订单");
return $server->serve();
}
// 验证订单状态
if ($order_inquiry['inquiry_status'] != 1){
// 问诊订单状态1:待支付 2:待分配 3:待接诊 4:已接诊 5:已完成 6:已结束 7:已取消)
Log::getInstance()->info("订单状态错误:当前为" . $order_inquiry['inquiry_status']);
return $server->serve();
}
// 支付状态无需验证,如第一次支付失败,会修改支付状态,再次支付时,会出现验证不通过的情况
// 修改支付状态
$data = array();
if ($message['trade_state'] == "SUCCESS"){
// 支付成功
$data['inquiry_pay_status'] = 2;
$data['pay_time'] = date('Y-m-d H:i:s',strtotime($message['success_time']));// 支付时间
if ($order_inquiry['inquiry_type'] == 1 || $order_inquiry['inquiry_type'] == 3){
// 专家-公益
$data['inquiry_status'] = 3;// 3:待接诊
}elseif ($order_inquiry['inquiry_type'] == 2 || $order_inquiry['inquiry_type'] == 4){
// 快速-购药
$data['inquiry_status'] = 2;// 2:待分配
}
}elseif($message['trade_state'] == "CLOSED"){
// 已关闭
$data['inquiry_pay_status'] = 6;
}elseif($message['trade_state'] == "REVOKED"){
// 已撤销(付款码支付)
$data['inquiry_pay_status'] = 7;
}elseif($message['trade_state'] == "USERPAYING"){
// 用户支付中(付款码支付)
$data['inquiry_pay_status'] = 3;
}elseif($message['trade_state'] == "PAYERROR"){
// 支付失败(其他原因,如银行返回失败)
$data['inquiry_pay_status'] = 4;
}
$data['escrow_trade_no'] = $message['transaction_id'];
$data['updated_at'] = date('Y-m-d H:i:s',time());
$params = array();
$params['order_inquiry_id'] = $order_inquiry['order_inquiry_id'];
OrderInquiry::edit($params,$data);
}catch (\Exception $e) {
// 验证失败
Log::getInstance()->error("微信支付回调数据验证失败:" . $e->getMessage());
return $this->wxPayErrorReturn($e->getMessage());
}
Log::getInstance()->info("微信支付回调处理成功");
Log::getInstance()->info("微信支付回调处理成功,开始发送系统问诊消息");
try {
if ($message['trade_state'] == "SUCCESS"){
if ($order_inquiry['inquiry_type'] == 2 || $order_inquiry['inquiry_type'] == 4){
// 快速-购药
// 加入分配医生队列
$data = array();
$data['order_inquiry_id'] = $order_inquiry['order_inquiry_id'];
$message = new AssignDoctorProducer($data);
$producer = ApplicationContext::getContainer()->get(Producer::class);
$result = $producer->produce($message);
if (!$result) {
Log::getInstance()->info("加入分配医生队列失败");
return $server->serve();
}
}elseif ($order_inquiry['inquiry_type'] == 1 || $order_inquiry['inquiry_type'] == 3){
// 专家-公益
$ImService = new ImService();
// 检测并创建患者账号
$ImService->createAccount($order_inquiry['user_id']);
// 获取订单医生数据
$params = array();
$params['doctor_id'] = $order_inquiry['doctor_id'];
$user_doctor = UserDoctor::getOne($params);
if (empty($user_doctor)){
Log::getInstance()->info("医生数据错误");
return $server->serve();
}
// 检测并创建医生账号
$ImService->createAccount($user_doctor['user_id']);
// 医生给患者发送消息
$message = new Message();
$arg = array();
$arg['From_Account'] = $user_doctor['user_id']; // 发送方user_id 如系统发送,无需填写
$arg['To_Account'] = $order_inquiry['user_id']; // 接收方user_id
$arg['MsgBody'] = [
[
"MsgType" => "TIMTextElem",
"MsgContent" => [
"Text" => "等待医生接诊",
],
]
];
// 自定义消息
$cloud_custom_data = array();
$cloud_custom_data['order_inquiry_id'] = $order_inquiry['order_inquiry_id'];
$cloud_custom_data['inquiry_type'] = $order_inquiry['inquiry_type'];
$cloud_custom_data['message_type'] = 1;//1系统发送 其余:用户发送
$arg['CloudCustomData'] = json_encode($cloud_custom_data,JSON_UNESCAPED_UNICODE);
$message->sendMessage($arg);
}
}
}catch (\Exception $e) {
// 验证失败
Log::getInstance()->error("微信支付回调数据处理成功,发送系统问诊消息失败:" . $e->getMessage());
return $server->serve();
}
Log::getInstance()->info("微信支付回调处理成功,发送系统问诊消息成功");
return $server->serve();
}
/**
* 微信退款回调
* @return ResponseInterface
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
* @throws \Throwable
*/
public function wxPayRefundCallBack(): ResponseInterface
{
try {
// 处理支付结果事件
$WechatPay = new WechatPay(1);
$app = $WechatPay->createApp();
$server = $app->getServer();
$message = $server->getRequestMessage();
if (empty($message)){
Db::rollBack();
return $this->response->withStatus(500)->withBody(new SwooleStream(strval(json_encode(['code' => 'ERROR', 'message' => "回调数据为空"], JSON_UNESCAPED_UNICODE))));
}
// 验证推送消息签名
$app->getValidator()->validate($app->getRequest());
Log::getInstance()->info("微信退款回调数据:" . json_encode($message->toArray(),JSON_UNESCAPED_UNICODE));
return $server->serve();
} catch (\Exception $e) {
// 验证失败
Db::rollBack();
Log::getInstance()->error("微信支付回调数据验证失败:" . $e->getMessage());
return $this->wxPayErrorReturn($e->getMessage());
}
}
/**
* 微信支付返回错误响应
* @param string $message
* @return ResponseInterface
*/
protected function wxPayErrorReturn(string $message): ResponseInterface
{
return $this->response
->withStatus(500)
->withBody(
new SwooleStream(
strval(
json_encode(['code' => 'ERROR', 'message' => $message], JSON_UNESCAPED_UNICODE)
)
)
);
}
//
/**
* im回调
* @return ResponseInterface
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public function imCallBack(): ResponseInterface
{
$request_params = $this->request->all();
try {
Log::getInstance()->info("Im回调数据" . json_encode($request_params,JSON_UNESCAPED_UNICODE));
if (empty($request_params['RequestTime']) || empty($request_params['Sign'])){
Log::getInstance()->error("Im回调数据处理失败:缺少时间时间戳/签名字段");
return $this->ImErrorReturn("缺少时间时间戳/签名字段");
}
// 鉴定回调签名
$imService = new ImService();
$result = $imService->validateSign($request_params['RequestTime'],$request_params['Sign']);
if (!$result){
Log::getInstance()->error("Im回调数据处理失败:回调签名不匹配");
return $this->ImErrorReturn("回调签名不匹配");
}
// 验证消息内容
if (empty($request_params['MsgBody'])){
Log::getInstance()->error("Im回调数据处理失败:消息内容错误");
return $this->ImErrorReturn("消息内容错误缺少MsgBody");
}
// 验证接收方user_id
if (empty($request_params['To_Account'])){
Log::getInstance()->error("Im回调数据处理失败:接收用户错误");
return $this->ImErrorReturn("消息内容错误,接收用户错误");
}
// 验证消息唯一id
if (empty($request_params['MsgKey'])){
Log::getInstance()->error("Im回调数据处理失败:消息唯一标识错误");
return $this->ImErrorReturn("消息内容错误,消息唯一标识错误");
}
// 验证消息重复性
$params = array();
$params['message_key'] = $request_params['MsgKey'];
$message = \App\Model\Message::getExists($params);
if ($message){
// 消息重复
Log::getInstance()->info("Im回调数据处理失败:消息重复");
return $this->ImSuccessReturn();
}
// 处理发送结果
if ($request_params['message_send_result'] == 0){
// im中0表示成功
$message_send_result = 1;
}
// 验证自定义消息内容
$is_system = 0;// 是否系统操作发送0:否 1:是)
if (!empty($request_params['CloudCustomData'])){
$cloud_custom_data = json_decode($request_params['CloudCustomData'],true);
if (!empty($cloud_custom_data['order_inquiry_id'])){
// 获取订单数据
$params = array();
$params['order_inquiry_id'] = $cloud_custom_data['order_inquiry_id'];
$order_inquiry = OrderInquiry::getOne($params);
if (empty($order_inquiry)){
Log::getInstance()->error("Im回调数据处理失败:非法订单");
return $this->ImErrorReturn("消息内容错误,非法订单");
}
$order_inquiry_id = $cloud_custom_data['order_inquiry_id'];
}
if (!empty($cloud_custom_data['is_system'])){
if ($cloud_custom_data['is_system'] == 1){
// 系统发送
$is_system = 1;
}
}
}
// 入库
$data = array();
if (!empty($request_params['From_Account'])){
// 系统发送时不带参数
$data['from_user_id'] = $request_params['From_Account'];
}
$data['to_user_id'] = $request_params['To_Account'];
$data['message_key'] = $request_params['MsgKey'];
$data['message_send_time'] = $request_params['RequestTime'];
$data['message_seq'] = $request_params['MsgSeq'];
$data['message_send_result'] = $message_send_result ?? 0;
$data['send_error_info'] = $request_params['ErrorInfo'];
$data['message_type'] = $request_params['MsgBody'][0]['MsgType'] ?? "未定义";
$data['is_system'] = $is_system;
if (!empty($order_inquiry_id)){
$data['order_inquiry_id'] = $order_inquiry_id;
}
$message_content = $request_params['MsgBody'][0]['MsgContent'] ?? "";
$data['message_content'] = json_encode($message_content,JSON_UNESCAPED_UNICODE);
$data['message_custom_content'] = $request_params['CloudCustomData'] ?? "";
$message = \App\Model\Message::addMessage($data);
if (empty($message)){
Log::getInstance()->error("Im回调数据处理失败:存储数据库失败");
return $this->wxPayErrorReturn("存储数据库失败");
}
// 存储redisList
if (!empty($order_inquiry) && !empty($request_params['CloudCustomData'])){
if (!empty($cloud_custom_data['is_system'])){
if ($cloud_custom_data['is_system'] != 1){
// 非系统发送
if (!empty($cloud_custom_data['sender_user_type'])){
if ($cloud_custom_data['sender_user_type'] == 1 || $cloud_custom_data['sender_user_type'] == 2){
// 患者-医生发送
$data['order_inquiry_id'] = $order_inquiry['order_inquiry_id'];
$data['patient_name'] = $order_inquiry['patient_name'];
$data['patient_sex'] = $order_inquiry['patient_sex'];
$data['patient_age'] = $order_inquiry['patient_age'];
$data['inquiry_status'] = $order_inquiry['inquiry_status'];
$data['message_send_time'] = $request_params['RequestTime'];
$data['last_message_content'] = $request_params['MsgBody'][0]['MsgContent'] ?? "";
$imService = new ImService();
$imService->addRecentContactRecordCache($order_inquiry['doctor_id'],$order_inquiry['inquiry_type'],$order_inquiry['user_id'],$data);
}
}
}
}
}
} catch (\Exception $e) {
// 验证失败
Log::getInstance()->error("Im回调数据处理失败:" . $e->getMessage());
return $this->wxPayErrorReturn($e->getMessage());
}
Log::getInstance()->info("Im回调数据处理成功");
return $this->ImSuccessReturn();
}
/**
* im返回错误响应
* @param string $message
* @return ResponseInterface
*/
protected function ImErrorReturn(string $message): ResponseInterface
{
return $this->response
->withStatus(200)
->withBody(
new SwooleStream(
strval(
json_encode([
'ActionStatus' => 'FAIL',
'ErrorCode' => 1,
'ErrorInfo' => $message,
], JSON_UNESCAPED_UNICODE)
)
)
);
}
/**
* im返回正确响应
* @return ResponseInterface
*/
protected function ImSuccessReturn(): ResponseInterface
{
return $this->response
->withStatus(200)
->withBody(
new SwooleStream(
strval(
json_encode([
'ActionStatus' => 'OK',
'ErrorCode' => 0,
'ErrorInfo' => "",
], JSON_UNESCAPED_UNICODE)
)
)
);
}
}