sifangpay/app/ServicePay/RongYiServices.php

357 lines
11 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

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

<?php
/**
* Created by PhpStorm.
* User: Yontal
* Date: 2020/10/20
* Time: 14:35
*/
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 RongYiServices 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 'http://103.223.122.125:12345';
}
//第二部配置支付信息payConfig
public function payConfig($type, $setConfig = [])
{
$config = [
'url' => $this->getGateUrl() . '/trade/pay',
'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 = [
'partnerid' => $accountId,//商户
'orderid' => strval($pay_data['out_trade_no']),//订单号
'payamount' => intval($pay_data['total_amount']) * 100, //支付金额为分
'notifyurl' => strval($this->pay_config['notify_url']),// //异步回调地址
'paytype' => $this->pay_gateway['mch_id'],//对应的三方通道
'version' => '1.0',
'payip' => '185.33.89.21',
'returnurl' => strval($this->pay_config['return_url']),//页面跳转通知
];
$sign = $this->sign($payData, $key);//签名
$payData['sign'] = $sign;
$this->debugLog('下单接口请求内容' . json_encode($payData, true), []);
return redirect()->away($this->pay_config['url'].'?'.http_build_query($payData));
}
private function sign($tempArr, $signKey){
$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 .= '&key=' . $signKey;
}
return md5($keyVal);
}
/**
* 检查订单
* @param $orderid
* @return bool|string
*/
private function checkOrder($orderid)
{
$url = $this->getGateUrl() . '/trade/query';
$payData = [
'orderid' => $orderid,
'partnerid' => $this->pay_gateway['app_id'],//商户号
'version' => '1.0'
];
$key = $this->pay_config['token'];
$payData['sign'] = $this->sign($payData, $key);
Log::channel('pay_order')->info('查询接口请求', $payData);
$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'] == '0'
&& isset($response['orderid']) && $response['orderid'] == $orderid
&& isset($response['orderstatus']) && in_array($response['orderstatus'],['1','4'])
) {
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['orderstatus']) && in_array($params['orderstatus'],['1','4'])
) {
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['partnerorderid'];
$queryOrder = $request['orderno'];
$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($queryOrder);
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['partnerorderid'],//我方订单号
'pay_order_sn' => $data['orderno'],//三方的订单号
'pay_money' => number_format($data['payamount']/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['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;
}
}