sifangpay/app/ServicePay/PayTrait.php

1413 lines
52 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace App\ServicePay;
use App\Models\Gateway;
use App\Models\GatewayWind;
use App\Models\Merchant;
use App\Models\MerchantCommission;
use App\Models\MerchantMoneyLog;
use App\Models\MerchantWallet;
use App\Models\Order;
use App\Models\OrderInfo;
use App\Models\PayLog;
use App\Models\SystemCommission;
use App\Models\User;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use App\Facades\PayServiceFacades;
use Ixudra\Curl\Facades\Curl;
trait PayTrait
{
use PayApiProvidesTrait;
public static $errorArr = [];
/**
* @var $pay_service PayApiInterface
*/
public $pay_service;//选择支付接口商的服务类
public $gateway;//当前支付的通道信息内容
public $pay_type;//支付类型weixin,alipay
public $pay_method;//scan 扫码wap,移动支付web电脑支付
public $order_sn;//订单编号
public $merchant;//商户信息
public $order;//订单信息
public $log_name;
public static $systemCommisArr = [];//系统佣金插入数组
public $user = [
'username' => '',
'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)
{
//临时测试一下看看是否可行
return response()->json($data);
if (request()->ajax()) {
return response()->json($data);
}
return $this->htmlAlert($data);
}
public function htmlAlert($data)
{
echo '<script>alert("' . $data['msg'] . '");window.history.back()</script>';
}
/*****************************回调处理部分****************************************/
/**
* 支付提交的结果写入到静态数组里面
* @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;
}
}