新支付
This commit is contained in:
parent
6294f2d45d
commit
53fc2d2ff2
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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'];
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
@ -58,6 +58,10 @@ return [
|
|||
'shandianpay' =>'闪电支付',
|
||||
'rongyipay' =>'融易支付',
|
||||
'zhanxinpay' =>'展信支付',
|
||||
'dalipay' =>'大利支付',
|
||||
'pingguopay' =>'苹果付',
|
||||
'koulinghbpay' =>'口令红包',
|
||||
'yihuibaopay' =>'易汇宝',
|
||||
],
|
||||
'payfor_status' => [
|
||||
0 => '等待处理',
|
||||
|
|
|
@ -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='
|
||||
]
|
||||
];
|
|
@ -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'
|
||||
],
|
||||
]
|
||||
];
|
|
@ -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>
|
||||
|
|
|
@ -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"/>
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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']);
|
||||
|
|
|
@ -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');
|
||||
//页面跳转同步通知页面路径
|
||||
|
|
Loading…
Reference in New Issue