<?php
/**
 * Created by PhpStorm.
 * User: leo
 * Date: 2018/2/24
 * Time: 下午12:48
 */

namespace frontendApi\modules\v1\controllers;

use common\helpers\Alarm;
use common\helpers\Cache;
use common\helpers\Date;
use common\helpers\DingTalk;
use common\helpers\Form;
use common\helpers\LoggerTool;
use common\helpers\Logistics;
use common\helpers\Tool;
use common\helpers\UPOP\PaySign;
use common\helpers\user\Info;
use common\models\ApproachOrder;
use common\models\ApproachOrderGoods;
use common\models\DecOrder;
use common\models\forms\ApproachOrderForm;
use common\models\forms\DeclarationForm;
use common\models\forms\OrderForm;
use common\models\Order;
use common\models\OrderGoods;
use common\models\ReceiveAddress;
use common\models\Region;
use common\models\ShopGoods;
use common\models\User;
use common\models\UserBonus;
use common\models\UserWallet;
use Exception;
use Yii;
use yii\data\Pagination;
use yii\db\Query;
use yii\web\HttpException;

class ShopController extends BaseController {

    public $modelClass = DecOrder::class;

    const TRANSACTION_TYPE_PAYMENT = 'payment';

    /**
     * 商品列表
     * @return mixed
     * @throws \yii\web\HttpException
     */
    public function actionIndex() {
        $cateId = \Yii::$app->request->get('cateId', 1);

        // 海外商品特定用户开放查询
//        $loginUserId = \Yii::$app->user->id;
//        if ($cateId == 2 && $loginUserId != '80552117701578757') {
//            // 通过设定一个不存在的值,让查询变为空
//            $cateId = 100;
//        }

        $condition = " AND CATE_ID={$cateId} AND STATUS=1 AND (FIND_IN_SET(2,GIFT_TYPE)>0";
//        $isStudio = User::getEnCodeInfo(\Yii::$app->user->id)['IS_STUDIO'];
//        if($isStudio==1){
//            $condition.= " OR FIND_IN_SET(4,GIFT_TYPE)>0";
//        }
        $condition.=")";

        $data = ShopGoods::lists($condition, [], [
            'orderBy' => 'SORT ASC,CREATED_AT DESC',
            'from' => ShopGoods::tableName(),
        ]);
        foreach ($data['list'] as $key => $value) {
            $data['list'][$key]['DISCOUNT'] = $value['SELL_DISCOUNT'] * 100;
            $data['list'][$key]['CATE'] = ShopGoods::GOODS_TYPE[$value['CATE_ID']]['name'] ?? '';
        }
        return static::notice($data);
    }

    /**
     * 获取商品详情
     * @return mixed
     * @throws \yii\web\HttpException
     */
    public function actionGoodsDetail(){
        $id = \Yii::$app->request->get('id');
        $data = null;
        if($id){
            $data = ShopGoods::findOneAsArray('ID=:ID AND STATUS=1', [':ID'=>$id]);
        }
        return static::notice($data);
    }

    /**
     * 购物车订单展示
     * @throws \yii\web\HttpException
     */
    public function actionShowCart(){
        // 媒体设备
        $device = \Yii::$app->request->get('device', 'website');

        $userId = \Yii::$app->user->id;
        $allAddress = ReceiveAddress::findAllAsArray('USER_ID=:USER_ID', [':USER_ID'=>$userId]);
        if($allAddress) {
            foreach ($allAddress as $key => $row) {
                $allAddress[$key]['PROVINCE_NAME'] = Region::getCnName($row['PROVINCE']);
                $allAddress[$key]['CITY_NAME'] = Region::getCnName($row['CITY']);
                $allAddress[$key]['COUNTY_NAME'] = Region::getCnName($row['COUNTY']);
            }
        }
        $userBalance = [
            'points' => 0,
            'cash' => 0,
            'exchange' => 0
        ];
        if ($userBonusResult = UserBonus::findOneAsArray(['USER_ID' => $userId])) {
            $userBalance['points'] = $userBonusResult['RECONSUME_POINTS'];
            $userBalance['exchange'] = $userBonusResult['EXCHANGE_POINTS'];
        }
        if ($userCashResult = UserWallet::findOneAsArray(['USER_ID' => $userId])) {
            $userBalance['cash'] = $userCashResult['CASH'];
        }

        return static::notice([
            'payList' => ShopGoods::getPayMethod(),
            'allAddress' => $allAddress,
            'userBalance' => $userBalance,
            'onlinePayList' => ShopGoods::getPayMethod($device)
        ]);
    }

