微信支付全套流程輸出

<?php

namespace app\modules\api\controllers;

use app\dato\ApiResponse;
use app\extensions\TencentSms;
use app\models\QyxClassification;
use app\models\QyxClassificationConfig;
use app\models\QyxMember;
use app\models\QyxUserMember;
use app\models\UserCardvip;
use app\models\UserCardvipList;
use app\modules\api\models\wxbdc\WXBizDataCrypt;
use Yii;


class ClassificationController extends Controller
{
    private $unifiedOrder;


    public function init()
    {
        parent::init();
        $this->unifiedOrder = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
    }

    /**
     * 對比愛學堂數據並同步
     */
    public function actionSyncData()
    {
        $aixuetang = QyxClassificationConfig::find()
            ->select('name,type,sort,if_open,if_delete,subject_if_displays,classification_id')
            ->where(['store_id' => 8])
            ->asArray()
            ->all();
        $weike = QyxClassificationConfig::find()
            ->select('name,type,sort,if_open,if_delete,subject_if_displays,classification_id')
            ->where(['store_id' => 9])
            ->asArray()
            ->all();
        $install = $aixuetang;
        //更新不同數據,並拿出沒有的數據
        foreach ($aixuetang as $k => $v) {
            foreach ($weike as $i => $j) {
                if ($v['classification_id'] == $j['classification_id']) {
                    unset($install[$k]);
                    if ($v != $j) {
                        $diff = array_diff_assoc($v, $j);
                        foreach ($diff as $k => $v) {
                            QyxClassificationConfig::updateAll([$k => $v], ['classification_id' => $j['classification_id'], 'store_id' => 9]);
                        }
                    }
                }
            }
        }
        //批量插入新紀錄
        $field = ['name', 'type', 'sort', 'if_open', 'if_delete', 'subject_if_displays', 'store_id', 'classification_id'];
        foreach ($install as $k => $v) {
            $insertData[] = [$v['name'], $v['type'], $v['sort'], $v['if_open'], $v['if_delete'], $v['subject_if_displays'], 9, $v['classification_id']];
        }
        Yii::$app->db->createCommand()->batchInsert(QyxClassificationConfig::tableName(), $field, $insertData)->execute();
    }

    /**
     * 數據去重
     */
    public function actionRemove()
    {
        $sql = 'SELECT id,classification_id, COUNT(*) AS sumCount FROM szdato_qyx_classification_config where store_id = 9 GROUP BY classification_id HAVING sumCount > 1';
        $command = Yii::$app->db->createCommand($sql);
        $data = $command->queryAll();
        foreach ($data as $k => $v) {
            $ids[$k] = $v['id'];
        }
        $ids = implode(",", $ids);
        $sql2 = 'delete from szdato_qyx_classification_config where id in(' . $ids . ')';
        $command = Yii::$app->db->createCommand($sql2);
        $data = $command->execute();
        return $data;
    }

