<?php


namespace App\Services\pay;

use Api\PhpServices\Idgen\Idgen;
use Api\PhpUtils\Log\FileLog;
use App\Models\Dictionary;
use App\Models\order\mysql\PayOrder;
use App\Models\order\mysql\PayOrderItem;
use App\Models\order\mysql\PayOrderClearing;
use App\Models\order\mysql\PayOrderClearingItem;
use App\Services\order\OrderService;

use App\Services\pingxx\PingxxService;
use App\Services\wallet\WalletService;
use Helpers\Strategy;
use Helpers\Sdk;
use Api\PhpServices\Wechat\Msg;
use Yaf\Application;

use App\Exception\custom\PayException;
use App\Exception\BaseException;

class PayService
{
    // 订单信息
    private $order_info = [];
    // 子订单信息
    private $order_items = [];

    private $pay_order = [];
    private $clear_list = [];
    private $clear_items_list = [];

    public function do_pay($order_id, $user_id, $pingxx_id, $pay_method_id = 105, $extra = [])
    {
        if(empty($order_id)) {
            throw new PayException(['cus' => 1]);
        }
        // 获取订单信息
        $data = OrderService::getFullOrderData($order_id);
        if (empty($data['result']['order_info'])) {
            throw new PayException(['cus' => 2]);
        }

        $order_info = $data['result']['order_info'];
        if ($order_info['user_id'] != $user_id) {
            throw new PayException(['cus' => 3]);
        }

        if (empty($order_info['pay_expiration_time'])) {
            throw new PayException(['cus' => 17]);
        }

        $pay_expiration_time = strtotime($order_info['pay_expiration_time']);
        if($pay_expiration_time < time()) {
            throw new PayException(['cus' => 16]);
        }

        if(empty($data['result']['order_item_list'])) {
            throw new PayException(['cus' => 14]);
        }

        $metadata = [
            'app_id'=>'merchant-c',
            'pingxx_id'=>PingxxService::getInstance($pingxx_id)->getAppId(),
            'environ'=>Application::app()->environ(),
            'order_id'=>$order_id,
            'goods'=>[],
            'marketing'=>[],
            'order_item_id'=>[],
        ];

        $min_expire_time = $now = time();
        foreach ($data['result']['order_item_list'] as $item) {

            if(strtotime($item['expiration_time']) < $min_expire_time) {
                $min_expire_time = strtotime($item['expiration_time']);
            }

            if(empty($metadata['goods'][$item['goods_sku_id']])) {
                $metadata['goods'][$item['goods_sku_id']] = 0;
            }

            $metadata['goods'][$item['goods_sku_id']] += $item['goods_num'];
            if(!empty($item['marketing_id'])) {
                $metadata['marketing'][$item['goods_sku_id']] = $item['marketing_id'];
            }
            array_push($metadata['order_item_id'], $item['order_item_id']);
        }

        if($now > $min_expire_time) {
            throw new PayException(['cus' => 15]);
        }

        //订单过期时间必须满足 70s+
        if($pay_expiration_time - $now < 70 ) {
            $pay_expiration_time = $now + 70;
        }

        $pay_order_id = $this->gen_pay_order_id($user_id);
        $new_pay_order = [
            'pay_order_id' => $pay_order_id,
            'user_id' => $order_info['user_id'],
            'life_account_id' => $order_info['life_account_id'],
            'shop_id' => $order_info['shop_id'],
            'order_id' => $order_info['order_id'],
            'pay_order_status' => Dictionary::O_PAY_STATUS_UNPAY,
            'pay_amount' => $order_info['payment'],
            'pay_channel' => $pay_method_id,
            'third_order_id' => '',
            'pingxx_id' => PingxxService::getInstance($pingxx_id)->getAppId(),
            'expire_time' => date('Y-m-d H:i:s', $pay_expiration_time),
            'source_name' => 10,
            'service_name' => 1,
            'business_from' => $order_info['business_from'],
            'extra' => json_encode([]),
        ];

        //获取或创建支付订单
        $pay_order = PayOrder::get_valid_order($order_id, $new_pay_order);
        if (empty($pay_order)) {
            throw new PayException(['cus' => 4]);
        }

        //不支持修改订单过期时间，再次调用支付服务
        if(strtotime($pay_order['expire_time']) < time()) {
            throw new PayException(['cus' => 16]);
        }

        if ($pay_order['pay_order_status'] == Dictionary::O_PAY_STATUS_PAYED) {
            throw new PayException(['cus' => 5]);
        }

        // 已经创建，需要查询返回
        if(!empty($pay_order['third_order_id'])) {
            $ret = PingxxService::getInstance($pingxx_id)->getOrder($pay_order['third_order_id']);
        } else {
            $ret = PingxxService::getInstance($pingxx_id)->createOrder($pay_order, $metadata);
        }

        if (!empty($ret['error'])) {
            throw new BaseException(['msg'=>$ret['error']['message'], 'code'=>'2301']);
        }

        if ($ret["status"] == 'paid' || $ret['status'] == 'refunded') {
            $edit = [
                'pay_order_status' => Dictionary::O_PAY_STATUS_PAYED,
                'third_order_id' => $ret['id'],
            ];
            //todo 需要做补偿
            //PayOrder::update($edit, ['pay_order_id' => $pay_order['pay_order_id']]);
            throw new PayException(['cus' => 5]);

        } elseif ($ret["status"] == 'canceled') {
            $edit = [
                'expire_time' => date('Y-m-d H:i:s'),
            ];
            //todo 需要做状态同步，不仅仅是更新状态
            PayOrder::update($edit, ['pay_order_id' => $pay_order['pay_order_id']]);
            throw new PayException(['cus' => 6]);

        } elseif ($ret["status"] == 'created') {
            $edit = [
                'pay_order_status' => Dictionary::O_PAY_STATUS_WAIT,
                'third_order_id' => $ret['id'],
            ];
            PayOrder::update($edit, ['pay_order_id' => $pay_order['pay_order_id']]);

        } else {
            throw new PayException(['cus' => 0]);
        }

        //存在一个继续支付单订单
        if($pay_order_id != $pay_order['pay_order_id']) {
            $ret['exist'] = true;
        }

        $channel_exist = false;
        $channel = $this->getChannel($pay_method_id);
        if(!empty($ret['charges']['data'])) {
            //是否存在
            foreach ($ret['charges']['data'] as $ch) {
                if($ch['channel'] == $channel) {
                    $channel_exist = true;
                }
            }

        }

        //判断是否做过pay操作 charge
        if($channel_exist == false) {
            // 创建支付单
            $payment = [
                'charge_order_no'=> $pay_order['pay_order_id'],
                'charge_amount'=> $pay_order['pay_amount'],
                'channel'=> $channel,
                'extra'=> $extra,
            ];

            $pay = PingxxService::getInstance($pingxx_id)->pay($ret['id'], $payment);
            if (!empty($pay['error'])) {
                throw new BaseException(['msg'=>$pay['error']['message'], 'code'=>'2002']);
            }

            return $pay;

        } else {
            return $ret;
        }
    }