    /**
     * 确认订单
     */
    public function actionSureOrder(){
        if (\Yii::$app->request->isPost) {
            $formModel = new OrderForm();
            $formModel->scenario = 'userOrder';
            $formModel->remark = '复销备注';
            $post = \Yii::$app->request->post();
            $post['type'] = DeclarationForm::TYPE_FX;
            if ($formModel->load($post, '') && $formModel->add()) {
                return static::notice('购物成功');
            } else {
                return static::notice(Form::formatErrorsForApi($formModel->getErrors()),400);
            }
        }
    }

    /**
     * 订单支付成功
     * @throws \yii\web\HttpException
     */
    public function actionPaySuccess(){
        $orderSn = \Yii::$app->request->get('orderSn');
        $data = null;
        if($orderSn){
            $data = Order::findOneAsArray('SN=:SN', [':SN'=>$orderSn]);
        }
        return static::notice($data);
    }

    /**
     * 我的报单
     * @return mixed
     * @throws \yii\web\HttpException
     */
    public function actionDecOrderList() {
        $condition = ' AND USER_ID=:USER_ID AND IS_DEL=0';
        $params[':USER_ID'] = \Yii::$app->user->id;
        $data = DecOrder::lists($condition, $params, [
            'select' => 'DO.*,U.USER_NAME USER_NAME,U.REAL_NAME REAL_NAME,RU.USER_NAME REC_USER_NAME,RU.REAL_NAME REC_REAL_NAME,CU.USER_NAME CON_USER_NAME,CU.REAL_NAME CON_REAL_NAME,OG.*',
            'orderBy' => 'DO.CREATED_AT DESC',
            'from' => DecOrder::tableName() . ' AS DO',
            'join' => [
                ['LEFT JOIN', User::tableName() . ' AS U', 'DO.TO_USER_ID=U.ID'],
                ['LEFT JOIN', User::tableName() . ' AS RU', 'DO.REC_USER_ID=RU.ID'],
                ['LEFT JOIN', User::tableName() . ' AS CU', 'DO.CON_USER_ID=CU.ID'],
                ['LEFT JOIN', OrderGoods::tableName() . ' AS OG', 'OG.ORDER_SN=DO.ORDER_SN'],
            ],
        ]);
        return static::notice($data);
    }

    /**
     * 我的订单(全部)
     * @return void
     * @throws HttpException
     */
    public function actionOrderList()
    {
        $uname = Info::getUserNameByUserId(\Yii::$app->user->id);
        $condition = " O.IS_DELETE = 0 AND O.ORDER_TYPE='FX' AND (O.USER_ID=:USER_ID OR O.CREATE_USER='$uname') AND O.CREATED_AT >= 1704038400";
        $params[':USER_ID'] = \Yii::$app->user->id;
        $orderQuery = Order::find()
            ->alias('O')
            ->where($condition, $params)
            ->select('O.*,U.REAL_NAME,OG.REAL_PRICE,OG.BUY_NUMS,OG.SKU_CODE,OG.GOODS_TITLE,OG.REAL_PV,OG.ORDER_SN,OG.GOODS_ID')
            ->join('INNER JOIN', User::tableName() . ' AS U', 'U.ID=O.USER_ID')
            ->join('INNER JOIN', OrderGoods::tableName() . ' AS OG', 'OG.ORDER_SN=O.SN')
            ->orderBy('O.CREATED_AT DESC');

        // 订单中间表只查询待支付和支付失败的订单
        $params[':NOT_PAID'] = \Yii::$app->params['orderStatus']['notPaid']['value'];   // 待支付
        $params[':FAIL_PAID'] = \Yii::$app->params['orderStatus']['failPaid']['value'];   // 支付失败
        $orderStandardQuery = ApproachOrder::find()
            ->alias('O')
            ->where($condition . ' AND (O.STATUS = :NOT_PAID OR O.STATUS = :FAIL_PAID) AND O.CREATED_AT >= 1704038400', $params)
            ->select('O.*,U.REAL_NAME,OG.REAL_PRICE,OG.BUY_NUMS,OG.SKU_CODE,OG.GOODS_TITLE,OG.REAL_PV,OG.ORDER_SN,OG.GOODS_ID')
            ->join('INNER JOIN', User::tableName() . ' AS U', 'U.ID=O.USER_ID')
            ->join('INNER JOIN', ApproachOrderGoods::tableName() . ' AS OG', 'OG.ORDER_SN=O.SN')
            ->orderBy('O.CREATED_AT DESC');

        $queryAll = $orderQuery->union($orderStandardQuery, true);
        $query = (new Query())->from(['Q' => $queryAll])->select('Q.*')->distinct()->orderBy(['CREATED_AT' => SORT_DESC]);

        $totalCount = $query->count();
        $pagination = new Pagination(['totalCount' => $totalCount, 'pageSize' => \Yii::$app->request->get('pageSize')]);
        $lists = $query->offset($pagination->offset)->limit($pagination->limit)->all();

        $data = [
            'list' => $lists,
            'currentPage'=>$pagination->page,
            'totalPages'=>$pagination->pageCount,
            'startNum' => $pagination->page * $pagination->pageSize + 1,
            'totalCount' => $pagination->totalCount,
            'pageSize' => $pagination->pageSize,
        ];

        foreach ($data['list'] as $key => $value) {
            $data['list'][$key]['ORDER_TYPE'] = $value['ORDER_TYPE'] == 'ZC' ? '首单' : '复消';
            $data['list'][$key]['PAY_AT'] = $value['PAY_AT'] ? Date::convert($value['PAY_AT'],'Y-m-d H:i:s') : '';
            $data['list'][$key]['CREATED_AT'] = $value['CREATED_AT'] ? Date::convert($value['CREATED_AT'],'Y-m-d H:i:s') : '';
            $data['list'][$key]['PAY_TYPE'] = ShopGoods::payTypes()[$value['PAY_TYPE']]['name'] ?? '';
            $data['list'][$key]['STATUS'] = \Yii::$app->params['orderStatus'][$value['STATUS']]['label'] ?? '';
        }

        return static::notice($data);
    }

