回调 $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); } }