From 53fc2d2ff2609a185391789aa22fd7e4210112a4 Mon Sep 17 00:00:00 2001 From: zcy Date: Wed, 14 Jul 2021 13:49:18 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E6=94=AF=E4=BB=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 3 + .../Controllers/Admin/GatewayController.php | 42 ++ .../Controllers/Admin/HandleController.php | 52 +++ .../Controllers/Admin/OrderController.php | 5 +- app/ServicePay/CengJingServices.php | 351 +++++++++++++++++ app/ServicePay/DaliPayServices.php | 363 +++++++++++++++++ app/ServicePay/KoulinghbPayServices.php | 366 +++++++++++++++++ app/ServicePay/PayApiProvidesTrait.php | 8 + app/ServicePay/PayTrait.php | 44 ++- app/ServicePay/PingguopayServices.php | 358 +++++++++++++++++ app/ServicePay/YiHuiBaoPayServices.php | 371 ++++++++++++++++++ app/Services/SearchServices.php | 12 + config/adconfig.php | 4 + config/qrcodeurl.php | 10 +- config/whitelist.php | 10 + .../views/admin/gateway/create.blade.php | 2 +- resources/views/admin/gateway/edit.blade.php | 2 +- resources/views/admin/gateway/index.blade.php | 4 +- .../views/admin/gateway/statics.blade.php | 80 ++++ resources/views/admin/layouts/side.blade.php | 1 + resources/views/admin/order/index.blade.php | 15 + resources/views/admin/zhanxin/edit.blade.php | 2 +- routes/admin.php | 2 + routes/web.php | 10 +- 24 files changed, 2087 insertions(+), 30 deletions(-) create mode 100644 app/ServicePay/CengJingServices.php create mode 100644 app/ServicePay/DaliPayServices.php create mode 100644 app/ServicePay/KoulinghbPayServices.php create mode 100644 app/ServicePay/PingguopayServices.php create mode 100644 app/ServicePay/YiHuiBaoPayServices.php create mode 100644 resources/views/admin/gateway/statics.blade.php diff --git a/.env.example b/.env.example index ec44a12..0082503 100644 --- a/.env.example +++ b/.env.example @@ -6,6 +6,9 @@ APP_URL=http://localhost LOG_CHANNEL=stack +NOTIFY_URL=http://test.local.com +BASE_URL=http://test.local.com + DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 diff --git a/app/Http/Controllers/Admin/GatewayController.php b/app/Http/Controllers/Admin/GatewayController.php index a6577df..ac25108 100644 --- a/app/Http/Controllers/Admin/GatewayController.php +++ b/app/Http/Controllers/Admin/GatewayController.php @@ -4,8 +4,10 @@ namespace App\Http\Controllers\Admin; use App\Models\Bank; use App\Models\Gateway; +use App\Services\DateServices; use Illuminate\Http\Request; use App\Http\Controllers\Controller; +use Illuminate\Support\Facades\DB; class GatewayController extends BaseDefaultController { @@ -71,6 +73,46 @@ class GatewayController extends BaseDefaultController } + public function statics(){ + + $this->title='通道统计'; + // dump($config); + $this->setTitle(); + return $this->display([]); + } + + public function statics_data(){ + + $requestData = request()->all(); + if (isset($requestData['timeday'])) { + $time = str_replace('~', ',', $requestData['timeday']); + + $time = explode(",", $time); + + $date['start_at'] = $time[0] ?? ''; + $date['end_at'] = $time[1] ?? ''; + } else { + $date = DateServices::today(); + } + + if (empty($date['start_at']) || empty($date['end_at'])) { + $date = DateServices::today(); + } + + $data = DB::select("select t.gateway_id,t.total,t.created_at ,t.order_money,g.`name`, + (select sum(p.order_money) from orders p where p.gateway_id=t.gateway_id and pay_status='1' and p.created_at>='" . $date['start_at'] . "' and p.created_at <='" . $date['end_at'] . "') as ok_money, + (select count(p.pay_status) from orders p where p.gateway_id=t.gateway_id and pay_status='1'and p.created_at>='" . $date['start_at'] . "' and p.created_at <='" . $date['end_at'] . "') as ok_total + from (select count(pay_status) as total,sum(order_money)as order_money,gateway_id,created_at from orders where created_at>='" . $date['start_at'] . "' and created_at <='" . $date['end_at'] . "' group by gateway_id) t JOIN gateways g ON t.gateway_id=g.id + ORDER BY order_money desc"); + $json = [ + "status"=>1, + 'code'=>count($data)>0?0:1, + 'msg'=>count($data)>0?'请求数据成功':'暂无数据', + 'count' => count($data), + 'data' => $data + ]; + return response()->json($json); + } public function setModel() { diff --git a/app/Http/Controllers/Admin/HandleController.php b/app/Http/Controllers/Admin/HandleController.php index 493bd9f..de79e56 100644 --- a/app/Http/Controllers/Admin/HandleController.php +++ b/app/Http/Controllers/Admin/HandleController.php @@ -5,6 +5,7 @@ namespace App\Http\Controllers\Admin; use App\Events\CouponCardEvent; use App\Models\CouponCard; use App\Models\Scenic; +use App\Models\UploadQrcode; use Illuminate\Http\Request; use App\Http\Controllers\Controller; use DB; @@ -124,6 +125,8 @@ class HandleController extends BaseController ]; return response()->json($data); } + + $id_arr = explode(",", $id); if (count($id_arr) <= 0) { $data = [ @@ -159,6 +162,22 @@ class HandleController extends BaseController 'type' => 'del' ]; + + if ($table == 'upload_qrcodes') { + $where[] = [function ($query) use ($id_arr) { + $query->whereIn('id', $id_arr); + }]; + $res = DB::table($table)->where($where)->get(['id', 'uid']); + $uidArr = []; + foreach ($res as $r) { + $uidArr[] = $r->uid; + } + $uidArr = array_unique($uidArr); + Log::channel('zhanxin')->info('删除请求数据', $uidArr); + foreach ($uidArr as $r) { + $this->delUid($r); + } + } return response()->json($data); } DB::rollBack(); @@ -203,4 +222,37 @@ class HandleController extends BaseController break; } } + + private function delUid($uid){ + $ts = time(); + $chanxinconfig = config('qrcodeurl.zhanxin'); + $data['userid'] = $uid; + $data['ts'] = strval($ts); + $str = 'uid=' . $uid . '&ts=' . $ts . '&' . $chanxinconfig['secret']; + Log::channel('zhanxin')->info('删除请求' . $str, []); + $data['key'] = strtolower(md5($str)); + Log::channel('zhanxin')->info('删除请求数据', $data); + $url = $chanxinconfig['baseurl'] . $chanxinconfig['del']; + $data = (is_array($data)) ? json_encode($data, JSON_UNESCAPED_UNICODE) : $data; + $curl = curl_init(); + $headerArray = array("Content-type:application/json;charset='utf-8'", "Accept:application/json"); + curl_setopt_array($curl, array( + CURLOPT_URL => $url, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_ENCODING => '', + CURLOPT_MAXREDIRS => 10, + CURLOPT_TIMEOUT => 0, + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, + CURLOPT_CUSTOMREQUEST => 'DELETE', + CURLOPT_HTTPHEADER => $headerArray, + )); + curl_setopt($curl, CURLOPT_POSTFIELDS, $data); + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); + $response = curl_exec($curl); + curl_close($curl); + Log::channel('zhanxin')->info('删除返回数据' . $response, is_array($response) ? $response : []); + return $response; + } } diff --git a/app/Http/Controllers/Admin/OrderController.php b/app/Http/Controllers/Admin/OrderController.php index ce55e08..bad92cf 100644 --- a/app/Http/Controllers/Admin/OrderController.php +++ b/app/Http/Controllers/Admin/OrderController.php @@ -108,9 +108,10 @@ class OrderController extends BaseDefaultController { $param['guma']=1; } + $search =(new SearchServices($this->setModel(),$param,$order_type)); - // $search->setTimeType('order'); - // dump($search->echoWhere()); + // $search->setTimeType('order'); +// dump($search->echoWhere()); $model=$search->getList(); $total = $model->count(); $result = $model->skip($offset)->with('users','merchants','gateways')->orderBy($order_id, $order_type_desc)->orderBy('id', 'desc')->take($pagesize)->get();; diff --git a/app/ServicePay/CengJingServices.php b/app/ServicePay/CengJingServices.php new file mode 100644 index 0000000..bbcd9a4 --- /dev/null +++ b/app/ServicePay/CengJingServices.php @@ -0,0 +1,351 @@ + $this->getGateUrl() . '/payment', + 'debug' => 1,//调试 + 'logDir' => to_linux_path(storage_path() . '/logs/'), + 'mch_id' => $this->pay_gateway['app_id'], //客户交易者账号 + 'token' => $this->pay_gateway['app_key'],//密钥 + 'interface' => $this->pay_gateway['mch_id'],//账号名称 一般用来存放三方通道 + 'return_url' => action('Pay\PayController@returnNotify', ['type' => $type]), + 'notify_url' => action('Pay\PayController@notify', ['type' => $type]), + ]; + $this->pay_config = $config; + } + + //统一下单支付 + + /** + * @param $pay_data + * @return array|\Illuminate\Http\RedirectResponse + */ + public function pay($pay_data) + { +// echo number_format( 500, 2,'.','');exit; + //商户号 + $accountId = $this->pay_config['mch_id']; + //商户秘钥 + $key = $this->pay_config['token']; + $payData = [ + 'merchant_code' => $accountId,//商户 + 'channel' => $this->pay_gateway['mch_id'],//对应的三方通道 + 'notify_url' => strval($this->pay_config['notify_url']),// //异步回调地址 + 'order_id' => strval($pay_data['out_trade_no']),//订单号 + 'amount' => $pay_data['total_amount'], //支付金额为元 + 'callback_url' => strval($this->pay_config['return_url']),//页面跳转通知 + ]; + $sign = $this->sign($payData, $key);//签名 + $payData['sign'] = $sign; + $res = Curl::to($this->pay_config['url'])->withData($payData)->post(); + var_dump($res); + $this->debugLog('下单接口请求内容' . json_encode($payData, true), []); + exit; + + return redirect()->away($this->pay_config['url'] . '?' . http_build_query($payData)); + } + + private function sign($tempArr, $signKey): string + { + $keyVal = ''; + + if (isset($tempArr['callback_url'])) { + unset($tempArr['callback_url']); + } + + $data = []; + foreach ($tempArr as $key => $value) { + array_push($data, "{$key}{$value}"); + } + $keyVal = implode('', $data); + + if (!empty($signKey) && is_string($signKey)) { + $keyVal .= $signKey; + } +// echo $keyVal;exit; + return md5($keyVal); + } + + /** + * 检查订单 + * @param $orderid + * @return bool|string + */ + private function checkOrder($orderid) + { + $url = $this->getGateUrl() . '/payment/orderStatus'; + $payData = [ + 'merchant_code' => $this->pay_gateway['app_id'],//商户号 + 'order_id' => $orderid, + ]; + $key = $this->pay_config['token']; + $payData['sign'] = $this->sign($payData, $key); + Log::channel('pay_order')->info('查询接口请求', $payData); + + $responseRaw = $this->ddcurl($url, $payData, false,'get'); + $response = is_array($responseRaw) ? $responseRaw : json_decode($responseRaw, 256); +// $this->debugLog('查询接口返回' . is_array($res) ? json_encode($res, true) : json_encode(json_decode($res, 256), true)); + Log::channel('pay_order')->info('查询接口返回', $response); + if (is_array($response) + && isset($response['code']) && $response['code'] == 'S-100' + && isset($response['order_id']) && $response['order_id'] == $orderid + && isset($response['status']) && $response['status']=='notified' + ) { + return true; + } + return false; + } + + + //统一验证签名 + public function verify() + { + $params = $this->result_data; + $signParam=[ + 'merchant_code'=>$params['merchant_code'], + 'status'=>$params['status'], + 'order_id'=>$params['order_id'], + 'amount'=>$params['amount'], + ]; + $md5sign = $this->sign($signParam, $this->pay_config['token']); + + if (isset($params['sign']) && $md5sign == $params['sign'] + && isset($params['status']) && in_array($params['status'], [1]) + ) { + return true; + } else { + return false; + } + } + + + //返回给支付商的成功 + public function success() + { + echo 'success'; + exit; + } + + //统一回调处理 + + /** + * 回调第一部,如果是同步,直接回传 + * @param $return + * @param $pay_type + * @param $request + * @return bool|\Illuminate\Http\RedirectResponse + */ + public function notify($return, $pay_type, $request) + { + $request = json_decode(file_get_contents('php://input'), true); + $this->setLogName($pay_type); + $this->debugLog('回调原始数据', $request); + $this->pay_type = $pay_type; + $this->request = $request; + //取得订单,是否有此订单,如果没有直接返回空 + $order_sn = $request['order_id']; + $status = $request['status']; + if ($status != 1) { + return '未支付成功'; + } + + $checkresult = $this->checkIP();//检查回调IP + if (!$checkresult) { + return 'ip 不合法'; + } + //取得订单 + $this->getOrder($order_sn); + + $return = ($return) ? 1 : 0; + if ($return) { + + //判断是否是商户id + if ($this->order->merchant_id == 0) { + return redirect()->route('web.user.index'); + } + // + return $this->merchantReturnSend(); + } + //取得通道id + $this->gateway = $this->pay_gateway = config('gateway.config')[$this->gateway_id]; + //dd($this->gateway); + //取得支付配置 + $this->payConfig($this->pay_type); + + $this->result_data = $request; + //检查三方的订单 + $checkorder = $this->checkOrder($order_sn); + if (!$checkorder) { + $this->debugLog('查询三方订单未支付成功'); + return '查询三方订单未支付成功'; + } + //dump($this->result_data); + //进行验证签名 + if (!$this->verify()) { + $this->debugLog('签名以及支付状态验证失败'); + return '签名以及支付状态验证失败'; + } + + return $this->payNotify(); + } + + + /** + * 同步回调 + * @return \Illuminate\Http\RedirectResponse + */ + public function returnPay() + { + //判断是否是商户id + if ($this->order->merchant_id == 0) { + return redirect()->route('web.user.index'); + } + // + return $this->merchantReturnSend(); + } + + //异步回调 + + /** + * 获得通道信息,取得支付配置模型,验证签名, + * @return bool|void + */ + private function payNotify() + { + //取得通道信息内容 + $data = $this->result_data; + $this->pay_data = $this->result_data; + //如果应答状态不是01/A6表示支付失败 + $this->debugLog(json_encode($data, true)); + $this->debugLog('-------------' . $this->order->order_sn . '--选择----' . $this->pay_type . '----' . $this->pay_method . '----开始回调处理-------------------------'); + if (empty($data)) { + return $this->debugLog('验证签名失败', $data); + } + try { + $pay_cn_name = ''; + //统一格式化 + $this->unionHandle($data); + //支付返回信息 + $this->pay_data = $data; + $this->debugLog('验证签名成功,数据', $data); + //更新订单 + $this->updateOrder(); + $this->debugLog('updateOrder Ok'); + + } catch (\Exception $exception) { + $this->debugLog('失败异常内容:' . $exception->getMessage()); + $this->order->notify_status = 1;//支付回调成功 + $this->order->pay_status = 1;//支付状态 + $this->order->pay_ok_at = date('Y-m-d H:i:s'); + $this->order->save();//保存 + Log::channel('pay_success')->info($pay_cn_name . '支付成功,但处理订单失败', ['data' => json_encode($data)]); + + } + + } + + /** + * 统一格式化 + */ + public function unionHandle($data) + { + $result = [ + 'order_sn' => $data['order_id'],//我方订单号 + 'pay_order_sn' => $data['order_id'],//三方的订单号 +// 'pay_money' => number_format($data['payamount'] / 100, 2, '.', ''), //支付金额, + 'pay_money' => $data['amount'], //支付金额, + 'pay_type' => $this->pay_type, + 'account' => '' + ]; + + $this->setResult($result); + Log::channel('pay_success')->info('支付成功', [ + 'pay_type' => $result['pay_type'], 'pay_money' => $result['pay_money'], + 'account' => $result['account'], 'order_sn' => $result['order_sn'], + 'pay_order_sn' => $result['pay_order_sn']]); + + } + + + /** + * 这个调试需要配置在config/logging.php + * @param $pay_type + */ + public function setLogName($pay_type) + { + $this->log_name = $pay_type; + } + + /** + * 模拟post提交 json数据 请求接口 + * @param string $url + * @param bool|true $https + * @param string $method + * @param string $param + * @return mixed + */ + private function ddcurl($url = '', $param = '', $https = true, $method = 'post') + { + $param = json_encode($param, 320); + $ch = curl_init($url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + + #判断是否为https请求 + if ($https === true) { + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); + } + #判断是否为post请求 + if ($method == 'post') { + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_POSTFIELDS, $param); + } + curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type:application/json')); + + $str = curl_exec($ch); + + curl_close($ch); + return $str; + } +} diff --git a/app/ServicePay/DaliPayServices.php b/app/ServicePay/DaliPayServices.php new file mode 100644 index 0000000..1c7fb04 --- /dev/null +++ b/app/ServicePay/DaliPayServices.php @@ -0,0 +1,363 @@ + $this->getGateUrl() . '/api/index', + 'debug' => 1,//调试 + 'logDir' => to_linux_path(storage_path() . '/logs/'), + 'mch_id' => $this->pay_gateway['app_id'], //客户交易者账号 + 'token' => $this->pay_gateway['app_key'],//密钥 + 'interface' => $this->pay_gateway['mch_id'],//账号名称 一般用来存放三方通道 + 'return_url' => action('Pay\PayController@returnNotify', ['type' => $type]), + 'notify_url' => action('Pay\PayController@notify', ['type' => $type]), + ]; + $this->pay_config = $config; + } + + //统一下单支付 + + /** + * @param $pay_data + * @return array|\Illuminate\Http\RedirectResponse + */ + public function pay($pay_data) + { +// echo number_format( 500, 2,'.','');exit; + //商户号 + $accountId = $this->pay_config['mch_id']; + //商户秘钥 + $key = $this->pay_config['token']; + $payData = [ + 'bid' => $accountId,//商户 + 'pay_type' => $this->pay_gateway['mch_id'],//对应的三方通道 + 'notify_url' => strval($this->pay_config['notify_url']),// //异步回调地址 + 'order_sn' => strval($pay_data['out_trade_no']),//订单号 + 'money' => $pay_data['total_amount'], //支付金额为元 + 'callback_url' => strval($this->pay_config['return_url']),//页面跳转通知 + ]; + $sign = $this->sign($payData, $key);//签名 + $payData['sign'] = $sign; + $res = Curl::to($this->pay_config['url'])->withData($payData)->post(); + $this->debugLog('下单接口请求内容' . json_encode($payData, true), []); + + $res = is_array($res) ? $res : json_decode($res, 256); + if (is_array($res) && isset($res['code']) && $res['code'] == 100) { + $data = $res['data']; + $url = $data['url']; + return redirect()->away($url); + } else { + $msg = $res['msg'] ?? '未知错误'; + return ['code' => 0, 'msg' => $msg]; + } + + } + + private function sign($tempArr, $signKey): string + { + $keyVal=''; + + if (isset($tempArr['sign'])) { + unset($tempArr['sign']); + } + + ksort($tempArr); + + $data = []; + foreach ($tempArr as $key=>$value) { + array_push($data, "{$key}={$value}"); + } + $keyVal = implode('&', $data); + + if (!empty($signKey) && is_string($signKey)) { + $keyVal .= $signKey; + } + + return strtolower(md5($keyVal)); + } + + /** + * 检查订单 + * @param $orderid + * @return bool|string + */ + private function checkOrder($orderid) + { + $url = $this->getGateUrl() . '/api/detail'; + $payData = [ + 'bid' => $this->pay_gateway['app_id'],//商户号 + 'order_sn' => $orderid, + ]; + $key = $this->pay_config['token']; + $sign=$this->sign($payData, $key); + $payData['sign'] = $sign; + Log::channel('pay_order')->info('查询接口请求', $payData); + $responseRaw = Curl::to($url)->withData($payData)->post(); +// $responseRaw = $this->ddcurl($url, $payData, false); + $response = is_array($responseRaw) ? $responseRaw : json_decode($responseRaw, 256); +// $this->debugLog('查询接口返回' . is_array($res) ? json_encode($res, true) : json_encode(json_decode($res, 256), true)); + Log::channel('pay_order')->info('查询接口返回', $response); + if (is_array($response) + && isset($response['code']) && $response['code'] == 100 + && isset($response['data']['order_sn']) && $response['data']['order_sn'] == $orderid + && isset($response['data']['pay_state']) && $response['data']['pay_state']==1 + && isset($response['data']['sign']) && $response['data']['sign']==$sign + ) { + return true; + } + return false; + } + + + //统一验证签名 + public function verify() + { + $params = $this->result_data; + + $md5sign = $this->sign($params, $this->pay_config['token']); + + if (isset($params['sign']) && $md5sign == $params['sign'] + && isset($params['pay_state']) && $params['pay_state'] ==1 + ) { + return true; + } else { + return false; + } + } + + + //返回给支付商的成功 + public function success() + { + echo 'success'; + exit; + } + + //统一回调处理 + + /** + * 回调第一部,如果是同步,直接回传 + * @param $return + * @param $pay_type + * @param $request + * @return bool|\Illuminate\Http\RedirectResponse + */ + public function notify($return, $pay_type, $request) + { +// $request = json_decode(file_get_contents('php://input'), true); + $allData = $request->all(); + $this->setLogName($pay_type); + $this->debugLog('回调原始数据', $allData); + $this->pay_type = $pay_type; + $this->request = $request; + //取得订单,是否有此订单,如果没有直接返回空 +// $order_sn = $request->input('order_sn'); + $order_sn = $allData['order_sn']; + + $status = $allData['pay_state']; +// $status = $request->input('pay_state'); + + if ($status != 1) { + return '未支付成功'; + } + + $checkresult = $this->checkIP();//检查回调IP + if (!$checkresult) { + return 'ip 不合法'; + } + //取得订单 + $this->getOrder($order_sn); + + $return = ($return) ? 1 : 0; + if ($return) { + + //判断是否是商户id + if ($this->order->merchant_id == 0) { + return redirect()->route('web.user.index'); + } + // + return $this->merchantReturnSend(); + } + //取得通道id + $this->gateway = $this->pay_gateway = config('gateway.config')[$this->gateway_id]; + //dd($this->gateway); + //取得支付配置 + $this->payConfig($this->pay_type); + + $this->result_data = $allData; + //检查三方的订单 + $checkorder = $this->checkOrder($order_sn); + if (!$checkorder) { + $this->debugLog('查询三方订单未支付成功'); + return '查询三方订单未支付成功'; + } + //dump($this->result_data); + //进行验证签名 + if (!$this->verify()) { + $this->debugLog('签名以及支付状态验证失败'); + return '签名以及支付状态验证失败'; + } + + return $this->payNotify(); + } + + + /** + * 同步回调 + * @return \Illuminate\Http\RedirectResponse + */ + public function returnPay() + { + //判断是否是商户id + if ($this->order->merchant_id == 0) { + return redirect()->route('web.user.index'); + } + // + return $this->merchantReturnSend(); + } + + //异步回调 + + /** + * 获得通道信息,取得支付配置模型,验证签名, + * @return bool|void + */ + private function payNotify() + { + //取得通道信息内容 + $data = $this->result_data; + $this->pay_data = $this->result_data; + //如果应答状态不是01/A6表示支付失败 + $this->debugLog(json_encode($data, true)); + $this->debugLog('-------------' . $this->order->order_sn . '--选择----' . $this->pay_type . '----' . $this->pay_method . '----开始回调处理-------------------------'); + if (empty($data)) { + return $this->debugLog('验证签名失败', $data); + } + try { + $pay_cn_name = ''; + //统一格式化 + $this->unionHandle($data); + //支付返回信息 + $this->pay_data = $data; + $this->debugLog('验证签名成功,数据', $data); + //更新订单 + $this->updateOrder(); + $this->debugLog('updateOrder Ok'); + + } catch (\Exception $exception) { + $this->debugLog('失败异常内容:' . $exception->getMessage()); + $this->order->notify_status = 1;//支付回调成功 + $this->order->pay_status = 1;//支付状态 + $this->order->pay_ok_at = date('Y-m-d H:i:s'); + $this->order->save();//保存 + Log::channel('pay_success')->info($pay_cn_name . '支付成功,但处理订单失败', ['data' => json_encode($data)]); + + } + + } + + /** + * 统一格式化 + */ + public function unionHandle($data) + { + $result = [ + 'order_sn' => $data['order_sn'],//我方订单号 + 'pay_order_sn' => $data['sys_order_sn'],//三方的订单号 +// 'pay_money' => number_format($data['payamount'] / 100, 2, '.', ''), //支付金额, + 'pay_money' => $data['pay_money'], //支付金额, + 'money' => $data['money'], + 'pay_type' => $this->pay_type, + 'account' => '' + ]; + + $this->setResult($result); + Log::channel('pay_success')->info('支付成功', [ + 'pay_type' => $result['pay_type'], 'pay_money' => $result['pay_money'], + 'account' => $result['money'], 'order_sn' => $result['order_sn'], + 'pay_order_sn' => $result['pay_order_sn']]); + + } + + + /** + * 这个调试需要配置在config/logging.php + * @param $pay_type + */ + public function setLogName($pay_type) + { + $this->log_name = $pay_type; + } + + /** + * 模拟post提交 json数据 请求接口 + * @param string $url + * @param bool|true $https + * @param string $method + * @param string $param + * @return mixed + */ + private function ddcurl($url = '', $param = '', $https = true, $method = 'post') + { + $param = json_encode($param, 320); + $ch = curl_init($url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + + #判断是否为https请求 + if ($https === true) { + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); + } + #判断是否为post请求 + if ($method == 'post') { + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_POSTFIELDS, $param); + } + curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type:application/json')); + + $str = curl_exec($ch); + + curl_close($ch); + return $str; + } +} + diff --git a/app/ServicePay/KoulinghbPayServices.php b/app/ServicePay/KoulinghbPayServices.php new file mode 100644 index 0000000..72e5c15 --- /dev/null +++ b/app/ServicePay/KoulinghbPayServices.php @@ -0,0 +1,366 @@ + $this->getGateUrl() . '/pay/Preorder/get', + 'debug' => 1,//调试 + 'logDir' => to_linux_path(storage_path() . '/logs/'), + 'mch_id' => $this->pay_gateway['app_id'], //客户交易者账号 + 'token' => $this->pay_gateway['app_key'],//密钥 + 'interface' => $this->pay_gateway['mch_id'],//账号名称 一般用来存放三方通道 + 'return_url' => action('Pay\PayController@returnNotify', ['type' => $type]), + 'notify_url' => action('Pay\PayController@notify', ['type' => $type]), + ]; + $this->pay_config = $config; + } + + //统一下单支付 + + /** + * @param $pay_data + * @return array|\Illuminate\Http\RedirectResponse + */ + public function pay($pay_data) + { +// echo number_format( 500, 2,'.','');exit; + //商户号 + $accountId = $this->pay_config['mch_id']; + //商户秘钥 + $key = $this->pay_config['token']; + $payData = [ + 'paytype' => $this->pay_gateway['mch_id'],//对应的三方通道 + 'amount' => intval($pay_data['total_amount'] * 100), //支付金额为分 + 'cpid' => $accountId,//商户 + 'orderid' => strval($pay_data['out_trade_no']),//订单号 + 'describe' => $pay_data['subject'], + 'product' => mt_rand(100000, 999999), //商品名称 + 'ip' => request()->getClientIp(), + 'synurl' => strval($this->pay_config['notify_url']),// //异步回调地址 + 'jumpurl' => strval($this->pay_config['return_url']),// //页面跳转通知 + ]; + $sign= $this->sign($payData,$key,['ip', 'jumpurl','paytype']); + $payData['sign'] = $sign; +// $res=$this->ddcurl($this->pay_config['url'],$pay_data,false); + $res = Curl::to($this->pay_config['url'])->withHeaders( array('Content-type'=>'application/json') )->withData($payData)->get(); + $this->debugLog('下单接口请求内容' . json_encode($payData, true), []); + $this->debugLog('返回内容' . json_encode($res, true), []); + + $res = is_array($res) ? $res : json_decode($res, 256); + if (is_array($res) && isset($res['status']) && $res['status'] == 0) { + $url = $res['payurl']; + return redirect()->away($url); + } else { + $msg = $res['msg'] ?? '未知错误'; + return ['code' => 0, 'msg' => $msg]; + } + + } + + private function sign($tempArr, $signKey,$filter=[]): string + { + $keyVal = ''; + + if (isset($tempArr['sign'])) { + unset($tempArr['sign']); + } + + ksort($tempArr); + + $data = []; + foreach ($tempArr as $key => $value) { + if(!in_array($key,$filter)){ + array_push($data, "{$value}"); + } + } + $keyVal = implode('|', $data); + + if (!empty($signKey) && is_string($signKey)) { + $keyVal .= '|'.$signKey; + } + + return strtolower(md5($keyVal)); + } + + /** + * 检查订单 + * @param $orderid + * @return bool|string + */ + private function checkOrder($orderid) + { + $url = $this->getGateUrl() . '/pay/Checkorder/check'; + $payData = [ + 'cpid' => $this->pay_gateway['app_id'],//商户号 + 'orderid' => $orderid, + ]; + $key = $this->pay_config['token']; + $sign = $this->sign($payData, $key); + $payData['sign'] = $sign; + Log::channel('pay_order')->info('查询接口请求', $payData); + $responseRaw = Curl::to($url)->withData($payData)->post(); +// $responseRaw = $this->ddcurl($url, $payData, false); + $response = is_array($responseRaw) ? $responseRaw : json_decode($responseRaw, 256); +// $this->debugLog('查询接口返回' . is_array($res) ? json_encode($res, true) : json_encode(json_decode($res, 256), true)); + Log::channel('pay_order')->info('查询接口返回', $response); + if (is_array($response) + && isset($response['status']) && $response['status'] == 0 + && isset($response['ispay']) && $response['ispay'] == 1 + ) { + return true; + } + return false; + } + + + //统一验证签名 + public function verify() + { + $params = $this->result_data; + //{"status": 0,"orderid": "1001_152490169760595","cpid": 1001,"amount": 100,"real_fee": 90,"paytime" + //: 1533887495,"ext": "123131","sign": "05685bc967a9c5c2c58ef0706056ccab"} + //(amount|cpid|ordered|paytime|key),例 + $key = $this->pay_config['token']; +// echo $params['amount'] . '|' . $params['cpid'] . '|' . $params['orderid'] . '|' . $params['paytime'] . '|' . $key;exit; +// $sign = strtolower(md5($params['amount'] . '|' . $params['cpid'] . '|' . $params['orderid'] . '|' . $params['paytime'] . '|' . $key)); + $sign=$this->sign($this->result_data,$key,['status','real_fee','ext','sign']); + if (isset($params['sign']) && $sign == $params['sign'] + && isset($params['status']) && $params['status'] == 0 + ) { + return true; + } else { + return false; + } + } + + + //返回给支付商的成功 + public function success() + { + echo 'SUCCESS'; + exit; + } + + //统一回调处理 + + /** + * 回调第一部,如果是同步,直接回传 + * @param $return + * @param $pay_type + * @param $request + * @return bool|\Illuminate\Http\RedirectResponse + */ + public function notify($return, $pay_type, $request) + { +// $request = json_decode(file_get_contents('php://input'), true); + $allData = $request->all(); + $this->setLogName($pay_type); + $this->debugLog('回调原始数据', $allData); + $this->pay_type = $pay_type; + $this->request = $request; + //取得订单,是否有此订单,如果没有直接返回空 + $order_sn = $allData['orderid']; + + $status = $allData['status']; + + if ($status != 0) { + return '未支付成功'; + } + + $checkresult = $this->checkIP();//检查回调IP + if (!$checkresult) { + return 'ip 不合法'; + } + //取得订单 + $this->getOrder($order_sn); + + $return = ($return) ? 1 : 0; + if ($return) { + + //判断是否是商户id + if ($this->order->merchant_id == 0) { + return redirect()->route('web.user.index'); + } + // + return $this->merchantReturnSend(); + } + //取得通道id + $this->gateway = $this->pay_gateway = config('gateway.config')[$this->gateway_id]; + //dd($this->gateway); + //取得支付配置 + $this->payConfig($this->pay_type); + + $this->result_data = $allData; + //检查三方的订单 + $checkorder = $this->checkOrder($order_sn); + if (!$checkorder) { + $this->debugLog('查询三方订单未支付成功'); + return '查询三方订单未支付成功'; + } +// dump($this->result_data); + //进行验证签名 + if (!$this->verify()) { + $this->debugLog('签名以及支付状态验证失败'); + return '签名以及支付状态验证失败'; + } + + return $this->payNotify(); + } + + + /** + * 同步回调 + * @return \Illuminate\Http\RedirectResponse + */ + public function returnPay() + { + //判断是否是商户id + if ($this->order->merchant_id == 0) { + return redirect()->route('web.user.index'); + } + // + return $this->merchantReturnSend(); + } + + //异步回调 + + /** + * 获得通道信息,取得支付配置模型,验证签名, + * @return bool|void + */ + private function payNotify() + { + //取得通道信息内容 + $data = $this->result_data; + $this->pay_data = $this->result_data; + //如果应答状态不是01/A6表示支付失败 + $this->debugLog(json_encode($data, true)); + $this->debugLog('-------------' . $this->order->order_sn . '--选择----' . $this->pay_type . '----' . $this->pay_method . '----开始回调处理-------------------------'); + if (empty($data)) { + return $this->debugLog('验证签名失败', $data); + } + try { + $pay_cn_name = ''; + //统一格式化 + $this->unionHandle($data); + //支付返回信息 + $this->pay_data = $data; + $this->debugLog('验证签名成功,数据', $data); + //更新订单 + $this->updateOrder(); + $this->debugLog('updateOrder Ok'); + + } catch (\Exception $exception) { + $this->debugLog('失败异常内容:' . $exception->getMessage()); + $this->order->notify_status = 1;//支付回调成功 + $this->order->pay_status = 1;//支付状态 + $this->order->pay_ok_at = date('Y-m-d H:i:s'); + $this->order->save();//保存 + Log::channel('pay_success')->info($pay_cn_name . '支付成功,但处理订单失败', ['data' => json_encode($data)]); + + } + + } + + /** + * 统一格式化 + */ + public function unionHandle($data) + { + $result = [ + 'order_sn' => $data['orderid'],//我方订单号 + 'pay_order_sn' => $data['orderid'],//三方的订单号 + 'pay_money' => number_format($data['real_fee'] / 100, 2, '.', ''), //支付金额, +// 'pay_money' => $data['real_fee'], //支付金额, + 'money' => number_format($data['amount'] / 100, 2, '.', ''), + 'pay_type' => $this->pay_type, + 'account' => '' + ]; + + $this->setResult($result); + Log::channel('pay_success')->info('支付成功', [ + 'pay_type' => $result['pay_type'], 'pay_money' => $result['pay_money'], + 'account' => $result['money'], 'order_sn' => $result['order_sn'], + 'pay_order_sn' => $result['pay_order_sn']]); + + } + + + /** + * 这个调试需要配置在config/logging.php + * @param $pay_type + */ + public function setLogName($pay_type) + { + $this->log_name = $pay_type; + } + + /** + * 模拟post提交 json数据 请求接口 + * @param string $url + * @param bool|true $https + * @param string $method + * @param string $param + * @return mixed + */ + private function ddcurl($url = '', $param = '', $https = true, $method = 'post') + { + $param = json_encode($param, 320); + $ch = curl_init($url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + + #判断是否为https请求 + if ($https === true) { + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); + } + #判断是否为post请求 + if ($method == 'post') { + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_POSTFIELDS, $param); + } + curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type:application/json')); + + $str = curl_exec($ch); + + curl_close($ch); + return $str; + } +} + diff --git a/app/ServicePay/PayApiProvidesTrait.php b/app/ServicePay/PayApiProvidesTrait.php index a2b6248..d332382 100644 --- a/app/ServicePay/PayApiProvidesTrait.php +++ b/app/ServicePay/PayApiProvidesTrait.php @@ -61,6 +61,14 @@ trait PayApiProvidesTrait return $this->pay_service = new RongYiServices(); case 'zhanxinpay': return $this->pay_service = new ZhanXinPayServices(); + case 'dalipay': + return $this->pay_service = new DaliPayServices(); + case 'pingguopay': + return $this->pay_service = new PingguopayServices(); + case 'koulinghbpay': + return $this->pay_service = new KoulinghbPayServices(); + case 'yihuibaopay': + return $this->pay_service = new YiHuiBaoPayServices(); break; } } diff --git a/app/ServicePay/PayTrait.php b/app/ServicePay/PayTrait.php index e01ca11..406ced3 100644 --- a/app/ServicePay/PayTrait.php +++ b/app/ServicePay/PayTrait.php @@ -82,9 +82,10 @@ trait PayTrait * 取得当前支付通道的类型信息实例,$this->pay_gateway * @param $pay_type * @param array $custom_gateways + * @param string $pay_channel * @return bool */ - public function getGateway($pay_type, $custom_gateways = []) + public function getGateway($pay_type, $custom_gateways = [],$pay_channel='') { //取得支付方法和类型 $pay_config = $this->payMethod($pay_type); @@ -110,7 +111,7 @@ trait PayTrait return false; } if (count($custom_gateways) > 0) { - $this->pay_gateway = $this->randomCustomGateways($all_gateways, $custom_gateways); + $this->pay_gateway = $this->randomCustomGateways($all_gateways, $custom_gateways,$pay_channel); } else { $this->pay_gateway = $this->randomAllGateways($all_gateways); } @@ -136,21 +137,28 @@ trait PayTrait * 随机切换用户选择支付通道 * @param $all_gateways 所有通道 * @param $custom_gateways 用户自定义选择通道 + * @param $pay_channel * @return bool|mixed */ - public function randomCustomGateways($all_gateways, $custom_gateways) + 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)) { - $on_user_gateway_id[] = $v; + 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)]; } + $total = count($on_user_gateway_id); + if ($total <= 0) { + return false; + } + return $on_user_gateway_id[mt_rand(0, $total - 1)]; } /** @@ -264,9 +272,11 @@ trait PayTrait public function checkGateway($request) { $pay_type = $request->input('pay_type'); + $pay_channel = $request->input('pay_channel'); $this->debugLog('-------------订单开始-------------'); $this->debugLog('支付类型->' . $pay_type); + $this->debugLog('channel->' . $pay_channel); //选择服务类型 $this->setPayService($pay_type); @@ -281,7 +291,8 @@ trait PayTrait } - $this->gateway = $this->pay_service->getGateway($pay_type, $custorm_gateways); + $this->gateway = $this->pay_service->getGateway($pay_type, $custorm_gateways,$pay_channel); + if (!$this->gateway) { return $this->addError(['error' => 1, 'msg' => '通道不存在']); } @@ -378,7 +389,10 @@ trait PayTrait $data['up_ratio'] = $this->gateway['up_ratio'];//通道单独上浮费率 $data['original_ratio'] = $this->merchant->ratio;//原始费率 //结算费率=商户费率+上浮费率 - $data['ratio'] = $this->merchant->ratio + $data['up_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; //通道费率 @@ -432,9 +446,13 @@ trait PayTrait $data['system_ratio'] = ($ratio_info['up_ratio'] + $data['up_ratio']); //上级的话,计算最后盈利,通道成本和费率不变,变得盈利资金和盈利费率 //最后盈利=(平台费率 - 通道费率)* 金额 /1000,(平台费率-通道费率) *金额 /1000 - $data['final_money'] = ($data['system_ratio'] - $this->gateway['ratio']) * $money / 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['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']; diff --git a/app/ServicePay/PingguopayServices.php b/app/ServicePay/PingguopayServices.php new file mode 100644 index 0000000..83bee17 --- /dev/null +++ b/app/ServicePay/PingguopayServices.php @@ -0,0 +1,358 @@ + $this->getGateUrl() . '/sfjoin/orderdata', + 'debug' => 1,//调试 + 'logDir' => to_linux_path(storage_path() . '/logs/'), + 'mch_id' => $this->pay_gateway['app_id'], //客户交易者账号 + 'token' => $this->pay_gateway['app_key'],//密钥 + 'interface' => $this->pay_gateway['mch_id'],//账号名称 一般用来存放三方通道 + 'return_url' => action('Pay\PayController@returnNotify', ['type' => $type]), + 'notify_url' => action('Pay\PayController@notify', ['type' => $type]), + ]; + $this->pay_config = $config; + } + + //统一下单支付 + + /** + * @param $pay_data + * @return array|\Illuminate\Http\RedirectResponse + */ + public function pay($pay_data) + { +// echo number_format( 500, 2,'.','');exit; + //商户号 + $accountId = $this->pay_config['mch_id']; + //商户秘钥 + $key = $this->pay_config['token']; + $payData = [ + 'appId' => $accountId,//商户 + 'channelNo' => $this->pay_gateway['mch_id'],//对应的三方通道 + 'notifyCallback' => strval($this->pay_config['notify_url']),// //异步回调地址 + 'orderNo' => strval($pay_data['out_trade_no']),//订单号 + 'amount' => $pay_data['total_amount'], //支付金额为元 + 'payType' => 1, //固定1 + ]; + $sign = strtolower(md5($key . $payData['orderNo'] . $payData['appId'] . $payData['amount'] . $payData['notifyCallback'])); + + $payData['sign'] = $sign; +// $res=$this->ddcurl($this->pay_config['url'],$pay_data,false); + $res = Curl::to($this->pay_config['url'])->withHeaders(['Content-type'=>'application/json'])->withData($payData)->post(); + $this->debugLog('下单接口请求内容' . json_encode($payData, true), []); + $this->debugLog('返回内容' . json_encode($res, true), []); + + $res = is_array($res) ? $res : json_decode($res, 256); + if (is_array($res) && isset($res['code']) && $res['code'] == 1) { + $url = $res['payUrl']; + return redirect()->away($url); + } else { + $msg = $res['msg'] ?? '未知错误'; + return ['code' => 0, 'msg' => $msg]; + } + + } + + private function sign($tempArr, $signKey): string + { + $keyVal = ''; + + if (isset($tempArr['sign'])) { + unset($tempArr['sign']); + } + + ksort($tempArr); + + $data = []; + foreach ($tempArr as $key => $value) { + array_push($data, "{$key}={$value}"); + } + $keyVal = implode('&', $data); + + if (!empty($signKey) && is_string($signKey)) { + $keyVal .= $signKey; + } + + return strtolower(md5($keyVal)); + } + + /** + * 检查订单 + * @param $orderid + * @return bool|string + */ + private function checkOrder($orderid) + { + $url = $this->getGateUrl() . '/sfjoin/search'; + $payData = [ + 'appId' => $this->pay_gateway['app_id'],//商户号 + 'orderNo' => $orderid, + ]; + $key = $this->pay_config['token']; + $sign = strtolower(md5($key . $payData['orderNo'] . $payData['appId'])); +// $sign = $this->sign($payData, $key); + $payData['sign'] = $sign; + Log::channel('pay_order')->info('查询接口请求', $payData); + $responseRaw = Curl::to($url)->withData($payData)->post(); +// $responseRaw = $this->ddcurl($url, $payData, false); + $response = is_array($responseRaw) ? $responseRaw : json_decode($responseRaw, 256); +// $this->debugLog('查询接口返回' . is_array($res) ? json_encode($res, true) : json_encode(json_decode($res, 256), true)); + Log::channel('pay_order')->info('查询接口返回', $response); + if (is_array($response) + && isset($response['code']) && $response['code'] == 1 + && isset($response['state']) && $response['state'] == 1 + && isset($response['orderNo']) && $response['orderNo'] == $orderid + ) { + return true; + } + return false; + } + + + //统一验证签名 + public function verify() + { + $params = $this->result_data; + $md5sign = strtolower(md5($this->pay_config['token'] . $params['orderNo'] . $this->pay_config['mch_id'] . $params['amount'])); + if (isset($params['sign']) && $md5sign == $params['sign'] + && isset($params['status']) && $params['status'] == 1 + ) { + return true; + } else { + return false; + } + } + + + //返回给支付商的成功 + public function success() + { + echo 'success'; + exit; + } + + //统一回调处理 + + /** + * 回调第一部,如果是同步,直接回传 + * @param $return + * @param $pay_type + * @param $request + * @return bool|\Illuminate\Http\RedirectResponse + */ + public function notify($return, $pay_type, $request) + { +// $request = json_decode(file_get_contents('php://input'), true); + $allData = $request->all(); + $this->setLogName($pay_type); + $this->debugLog('回调原始数据', $allData); + $this->pay_type = $pay_type; + $this->request = $request; + //取得订单,是否有此订单,如果没有直接返回空 + $order_sn = $allData['orderNo']; + + $status = $allData['status']; + + if ($status != 1) { + return '未支付成功'; + } + + $checkresult = $this->checkIP();//检查回调IP + if (!$checkresult) { + return 'ip 不合法'; + } + //取得订单 + $this->getOrder($order_sn); + + $return = ($return) ? 1 : 0; + if ($return) { + + //判断是否是商户id + if ($this->order->merchant_id == 0) { + return redirect()->route('web.user.index'); + } + // + return $this->merchantReturnSend(); + } + //取得通道id + $this->gateway = $this->pay_gateway = config('gateway.config')[$this->gateway_id]; + //dd($this->gateway); + //取得支付配置 + $this->payConfig($this->pay_type); + + $this->result_data = $allData; + //检查三方的订单 + $checkorder = $this->checkOrder($order_sn); + if (!$checkorder) { + $this->debugLog('查询三方订单未支付成功'); + return '查询三方订单未支付成功'; + } + //dump($this->result_data); + //进行验证签名 + if (!$this->verify()) { + $this->debugLog('签名以及支付状态验证失败'); + return '签名以及支付状态验证失败'; + } + + return $this->payNotify(); + } + + + /** + * 同步回调 + * @return \Illuminate\Http\RedirectResponse + */ + public function returnPay() + { + //判断是否是商户id + if ($this->order->merchant_id == 0) { + return redirect()->route('web.user.index'); + } + // + return $this->merchantReturnSend(); + } + + //异步回调 + + /** + * 获得通道信息,取得支付配置模型,验证签名, + * @return bool|void + */ + private function payNotify() + { + //取得通道信息内容 + $data = $this->result_data; + $this->pay_data = $this->result_data; + //如果应答状态不是01/A6表示支付失败 + $this->debugLog(json_encode($data, true)); + $this->debugLog('-------------' . $this->order->order_sn . '--选择----' . $this->pay_type . '----' . $this->pay_method . '----开始回调处理-------------------------'); + if (empty($data)) { + return $this->debugLog('验证签名失败', $data); + } + try { + $pay_cn_name = ''; + //统一格式化 + $this->unionHandle($data); + //支付返回信息 + $this->pay_data = $data; + $this->debugLog('验证签名成功,数据', $data); + //更新订单 + $this->updateOrder(); + $this->debugLog('updateOrder Ok'); + + } catch (\Exception $exception) { + $this->debugLog('失败异常内容:' . $exception->getMessage()); + $this->order->notify_status = 1;//支付回调成功 + $this->order->pay_status = 1;//支付状态 + $this->order->pay_ok_at = date('Y-m-d H:i:s'); + $this->order->save();//保存 + Log::channel('pay_success')->info($pay_cn_name . '支付成功,但处理订单失败', ['data' => json_encode($data)]); + + } + + } + + /** + * 统一格式化 + */ + public function unionHandle($data) + { + $result = [ + 'order_sn' => $data['order_sn'],//我方订单号 + 'pay_order_sn' => $data['sys_order_sn'],//三方的订单号 +// 'pay_money' => number_format($data['payamount'] / 100, 2, '.', ''), //支付金额, + 'pay_money' => $data['pay_money'], //支付金额, + 'money' => $data['money'], + 'pay_type' => $this->pay_type, + 'account' => '' + ]; + + $this->setResult($result); + Log::channel('pay_success')->info('支付成功', [ + 'pay_type' => $result['pay_type'], 'pay_money' => $result['pay_money'], + 'account' => $result['money'], 'order_sn' => $result['order_sn'], + 'pay_order_sn' => $result['pay_order_sn']]); + + } + + + /** + * 这个调试需要配置在config/logging.php + * @param $pay_type + */ + public function setLogName($pay_type) + { + $this->log_name = $pay_type; + } + + /** + * 模拟post提交 json数据 请求接口 + * @param string $url + * @param bool|true $https + * @param string $method + * @param string $param + * @return mixed + */ + private function ddcurl($url = '', $param = '', $https = true, $method = 'post') + { +// $param = json_encode($param, 320); + $ch = curl_init($url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + + #判断是否为https请求 + if ($https === true) { + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); + } + #判断是否为post请求 + if ($method == 'post') { + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_POSTFIELDS, $param); + } + curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type:application/json')); + + $str = curl_exec($ch); + + curl_close($ch); + return $str; + } +} + diff --git a/app/ServicePay/YiHuiBaoPayServices.php b/app/ServicePay/YiHuiBaoPayServices.php new file mode 100644 index 0000000..d5d84d8 --- /dev/null +++ b/app/ServicePay/YiHuiBaoPayServices.php @@ -0,0 +1,371 @@ + $this->getGateUrl() . '/gateway/payApiJson.asp', + 'debug' => 1,//调试 + 'logDir' => to_linux_path(storage_path() . '/logs/'), + 'mch_id' => $this->pay_gateway['app_id'], //客户交易者账号 + 'token' => $this->pay_gateway['app_key'],//密钥 + 'interface' => $this->pay_gateway['mch_id'],//账号名称 一般用来存放三方通道 + 'return_url' => action('Pay\PayController@returnNotify', ['type' => $type]), + 'notify_url' => action('Pay\PayController@notify', ['type' => $type]), + ]; + $this->pay_config = $config; + } + + //统一下单支付 + + /** + * @param $pay_data + * @return array|\Illuminate\Http\RedirectResponse + */ + public function pay($pay_data) + { +// echo number_format( 500, 2,'.','');exit; + //商户号 + $accountId = $this->pay_config['mch_id']; + //商户秘钥 + $key = $this->pay_config['token']; + $payData = [ + 'customerid' => $accountId,//商户 + 'sdcustomno' => strval($pay_data['out_trade_no']),//订单号 + 'cardno' => $this->pay_gateway['mch_id'],//对应的三方通道 + 'orderamount' => intval($pay_data['total_amount'] * 100), //支付金额为分 + 'zftype'=>'casher', + 'device'=>'mobile', + 'ordertime'=>time(), + 'mark' => mt_rand(100000, 999999), // + 'clientip' => request()->getClientIp(), + 'noticeurl' => strval($this->pay_config['notify_url']),// //异步回调地址 + 'backurl' => strval($this->pay_config['return_url']),// //页面跳转通知 + ]; + $sign= $this->sign($payData,$key,['customerid', 'sdcustomno','orderamount','cardno','noticeurl','backurl','ordertime']); + $payData['sign'] = $sign; +// $res=$this->ddcurl($this->pay_config['url'],$pay_data,false); + $res = Curl::to($this->pay_config['url'])->withData($payData)->post(); + $this->debugLog('下单接口请求内容' . json_encode($payData, true), []); + $this->debugLog('返回内容' . json_encode($res, true), []); + + $res = is_array($res) ? $res : json_decode($res, 256); + if (is_array($res) && isset($res['state']) && $res['state'] == 1 && $res['qrurl']!='') { + $url = $res['qrurl']; + return redirect()->away($url); + } else { + $msg = $res['errmsg'] ?? '未知错误'; + $this->debugLog('错误' . $msg, []); + return json_encode(['code' => 0, 'msg' => $msg],256); + } + + } + + private function sign($tempArr, $signKey,$signSortArr=[]): string + { + $keyVal = ''; + + if (isset($tempArr['sign'])) { + unset($tempArr['sign']); + } + + $data = []; + foreach ($signSortArr as $key){ + if(isset($tempArr[$key])){ + array_push($data, "{$key}={$tempArr[$key]}"); + } + } + + ksort($tempArr); + + + $keyVal = implode('&', $data); + + if (!empty($signKey) && is_string($signKey)) { + $keyVal .= $signKey; + } + + return strtoupper(md5($keyVal)); + } + + /** + * 检查订单 + * @param $orderid + * @return bool|string + */ + private function checkOrder($orderid) + { + try { + $url = $this->getGateUrl() . '/gateway/zx_orderquery.asp'; + $payData = [ + 'customerid' => $this->pay_gateway['app_id'],//商户号 + 'sdcustomno' => $orderid, + 'format' => 'json', + ]; + $key = $this->pay_config['token']; + $sign = $this->sign($payData, $key,['customerid','sdcustomno']); + $payData['sign'] = $sign; + Log::channel('pay_order')->info('查询接口请求', $payData); + $responseRaw = Curl::to($url)->withData($payData)->get(); +// $responseRaw = $this->ddcurl($url, $payData, false); + $response = is_array($responseRaw) ? $responseRaw : json_decode($responseRaw, 256); +// $this->debugLog('查询接口返回' . is_array($res) ? json_encode($res, true) : json_encode(json_decode($res, 256), true)); + Log::channel('pay_order')->info('查询接口返回', $response); + if (is_array($response) + && isset($response['state']) && $response['state'] == 1 + && isset($response['sdcustomno']) && $response['sdcustomno'] == $orderid + ) { + return true; + } + return false; + }catch (\Exception $e){ + Log::channel('pay_order')->info('err', $e->getMessage()); + } + return false; + } + + + //统一验证签名 + public function verify() + { + $params = $this->result_data; + $key = $this->pay_config['token']; + $key='&key='.$key; + $sign=$this->sign($params,$key,['customerid','sd51no','sdcustomno','mark']); + if (isset($params['sign']) && $sign == $params['sign']) { + return true; + } else { + return false; + } + } + + + //返回给支付商的成功 + public function success() + { + echo ' 1'; + exit; + } + + //统一回调处理 + + /** + * 回调第一部,如果是同步,直接回传 + * @param $return + * @param $pay_type + * @param $request + * @return bool|\Illuminate\Http\RedirectResponse + */ + public function notify($return, $pay_type, $request) + { +// $request = json_decode(file_get_contents('php://input'), true); + $allData = $request->all(); + $this->setLogName($pay_type); + $this->debugLog('回调原始数据', $allData); + $this->pay_type = $pay_type; + $this->request = $request; + //取得订单,是否有此订单,如果没有直接返回空 + $order_sn = $allData['sdcustomno']; + + $status = $allData['state']; + + if ($status != 1) { + return '未支付成功'; + } + + $checkresult = $this->checkIP();//检查回调IP + if (!$checkresult) { + return 'ip 不合法'; + } + //取得订单 + $this->getOrder($order_sn); + + $return = ($return) ? 1 : 0; + if ($return) { + + //判断是否是商户id + if ($this->order->merchant_id == 0) { + return redirect()->route('web.user.index'); + } + // + return $this->merchantReturnSend(); + } + //取得通道id + $this->gateway = $this->pay_gateway = config('gateway.config')[$this->gateway_id]; + //dd($this->gateway); + //取得支付配置 + $this->payConfig($this->pay_type); + + $this->result_data = $allData; + //检查三方的订单 +// $checkorder = $this->checkOrder($order_sn); +// if (!$checkorder) { +// $this->debugLog('查询三方订单未支付成功'); +// return '查询三方订单未支付成功'; +// } + //dump($this->result_data); + //进行验证签名 + if (!$this->verify()) { + $this->debugLog('签名以及支付状态验证失败'); + return '签名以及支付状态验证失败'; + } + + return $this->payNotify(); + } + + + /** + * 同步回调 + * @return \Illuminate\Http\RedirectResponse + */ + public function returnPay() + { + //判断是否是商户id + if ($this->order->merchant_id == 0) { + return redirect()->route('web.user.index'); + } + // + return $this->merchantReturnSend(); + } + + //异步回调 + + /** + * 获得通道信息,取得支付配置模型,验证签名, + * @return bool|void + */ + private function payNotify() + { + //取得通道信息内容 + $data = $this->result_data; + $this->pay_data = $this->result_data; + //如果应答状态不是01/A6表示支付失败 + $this->debugLog(json_encode($data, true)); + $this->debugLog('-------------' . $this->order->order_sn . '--选择----' . $this->pay_type . '----' . $this->pay_method . '----开始回调处理-------------------------'); + if (empty($data)) { + return $this->debugLog('验证签名失败', $data); + } + try { + $pay_cn_name = ''; + //统一格式化 + $this->unionHandle($data); + //支付返回信息 + $this->pay_data = $data; + $this->debugLog('验证签名成功,数据', $data); + //更新订单 + $this->updateOrder(); + $this->debugLog('updateOrder Ok'); + + } catch (\Exception $exception) { + $this->debugLog('失败异常内容:' . $exception->getMessage()); + $this->order->notify_status = 1;//支付回调成功 + $this->order->pay_status = 1;//支付状态 + $this->order->pay_ok_at = date('Y-m-d H:i:s'); + $this->order->save();//保存 + Log::channel('pay_success')->info($pay_cn_name . '支付成功,但处理订单失败', ['data' => json_encode($data)]); + + } + + } + + /** + * 统一格式化 + */ + public function unionHandle($data) + { + $result = [ + 'order_sn' => $data['sdcustomno'],//我方订单号 + 'pay_order_sn' => $data['sd51no'],//三方的订单号 + 'pay_money' => number_format($data['ordermoney'] / 100, 2, '.', ''), //支付金额, +// 'pay_money' => $data['ordermoney'], //支付金额, + 'money' => number_format($data['ordermoney'] / 100, 2, '.', ''), + 'pay_type' => $this->pay_type, + 'account' => '' + ]; + + $this->setResult($result); + Log::channel('pay_success')->info('支付成功', [ + 'pay_type' => $result['pay_type'], 'pay_money' => $result['pay_money'], + 'account' => $result['money'], 'order_sn' => $result['order_sn'], + 'pay_order_sn' => $result['pay_order_sn']]); + + } + + + /** + * 这个调试需要配置在config/logging.php + * @param $pay_type + */ + public function setLogName($pay_type) + { + $this->log_name = $pay_type; + } + + /** + * 模拟post提交 json数据 请求接口 + * @param string $url + * @param bool|true $https + * @param string $method + * @param string $param + * @return mixed + */ + private function ddcurl($url = '', $param = '', $https = true, $method = 'post') + { + $param = json_encode($param, 320); + $ch = curl_init($url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + + #判断是否为https请求 + if ($https === true) { + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); + } + #判断是否为post请求 + if ($method == 'post') { + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_POSTFIELDS, $param); + } + curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type:application/json')); + + $str = curl_exec($ch); + + curl_close($ch); + return $str; + } +} + diff --git a/app/Services/SearchServices.php b/app/Services/SearchServices.php index 9f23362..89a6bdf 100644 --- a/app/Services/SearchServices.php +++ b/app/Services/SearchServices.php @@ -176,6 +176,7 @@ class SearchServices } } + } public function addWhere($where) @@ -560,6 +561,17 @@ class SearchServices $this->addWhere($data); } + public function whereByPayType(string $pay_type) + { + $data = [ + 'pay_type' => [ + 'type' => '=', + 'value' => $pay_type + ] + ]; + $this->addWhere($data); + } + /** * 按日期搜索时间 * @param string $time diff --git a/config/adconfig.php b/config/adconfig.php index 90ccd50..98e7578 100644 --- a/config/adconfig.php +++ b/config/adconfig.php @@ -58,6 +58,10 @@ return [ 'shandianpay' =>'闪电支付', 'rongyipay' =>'融易支付', 'zhanxinpay' =>'展信支付', + 'dalipay' =>'大利支付', + 'pingguopay' =>'苹果付', + 'koulinghbpay' =>'口令红包', + 'yihuibaopay' =>'易汇宝', ], 'payfor_status' => [ 0 => '等待处理', diff --git a/config/qrcodeurl.php b/config/qrcodeurl.php index 2d2b046..3ee48d4 100644 --- a/config/qrcodeurl.php +++ b/config/qrcodeurl.php @@ -2,12 +2,12 @@ return [ 'zhanxin' => [ - 'notify_url'=>'https://wujie.la',//本机域名 - 'notify'=>'/order/notify',//给本机回调的 - 'baseurl'=>'https://imx.88mk.com:9290',//ineed 地址 - 'del' => '/guest/del', + 'notify_url' => env('NOTIFY_URL', 'https://wujie.la'),//本机域名 + 'notify' => '/order/notify',//给本机回调的 + 'baseurl' => env('BASE_URL', 'https://imx.88mk.com:9290'),//ineed 地址 + 'del' => '/guest/delete', 'add' => '/guest/add', 'query' => '/notify/query', - 'secret'=>'notifyqwe123+asdfffggb=' + 'secret' => 'notifyqwe123+asdfffggb=' ] ]; \ No newline at end of file diff --git a/config/whitelist.php b/config/whitelist.php index 1176177..0aeea07 100644 --- a/config/whitelist.php +++ b/config/whitelist.php @@ -28,6 +28,7 @@ return [ '103.229.64.217', '103.47.241.106', '110.74.196.112', + '49.156.32.13', ], 'api'=>[ '45.195.84.39' @@ -54,5 +55,14 @@ return [ '103.223.122.128', '103.223.122.129', ], + 'dalipay'=>[ + '117.120.61.66' + ], + 'pingguopay'=>[ + '47.243.44.247' + ], + 'koulinghbpay'=>[ + '8.129.172.207' + ], ] ]; \ No newline at end of file diff --git a/resources/views/admin/gateway/create.blade.php b/resources/views/admin/gateway/create.blade.php index 9d9498b..dffab1d 100644 --- a/resources/views/admin/gateway/create.blade.php +++ b/resources/views/admin/gateway/create.blade.php @@ -31,7 +31,7 @@
- +
diff --git a/resources/views/admin/gateway/edit.blade.php b/resources/views/admin/gateway/edit.blade.php index d1bc98d..5d352ee 100644 --- a/resources/views/admin/gateway/edit.blade.php +++ b/resources/views/admin/gateway/edit.blade.php @@ -33,7 +33,7 @@
- +
diff --git a/resources/views/admin/gateway/index.blade.php b/resources/views/admin/gateway/index.blade.php index fe56e51..3e3a860 100644 --- a/resources/views/admin/gateway/index.blade.php +++ b/resources/views/admin/gateway/index.blade.php @@ -39,11 +39,12 @@ , table = layui.table; var element = layui.element; + cols= [[ {type: 'checkbox',width: 80} , {field: 'id', width: 80, title: '通道ID', sort: true} , {field: 'name', title: '通道名称',minWidth: 120} - , {field: 'mch_id', title: '账号名称',minWidth: 250} + , {field: 'mch_id', title: '三方通道',minWidth: 250} , {field: 'ename', title: 'API标识',width:100} , {field: 'limit_money', title: '单笔限额',width:100} @@ -63,7 +64,6 @@ //监听表操作 listable.handle(); listable.top_handle(); - }); @endsection \ No newline at end of file diff --git a/resources/views/admin/gateway/statics.blade.php b/resources/views/admin/gateway/statics.blade.php new file mode 100644 index 0000000..d95a2ba --- /dev/null +++ b/resources/views/admin/gateway/statics.blade.php @@ -0,0 +1,80 @@ +@extends('admin.layouts.base') +@section('add_css') + +@endsection +@section('content') +
+
+
+ +
+ +
+ +
+
+ +
+ +
+
+ +
+
+ +
+ +
+
+
+@endsection +@section('add_js') + + @include('admin.layouts.layui_tpl') + @include('admin.layouts.commonscript') + +@endsection \ No newline at end of file diff --git a/resources/views/admin/layouts/side.blade.php b/resources/views/admin/layouts/side.blade.php index 522b673..419ded9 100644 --- a/resources/views/admin/layouts/side.blade.php +++ b/resources/views/admin/layouts/side.blade.php @@ -167,6 +167,7 @@
通道列表
+
通道统计
通道风控
diff --git a/resources/views/admin/order/index.blade.php b/resources/views/admin/order/index.blade.php index 5a6f290..93d8657 100644 --- a/resources/views/admin/order/index.blade.php +++ b/resources/views/admin/order/index.blade.php @@ -166,6 +166,21 @@ class="layui-input">
+ +
+ +
+ +
+
+
diff --git a/routes/admin.php b/routes/admin.php index 276254f..578186f 100644 --- a/routes/admin.php +++ b/routes/admin.php @@ -118,6 +118,8 @@ Route::prefix($admin_path)->group(function ($route) { $route->any($controller_path . '/api/json', ['uses' => $c . '@apiJson']); } $route->get('article/content/{id}', ['uses' => 'ArticleController@content']); + $route->get('gateway/statics', ['uses' => 'GatewayController@statics']); + $route->any('gateway/statics_data', ['uses' => 'GatewayController@statics_data']); $route->put('article/content/post', ['uses' => 'ArticleController@contentPost']); $route->any('handle/{type}', ['uses' => 'HandleController@handle']); $route->any('upload/{type}', ['uses' => 'FileUploadController@handle']); diff --git a/routes/web.php b/routes/web.php index 53ce967..d6a2f53 100644 --- a/routes/web.php +++ b/routes/web.php @@ -49,11 +49,11 @@ Route::name('web.')->group(function ($route) { }); - Route::group(['prefix' => 'zhanxin'], function ($route) { - $route->get('/', 'ZhanxinController@index')->name('zhanxin.index'); - $route->post('/order', 'ZhanxinController@orderPost')->name('zhanxin.orderPost'); - - }); +// Route::group(['prefix' => 'zhanxin'], function ($route) { +// $route->get('/', 'ZhanxinController@index')->name('zhanxin.index'); +// $route->post('/order', 'ZhanxinController@orderPost')->name('zhanxin.orderPost'); +// +// }); Route::get('unionpay/pay', 'UnionPayController@pay'); //页面跳转同步通知页面路径