    /**
     * 我的订单(已支付))
     * @return mixed
     * @throws \yii\web\HttpException
     */
    public function actionOrderCompleteList() {
        $uname = Info::getUserNameByUserId(\Yii::$app->user->id);
        $condition = " AND IS_DELETE=0 AND ORDER_TYPE='FX' AND (USER_ID=:USER_ID OR CREATE_USER='$uname')";
        $params[':USER_ID'] = \Yii::$app->user->id;
        $data = Order::lists($condition, $params, [
            'select' => 'O.*,U.REAL_NAME,OG.*',
            'orderBy' => 'O.CREATED_AT DESC',
            'from' => Order::tableName() . ' AS O',
            'join' => [
                ['LEFT JOIN', User::tableName() . ' AS U', 'U.ID=O.USER_ID'],
                ['LEFT JOIN', OrderGoods::tableName() . ' AS OG', 'OG.ORDER_SN=O.SN'],
            ],
        ]);
        foreach ($data['list'] as $key => $value) {
            $data['list'][$key]['ORDER_TYPE'] = $value['ORDER_TYPE']=='ZC' ? '首单' : '复消';
            $data['list'][$key]['PAY_AT'] = Date::convert($value['PAY_AT'],'Y-m-d H:i:s');
            $data['list'][$key]['PAY_TYPE'] = ShopGoods::payTypes()[$value['PAY_TYPE']]['name'] ?? '';
            $data['list'][$key]['STATUS'] = \Yii::$app->params['orderStatus'][$value['STATUS']]['label'] ?? '';
        }
        return static::notice($data);
    }

    /**
     * 我的订单(待支付)
     * @return mixed
     * @throws HttpException
     */
    public function actionOrderIncompleteList() {
        $uname = Info::getUserNameByUserId(\Yii::$app->user->id);
        $condition = " AND IS_DELETE=0 AND ORDER_TYPE='FX' AND (USER_ID=:USER_ID OR CREATE_USER='{$uname}')";
        $params[':USER_ID'] = \Yii::$app->user->id;
        $data = ApproachOrder::lists($condition, $params, [
            'select' => 'O.*,U.REAL_NAME,OG.*',
            'orderBy' => 'O.CREATED_AT DESC',
            'from' => Order::tableName() . ' AS O',
            'join' => [
                ['LEFT JOIN', User::tableName() . ' AS U', 'U.ID=O.USER_ID'],
                ['LEFT JOIN', ApproachOrderGoods::tableName() . ' AS OG', 'OG.ORDER_SN=O.SN'],
            ],
        ]);
        foreach ($data['list'] as $key => $value) {
            $data['list'][$key]['ORDER_TYPE'] = $value['ORDER_TYPE']=='ZC' ? '首单' : '复消';
            $data['list'][$key]['PAY_AT'] = Date::convert($value['PAY_AT'],'Y-m-d H:i:s');
            $data['list'][$key]['PAY_TYPE'] = ShopGoods::payTypes()[$value['PAY_TYPE']]['name'] ?? '';
            $data['list'][$key]['STATUS'] = \Yii::$app->params['orderStatus'][$value['STATUS']]['label'] ?? '';
        }
        return static::notice($data);
    }