    /**
     * @throws PayException
     * 回调订单支付
     */
    public function call_back($data)
    {
        if (!in_array($data['type'], ['order.succeeded', 'charge.succeeded'])) {
            return ['error'=>'支付回调类型不正确'];
        }

        if (empty($data['data']['object'])) {
            return ['error'=>'支付回调格式不正确'];
        }

        $object = $data['data']['object'];
        if(empty($object['metadata']['app_id']) || $object['metadata']['app_id'] != "merchant-c") {
            //非支付中心发出的订单，需要忽略
            return ['error'=>'非merchant渠道订单，不做处理。'];
        }

        if($data['type'] == 'charge.succeeded') {
            $pay_order_id = $object['order_no'];
            $paid = $object['paid'];
            $amount = $object['amount'];
        } else {
            $pay_order_id = $object['merchant_order_no'];
            $paid = $object['paid'];
            $amount = $object['actual_amount'];
        }

        if($paid != true) {
            return ['error'=>'支付状态不正确，不做处理。'];
        }

        $pay_order = PayOrder::get('*', ['pay_order_id' => $pay_order_id]);
        if (empty($pay_order)) {
            throw new PayException(['cus' => 7]);
        }
        if($pay_order['pay_amount'] != $amount) {
            throw new PayException(['cus' => 8]);
        }

        // 修改状态，锁定业务
        $edit = [
            'pay_order_status' => 2, //已经支付
            'pingxx_callback_success_time' => date('Y-m-d H:i:s'),
        ];
        $where = [
            'pay_order_id' => $pay_order_id,
            'pay_order_status' => 1, //待支付确认
        ];
        $cnt = PayOrder::update($edit, $where);

        //保持幂等返回成功
        if($cnt == 0) {
            return ['pay_order_id' => $pay_order_id];
        }

        //获取订单 + 子单 + 分销信息
        $ret = OrderService::getFullOrderData($pay_order['order_id'], $pay_order['user_id']);
        if (empty($ret['result']['order_info'])) {
            throw new PayException(['cus' => 1]);
        }

        $this->pay_order = $pay_order;

        // 生成支付清分单
        $this->make_order_clearing($ret['result']);

        //收集第一商品名称
        if($this->order_items) {
            $title = $this->order_items[0]['goods_name'] ?? '商品名称';
        } else {
            $title = '';
        }


        try{
            //通知消息
            $app_id = 'wx65e9ba99c333444f';
            $template_id = 'EzOH2ZpfW-eUdFf9gzjZTAv-Z9PFmKHNsQ0VOGvvN7c';
            $page_url = \Yaf\Application::app()->getConfig()->get('wxApp.jw.order');
            $type = 1;
            $query = [
                $title,
                $pay_order['order_id'],
                round($pay_order['pay_amount'] / 100, 2),
                date('Y-m-d'),
            ];

            if(isset($ret['result']['order_info']['business_from']) && $ret['result']['order_info']['business_from'] != 2) {
                //接龙业务不发送消息
                Msg::send($pay_order['user_id'], $app_id, $template_id, $page_url, $type, $query);
            }

        }catch (\Throwable $e) {
            ;
        }

        return ['pay_order_id' => $pay_order_id];
    }

