'', 'id' => '' ]; public static $orderData = []; public static $orderInfoData = []; public function getErrors(){ return self::$errorArr; } public function setOrder($order){ $this->order=$order; } /** * 检查通道是否存在错误 */ public function checkGatewayConfig() { $pay_method = $this->pay_method; if(empty($this->gateway_list)) { return self::addError(['msg' => '通道支付不存在']); } if (count($this->gateway_list) <= 0) { return self::addError(['msg' => '通道支付不存在']); } if (!isset($this->gateway_list[$pay_method])) { return self::addError(['msg' => '通道支付类型不存在']); } } /** * 取得订单,支付宝和微信返回的订单号都有差异,需要分开处理 * @param $order_sn */ public function getOrder($order_sn) { $this->order = Order::where('order_sn', $order_sn)->first(); //订单不存在返回空 if (empty($this->order)) { $this->debugLog('订单不存在:' . $order_sn); return false; } $this->pay_method = $this->order->gateway_method;//支付方法 $this->gateway_id = $this->order->gateway_id;//通道ID $this->merchant = Merchant::find($this->order->merchant_id); } /** * 取得当前支付通道的类型信息实例,$this->pay_gateway * @param $pay_type * @param array $custom_gateways * @param string $pay_channel * @return bool */ public function getGateway($pay_type, $custom_gateways = [],$pay_channel='') { //取得支付方法和类型 $pay_config = $this->payMethod($pay_type); $this->pay_type = $pay_config['pay_type']; $this->pay_method = $pay_config['method']; $this->debugLog('pay_config:' . json_encode(array_merge($pay_config, ['pay_channel' => $pay_channel]), true)); //取得配置通道文件 $this->gateway_list = config('gateway.' . $this->pay_type); if(!$this->gateway_list) { return false; } //检查通道配置信息 $this->checkGatewayConfig(); if (count(self::$errorArr) > 0) { return false; } //当前的支付类型方法的通道,比如扫码支付,有多个这样子 $all_gateways = $this->gateway_list[$this->pay_method]; //当前用户是否指定了支付通道 try { if (!is_array($custom_gateways)) { return false; } if (count($custom_gateways) > 0) { $this->pay_gateway = $this->randomCustomGateways($all_gateways, $custom_gateways,$pay_channel); } else { $this->pay_gateway = $this->randomAllGateways($all_gateways); } return $this->pay_gateway;//支付数据库信息 } catch (\Exception $e) { return false; } } /** * 全部轮询支付通道,随机切换 * @param $all_gateways * @return mixed */ public function randomAllGateways($all_gateways) { $total = count($all_gateways); return $all_gateways[mt_rand(0, $total - 1)]; } /** * 随机切换用户选择支付通道 * @param $all_gateways 所有通道 * @param $custom_gateways 用户自定义选择通道 * @param $pay_channel * @return bool|mixed */ public function randomCustomGateways($all_gateways, $custom_gateways,$pay_channel='') { $on_user_gateway_id = []; foreach ($all_gateways as $k => $v) { if (in_array($v['id'], $custom_gateways)) { if ($pay_channel != '') { if ($v['mch_id'] == $pay_channel) { $on_user_gateway_id[] = $v; } } else { $on_user_gateway_id[] = $v; } } } $total = count($on_user_gateway_id); if ($total <= 0) { return false; } return $on_user_gateway_id[mt_rand(0, $total - 1)]; } /** * 更新订单操作 * @return mixed|void */ public function updateOrder() { $order = $this->order; //判断是否本站 if ($order->merchant_id == 0) { //本地订单处理 return $this->locationOrder(); } else { //外站订单处理 return $this->outOrder(); } } /** * 错误输入数组 * @param $data * @return int */ public function addError($data) { return array_push(self::$errorArr, $data);//加入错误 //return self::$errorArr = self::$errorArr + $data;//加入错误数组 } /** * 验证必填参数 * @param $request */ public function checkPost($request) { $rq_data = $request->all(); $must_arr = $this->must_input; //验证字段 foreach ($must_arr as $k => $v) { if (!array_key_exists($v, $rq_data)) { $this->addError(['error' => 1, 'msg' => '缺少参数' . $v]); } } $this->setPayMethod($request);//设置请求方法 } /** * 检测提交de支付商户是否有错误 * @param $request */ public function checkMerchant($request) { $merchant = $this->merchant; if (empty($merchant)) { $this->addError(['error' => 1, 'msg' => '商户不存在']); } //后台关闭商户 if ($merchant->is_checked != 1) { $this->addError(['error' => 1, 'msg' => '商户支付通道关闭']); } //单笔最小交易金额 if ($merchant->min_price > $request->input('money')) { $this->addError(['error' => 1, 'msg' => '商户单笔交易最低' . $merchant->min_price]); } //单笔最大交易 if ($merchant->max_price < $request->input('money')) { $this->addError(['error' => 1, 'msg' => '商户单笔交易最大' . $merchant->max_price]); } } /**检查回调IP * @return bool */ public function checkIP(){ $ip = request()->getClientIp(); $ipArr = config('whitelist.callback'); if (isset($ipArr[$this->pay_type])) { $ipWhite = $ipArr[$this->pay_type]; $this->debugLog('回调IP', [$ip,$ipWhite]); if (!in_array($ip, $ipWhite)) { // $this->debugLog('IP不合法', [$ip,$ipWhite]); return false; } } return true; } public function debugLog($str = '', $arr = []) { $arr = is_array($arr) ? $arr : [$arr]; Log::channel('pay_order')->info($str, $arr); } /** * 检查通道验证,是否存在,是否超出单笔交易 * @param $request * @return mixed */ public function checkGateway($request) { $pay_type = $request->input('pay_type'); $pay_channel = $request->input('pay_channel'); $this->debugLog('-------------订单开始-------------'); $this->debugLog('appid->' . $request->input('app_id')); $this->debugLog('请求数据->' , $request->all()); // $this->debugLog('支付类型->' . $pay_type); // $this->debugLog('channel->' . $pay_channel); //选择服务类型 $this->setPayService($pay_type); if (is_null($this->pay_service)) { $this->debugLog('通道不存在或支付类型错误',$request->all()); return $this->addError(['error' => 1, 'msg' => '通道不存在或支付类型错误']); } $custorm_gateways = []; try { $custorm_gateways = $this->merchant['gateways_id'] ? explode(",", $this->merchant['gateways_id']) : []; } catch (\Exception $exception) { $custorm_gateways = []; } $this->gateway = $this->pay_service->getGateway($pay_type, $custorm_gateways,$pay_channel); if (!$this->gateway) { return $this->addError(['error' => 1, 'msg' => '通道不存在']); } $gategory_money = $this->gateway['limit_money'] ? $this->gateway['limit_money'] : 45000; //判断支付金额,是否大于通道限额 if ($request->input('money') > $gategory_money) { return $this->addError(['error' => 1, 'msg' => '超出单笔支付限额']); } } public function setOrderName() { return $this->order_sn . '定制订单';//这里需要伪造, } private function getcode($length){ $str = '0123456789abcdefghijklmnopqrstuvwxyz'; $s = ''; for ($i = 1; $i <= $length; $i++) { $num = mt_rand(0, 34); $s .= substr($str,$num, 1); } return $s; } /** * 提交订单的参数设置 * @param $request * @param int $is_local */ public function setOrderData($request, $is_local = 0) { $this->order_sn = order_sn(); $data['order_sn'] = $this->order_sn; $data['gateway_id'] = $this->gateway['id'];//通道id $data['gateway_method'] = $this->pay_method;//支付通道方法:扫码,移动,PC $data['name'] = $this->setOrderName();//这里需要伪造, $data['order_money'] = $request->input('money');//订单金额 $data['pay_type'] = $this->pay_type; $data['username'] = $this->user['nickname']; $data['local_user_id'] = $this->user['id']; $data['out_user_id'] = $request->input('user_id', ''); $data['out_trade_sn'] = $request->input('out_trade_sn', ''); $data['ewm_account'] = $request->input('ewm_account', ''); $data['language'] = $request->input('language', 'zh_cn'); $data['ewm_mark'] = $this->getcode(6); $data['order_at'] = date('Y-m-d H:i:s'); if ($is_local) { if (user('nickname')) { $data['username'] = user('nickname'); } } $this->setRatio($request, $is_local); $this->addOrderData($data); $this->setMerchantData($is_local); } /* * 设置费率计算 */ public function setRatio($request, $is_local) { return $is_local ? $this->localRatio($request) : $this->apiRatio($request); } /** * 提交支付的使用地方 * commonNotify() 取得 $this->gateway * checkGateway 取得 $this->gateway * 本地费率 * @param $request */ public function localRatio($request) { $money = floatval($request->input('money')); $ratio = $this->gateway['ratio']; $data['ratio'] = $ratio;//通道交易费率 $pate = $ratio * $money / 1000;//费率*金额=扣除的金额 $data['total_money'] = $money - $pate;//结算金额=提交金额 - 扣除费用金额; $data['pay_rate'] = $pate;//扣除费用金额 //通道成本金额=支付金额 * 通道费率 /1000 $data['gateway_money'] = $pate; $data['gateway_ratio'] = $ratio;//通道费率 $data['final_money'] = 0;//最后盈利,本站盈利0 $data['final_ratio'] = 0;//商户费率-通道费率=盈利费率 $data['up_ratio'] = 0;//本站上浮点数,全部归0 $data['original_ratio'] = $ratio;//原来费率,没有浮动之前的费率 $data['real_pate_money'] = $pate;//扣除商户真实费用 $this->addOrderData($data); } /** * 提交支付的使用地方 * commonNotify() 取得 $this->gateway * checkGateway 取得 $this->gateway * API支付费率 * 通道成本,上级佣金,股东佣金计算 * @param $requestpaySend */ public function apiRatio($request) { $money = floatval($request->input('money')); $data['up_ratio'] = $this->gateway['up_ratio'];//通道单独上浮费率 $data['original_ratio'] = $this->merchant->ratio;//原始费率 //结算费率=商户费率+上浮费率 // $data['ratio'] = $this->merchant->ratio + $data['up_ratio']; // 总费率:3% (通道成本+上浮) 2021-07-12 改成 $data['ratio'] = $data['up_ratio'] + $this->gateway['ratio']; //手续费=(商户费率+上浮费率)* 支付金额/1000 $pate = $data['ratio'] * $money / 1000; //通道费率 $gateway_ratio = $this->gateway['ratio']; //通道成本=支付金额*通道费率/1000 $gateway_money = $money * $gateway_ratio / 1000; //最后盈利=((商户费率 +上浮费率)- 通道费率)* 金额 /1000 $final_money = ($data['ratio'] - $gateway_ratio) * $money / 1000; //最后盈利点数=商户费率+上浮费率 - 通道费率或结算费率-通道费率 $final_ratio = $data['ratio'] - $gateway_ratio; //商户结算金额=支付金额 - (支付金额 * 商户费率+上浮费率)/1000。 $data['total_money'] = $money - $pate; //平台总手续费=(商户的费率 + 上浮费率)* 支付金额/1000 $data['pay_rate'] = $pate;//总扣点费用 //平台费率,没用上级的情况下=商户费率 + 通道上浮费率 $data['system_ratio'] = $data['ratio']; //扣除商户费用=(商户费率 + 通道上浮费率) * 支付金额/1000 $data['real_pate_money'] = $data['ratio'] * $money / 1000; //商户推广佣金费率,没用上级的情况下,都是0 $data['next_ratio'] = 0;//下级费率-上级费率=上级利润费率 //上级利润=上级点数*金额 $data['next_money'] = 0; //股东费率 $data['top_ratio'] = 0; //股东盈利 $data['top_money'] = 0; //通道成本 $data['gateway_money'] = $gateway_money; $data['gateway_ratio'] = $gateway_ratio; //扣除通道费率最后的盈利资金 $data['final_money'] = $final_money; //最后盈利费率real_pate_money $data['final_ratio'] = $final_ratio; //如果存在上级 if ($this->merchant->from_id != 0) { //存在上级,取得费率关系表 $ratio_info = $this->getRatioInfo($this->merchant->id); //dump($ratio_info); //判断上级是什么身份 //股东 if ($ratio_info['up_level'] == 1) { //股东身份,那么就是2级的级别 //股东盈利费率=商户费率-股东费率 $data['top_ratio'] = $this->merchant->ratio - $ratio_info['up_ratio']; //股东盈利 $data['top_money'] = $money * $data['top_ratio'] / 1000; //系统扣点费用=股东费率+上浮费率*金额/100 $data['pay_rate'] = ($ratio_info['up_ratio'] + $data['up_ratio']) * $money / 1000; //平台费率=上级费率 + 上浮费率 $data['system_ratio'] = ($ratio_info['up_ratio'] + $data['up_ratio']); //上级的话,计算最后盈利,通道成本和费率不变,变得盈利资金和盈利费率 //最后盈利=(平台费率 - 通道费率)* 金额 /1000,(平台费率-通道费率) *金额 /1000 // $data['final_money'] = ($data['system_ratio'] - $this->gateway['ratio']) * $money / 1000; // 佣金盈利2021-07-12 改为 上浮费率X金额 $data['final_money'] = ($data['ratio'] - $this->gateway['ratio']) * $money / 1000; //盈利费率=平台费率 - 通道费率 // $data['final_ratio'] = $data['system_ratio'] - $this->gateway['ratio'];//最后盈利费率 //改为上浮费率 $data['final_ratio'] = $data['ratio'] - $this->gateway['ratio'];//最后盈利费率 //股东-》商户,上下和顶级都是股东, $data['next_ratio'] = $data['top_ratio']; $data['next_money'] = $data['top_money']; $data['top_id'] = $ratio_info['up_id'];//股东id //dd(1123); //dump($data); //dd(2343424); } if ($ratio_info['up_level'] == 2) { //上级费率盈利=商户费率 - 代理费率 $data['next_ratio'] = $this->merchant->ratio - $ratio_info['up_ratio']; $data['next_money'] = $money * $data['next_ratio'] / 1000; //判断他的顶级是否存在,如果存在才有3级,不存在怎没有,还是2级 if ($ratio_info['top_id'] != 0) { //股东下的信息 //股东盈利费率=代理费率 - 股东费率 $data['top_ratio'] = $ratio_info['up_ratio'] - $ratio_info['top_ratio']; //股东盈利 $data['top_money'] = $money * $data['top_ratio'] / 1000; //系统扣点费用=股东费率+上浮费率*金额/100 $data['pay_rate'] = ($ratio_info['top_ratio'] + $data['up_ratio']) * $money / 1000; //平台费率=股东费率 + 上浮费率 $data['system_ratio'] = ($ratio_info['top_ratio'] + $data['up_ratio']); //代理盈利费率=商户-代理费率 // $data['next_ratio'] = $ratio_info['ratio'] - $ratio_info['up_ratio']; // $data['next_money'] = $money * $data['next_ratio'] / 1000; $data['top_id'] = $ratio_info['top_id'];//股东id $data['dali_id'] = $ratio_info['up_id'];//代理id //dd(111); } else { //代理2级计算 //系统扣点费用按股东的算=代理费率+上浮费率*金额/1000 $data['pay_rate'] = ($ratio_info['up_ratio'] + $data['up_ratio']) * $money / 1000; //平台费率=股d费率 + 上浮费率 $data['system_ratio'] = ($ratio_info['up_ratio'] + $data['up_ratio']); $data['dali_id'] = $ratio_info['up_id'];//代理id } //上级的话,计算最后盈利,通道成本和费率不变,变得盈利资金和盈利费率 //最后盈利=(平台费率 - 通道费率)* 金额 /1000,(平台费率-通道费率) *金额 /1000 $data['final_money'] = ($data['system_ratio'] - $this->gateway['ratio']) * $money / 1000; //盈利费率=平台费率 - 通道费率 $data['final_ratio'] = $data['system_ratio'] - $this->gateway['ratio'];//最后盈利费率 //dump($data); //dd(2343424); } } $this->addOrderData($data); } /** * 取得商户的费率关系表 * @param string $mid * @return \Illuminate\Config\Repository|mixed */ public function getRatioInfo($mid = '') { $config = config('merchant_ratio'); if (count($config) <= 0) { //没有记录的情况下,再来写入 write_merchant_ratio(); $config = config('merchant_ratio'); } return $mid ? $config[$mid] : $config; } /** * 设置订单附加信息数据提交 * @param $request */ public function setOrderInfo($request, $is_local = 0) { $data['app_id'] = $this->merchant['app_key'];//app_id $data['prodcut_name'] = $request->input('title', '商品购买');//保持请求过来的产品标题 $data['notify_url'] = $request->input('notify_url'); $data['return_url'] = $request->input('return_url'); $data['username'] = $request->input('username', ''); $data['local_user_id'] = $this->user['id']; $data['out_user_id'] = $request->input('user_id'); $data['money'] = $request->input('money');//订单金额 $data['from_url'] = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : request()->getUri(); $data['from_ip'] = $request->getClientIp(); $data['sign'] = $request->input('sign');//签名 $data['attach'] = $request->input('attach', '');//附加信息,原样返回 $data['gateway_name'] = $this->gateway['name'];//通道名字 $this->addOrderInfoData($data); $this->setMerchantData($is_local); } /** * s设置是否本站或者是API提交 * @param $is_local */ public function setMerchantData($is_local) { if ($is_local) { $data['merchant_id'] = '0'; $data['merchant_name'] = '本站'; } else { $data['merchant_id'] = $this->merchant->id; $data['merchant_name'] = $this->merchant->name; } $this->addOrderData($data); $this->addOrderInfoData($data); } /** * 订单提交数据增加 * @param $data * @return array */ public function addOrderData($data) { return self::$orderData = $data + self::$orderData; } /** * 创建会员 * @param $request */ public function createUser($request) { $user_data = [ 'nickname' => $request->input('username'), 'from_user_id' => $request->input('user_id'), 'merchant_id' => $this->merchant->id, 'from_ip' => $request->getClientIp(), 'mobile' => $request->input('mobile', ''), ]; //创建会员 $this->user = User::getOrCreate($user_data, ['from_user_id' => $request->input('user_id')]); } /** * 订单附加信息数据增加 * @param $data * @return array */ public function addOrderInfoData($data) { return self::$orderInfoData = $data + self::$orderInfoData; } /** * 发起支付 * @param $data 支付数据内容 * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function paySend($data,$order='') { if (in_array($this->pay_method, ['web', 'wap', 'app'])) { $this->debugLog('发送的支付'); return $this->pay_service->pay($data,$order); } elseif ($this->pay_method == 'scan') { $this->debugLog('发送扫码支付'); $pay_data=$data; if(in_array($this->pay_type,['weixin','weixinscan','weixinh5'])){ unset($pay_data['created_at']); } $r = $this->pay_service->pay($pay_data,$order); return $this->scan($r); } } //扫码支付 public function scan($r) { if(in_array($this->pay_type,['weixin','weixinscan','weixinh5'])){ $r->qr_code=$r->code_url; } $data = [ 'url' => $r->qr_code, 'order' => $this->order, 'type_name' => config('adconfig.pay_type')[$this->order->pay_type] ]; return view('web.order.scan', $data); } /** * 订单创建 * @return bool|int */ public function createOrder() { DB::beginTransaction(); $order = new Order(); foreach (self::$orderData as $k => $v) { $order->$k = $v; } $r = $order->save(); $info_data = self::$orderInfoData; $info_data['order_id'] = $order->id; $info_r = $this->orderInfoInsert($info_data); if ($r && $info_r) { $this->order = $order; $this->debugLog('订单创建成功---' . $order->id . '---订单号:' . $order->order_sn); DB::commit(); return 1; } else { DB::rollBack(); return false; } } /** * 附加信息创建 * @param $data * @return mixed */ public function orderInfoInsert($data) { $order_info = new OrderInfo(); return $order_info->insert($data); } /** 设置当前请求的支付类型的方法到类属性里面 * @param $request */ public function setPayMethod($request) { $pay_type = $request->input('pay_type'); $pay_config = $this->payMethod($pay_type); $this->pay_type = $pay_config['pay_type']; $this->pay_method = $pay_config['method']; } /** * 错误格式输出 * @return array */ public function errorFormat() { $html_str = ''; foreach (self::$errorArr as $k => $v) { $html_str = $v['msg'] . " "; } return ['error' => 1, 'msg' => $html_str]; } /** * 验证签名问题 * @param $merchant * @param $request */ public function checkSign($merchant, $request) { $sign_data = [ 'token' => $merchant->token, 'app_id' => $merchant->app_key, 'money' => $request->input('money'), 'return_url' => $request->input('return_url'), 'notify_url' => $request->input('notify_url'), 'out_trade_sn' => $request->input('out_trade_sn') ]; if (!PayServiceFacades::checkSign($sign_data, $request->input('sign'))) { $this->debugLog('签名错误' . json_encode($sign_data).$request->input('sign')); $this->addError(['error' => 1, 'msg' => '签名错误']); } } public function msg($data) { if(!isset($data['code'])){ $data['code'] = 0; } //临时测试一下看看是否可行 return response()->json($data); if (request()->ajax()) { return response()->json($data); } return $this->htmlAlert($data); } public function htmlAlert($data) { echo ''; } /*****************************回调处理部分****************************************/ /** * 支付提交的结果写入到静态数组里面 * @param $arr * @return bool */ public function setResult($arr) { if (count($arr) < 0) { return false; } foreach ($arr as $k => $v) { self::$result[$k] = $v; } } /* * 本地订单回调 * 写入支付日志 * 写入风控记录表 * 佣金计算 */ public function locationOrder() { $order = $this->order; //订单已经支付成功,直接success if ($order->pay_status == 1) { return $this->success();; } else { //支付日志写入 $this->addPayLog(); //风控 $this->gategoryWind(); } //佣金计算 $this->pateMoney(); $order->pay_order_sn = self::$result['pay_order_sn'];//支付流水号 //更新支付状态,支付订单,回调状态 $order->status = 1;//交易完成 $order->notify_status = 1;//支付回调成功 $order->out_notify_status = 1;//外站回调成功 if ($order->save()) { $this->debugLog('--------END---------------' . $this->order->order_sn . '-本地订单交易更新完成------------------------'); } else { $this->debugLog('--------END---------------' . $this->order->order_sn . '-本地订单交易更新失败------------------------'); } } /** * 外站订单更新处理 * 原样返回obj */ public function outOrder() { $order = $this->order; $result = self::$result; //如果已经支付,且外站已经回调,返回给支付宝success if ($order->pay_status == 1 && $order->out_notify_status == 1) { $this->debugLog('订单已经支付,外站已经回调,更新完毕交易成功,'); return $this->success(); } else { //如果订单还没有更新支付状态,写入风控,写入支付日志 if ($order->pay_status == 0) { //风控 $this->gategoryWind(); $order->pay_order_sn = $result['pay_order_sn'];//支付流水号 //开始更新订单数据 $order->pay_money = $result['pay_money'];//支付金额 $order->ewm_name = $result['ewm_name'];//支付账号姓名 $order->notify_status = 1;//支付回调成功 $order->pay_status = 1;//支付成功 $order->status = 2;//2=>已支付,待外站回调 $order->pay_ok_at = date('Y-m-d H:i:s');//支付完成时间 $this->debugLog('佣金计算开始'); //佣金计算 try { $this->pateMoney(); } catch (\Exception $exception) { $this->debugLog('佣金计算完成' . $exception->getMessage()); } try { //支付日志写入 $this->addPayLog(); } catch (\Exception $e) { $this->debugLog('支付日志写入失败' . $exception->getMessage()); } $this->debugLog('佣金计算完成'); if ($this->order->save()) { //外站是否回调 if ($order->merchant_id != 0) { if ($this->updateOutNotify() == true) { $this->debugLog('异步回调成功'); return $this->success();; } else { $this->debugLog('订单更新成功,但异步回调失败' . date('H:i:s')); return false; } } else { $this->debugLog('订单更新成功'); return $this->success();; } } $this->debugLog('无法完成订单更新失败' . date('H:i:s')); } else { //已经支付,但没有回调成功,发起异步回调 //异步回调是否成功 $this->debugLog('已支付,但没有异步回调成功,现在发起异步回调'); if ($this->updateOutNotify() == true) { $this->debugLog('已支付,外站异步回调成功'); $this->debugLog('--------END---------------' . $this->order->order_sn . '-处理完成------------------------'); return $this->success(); } else { $this->debugLog('已支付,订单更新成功,但外站异步回调失败'); $this->debugLog('---------END---------' . $this->order->order_sn . '-但外站异步回调失败------------------------'); return $order; } } } } //更新外站异步回调 public function updateOutNotify() { $order = $this->order; //取得订单信息 $order_info = OrderInfo::where('order_id', $this->order->id)->first(); $notify_url = $order_info->notify_url; //发送回调 //发送签名过去,组装信息 $notify_data = $this->backParam($order_info); //资金变动写入 $this->addMerchantMoneyLog($order->total_money); $this->debugLog('发送异步数据', $notify_data); //发送curl $r = Curl::to($notify_url)->withData($notify_data)->post(); $this->debugLog('回调返回内容', $r); //返回success表示回调成功,成功之后,更新订单状态=1,外站回调状态1 if ($r === 'success') { //更新订单状态 $order->out_notify_status = 1; $order->status = 1;//更新订单状态 $or = $order->save(); //更新订单附加信息 $order_info->notify_data = json_encode($notify_data); $order_info->notify_status = 'success'; $of_r = $order_info->save(); if ($of_r && $or) { $this->debugLog('异步回调发送成功'); return true; } return false; } else { //记录失败 $this->debugLog('回调失败,订单是.' . $this->order->order_sn); return false; } } //资金变动交易写入 public function addMerchantMoneyLog($money) { $this->debugLog($this->order->order_sn . '资金变动交易写入结算金额:' . $money); DB::beginTransaction(); $r = MerchantMoneyLog::addMoney($this->order, $money); //如果商户资金变动成功,插入商户钱包 if ($r) { $u_r=$this->addMerchantWallet(self::$result['pay_money'], $money); if($u_r) { DB::commit(); }else{ DB::rollBack(); } }else { //释放 DB::rollBack(); } } //商户钱包写入 public function addMerchantWallet($trans_money, $money) { $this->debugLog('写入商户钱包成功:', $money); return MerchantWallet::addWallte($this->order->merchant_id, $trans_money, $money); } //只有1级的时候,没有上级的佣金计算 /** * 没有上级的费率计算 * 入库系统佣金 * @param $result * @return mixed */ public function levelPateTop($result) { $merchant = $this->merchant; $order = $this->order; //支付金额和支付接口商返回金额一致时,设置系统佣金计算参数 //推广佣金写入 //平台扣除费用,手续费含通道成本 $ysytem_pate = ($result['pay_money'] * $order->ratio) / 1000; $this->debugLog('没有上级,本次平台订单佣金是:' . $ysytem_pate); //结算金额=支付金额-手续费 $order->total_money = $result['pay_money'] - $ysytem_pate; $order->pay_rate = $ysytem_pate;//手续费 $gateway_money = $order->gateway_money; $gateway_ratio = $order->gateway_ratio;//通道费率 $final_money = $order->final_money;//最后盈利。 $final_ratio = $order->final_ratio;//最后盈利点数 //如果发生支付金额对不上提交支付金额,重新计算费率这些 if ($result['pay_money'] != $order->order_money) { //订单金额更新为支付金额 $order->order_money = $result['pay_money'];//支付金额 //系统扣点=支付金额 * 商户费率+上浮费率 。$order->ratio=商户费率+上浮费率 $ysytem_pate = ($result['pay_money'] * $order->ratio) / 1000;//佣金手续费 $this->debugLog('没有上级,重新计算本次平台订单佣金是:' . $ysytem_pate); //结算金额=支付金额-手续费 $order->total_money = $result['pay_money'] - $ysytem_pate; $order->pay_rate = $ysytem_pate;//手续费 //通道成本=通道费率*支付金额/1000,单位都是千 $gateway_money = $order->gateway_money = ($this->gateway['ratio'] * $result['pay_money']) / 1000; $gateway_ratio = $order->gateway_ratio = $this->gateway['ratio'];//通道费率 //最后盈利=手续费-通道成本 $final_money = $order->final_money = $ysytem_pate - $gateway_money;// $final_ratio = $order->final_ratio = $order->ratio - $gateway_ratio;//最后盈利点数 } //平台佣金写入 $sys_data = [ 'merchant_id' => $order->merchant_id, 'gateway_id' => $this->gateway_id, 'order_id' => $order->id, 'order_sn' => $order->order_sn, 'order_money' => $order->order_money, 'pay_money' => $result['pay_money'], 'payfor_money' => $order->total_money, 'money' => $ysytem_pate, 'ratio' => $order->system_ratio,//系统佣金比率 'name' => $merchant->name . '的订单佣金', 'order_at' => $order->order_at, 'pay_ok_at' => $order->pay_ok_at, 'gateway_money' => $gateway_money,//通道扣除费用金额 'gateway_ratio' => $gateway_ratio,//通道扣点 'final_money' => $final_money,//最后盈利金额 'final_ratio' => $final_ratio,//最后盈利扣点 'status' => '1', ]; $this->debugLog('写入平台佣金:', $sys_data); $this->systemCommission($sys_data);//平台佣金 return $order; } /** * 存在上级的费率计算,包括股东,代理 * @param $result */ public function levelPateOther($result) { $merchant = $this->merchant; $order = $this->order; $tui_pate = 0; $tui_ratio = 0; $is_only_system = 0; //判断商户是否是有上级,如果有,需要给推广上级增加佣金 //取得对应的费率关系 $merchant_ratio_info = $this->getRatioInfo($this->merchant->id); //如果这个数组不存在,直接跳过写入佣金,直接写入平台佣金 if (empty($merchant_ratio_info)) { $is_only_system == 1; } //平台手续费含通道成本,没有上级就是商户的扣点计算,有上级按上级的计算扣点 $ysytem_pate = $this->order->pay_rate;//手续费 //代理利润费 $dali_pate = $order->next_money; //代理利润费率=(商户费率 ) - 代理费率 $dali_ratio = $order->next_ratio; //股东利润 $gudong_pate = $order->top_money; //股东利润费率 $gudong_ratio = $order->top_ratio; //通道扣费金额 $gateway_money = $order->gateway_money; //通道费率 $gateway_ratio = $order->gateway_ratio;//通道费率 $final_money = $order->final_money;//最后盈利。 $final_ratio = $order->final_ratio;//最后盈利点数 //如果发生支付金额对不上,需要重新计算 if ($result['pay_money'] != $order->order_money) { //金额对不上,需要修改:手续费,代理/股东佣金,通道成本,最后盈利 //修改原来支付的订单金额 $order->order_money = $ysytem_pate = $result['pay_money'];//支付金额 $this->debugLog('重新计算平台佣金手续费:' . $ysytem_pate); $money = $result['pay_money']; //通道成本 $gateway_money = $order->gateway_money = $money * $order->gateway_ratio / 1000; //最后盈利=(平台费率 - 通道费率)* 金额 /1000,(平台费率-通道费率) *金额 /1000 $final_money = $order->final_money = $order->final_ratio * $money / 1000; //手续费 $ysytem_pate = $order->pay_rate = $order->system_ratio * $money / 1000; //判断商户的上级是啥身份 if ($merchant_ratio_info['up_level'] == 1) { //股东身份 //股东盈利重写 $gudong_pate = $order->top_money = $money * $order->top_ratio / 1000; //系统扣点费用=股东费率+上浮费率*金额/100 //重写手续费:含通达成本 //股东-》商户,上下和顶级都是股东, $dali_pate = $order->next_money = $gudong_pate; } elseif ($merchant_ratio_info['up_level'] == 2) { //判断股东是否存在 if ($merchant_ratio_info['up_level']['top_id'] != 0) { $gudong_pate = $order->top_money = $money * $order->top_ratio / 1000; $dali_pate = $order->next_money = $money * $order->next_ratio / 1000;; } else { //只有代理和商户关系,股东费率为0,股份金钱0 $gudong_pate = $order->top_money = 0; $dali_pate = $order->next_money = $money * $order->next_ratio / 1000;; } //代理-》股东 //股东盈利重写=金额*股东盈利费率 } } //写入平台佣金 $sys_data = [ 'merchant_id' => $order->merchant_id, 'gateway_id' => $this->gateway_id, 'order_id' => $order->id, 'order_sn' => $order->order_sn, 'order_money' => $order->order_money, 'pay_money' => $result['pay_money'], 'payfor_money' => $order->total_money, 'money' => $ysytem_pate, 'ratio' => $order->system_ratio,//系统佣金比率 'name' => $merchant->name . '的订单佣金', 'order_at' => $order->order_at, 'pay_ok_at' => $order->pay_ok_at, 'gateway_money' => $gateway_money,//通道扣除费用金额 'gateway_ratio' => $gateway_ratio,//通道扣点 'final_money' => $final_money,//最后盈利金额 'final_ratio' => $final_ratio,//最后盈利扣点 'status' => '1', ]; $this->debugLog('写入平台佣金:', $sys_data); $this->systemCommission($sys_data);//平台佣金 $this->debugLog('写入平台佣金完成' . $is_only_system); if ($is_only_system == 0) { $this->debugLog('进入商户佣金计算'); //判断这个商户上级是股东还是代理,如果是股东,只有2级关系,其他3级 if ($merchant_ratio_info['up_level'] == 1) { $this->debugLog('使用股东de'); //使用股东de $tui_pate = $gudong_pate; $tui_ratio = $gudong_ratio; //大股东下de商户,增加一条佣金记录 //推广上级佣金写入 $merchant_data = [ 'merchant_id' => $order->merchant_id, 'from_merchant_id' => $merchant->from_id, 'gateway_id' => $this->gateway_id, 'order_id' => $order->id, 'order_sn' => $order->order_sn, 'order_money' => $order->order_money,//订单金额 'pay_money' => $result['pay_money'], 'money' => $tui_pate,//获得佣金 'ratio' => $tui_ratio,//利润返点 'name' => $merchant->name . '的订单佣金', 'order_at' => $order->order_at, 'pay_ok_at' => $order->pay_ok_at, 'status' => '2',//佣金状态,改为处理中,结算时是按后台结算 ]; $this->merchantCommission($merchant_data, $merchant->from_id);//商户佣金写入 $this->debugLog($merchant_ratio_info['up_level_name'] . '佣金写入完成'); } elseif ($merchant_ratio_info['up_level'] == 2) { //代理,股东部分 $this->debugLog('代理,股东部分'); //代理佣金 $daili_merchant_data = [ 'merchant_id' => $order->merchant_id, 'from_merchant_id' => $merchant->from_id,//代理ID 'gateway_id' => $this->gateway_id, 'order_id' => $order->id, 'order_sn' => $order->order_sn, 'order_money' => $order->order_money,//订单金额 'pay_money' => $result['pay_money'], 'money' => $dali_pate,//获得佣金 'ratio' => $dali_ratio,//利润返点 'name' => $merchant->name . '的订单佣金', 'order_at' => $order->order_at, 'pay_ok_at' => $order->pay_ok_at, 'status' => '2',//佣金状态,改为处理中,结算时是按后台结算 ]; $this->merchantCommission($daili_merchant_data, $merchant->from_id);//代理佣金写入 $this->debugLog('代理佣金写入ok'); //判断顶级股东是否存在,如果存在才给,不存在则还是2级 if ($merchant_ratio_info['top_id'] != 0) { $this->debugLog('股东佣金'); //股东佣金 $gudong_merchant_data = [ 'merchant_id' => $order->merchant_id, 'from_merchant_id' => $merchant_ratio_info['top_id'],//股东deID 'gateway_id' => $this->gateway_id, 'order_id' => $order->id, 'order_sn' => $order->order_sn, 'order_money' => $order->order_money,//订单金额 'pay_money' => $result['pay_money'], 'money' => $gudong_pate,//获得佣金 'ratio' => $gudong_ratio,//利润返点 'name' => $merchant->name . '的订单佣金', 'order_at' => $order->order_at, 'pay_ok_at' => $order->pay_ok_at, 'status' => '2',//佣金状态,改为处理中,结算时是按后台结算 ]; $this->debugLog($merchant_ratio_info['up_level_name'] . '股东佣金写入完成'); $this->merchantCommission($gudong_merchant_data, $merchant_ratio_info['top_id']);//股东佣金写入 } } } } //推广商户佣金写入 public function merchantCommission($data, $mid) { return MerchantCommission::getOrCreate($data, ['order_id' => $this->order->id, 'merchant_id' => $mid]); } //系统佣金写入 public function systemCommission($data) { return SystemCommission::getOrCreate($data, ['order_id' => $this->order->id]); } public function addSystemCommisArr($data) { return self::$errorArr = self::$errorArr + $data;//加入错误数组 } //佣金计算 public function pateMoney() { $order = $this->order; $result = self::$result; //本地站 if ($order->merchant_id == 0) { //佣金手续费=支付金额*支付比率比例(单位为1000的) $pate = ($result['pay_money'] * $order->ratio) / 1000;//佣金手续费 $this->debugLog('本地站订单,支付手续费是:' . $pate); $order->total_money = $result['pay_money'] - $pate;//结算金额=支付金额-手续费 $order->pay_rate = $pate;//手续费 return $order; } else { //外站处理 //判断商户是否是有上级,如果有,需要给推广上级增加佣金 $merchant = $this->merchant; //存在上级 if ($merchant->from_id != 0) { return $this->levelPateOther($result); } //没有上级情况下 return $this->levelPateTop($result); } } //支付风控写入 public function gategoryWind() { $gateway_id = $this->gateway_id;// getOrder获得gateway_id $money = self::$result['pay_money']; //风控 $obj = new GatewayWind(); $has = GatewayWind::where(['gateway_id' => $gateway_id, 'day' => date('Y-m-d')])->lockForUpdate()->first(); if ($has) { $this->debugLog('风控开始更新金额:' . $money); $now_money = $money + $has->amount_total; $has->increment('amount_total', $money);//增加金额 //判断金额是否大于最大的限额,如果是,则更新通道并且关闭 if ($now_money >= $has->max_total) { //更新通道为关闭,并且时系统设置 Gateway::where('id', $gateway_id)->update(['is_checked' => 0, 'is_system_close' => 1]); write_gateway();//写入文件 } $this->debugLog('风控完成更新金额:' . $money); } else { $this->debugLog('风控开始写入:' . $money); $obj->day = date('Y-m-d'); $obj->gateway_name = $this->pay_gateway['name'] . '(' . $this->pay_gateway['mch_id'] . ')';//通道 $obj->amount_total = $money; $obj->gateway_id = $this->gateway_id; $obj->save(); $this->debugLog('风控完成写入成功'); } } //支付日志 public function addPayLog() { $data = $this->payLogData(); $pay_order_sn = $data['pay_order_sn']; $this->debugLog('支付日志写入数据是', $data); $has = PayLog::where('pay_order_sn', $pay_order_sn)->count(); if (!$has) { PayLog::insert($data); } } /** * 支付日志参数 * @return array */ public function payLogData() { $result = self::$result; $pay_log_data = [ 'pay_order_sn' => $result['pay_order_sn'], 'pay_status' => 1, 'order_sn' => $result['order_sn'], 'pay_money' => $result['pay_money'], 'pay_type' => $result['pay_type'], 'data' => is_array($this->pay_data) ? json_encode($this->pay_data) : json_encode($this->pay_data->toArray()), 'created_at' => date('Y-m-d H:i:s') ]; return $pay_log_data; } /** * 同步回调给商户 * @return \Illuminate\Http\RedirectResponse */ public function merchantReturnSend() { //取得订单信息 $order_info = OrderInfo::where('order_id', $this->order->id)->first(); //发送回调 //发送签名过去,组装信息 $notify_data = $this->backParam($order_info); $notify_data['pay_order_sn'] = $this->order->pay_order_sn; //取得订单附加信息,然后回调到第三方 $url = $this->order->infos['return_url']; if ($url) { return redirect()->away(arr_to_url($url, $notify_data)); } } /** * 返回数据的签名参数 */ public function backParam($order_info, $is_return = 0) { $order = $this->order; //商户信息 $merchant = get_merchant($order_info->app_id);//取得商户 $notify_data = [ 'pay_money' => $order->pay_money, 'money' => $order->order_money, 'order_sn' => $order->order_sn, 'out_trade_sn' => $order->out_trade_sn, 'pay_order_sn' => isset(self::$result['pay_order_sn']) ? self::$result['pay_order_sn'] : $order->pay_order_sn, 'sign' => md5($merchant['token'] . $order_info->sign . 'pay_money=' . $order->pay_money . 'pay_status=' . $order->pay_status), // 'attach' => $order_info->attach, 'attch' => $order_info->attach, 'pay_status' => $order->pay_status, 'return_url' => $order_info->return_url, 'notify_url' => $order_info->notify_url ]; return $notify_data; } public function getGatewayInfo($gateway_id, $pay_method) { $this->pay_method = $pay_method; $this->pay_gateway=$this->gateway = config('gateway.config')[$gateway_id]; return $this->pay_gateway; } public function gatewayHas(){ dd(3333); } public function beforeCreateOrder(&$orderData,&$orderInfo){ return true; } }