    /**
     * 会员复消
     */
    public function actionReconsume() {
        $isStudio = User::getEnCodeInfo(\Yii::$app->user->id)['IS_STUDIO'];
        $condition = " AND STATUS=1";
        if($isStudio==1){
            $condition .= " AND  (FIND_IN_SET(4,GIFT_TYPE)>0)";
        }
//        $condition.= ")";

        $data = ShopGoods::lists($condition, [], [
            'orderBy' => 'SORT ASC,CREATED_AT DESC',
            'from' => ShopGoods::tableName(),
        ]);
        foreach ($data['list'] as $key => $value) {
            $data['list'][$key]['DISCOUNT'] = $value['SELL_DISCOUNT']*100;
        }
        return static::notice($data);
    }

    /**
     * 帮会员复消购物车
     * @throws \yii\web\HttpException
     */
    public function actionReconsumeCart(){
        $userId = \Yii::$app->user->id;
        $payList = ['cash'=>['name'=>'消费点数支付'],];
        $userBalance = [
            'points' => 0,
            'cash' => 0
        ];
        if ($userBonusResult = UserBonus::findOneAsArray(['USER_ID' => $userId])) {
            $userBalance['points'] = $userBonusResult['RECONSUME_POINTS'];
        }
        if ($userCashResult = UserWallet::findOneAsArray(['USER_ID' => $userId])) {
            $userBalance['cash'] = $userCashResult['CASH'];
        }
        return static::notice(['payList'=>$payList,'userBalance'=>$userBalance]);
    }

    /**
     * 帮会员复消确认订单
     */
    public function actionReconsumeSureOrder(){
        if (\Yii::$app->request->isPost) {
            $formModel = new OrderForm();
            $formModel->scenario = 'reconsumeOrder';
            $formModel->remark = '帮会员复销';
            $post = \Yii::$app->request->post();
            $post['type'] = DeclarationForm::TYPE_FX;
            if ($formModel->load($post, '') && $formModel->reconsumeAdd()) {
                return static::notice('帮会员复消成功');
            } else {
                return static::notice(Form::formatErrorsForApi($formModel->getErrors()),400);
            }
        }

        return static::notice('无效请求');
    }

    /**
     * 确认订单
     */
    public function actionSureApproachOrder(){
        if (\Yii::$app->request->isPost) {
            $post = \Yii::$app->request->post();
            // 银行代码
            $bankCode = $post['payType'];
            // 支付宝WAP/正扫 -> 支付宝支付; 微信WAP/正扫 -> 微信支付
            $post['payType'] = ShopGoods::bankCode2PayType($bankCode);

            $formModel = new ApproachOrderForm();
            $formModel->scenario = 'userOrder';
            $formModel->remark = '复销备注';

            $post['type'] = DeclarationForm::TYPE_FX;
            if ($formModel->load($post, '') && $order = $formModel->add()) {
                // 订单商品
                $orderProducts = ApproachOrderGoods::findOneAsArray(['ORDER_SN' => $order->SN]);
                // 支付报文
                $payload = [
                    "version" => "2.0.0",   // 版本号(定值2.0.0).
                    "trade_code" => "PAY",  // 交易代码(定值PAY)
                    "bank_code" => $bankCode, // 银行代码
                    "agencyId" => \Yii::$app->params['UPOP']['agencyId'], // 商户号
                    "child_merchant_no" => \Yii::$app->params['UPOP']['childMerchantId'], // 子商户号
                    "terminal_no" => \Yii::$app->params['UPOP']['terminalId'], // 商户终端号
                    "order_no" => $order->SN,   // 第三方订单号
                    "amount" => sprintf("%.2f", $order['PAY_AMOUNT']),   // 交易金额(元) 2位小数
//                    "amount" => sprintf("%.2f", 0.1),   // TODO: 交易金额(元) 2位小数
                    "currency_type" => \Yii::$app->params['UPOP']['currencyType'],   // 交易币种 HKD(港币) CNY(人民币)
                    "sett_currency_type" => 'HKD',  // 清算币种 HKD(港币) 固定
                    "product_name" => $orderProducts['GOODS_TITLE'], // 产品名称
                    "return_url" => \Yii::$app->params['UPOP']['returnUrl'], // 同步通知地址
                    "notify_url" => \Yii::$app->params['UPOP']['notifyUrl'], // 异步通知地址
                    "client_ip" => $_SERVER['REMOTE_ADDR'], // 客户端IP(订单⽣成的机器IP，指⽤户浏览器端IP，不是商户服务器IP)
                ];
                // 预支付
                $response = (new PaySign())->sendEncodeData($payload, \Yii::$app->params['UPOP']['backPayUrl']);
                // 预支付结果写入表
                ApproachOrder::updateAll(['REMARK' => json_encode($response['bank_code'] = $bankCode)], 'SN=:SN', [':SN' => $order->SN]);

                return static::notice($response);
            } else {
                return static::notice(Form::formatErrorsForApi($formModel->getErrors()),400);
            }
        }

        return static::notice('无效请求');
    }

