Files
xk-api-yii/service/modules/v1/controllers/CallbackController.php

437 lines
20 KiB
PHP

<?php
namespace service\modules\v1\controllers;
use Carbon\Carbon;
use common\enums\ProductOrderEnum;
use common\events\ProductOrderEvent;
use common\jobs\ProductOrderSyncPlatformJob;
use common\models\oldDb\Address;
use common\models\oldDb\Callback;
use common\models\oldDb\Drug;
use common\models\oldDb\FundWater;
use common\models\oldDb\PaymentProductOrder;
use common\models\oldDb\PaymentProductRefund;
use common\models\oldDb\PaymentRegister;
use common\models\oldDb\PaymentRegisterRefund;
use common\models\oldDb\ProductOrder;
use common\models\oldDb\ProductOrderItems;
use common\models\oldDb\ProductOrderRefund;
use common\models\oldDb\Region;
use common\models\oldDb\Register;
use common\models\oldDb\RegisterRefund;
use common\models\oldDb\StoreUser;
use common\models\oldDb\UserPatient;
use common\services\UploadService;
use common\services\WechatService;
use member\models\forms\ProductOrderSubmitForm;
use member\models\forms\RegisterSubmitForm;
use yii\base\Exception;
use yii\helpers\Json;
use yii\web\Response;
class CallbackController extends \yii\web\Controller
{
public $enableCsrfValidation = false;
/**
* 下单回调
* @return mixed
*/
public function actionNotify()
{
\Yii::$app->response->format = Response::FORMAT_RAW;
\Yii::$app->response->formatters = [];
$response = WechatService::getInstance()->payment->handlePaidNotify(function ($notify, $fail) {
/**
* {"appid":"wx36bbb299d88c6127","bank_type":"ZJRCUB_DEBIT","cash_fee":"1","fee_type":"CNY","is_subscribe":"N","mch_id":"1496340382","nonce_str":"637ed1617f5f3","openid":"o88xX5Z-mpVWWV-yw2X6MefDIUqE","out_trade_no":"PY20221124100521434224","result_code":"SUCCESS","return_code":"SUCCESS","sign":"FAB5D4E3AD785DBF7D6FB1FE0E1A897E","time_end":"20221124100606","total_fee":"1","trade_type":"JSAPI","transaction_id":"4200001675202211242752421487"}
*/
//记录回调信息
$callback = new Callback();
$callback->content = json_encode($notify);
$callback->type = 'order';
$callback->save();
if($notify['return_code']=='SUCCESS' && $notify['result_code']=='SUCCESS'){
$t = \Yii::$app->db->beginTransaction();
try {
$out_trade_no = $notify['out_trade_no'];
$paymentProductOrder = PaymentProductOrder::find()->where([
'pay_order_no' => $out_trade_no
])->one();
if($paymentProductOrder){
$data['order_no'] = $paymentProductOrder->order_no;
$data['transaction_id'] = $notify['transaction_id'];
$data['pay_type'] = 1;
$productOrderPayForm = new ProductOrderSubmitForm();
$order = $productOrderPayForm->paid($data);
$order_type=1;
}else{
$PaymentRegister=PaymentRegister::find()->where([
'pay_order_no' => $out_trade_no
])->one();
if (!$PaymentRegister){
throw new Exception('订单不存在');
}
$data['order_no']= $PaymentRegister->order_no;
$data['transaction_id'] = $notify['transaction_id'];
$data['pay_type'] = 1;
$RegisterSubmitForm = new RegisterSubmitForm();
$order = $RegisterSubmitForm->paid($data);
$order_type=2;
}
// 增加流水记录
$fundWater = new FundWater();
$fundWater->store_id = $order->store_id; // 入账
$fundWater->type = 'enter'; // 入账
$fundWater->order_type = $order_type;
$fundWater->order_id = $order->id;
$fundWater->user_id = $order->user_id;
$fundWater->service_user_id = $order_type==1?$order->su_id:$order->service_user_id;
$fundWater->order_no = $order->order_no;
$fundWater->price = $order_type==1 ? $order->total_pay_price : $order->price;
$fundWater->pay_type = 1; //微信
$fundWater->saveOrFail();
//回调处理成功
$callback->status = 1;
$callback->save();
$t->commit();
return true;
}catch (\Exception $exception){
$t->rollBack();
$callback->message = $exception->getMessage();
$callback->save();
return $fail('通信失败,请稍后再通知我');
}
}
});
// $response = unserialize('O:41:"Symfony\\Component\\HttpFoundation\\Response":6:{s:7:"headers";O:50:"Symfony\\Component\\HttpFoundation\\ResponseHeaderBag":5:{s:23:"' . "\0" . '*' . "\0" . 'computedCacheControl";a:1:{s:8:"no-cache";b:1;}s:10:"' . "\0" . '*' . "\0" . 'cookies";a:0:{}s:14:"' . "\0" . '*' . "\0" . 'headerNames";a:2:{s:13:"cache-control";s:13:"Cache-Control";s:4:"date";s:4:"Date";}s:10:"' . "\0" . '*' . "\0" . 'headers";a:2:{s:13:"cache-control";a:1:{i:0;s:8:"no-cache";}s:4:"date";a:1:{i:0;s:29:"Wed, 09 Mar 2022 02:19:18 GMT";}}s:15:"' . "\0" . '*' . "\0" . 'cacheControl";a:0:{}}s:10:"' . "\0" . '*' . "\0" . 'content";s:96:"<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";s:10:"' . "\0" . '*' . "\0" . 'version";s:3:"1.0";s:13:"' . "\0" . '*' . "\0" . 'statusCode";i:200;s:13:"' . "\0" . '*' . "\0" . 'statusText";s:2:"OK";s:10:"' . "\0" . '*' . "\0" . 'charset";N;}');
return $response;
}
/**
* 退款回调
*/
public function actionRefundNotify()
{
\Yii::$app->response->format = Response::FORMAT_RAW;
\Yii::$app->response->formatters = [];
$response = WechatService::getInstance()->payment->handleRefundedNotify(function ($message, $reqInfo, $fail) {
// 其中 $message['req_info'] 获取到的是加密信息
// $reqInfo 为 message['req_info'] 解密后的信息
// 你的业务逻辑...
/**
* {"cash_refund_fee":"1","out_refund_no":"RF20221124103051025400","out_trade_no":"PY20221124100521434224","refund_account":"REFUND_SOURCE_RECHARGE_FUNDS","refund_fee":"1","refund_id":"50300503882022112427569050043","refund_recv_accout":"\u6d59\u6c5f\u519c\u4fe1\u501f\u8bb0\u53617865","refund_request_source":"API","refund_status":"SUCCESS","settlement_refund_fee":"1","settlement_total_fee":"1","success_time":"2022-11-24 10:31:00","total_fee":"1","transaction_id":"4200001675202211242752421487"}
*/
//记录回调信息
$callback = new Callback();
$callback->content = json_encode($reqInfo);
$callback->type = 'refund';
$callback->save();
$t = \Yii::$app->db->beginTransaction();
try {
$transaction_id = $reqInfo['transaction_id'];
$out_refund_no = $reqInfo['out_refund_no'];
$paymentProductOrder = PaymentProductOrder::find()->where([
'transaction_id' => $transaction_id,
])->one();
if ($paymentProductOrder){
if ($paymentProductOrder->is_pay!=1){
throw new Exception('支付订单不存在');
}
$order = ProductOrder::find()->where([
'order_no' => $paymentProductOrder->order_no,
])->with('prescription')->one();
if(!$order || $order->is_pay!=1){
throw new Exception('订单不存在');
}
$order_type = 1;
$refund = ProductOrderRefund::find()->where(['refund_no'=>$out_refund_no])->one();//退款订单
$payment_refund = PaymentProductRefund::find()->where(['refund_no'=>$out_refund_no])->one();
}else{
$PaymentRegister=PaymentRegister::find()->where([
'transaction_id' => $transaction_id
])->one();
if (!$PaymentRegister || $PaymentRegister->is_pay!=1){
throw new \yii\db\Exception('支付订单不存在');
}
$order = Register::find()->where([
'order_no' => $PaymentRegister->order_no,
])->one();
if(!$order || $order->is_pay!=1){
throw new Exception('订单不存在');
}
$order_type = 2;
$refund= RegisterRefund::find()->where(['refund_no'=>$out_refund_no])->one();//退款订单
$payment_refund= PaymentRegisterRefund::find()->where(['refund_no'=>$out_refund_no])->one();
}
if(!$refund || !$payment_refund){
throw new Exception('退款订单不存在');
}
if($reqInfo['refund_status'] == 'SUCCESS'){
if ($order_type == 1){
$order->refund_status =3;//已退款
$order->status = ProductOrderEnum::REFUND;//已退款
$order->refund_time = time();
$order->save();
if($order->is_online){ //平台订单状态同步
\Yii::$app->queue->delay(0)->push(new ProductOrderSyncPlatformJob([
'orderId' => $this->event->order->id,
'status' => 3
]));
}
}
$refund->is_refund = 1;
$refund->refund_time = date('Y-m-d H:i:s',strtotime($reqInfo['success_time']));
$refund->save();
$payment_refund->is_pay = 1;
$payment_refund->pay_type = 1;
$payment_refund->save();
}else{
$refund->is_refund = -1;
$refund->save();
$payment_refund->is_pay = -1;
$payment_refund->save();
}
// 增加流水记录
$fundWater = new FundWater();//出账
$fundWater->store_id = $order->store_id;
$fundWater->order_type = $order_type;
$fundWater->type = 'refund'; // 出账
$fundWater->order_id = $order->id;
$fundWater->user_id = $order->user_id;
$fundWater->service_user_id = $order_type==1?$order->su_id:$order->service_user_id;
$fundWater->refund_no = $refund->refund_no;
$fundWater->price = $order_type==1 ? $order->total_pay_price : $order->price;
$fundWater->pay_type = 1; //微信
$fundWater->saveOrFail();
$callback->status = 1;
$callback->save();
$t->commit();
return true; // 返回 true 告诉微信“我已处理完成”
// 或返回错误原因 $fail('参数格式校验错误');
}catch (\Exception $exception){
$t->rollBack();
$callback->message = $exception->getMessage();
$callback->save();
$fail($exception->getMessage());
}
});
return $response;
}
/**
* 阿里oss直传回调
*/
public function actionUploadNotify()
{
// 1.获取OSS的签名header和公钥url header
$headers =\Yii::$app->request->getHeaders();
$authorizationBase64 = "";
$pubKeyUrlBase64 = "";
if(isset($headers['authorization'])) {
$authorizationBase64 = $headers['authorization'];
}else{
if (isset($_SERVER['HTTP_AUTHORIZATION']))
{
$authorizationBase64 = $_SERVER['HTTP_AUTHORIZATION'];
}
}
if(isset($headers['x-oss-pub-key-url'])){
$pubKeyUrlBase64 = $headers['x-oss-pub-key-url'];
}else{
if (isset($_SERVER['HTTP_X_OSS_PUB_KEY_URL']))
{
$pubKeyUrlBase64 = $_SERVER['HTTP_X_OSS_PUB_KEY_URL'];
}
}
if ($authorizationBase64 == '' || $pubKeyUrlBase64 == '')
{
throw new Exception('参数异常');
}
// 2.获取OSS的签名
$authorization = base64_decode($authorizationBase64);
// 4.获取回调body
$body = file_get_contents('php://input');
// 5.拼接待签名字符串
$authStr = '';
$path = $_SERVER['REQUEST_URI'];
$pos = strpos($path, '?');
if ($pos === false)
{
$authStr = urldecode($path)."\n".$body;
}
else
{
$authStr = urldecode(substr($path, 0, $pos)).substr($path, $pos, strlen($path) - $pos)."\n".$body;
}
// 3.获取公钥
$pubKey = (new UploadService())->getPublicKey($pubKeyUrlBase64);
if ($pubKey == "")
{
throw new Exception('公钥异常');
}
// 6.验证签名
$ok = openssl_verify($authStr, $authorization, $pubKey, OPENSSL_ALGO_MD5);
if(!$ok){
throw new Exception('签名异常');
}
$data = (new UploadService())->getBody($body);
return $data;
}
// 互医订单同步
public function actionPlatformNotify(){
\Yii::$app->response->format = Response::FORMAT_RAW;
$content = file_get_contents('php://input');
$callback = new Callback();
$callback->content = $content;
$callback->type = 'platform_notify';
$callback->save();
$t = \Yii::$app->db->beginTransaction();
try {
$data = json_decode($content, true);
$config = \Yii::$app->params;
$sign = md5($data['order']['order_no'].$data['time'].$config['platform']['token'].$data['type']);
if($sign != $data['sign']){
throw new Exception('sign不匹配');
}
$isExist = ProductOrder::find()->where(['sync_order_no' => $data['order']['order_no'], 'is_online' => 1])->one();
switch ($data['type']) {
case 'order_create'://订单创建
if($isExist){
throw new Exception('产品订单已存在');
}
$userPatient = UserPatient::findOne([
'user_id' => $data['order']['user_id'],
'id_card' => $data['order']['patient']['id_card'],
'is_delete' => 0
]);
$storeUser = StoreUser::find()->where([
'user_id' => $data['order']['user_id'],
'is_online' => 1
])->one();
$userAddress = Address::find()->select('id,name,mobile,province,region,detail_address')->where(['user_id' => $data['order']['user_id']])->orderBy('is_default DESC')->asArray()->all();
$productOrder = new ProductOrder();
$productOrder->store_id = $storeUser->store_id??11001;
$productOrder->is_online = 1;
$productOrder->dosage = isset($data['order']['dosage'])?$data['order']['dosage']:0;
$productOrder->su_id = $data['order']['doctor_id'];
$productOrder->user_id = $data['order']['user_id'];
$productOrder->up_id = $userPatient->id??0;
$productOrder->order_no = Carbon::now()->format('YmdHis') . rand(10000, 99999) . rand(10000, 99999);
$productOrder->sync_order_no = $data['order']['order_no'];
$productOrder->order_type = 2; //商城订单
$productOrder->prescription_type = $data['order']['prescription_type'];
$productOrder->p_id = 0;
$productOrder->status = 0;
$productOrder->items_price = $data['order']['total_price'];
$productOrder->trans_expenses = 0;
$totalPayPrice = $data['order']['total_price'];
if($userAddress){
$productOrder->address_id = $userAddress[0]['id'];
$productOrder->address = Json::encode($userAddress[0]);
$productOrder->express_name = $userAddress[0]['name'];
$productOrder->express_mobile = $userAddress[0]['mobile'];
$productOrder->express_region = $userAddress[0]['region'];
$productOrder->express_address = $userAddress[0]['detail_address'];
$region = Region::find()->where(['name' => $userAddress[0]['province']])->one();
$productOrder->trans_expenses = $region->express_fee;
$totalPayPrice = $totalPayPrice + $region->express_fee;
}
$productOrder->total_pay_price = $totalPayPrice;
$productOrder->saveOrFail();
foreach($data['order']['goods'] as $v){
$drug = Drug::find()->where(['id' => $v['id']])->one();
if(!$drug){
throw new Exception('药品不存在:'.$v['id']);
}
$item = new ProductOrderItems();
$item->product_order_id = $productOrder->id;
if ($drug) {
$item->drug_id = $drug->id;
$item->drug_image = $drug->image;
$item->number = $v['number'];
$item->drug_no = $drug->drug_number;
$item->price = $v['price'];
$item->drug_name = $drug->drug_name;
$item->small_info = $drug->small_info;
$item->saveOrFail();
}
}
//触发订单创建事件
$event = new ProductOrderEvent();
$event->order = $productOrder;
$event->sender = $this;
\Yii::$app->trigger(ProductOrder::EVENT_CREATED, $event);
break;
case 'prescription_pass'://处方通过
if(!$isExist){
throw new Exception('产品订单不存在');
}
$isExist->online_prescription_status = 1;
$isExist->save();
break;
case 'prescription_refuse'://处方拒绝
if(!$isExist){
throw new Exception('产品订单不存在');
}
$isExist->online_prescription_status = 2;
$isExist->save();
//TODO 未付款订单取消/已付款订单退款
break;
default:
throw new Exception('错误的回调类型');
break;
}
$callback->status = 1;
$callback->save();
$t->commit();
return true;
} catch (Exception $e) {
$t->rollBack();
$callback->message = $e->getMessage();
$callback->save();
Yii::$app->response->setStatusCode('400');
return false;
}
}
}