hxp
2025-06-09 6c3f6335c70859ded94a1ad8d218acb0ac34239c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
<?php
include_once '/Common/CommFunc.php';
include_once '/Common/Logging.php';
include_once '/Common/Signature.php';
include_once '/Common/PayOrder.php';
include_once "/ProjComm/CfgReader.php";
include_once "/db/DBOper.php";
 
header("Content-type: text/html; charset=utf-8");
// https://open.x7sy.com/sdk_resources/documentDetails?document_id=8
// 二、【游戏支付】与【游戏支付回调】流程 -> 回调
 
$pre = "pay";
// $_SERVER['PHP_SELF'] = /api/x7/$prexxxxx.php
// strripos 最后一次出现 / 的位置,再+1得到 $prexxxxx.php
// +$pre长度   从$pre后面开始
// -4   去除最后的.php
$appid = substr($_SERVER['PHP_SELF'], strripos($_SERVER['PHP_SELF'], "/") + 1 + strlen($pre), -4);
\Logging\CreateLogging("x7." . $pre . $appid . ".php");
 
\Logging\LogInfo("_POST: " . print_r($_POST, true));
 
$encryp_data = $_POST['encryp_data'];
$extends_info_data = $_POST['extends_info_data'];
$game_area = $_POST['game_area'];
$game_level = $_POST['game_level'];
$game_orderid = $_POST['game_orderid'];
$game_role_id = $_POST['game_role_id'];
$game_role_name = $_POST['game_role_name'];
$sdk_version = $_POST['sdk_version'];
$subject = $_POST['subject'];
$xiao7_goid = $_POST['xiao7_goid']; // 游戏订单在【小7服务器】中的唯一标识,由于这个是【小7服务器】订单中的唯一标识,建议游戏厂商在游戏方中保存当前字段内容用来标识当前的订单
$sign_data = $_POST['sign_data']; // RSA 签名,是将除了当前参数 sign_data 之外的所有参数,根据键名 的正序形式组成的 url。
 
if (!$encryp_data || !$game_area || !$game_level || !$game_orderid || !$game_role_id || !$game_role_name || !$subject || !$xiao7_goid || !$sign_data) {
    Ret("ParamError");
    exit;
}
 
if (!\CfgReader\ReadConfig() || !\CfgReader\GetConfigData("x7", "Pubkey_" . $appid, $pubkey)) {
    Ret("CfgError");
    exit;
}
 
// 1)对 sign_data 进行签名验证;
//     验签步骤:
//     1. 将接收到的sign_data参数进行base64_decode得到【raw_sign_data】
//     2. 将除sign_data以外的其他参数按字典序正序排列,再拼接成查询字符串【source_str】,形如:key=value&key=value(无需urlencode)
//     3. 将【raw_sign_data】【source_str】与【小7RSA公钥】参数使用签名算法 “SHA1withRSA”(Java,java.security.Signature类)或 “OPENSSL_ALGO_SHA1”(PHP,openssl_verify函数)进行签名verify验证
$source_str = "encryp_data=" . $encryp_data . "&extends_info_data=" . $extends_info_data . "&game_area=" . $game_area
    . "&game_level=" . $game_level . "&game_orderid=" . $game_orderid . "&game_role_id=" . $game_role_id . "&game_role_name=" . $game_role_name
    . "&sdk_version=" . $sdk_version . "&subject=" . $subject . "&xiao7_goid=" . $xiao7_goid;
if (Signature::verify($source_str, $sign_data,  $pubkey, OPENSSL_ALGO_SHA1) != 1) {
    Ret("sign_data_verify_failed");
    exit;
}
 
// 2)解密 encryp_data 得到关键数据;这一步解密 encryp_data 将会得到类似这样的字符串 game_orderid= 订单号&guid=游戏用户唯一标识&pay_price=商品金额 
//     解密步骤:
//         1. 将接收到的【encryp_data】进行base64_decode得到【raw_encryp_data】
//         2. 使用小7RSA公钥对【raw_encryp_data】进行解密(php: openssl_public_decrypt, java: javax.crypto.Cipher)得到查询字符串(key=value&key=value..)
$raw_encryp_data = base64_decode($encryp_data);
if (!openssl_public_decrypt($raw_encryp_data, $decrypted_data, Signature::formatRsaPublicKey($pubkey))) {
    Ret("encryp_data_decrypt_failed", "decrypt false");
    exit;
}
// game_orderid    String    游戏订单号    2018182571972272
// pay_price    Float    商品原价(精确到小数点后面两位)    1.00
// guid    Integer    标识用户在小 7 平台中的唯一标 识    1219663
$decryptedKVData = array();
$kvlist = explode("&",  $decrypted_data);
if (isset($kvlist)) {
    foreach ($kvlist as $value) {
        $kv = explode("=",  $value);
        if (!$kv || count($kv) != 2) {
            Ret("encryp_data_decrypt_failed", "kverror:" . $value);
            exit;
        }
        $decryptedKVData[$kv[0]] = $kv[1];
    }
}
\Logging\LogInfo("decryptedKVData: " . print_r($decryptedKVData, true));
if (
    !array_key_exists("game_orderid", $decryptedKVData)
    || !array_key_exists("pay_price", $decryptedKVData)
    || !array_key_exists("guid", $decryptedKVData)
) {
    Ret("encryp_data_decrypt_failed");
    exit;
}
 
$orderID = $game_orderid;
$serverID = intval($game_area);
$pay_time = "";
$AccountID = ""; // 此处不传,事先创建订单的db中有
$OrderInfo = ""; // 此处不传,事先创建订单的db中有
$amount = ""; // 此处不传,事先创建订单的db中有
$returnArr = \PayOrder\DoReceivePayOrder($appid, $orderID, $xiao7_goid, $AccountID, $serverID, $OrderInfo, $amount, $pay_time, true, "CheckPayx7bt5");
 
$success = "success";
$failed = "failed:order error";
$result = $failed;
$msg = "";
 
switch ($returnArr["errorcode"]) {
    case 1:
        $result = $success;
        break;
    case 2:
        $result = $success;
        break;
    default:
        if ($returnArr["errordesc"]) {
            $msg = $returnArr["errordesc"];
        }
        break;
}
Ret($result, $msg);
exit;
 
/**
 * x7bt5充值回调额外检查
 */
function CheckPayx7bt5($dbOrderInfo)
{
    global $xiao7_goid, $game_area, $decryptedKVData;
    if ($dbOrderInfo["ServerID"] != $game_area) {
        return "failed:game_area error";
    }
 
    if ($dbOrderInfo["OrderID"] != $decryptedKVData["game_orderid"]) {
        return "failed:game_orderid error";
    }
 
    if ($dbOrderInfo["OrderAmount"] != $decryptedKVData["pay_price"]) {
        return "failed:pay_price error";
    }
 
    if ($dbOrderInfo["AccountID"] != $decryptedKVData["guid"]) {
        return "failed:guid error";
    }
 
    if ($dbOrderInfo["State"] == 1) {
        if ($dbOrderInfo["OrderIDSDK"] != $xiao7_goid) {
            return "failed:xiao7_goid error";
        }
    }
    return "";
}
 
function Ret($ret, $msg = "")
{
    global $success;
    echo $ret;
    $logMsg = $ret;
    if ($msg) {
        $logMsg .= " msg => " . $msg;
    }
    if ($ret != $success) {
        \Logging\LogError($logMsg);
    } else {
        \Logging\LogInfo($logMsg);
    }
}