    /**
     * iPay88支付成功的webhook.
     * @throws \Exception
     */
    public function actionVerifyApproachOrderIpay88() {
        // iPay88支付成功的webhook.
        $rawPostData = file_get_contents('php://input');
        LoggerTool::notice(['actionVerifyApproachOrder', $rawPostData]);
        $data = [];
        if (strlen($rawPostData) > 0) {
            $rawPostArray = explode('&', $rawPostData);
            foreach ($rawPostArray as $raw) {
                $raw = explode('=', $raw);
                if (count($raw) == 2)
                    $data[$raw[0]] = urldecode($raw[1]);
            }
        }

        // 支付webhook回调日志
        //Tool::approachOrderCall($data);

        try {
            // 订单状态
            $orderStatus = ($data['Status'] == '1') ? \Yii::$app->params['orderStatus']['paid']['value'] : \Yii::$app->params['orderStatus']['failPaid']['value'];

            $oderSn = $data['RefNo'] ?? '';

            $formModel =  new ApproachOrderForm();
            $formModel->scenario = 'verifyPay';
            $load = [
                'sn' => $oderSn,
                'scenario' => 'verifyPay',
                'status' => $orderStatus,
                'note' => [
                    'MerchantCode' => $data['MerchantCode'],
                    'PaymentId' => $data['PaymentId'],
                    'status' => $data['Status'],
                    'Signature' => $data['Signature'],
                    'Currency' => $data['Currency'],
                    'Amount' => $data['Amount'],
                    'TransId' => $data['TransId'],
                    'TranDate' => $data['TranDate'],
                    'BankMID' => $data['BankMID'],
                    'CCNo' => $data['CCNo'],

                ],
            ];

            if ($formModel->load($load, '') && $result = $formModel->verifyPayOnline()) {
                LoggerTool::info($result);

                echo 'RECEIVEOK';
                return http_response_code(200);
            } else {
                echo 'RECEIVEOK';
                LoggerTool::error(Form::formatErrorsForApi($formModel->getErrors()));
                return http_response_code(200);
            }
        } catch (\Exception $e) {
            echo 'RECEIVEOK';
            LoggerTool::error(sprintf('actionVerifyApproachOrderError: File[%s], Line:[%s], Message[%s]', $e->getFile(), $e->getLine(), $e->getMessage()));
            return http_response_code(200);
        }
    }

