<?php
/**
 * 易优CMS
 * ============================================================================
 * 版权所有 2016-2028 海口快推科技有限公司，并保留所有权利。
 * 网站地址: http://www.eyoucms.com
 * ----------------------------------------------------------------------------
 * 如果商业用途务必到官方购买正版授权, 以免引起不必要的法律纠纷.
 * ============================================================================
 * Author: 小虎哥 <1105415366@qq.com>
 * Date: 2018-4-3
 */

namespace app\common\model;

use think\Db;
use think\Config;

/**
 * 抖音公共模型
 */
load_trait('controller/Jump');
class TikTok
{
    use \traits\controller\Jump;

    // 构造函数
    public function __construct($tikTokConfig = [])
    {
        // 统一接收参数处理
        $this->times = getTime();
        // 接口请求头
        $this->headers  = ['Content-Type: application/json'];
        // 抖音信息
        $this->tikTokConfig = !empty($tikTokConfig) ? $tikTokConfig : model('ShopPublicHandle')->getSpecifyAppletsConfig();
    }

    // 获取抖音支付订单号(order_id)、订单token(order_token)
    public function getTikTokAppletsPay($orderID = '', $orderCode = '', $orderAmount = 0, $orderUnpayCloseTime = 2880, $table = 'shop_order', $type = 2)
    {
        // 接口参数
        $postData = [
            'app_id'       => $this->tikTokConfig['appid'],
            'out_order_no' => strval($orderCode),
            'total_amount' => floatval($orderAmount * 100),
            'subject'      => '抖音支付',
            'body'         => '商品购买',
            'valid_time'   => intval(intval($orderUnpayCloseTime) * 60),
            'cp_extra'     => "tikTok|,|" . session('users_id') . "|,|" . $orderID . "|,|" . $orderCode . "|,|" . $table . "|,|" . $type,
            'notify_url'   => request()->domain() . ROOT_DIR . '/index.php',
        ];
        // MD5加密签名
        $postData['sign'] = $this->getSignParam($postData);
        // 接口API
        $url = 'https://developer.toutiao.com/api/apps/ecpay/v1/create_order';
        $jsonData = json_decode(httpRequest($url, 'POST', json_encode($postData), $this->headers, 300000), true);
        // 返回订单创建信息
        if (isset($jsonData['err_no']) && 0 === intval($jsonData['err_no']) && isset($jsonData['err_tips']) && 'success' == strval($jsonData['err_tips'])) {
            return [
                'success' => true,
                'order_id' => $jsonData['data']['order_id'],
                'order_token' => $jsonData['data']['order_token'],
            ];
        } else {
            if (stristr($jsonData['err_tips'], '签名')) $jsonData['err_tips'] = 'AppID或SALT错误，请逐个检查再提交';
            return [
                'success' => false,
                'err_tips' => $jsonData['err_tips'],
            ];
        }
    }

    // 抖音小程序商品购买支付后续处理
    public function tikTokAppletsPayDealWith($post = [], $notify = false, $table = 'shop_order')
    {
        // 异步回调时执行
        $cpExtra = !empty($post['msg']['cp_extra']) ? explode('|,|', $post['msg']['cp_extra']) : [];
        if (true === $notify && !empty($cpExtra[0]) && 'tikTok' == $cpExtra[0]) {
            $post['users_id'] = !empty($cpExtra[1]) ? $cpExtra[1] : 0;
            $post['order_id'] = !empty($cpExtra[2]) ? $cpExtra[2] : 0;
            $post['order_code'] = !empty($cpExtra[3]) ? $cpExtra[3] : '';
            $post['transaction_type'] = !empty($cpExtra[5]) ? $cpExtra[5] : 0;
            $table = !empty($cpExtra[4]) ? $cpExtra[4] : $table;
        }

        if (!empty($post['users_id'])) {
            // 获取系统订单
            $order = $this->getSystemOrder($post, $notify, $table);
            // 查询抖音支付订单是否真实完成支付
            $jsonData = $this->queryOrderPayResult($order['unified_number']);
            if (isset($jsonData['err_no']) && 0 === intval($jsonData['err_no']) && !empty($jsonData['payment_info']['order_status'])) {
                // 支付成功
                if ('SUCCESS' == $jsonData['payment_info']['order_status']) {
                    // 处理系统订单
                    $post['unified_id'] = $order['unified_id'];
                    $post['unified_number'] = $order['unified_number'];
                    $payApiLogic = new \app\user\logic\PayApiLogic($post['users_id'], true);
                    $payApiLogic->OrderProcessing($post, $order, $jsonData);
                }
                // 正在支付中
                else if ('PROCESSING' == $jsonData['payment_info']['order_status']) {
                    if (true !== $notify) $this->success('正在支付中');
                }
                // 超时未支付
                else if ('TIMEOUT' == $jsonData['payment_info']['order_status']) {
                    if (true !== $notify) $this->error($jsonData['err_tips']);
                }
                // 支付失败
                else if ('FAIL' == $jsonData['payment_info']['order_status']) {
                    if (true !== $notify) $this->error($jsonData['err_tips']);
                }
            } else {
                if (true !== $notify) $this->error($jsonData['err_tips']);
            }
        }
    }