    /**
     * @param $order_id
     * @return array
     * @throws BaseException
     * @throws PayException
     * 返回订单状态及订单渠道列表
     */
    public function pay_charges($order_id) {

        $pay_order = PayOrder::get('*', ['order_id'=>$order_id]);
        if(empty($pay_order)) {
            throw new PayException(['cus' => 18]);
        }

        $data = [
            'status'=>'created',
            'max_expire_time'=>$pay_order['expire_time'],
            'list'=>[]
        ];

        $max_expire_time = strtotime($pay_order['expire_time']);

        if($max_expire_time < time()) {
            $data["status"] = 'canceled';
        }

        if(empty($pay_order['third_order_id'])) {
            return $data;
        }

        //paid、refunded、canceled、created
        $ret = PingxxService::getInstance($pay_order['pingxx_id'])->getOrder($pay_order['third_order_id']);
        if (!empty($ret['error'])) {
            throw new BaseException(['msg'=>$ret['error']['message'], 'code'=>'2301']);
        }

        $data["status"] = $ret["status"];
        if(!empty($ret['charges']['data'])) {
            //是否存在
            foreach ($ret['charges']['data'] as $ch) {

                $data["list"][] = [
                    'paid'=>$ch['paid'],
                    'refunded'=>$ch['refunded'],
                    'channel'=>$ch['channel'],
                    'time_expire'=>$ch['time_expire'],
                ];

                if($max_expire_time < $ch['time_expire']) {
                    $max_expire_time = $ch['time_expire'];
                }
            }
        }

        $data['max_expire_time'] = date('Y-m-d H:i:s', $max_expire_time);
        return $data;
    }