    public function actionReQueryPayment()
    {
        // 每天巡查一次，查询近24小时的未支付订单. 支付参数记录在NOTE字段中,如没有此数据,则不能进行查询.(待支付、支付方式online、当天订单、未删除)
        $orderList = ApproachOrder::find()
            ->where('STATUS=:STATUS AND PAY_TYPE=:PAY_TYPE AND CREATED_AT>=:CREATED_AT AND DELETED_AT=0',
                [':STATUS' => 0, ':PAY_TYPE' => 'online', ':CREATED_AT' => strtotime(date('Y-m-d', time()))])
            ->andWhere(['not', ['NOTE' => null]])
            ->asArray()
            ->all();
        LoggerTool::debug(['actionReQueryPayment', $orderList]);
        if (!$orderList) {
            return static::notice('no record');
        }

        foreach ($orderList as $order) {
            $message = '';
            // 支付参数记录在NOTE字段中,如没有此数据,则不能进行查询
            $orderPayment = json_decode($order['NOTE'], true);
            $rawPostData = "MerchantCode={$orderPayment['MerchantCode']}&RefNo={$orderPayment['RefNo']}&Amount={$orderPayment['Amount']}";
            try {
                $ch = curl_init();
                $url = 'https://payment.ipay88.com.my/epayment/enquiry.asp' . '?' . $rawPostData;
                curl_setopt($ch, CURLOPT_URL, $url);
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
                $result = curl_exec($ch);

                switch (strtolower($result)) {
                    case '00':  // Successful payment.
                        ApproachOrder::updateAll(['REMARK' => '00: Successful payment'], 'SN=:SN', [':SN' => $order['SN']]);

                        $paymentParams = [
                            'RefNo' => $orderPayment['RefNo'],
                            'Amount' => $orderPayment['Amount'],
                            'PaymentId' => '182',
                            'ProdDesc' => 'Pay for sales',
                            'UserName' => 'MY32',
                            'SignatureType' => 'SHA256',
                            'UserEmail' => 'ek_dummy25@elken.com',
                            'UserContact' => '60172249692',
                        ];
                        $paymentFields = \Yii::$app->iPay88->getPaymentFields($paymentParams, self::TRANSACTION_TYPE_PAYMENT);

                        $formModel =  new ApproachOrderForm();
                        $formModel->scenario = 'verifyPay';
                        $load = [
                            'sn' => $orderPayment['RefNo'],
                            'scenario' => 'verifyPay',
                            'status' => \Yii::$app->params['orderStatus']['paid']['value'],
                            'note' => [
                                'MerchantCode' => $orderPayment['MerchantCode'],
                                'PaymentId' => $paymentFields['PaymentId'],
                                'status' => \Yii::$app->params['orderStatus']['paid']['value'],
                                'Signature' => $paymentFields['Signature'],
                                'Currency' => $paymentFields['Currency'],
                                'Amount' => $paymentFields['Amount'],
                                'TransId' => '',
                                'TranDate' => '',
                                'BankMID' => '',
                                'CCNo' => '',
                            ],
                        ];

                        if ($formModel->load($load, '') && $result = $formModel->verifyPayOnline()) {
                            LoggerTool::info($result);
                        }
                        $message = '(ReQueryIPay88Payment). orderSN{%s} 00: Successful payment';
                        break;
                    case 'invalid parameters':
                        ApproachOrder::updateAll(
                            ['STATUS' => \Yii::$app->params['orderStatus']['failPaid']['value'], 'REMARK' => 'Invalid parameters: Parameters pass in incorrect'],
                            'SN=:SN', [':SN' => $order['SN']]
                        );

                        $message = '(ReQueryIPay88Payment). orderSN{%s} Invalid parameters: Parameters pass in incorrect';
                        break;
                    case 'record not found':
                        ApproachOrder::updateAll(
                            ['STATUS' => \Yii::$app->params['orderStatus']['failPaid']['value'], 'REMARK' => 'Record not found: Cannot found the record'],
                            'SN=:SN', [':SN' => $order['SN']]
                        );
                        $message = '(ReQueryIPay88Payment). orderSN{%s} Record not found: Cannot found the record';
                        break;
                    case 'incorrect amount':
                        $message = '(ReQueryIPay88Payment). orderSN{%s} Incorrect amount: Amount different';
                        ApproachOrder::updateAll(
                            ['STATUS' => \Yii::$app->params['orderStatus']['failPaid']['value'], 'REMARK' => 'Incorrect amount: Amount different'],
                            'SN=:SN', [':SN' => $order['SN']]
                        );
                        break;
                    case 'payment fail':
                        ApproachOrder::updateAll(
                            ['STATUS' => \Yii::$app->params['orderStatus']['failPaid']['value'], 'REMARK' => 'Payment fail: Payment fail'],
                            'SN=:SN', [':SN' => $order['SN']]
                        );
                        $message = '(ReQueryIPay88Payment). orderSN{%s} Payment fail: Payment fail';
                        break;
                    case 'm88admin':
                        ApproachOrder::updateAll(
                            ['STATUS' => \Yii::$app->params['orderStatus']['failPaid']['value'], 'REMARK' => 'M88Admin: Payment status updated by iPay88 Admin(Fail)'],
                            'SN=:SN', [':SN' => $order['SN']]
                        );
                        $message = '(ReQueryIPay88Payment). orderSN{%s} M88Admin: Payment status updated by iPay88 Admin(Fail)';
                        break;
                    default:
                }

                curl_close($ch);

                // 推送消息到预警平台
//                Alarm::reportAlarm(['brand' => 'MSG', 'message'  => sprintf($message, $orderPayment['RefNo'])]);
            } catch (exception $e) {
                curl_close($ch);
                LoggerTool::error('err. ' . $e->getMessage());
//                Alarm::reportAlarm(['brand' => 'MSG', 'message'  => sprintf('err. (ReQueryIPay88Payment). orderSN{%s}. %s', $orderPayment['RefNo'], $e->getMessage())]);
            }
        }

        return static::notice('');
    }

