新支付

This commit is contained in:
zcy 2021-07-14 13:49:18 +08:00
parent 6294f2d45d
commit 53fc2d2ff2
24 changed files with 2087 additions and 30 deletions

View File

@ -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

View File

@ -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()
{

View File

@ -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;
}
}

View File

@ -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();;

View File

@ -0,0 +1,351 @@
<?php
namespace App\ServicePay;
use App\Models\Merchant;
use App\Models\Order;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Collection;
use Illuminate\Http\Request;
use Ixudra\Curl\Facades\Curl;
/**
* Class RongYiServices
* @package App\ServicePay
*/
class CengJingServices implements PayApiInterface
{
use PayTrait;
use ThirdPaySignTrait;
public $gateway_list;//当前类型的支付通道列表
public $pay_type;//支付类型
public $pay_method;//支付方法
public $pay_gateway;//当前的支付通道实例
public $pay_config;//这个通道的支付配置信息
public $order;
public $request;
public $gateway_id;
public $pay_data;
public $log_name;
public $result_data;
public static $result;
/**
* 网关域名
* @return string
*/
private function getGateUrl(): string
{
return 'http://aimeisenfzf.com';
}
//第二部配置支付信息payConfig
public function payConfig($type, $setConfig = [])
{
$config = [
'url' => $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;
}
}

View File

@ -0,0 +1,363 @@
<?php
namespace App\ServicePay;
use App\Models\Merchant;
use App\Models\Order;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Collection;
use Illuminate\Http\Request;
use Ixudra\Curl\Facades\Curl;
/**
* @package App\ServicePay
*/
class DaliPayServices implements PayApiInterface
{
use PayTrait;
use ThirdPaySignTrait;
public $gateway_list;//当前类型的支付通道列表
public $pay_type;//支付类型
public $pay_method;//支付方法
public $pay_gateway;//当前的支付通道实例
public $pay_config;//这个通道的支付配置信息
public $order;
public $request;
public $gateway_id;
public $pay_data;
public $log_name;
public $result_data;
public static $result;
/**
* 网关域名
* @return string
*/
protected function getGateUrl(): string
{
return 'https://pay.dali5566.com';
}
//第二部配置支付信息payConfig
public function payConfig($type, $setConfig = [])
{
$config = [
'url' => $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;
}
}

View File

@ -0,0 +1,366 @@
<?php
namespace App\ServicePay;
use Illuminate\Support\Facades\Log;
use Ixudra\Curl\Facades\Curl;
/**
* @package App\ServicePay
*/
class KoulinghbPayServices implements PayApiInterface
{
use PayTrait;
use ThirdPaySignTrait;
public $gateway_list;//当前类型的支付通道列表
public $pay_type;//支付类型
public $pay_method;//支付方法
public $pay_gateway;//当前的支付通道实例
public $pay_config;//这个通道的支付配置信息
public $order;
public $request;
public $gateway_id;
public $pay_data;
public $log_name;
public $result_data;
public static $result;
/**
* 网关域名
* @return string
*/
protected function getGateUrl(): string
{
return 'http://bank.dm19.com';
}
//第二部配置支付信息payConfig
public function payConfig($type, $setConfig = [])
{
$config = [
'url' => $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;
}
}

View File

@ -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;
}
}

View File

@ -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'];

View File

@ -0,0 +1,358 @@
<?php
namespace App\ServicePay;
use Illuminate\Support\Facades\Log;
use Ixudra\Curl\Facades\Curl;
/**
* @package App\ServicePay
*/
class PingguopayServices implements PayApiInterface
{
use PayTrait;
use ThirdPaySignTrait;
public $gateway_list;//当前类型的支付通道列表
public $pay_type;//支付类型
public $pay_method;//支付方法
public $pay_gateway;//当前的支付通道实例
public $pay_config;//这个通道的支付配置信息
public $order;
public $request;
public $gateway_id;
public $pay_data;
public $log_name;
public $result_data;
public static $result;
/**
* 网关域名
* @return string
*/
protected function getGateUrl(): string
{
return 'http://applesf.tianshuyi.cn:18088';
}
//第二部配置支付信息payConfig
public function payConfig($type, $setConfig = [])
{
$config = [
'url' => $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;
}
}

View File

@ -0,0 +1,371 @@
<?php
namespace App\ServicePay;
use Illuminate\Support\Facades\Log;
use Ixudra\Curl\Facades\Curl;
/**
* @package App\ServicePay
*/
class YiHuiBaoPayServices implements PayApiInterface
{
use PayTrait;
use ThirdPaySignTrait;
public $gateway_list;//当前类型的支付通道列表
public $pay_type;//支付类型
public $pay_method;//支付方法
public $pay_gateway;//当前的支付通道实例
public $pay_config;//这个通道的支付配置信息
public $order;
public $request;
public $gateway_id;
public $pay_data;
public $log_name;
public $result_data;
public static $result;
/**
* 网关域名
* @return string
*/
protected function getGateUrl(): string
{
return 'http://api.huhu199.com';
}
//第二部配置支付信息payConfig
public function payConfig($type, $setConfig = [])
{
$config = [
'url' => $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 ' <result>1</result>';
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;
}
}

View File

@ -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

View File

@ -58,6 +58,10 @@ return [
'shandianpay' =>'闪电支付',
'rongyipay' =>'融易支付',
'zhanxinpay' =>'展信支付',
'dalipay' =>'大利支付',
'pingguopay' =>'苹果付',
'koulinghbpay' =>'口令红包',
'yihuibaopay' =>'易汇宝',
],
'payfor_status' => [
0 => '等待处理',

View File

@ -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='
]
];

View File

@ -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'
],
]
];

