Order.php 13.4 KB
<?php

namespace addons\facrm\library;

use app\admin\model\facrm\contract\Receivables;
use app\common\library\Auth;
use app\common\model\User;
use fast\Date;
use think\Exception;

class Order
{

    /**
     * 发起订单支付[收款]
     *
     * @param string  $receivables_id     付款单ID或合同ID或访问付款凭证
     * @param string $ordertype 付款类型 renew续费,pay支付
     * @param string $paytype 支付类型 wechat,alipay
     * @param string $method    支付方法
     * @param string $openid    Openid
     * @param string $notifyurl 通知地址
     * @param string $returnurl 返回地址
     * @param array $extend 附加参数
     * @return \addons\epay\library\Collection|\addons\epay\library\RedirectResponse|\addons\epay\library\Response
     * @throws Exception
     */
    public static function submit($pay_token,$ordertype='pay',$paytype = 'wechat', $method = 'web', $openid = '', $notifyurl = '', $returnurl = '',$extend=array())
    {
        $epay = get_addon_info('epay');

        if (empty($epay) || !$epay['state']) {
            throw new Exception("请先在后台安装并配置微信支付宝整合插件");
        }

        //小程序和公众号openid不能为空
        if (in_array($method, ['mp', 'miniapp']) && empty($openid)) {
            throw new Exception("公众号和小程序支付openid不能为空!");
        }
        //获取续费配置
        $pay_config =\addons\facrm\library\Order::getPayConfig();
        if (!$pay_config) {
            throw new Exception(__("未配置收款"));
        }

        $contractModel=   new \app\admin\model\facrm\Contract();
        $receivablesModel=   new \app\admin\model\facrm\contract\Receivables();
        $contract_id=$renew_day=$receivables_id=0;
        switch ($ordertype){
            case 'pay'://收款单
                //判断是否开启续费功能
                if ($pay_config['values']['online_pay'] != 1) {
                    throw new Exception(__("未开启收款功能"));
                }

                if (is_numeric($pay_token)){
                    $receivablesInfo=$receivablesModel->where('id',$pay_token)->find();
                }else{
                    $receivablesInfo=$receivablesModel->where('pay_token',$pay_token)->find();
                }
                $check_data=\addons\facrm\library\Order::checkPay($receivablesInfo, 'pay',$pay_config);
                if ($check_data['code']!=1){
                    throw new Exception($check_data['msg']);
                }

                $amount=$receivablesInfo['money'];
                $title="收款单号{$receivablesInfo['number']},支付{$amount}元";
                $contract_id=$receivablesInfo->contract_id;
                $receivables_id=$receivablesInfo->id;
                break;
            case 'renew'://合同续费
                //判断是否开启续费功能
                if ($pay_config['values']['renew_pay'] != 1) {
                    throw new Exception(__("未开启续费功能"));
                }

                if (is_numeric($pay_token)){
                    $contractInfo=$contractModel->where('id',$pay_token)->find();
                }else{
                    $contractInfo=$contractModel->where('renewtoken',$pay_token)->find();
                }
                $check_data=self::checkPay($contractInfo, 'renew',$pay_config);
                if ($check_data['code']!=1){
                    throw new Exception($check_data['msg']);
                }
                //判断合同是否设定了续费单价,
                if ($contractInfo['renewmoeny']<=0){
                    $contractInfo['renewmoeny']=bcdiv(($contractInfo['money']*$pay_config['values']['renew_percentage']),100,2);
                }
                //判断下单数
                if ($pay_config['values']['renew_max']<$extend['number']){
                    throw new Exception(__("下单数量不能超过%s",$pay_config['values']['renew_max']));
                }
                //续费转化为天数
                $renew_day=0;
                switch ($pay_config['values']['renew_unit']){
                    case 'year':
                        $renew_day=365*$extend['number'];
                        break;
                    case 'month':
                        $renew_day=date("t",strtotime(date('Y-m-d')))*$extend['number'];
                        break;
                    default:
                        $renew_day=$extend['number'];

                }
                $amount=$contractInfo['renewmoeny']*$extend['number'];//续费总额=续费金额*单数
                $title="合同续费{$contractInfo['number']}支付{$amount}元";
                $contract_id=$contractInfo->id;
                break;
            default:
                throw new Exception(__("操作方式有误"));

        }
		if($amount<=0){
			throw new Exception(__("金额有误"));
		}


        $auth = Auth::instance();
        $user_id = $auth->isLogin() ? $auth->id : 0;
        $order=null;

        $request = \think\Request::instance();
        if (!$order) {
            $orderid = date("Ymdhis") . sprintf("%08d", $user_id) . mt_rand(1000, 9999);
            $data = [
                'orderid'   => $orderid,
                'contract_id'   => $contract_id,
                'receivables_id'   => $receivables_id,
                'renew_day'=>$renew_day,
                'user_id'   => $user_id,
                'amount'    =>$amount,
                'payamount' => 0,
                'paytype'   => $paytype,
                'ip'        => $request->ip(),
                'useragent' => substr($request->server('HTTP_USER_AGENT'), 0, 255),
                'status'    => 'created',
                'ordertype'=>$ordertype,
            ];
            $order = \addons\facrm\model\Order::create($data);
        }



        $notifyurl = $notifyurl ? $notifyurl :addon_url('facrm/order/epay/type/notify/paytype/'.$paytype,[],'',true);
        $returnurl = $returnurl ? $returnurl :addon_url('facrm/order/epay',['type'=>'return','paytype'=>$paytype],'',true);

        $params = [
            'amount'    => $amount,
            'orderid'   => $order->orderid,
            'type'      => $paytype,
            'title'     => $title,
            'notifyurl' => $notifyurl,
            'returnurl' => $returnurl,
            'method'    => $method,
            'openid'    => $openid
        ];



        $response = \addons\epay\library\Service::submitOrder($params);
        return $response;
    }


