<?php
/**
 * 微信支付通知类
 * Created by PhpStorm.
 * User: phperstar
 * Date: 2019/11/28
 * Time: 5:00 PM
 */
namespace JinDouYun\Controller\Common;

use JinDouYun\Dao\Finance\DAccountType;
use JinDouYun\Dao\Finance\DExpenseSingle;
use JinDouYun\Dao\Market\DVipCardOrder;
use JinDouYun\Model\Finance\MAccount;
use JinDouYun\Model\Finance\MExpenseSingle;
use JinDouYun\Model\Shop\MShopCardOrder;
use JinDouYun\Model\Shop\MShopSubscribe;
use Mall\Framework\Core\ErrorCode;
use Mall\Framework\Core\ResultWrapper;
use Mall\Framework\Factory;
use Mall\Framework\Core\StatusCode;

use JinDouYun\Controller\BaseController;

use JinDouYun\Model\Order\MOrder;
use JinDouYun\Model\Market\MVipCard;
use JinDouYun\Model\System\MPaymentSetting;

class WeiXinPayNotify extends BaseController
{
    /**
     * 商户支付密钥
     */
    private $partnerKey = '45c87Fa0352211e78D40d4977a9Ea871';

    public function __construct($isCheckAcl = false, $isMustLogin = false, $checkToken = false)
    {
        parent::__construct($isCheckAcl, $isMustLogin, $checkToken);
    }