    /**
     * 删除准订单
     */
    public function actionDeleteApproachOrder()
    {
        $orderSn = \Yii::$app->request->post('orderSn');
        // 订单中间表更新订单状态为取消
        ApproachOrder::updateAll(
            [
                'STATUS' => \Yii::$app->params['orderStatus']['cancel']['value'],
                'DELETED_AT' => Date::nowTime(),
                'REMARK' => 'Member cancel order',
            ],
            'SN=:SN',
            [':SN' => $orderSn]);

        return static::notice('');
    }

    /**
     * iPay88支付
     * @return mixed
     * @throws HttpException
     */
    public function actionIPay88()
    {
        // 订单ID
        $paymentParams['RefNo'] = \Yii::$app->request->post('RefNo');
        // 订单
        $order = ApproachOrder::findOne(['SN' => $paymentParams['RefNo']]);
        if (is_null($order) || is_null($order->toArray()) || !$order->toArray()) {
            return static::notice('订单编号无效');
        }
        // 转为分
        $money = $order['PAY_AMOUNT'];

        // 订单金额,元=>分
//        $money = \Yii::$app->request->post('Amount');
        // 马来币汇率
        $exchangeRateMYR = floatval(Cache::getSystemConfig()['exchangeRateMYR']['VALUE'] ?? 0);
        // 计算马来币
        $amount = number_format(round($money * $exchangeRateMYR), 2, '.', '');
//        $amount = number_format($money, 2, '.', '');
//        $amount = number_format(1, 2, '.', ''); // TODO: 测试
        $paymentParams['Amount'] = str_replace('.', '', $amount);
        // (Optional) (int)
        $paymentParams['PaymentId'] = '182';   // 2=信用卡 182=银联
        // Product description. (length 100)
        $paymentParams['ProdDesc'] = 'Pay for sales';
        // Customer name. (length 100)
        $paymentParams['UserName'] = 'MY32';
        $paymentParams['SignatureType'] = 'SHA256';
        // Customer email.  (length 100)
        $paymentParams['UserEmail'] = 'ek_dummy25@elken.com';
        // Customer contact.  (length 20)
        $paymentParams['UserContact'] = '60172249692';

        // (Optional) Merchant remarks. (length 100)
        //$paymentParams['Remark'] = 'Here is the description';
        //merchantkey + merchantcode+ reference Number + amount in cent + currency_code
        $paymentFields = \Yii::$app->iPay88->getPaymentFields($paymentParams, self::TRANSACTION_TYPE_PAYMENT);

        $transactionUrl = \Yii::$app->iPay88->getTransactionUrl(self::TRANSACTION_TYPE_PAYMENT);
        $paymentFields['Amount'] = $amount;
        $res = [
            'paymentFields' => $paymentFields,
            'transactionUrl' => $transactionUrl,
        ];

        // 支付信息写入note
        $order->NOTE = json_encode([
            'MerchantCode' => $paymentFields['MerchantCode'],
            'PaymentId' => $paymentFields['PaymentId'],
            'RefNo' => $paymentFields['RefNo'],
            'Amount' => $paymentFields['Amount'],
            'Currency' => $paymentFields['Currency'],
            'Signature' => $paymentFields['Signature'],
        ]);
        $order->update();

        return static::notice($res);
    }

    /**
     * 推送订单到wst仓储系统
     * @throws HttpException
     * @throws \Exception
     */
    public function actionLogistics()
    {
        $orderSn = \Yii::$app->request->get('sn');
        $order = Order::find()
            ->where('SN=:ORDER_SN', [':ORDER_SN' => $orderSn])
            ->asArray()
            ->one();

        if (!$order) {
            return static::notice('订单【' . $orderSn . '】不存在');
        }
        if ($order['SEND_AT'] > 0) {
            return static::notice('订单【' . $orderSn . '】不可重复推送');
        }

        $logistics = new Logistics();
        $response = $logistics->createOrder($order);
        LoggerTool::info(['actionLogistics', $response]);
        if ($response['success'] == 1) {
            // 更新db中订单推送成功状态
            if (Order::updateAll(['SEND_AT' => time()], 'SN=:SN', [':SN' => $orderSn])) {
                return static::notice($response);
            } else {
                return static::notice($orderSn . ' 推送wst系统成功, 更新状态失败');
            }
        }

        return static::notice($orderSn . ' 推送wst系统失败');
    }