    /**
     * 订单结算
     * @param int    $orderid   订单号
     * @param float  $payamount 支付金额
     * @param string $memo      备注
     * @return bool
     */
    public static function settle($orderid, $payamount, $memo = '')
    {

        $order = \addons\facrm\model\Order::getByOrderid($orderid);


        if (!$order) {
            \think\Log::write("__支付[receivables][pay][{$orderid}][订单id不存在]");
            return false;
        }
        if ($payamount != $order['amount']) {
            \think\Log::write("__支付[receivables][pay][{$orderid}][订单支付金额不一致]");
            return false;
        }
        $pay_config =   $pay_config =self::getPayConfig();

        if ($order['status'] != 'paid') {

            $order->payamount = $payamount;
            $order->paytime = time();
            $order->status = 'paid';
            $order->memo = $memo;

            $order->save();
            switch ($order->ordertype){
                case 'pay':

                    //收款单改为付款状态
                    $receivablesModel=   new \app\admin\model\facrm\contract\Receivables();
                    $receivablesInfo=$receivablesModel->where('id',$order->receivables_id)->find();
                    if ($receivablesInfo){
                        $receivablesInfo->contract->return_money+=$payamount;
                        $receivablesInfo->contract->save();
                        $receivablesInfo->account_id= $order->paytype=='wechat'?$pay_config['values']['weixin_id']:$pay_config['values']['alipay_id'];

                        $receivablesInfo->pay_status=1;
                        $receivablesInfo->return_time=time();
                        $receivablesInfo->check_status=2;
                        $receivablesInfo->remark.="在线支付";
                        $receivablesInfo->save();
                    }
                    $result = \think\Hook::listen('facrm_receivables_order_settled', $order);
                    break;
                case 'renew':
                    $contractModel=   new \app\admin\model\facrm\Contract();
                    $contractInfo=$contractModel->where('id',$order->contract_id)->find();
                    //续费
                    $remark=__("在线续费%s天",$order->renew_day);

                    //判断续期处理方式,只有合同过期才需要处理
                    if ($pay_config['values']['renew_type']!=1&&$contractInfo->end_time<time()){
                        $contractInfo->end_time= time()+(86400*$order->renew_day);
                    }else{
                        $contractInfo->end_time= $contractInfo->end_time+(86400*$order->renew_day);
                    }
                    $contractInfo->totalday= $contractInfo->totalday+$order->renew_day;//累加续费天数
                    $contractInfo->totalrenew= $contractInfo->totalrenew+$payamount;//累加续费总额
                    $contractInfo->save();
                    //增加回款记录
                    $contractInfo->receivables()->save([
                        'number'=>date("Ymdhis") . sprintf("%04d", $contractInfo->id) . mt_rand(1000, 9999),
                        'customer_id'=>$contractInfo->customer_id,
                        'contract_id'=>$contractInfo->id,
                        'return_time'=>time(),
                        'account_id'=>$order->paytype=='wechat'?$pay_config['values']['weixin_id']:$pay_config['values']['alipay_id'],
                        'money'=>$payamount,
                        'check_status'=>2,//默认审批通过
                        'remark'=>$remark,
                        'pay_type'=>3,
                        'pay_status'=>'1',
                        'create_user_id'=>0,
                        'order_admin_id'=>$contractInfo->order_admin_id,
                        'create_time'=>time(),
                    ]);


                    break;

            }




        }
        return true;
    }

