sifangpay/app/ServicePay/UnionpayServices.php

290 lines
9.3 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
namespace App\ServicePay;
use App\Models\Merchant;
use App\Models\Order;
use Illuminate\Support\Facades\Log;
use Yansongda\Pay\Pay;
use Yansongda\Pay\Gateways\Wechat\Support;
use Illuminate\Support\Collection;
use Illuminate\Http\Request;
use Ixudra\Curl\Facades\Curl;
use Omnipay;
class UnionpayServices implements PayApiInterface
{
use PayTrait;
public $gateway_list;//当前类型的支付通道列表
public $pay_type;//支付类型
public $pay_method;//支付方法
public $pay_gateway;//当前的支付通道实例
public $pay_config;//这个通道的支付配置信息
public $pay_model;//支付接口实例模型
public $order;
public $request;
public $gateway_id;
public $pay_data;
public $log_name;
public $result_data;
public static $result;
//支付发起第一步取得通道getGateway随机通道第二部配置支付信息payConfig,第三部发起支付
//取得通道getGateway
public function getGateway($pay_type, $custom_gateways = [])
{
//取得支付方法和类型
$pay_config = $this->payMethod($pay_type);
$this->pay_type = $pay_config['pay_type'];
$this->pay_method = $pay_config['method'];
//取得配置通道文件
$this->gateway_list = config('gateway.' . $this->pay_type);
$this->checkGatewayConfig();
if (count(self::$errorArr) > 0) {
return false;
}
//当前的支付类型方法的通道,比如扫码支付,有多个这样子
$all_gateways = $this->gateway_list[$this->pay_method];
//当前用户是否指定了支付通道
try {
if (!is_array($custom_gateways)) {
return false;
}
if (count($custom_gateways) > 0) {
$this->pay_gateway = $this->randomCustomGateways($all_gateways, $custom_gateways);
} else {
$this->pay_gateway = $this->randomAllGateways($all_gateways);
}
//dump($this->pay_gateway);
return $this->pay_gateway;//支付数据库信息
} catch (\Exception $e) {
return false;
}
}
/**
* 检查通道是否存在错误
*/
public function checkGatewayConfig()
{
$pay_method = $this->pay_method;
if (count($this->gateway_list) <= 0) {
self::addError(['msg' => '通道支付不存在']);
}
if (!isset($this->gateway_list[$pay_method])) {
self::addError(['msg' => '通道支付类型不存在']);
}
}
//第二部配置支付信息payConfig
public function payConfig($type, $setConfig = [])
{
//将支付配置模型赋值给$this->pay_model发起支付的时候使用
$gateway = Omnipay\Omnipay::create('UnionPay_Express');
$gateway->setMerId($this->pay_gateway['app_id']); //商户号
//to_linux_path(public_path()) .
$cert_key = to_linux_path(public_path()) . $this->pay_gateway['cert_key'];
//dd($cert_key);
$gateway->setCertPath($cert_key); // 商户私钥证书
//$gateway->setCertDir( $this->pay_gateway['cert_pub']); //测试环境银联公钥证书
//$gateway->setCertPath(to_linux_path(public_path()) . '/certs/700000000000001_acp.p12'); // 商户私钥证书
$gateway->setCertDir(to_linux_path(app_path()) . '/certs/verify_sign_acp.cer'); //测试环境银联公钥证书
//dump($this->pay_gateway['cert_pub']);
$gateway->setPublicKey(to_linux_path(public_path()) . $this->pay_gateway['cert_pub']); // path or content
$gateway->setReturnUrl(action('Pay\PayController@returnNotify', ['type' => $type])); // 支付后同步通知页面地址
$gateway->setNotifyUrl(action('Pay\PayController@notify', ['type' => $type]));
// dd($this->pay_gateway['app_key']);
$gateway->setCertPassword($this->pay_gateway['app_key']); // 密码
$this->pay_model = $gateway;
}
//统一下单支付
public function pay($pay_data)
{
//dd($pay_data);
$response = $this->pay_model->purchase($pay_data)->send();
$response->redirect(); // 发起银联支付请求
}
//统一验证签名
public function verify()
{
$response = $this->pay_model->completePurchase(['request_params' => $this->request->all()])->send();
$this->result_data = $response->getData();
return $response->isPaid();
}
//返回给支付商的成功
public function success()
{
return 'success';
}
//统一回调处理
/**
* 回调第一部,如果是同步,直接回传
* @param $return
* @param $pay_type
* @param $request
* @return bool|\Illuminate\Http\RedirectResponse
*/
public function notify($return, $pay_type, $request)
{
$this->request = $request;
$this->pay_type = $pay_type;
$this->setLogName($this->pay_type);
// self::$result = $request->all();
// self::$result['pay_order_sn'] = $request->input('queryId');
//取得订单
$this->getOrder($this->request->input('orderId'));
if ($return) {
//return $this->unionPayNotify();
return $this->returnUnionPay();
}
return $this->unionPayNotify();
}
/**
* 取得订单,支付宝和微信返回的订单号都有差异,需要分开处理
* @param $order_sn
*/
public function getOrder($order_sn)
{
$this->order = Order::where('order_sn', $order_sn)->first();
$this->pay_method = $this->order->gateway_method;//支付方法
$this->gateway_id = $this->order->gateway_id;//通道ID
$this->merchant = Merchant::find($this->order->merchant_id);
}
/**
* 同步回调
* @return \Illuminate\Http\RedirectResponse
*/
public function returnUnionPay()
{
//判断是否是商户id
if ($this->order->merchant_id == 0) {
return redirect()->route('web.user.index');
}
//
return $this->merchantReturnSend();
}
//异步回调
/**
* 获得通道信息,取得支付配置模型,验证签名,
* @return bool|void
*/
public function unionPayNotify()
{
//取得通道信息内容
$this->gateway = $this->pay_gateway = config('gateway.config')[$this->gateway_id];
//加载通道的支付配置信息
//这里取得支付实例化$this->pay_model
$this->payConfig($this->pay_type);
//验证签名
if (!$this->verify()) {
$this->debugLog('订单验证签名失败', $this->request->all());
return false;
}
$data = $this->result_data;
$this->pay_data = $this->result_data;
//如果应答状态不是01/A6表示支付失败
if (!in_array($data['respCode'], ['00', 'A6'])) {
$this->debugLog('订单支付失败', $this->request->all());
return false;//支付失败
}
$this->debugLog('-------------' . $this->order->order_sn . '--选择----' . $this->pay_type . '----' . $this->pay_method . '----开始回调处理-------------------------');
if (empty($data)) {
return $this->debugLog('验证签名失败', $this->request->all());
}
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());
if (!in_array($data['respCode'], ['00', 'A6'])) {
$this->debugLog('订单支付失败', $this->request->all());
return false;//支付失败
}
$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['queryId'],
'pay_money' => $data['settleAmt'] / 100,//单位分需要/100等于元
'pay_type' => 'unionpay',
'account' => $data['accNo']
];
// dd($result);
$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)
{
$name = '';
switch ($pay_type) {
case 'unionpay':
$name = 'unionpay_';
break;
}
$this->log_name = $name;
}
}