    /**
     * @throws HttpException
     * @throws \Exception
     */
    public function actionLogisticsAuto()
    {
        $createdAtEnd = strtotime(date('Y-m-d')) - 1;
        // 早0点推送，前一天0-24点的订单
        $orderList = Order::find()
            ->where(
                "(CREATED_AT <= :CREATED_AT_END) AND STATUS=:STATUS AND SEND_AT=:SEND_AT AND (PAY_TYPE='wechat' OR PAY_TYPE='alipay') AND IS_DELETE = 0",
                [
                    ':CREATED_AT_END' => $createdAtEnd,
                    ':STATUS' => \Yii::$app->params['orderStatus']['paid']['value'],
                    ':SEND_AT' => 0,
                ]
            )
            ->asArray()
            ->all();

        if (!$orderList) {
            // 发送预警通知
            $alarm = [
                'stance' => 2,
                'brand' => 'MSG',
                'message'  => '跨境商品推送淘布斯系统终止,原因：无订单',
            ];
            Alarm::reportAlarm($alarm);
            return static::notice('推送wst系统终止,原因：无订单');
        }

        $orderSnSuccess = [];
        $orderSnFailed = [];
        $logistics = new Logistics();
        foreach ($orderList as $order) {
            // 发送wst仓库系统
            $response = $logistics->createOrder($order);
            LoggerTool::info($response);
            if ($response['success'] == 1) {
                // 写入mongo
                Tool::wstOrderCall($response['data']);
                $orderSnSuccess[] = $order['SN'];
            } else {
                // 记录推送结果
                $orderSnFailed[] = $order['SN'];
                // 发送预警通知
                $alarm = [
                    'stance' => 5,
                    'brand' => 'MSG',
                    'message'  => sprintf('跨境商品推送淘布斯系统失败. 订单号[%s], error[%s]', $order['SN'], $response),
                ];
                Alarm::reportAlarm($alarm);
            }
        }

        $notify = '跨境商品推送淘布斯系统结束. ';
        // 更新db中订单推送成功状态
        if (count($orderSnSuccess) > 0) {
            $orderSnSuccessIds = implode("','", $orderSnSuccess);
            Order::updateAll(['SEND_AT' => time()], "SN IN ('" . $orderSnSuccessIds . "')");
            $notify .= sprintf('成功订单数{%d}, 订单号[%s];', count($orderSnSuccess), implode(', ', $orderSnSuccess));
        }
        if (count($orderSnFailed) > 0) {
            $notify .= sprintf('失败订单数{%d}, 订单号[%s]', count($orderSnFailed), implode(', ', $orderSnFailed));
        }

        // 发送预警通知
        $alarm = [
            'stance' => 2,
            'brand' => 'MSG',
            'message'  => $notify,
        ];
        Alarm::reportAlarm($alarm);

        return static::notice($notify);
    }

    /**
     * UPOP支付成功的webhook.
     * @throws \Exception
     */
    public function actionUpopWebhook() {
        $rawPostData = \Yii::$app->request->post();
        LoggerTool::debug(['UPOP - webhook: (init).', $rawPostData]);

        $agencyId = $rawPostData['agencyId'] ?? '';
        $signData = $rawPostData['signData'] ?? '';
        $encryptKey = $rawPostData['encryptKey'] ?? '';
        $encryptData = $rawPostData['encryptData'] ?? '';
        // 终端号
        if (!$agencyId || $agencyId != \Yii::$app->params['UPOP']['agencyId']) {
            LoggerTool::error([sprintf('UPOP - webhook: (error). agencyId {%s} does not exits or error.', $agencyId)]);
            echo 'success';
        }
        // 解密
        $payload = (new PaySign())->decodeData($encryptKey, $signData, $encryptData);
        if (!$payload) {
            LoggerTool::error(['UPOP - webhook: (error). payload is false']);
            echo 'success';
        }

        try {
            // 支付状态
            $orderStatus = ($payload['pay_result'] == '1') ? \Yii::$app->params['orderStatus']['paid']['value'] : \Yii::$app->params['orderStatus']['failPaid']['value'];

            $formModel =  new ApproachOrderForm();
            $formModel->scenario = 'verifyPay';
            $load = [
                'sn' => $payload['order_no'],
                'scenario' => 'verifyPay',
                'status' => $orderStatus,
                'note' => $payload,
            ];
            if ($formModel->load($load, '') && $formModel->verifyPayUPOP()) {
                LoggerTool::debug([sprintf('UPOP - webhook: (success). orderNo: {%s}', $payload['order_no'])]);
                echo 'success';
            } else {
                echo 'success';
                LoggerTool::error([sprintf('UPOP - webhook: (error). orderNo: {%s}', $payload['order_no'])]);
            }
        } catch (\Exception $e) {
            echo 'success';
            LoggerTool::error([sprintf('UPOP - webhook: (exp). orderNo: {%s}, File[%s], Line:[%s], Message[%s]', $payload['order_no'], $e->getFile(), $e->getLine(), $e->getMessage())]);
        }
    }
}