    /**
     * 获取支付的配置
     * @return array|bool|false|\PDOStatement|string|\think\Model|null
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public static function getPayConfig(){
        $settingModel = new \app\admin\model\facrm\Setting();
        $pay_config = $settingModel->where('key', 'payonline')->find();
        return $pay_config;
    }

    /**
     * 支付检查
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public static function checkPay($row,$ordertype='pay',&$pay_config=[]){
        $return_data=['code'=>0,'data'=>[],'msg'=>''];

        if (!$pay_config){
            $pay_config =self::getPayConfig();
        }

        if (!$pay_config) {
            $return_data['msg']="未开通在线收款";
            return $return_data;
        }
        switch ($ordertype){
            case 'pay':
                //判断是否开启收款功能
                if ($pay_config['values']['online_pay'] != 1) {
                    $return_data['msg']="未开启收款功能";
                    return $return_data;
                }
                if (!$row) {
                    $return_data['msg']="付款单不存在";
                    return $return_data;
                }
                /*//判断合同是否审核
                if ($row->contract->check_status != 2) {
                    $return_data['msg']="合同未审核或未通过";
                    return $return_data;
                }*/

                //判断状态
                if (!isset($row['pay_status']) || $row['pay_status'] != 0 || $row['money'] <= 0 || $row['pay_type'] != 2) {
                    $return_data['msg']="不需要支付";
                    return $return_data;
                }
                break;
            case 'renew':
                //判断是否开启续费功能
                if ($pay_config['values']['renew_pay'] != 1) {
                    $return_data['msg']="未开启续费功能";
                    return $return_data;
                }
                if (!$row) {
                    $return_data['msg']="合同不存在";
                    return $return_data;
                }
                //判断是否审核
                if ($row['check_status'] != 2) {
                    $return_data['msg']="审核未通过";
                    return $return_data;
                }
                //判断是否到期时间是否可以续费
                $newtime = time();
                if ($newtime < $row['end_time'] &&
                    (Date::span($row['end_time'], $newtime, 'days')>$pay_config['values']['renew_day'])) {
                    $return_data['msg']=__("最多只能提前%s天续费",$pay_config['values']['renew_day']);
                    return $return_data;
                }
                break;
            default:

        }
        $return_data['code']=1;
        return   $return_data ;

    }
}