    /**
     * @param $order_item_id
     * @param $life_account_id
     * @throws \App\Exception\custom\CodeSpecialException
     * 子订单核销
     */
    public function write_off($order_item_id, $life_account_id)
    {
        $cnt = 0;
        //锁定状态
        try{
            PayOrderItem::beginTransaction();

            $item = PayOrderItem::getMaster('*', ['order_item_id' => $order_item_id]);
            if(empty($item)) {
                throw new PayException(['cus'=>10]);
            }

            if($item['refund_order_status'] != 0) {
                throw new PayException(['cus'=>9]);
            }

            $pay_order = PayOrder::getMaster('*', ['pay_order_id'=>$item['pay_order_id']]);
            if(empty($pay_order) || $pay_order['life_account_id'] != $life_account_id) {
                throw new PayException(['cus'=>11]);
            }

            $cnt = PayOrderItem::update([
                'notify_account_status' => 0,
                'can_notify_account' => 1,
                'can_notify_account_time' => date('Y-m-d H:i:s'),
            ], ['order_item_id' => $order_item_id, 'can_notify_account'=>0, 'refund_order_status'=>0]);


            PayOrderItem::commit();
        }catch (\Exception $e) {
            PayOrderItem::rollback();
            throw new BaseException(['msg'=>$e->getMessage(), 'code'=>$e->getCode()]);
        }

        if($cnt == 0) {//幂等直接返回
            return ['order_item_id' => $order_item_id];
        }

        $this->sync_account_wallet($order_item_id);

        return ['order_item_id' => $order_item_id];
    }

    /**
     * @param $order_item_id
     * @throws \App\Exception\custom\CodeSpecialException
     * 同步钱包处理
     */
    public function sync_account_wallet($order_item_id) {

        $cnt = PayOrderItem::update([
            'notify_account_status' => 1,
        ], ['order_item_id' => $order_item_id, 'can_notify_account' => 1, 'notify_account_status'=>0]);

        if($cnt ==0) {//乐观锁，不满足条件不处理
            return true;
        }

        //注意查找需要保证pdo是一个，避免数据操作超时
        $clearing_items = PayOrderClearingItem::selectMaster('*',
            ['order_item_id' => $order_item_id]
        );

        $wallet_list = [];
        foreach ($clearing_items as $row) {
            if($row['pay_amount'] <= 0) {
                continue;
            }

            //处理商家结算价格的兼容
            if($row['clear_payment'] > 0 && $row['pay_sub_type'] == 102) {
                $pay_amount = $row['clear_payment'];
            } else {
                $pay_amount = $row['pay_amount'];
            }

            $wallet_list[] = [
                'user_id' => $row['account_id'],
                'service_name' => 10,
                'source_name' => 1,
                'amount' => $pay_amount,
                'third_order_id' => $row['pay_order_clearing_item_id'],
                'third_order_id_type' => $row['pay_sub_type'],
                'third_order_desc' => $row['remark'],
            ];
        }

        try{
            if($wallet_list) { //同步成功，返回结果
                WalletService::send(['list'=>$wallet_list]);
            }
            PayOrderItem::update([
                'notify_account_status' => 2,
                'notify_account_times[+]' => 1,
                'notify_account_success_time' => date('Y-m-d H:i:s')
            ], ['order_item_id' => $order_item_id, 'can_notify_account' => 1]);

        } catch (\Exception $e) {
            //补偿处理
            $item = PayOrderItem::getMaster('*', ['order_item_id' => $order_item_id]);
            $time = $this->getNextTime($item['notify_account_times']); //计算下次同步的时间
            PayOrderItem::update([
                'notify_account_status' => 0,
                'notify_account_times[+]' => 1,
                'can_notify_account_time' => date('Y-m-d H:i:s', $time),
            ], ['order_item_id' => $order_item_id, 'can_notify_account' => 1]);

            FileLog::error('pay-service:wallet: 钱包同步失败', json_encode($wallet_list, JSON_UNESCAPED_UNICODE), $e);
        }
    }

