<?php

namespace app\api\controller;

use app\common\controller\Api;
use app\common\model\PayOrderModel;
use app\common\model\Wallet;
use app\utils\LogUtil;
use think\Db;
use addons\epay\library\Service;
use think\Request;

use app\admin\model\shopro\Pay as PayModel;
use addons\shopro\service\pay\PayOper;

/**
 * 订单支付回调
 */
class Notify extends Api
{
    // 日志模块名称
    const LOG_MODULE = 'Notify';
    protected $noNeedLogin = ['*'];
    protected $noNeedRight = ['*'];

    public function __construct(Request $request = null)
    {
        parent::__construct($request);
        //日志统一写入
        register_shutdown_function([new LogUtil, 'close']);
        LogUtil::getInstance('Api/'); //设置日志存入通道
    }

    // 余额充值 支付回调
    public function recharge()
    {
        //验签
        $pay_type = input('pay_type', 'wechat');
        LogUtil::info("用户充值 {$pay_type}支付回调", self::LOG_MODULE, __FUNCTION__, $this->request->param());
        if (!$pay = Service::checkNotify($pay_type)) {
            LogUtil::info('签名错误', self::LOG_MODULE, __FUNCTION__);
            return $this->error('签名错误 err01');
        }

        //验证,拿订单号等信息
        $data         = $pay->verify();
        $out_trade_no = $data['out_trade_no'];
        [$res, $msg] = PayOrderModel::recharge($out_trade_no);
        if (!$res) {
            LogUtil::info($msg, self::LOG_MODULE, __FUNCTION__);
            return $this->error('签名错误 err02');
        }
        LogUtil::info('处理成功', self::LOG_MODULE, __FUNCTION__);
        return $pay->success();
    }

    //充值VIP 异步回调对外方法
    public function vip_notify_base()
    {

        //验签
        $paytype     = input('paytype', 'wechat');
        $notify_file = $this->notify_log_start($paytype);
        $pay         = Service::checkNotify($paytype);
        if (!$pay) {
            echo '签名错误';
            exit;
        }

        //验证,拿订单号等信息
        $data         = $pay->verify();
        $out_trade_no = $data['out_trade_no'];
        //订单查询
        $info = Db::name('pay_order')->where('out_trade_no', $out_trade_no)->find();

        if (empty($info)) {
            echo $pay->success();
            exit;
        }

        if ($info['order_status'] != 0) {
            echo $pay->success();
            exit;
        }
        //你可以在此编写订单逻辑
        $rs = $this->vip_notify_do($out_trade_no);
        if ($rs === false) {
            //不论结果都应返回success
            echo $pay->success();
            exit;
        } else {
            //不论结果都应返回success
            echo $pay->success();
            exit;
        }

        //默认
        echo $pay->success();
        exit;
    }

    //充值金币 逻辑
    private function vip_notify_do($out_trade_no)
    {

        Db::startTrans();
        $orderInfo = Db::name('pay_order')->where(['out_trade_no' => $out_trade_no])->lock(true)->find();
        if (empty($orderInfo)) {
            Db::rollback();
            return false;
        }

        if ($orderInfo['order_status'] != 0) {
            Db::rollback();
            return false;
        }

        //逻辑开始
        //先充值
        $args      = json_decode($orderInfo['args'], true);
        $user_info = Db::name('user_wallet')->where('user_id', $orderInfo['user_id'])->lock(true)->find();
        if ($user_info['vip_endtime'] < time()) {
            //过期了
            $vip_endtime = time() + (intval($args['days']) * 86400);
            $vip_type    = 1;
        } else {
            //追加vip
            $vip_endtime = $user_info['vip_endtime'] + (intval($args['days']) * 86400);
            $vip_type    = 2;
        }
        $update_data = [
            'vip_endtime' => $vip_endtime,
        ];
        $result      = Db::name('user_wallet')->where('user_id', $orderInfo['user_id'])->update($update_data);

        //记录日志
        $log_data = [
            'user_id'      => $orderInfo['user_id'],
            'before'       => $user_info['vip_endtime'],
            'change_value' => intval($args['days']) * 86400,
            'remain'       => $vip_endtime,
            'remark'       => '购买vip',
            'createtime'   => time(),
            'vip_type'     => $vip_type,
        ];
        Db::name('user_vip_log')->insertGetId($log_data);

        if ($result === false) {
            Db::rollback();
            return false;
        }


        //逻辑结束

        //状态
        $ros = Db::name('pay_order')->where(['out_trade_no' => $out_trade_no])->update(['order_status' => 1, 'notifytime' => time()]);
        if ($ros === false) {
            Db::rollback();
            return false;
        }

        //默认提交
        Db::commit();
        return true;
    }

