ECPay Cancel Order (Refund credit card)

class Order_lib{
    private $order = NULL;
    public $err = '';
    private $ci = null;
    private $allpay = null;
    private $ut = null;

    function __construct($params) {
        $ci =& get_instance();

        $ci->load->model('orders_m');

        $ci->load->config('config_wikicms');
        $this->allpay = $ci->config->item('allpay');

        //B2B API
        $config = $ci->config->item('utapi');
        $this->ut = new UTravelerHelper();
        $this->ut->ServiceURL = $config['service'];
        $this->ut->client_id = $config['client_id'];
        $this->ut->client_secret = $config['client_secret'];

        $this->ci = $ci;

        $this->order = $params['order'];
    }

	public function __destruct(){

	}

    public function cancel(){
        $order = $this->order;

        //如果訂單未付款,直接修改status就好
        if($order->payment_status == 0){
            $result = $this->update_order_status(2);
            if($result == false){
                return false;
            }

            return true;
        }

        //是信用卡而且結帳金額大於0需要取消歐付寶訂單
        if($order->payment_type == 'Credit'){
            if($order->final_price > 0){
                //Cancel allpay order
                $result = $this->cancel_allpay_order($order);
                if($result == false){
                    return false;
                }

                $result = $this->update_payment_status(4);//refund已退款
                if($result == false){
                    return false;
                }
            }
        }

        //Cancel B2B order
        $result = $this->cacnel_b2b_orders($order);
        //logg($result);
        if($result == false){
            return false;
        }

        $result = $this->update_order_status(2);
        if($result == false){
            return false;
        }

        return true;
    }

    private function cancel_allpay_order($order){
        try{
            $merchantTradeNo = $order->trade_no;
            $oPayment = new ECPay_AllInOne();

            /* 服務參數 */
            $oPayment->ServiceURL = $this->allpay['query_service'];
            $oPayment->HashKey = $this->allpay['hash_key'];
            $oPayment->HashIV = $this->allpay['hash_iv'];
            $oPayment->MerchantID = $this->allpay['merchant_id'];

            //查詢訂單資料
            //發生過付款成功,但是查詢不到訂單內容的問題
            $oPayment->Query['MerchantTradeNo'] = $merchantTradeNo;
            $arQueryFeedback = $oPayment ->QueryTradeInfo();
            //logg($arQueryFeedback);

            $tradeNo = $arQueryFeedback['TradeNo'];
            $tradeAmt = $arQueryFeedback['TradeAmt'];

            $orderTime = strtotime($arQueryFeedback['PaymentDate']);
            $today = std_date(time());
            $today_cut = std_date(time()) . ' 20:00';
            //logg(date("Y-m-d"));
            //logg(date("Y-m-d", $orderTime));

            //https://payment.ecpay.com.tw/CreditDetail/DoAction
            $oPayment->ServiceURL = $this->allpay['refund_service'];
            $oPayment->Action['MerchantTradeNo'] = $merchantTradeNo;
            $oPayment->Action['TradeNo'] = $tradeNo;
            $oPayment->Action['TotalAmount'] = (int)$tradeAmt;

            //歐付寶工程師電話回覆:(2016/11/23)
            //因此如果是隔天的訂單要進行退刷,則直接執行R退刷,(不需要再執行C關帳)
            //後續晚上八點(不是12點)我們也會協助為您關帳,再煩請確認
            //logg($orderTime < strtotime($today) || $orderTime > strtotime($today_cut));
            if($orderTime > strtotime($today) && $orderTime < strtotime($today_cut)){//今天晚上8點前
                //logg(date('G', time()));
                if(date('G', time()) > 20){
                    $oPayment->Action['Action'] = ECPay_ActionType::R;
                }else{
                    $oPayment->Action['Action'] = ECPay_ActionType::N;
                }
            }else{
              /*
                  $oPayment->Action['MerchantTradeNo'] = $merchantTradeNo;
                  $oPayment->Action['TradeNo'] = $tradeNo;
                  $oPayment->Action['Action'] = ECPay_ActionType::C;//關帳
                  $oPayment->Action['TotalAmount'] = (int)$tradeAmt;
                  $arFeedback = $oPayment->DoAction();
                  //logg($arFeedback);

                  if($merchantTradeNo == 'UTT1478263268001'){
                    //logg($arFeedback);
                  }

                  if($arFeedback != false && $arFeedback['RtnCode'] != 1){
                    throw new Exception('無法關帳');
                  }
              */
              $oPayment->Action['Action'] = ECPay_ActionType::R;//退刷
            }

            $arFeedback = $oPayment->DoAction();
            if($arFeedback != false && $arFeedback['RtnCode'] != 1){
                throw new Exception('無法退刷');
            }

            if (sizeof($arFeedback) > 0) {
                //logg($arFeedback['RtnCode']);
                if(isset($arFeedback['RtnCode']) == false){
                    print_r($arFeedback);
                    exit();
                }

                if($arFeedback['RtnCode'] != 1){
                    throw new Exception('不明錯誤,目前無法取消付款');
                }
            } else {
                throw new Exception('不明錯誤,目前無法取消付款');
            }
        } catch (Exception $e){
            $this->err = $e->getMessage();
            return false;
        }

        return true;
    }

    private function cacnel_b2b_orders($order){
        $prods = $this->ci->orders_m->get_order_products($order->id);
        //logg($prods);

        foreach($prods as $prod){
            //Cancel B2B order
            $res = $this->ut->cancelOrder($order->order_no, $prod->unique_id, 2);

            //helper: api_string_helper
            if(is_json($res) == false){
                $this->err = 'API回傳資料格式錯誤';
                return false;
            }

            $res = json_decode($res);
            //logg($res);
            if($res->status == 'fail'){
                $this->err = $res->message;
                return false;
            }
        }

        return true;
    }

    private function update_order_status($status){
        $ci = $this->ci;

        $data = array(
              'status' => $status,
              'updated_time' => timestamp_string()
        );

        $result = $ci->orders_m->update_order($this->order, $data);
        if($result == false){
            $this->err = '無法更新訂單狀態';
            return false;
        }

        return true;
    }

    private function update_payment_status($status){
        $order = $this->order;
        $ci = $this->ci;

        $data = array(
            'payment_status' => $status
        );
        $result = $ci->orders_m->update_order($order, $data);
        //logg($result);
        if($result == false){
            $this->err = '無法更新訂單刷退狀態';
            return false;
        }

        return true;
    }
}