    /**
     * @param $data
     * 构造订单流水
     */
    private function make_order_clearing($data)
    {
        $this->order_info = $data['order_info'];
        $this->order_items = $data['order_item_list'];

        $this->clear_list = [];
        $this->clear_items_list = [];

        $pay_order_items = [];
        foreach ($this->order_items as $r) {
            $pay_order_items[] = [
                'pay_order_item_id' => $this->gen_pay_order_item_id(),
                'pay_order_id' => $this->pay_order['pay_order_id'],
                'order_id' => $this->pay_order['order_id'],
                'order_item_id' => $r['order_item_id'],
                'payment' => $r['payment'],
                'user_id' => $this->pay_order['user_id'],
            ];
        }

        $wx_tip = $this->make_tip_clearing(); //微信手续费
        $distribution_tip = $this->make_distribution_clearing(); //团长收益
        $platform_tip = $this->make_platform_clearing(); //平台收益
        $merchant_cash = $this->order_info['payment'] - $wx_tip - $distribution_tip - $platform_tip;

        //核对各项资金的合理性
        if($wx_tip <0 || $distribution_tip <0 || $platform_tip < 0 || $merchant_cash < 0) {
            FileLog::error('pay-service: 支付预结算失败，结算资金为负',
                json_encode([$this->order_info['payment'], $wx_tip, $distribution_tip, $platform_tip, $merchant_cash]));
            throw new PayException(['cus'=>12]);
        }

        $this->make_merchant_clearing($merchant_cash); //商户收益

        try {
            PayOrderClearing::beginTransaction();
            $c_cnt = PayOrderItem::insert($pay_order_items, ['rowCount' => true]);
            $i_cnt = PayOrderClearing::insert($this->clear_list, ['rowCount' => true]);
            $ci_cnt = PayOrderClearingItem::insert($this->clear_items_list, ['rowCount' => true]);

            if ($i_cnt * $c_cnt * $ci_cnt == 0) {
                throw new PayException(['cus' => 0]);
            }

            PayOrderClearing::commit();
        } catch (\Exception $e) {
            PayOrderClearing::rollback();
            throw new PayException(['cut' => 5]);
        }

        //如果是不可退款商品，则需进入结算队列
        foreach ($this->order_items as $r) {
            // 收集直接到账信息
            //rule_refund 退款规则：1到期自动退款，2购买后不允许退款，3到期后不退款
            if($r['rule_refund'] == 2 ) { //分销商品一定是不可退
                PayOrderItem::update([
                    'can_notify_account'=>1,
                    'can_notify_account_time'=>date('Y-m-d H:i:s')
                ], ['order_item_id'=>$r['order_item_id']]);
            }
        }
    }

    /**
     * @param $payment
     * @return false|float
     * 获取微信手续费
     */
    private function make_tip_clearing()
    {
        $wx_rate = config('pay','pay.wechat_rate') ?? 60; //微信利率 60 / 10000
        $wx_account_id = config('pay','pay.wechat_account_id') ?? '1111';

        $float_tip = $wx_rate * $this->order_info['payment'] / 10000;
        if($float_tip >= 1 ) {
            $total_tip = round($float_tip);
        } else {
            $total_tip = 0;
        }
        if (empty($total_tip)) {
            return 0;
        }

        $account = [
            'account_id' => $wx_account_id,
            'amount' => $total_tip,
        ];

        $account['account_type'] = 4; //三方手续费 + 平台总帐
        $account['pay_type'] = 2; //支付
        $account['pay_sub_type'] = 406; //第三方渠道手续费
        $account['need_recorded'] = 0; //不需同步给平台

        /* 微信手续费总单，在退款、核销的时候会更新这个金额，保证他的准确 */
        $this->do_clearing_data($account, $total_tip, true);
        return $total_tip;
    }

    /**
     * @param $total
     * @return false|float
     * 计算平台收入
     */
    private function make_platform_clearing()
    {
        $account = [
            'account_id' => '100020003201',
            'amount' => 0,
            'rate' => 0,
            'title' => '平台收益',
        ];

        $total_tip = $account['amount'] = round($this->order_info['total_price'] * $account['rate'] / 10000);
        if (empty($total_tip)) {
            return 0;
        }

        $account['account_type'] = Dictionary::ACCOUNT_TYPE_SS;
        $account['pay_type'] = Dictionary::PAY_TYPE_IN;
        $account['pay_sub_type'] = Dictionary::PAY_SUB_TYPE_SYS_IN;
        $account['need_recorded'] = Dictionary::NO;

        $this->do_clearing_data($account, $total_tip, false);
        return $total_tip;
    }