    public function shopro_notify_base_test(){
        //验签
        $paytype     = input('paytype', 'wechat');

        //验证,拿订单号等信息
        $out_trade_no = input('out_trade_no', '');

        //订单查询
        $info = Db::name('shopro_pay')->where('pay_sn', $out_trade_no)->find();

        if (empty($info)) {
            echo 'success';
            exit;
        }

        if ($info['status'] != 'unpaid') {
            echo 'success';
            exit;
        }
        //你可以在此编写订单逻辑
        $data = [
            'out_trade_no' => $out_trade_no,
            'transaction_id' => 'test',
            'notify_time' => time(),
            'buyer_info' => 'test',
            'pay_fee' => 0,
        ];

        $rs = $this->shopro_notify_do($out_trade_no,$data,$paytype);
        if ($rs === false) {
            //不论结果都应返回success
            echo 'success';
            exit;
        } else {
            //不论结果都应返回success
            echo 'success';
            exit;
        }

        //默认
        echo $pay->success();
        exit;
    }

    //充值VIP 异步回调对外方法
    public function shopro_notify_base()
    {

        //验签
        $paytype     = input('paytype', 'wechat');
        $notify_file = $this->notify_log_start($paytype);
        $pay         = Service::checkNotify($paytype);
        if (!$pay) {
            echo '签名错误';
            exit;
        }

        //验证,拿订单号等信息
        $data         = $pay->verify();
        $out_trade_no = $data['out_trade_no'];
        //订单查询
        $info = Db::name('shopro_pay')->where('pay_sn', $out_trade_no)->find();

        if (empty($info)) {
            echo $pay->success();
            exit;
        }

        if ($info['status'] != 'unpaid') {
            echo $pay->success();
            exit;
        }
        //你可以在此编写订单逻辑
        $rs = $this->shopro_notify_do($out_trade_no,$data,$paytype);
        if ($rs === false) {
            //不论结果都应返回success
            echo $pay->success();
            exit;
        } else {
            //不论结果都应返回success
            echo $pay->success();
            exit;
        }

        //默认
        echo $pay->success();
        exit;
    }

    //充值金币 逻辑
    private function shopro_notify_do($out_trade_no,$data,$payment)
    {

        // 查询 pay 交易记录
        $payModel = PayModel::where('pay_sn', $out_trade_no)->find();
        if (!$payModel || $payModel->status != PayModel::PAY_STATUS_UNPAID) {
            // 订单不存在,或者订单已支付
            return false;
        }

        $originData = [];
        Db::transaction(function () use ($payModel, $data, $originData, $payment) {
            $notify = [
                'pay_sn' => $data['out_trade_no'],
                'transaction_id' => $data['transaction_id'],
                'notify_time' => $data['notify_time'],
                'buyer_info' => $data['buyer_info'],
                'payment_json' => $originData ? json_encode($originData) : json_encode($data),
                'pay_fee' => $data['pay_fee'],          // 微信的已经*100处理过了
                'pay_type' => $payment              // 支付方式
            ];

            // pay 实例
            $payOper = new PayOper($payModel->user_id);
            $payOper->notify($payModel, $notify);
        });

        return true;
    }

    //异步日志
    private function notify_log_start($paytype = 'wechat')
    {
        //记录支付回调数据
        ignore_user_abort(); // run script in background
        set_time_limit(30);
        // 日志文件 start
        $log_base_dir = '../paylog/' . $paytype . '/';
        if (!is_dir($log_base_dir)) {
            mkdir($log_base_dir, 0770, true);
            @chmod($log_base_dir, 0770);
        }
        $notify_file = $log_base_dir . 'notify.txt';
        if (!file_exists($notify_file)) {
            @touch($notify_file);
            @chmod($notify_file, 0770);
        }
        if (filesize($notify_file) > 5242880)//大于5M自动切换
        {
            rename($notify_file, $log_base_dir . 'notify_' . date('Y_m_d_H_i_s') . '.txt');
        }
        if (!file_exists($notify_file)) {
            @touch($notify_file);
            @chmod($notify_file, 0770);
        }
        // 日志文件 end
        //开始写入
        $_REQUEST = isset($_REQUEST) ? $_REQUEST : array();
        if ($_REQUEST && $paytype == 'alipay') {
            file_put_contents($notify_file, "\r\n\r\n" . date('Y-m-d H:i:s') . " [notify][入口接收request]" . json_encode($_REQUEST), FILE_APPEND);
        } else {
            $xml = file_get_contents("php://input");
            file_put_contents($notify_file, "\r\n\r\n" . date('Y-m-d H:i:s') . " [notify][入口接收php://input流原始数据] \n" . $xml, FILE_APPEND);
            $xmlObj = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
            file_put_contents($notify_file, "\r\n\r\n" . date('Y-m-d H:i:s') . " [notify][入口接收php://input流] " . json_encode($xmlObj), FILE_APPEND);
        }

        ini_set('display_errors', 'On');

        return $notify_file;

    }
}