333 lines
10 KiB
PHP
333 lines
10 KiB
PHP
<?php
|
||
/**
|
||
* Created by PhpStorm.
|
||
* User: Yontal
|
||
* Date: 2020/9/29
|
||
* Time: 9:59
|
||
*/
|
||
|
||
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 DaLePayServices
|
||
* @package App\ServicePay
|
||
*/
|
||
class DaLePayServices 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()
|
||
{
|
||
return 'https://pay.dlf66.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)
|
||
{
|
||
/**
|
||
* $pay_data= array:4 [▼
|
||
"out_trade_no" => "20200614222939281502"
|
||
"total_amount" => "500.00"
|
||
"subject" => "20200614222939281502定制"
|
||
"created_at" => "2020-06-14 22:29:39"
|
||
]
|
||
*/
|
||
//商户号
|
||
$accountId = $this->pay_config['mch_id'];
|
||
//商户秘钥
|
||
$key = $this->pay_config['token'];
|
||
$payData = [
|
||
'bid' => $accountId,//商户
|
||
'pay_type' =>$this->pay_gateway['mch_id'],//对应的三方通道
|
||
'order_sn' => strval($pay_data['out_trade_no']),//订单号
|
||
'money' => number_format($pay_data['total_amount'], 2, '.', ''), //支付金额
|
||
'notify_url' => strval($this->pay_config['notify_url']),// //异步回调地址
|
||
// 'returnUrl' => strval($this->pay_config['return_url']),// //页面跳转通知
|
||
];
|
||
$sinArr=[
|
||
'key'=>$key,
|
||
'bid'=>$payData['bid'],
|
||
'money'=>$payData['money'],
|
||
'order_sn'=>$payData['order_sn'],
|
||
'notify_url'=>$payData['notify_url'],
|
||
];
|
||
$sign = $this->sign( $sinArr);//签名
|
||
$payData['sign'] = $sign;
|
||
$this->debugLog('下单接口请求内容' . json_encode($payData, true), []);
|
||
$res = Curl::to($this->pay_config['url'])->withData($payData)->post();
|
||
$this->debugLog('下单接口返回' . $res);
|
||
$res=!is_array($res)?json_decode($res,true):$res;
|
||
if (is_array($res) && isset($res['code']) && $res['code'] == 100) {
|
||
$url = $res['data']['url'];
|
||
return redirect()->away($url);//跳转支付
|
||
} else {
|
||
$msg = $res['msg'] ?? '未知错误';
|
||
return ['code' => 0, 'msg' => $msg];
|
||
}
|
||
}
|
||
|
||
private function sign($tempArr){
|
||
$keyVal='';
|
||
foreach ($tempArr as $k => $val) {
|
||
$keyVal .= $val . "|";
|
||
}
|
||
return md5(trim($keyVal,'|'));
|
||
}
|
||
|
||
/**
|
||
* 检查订单
|
||
* @param $orderid
|
||
* @return bool|string
|
||
*/
|
||
private function checkOrder($orderid)
|
||
{
|
||
$url = $this->getGateUrl() . '/api/detail';
|
||
$payData = [
|
||
'order_sn' => $orderid,
|
||
'bid' => $this->pay_gateway['app_id'],//商户号
|
||
];
|
||
$key = $this->pay_config['token'];
|
||
$sign = $this->sign([
|
||
'key'=>$key,
|
||
'bid'=>$payData['bid'],
|
||
'order_sn'=>$payData['order_sn'],
|
||
]);
|
||
$payData['sign'] = $sign;
|
||
Log::channel('pay_order')->info('查询接口请求', $payData);
|
||
|
||
$res = Curl::to($url)->withData($payData)->post();
|
||
$res = is_array($res) ? $res : json_decode($res, 256);
|
||
// $this->debugLog('查询接口返回' . is_array($res) ? json_encode($res, true) : json_encode(json_decode($res, 256), true));
|
||
Log::channel('pay_order')->info('查询接口返回', $res);
|
||
if (isset($res['code']) && $res['code'] == 100) {
|
||
if ($res['data']['order_sn'] == $orderid && $res['data']['pay_state']==1) {
|
||
//,2-支付成功,3-业务处理完成
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
|
||
//统一验证签名
|
||
public function verify()
|
||
{
|
||
$para = $this->result_data;
|
||
$sign = $para['sign'];
|
||
unset($para['sign']);
|
||
$token = $this->pay_config['token'];
|
||
$signArr=[
|
||
'key'=>$token,
|
||
'pay_time'=>$para['pay_time'],
|
||
'money'=>$para['money'],
|
||
'pay_money'=>$para['pay_money'],
|
||
'order_sn'=>$para['order_sn'],
|
||
'sys_order_sn'=>$para['sys_order_sn'],
|
||
];
|
||
$md5sign = $this->sign($signArr);
|
||
if ($md5sign == $sign) {
|
||
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)
|
||
{
|
||
$this->setLogName($pay_type);
|
||
$this->debugLog('回调原始数据', $request->all());
|
||
$this->pay_type = $pay_type;
|
||
$this->request = $request;
|
||
//取得订单,是否有此订单,如果没有直接返回空
|
||
$order_sn = $request->input('order_sn');
|
||
|
||
$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->all();
|
||
//检查三方的订单
|
||
$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' => $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['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;
|
||
}
|
||
}
|