    /**
     * 微信回调处理方法
     */
    public function notify()
    {

        $postStr = file_get_contents('php://input');// 将整个文件读入字符串
        file_put_contents('/www/wwwroot/logs/api.junhailan.com/weixinpay.log',date('Y-m-d H:i:s').'回调数据'.var_export($postStr,true).PHP_EOL,FILE_APPEND);

        /*
        $postStr = '<xml><appid><![CDATA[wxb2198cca99031de1]]></appid>
<attach><![CDATA[64|80|27]]></attach>
<bank_type><![CDATA[OTHERS]]></bank_type>
<cash_fee><![CDATA[1]]></cash_fee>
<fee_type><![CDATA[CNY]]></fee_type>
<is_subscribe><![CDATA[N]]></is_subscribe>
<mch_id><![CDATA[1565202181]]></mch_id>
<nonce_str><![CDATA[9dbae1af7e660f5a5dde2174060f47d9]]></nonce_str>
<openid><![CDATA[oEDnY5VI3HIbLQCxLOc88qFun3JQ]]></openid>
<out_trade_no><![CDATA[vip_tmp322202106228039826320]]></out_trade_no>
<result_code><![CDATA[SUCCESS]]></result_code>
<return_code><![CDATA[SUCCESS]]></return_code>
<sign><![CDATA[4E3D79E8E38A2B35E47BF836589A53FD]]></sign>
<time_end><![CDATA[20210622184532]]></time_end>
<total_fee>1</total_fee>
<trade_type><![CDATA[JSAPI]]></trade_type>
<transaction_id><![CDATA[4200001172202106224897300202]]></transaction_id>
</xml>';
        */
        
        if (!empty($postStr)) {
            libxml_disable_entity_loader(true);//  禁用加载外部实体的功能
            // 先做签名校验
            $data = json_decode(json_encode(simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
            ksort($data);//根据下标进行排序
            $buff = '';
            foreach ($data as $k => $v){
                if($k != 'sign'){
                    $buff .= $k . '=' . $v . '&';
                }
            }

            if(empty($data['attach'])){
                $this->weixinErrorEcho('附加数据为空');
            }
            $attach = explode('|', $data['attach']);

            $enterpriseId = $attach[0];
            unset($attach[0]);
            $userCentId = $attach[1];
            unset($attach[1]);

            //获取支付配置
            $objMPaymentSetting = new MPaymentSetting($userCentId, $enterpriseId);
            $result = $objMPaymentSetting->getPayData(StatusCode::$payType['wxPay']);
            if (!$result->isSuccess() || empty($result->getData())) {
                $this->weixinErrorEcho('获取微信配置错误');
            }
            $payment = $result->getData();

            /*
            $weixinPayConfigData = Factory::config()->getAppoint('weixin', 'pay');
            if(empty($weixinPayConfigData)){
                $this->weixinErrorEcho('微信配置错误');
            }

            $stringSignTemp = $buff . 'key='.$weixinPayConfigData['apiPartnerKey'];*/


            $stringSignTemp = $buff . 'key='.$payment['apiPartnerKey'];
            $sign = strtoupper(md5($stringSignTemp)); //加密后将所有字母转换成大写
            if($sign !== $data['sign']){
                $this->weixinErrorEcho('签名错误');
            }
            //  函数转换形式良好的 XML 字符串为 SimpleXMLElement 对象。
            $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
            //通信标识
            if ($postObj->return_code == 'SUCCESS') {
                //业务结果
                if ($postObj->result_code == 'SUCCESS') {

                    $response_content = (array)$postObj;
                    $data = array(
                        'attach'         => $response_content['attach'], // 附加数据
                        'transaction_id' => $response_content['transaction_id'], // 微信支付订单号
                        'out_trade_no'   => $response_content['out_trade_no'],  // 商户订单号
                        'time_end'       => $response_content['time_end'],      // 支付完成时间
                        'total_fel'      => $response_content['total_fee'] / 100, //支付金额(转化为元)
                    );

                    if(empty($data['attach'])){
                        $this->weixinErrorEcho('附加数据为空');
                    }
                    $attach = explode('|', $data['attach']);


                    $enterpriseId = $attach[0];
                    unset($attach[0]);
                    $userCentId = $attach[1];
                    unset($attach[1]);

                    $allOrdersId = array_values($attach);


                    //处理销售订单
                    if (strpos( $data['out_trade_no'],'tmp') === false || substr($data['out_trade_no'],0,3) == 'tmp') {
                        $updateOrderData = [
                            'outerTradeNo' => $data['transaction_id'],
                            'payType' => StatusCode::$payType['wxPay'],
                            'payStatus' => StatusCode::$standard,
                            'orderStatus' => StatusCode::$orderStatus['waitDelivery'],
                            'payTime' => strtotime($data['time_end']),
                            'total_fel'=> $data['total_fel'],
                            'pay_way'=>StatusCode::$payType['wxPay']
                        ];

                        $objMOrder = new MOrder($userCentId, $enterpriseId);
                        if(strpos( $data['out_trade_no'],'tmp') === false){
                            $result = $objMOrder->updateOrderPayData($updateOrderData, ['id'=>$allOrdersId,'no'=>$data['out_trade_no']],true);// 修改订单的支付状态
                        }else{
                            $result = $objMOrder->updateOrderPayData($updateOrderData, ['id'=>$allOrdersId,'outerTradeNo'=>$data['out_trade_no']],true);// 修改订单的支付状态
                        }

                        if($result->isSuccess()){
                            $result = array(
                                'return_code' => 'SUCCESS',
                                'return_msg'  => 'OK',
                            );
                            echo arrayToWeiXinXml($result);// 数组转xml
                            exit();
                        }else{
                            $this->weixinErrorEcho($result->getData());
                        }
                    }

                    //处理会员卡订单
                    if (strpos( $data['out_trade_no'],'tmp') !== false && substr($data['out_trade_no'],0,3) == 'vip') {
                        $vipOrderData = [
                            'outerTradeNo' => $data['transaction_id'],
                            'payType' => StatusCode::$payType['wxPay'],
                            'payStatus' => StatusCode::$standard,
                            'payTime' => strtotime($data['time_end']),
                        ];

                        $objMVipCard = new MVipCard($enterpriseId, $userCentId);
                        // 修改订单支付状态，支付成功后赠送对应优惠券
                        $result = $objMVipCard->updateVipOrderPayData($vipOrderData, ['id'=>$allOrdersId,'outerTradeNo'=>$data['out_trade_no']],true);

                        // 会员卡订单表
                        $objDVipCard = new DVipCardOrder();
                        $objDVipCard->setTable('qianniao_vip_card_order_'.$enterpriseId);
                        // 费用类型
                        $objDAccountType = new DAccountType('finance');
                        $objDAccountType->setTable('qianniao_account_type');
                        if($result->isSuccess()){
                            //微信回调方法，新增一条已审核的费用单
                            //判断有无会员卡消费费用类型
                            $accountTypeResult = $objDAccountType->query('select * from qianniao_account_type where type = '.StatusCode::$standard.' and name like "%会员卡%"');
                            if($accountTypeResult === false){
                                $this->weixinErrorEcho($objDAccountType->error());
                            }
                            if(empty($accountTypeResult)){ //没有创建一个收入的会员卡消费类型
                                $accountTypeDate = [
                                    'enterpriseId' => $enterpriseId,
                                    'name' => '会员卡',
                                    'type' => StatusCode::$standard,
                                    'remarks' => '购买会员卡',
                                    'createTime' => time()
                                ];
                                $accountTypeInsert = $objDAccountType->insert($accountTypeDate);
                                if($accountTypeInsert === false){
                                    $this->weixinErrorEcho($objDAccountType->error());
                                }
                            }

                            //查询当前会员卡订单信息
                            foreach ($allOrdersId as $cardOrderId) {
                                $vipCardResult = $objDVipCard->get($cardOrderId);
                                if($vipCardResult === false){
                                    $this->weixinErrorEcho($objDVipCard->error());
                                }
                                //获取微信默认账户信息
                                $objMAccount = new MAccount($enterpriseId, $userCentId);
                                $defaultAccountResult = $objMAccount->getDefaultAccount($vipCardResult['payType']);

                                if ($defaultAccountResult->isSuccess() == false) {
                                    $this->weixinErrorEcho($defaultAccountResult->getData());
                                }
                                $defaultAccount = $defaultAccountResult->getData();
                                if(empty($defaultAccount)){
                                    $this->weixinErrorEcho('支付方式对应的银行账户为空');
                                }
                                
                                //组装费用单信息
                                $expenseSingleData = [
                                    'currentUnitId'           => $vipCardResult['customerId'],
                                    'currentUnit'             => $vipCardResult['customerName'],
                                    'type'                    => StatusCode::$delete,
                                    'billTime'                => time(),
                                    'manager'                 => '',
                                    'shopId'                  => $vipCardResult['shopId'],
                                    'shopName'                => '',
                                    'consumeTypeId'           => !empty($accountTypeResult)? $accountTypeResult[0]['id'] : $accountTypeInsert,
                                    'consumeTypeName'         => !empty($accountTypeResult)? $accountTypeResult[0]['name'] : $accountTypeDate['name'],
                                    'totalCollectionAmount'   => $vipCardResult['payAmount'],
                                    'totalPreferentialAmount' => 0,
                                    'totalActualAmount'       => $vipCardResult['payAmount'],
                                    'payType'                 => StatusCode::$standard,
                                    'auditStatus'             => StatusCode::$auditStatus['auditing'],
                                    'deleteStatus'            => StatusCode::$standard,
                                    'expenseSingleAccountDate'=> [
                                        [
                                            'expenseName' => 'vip会员卡收入',
                                            'amount' => $vipCardResult['payAmount'],
                                            'settlementMethodId' => StatusCode::$payType['wxPay'],
                                            'settlementAccount' => StatusCode::$payType[1],
                                            'accountId' => $defaultAccount['id'],
                                            'preferentialAmount' => 0
                                        ]
                                    ]
                                ];

                                // 添加一条费用单
                                $objMExpenseSingle = new MExpenseSingle($enterpriseId, $userCentId);
                                $expenseSingleResult = $objMExpenseSingle->addExpenseSingle($expenseSingleData);
                                if ($expenseSingleResult->isSuccess() == false) {
                                    $this->weixinErrorEcho($expenseSingleResult->getData());
                                }
                                //审核
                                $updateExpenseSingle = $objMExpenseSingle->updateExpenseStatus(['id'=>$expenseSingleResult->getData(),'createTime'=>time()]);
                                if ($updateExpenseSingle->isSuccess() == false) {
                                    $this->weixinErrorEcho($updateExpenseSingle->getData());
                                }
                            }
                            $result = array(
                                'return_code' => 'SUCCESS',
                                'return_msg'  => 'OK',
                            );
                            echo arrayToXml($result); // 数组转xml内容
                            exit();
                        }else{
                            $this->weixinErrorEcho($result->getData());
                        }
                    }

                    //处理预约项目订单
                    if (substr($data['out_trade_no'],0,2) == 'wx') {
                        $Msub = new MShopSubscribe($enterpriseId);
                        $subOrder = $Msub->details(['order_id' => $data['out_trade_no']]);
                        $subOrder = $subOrder->getData();
                        if ($subOrder['paid'] == 1){
                            //已支付
                            $result = array(
                                'return_code' => 'SUCCESS',
                                'return_msg'  => 'OK',
                            );
                            echo arrayToXml($result); // 数组转xml内容
                            exit();
                        }

                        $res = $Msub->paySuccess($data['out_trade_no']);
                        if ($res){
                            $result = array(
                                'return_code' => 'SUCCESS',
                                'return_msg'  => 'OK',
                            );
                            echo arrayToXml($result); // 数组转xml内容
                            exit();
                        }else{
                            $this->weixinErrorEcho('失败');
                        }
                    }

                    //处理优惠卡订单
                    if (substr($data['out_trade_no'],0,2) == 'car') {
                        $Mcard = new MShopCardOrder($enterpriseId);
                        $order = $Mcard->details(['order_id' => $data['out_trade_no']]);
                        $order = $order->getData();
                        if ($order['paid'] == 1){
                            //已支付
                            $result = array(
                                'return_code' => 'SUCCESS',
                                'return_msg'  => 'OK',
                            );
                            echo arrayToXml($result); // 数组转xml内容
                            exit();
                        }

                        $res = $Mcard->paySuccess($data['out_trade_no']);
                        if ($res){
                            $result = array(
                                'return_code' => 'SUCCESS',
                                'return_msg'  => 'OK',
                            );
                            echo arrayToXml($result); // 数组转xml内容
                            exit();
                        }else{
                            $this->weixinErrorEcho('失败');
                        }
                    }


                    $this->weixinErrorEcho('out_trade_no错误');
                } else {
                    $this->weixinErrorEcho($postObj->err_code.':'.$postObj->err_code_des);
                }
            } else {
                $this->weixinErrorEcho($postObj->return_msg);
            }
        }else{
            $this->weixinErrorEcho('微信回调数据为空');
        }
    }

    /**
     * 统一错误输出
     */
    public function weixinErrorEcho($errorMsg){
        $result = array(
            'return_code' => 'FAIL',
            'return_msg'  => $errorMsg,
        );
        echo arrayToWeiXinXml($result);
        exit();
    }
}