/** * 检查参数签名 */ function authSig($request) { $method = $request['m']; $param = $request['p']; if ($param['signature']) { $signature = $param['signature']; unset($param['signature']); $keys = array_keys($param); sort($keys); $s = ''; foreach ($keys as $key) { $value = $param[$key]; if (is_string($value) || is_numeric($value) || is_bool($value)) { $s .= '&' . $key . '=' . $value; } } $s = substr($s, 1) . $method . P_VERSION . '~@#1xdaf,dmuopamie%%123.'; $mysig = md5($s); if ($mysig != $signature) { glog::info("签名不对[{$mysig}]!=[{$signature}], " . json_encode($request), 'sign'); return array('s' => StatusCode::invalid_siginature, 'msg' => 'invalid signature'); } $timestamp = $param['timestamp']; if ($method == 'System.login') { // 手机设备时间和服务器时间可能有差异,所以第一次请求 System.login 时不验证时间。 return false; } // 1. 对 timestamp 做验证 与 服务器当前时间相差太多的 认为是不合法的请求 $now = getApp()->now; if (abs($now - $timestamp) > 300) { $ts1 = date('Y-m-d H:i:s', $now); $ts2 = date('Y-m-d H:i:s', $timestamp); glog::info("请求时间异常 server[{$ts1}], client[{$ts2}], " . json_encode($request), 'sign'); return false; return array('s' => StatusCode::invalid_request_time, 'msg' => 'invalid timestamp'); } // 2. 记录用户上次调用这个接口的时间戳,如果新的 timestamp <= old_timestamp 则认为是不合法的请求 $uid = getApp()->getuid(); $section_id = getApp()->getsec(); if ($uid && $section_id) { if (model_Util::inBlacklist($uid)) { //黑名单访问,禁止 glog::info("黑名单中玩家[{$uid}]访问分区[{$section_id}] " . json_encode($request), 'blacklist'); return array('s' => StatusCode::invalid_request_time, 'msg' => "uid[{$uid}] is in blacklist"); } try { $redis = DbConfig::getRedis('cache'); $timestamp_key = "sig_{$section_id}_{$uid}_{$method}"; $old_timestamp = $redis->get($timestamp_key); if (is_numeric($old_timestamp)) { // 手机端网络超时后重试,后台可能会收到两次同样时间戳的请求 所以 $timestamp == $old_timestamp 还是很有可能的 if ($timestamp < $old_timestamp) { $ts1 = date('Y-m-d H:i:s', $old_timestamp); $ts2 = date('Y-m-d H:i:s', $timestamp); glog::info("请求时间异常, 上次请求[{$ts1}], 本次请求[{$ts2}], " . json_encode($request), 'sign'); return false; return array('s' => StatusCode::outdated_siginature, 'msg' => 'outdated signature', 'debug' => "old_timestamp: {$old_timestamp}"); } else { $redis->multi(); $redis->set($timestamp_key, $timestamp); $redis->expire($timestamp_key, 360); $redis->exec(); return false; } } else { $redis->multi(); $redis->set($timestamp_key, $timestamp); $redis->expire($timestamp_key, 360); $redis->exec(); return false; } } catch (Exception $ex) { error_log("无法连接 cache redis "); return false; } } return false; } glog::info("没有签名," . json_encode($request), 'sign'); return array('s' => StatusCode::invalid_siginature, 'msg' => 'no signature'); }
/** * actionPayment * @author 符璨 * @param * pid * uid * appid * sec * transaction_id:订单id * cashier_id:支付单id * cash:支付金额 * status: * time:支付单生成时间戳 * product_id:购买产品编号 * product_cnt * sig:签名 * @return * s 状态码 * 100:玩家数据不存在 * 108:签名验证错误 * 11:product_id或其他原因引起的加载支付配置错误引发的异常 * ok:支付成功 * @desc * 提供给cashier服务器调用的支付接口 */ public function actionPayment() { $now = getApp()->now; //取出所有参数 $pid = $_POST['pid']; $uid = $_POST['uid']; $appid = $_POST['appid']; $transaction_id = $_POST['transaction_id']; $cashier = $_POST['cashier']; $cash = $_POST['cash']; $status = $_POST['status']; $create_t = $_POST['create_t']; $product_id = $_POST['product_id']; $product_cnt = $_POST['product_cnt']; $channel = $_POST['channel']; $channel_id = $_POST['channel_id']; $sec = $_POST['sec']; $isrepay = $_POST['isrepay']; //验证签名 $data = array('pid' => $pid, 'uid' => $uid, 'appid' => $appid, 'channel' => $channel, 'channel_id' => $channel_id, 'sec' => $sec, 'transaction_id' => $transaction_id, 'cashier' => $cashier, 'cash' => $cash, 'status' => $status, 'create_t' => $create_t, 'product_id' => $product_id, 'product_cnt' => $product_cnt, 'isrepay' => $isrepay); ksort($data); $sig = md5(http_build_query($data) . '171ca1475ffcd016fca228cd716f14b7'); if ($sig != $_POST['sig']) { echo json_encode(array('s' => StatusCode::invalid_siginature)); return; } //加锁避免重复处理 $redis = DbConfig::getRedis('rank'); $lock_key = "payment_{$transaction_id}"; $lock_res = $redis->SETNX($lock_key, $now); if ($lock_res) { //60秒过期 $redis->SETEX($lock_key, 60, $now); } else { echo json_encode(array('s' => StatusCode::can_not_do)); return; } //判断账单是否处理避免重复处理 $mon = getApp()->getPaymentMongoConnection(); $order = $mon->findOne(array('transaction_id' => $transaction_id)); if ($order) { echo json_encode(array('s' => StatusCode::ok)); return; } unset($data['time']); unset($data['uid']); //$data['cashier_t'] = $cashier_t; $data['process_t'] = $now; $data['_u'] = is_numeric($uid) ? intval($uid) : $uid; $data['action'] = 'recharge_gem'; $data['_sec'] = $data['sec']; $data['_tm'] = $data['create_t']; $player = new model_Player($uid, $sec); $user_data = $player->getFields(array('level', 'vip.lvl', 'gem')); $data['_lvl'] = $user_data['level']; $data['_vip'] = $user_data['vip']['lvl']; $data['ogem'] = $user_data['gem']; $data['order_id'] = $transaction_id; if ($data['channel'] == "zongle") { //需求使用纵乐sdk发布cps包 by zhangjun $data['source'] = $data['channel'] . $data['channel_id']; } else { $data['source'] = $data['channel']; } //根据pid获取uid并生成用户session PL_Session::$usecookie = false; $_REQUEST['cid'] = PL_Session::gencid($uid, $sec); //uid非法 if (!$uid || $uid < 0) { //玩家不存在 glog::info("异常的支付数据[uid:{$uid}][section_id:{$sec}][transaction_id:{$transaction_id}][product_id:{$product_id}]", 'payment'); echo json_encode(array('s' => StatusCode::exception)); return; } try { $player = getApp()->getPlayer(); } catch (Exception $e) { //玩家不存在 glog::info("异常的支付数据[uid:{$uid}][section_id:{$sec}][transaction_id:{$transaction_id}][product_id:{$product_id}]", 'payment'); echo json_encode(array('s' => StatusCode::exception, 'msg' => 'error1')); return; } $data['cash'] = $data['cash'] / 100; //cash通知单位是分 if ($channel == 'wanpay_web') { $this->processWanpay($data); } $ret = $player->process_payment($data, true, $data['cash']); $redis->DEL($lock_key); echo json_encode($ret); }
/** * @auther lifei@playcarb.com * 发放燕子坞活动 未领奖励 */ public static function action_award_yanziwu() { $app = getApp(); $now = $app->now; //活动界面关闭后才发送奖励 $config = $app->getActivityConfig('act_yanziwuqiangqin_20130425'); if ($now <= $config['end_t']) { //self::showError("",__LINE__); self::showError("activity not finished!", __LINE__); } $sections = array_keys(getApp()->getSectionConfig()); if (empty($sections)) { self::showError("get section config error!", __LINE__); } $start_md = date('md', $config['start_t']); $redis = DbConfig::getRedis('rank'); //时间肯定超过12、21、24了不判断时间 //所有区 foreach ($sections as $sec) { echo "===============分区:{$sec}==========================\n"; //检查各个时段的排行榜奖励 for ($i = 1; $i <= 3; $i++) { $redis_key = "act_yanziwuqiangqin_" . $start_md . "_" . $sec . "_" . $i; //查询各个时段排行榜 $list = self::getQiangQinRank(0, 19, $redis, $redis_key, $config, $sec); if (empty($list)) { echo "warning:第{$i}段,分区:{$sec}的排行为空!\n"; continue; } echo "=============当前时段:{$i}============="; echo $redis_key . "\n"; print_r($list); foreach ((array) $list as $v) { //判断玩家是否领取过 $uid = $user_key = $v['id']; $player = new model_Player($uid, $sec); //玩家存的是带年的 $start_ymd = date('Ymd', $config['start_t']); $player_data = $player->getFields(array('qiyu.yanziwuqiangqin_' . $start_ymd)); $player_pos = $player_data['qiyu']['yanziwuqiangqin_' . $start_ymd]; if (!empty($player_pos[$i])) { //领过了 echo "warning:====玩家{$uid}/{$sec}领过第{$i}段奖励了!\n"; continue; } //判断奖励 //玩家自己的排名 $rank = $redis->zrevrank($redis_key, "{$user_key}"); echo "====玩家{$uid}/{$sec}===当前排名:{$rank}\n"; if ($rank === false) { echo "warning:====玩家{$uid}/{$sec}排名错误为假!\n"; continue; } // 确定该玩家是否在前20,计算并列20的情况 $my_num = 0; if ($rank >= 20) { // 玩家自己的积分 $my_num = $redis->zscore($redis_key, $user_key); // 玩家正好与第20名的积分相同 if ($my_num == $list[count($list) - 1]['num']) { // 奖励list中最后一名相同的奖励 $award_config = PL_Config_Numeric::get('yanziwuaward', $list[count($list) - 1]['rank'], false); } } else { // 如果在前20名,那么list中一定存在该玩家信息 foreach ($list as $val) { if ($val['id'] == $uid) { $my_rank = $val['rank']; $my_num = $val['num']; } } $award_config = PL_Config_Numeric::get('yanziwuaward', $my_rank, false); } //24点必须大于2000 if ($i == 3 && $my_num < 2000) { continue; } echo "{$sec}=={$uid}开始发第{$i}段奖..\n"; $log['action'] = __CLASS__ . '.' . __FUNCTION__; //print_r($award_config); self::awardQiangQin($award_config, $i, $my_num, $player_pos, &$player, $config, &$log, $rank, $uid, $sec); // 标记已经领取 $player_pos[$i] = 1; $player->objectPut('qiyu', 'yanziwuqiangqin_' . date('Ymd', $config['start_t']), $player_pos); $result = $player->commit(); $log['ret'] = $result; glog::stat($log); } //print_r($list); } } }