View File

@ -31,7 +31,7 @@
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">账号</label>
<label class="layui-form-label">三方通道</label>
<div class="layui-input-block">
<input type="text" name="mch_id" lay-verify="rq" autocomplete="off" class="layui-input"/>
</div>

View File

@ -33,7 +33,7 @@
</div>
<div class="layui-form-item">
<label class="layui-form-label">账号</label>
<label class="layui-form-label">三方通道</label>
<div class="layui-input-block">
<input type="text" name="mch_id" value="{{ $show->mch_id }}" lay-verify="rq" autocomplete="off"
class="layui-input"/>

View File

@ -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();
});
</script>
@endsection

View File

@ -0,0 +1,80 @@
@extends('admin.layouts.base')
@section('add_css')
@endsection
@section('content')
<div class="layui-card">
<div class="layui-form layui-form-pane layui-card-header layuiadmin-card-header-auto">
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label">时间</label>
<div class="layui-input-block" >
<input type="text" name="timeday" id="times" readonly placeholder="请输入" autocomplete="off"
class="layui-input">
</div>
</div>
<div class="layui-inline">
<button class="layui-btn layuiadmin-btn-admin" lay-submit lay-filter="LAY-list-search"
style="">
<i class="layui-icon layui-icon-search layuiadmin-button-btn"></i>
</button>
</div>
</div>
</div>
<div class="layui-card-body">
<table id="LAY-list-table" lay-filter="LAY-list-table"></table>
</div>
</div>
</div>
@endsection
@section('add_js')
@include('admin.layouts.layui_tpl')
@include('admin.layouts.commonscript')
<script>
listable_url="{{ action($controller.'@statics_data') }}";
listConfig.open_width='800px';
layui.use(['index', 'table','listable','laydate'], function () {
var $ = layui.$
, form = layui.form
,listable=layui.listable
, table = layui.table;
var element = layui.element;
var laydate = layui.laydate;
laydate.render({
elem: '#times',
max: 0
, range: '~'
, format: 'yyyy-MM-dd'
});
cols= [[
{field: 'gateway_id', minWidth: 80, title: '通道ID', sort: true}
, {field: 'name', title: '通道名称',minWidth: 120}
, {field: 'order_money', title: '订单金额',minWidth: 250}
, {field: 'ok_money', title: '成功金额',minWidth:100}
, {field: 'total', title: '订单数',minWidth:100}
, {field: 'ok_total', title: '成功数',minWidth:120}
, {field: 'up_ratio', title: '成功率',minWidth:120,templet: function (d) {
return ((d.ok_total/d.total).toFixed(2)*100).toFixed(2)+'%';
}}
]];
listable.list(listable_url,cols,{
where:{
}
});
//监听表操作
listable.handle();
listable.top_handle();
listable.search();
});
</script>
@endsection

View File

@ -167,6 +167,7 @@
</a>
<dl class="layui-nav-child">
<dd><a lay-href="{{ admin_url('Gateway','index') }}">通道列表</a></dd>
<dd><a lay-href="{{ admin_url('Gateway','statics',['type'=>'corn']) }}">通道统计</a></dd>
<dd><a lay-href="{{ admin_url('GatewayWind','index') }}">通道风控</a></dd>

View File

@ -166,6 +166,21 @@
class="layui-input">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">通道</label>
<div class="layui-input-block">
<select name="pay_type">
<option value="">全部</option>
@if(count($gateway)>0)
@foreach (config('adconfig.pay_type') as $k=>$v)
<option value="{{ $k }}">{{ $v }}</option>
@endforeach
@endif
</select>
</div>
</div>
<div class="layui-inline">
<button class="layui-btn layui-btn-sm" data-doing="1" data-type="day"

View File

@ -52,7 +52,7 @@
<div class="layui-form-item">
<label class="layui-form-label">uid</label>
<div class="layui-input-block">
<input type="number" name="uid" autocomplete="off" value="{{ $show->uid }}" class="layui-input"/>
<input type="number" name="uid" readonly="readonly" autocomplete="off" value="{{ $show->uid }}" class="layui-input"/>
</div>
</div>
<div class="layui-form-item">

View File

@ -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']);

View File

@ -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');
//页面跳转同步通知页面路径