    /**
     * 獲取科目,年級,版本
     * @return \app\dato\ApiResponse
     */
    public function actionIndex()
    {
        $form = $_POST;
        if (!$form['store_id']) {
            return new ApiResponse(400, '獲取失敗,缺少參數store_id');
        }
        $res = QyxClassification::find()
            ->from(QyxClassification::tableName() . 'a')
            ->select('a.id,a.name,a.type,a.sort,a.if_open,a.img_src,a.subject_if_displays')
            ->leftJoin(QyxclassificationConfig::tableName() . 'b', 'a.id = b.classification_id and b.if_delete = 0 and b.if_open = 1 and b.store_id =' . $form['store_id'])
            ->andWhere(['a.if_delete' => 0, 'a.if_open' => 1, 'b.if_delete' => 0, 'b.if_open' => 1])
            ->orderBy('b.sort asc,a.sort asc,a.id asc')
            ->asArray()
            ->all();
        $data = QyxclassificationConfig::find()->where(['if_delete' => 0, 'store_id' => $form['store_id']])->asArray()->all();
        foreach ($res as $k => $value) {
            foreach ($data as $j => $item) {
                if ($value['id'] == $item['classification_id']) {
                    if (!empty($item['name'])) {
                        $res[$k]['name'] = $item['name'];
                    }
                    if (!empty($item['img_src'])) {
                        $res[$k]['img_src'] = $item['img_src'];
                    }
                    if (!empty($item['subject_if_displays']) || $item['subject_if_displays'] == 0) {
                        $res[$k]['subject_if_displays'] = $item['subject_if_displays'];
                    }
                    if (!empty($item['sort'])) {
                        $res[$k]['sort'] = $item['sort'];
                    } else {
                        $res[$k]['sort'] = 5;
                    }
                }
            }
        }
        /*foreach ($res as $k => $v) {
            if ($v['subject_if_displays'] != 1 &&$v['type'] == 'subject') {
                unset($res[$k]);
            }
        }*/
        /*foreach ($res as $k => $v) {
            $arr[$v['sort']][] = $v;
        }
        ksort($arr);
        $arr_res = [];
        foreach ($arr as $k => $v) {
            foreach ($v as $k1 => $v2) {
                $arr_res[] = $v2;
            }
        }*/
        $result['grade'][] = [
            'id' => '0',
            'name' => '全部',
            'type' => 'grade',
            'sort' => '5',
            'if_open' => '1',
            'img_src' => null,
            'subject_if_displays' => '1'
        ];
        $result['version'][] = [
            'id' => '0',
            'name' => '全部',
            'type' => 'version',
            'sort' => '5',
            'if_open' => '1',
            'img_src' => null,
            'subject_if_displays' => '1'
        ];
        if ($form['store_id'] == 9 || $form['store_id'] == 8) {
            switch ($form['store_id']) {
                case '9':
                    $result['subject'][] = [
                        'id' => '0',
                        'name' => '全部',
                        'type' => 'subject',
                        'sort' => '5',
                        'if_open' => '1',
                        'img_src' => 'https://app.2019edu.com/web/uploads/image/imgs/whole.png',
                        'subject_if_displays' => '1'
                    ];
                    break;
                case '8':
                    $result['subject'][] = [
                        'id' => '0',
                        'name' => '全部',
                        'type' => 'subject',
                        'sort' => '5',
                        'if_open' => '1',
                        'img_src' => 'https://app.2019edu.com/web/uploads/image/imgs/whole.bak.png',
                        'subject_if_displays' => '1'
                    ];
                    break;
            }

        }
        foreach ($res as $key => $value) {
            if ($value['type'] == 'grade') {
                $result['grade'][] = $value;
            }
            if ($value['type'] == 'subject') {
                $result['subject'][] = $value;
            }
            //關閉了全部版本
            /*if ($value['type'] == 'version') {
                $result['version'][] = $value;
            }*/
        }
        return new \app\dato\ApiResponse(200, 'success', $result);

    }

