100 lines
2.8 KiB
PHP
100 lines
2.8 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace app\adminapi\controller\order;
|
|
|
|
use app\common\model\Order;
|
|
use think\response\Json;
|
|
|
|
/**
|
|
* 支付宝支付回调控制器
|
|
* Class AlipayNotifyController
|
|
* @package app\adminapi\controller\order
|
|
*/
|
|
class AlipayNotifyController
|
|
{
|
|
/**
|
|
* @notes 支付宝异步通知
|
|
* @return string
|
|
*/
|
|
public function notify()
|
|
{
|
|
try {
|
|
// 获取支付宝配置
|
|
$alipayConfig = config('pay.alipay');
|
|
|
|
// 获取POST数据
|
|
$data = request()->post();
|
|
|
|
// 验证签名
|
|
if (!$this->verifyAlipaySign($data, $alipayConfig['alipay_public_key'])) {
|
|
return 'fail';
|
|
}
|
|
|
|
// 验证金额
|
|
$order = Order::where('order_no', $data['out_trade_no'])->find();
|
|
if (!$order) {
|
|
return 'fail';
|
|
}
|
|
|
|
if ((float)$data['total_amount'] != (float)$order->amount) {
|
|
return 'fail';
|
|
}
|
|
|
|
// 验证交易状态
|
|
if ($data['trade_status'] == 'TRADE_SUCCESS' || $data['trade_status'] == 'TRADE_FINISHED') {
|
|
// 更新订单状态
|
|
if ($order->status == 1) { // 只有待支付的订单才能更新
|
|
$order->status = 2; // 已支付
|
|
$order->payment_method = 'alipay';
|
|
$order->payment_time = date('Y-m-d H:i:s');
|
|
$order->trade_no = $data['trade_no'];
|
|
$order->save();
|
|
}
|
|
}
|
|
|
|
return 'success';
|
|
} catch (\Exception $e) {
|
|
return 'fail';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @notes 验证支付宝签名
|
|
* @param array $data
|
|
* @param string $publicKey
|
|
* @return bool
|
|
*/
|
|
private function verifyAlipaySign(array $data, string $publicKey): bool
|
|
{
|
|
try {
|
|
// 获取签名
|
|
$sign = $data['sign'] ?? '';
|
|
unset($data['sign']);
|
|
unset($data['sign_type']);
|
|
|
|
// 按键排序
|
|
ksort($data);
|
|
|
|
// 构建签名字符串
|
|
$signStr = '';
|
|
foreach ($data as $key => $value) {
|
|
if ($value !== '' && $value !== null) {
|
|
$signStr .= $key . '=' . $value . '&';
|
|
}
|
|
}
|
|
$signStr = rtrim($signStr, '&');
|
|
|
|
// 验证签名
|
|
$publicKeyResource = openssl_pkey_get_public($publicKey);
|
|
$result = openssl_verify($signStr, base64_decode($sign), $publicKeyResource, OPENSSL_ALGO_SHA256);
|
|
openssl_free_key($publicKeyResource);
|
|
|
|
return $result === 1;
|
|
} catch (\Exception $e) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|