437 lines
20 KiB
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;
|
|
}
|
|
}
|
|
|
|
} |