    /**
     * 統一下單,準備支付各項參數
     * @return \app\dato\ApiResponse
     */
    public function actionJoinvip()
    {
        $params = Yii::$app->request->post();

        //判斷前端是否傳入必要參數 ,以下4個參數爲必要參數,缺失一個將導致支付失敗
        if (empty($params['store_id']) || empty($params['user_id']) || empty($params['total_fee']) || empty($params['open_id'])) {
            return new \app\dato\ApiResponse(400, '前端參數傳入錯誤,請稍後支付', []);
        }

        $moneys = !empty($params['total_fee']) ? ($params['total_fee'] * 1000) / 10 : 1;//前端插入金額以分爲單位,小數位decimal(10,2)
        $open_id = !empty($params['open_id']) ? $params['open_id'] : 'oo9kN5EQfseaIaTpKfv_7CqQLs4c';//前端獲取全局openid

        $post = [];
        $input = new \WxPayUnifiedOrder();
        $input->SetBody("會員購買");
        $input->SetOut_trade_no("hexie" . date("YmdHis") . '_' . substr($open_id, 0, 9));
        $input->SetTotal_fee($moneys);
        $input->SetNotify_url("https://app.2019edu.com/web/paymentresult.php");
        $input->SetTrade_type("JSAPI");
        $input->SetOpenid($open_id);


        $data = $params;
        $user_id = $data['user_id'];
        $pay_time = time();
        $store_id = $data['store_id'];
        $order_no = $input->GetOut_trade_no();
        $pay_price = $params['total_fee'];
        $pay_type = 1;
        $is_pay = 0;
        $pid = !empty($data['pid']) ? $data['pid'] : ' ';
        $member_id = $data['member_id'];
        $vip_end_time = $data['end_time'];
        $opening_time = $data['opening_name'];


        //查詢是否已購買過該年級下會員
        $vip = $this->selectThisVipInfo($user_id, $store_id, $member_id, $vip_end_time, $opening_time);

        if ($vip) {
            $local_time = date('Y-m-d', time());
            if ($local_time < $vip['vip_end_time']) {
                return new \app\dato\ApiResponse(401, '您已購買過當前年級下的會員,到期時間爲:' . $vip_end_time . '請勿重複購買', []);
            }
        }


        //創建未支付訂單
        $last_id = $this->insertLevelOrder($store_id, $order_no, $user_id, $pay_price, $pay_type, $is_pay, $pay_time, $pid, $member_id, $vip_end_time, $opening_time);
        if (!$last_id) {
            return new \app\dato\ApiResponse(402, '初始訂單創建失敗,請稍後支付', []);
        }

        $post['appid'] = $appid = $this->getAppid($store_id)['app_id'];
        $post['attach'] = $attach = $last_id;//商家數據包,附加數據
        $post['body'] = $body = $input->GetBody(); //交易標識簽名
        $post['mch_id'] = $mch_id = $this->getAppid($store_id)['mch_id']; //商戶ID
        $post['nonce_str'] = $nonce_str = $this->getARandomString();//隨機字符串
        $post['notify_url'] = $notify_url = $input->GetNotify_url(); //回調地址
        $post['openid'] = $openid = $input->GetOpenid();//openid 小程序:去預習 oo9kN5EQfseaIaTpKfv_7CqQLs4c
        $post['out_trade_no'] = $out_trade_no = $input->GetOut_trade_no();//商戶訂單號
        $post['spbill_create_ip'] = $spbill_create_ip = $this->getIp();//終端的ip
        $post['total_fee'] = $total_fee = $input->GetTotal_fee();//總金額 最低爲一分錢 必須是整數
        $post['trade_type'] = $trade_type = $input->GetTrade_type();//交易類型,默認


        $sign = $this->getCryptographicSignature($post, $store_id);//簽名

        $post_xml = $this->assemTheDataInXmlFormatToTheWeChatServer($appid, $attach, $body, $mch_id, $nonce_str, $notify_url, $openid, $out_trade_no, $spbill_create_ip, $total_fee, $trade_type, $sign);

        $url = $this->unifiedOrder;

        //微信服務器返回xml字符串
        $xml = $this->httpRequestGetTheXmlReturned($url, $post_xml);
        if (!$xml) {
            return new \app\dato\ApiResponse(403, '支付錯誤,請檢查請求參數是否通過post方法提交,請稍後支付', []);
        }

        //轉義xml字符串至數組,轉義後數組的鍵全部是大寫
        $array = $this->getTheEscapedXml($xml);


        //將統一下單接口獲取的PREPAY_ID保存到數據庫中供後期模板消息調用,PREPAY_ID將作爲模板消息的重要參數之一
        $sql = "UPDATE szdato_level_order SET
              prepay_id='{$array['PREPAY_ID']}'
              WHERE id={$last_id}";

        $command = Yii::$app->db->createCommand($sql);
        $prepay = $command->execute();

        if (!$prepay) {
            return new \app\dato\ApiResponse(403, 'prepay_id保存失敗,請重試或稍後支付', []);
        }


        if ($array['RETURN_CODE'] == 'SUCCESS' && $array['RESULT_CODE'] == 'SUCCESS') {
            $time = time();
            $tmp = [];//臨時數組用於簽名
            $tmp['appId'] = $appid;
            $tmp['nonceStr'] = $nonce_str;
            $tmp['package'] = 'prepay_id=' . $array['PREPAY_ID'];
            $tmp['signType'] = 'MD5';
            $tmp['timeStamp'] = "$time";

            $datas = $this->getPaymentParameters($time, $nonce_str, $array, $tmp, $out_trade_no, $store_id);

            return new \app\dato\ApiResponse(200, 'success', $datas);

        } else {
            $datas['state'] = 0;
            $datas['text'] = "參數錯誤";
            $datas['ERR_CODE'] = $array['ERR_CODE'];
            $datas['RESULT_CODE'] = $array['RESULT_CODE'];
            $datas['RETURN_CODE'] = $array['RETURN_CODE'];
            $datas['RETURN_MSG'] = $array['RETURN_MSG'];
            $datas['ERR_CODE_DES'] = $array['ERR_CODE_DES'];
            return new \app\dato\ApiResponse(404, '支付參數錯誤,請稍後支付', $datas);
        }

    }

    /**
     * 提供微信支付參數
     * @param $time
     * @param $nonce_str
     * @param $array
     * @param $tmp
     * @param $out_trade_no
     * @param $store_id
     * @return array
     */
    private function getPaymentParameters($time, $nonce_str, $array, $tmp, $out_trade_no, $store_id)
    {
        $data = [];
        $data['state'] = 1;
        $data['timeStamp'] = "$time";//時間戳
        $data['nonceStr'] = $nonce_str;//隨機字符串
        $data['signType'] = 'MD5';//簽名算法
        $data['package'] = 'prepay_id=' . $array['PREPAY_ID'];//統一下單接口返回的 prepay_id 參數值,提交格式如:prepay_id=*
        $data['paySign'] = $this->getCryptographicSignature($tmp, $store_id);//簽名,具體簽名方案參見微信公衆號支付幫助文檔;
        $data['out_trade_no'] = $out_trade_no;
        return $data;

    }


