mirror of
https://github.com/ProxyPanel/ProxyPanel.git
synced 2026-04-03 02:58:42 +00:00
Rewrite Alipay Notify logic
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
<?php
|
||||
/*
|
||||
* 作者:BrettonYe
|
||||
* 功能:ProxyPanel 支付宝面对面 【收单线下交易预创建】 【收单交易查询】 接口实现库
|
||||
* 时间:2022/12/28
|
||||
* 功能:ProxyPanel 支付宝面对面【收单线下交易预创建】【收单交易查询】接口实现库
|
||||
* 更新时间:2023/10/29
|
||||
* 参考资料:https://opendocs.alipay.com/open/02ekfg?scene=19 riverslei/payment
|
||||
*/
|
||||
|
||||
@@ -13,7 +13,7 @@ use RuntimeException;
|
||||
|
||||
class AlipayF2F
|
||||
{
|
||||
private static string $gatewayUrl = 'https://openapi.alipay.com/gateway.do';
|
||||
private static string $gatewayUrl = 'https://openapi.alipay.com/gateway.do'; //https://openapi-sandbox.dl.alipaydev.com/gateway.do
|
||||
|
||||
private array $config;
|
||||
|
||||
@@ -98,7 +98,7 @@ class AlipayF2F
|
||||
throw new RuntimeException('请求错误-看起来是请求失败');
|
||||
}
|
||||
|
||||
if (! $this->rsaVerify($response[$resKey], $response['sign'])) {
|
||||
if (! $this->validate_response_sign($response[$resKey], $response['sign'])) {
|
||||
throw new RuntimeException('验签错误-'.$response[$resKey]['msg'].' | '.($response[$resKey]['sub_msg'] ?? var_export($response, true)));
|
||||
}
|
||||
|
||||
@@ -113,14 +113,14 @@ class AlipayF2F
|
||||
private function buildParams(): array
|
||||
{
|
||||
$params = [
|
||||
'app_id' => $this->config['app_id'] ?? '',
|
||||
'method' => $this->config['method'] ?? '',
|
||||
'app_id' => $this->config['app_id'],
|
||||
'method' => $this->config['method'],
|
||||
'charset' => 'utf-8',
|
||||
'sign_type' => 'RSA2',
|
||||
'timestamp' => date('Y-m-d H:m:s'),
|
||||
'biz_content' => $this->config['biz_content'] ?? [],
|
||||
'biz_content' => $this->config['biz_content'],
|
||||
'version' => '1.0',
|
||||
'notify_url' => $this->config['notify_url'] ?? '',
|
||||
'notify_url' => $this->config['notify_url'],
|
||||
];
|
||||
$params = array_filter($params);
|
||||
$params['sign'] = $this->encrypt($this->buildQuery($params));
|
||||
@@ -155,21 +155,39 @@ class AlipayF2F
|
||||
}
|
||||
|
||||
/**
|
||||
* RSA2验签.
|
||||
* 同步返回验签.
|
||||
*
|
||||
* @param array $data 待签名数据
|
||||
* @param array $body 待签名数据
|
||||
*
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function rsaVerify(array $data, string $sign): bool
|
||||
public function validate_response_sign(array $body, string $sign): bool
|
||||
{
|
||||
unset($data['sign'], $data['sign_type']);
|
||||
unset($body['sign'], $body['sign_type']);
|
||||
$publicKey = openssl_pkey_get_public($this->config['public_key']);
|
||||
if (empty($publicKey)) {
|
||||
throw new RuntimeException('支付宝RSA公钥错误。请检查公钥文件格式是否正确');
|
||||
}
|
||||
|
||||
return (bool) openssl_verify(json_encode($data), base64_decode($sign), $publicKey, OPENSSL_ALGO_SHA256);
|
||||
return (bool) openssl_verify(json_encode($body), base64_decode($sign), $publicKey, OPENSSL_ALGO_SHA256);
|
||||
}
|
||||
|
||||
/**
|
||||
* 异步通知验签.
|
||||
*
|
||||
* @param array $body 待签名数据
|
||||
*
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function validate_notification_sign(array $body, string $sign): bool
|
||||
{
|
||||
unset($body['sign'], $body['sign_type']);
|
||||
$publicKey = openssl_pkey_get_public($this->config['public_key']);
|
||||
if (empty($publicKey)) {
|
||||
throw new RuntimeException('支付宝RSA公钥错误。请检查公钥文件格式是否正确');
|
||||
}
|
||||
|
||||
return (bool) openssl_verify($this->buildQuery($body), base64_decode($sign), $publicKey, OPENSSL_ALGO_SHA256);
|
||||
}
|
||||
|
||||
public function qrCharge(array $content): array
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Utils\Payments;
|
||||
|
||||
use App\Models\Payment;
|
||||
use App\Services\PaymentService;
|
||||
use App\Utils\Library\AlipayF2F;
|
||||
use App\Utils\Library\Templates\Gateway;
|
||||
@@ -14,16 +15,16 @@ use Response;
|
||||
|
||||
class F2Fpay extends PaymentService implements Gateway
|
||||
{
|
||||
private static array $aliConfig;
|
||||
private static AlipayF2F $aliClient;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
self::$aliConfig = [
|
||||
self::$aliClient = new AlipayF2F([
|
||||
'app_id' => sysConfig('f2fpay_app_id'),
|
||||
'ali_public_key' => sysConfig('f2fpay_public_key'),
|
||||
'rsa_private_key' => sysConfig('f2fpay_private_key'),
|
||||
'notify_url' => route('payment.notify', ['method' => 'f2fpay']),
|
||||
];
|
||||
]);
|
||||
}
|
||||
|
||||
public function purchase(Request $request): JsonResponse
|
||||
@@ -37,8 +38,7 @@ class F2Fpay extends PaymentService implements Gateway
|
||||
];
|
||||
|
||||
try {
|
||||
$gateWay = new AlipayF2F(self::$aliConfig);
|
||||
$result = $gateWay->qrCharge($data);
|
||||
$result = self::$aliClient->qrCharge($data);
|
||||
$payment->update(['qr_code' => 1, 'url' => $result['qr_code']]);
|
||||
} catch (Exception $e) {
|
||||
Log::alert('【支付宝当面付】支付错误: '.$e->getMessage());
|
||||
@@ -52,26 +52,47 @@ class F2Fpay extends PaymentService implements Gateway
|
||||
public function notify(Request $request): void
|
||||
{
|
||||
try {
|
||||
$result = (new AlipayF2F(self::$aliConfig))->tradeQuery($request->only('out_trade_no', 'trade_no'));
|
||||
Log::notice('【支付宝当面付】回调验证验证:'.var_export($result, true));
|
||||
if (sysConfig('f2fpay_app_id') === $request->input('app_id') && self::$aliClient->validate_notification_sign($request->except('method'), $request->input('sign'))) {
|
||||
$payment = Payment::whereTradeNo($request->input('out_trade_no'))->with('order')->first();
|
||||
if ($payment && abs($payment->amount - $request->input('total_amount')) < 0.01 && in_array($request->input('trade_status'), ['TRADE_FINISHED', 'TRADE_SUCCESS']) && $this->paymentReceived($request->input('out_trade_no'))) {
|
||||
exit('success');
|
||||
}
|
||||
}
|
||||
Log::error('【支付宝当面付】异步验证失败,尝试订单查询');
|
||||
if ($this->capture($request->input('out_trade_no'), $request->input('trade_no'))) {
|
||||
exit('success');
|
||||
}
|
||||
|
||||
Log::notice('【支付宝当面付】异步验证失败:'.var_export($request->all(), true));
|
||||
} catch (Exception $e) {
|
||||
Log::alert('【支付宝当面付】回调信息错误: '.$e->getMessage());
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($result['code'] === '10000' && $result['msg'] === 'Success') {
|
||||
if ($request->has('out_trade_no') && in_array($request->input('trade_status'), ['TRADE_FINISHED', 'TRADE_SUCCESS'])) {
|
||||
if ($this->paymentReceived($request->input('out_trade_no'))) {
|
||||
exit('success');
|
||||
}
|
||||
} else {
|
||||
Log::error('【支付宝当面付】交易失败:'.var_export($request->all(), true));
|
||||
}
|
||||
} else {
|
||||
Log::error('【支付宝当面付】验证失败:'.var_export($result, true));
|
||||
}
|
||||
|
||||
// 返回验证结果
|
||||
exit('fail');
|
||||
}
|
||||
|
||||
public function capture(string $trade_no = null, string $ali_trade_no = null): bool
|
||||
{
|
||||
$result = self::$aliClient->tradeQuery(array_filter([
|
||||
'out_trade_no' => $trade_no,
|
||||
'trade_no' => $ali_trade_no,
|
||||
]));
|
||||
|
||||
if ($result['code'] === '10000' && $result['msg'] === 'Success') {
|
||||
if ($result['out_trade_no'] && in_array($result['trade_status'], ['TRADE_FINISHED', 'TRADE_SUCCESS'])) {
|
||||
if ($this->paymentReceived($result['out_trade_no'])) {
|
||||
return true;
|
||||
}
|
||||
Log::error('【支付宝当面付】收单交易订单结算失败:'.var_export($result, true));
|
||||
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
Log::error('【支付宝当面付】收单交易查询失败:'.var_export($result, true));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user