$paramArr['app_id'], 'game_id' => $data['user_id'], 'game_token' => $data['channel_token'], ]; $result = getHttpGet($this->open_url . 'game/user_info/v2', $param); $res = json_decode($result, true); if ($res['result'] == 1) { return $data['user_id']; } else { return false; } } // 登陆效验 public function checkLogin($data, $polyChannelGame = []) { return ['user_id' => $data['user_id']]; } // ## 下单 public function getOrder($data) { if (!$channelConfig = json_decode($data['channel_info']['param'], true)) { return false; } if(empty($data['extparam']) || empty($data['extparam']['user_id']) || empty($data['extparam']['channel_id'])){ return ['code' => -200, 'msg' => '登录失效,请重新登录!', 'param' => []]; } $requiredKeys = ['roleid', 'rolename', 'rolelevel', 'serverid', 'server_name', 'product_id', 'amount', 'notify_url']; $missingKeys = checkDataHasKeys($data, $requiredKeys); if (!empty($missingKeys)) { return ['code' => -200, 'msg' => '缺失参数:' . implode(', ', $missingKeys), 'param' => []]; } try { $param = [ "app_id" => $channelConfig['app_id'], "channel_id" => $data['extparam']['channel_id'], "game_id" => $data['extparam']['user_id'], "role_id" => $data['roleid'], "role_name" => $data['rolename'], "role_level" => $data['rolelevel'], "server_id" => $data['serverid'], "server_name" => $data['server_name'], "product_id" => $data['product_id'], "product_name" => $data['product_name']??'', "product_desc" => $data['product_desc']??'', "money" => formatYuanToFen($data['amount']), "currency_type" => 'CNY', "notify_url" => $data['notify_url'], "extension" => json_encode(['order_id' => $data['pay_info']['orderid']]), "user_ip" => $data['pay_info']['ip'], "third_party_trade_no" => $data['pay_info']['orderid'], ]; $param['sign'] = $this->handleSIgn($param, $this->getKeyData('pay')); }catch (Exception $e){ return ['code' => -200, 'msg' => $e->getMessage()]; } return ['code' => 200, 'msg' => 'success', 'param' => $param]; } // 回调订单参数 public function getData($data) { $orderData = json_decode($data['extension'], true); if(empty($orderData['order_id'])){ return false; } return [ 'orderid' => $orderData['order_id'],//我方聚合订单 'amount' => formatFenToYuan($data['money']), // 充值金额(单位:元) 'sub_orderid' => $data['allin_trade_no'],//渠道订单 ]; } // 回调效验 public function paySign($data, $polyChannelGame = []) { // 回调范例:{"app_id":"ks684828619578671316","role_id":"202005201314","server_id":"1","product_id":"kdzz_goods_001","money":"1","extension":"{\"order_id\":\"CMWL17452303393425188518\"}","allin_trade_no":"AI677228795252780746","data":"{\"environment\":\"PRODUCTION\"}","sign":"k0SSvITO06zSsC74nwWnePYe0cFyoneAlYeMGDSDx9ZZr4Lqal\/LWFRRMQbL1hxhQ4VcUpOyqpY+B5h7U1KsgO0gh\/6VQDK0ZbMrxP8RnGnalo5ua1d+FkiIYMcSlx\/5848XAC4GbHRCLUClAE+IQ4B4s6djxv5Usujvma\/4gIwW53TWJrbU+F3Pzi0G9arMoRFkl9fqgO1nEtSDeX8oZH1+cOHFoONIkZXa4z+Y7sErC0FuJHOKQSznzSa5iAcgEXqG1cfCvLo0nVRDoyJ\/AIb36GEerHzK0RomXd+5LrHyf\/zyE4VJzpgh\/JaslcSC7vQUf7MrqmJqDnHSHSCE4w=="} try { $requiredKeys = ['app_id', 'role_id', 'server_id', 'product_id', 'money', 'extension', 'allin_trade_no', 'sign']; $missingKeys = checkDataHasKeys($data, $requiredKeys); if (!empty($missingKeys)) { return "ERROR: 回调参数不匹配!"; } $param = [ 'app_id' => $data['app_id'], 'role_id' => $data['role_id'], 'server_id' => $data['server_id'], 'product_id' => $data['product_id'], 'money' => $data['money'], 'extension' => $data['extension'], 'allin_trade_no' => $data['allin_trade_no'], 'data' => $data['data']??'', 'notify_detail' => $data['notify_detail']??'', 'sign' => $data['sign'], ]; $result = $this->handleSignVerify($param, $this->getKeyData('notify'), $param['sign']); if ($result) { return true; } } catch (Exception $e){ return "ERROR: ".$e->getMessage(); } return false; } public function getFail($msg = '') { echo 'fail:'.$msg; exit(); } public function getSuccess($msg = '') { echo 'success'; exit(); } /** * 设置需要存储的数据 * * @param $input 请求参数 * @return array */ public function setParam($input){ if($input == '' || is_null($input)) return ""; return [ "user_id" => $input['user_id'], "channel_id" => $input['extparam'], ]; } /** * 获取签名秘钥 * * @param $type 类型 pay|notify * @return string */ public function getKeyData($type = 'pay') { $key_file = APP_PATH . 'common/config/complex/qm_private_key.pem'; if ($type == 'notify') { $key_file = APP_PATH . 'common/config/complex/kuaishou_public.pem'; } if (!file_exists($key_file)) { throw new Exception('签名秘钥文件不存在'); } return file_get_contents($key_file); } /** * 处理签名数据 * * @param $data * * @return string */ public function handleSignData($data){ ksort($data); $signString = ''; foreach ($data as $key => $value) { if($key == 'sign' || $value == ''){ continue; } if ($signString !== '') { $signString .= '&'; } $signString .= $key . '=' . $value; } return $signString; } /** * 使用 RSA 私钥 + SHA512 签名数组 * * @param array $data 要签名的数组 * @param string $privateKey 私钥内容(PEM格式) * @return string Base64 编码签名字符串 */ function handleSign(array $data, string $privateKey): string { $signString = $this->handleSignData($data); $pkey = openssl_pkey_get_private($privateKey); if (!$pkey) { throw new Exception('无效的 RSA 私钥'); } $signature = ''; $success = openssl_sign($signString, $signature, $pkey, OPENSSL_ALGO_SHA512); openssl_free_key($pkey); if (!$success) { throw new Exception('签名失败'); } // 6. 返回 Base64 编码后的签名 return base64_encode($signature); } /** * 签名效验 * * @param array $data * @param string $publicKey * @param string $signstr * * @return string */ function handleSignVerify(array $data, string $publicKey, string $signstr): string { $signString = $this->handleSignData($data); $public_key_res = openssl_get_publickey($publicKey); $res = openssl_verify($signString, base64_decode($signstr), $public_key_res, OPENSSL_ALGO_SHA512); if($res == 1){ return true; } return false; } }