    /**
     * 獲取小程序基本信息
     * @param $store_id
     * @return array|false
     */
    private function getAppid($store_id)
    {
        $command = Yii::$app->db->createCommand("SELECT * FROM szdato_wechat_app where store_id={$store_id}");
        $data = $command->queryOne();
        if (!$data) {
            return false;
        }
        return $data;
    }


    /**
     * 獲取是否存在vip信息
     * @param $user_id
     * @param $store_id
     * @param $member_id
     * @param $vip_end_time
     * @param $opening_time
     * @return array|false
     */
    private function selectThisVipInfo($user_id, $store_id, $member_id, $vip_end_time, $opening_time)
    {
        $command = Yii::$app->db->createCommand("SELECT * FROM szdato_level_order 
                    where user_id=$user_id 
                    AND store_id=$store_id 
                    AND member_id=$member_id 
                    AND is_pay=1
                    AND vip_end_time='{$vip_end_time}' 
                    AND opening_time='{$opening_time}'");
        $data = $command->queryOne();
        return $data;

    }


    /**
     * 插入初始會員訂單
     * @param $store_id
     * @param $order_no
     * @param $user_id
     * @param $pay_price
     * @param $pay_type
     * @param $is_pay
     * @param $pay_time
     * @param $pid
     * @param $member_id
     * @param $vip_end_time
     * @param $opening_time
     * @return string
     */
    private function insertLevelOrder($store_id, $order_no, $user_id, $pay_price, $pay_type, $is_pay, $pay_time, $pid, $member_id, $vip_end_time, $opening_time)
    {
        $sql = "INSERT INTO szdato_level_order(
                  store_id,
                  order_no,
                  user_id,
                  pay_price,
                  pay_type,
                  is_pay,
                  pay_time,
                  pid,
                  member_id,
                  vip_end_time,
                  opening_time)
                  VALUES(
                  '{$store_id}',
                  '{$order_no}',
                  '{$user_id}',
                  '{$pay_price}',
                  '{$pay_type}',
                  '{$is_pay}',   
                  '{$pay_time}',
                  '{$pid}',
                  '{$member_id}',
                  '{$vip_end_time}',
                  '{$opening_time}')";
        $command = Yii::$app->db->createCommand($sql);
        $command->execute();
        $last_id = Yii::$app->db->getLastInsertID();
        return $last_id;
    }


    /**
     * 隨機字符串 ,最多32位
     * @return string
     */
    private function getARandomString()
    {
        $result = '';
        $str = 'QWERTYUIOPASDFGHJKLZXCVBNMabcdefghijklmnopqrstuvwxyz';//自定義大小寫字母
        for ($i = 0; $i < 32; $i++) {
            $result .= $str[rand(0, 51)];
        }
        return $result;
    }


    /**
     * 傳入微信需要的參數
     * @param $appid
     * @param $attach
     * @param $body
     * @param $mch_id
     * @param $nonce_str
     * @param $notify_url
     * @param $openid
     * @param $out_trade_no
     * @param $spbill_create_ip
     * @param $total_fee
     * @param $trade_type
     * @param $sign
     * @return string
     */
    private function assemTheDataInXmlFormatToTheWeChatServer($appid, $attach, $body, $mch_id, $nonce_str, $notify_url, $openid, $out_trade_no, $spbill_create_ip, $total_fee, $trade_type, $sign)
    {
        $string = '<xml>
           <appid>' . $appid . '</appid>
           <attach>' . $attach . '</attach>
           <body>' . $body . '</body>
           <mch_id>' . $mch_id . '</mch_id>
           <nonce_str>' . $nonce_str . '</nonce_str>
           <notify_url>' . $notify_url . '</notify_url>
           <openid>' . $openid . '</openid>
           <out_trade_no>' . $out_trade_no . '</out_trade_no>
           <spbill_create_ip>' . $spbill_create_ip . '</spbill_create_ip>
           <total_fee>' . $total_fee . '</total_fee>
           <trade_type>' . $trade_type . '</trade_type>
           <sign>' . $sign . '</sign>
        </xml> ';

        return $string;

    }


    /**簽名函數
     * @param $data
     * @param $store_id
     * @return string
     */
    private function getCryptographicSignature($data, $store_id)
    {
        $stringA = '';
        foreach ($data as $key => $value) {
            if (!$value) continue;
            if ($stringA) {
                $stringA .= '&' . $key . "=" . $value;
            } else {
                $stringA = $key . "=" . $value;
            }
        }
        $wx_key = $this->getAppid($store_id)['key'];//申請支付後有給予一個商戶賬號和密碼,登陸後自己設置key

        $stringSignTemp = $stringA . '&key=' . $wx_key;
        return strtoupper(md5($stringSignTemp));
    }