    /**
     * @return mixed
     * 计算分销信息, 分销没有总帐，仅有单条floor的计算
     */
    private function make_distribution_clearing()
    {

        /**
         * 'distributor_user_id'=>122234,
         * 'distributor_commission_value'=>60,
         * 'parent_user_id'=>122234 . rand(111, 999),
         * 'parent_commission_value'=>60,
         */

        $total_tip = 0;
        foreach ($this->order_items as $r) {
            //仅处理分销业务
            if(empty($r['distributor_user_id']) || $r['marketing_type'] != 1) {
                continue;
            }
            $r['distributor_commission_value'] = intval($r['distributor_commission_value']);
            $r['parent_commission_value'] = intval($r['parent_commission_value']);

            $_one = $_two = 0;
            if($r['commission_mode'] == 1) {
                $_one = floor($r['distributor_commission_value'] * $this->order_info['total_price'] / 10000);
                $_two = floor($r['parent_commission_value'] * $this->order_info['total_price'] / 10000);

            } elseif($r['commission_mode'] == 2) {
                $_one = $r['distributor_commission_value'];
                $_two = $r['parent_commission_value'];
            }

            $users[0] = [
                'user_id'=>$r['distributor_user_id'],
                'value'=>$r['distributor_commission_value'],
                'amount'=>$_one
            ];

            if(!empty($r['parent_user_id'])) {
                $users[1] = [
                    'user_id'=>$r['parent_user_id'],
                    'value'=>$r['parent_commission_value'],
                    'amount'=>$_two
                ];
            }

            foreach ($users as $u) {
                if (empty($r['user_id']) || $u['amount'] == 0) {
                    continue;
                }

                $this->clear_items_list[] = [
                    'pay_order_clearing_item_id' => $this->gen_pay_order_clearing_item_id(),
                    'pay_order_clearing_id' => '',
                    'pay_order_id' => $this->pay_order['pay_order_id'],
                    'order_id' => $this->pay_order['order_id'],
                    'order_item_id' => $r['order_item_id'],
                    'account_id' => $u['user_id'],
                    'account_type' => 1, //用户
                    'pay_amount' => $u['amount'],
                    'clear_payment' => 0, //商品结算价格
                    'pay_type' => 1, //收入
                    'pay_sub_type' => 105, //团长佣金收入
                    'remark' => '',
                    'need_recorded' => 1,
                ];

                $total_tip += $u['amount'];
            }
        }

        return $total_tip;
    }

    /**
     * @param $merchant_cash
     * @return mixed
     * 计算商户清分信息
     */
    private function make_merchant_clearing($merchant_cash)
    {
        $ret = $this->get_life_account($this->order_info['life_account_id']);
        if(empty($ret['result']['life_account_admin_id'])) {
            $log_string = json_encode([
                'life_account_id'=>$this->order_info['life_account_id'],
                'ret'=>$ret,
            ], JSON_UNESCAPED_UNICODE);

            FileLog::error('pay-service:', '获取生活号管理员失败', $log_string);
            throw new PayException(['cus'=>13]);
        }

        $account = [
            'account_id' => $ret['result']['life_account_admin_id'],
            'amount' => $merchant_cash,
            'title' => '商家订单收益',
        ];

        $account['account_type'] = 2; //商户
        $account['pay_type'] = 1; //收入
        $account['pay_sub_type'] = 102; //商品交易
        $account['need_recorded'] = 1; //同步到平台总帐

        $this->do_clearing_data($account, $merchant_cash, false);
        return $merchant_cash;
    }

