Notify.php 8.1 KB
<?php

namespace app\api\controller;

use app\api\model\Appointment;
use app\api\model\Doctor;
use app\api\model\DoctorLevel;
use app\api\model\DoctorMoneyLog;
use app\api\model\GiftOrder;
use app\common\controller\Api;
use app\common\controller\Wechat;
use think\Db;
use think\Exception;
use think\exception\PDOException;
use think\Log;
use think\Validate;

/**
 * @ApiInternal
 * 支付回调
 */
class Notify extends Api
{

    protected $noNeedLogin = ['*'];
    protected $noNeedRight = ['*'];
    protected $layout = '';
    public function _initialize()
    {
        parent::_initialize();
    }

    /**
     * 异步回调(预约)
     * @ApiInternal
     */
    public function notifyAppointment()
    {
        $payment = Wechat::payment();
        $response = $payment->handlePaidNotify(function($message, $fail){
            if ($message['return_code'] !== 'SUCCESS') { // return_code 表示通信状态,不代表支付状态
                return $fail('通信失败,请稍后再通知我');
            }
            // 用户支付失败 - 支付失败也需要返回true,表示服务器已处理,不然微信会反复通知,没有意义
            if ($message['result_code'] === 'FAIL') {
                return true;
            }
            // 支付成功后的业务逻辑
            if ($message['result_code'] === 'SUCCESS') {
                Db::startTrans();
                try {
                    // 处理订单
                    $this->handleAppointment($message);
                    Db::commit();
                } catch (PDOException $e) {
                    Db::rollback();
                    return $fail('服务器处理失败,请稍后再通知我');
                } catch (Exception $e) {
                    Db::rollback();
                    return $fail('服务器处理失败,请稍后再通知我');
                }
            }
            return true;
        });
        $response->send(); // return $response;
    }

    /**
     * 异步回调(预约)-零元
     * @ApiInternal
     */
    public function notifyAppointmentZero($message)
    {
        Db::startTrans();
        try {
            $this->handleAppointment($message);
            Db::commit();
        } catch (PDOException $e) {
            Db::rollback();
            $this->error($e->getMessage());
            return false;
        } catch (Exception $e) {
            Db::rollback();
            $this->error($e->getMessage());
            return false;
        }
        return true;
    }

    /**
     * 异步回调(预约)-处理订单
     */
    private function handleAppointment($message)
    {
        $appointment = Appointment::get(['order_sn'=>$message['out_trade_no']]);
        if (!$appointment || $appointment['status'] == '1') { // 如果订单不存在 或者 订单已经支付过了
            return true; // 告诉微信,我已经处理完了,订单没找到,别再通知我了
        }
        $appointment->transaction_id = $message['transaction_id']; // 回填微信的订单号
        $appointment->pay_time = time(); // 更新支付时间为当前时间
        $appointment->status = '1';
        $appointment->save();

        // 医生信息
        $doctor = $appointment['doctor'];
        if($doctor){
            // 即将到账
            $level = DoctorLevel::where('id',$doctor['level_id'])->find();
            $doctor_income = $level ? round($appointment['pay_fee'] * ($level['income_ratio'] / 100),2) : 0;
            if($doctor_income > 0){
                DoctorMoneyLog::create([
                    'doctor_id' => $appointment['doctor_id'],
                    'money' => $doctor_income,
                    'before' => $doctor['money'],
                    'after' => $doctor['money'],
                    'memo' => '即将到账',
                    'appointment_id' => $appointment['id'],
                    'status' => '2'
                ]);
            }
            // 给被预约医生发送短信提醒
            if(Validate::regex($doctor['mobile'], "^1\d{10}$")){
                $ret = send_sms2([
                    'content' => '【在线会诊】预约人名称:' . $appointment['user']['nickname'] . ',下单时间:' . date('Y-m-d H:i:s') . ',预约时间:' . date('Y-m-d H:i',$appointment['date_time']) . ',价格:' .$appointment['pay_fee']. '元',//短信内容
                    'mobile' => $doctor['mobile'],//手机号码
                    'tKey' => time(),
                ]);
                $ret = json_decode($ret,true);
                if($ret['code'] != 200){
                    Log::write('短信发送失败:' . $ret['msg']);
                }
            }
            // 给预约用户发送短信提醒
            if(Validate::regex($appointment['user']['mobile'], "^1\d{10}$")){
                $ret = send_sms2([
                    'content' => '【在线会诊】被预约医生名称:' . $doctor['nickname'] . ',下单时间:' . date('Y-m-d H:i:s') . ',预约时间:' . date('Y-m-d H:i',$appointment['date_time']) . ',价格:' .$appointment['pay_fee']. '元',//短信内容
                    'mobile' => $appointment['user']['mobile'],//手机号码
                    'tKey' => time(),
                ]);
                $ret = json_decode($ret,true);
                if($ret['code'] != 200){
                    Log::write('短信发送失败:' . $ret['msg']);
                }
            }
        }
        return true;
    }

    /**
     * 异步回调(礼物)
     * @ApiInternal
     */
    public function notifyGift()
    {
        $payment = Wechat::payment();
        $response = $payment->handlePaidNotify(function($message, $fail){
            if ($message['return_code'] !== 'SUCCESS') { // return_code 表示通信状态,不代表支付状态
                return $fail('通信失败,请稍后再通知我');
            }
            // 用户支付失败 - 支付失败也需要返回true,表示服务器已处理,不然微信会反复通知,没有意义
            if ($message['result_code'] === 'FAIL') {
                return true;
            }
            // 支付成功后的业务逻辑
            if ($message['result_code'] === 'SUCCESS') {
                Db::startTrans();
                try {
                    // 处理订单
                    $this->handleGiftOrder($message);
                    Db::commit();
                } catch (PDOException $e) {
                    Db::rollback();
                    return $fail('服务器处理失败,请稍后再通知我');
                } catch (Exception $e) {
                    Db::rollback();
                    return $fail('服务器处理失败,请稍后再通知我');
                }
            }
            return true;
        });
        $response->send(); // return $response;
    }

    /**
     * 异步回调(礼物)-零元
     * @ApiInternal
     */
    public function notifyGiftZero($message)
    {
        Db::startTrans();
        try {
            $this->handleGiftOrder($message);
            Db::commit();
        } catch (PDOException $e) {
            Db::rollback();
            $this->error($e->getMessage());
            return false;
        } catch (Exception $e) {
            Db::rollback();
            $this->error($e->getMessage());
            return false;
        }
        return true;
    }

    /**
     * 异步回调(礼物)-处理订单
     */
    private function handleGiftOrder($message)
    {
        $order = GiftOrder::get(['order_sn'=>$message['out_trade_no']]);
        if (!$order || $order['pay_status'] == '1') { // 如果订单不存在 或者 订单已经支付过了
            return true; // 告诉微信,我已经处理完了,订单没找到,别再通知我了
        }
        $order->transaction_id = $message['transaction_id']; // 回填微信的订单号
        $order->pay_time = time(); // 更新支付时间为当前时间
        $order->pay_status = '1';
        $order->save();
        // 打赏金额
        $appointment = $order['appointment'];
        $appointment->setInc('gift_fee',$order['pay_fee']);
        return true;
    }
}