    /**
     * 獲取IP
     * @return string
     */
    public function getIp()
    {
        if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
            $cip = $_SERVER['HTTP_CLIENT_IP'];
        } else if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
            $cip = $_SERVER["HTTP_X_FORWARDED_FOR"];
        } else if (!empty($_SERVER["REMOTE_ADDR"])) {
            $cip = $_SERVER["REMOTE_ADDR"];
        } else {
            $cip = '';
        }
        preg_match("/[\d\.]{7,15}/", $cip, $cips);
        $cip = isset($cips[0]) ? $cips[0] : 'unknown';
        unset($cips);
        return $cip;
    }


    /**
     * curl請求
     * @param $url
     * @param null $data
     * @param array $headers
     * @return mixed
     */
    private function httpRequestGetTheXmlReturned($url, $data = null, $headers = array())
    {
        $curl = curl_init();
        if (count($headers) >= 1) {
            curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
        }
        curl_setopt($curl, CURLOPT_URL, $url);

        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);

        if (!empty($data)) {
            curl_setopt($curl, CURLOPT_POST, 1);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        }
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        $output = curl_exec($curl);
        curl_close($curl);
        return $output;
    }


    /**
     * 解義xml
     * @param $xml
     * @return string
     */
    private function getTheEscapedXml($xml)
    {
        $p = xml_parser_create();//創建 XML 解析器
        xml_parse_into_struct($p, $xml, $vals, $index);
        xml_parser_free($p);
        $data = "";
        foreach ($index as $key => $value) {
            if ($key == 'xml' || $key == 'XML') continue;
            $tag = $vals[$value[0]]['tag'];
            $value = $vals[$value[0]]['value'];
            $data[$tag] = $value;
        }
        return $data;
    }


    /**
     * 獲取加密信息
     * @return \app\dato\ApiResponse
     */
    public function actionJm()
    {
        $appid = 'wx4f4bc4dec97d474b';
        $sessionKey = 'tiihtNczf5v6AKRyjwEUhQ==';
        $iv = 'r7BXXKkLb8qrSNn05n0qiA==';//前端傳入

        $encryptedData = "CiyLU1Aw2KjvrjMdj8YKliAjtP4gsMZM
                QmRzooG2xrDcvSnxIMXFufNstNGTyaGS
                9uT5geRa0W4oTOb1WT7fJlAC+oNPdbB+
                3hVbJSRgv+4lGOETKUQz6OYStslQ142d
                NCuabNPGBzlooOmB231qMM85d2/fV6Ch
                evvXvQP8Hkue1poOFtnEtpyxVLW1zAo6
                /1Xx1COxFvrc2d7UL/lmHInNlxuacJXw
                u0fjpXfz/YqYzBIBzD6WUfTIF9GRHpOn
                /Hz7saL8xz+W//FRAUid1OksQaQx4CMs
                8LOddcQhULW4ucetDf96JcR3g0gfRK4P
                C7E/r7Z6xNrXd2UIeorGj5Ef7b1pJAYB
                6Y5anaHqZ9J6nKEBvB4DnNLIVWSgARns
                /8wR2SiRS7MNACwTyrGvt9ts8p12PKFd
                lqYTopNHR1Vf7XjfhQlVsAJdNiKdYmYV
                oKlaRv85IfVunYzO0IKXsyl7JCUjCpoG
                20f0a04COwfneQAGGwd5oa+T8yO5hzuy
                Db/XcxxmK01EpqOyuxINew==";


        $pc = new WXBizDataCrypt($appid, $sessionKey);
        $errCode = $pc->decryptData($encryptedData, $iv, $data);

        if ($errCode == 0) {
            return new \app\dato\ApiResponse(200, 'success', $data . "\n");
        } else {
            return new \app\dato\ApiResponse(400, 'error', $errCode . "\n");
        }
    }


    /**
     * 回調 函數  回調方法參見:統一下單接口中回調地址url
     */
    public function actionPaymentresult()
    {
        $post = file_get_contents("php://input");
        /**支付成功返回示例 詳見 https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=9_7&index=7**
         * $post = '<xml>
         * <appid><![CDATA[wx2421b1c4370ec43b]]></appid>
         * <attach><![CDATA[支付測試]]></attach>
         * <bank_type><![CDATA[CFT]]></bank_type>
         * <fee_type><![CDATA[CNY]]></fee_type>
         * <is_subscribe><![CDATA[Y]]></is_subscribe>
         * <mch_id><![CDATA[10000100]]></mch_id>
         * <nonce_str><![CDATA[5d2b6c2a8db53831f7eda20af46e531c]]></nonce_str>
         * <openid><![CDATA[oUpF8uMEb4qRXf22hE3X68TekukE]]></openid>
         * <out_trade_no><![CDATA[1409811653]]></out_trade_no>
         * <result_code><![CDATA[SUCCESS]]></result_code>
         * <return_code><![CDATA[SUCCESS]]></return_code>
         * <sign><![CDATA[B552ED6B279343CB493C5DD0D78AB241]]></sign>
         * <sub_mch_id><![CDATA[10000100]]></sub_mch_id>
         * <time_end><![CDATA[20140903131540]]></time_end>
         * <total_fee>1</total_fee>
         * <coupon_fee_0><![CDATA[10]]></coupon_fee_0>
         * <coupon_count><![CDATA[1]]></coupon_count>
         * <coupon_type><![CDATA[CASH]]></coupon_type>
         * <coupon_id><![CDATA[10000]]></coupon_id>
         * <trade_type><![CDATA[JSAPI]]></trade_type>
         * <transaction_id><![CDATA[1004400740201409030005092168]]></transaction_id>
         * </xml>';
         **支付成功返回示例**/
//        $post = '<xml>
//                      <appid><![CDATA[wx2421b1c4370ec43b]]></appid>
//                      <attach><![CDATA[支付測試]]></attach>
//                      <bank_type><![CDATA[CFT]]></bank_type>
//                      <fee_type><![CDATA[CNY]]></fee_type>
//                      <is_subscribe><![CDATA[Y]]></is_subscribe>
//                      <mch_id><![CDATA[10000100]]></mch_id>
//                      <nonce_str><![CDATA[5d2b6c2a8db53831f7eda20af46e531c]]></nonce_str>
//                      <openid><![CDATA[oUpF8uMEb4qRXf22hE3X68TekukE]]></openid>
//                      <out_trade_no><![CDATA[1409811653]]></out_trade_no>
//                      <result_code><![CDATA[SUCCESS]]></result_code>
//                      <return_code><![CDATA[SUCCESS]]></return_code>
//                      <sign><![CDATA[B552ED6B279343CB493C5DD0D78AB241]]></sign>
//                      <sub_mch_id><![CDATA[10000100]]></sub_mch_id>
//                      <time_end><![CDATA[20140903131540]]></time_end>
//                      <total_fee>1</total_fee>
//                      <coupon_fee_0><![CDATA[10]]></coupon_fee_0>
//                      <coupon_count><![CDATA[1]]></coupon_count>
//                      <coupon_type><![CDATA[CASH]]></coupon_type>
//                      <coupon_id><![CDATA[10000]]></coupon_id>
//                      <trade_type><![CDATA[JSAPI]]></trade_type>
//                      <transaction_id><![CDATA[1004400740201409030005092168]]></transaction_id>
//                </xml>';


        if ($post) {
            $data = $this->getTheEscapedXml($post);
            if ($data['RETURN_CODE'] == 'SUCCESS') {//此時返回了正確的數據,可以保存到數據庫了
                $result = json_encode($data);
                $this->savePaymentInformation($result);
            }

            $str = '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
            echo $str;
        } else {
            exit('<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[Callback error]]></return_msg></xml>');
        }


    }

    /**
     *保存回調數據
     * @param $result
     * @return int
     */
    private function savePaymentInformation($result)
    {
        $res = Yii::$app->db->createCommand()->insert('szdato_qyx_wxpay_callback',
            ['pay_info' => $result, 'add_time' => time(), 'create_date' => time()])->execute();
        return $res;

    }


    public function sendTemplateInfo($prepay_id, $out_trade_no, $openid)
    {
        $formid = $prepay_id;
        $template_id = 'KlrWgWw0nB6IUDgOR4Dh3_MDQDJM3PtfMOSk5700b94';//模板ID
        $page = 'pages/index/index';
        $open_id = $openid;
        if (!$openid || !$formid) die('failed!');
        $key1 = $out_trade_no;//訂單號
        $key2 = '0.01';//支付金額
        $key3 = date('Y-m-d H:i:s');//下單時間
        $key4 = 'VIP會員';//物品名稱

        $access_token = $this->returnAssKey();

        $url = 'https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=' . $access_token;

        $data = array(//這裏一定要按照微信給的格式
            "touser" => $open_id,
            "template_id" => $template_id,
            "page" => $page,
            "form_id" => $formid,
            "data" => array(
                "keyword1" => array(
                    "value" => $key1,

                ),
                "keyword2" => array(
                    "value" => $key2,

                ),
                "keyword3" => array(
                    "value" => $key3,

                ),
                "keyword4" => array(
                    "value" => $key4,

                )

            ),
            "emphasis_keyword" => "keyword2.DATA",//需要進行加大的消息
        );


        $res = $this->postCurl($url, $data, 'json');//將data數組轉換爲json數據

        return json_decode($res);


    }


    private function returnAsskey()
    {
        $url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wxdda3d40e074e4e7d&secret=f50fb02c140c4fcfe11b8279f6217863';
        $ass_key = $this->curl_get($url);
        $a1 = $ass_key->access_token;
        return $a1;
    }

    private function curl_get($url)
    {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        $data = curl_exec($curl);
        $err = curl_error($curl);
        curl_close($curl);
        return json_decode($data);//對數據進行json解碼

    }


    private function postCurl($url, $data, $type)
    {
        if ($type == 'json') {
            $data = json_encode($data);//對數組進行json編碼
            $header = array("Content-type: application/json;charset=UTF-8", "Accept: application/json", "Cache-Control: no-cache", "Pragma: no-cache");
        }
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_POST, 1);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
        if (!empty($data)) {
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        }
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
        $res = curl_exec($curl);
        if (curl_errno($curl)) {
            echo 'Error+' . curl_error($curl);
        }
        curl_close($curl);
        return $res;

    }


    /**
     * 兌換碼接口
     * @return ApiResponse
     * @throws \yii\db\Exception
     */
    public function actionSaveredeemcode()
    {
        if (\Yii::$app->request->isPost) {
            $data = \Yii::$app->request->post();
            $redeemCode = !empty($data['code']) ? strtoupper($data['code']) : ' ';
            $store_id = !empty($data['store_id']) ? $data['store_id'] : ' ';
            $user_id = !empty($data['user_id']) ? $data['user_id'] : null; //綁定者
            $bindtime = time(); //綁定時間
            $member_id = !empty($data['member_id']) ? $data['member_id'] : null;//套餐id


            if (!$redeemCode || !$user_id || !$member_id) {
                return new \app\dato\ApiResponse(400, '參數錯誤 , 請稍後再試!', []);
            }


            //修改綁定人,綁定時間
            if ($redeemCode && $store_id && $member_id) {

                $UserCardvipList = new UserCardvipList();
                $datas = $UserCardvipList::find()->where(['redeem_code' => $redeemCode, 'store_id' => $store_id])->asArray()->one();

                if (!$datas || $datas['status'] || $datas['user_id'] || $datas['bindingtime'] || $datas['bind_member_id']) {
                    return new \app\dato\ApiResponse(401, '該兌換碼不存在或已使用', []);
                }


                $UserCardvipInfo = UserCardvip::find()->where(['id' => $datas['redeem_code_id']])->asArray()->one();
                $starttime = $UserCardvipInfo['starttime'];
                $endtime = $UserCardvipInfo['endtime'];
                $localtime = date('Y-m-d H:i:s', time());

                if ($localtime < $starttime || $localtime > $endtime) {
                    if ($localtime < $starttime) {
                        $mgs = '請在開始時間' . $starttime . '後開始兌換';
                    }
                    $is_show = 1;
                }

                if (!$UserCardvipInfo['status'] || $is_show == 1) {

                    if (!empty($mgs)) {
                        return new \app\dato\ApiResponse(406, $mgs, []);
                    }
                    return new \app\dato\ApiResponse(402, '該兌換碼已失效或活動已結束', []);
                }

                //該兌換碼是免費時 is_free=0
                if (!$UserCardvipInfo['is_free']) {
                    //查詢是否有使用過免費兌換碼
                    $code_list = UserCardvipList::find()->where(['user_id' => $user_id, 'store_id' => $store_id])->asArray()->all();
                    if (!empty($code_list)) {
                        $ids = [];
                        foreach ($code_list as $v) {
                            $ids[] = $v['redeem_code_id'];
                        }
                        if (!empty($ids)) {
                            $ids = implode(',', $ids);
                            $where = [
                                'and',
                                'id in (' . $ids . ')',
                                'is_free=0'
                            ];

                            $code = UserCardvip::find()->where($where)->asArray()->one();
                            if (!empty($code)) {
                                return new \app\dato\ApiResponse(407, '您已經參加過此類活動了', []);
                            }
                        }
                    }
                }


                $arrcode = $UserCardvipList::find()->where(['redeem_code' => $redeemCode])->one();
                $arrcode->status = 1;
                $arrcode->bindingtime = $bindtime;
                $arrcode->user_id = $user_id;
                $arrcode->bind_member_id = $member_id;
                $res = $arrcode->save();

                if (!$res) {
                    return new \app\dato\ApiResponse(403, '綁定失敗', []);
                }


                $UserCardvipInfo = QyxUserMember::find()
                    ->where(['user_id' => $user_id, 'member_id' => $member_id])
                    ->andWhere(['>','endtime',strtotime(date('Y-m-d', time()))])
                    ->orderBy('id desc')
                    ->asArray()
                    ->all();

                //該情況爲沒有買過vip會員或者會員過期的情況,首次參與兌換碼活動
                if (!$UserCardvipInfo) {
                    $endtime = $datas['usetime'] * 3600 * 24 + strtotime(date('Y-m-d', time()));
                    $vip_end_time = date('Y-m-d', $endtime);
                } else {
                    //已買過會員,使用兌換碼時發生以下:延長(或增加)會員時間。
                    $endtime = $UserCardvipInfo[0]['endtime'] + $datas['usetime'] * 3600 * 24;
                    $vip_end_time = date('Y-m-d', $endtime);
                }

                $codeArrays = [[$user_id, time(), $endtime, $member_id, $vip_end_time, '兌換碼兌換會員']];
                $resultUserMenber = \Yii::$app->db->createCommand()
                    ->batchInsert('szdato_qyx_user_member',
                        ['user_id', 'addtime', 'endtime', 'member_id', 'vip_end_time', 'remarks'], $codeArrays)
                    ->execute();

                if (!$resultUserMenber) {
                    return new \app\dato\ApiResponse(404, '會員延長時間保存失敗', []);
                }


                $memberInfo = QyxMember::find()->where(['id' => $member_id])->asArray()->one();
                $classification_config_id = $memberInfo['classification_config_id'];
                $sql = "SELECT group_concat(name)  as classification_config_info 
                        FROM   szdato_qyx_classification_config
                        WHERE  id in($classification_config_id)";

                $command = Yii::$app->db->createCommand($sql);
                $classificationConfigInfo = $command->queryAll();

                $resultArrayInfo = [
                    'vip_end_time' => $vip_end_time,
                    'add_vip_time' => $datas['usetime'] . '天',
                    'gradeInfo' => $classificationConfigInfo[0]

                ];

                return new \app\dato\ApiResponse(200, '綁定成功', $resultArrayInfo);
            }

        } else {

            return new \app\dato\ApiResponse(405, 'ajax請求錯誤', []);

        }


    }


    /**
     * curl 定時任務 :發送短信提醒會員到期時間
     * @return string
     * @throws \yii\db\Exception
     */
    public function actionServicenotice()
    {
        $sql = "select  m.* , max(m.endtime) as maxtime ,u.wechat_open_id ,u.nickname,u.binding
                from szdato_qyx_user_member as m
                join szdato_user as u on m.user_id=u.id             
                group by m.user_id";

        $command = Yii::$app->db->createCommand($sql);
        $user_member_info = $command->queryAll();


        date_default_timezone_set("PRC");
        $local_time = strtotime(date('Y-m-d', time()));

        $user_member_infos = [];
        foreach ($user_member_info as $k => $value) {
            if (1 * 3600 * 24 >= $value['endtime'] - $local_time) {//小於1天自動提醒
                $user_member_infos[] = $value;
            }
        }
        if (!$user_member_infos) {
            return new \app\dato\ApiResponse(404, '暫時沒有發送短信的對象。', []);
        }

        $resultphones = [];
        foreach ($user_member_infos as $n => $info) {
            if (!empty($info['binding'])) {
                $resultphones[] = $info['binding'];
            }
        }

        //如果有需要發送的對象,則執行發送短信:
        $tencentSms = new TencentSms();
        $sms_id = 3;//短信id
        $sms = 1;//天數
        $result = $tencentSms->qunfaSms($sms, $resultphones, $sms_id);
        $result = json_decode($result);

        $send_phones = [];
        $no_send_phones = [];

        foreach ($result->detail as $i => $node) {
            if (!$node->result) {
                $send_phones[$i] = $node->mobile;
            } else {
                $no_send_phones[$i] = $node->mobile;
            }
        }

        $send_total = count($send_phones);
        $no_send_total = count($no_send_phones);
        $sms_info = "被騷擾對象:" . json_encode($send_phones) . ";發送失敗:" . json_encode($no_send_phones);
        $tips = "總髮送數:" . count($result->detail) . ",成功條數:" . $send_total . ";失敗條數:" . $no_send_total;
        $create_date = time();

        $sql = "INSERT INTO szdato_sms_callback(
                  sms_info,
                  tips,
                  create_date)
                  VALUES(
                  '{$sms_info}',
                  '{$tips}',
                  '{$create_date}')";

        $command = Yii::$app->db->createCommand($sql);
        $command->execute();

        //記錄定時任務是否執行
        if($send_phones){
            file_put_contents('sms_send_callback.log', date('Y-m-d H:i:s', time()) . '執行了一次定時任務,並且騷擾了' . json_encode($send_phones), FILE_APPEND);

        }

        $string = $tips . '<br>' . $sms_info;

        return new \app\dato\ApiResponse(200, $string, []);


    }


}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章