198 lines
7.1 KiB
PHP
198 lines
7.1 KiB
PHP
|
|
<?php
|
|||
|
|
// 页面跳转通知处理
|
|||
|
|
$config = include('config.php');
|
|||
|
|
|
|||
|
|
// 使用 $_GET 获取回调参数
|
|||
|
|
$pid = $_GET['pid'] ?? '';
|
|||
|
|
$trade_no = $_GET['trade_no'] ?? '';
|
|||
|
|
$out_trade_no = $_GET['out_trade_no'] ?? '';
|
|||
|
|
$type = $_GET['type'] ?? '';
|
|||
|
|
$name = $_GET['name'] ?? '';
|
|||
|
|
$money = $_GET['money'] ?? '';
|
|||
|
|
$trade_status = $_GET['trade_status'] ?? '';
|
|||
|
|
$sign_from_request = $_GET['sign'] ?? null;
|
|||
|
|
$sign_type = $_GET['sign_type'] ?? 'MD5';
|
|||
|
|
|
|||
|
|
// 记录回调请求的参数,便于调试
|
|||
|
|
error_log('Callback received: ' . json_encode($_GET));
|
|||
|
|
|
|||
|
|
// 验证签名
|
|||
|
|
if (validateSign($_GET, $config['api_key'])) {
|
|||
|
|
if ($trade_status == 'TRADE_SUCCESS') {
|
|||
|
|
// 处理支付成功的逻辑
|
|||
|
|
$api_response = set_order_success($out_trade_no);
|
|||
|
|
$message = '支付成功';
|
|||
|
|
$alert_class = 'alert-success';
|
|||
|
|
$icon = 'fas fa-check-circle';
|
|||
|
|
$additional_info = '感谢您的支付!您的订单已成功处理。';
|
|||
|
|
$button_text = '返回主页';
|
|||
|
|
$button_link = '/';
|
|||
|
|
} else {
|
|||
|
|
// 支付失败或状态异常
|
|||
|
|
$message = '支付失败';
|
|||
|
|
$alert_class = 'alert-danger';
|
|||
|
|
$icon = 'fas fa-exclamation-circle';
|
|||
|
|
$additional_info = '您的订单号:' . htmlspecialchars($out_trade_no) . '<br>支付过程中出现了问题,请发送工单联系管理员处理。';
|
|||
|
|
$button_text = '联系管理员';
|
|||
|
|
$button_link = 'mailto:pghkipy@gmail.com';
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
// 签名验证失败
|
|||
|
|
$message = '签名无效';
|
|||
|
|
$alert_class = 'alert-danger';
|
|||
|
|
$icon = 'fas fa-exclamation-circle';
|
|||
|
|
$additional_info = '签名验证失败,请联系管理员。';
|
|||
|
|
$button_text = '联系管理员';
|
|||
|
|
$button_link = 'mailto:pghkipy@gmail.com';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// HTML 页面开始
|
|||
|
|
?>
|
|||
|
|
<!DOCTYPE html>
|
|||
|
|
<html lang="zh">
|
|||
|
|
<head>
|
|||
|
|
<meta charset="UTF-8">
|
|||
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|||
|
|
<title>支付结果 - DokiDoki CDN 心跳网络</title>
|
|||
|
|
<!-- Bootstrap v4.6 CSS -->
|
|||
|
|
<link rel="stylesheet" href="https://www.dnm.ink/www/assets/bootstrap.min.css" crossorigin="anonymous">
|
|||
|
|
<!-- Font Awesome for icons -->
|
|||
|
|
<link rel="stylesheet" href="https://www.dnm.ink/www/assets/fontawesome-free-5.15.4-web/css/all.min.css"/>
|
|||
|
|
<link rel="shortcut icon" href="https://www.dnm.ink/www/images/icon.png"/>
|
|||
|
|
<style>
|
|||
|
|
body {
|
|||
|
|
background: linear-gradient(180deg, #f0e7ff 0%, #e6d9ff 100%);
|
|||
|
|
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
|||
|
|
color: #333;
|
|||
|
|
line-height: 1.6;
|
|||
|
|
transition: background 0.3s ease;
|
|||
|
|
}
|
|||
|
|
.container {
|
|||
|
|
padding-top: 50px;
|
|||
|
|
text-align: center;
|
|||
|
|
}
|
|||
|
|
.card {
|
|||
|
|
border: none;
|
|||
|
|
border-radius: 15px;
|
|||
|
|
box-shadow: 0 6px 25px rgba(0, 0, 0, 0.05);
|
|||
|
|
background: linear-gradient(145deg, #fff, #f8f9ff);
|
|||
|
|
margin: 0 auto;
|
|||
|
|
max-width: 500px;
|
|||
|
|
padding: 20px;
|
|||
|
|
}
|
|||
|
|
.btn-primary {
|
|||
|
|
background: linear-gradient(135deg, #3176d6, #5b95e8);
|
|||
|
|
border: none;
|
|||
|
|
border-radius: 30px;
|
|||
|
|
padding: 12px 35px;
|
|||
|
|
font-weight: 600;
|
|||
|
|
box-shadow: 0 4px 15px rgba(49, 118, 214, 0.2);
|
|||
|
|
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|||
|
|
}
|
|||
|
|
.btn-primary:hover {
|
|||
|
|
background: linear-gradient(135deg, #255ca3, #4b7bc8);
|
|||
|
|
transform: translateY(-2px);
|
|||
|
|
box-shadow: 0 6px 20px rgba(49, 118, 214, 0.3);
|
|||
|
|
}
|
|||
|
|
.alert {
|
|||
|
|
border-radius: 15px;
|
|||
|
|
font-size: 1.1rem;
|
|||
|
|
padding: 20px;
|
|||
|
|
}
|
|||
|
|
.alert-success {
|
|||
|
|
background: linear-gradient(145deg, #d4edda, #c3e6cb);
|
|||
|
|
color: #155724;
|
|||
|
|
}
|
|||
|
|
.alert-danger {
|
|||
|
|
background: linear-gradient(145deg, #f8d7da, #f5c6cb);
|
|||
|
|
color: #721c24;
|
|||
|
|
}
|
|||
|
|
</style>
|
|||
|
|
</head>
|
|||
|
|
<body>
|
|||
|
|
<div class="container">
|
|||
|
|
<div class="card">
|
|||
|
|
<div class="alert <?php echo $alert_class; ?>" role="alert">
|
|||
|
|
<i class="<?php echo $icon; ?> mr-2"></i> <?php echo $message; ?>
|
|||
|
|
</div>
|
|||
|
|
<p class="text-muted"><?php echo $additional_info; ?></p>
|
|||
|
|
<a href="<?php echo $button_link; ?>" class="btn btn-primary mt-3"><?php echo $button_text; ?></a>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
<!-- Bootstrap JS and dependencies -->
|
|||
|
|
<script src="https://www.dnm.ink/www/assets/jquery.slim.min.js" crossorigin="anonymous"></script>
|
|||
|
|
<script src="https://www.dnm.ink/www/assets/popper.min.js" crossorigin="anonymous"></script>
|
|||
|
|
<script src="https://www.dnm.ink/www/assets/bootstrap.min.js" crossorigin="anonymous"></script>
|
|||
|
|
</body>
|
|||
|
|
</html>
|
|||
|
|
<?php
|
|||
|
|
// 结束 PHP 代码
|
|||
|
|
|
|||
|
|
// 以下是辅助函数
|
|||
|
|
function validateSign($received_params, $api_key) {
|
|||
|
|
$original_sign = $received_params['sign'] ?? null;
|
|||
|
|
if ($original_sign === null) {
|
|||
|
|
error_log('签名验证失败:URL中缺少 "sign" 参数。');
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
$calculated_sign = generateSign($received_params, $api_key);
|
|||
|
|
if ($calculated_sign === $original_sign) {
|
|||
|
|
return true;
|
|||
|
|
} else {
|
|||
|
|
error_log('签名验证失败:计算签名与原始签名不匹配。');
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function generateSign($params, $key) {
|
|||
|
|
ksort($params);
|
|||
|
|
$signStr = '';
|
|||
|
|
foreach ($params as $k => $v) {
|
|||
|
|
if ($k != "sign" && $k != "sign_type" && $v !== '' && $v !== null) {
|
|||
|
|
$signStr .= $k . '=' . $v . '&';
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
$signStr = rtrim($signStr, '&');
|
|||
|
|
$signStr .= $key;
|
|||
|
|
return md5($signStr);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function set_order_success($order_no){
|
|||
|
|
global $config;
|
|||
|
|
$auth_info = [
|
|||
|
|
"type"=> "admin",
|
|||
|
|
"accessKeyId"=> $config['goedge_access_id'],
|
|||
|
|
"accessKey"=> $config['goedge_access_key']
|
|||
|
|
];
|
|||
|
|
$access_token_json = sendPostJson($config['goedge_api_url']."/APIAccessTokenService/getAPIAccessToken",json_encode($auth_info,true),"none");
|
|||
|
|
$access_token_obj = json_decode($access_token_json,true);
|
|||
|
|
if (isset($access_token_obj['data']['token'])) {
|
|||
|
|
$token = $access_token_obj['data']['token'];
|
|||
|
|
$code = ["code"=>$order_no];
|
|||
|
|
$finish_order = sendPostJson($config['goedge_api_url']."/UserOrderService/finishUserOrder",json_encode($code,true),$token);
|
|||
|
|
return $finish_order;
|
|||
|
|
} else {
|
|||
|
|
error_log("获取 access token 失败: " . $access_token_json);
|
|||
|
|
return "获取 access token 失败: " . $access_token_json;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function sendPostJson($url, $json_data, $token) {
|
|||
|
|
$ch = curl_init($url);
|
|||
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|||
|
|
curl_setopt($ch, CURLOPT_POST, true);
|
|||
|
|
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
|
|||
|
|
'Content-Type: application/json',
|
|||
|
|
'Content-Length: ' . strlen($json_data),
|
|||
|
|
'X-Edge-Access-Token: ' . $token
|
|||
|
|
));
|
|||
|
|
curl_setopt($ch, CURLOPT_POSTFIELDS, $json_data);
|
|||
|
|
$response = curl_exec($ch);
|
|||
|
|
if (curl_errno($ch)) {
|
|||
|
|
error_log('cURL Error in sendPostJson to ' . $url . ': ' . curl_error($ch));
|
|||
|
|
return "cURL Error: " . curl_error($ch);
|
|||
|
|
}
|
|||
|
|
curl_close($ch);
|
|||
|
|
return $response;
|
|||
|
|
}
|
|||
|
|
?>
|