    // 查询系统订单
    private function getSystemOrder($post = [], $notify = false, $table = 'shop_order')
    {
        // 商城商品订单
        if ('shop_order' == $table) {
            // 查询系统订单信息
            $where = [
                'users_id'   => intval($post['users_id']),
                'order_id'   => intval($post['order_id']),
                'order_code' => strval($post['order_code']),
            ];
            $order = Db::name('shop_order')->where($where)->find();
            if (empty($order)) {
                // 同步
                if (true !== $notify) $this->error('无效订单');
            } else if (0 < $order['order_status']) {
                // 异步
                if (true === $notify) {
                    exit(json_encode(['err_no' => 0, 'err_tips' => 'success']));
                }
                // 同步
                else {
                    $usersData = Db::name('users')->where('users_id', $post['users_id'])->find();
                    // 邮箱发送
                    $resultData['email'] = GetEamilSendData(tpCache('smtp'), $usersData, $order, 1, 'wechat');
                    // 短信发送
                    $resultData['mobile'] = GetMobileSendData(tpCache('sms'), $usersData, $order, 1, 'wechat');
                    // 跳转链接
                    $url = 1 == input('param.fenbao/d') ? '' : '/pages/order/index';
                    $resultData['url'] = $url;
                    $this->success('支付完成', $url, $resultData);
                }
            }
            $order['unified_id'] = intval($order['order_id']);
            $order['unified_number'] = strval($order['order_code']);
        }
        // 会员充值套餐订单
        else if ('users_recharge_pack_order' == $table) {
            $where = [
                'users_id' => intval($post['users_id']),
                'order_id' => intval($post['order_id']),
                'order_code' => strval($post['order_code']),
                'order_pay_code' => strval($post['order_pay_code']),
            ];
            $order = Db::name('users_recharge_pack_order')->where($where)->find();
            if (empty($order)) {
                // 同步
                if (true !== $notify) $this->error('无效订单');
            } else if (1 < $order['order_status']) {
                // 异步
                if (true === $notify) {
                    exit(json_encode(['err_no' => 0, 'err_tips' => 'success']));
                }
                // 同步
                else {
                    $this->success('支付完成');
                }
            }
            $order['unified_id'] = intval($order['order_id']);
            $order['unified_number'] = strval($order['order_pay_code']);
        }
        // 会员(充值余额 or 升级)订单
        else if ('users_money' == $table) {
            $post['moneyid'] = !empty($post['order_id']) ? $post['order_id'] : $post['moneyid'];
            $post['order_number'] = !empty($post['order_code']) ? $post['order_code'] : $post['order_number'];
            $where = [
                'moneyid' => intval($post['moneyid']),
                'users_id' => intval($post['users_id']),
                'order_number' => strval($post['order_number']),
            ];
            $order = Db::name('users_money')->where($where)->find();
            if (empty($order)) {
                // 同步
                if (true !== $notify) $this->error('无效订单');
            } else if (1 < $order['status']) {
                // 异步
                if (true === $notify) {
                    exit(json_encode(['err_no' => 0, 'err_tips' => 'success']));
                }
                // 同步
                else {
                    $this->success('支付完成');
                }
            }
            $order['unified_id'] = intval($order['moneyid']);
            $order['unified_number'] = strval($order['order_number']);
        }

        return $order;
    }

    // 查询抖音支付订单是否真实完成支付
    public function queryOrderPayResult($orderCode = '')
    {
        // 接口参数
        $postData = [
            'app_id'       => $this->tikTokConfig['appid'],
            'out_order_no' => strval($orderCode),
        ];
        // MD5加密签名
        $postData['sign'] = $this->getSignParam($postData);
        // 接口API
        $url = 'https://developer.toutiao.com/api/apps/ecpay/v1/query_order';
        // 返回结果
        return json_decode(httpRequest($url, 'POST', json_encode($postData), $this->headers, 300000), true);
    }

    private function getSignParam($map = [])
    {
        $param = [];
        foreach($map as $key => $value) {
            // 排除不参与加密的字段
            if ($key == "other_settle_params" || $key == "app_id" || $key == "sign" || $key == "thirdparty_id") continue;

            // 参数处理
            $valueNew = trim(strval($value));
            if (is_array($value)) $valueNew = arrayToStr($value);

            $len = strlen($valueNew);
            if ($len > 1 && substr($valueNew, 0,1)=="\"" && substr($valueNew, $len-1)=="\"") $valueNew = substr($valueNew,1, $len-1);

            $valueNew = trim($valueNew);
            if ($valueNew == "" || $valueNew == "null") continue;

            $param[] = $valueNew;
        }
        $param[] = $this->tikTokConfig['salt'];
        sort($param, SORT_STRING);
        return md5(trim(implode('&', $param)));
    }

    private function arrayToStr($map = [])
    {
        $isMap = isArrMap($map);

        $result = "";
        if (!empty($isMap)) $result = "map[";

        $keyArr = array_keys($map);
        if (!empty($isMap)) sort($keyArr);

        $paramsArr = array();
        foreach($keyArr as $key) {
            $v = $map[$key];
            if (!empty($isMap)) {
                if (is_array($v)) {
                    $paramsArr[] = sprintf("%s:%s", $key, arrayToStr($v));
                } else  {
                    $paramsArr[] = sprintf("%s:%s", $key, trim(strval($v)));
                }
            } else {
                if (is_array($v)) {
                    $paramsArr[] = arrayToStr($v);
                } else  {
                    $paramsArr[] = trim(strval($v));
                }
            }
        }

        $result = sprintf("%s%s", $result, join(" ", $paramsArr));
        if (empty($isMap)) {
            $result = sprintf("[%s]", $result);
        } else {
            $result = sprintf("%s]", $result);
        }

        return $result;
    }

    private function isArrMap($map = [])
    {
        foreach($map as $k =>$v) {
            if (is_string($k)) return true;
        }
        return false;
    }

}