    private function do_clearing_data($account, $total_tip, $is_wx = false)
    {
        $total_amount = $this->order_info['payment']; //订单支付总价格
        $cleared_amount = 0; //已经结算记录
        $cleared_tip = 0; //已经结算记录

        $pay_order_clearing_id = $this->gen_pay_order_clearing_id();
        $this->clear_list[] = [
            'pay_order_clearing_id' => $pay_order_clearing_id,
            'pay_order_id' => $this->pay_order['pay_order_id'],
            'order_id' => $this->pay_order['order_id'],
            'account_id' => $account['account_id'],
            'account_type' => $account['account_type'],
            'pay_amount' => $account['amount'],
            'pay_type' => $account['pay_type'],
            'pay_sub_type' => $account['pay_sub_type'],
            'need_recorded' => $account['need_recorded'],
        ];

        if ($is_wx) { //微信不计算手续费拆弹
            return true;
        }

        foreach ($this->order_items as $r) {

            $current_tip = Strategy::getTip($r['payment'], $total_amount, $cleared_amount, $total_tip, $cleared_tip);
            $id = $this->gen_pay_order_clearing_item_id();

            //商家资金需要显示商品名称
            if($account['pay_sub_type'] == 102) {
                $remark = $r['goods_name'] ?? '';
                if(mb_strlen($remark) > 100) {
                    $remark = mb_substr($remark, 0, 100) . '...';
                }

                if(!empty($r['clear_price'])) {
                    $clear_payment = $r['goods_num'] * $r['clear_price'];
                } else {
                    $clear_payment = 0;
                }

            } else {
                $remark = '';
                $clear_payment = 0;
            }

            $this->clear_items_list[] = [
                'pay_order_clearing_item_id' => $id,
                'pay_order_clearing_id' => $pay_order_clearing_id,
                'pay_order_id' => $this->pay_order['pay_order_id'],
                'order_id' => $this->pay_order['order_id'],
                'order_item_id' => $r['order_item_id'],
                'account_id' => $account['account_id'],
                'account_type' => $account['account_type'],
                'pay_amount' => $current_tip,
                'clear_payment' => $clear_payment, //商品结算价格
                'pay_type' => $account['pay_type'],
                'pay_sub_type' => $account['pay_sub_type'],
                'remark' => $remark,
                'need_recorded' => $account['need_recorded'],
            ];

            $cleared_amount += $r['payment'];
            $cleared_tip += $current_tip;
        }
    }

    private function gen_pay_order_id($user_id)
    {
        $number = substr($user_id, -2);
        $ids = $this->get_idgen_id($number, 1);
        return array_pop($ids);
    }

    private function gen_pay_order_item_id()
    {
        $number = substr($this->order_info['user_id'], -2);
        $ids = $this->get_idgen_id($number, 1);
        return array_pop($ids);
    }

    private function gen_pay_order_clearing_id()
    {
        $number = substr($this->order_info['user_id'], -2);
        $ids = $this->get_idgen_id($number, 1);
        return array_pop($ids);
    }

    private function gen_pay_order_clearing_item_id()
    {
        $number = substr($this->order_info['user_id'], -2);
        $ids = $this->get_idgen_id($number, 1);
        return array_pop($ids);
    }

    private function get_idgen_id($number, $count = 1)
    {
        $number = intval($number);
        $res = Idgen::get(appConfig('idgen.partner'), appConfig('idgen.key'), [], [[
            "type" => "55c768",
            'number' => $number,
            "count" => $count]]);
        $id = $res['id_datetime']['55c768'] ?? [];
        return $id;
    }

    private function get_life_account($life_account_id)
    {
        $url = config('interface', 'merchant.lifeaccount.get_life_account_by_id');
        if (!$url) {
            throw new CodeSpecialException("failed" . __METHOD__);
        }
        $params = ['life_account_id' => $life_account_id];
        return Sdk::call($url, $params);
    }

    private function getChannel($pay_method_id) {

        $maps = [
            105=>"wx",	//微信 App 支付
            106=>"alipay",	//支付宝
            107=>"wx_pub",	//微信 JSAPI 支付
            108=>"wx_pub_qr",	//微信 Native 支付
            109=>"wx_wap",	//微信 H5 支付
            110=>"wx_lite",	//微信小程序支付
        ];

        if(!empty($maps[$pay_method_id])) {
            return $maps[$pay_method_id];
        } else {
            return $maps[105];
        }
    }

    private function getNextTime($times = 0) {
        return time() + pow(3, $times + 1);
    }
}