PayProc.php 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662
  1. <?php
  2. namespace loyalsoft;
  3. require_once ROOTDIR . '/Process/PayProc/MLogType.php'; // 日志类型定义
  4. if (PLAT == 'web') {
  5. include_once ROOTDIR . '/Process/PayProc/WebPayProc.php';
  6. }
  7. //include_once ROOTDIR . '/Process/PayProc/YuanBaoPayProc.php';
  8. //include_once ROOTDIR . '/Process/StoreProc.php';
  9. /**
  10. * 付费、游戏内消费相关处理
  11. * 全部动态交易数据需要保存到db作为[存根]
  12. * @version <br/>
  13. * 2.2.0 第三版: 独立的游戏币<元宝>, 面向多渠道的充值模式, 拉起充值成功后, 给玩家发放元宝. 游戏内部消费元宝,钻石和金币.可以用元宝购买金币和钻石.这一版在上面的PayProc中 * 2015年9月23日 <br/>
  14. * 2.1.0 mn_pay mn_AddUserCash ... 以 mn_ 打头的函数是第二版, 修改为伪托管模式,除了充值的时候跟腾讯通讯,其余时间自己管理游戏币:钻石. * 2015年7月23日 <br/>
  15. * 2.0.1 m_pay m_AddUserCash ... 以 m_ 打头的函数是第一版, 完全按照应用宝官方要求托管游戏币的模式开发的. * 2015年4月23日 <br/>
  16. * 1.0.0 Created at 2016-4-20. by --gwang <br/>
  17. * @author gwang (mail@wanggangzero.cn)
  18. * @copyright © 2016-4-20, SJZ LoyalSoft Corporation & gwang. All rights reserved.
  19. */
  20. class PayProc {
  21. const orderTab = 'tpl_order_tab';
  22. /**
  23. * 逻辑分发
  24. * 所有的Proc中必须有这样一个方法
  25. * @param Req $req
  26. */
  27. public static function procMain($req) {
  28. switch ($req->cmd) {
  29. // 支付相关的活动
  30. case CmdCode::cmd_pay_getfirstpaygift: # 8802 领取首充礼包
  31. return PayProc::m_GetFirstPayGift($req);
  32. //
  33. // <editor-fold defaultstate="collapsed" desc=" 页游支付 ">
  34. case CmdCode::cmd_pay_buygoods: # 8801 购买商品
  35. return WebPayProc::buyGoods($req);
  36. case CmdCode::cmd_pay_getvipnewergift: # 8803 领取vip新手礼包
  37. return WebPayProc::getVipNewerGift($req);
  38. case CmdCode::cmd_pay_getvipdaygift: # 8804 领取黄钻每日礼包
  39. return WebPayProc::getVipDayGift($req);
  40. case CmdCode::cmd_pay_getvipopengift: # 8805 领取黄钻开通包月礼包
  41. return WebPayProc::getVipOpenGift($req);
  42. case CmdCode::cmd_pay_confirmdelivery: # 8806 客户端确认支付
  43. return WebPayProc::confirmDelivery($req);
  44. // </editor-fold>
  45. //
  46. // <editor-fold defaultstate="collapsed" desc=" 手机多渠道版 mpay ">
  47. case CmdCode::cmd_mpay_pay: # 8807 消费..
  48. return self::m_pay($req); # 购买普通商城物品
  49. case CmdCode::cmd_mpay_get_balance: # 8808 刷新账号余额
  50. return self::m_refreshChargeOrders($req); # 刷新订单-领取充值金额
  51. case CmdCode::cmd_mpay_buyDynamic: # 8809 购买动态商城物品
  52. return self::m_pay_buyDynamic($req);
  53. case CmdCode::cmd_mpay_getDynamic: # 8810 刷新神秘商城物品
  54. return self::m_pay_getDynamic($req);
  55. case CmdCode::cmd_mpay_selfCheckOrders: # 8811 自助检查异常订单
  56. return self::selfhelpCheckOrders($req);
  57. case CmdCode::cmd_mpay_selfCheckOrders:
  58. return;
  59. // </editor-fold>
  60. //
  61. default:
  62. return Resp::err(ErrCode::cmd_err);
  63. }
  64. }
  65. /**
  66. * 8812 查询充值记录
  67. * @param Req $req
  68. */
  69. static function GetPayRecoreds($req) {
  70. $uid = $req->uid;
  71. $table = "tpl_order_tab";
  72. $arr = daoInst()->select(" cpOrderId as '订单' ,product_name as '道具',amount as '金额' ,from_unixtime(order_ts) as '时间' ")->from($table)
  73. ->where("uid")->eq($uid)
  74. ->andWhere("status")->eq(1)
  75. ->fetchall();
  76. return Resp::ok($arr);
  77. }
  78. //
  79. // <editor-fold defaultstate="collapsed" desc=" 移动支付 - 刷新订单 ">
  80. /**
  81. * 刷新充值订单(领取充值结果)
  82. * @param Req $req
  83. */
  84. public static function m_refreshChargeOrders($req) {
  85. # 客户端参数解析
  86. $uid = $req->uid; # userID
  87. $zoneid = $req->zoneid; # 分区Id
  88. if (count($req->paras) <= 0) { # 参数为空, 执行自检逻辑
  89. return self::selfhelpCheckOrders($req);
  90. }
  91. $cpOrderId = $req->paras[0]; # 后台订单编号
  92. if (!$uid || ($zoneid < 1) || strlen($cpOrderId) != 16) { # 订单编号长16位
  93. return Resp::err(ErrCode::paras_err);
  94. }
  95. $order = daoInst()->select()->from(self::orderTab) # 取订单数据
  96. ->where('cpOrderId')->eq($cpOrderId)
  97. ->limit(1)->fetch();
  98. if (!$order) {
  99. // var_dump($order);
  100. CLog::pay(' 订单不存在! ' . $cpOrderId);
  101. return Resp::err(ErrCode::pay_order_no);
  102. }
  103. if (false === strpos($uid, $order->uid)) { # UID不符
  104. return Resp::err(ErrCode::pay_order_uid);
  105. }
  106. if ($order->status != 1) {
  107. CLog::pay(' 订单尚未完成支付!');
  108. return Resp::err(ErrCode::pay_order_paystatus);
  109. }
  110. if ($order->drawed_ts > 0) { # 定单已经发过货了
  111. CLog::pay(' 订单重复请求发货!' . $cpOrderId);
  112. return Resp::err(ErrCode::pay_order_drawed);
  113. }
  114. // 准备发货
  115. $product_id = $order->product_id;
  116. $product_count = $order->product_count;
  117. $typid = substr("$product_id", 0, 3); # 提取商品编号前缀
  118. switch ($typid) {
  119. case '802': # 神秘商城物品
  120. $item = GameConfig::secretshop_typeId_getItem($product_id);
  121. break;
  122. case '801': # 商城物品
  123. $item = GameConfig::shop_getItem($product_id);
  124. break;
  125. default :
  126. return Resp::err(ErrCode::pay_systembusy_err);
  127. }
  128. if (!$item) {
  129. return Resp::err(ErrCode::pay_shopItem_cosnt_goods_err);
  130. }
  131. if ($item->pricetype != 0) {
  132. CLog::pay(" 道具付费类型异常:" . $product_id);
  133. return Resp::err(ErrCode::pay_m_type_err);
  134. }
  135. for ($i = 0; $i < $product_count; $i++) { # 默认为1,还没有设计为n的情况
  136. StoreProc::AddMultiItemInStore($req, $item->goods, 5); # 发货
  137. }
  138. $n = daoInst()->update(self::orderTab)
  139. ->data(array('drawed_ts' => now()))
  140. ->where('cpOrderId')->eq($cpOrderId)
  141. ->exec();
  142. if (!$n) {
  143. return Resp::err(ErrCode::err_db); # 数据库操作失败
  144. }
  145. $req->userInfo->game->charge_amt += $order->amount; # 历史充值记录(单位分)
  146. UserProc::updateUserInfo($req); # 更新玩家数据信息
  147. Event::trigger('pay', array('amt' => $order->amount)); # 触发充值事件
  148. CLog::pay("订单发货成功: $cpOrderId");
  149. return Resp::ok(# 返回
  150. array('cash' => $req->userInfo->game->cash, # # 直接将游戏币的最新值返回给客户端
  151. 'charge_amt' => $req->userInfo->game->charge_amt, # # 充值总记录
  152. 'store' => $req->userInfo->game->store, # # 背包
  153. 'goods' => $item->goods, # # 发货内容
  154. 'count' => $product_count, # # 发货数量
  155. )
  156. );
  157. }
  158. /**
  159. * 检查内侧订单
  160. * @param Req $req
  161. */
  162. static function checkDeltest($req) {
  163. $uid = $req->uid;
  164. if (!isset($req->userInfo->game->privateState->deltest)) {
  165. $orders = daoInst()->select()->from('tpl_order_tab_deltest')
  166. ->where('uid')->eq(substr($uid, strpos($uid, "-") + 1))
  167. ->andwhere('status')->eq(1)
  168. ->fetchall();
  169. if (count($orders) > 0) { # 有充值记录
  170. foreach ($orders as $order) {
  171. // 准备补发
  172. $product_id = $order->product_id;
  173. $product_count = $order->product_count;
  174. $typid = substr("$product_id", 0, 3); # 提取商品编号前缀
  175. switch ($typid) {
  176. case '802': # 神秘商城物品
  177. $item = GameConfig::secretshop_typeId_getItem($product_id);
  178. break;
  179. case '801': # 商城物品
  180. $item = GameConfig::shop_getItem($product_id);
  181. break;
  182. default :
  183. return Resp::err(ErrCode::pay_systembusy_err);
  184. }
  185. if (!$item) {
  186. return Resp::err(ErrCode::pay_shopItem_cosnt_goods_err);
  187. }
  188. if ($item->pricetype != 0) { # 并非人民币定价
  189. CLog::pay(" 道具付费类型异常:" . $product_id);
  190. return Resp::err(ErrCode::pay_m_type_err);
  191. }
  192. for ($i = 0; $i < $product_count; $i++) { # 默认为1,还没有设计为n的情况
  193. EmailProc::SendDelTestMail($req->zoneid, $uid, $item->name, $item->goods);
  194. }
  195. CLog::pay($req->uid . '发送删档内侧补偿邮件' . $order->cpOrderId);
  196. }
  197. }
  198. $req->userInfo->game->privateState->deltest = 0;
  199. }
  200. }
  201. /**
  202. * 检查异常订单
  203. * @param Req $req
  204. */
  205. public static function selfhelpCheckOrders($req) {
  206. if ('ios' == PLAT) { # ios版的创建订单时带着前缀了。。。
  207. $uid = $req->uid;
  208. } else {
  209. $uid = substr($req->uid, strpos($req->uid, '-') + 1);
  210. }
  211. $orders = daoInst()->select()
  212. ->from('tpl_order_tab')
  213. ->where('uid')->eq($uid)
  214. ->andWhere('status')->eq(1)
  215. ->andWhere('drawed_ts')->le(0)
  216. ->fetchAll();
  217. if (count($orders) > 0) {
  218. foreach ($orders as $order) {
  219. // 准备补发
  220. $product_id = $order->product_id;
  221. $product_count = $order->product_count;
  222. $typid = substr("$product_id", 0, 3); # 提取商品编号前缀
  223. $goods = '';
  224. switch ($typid) {
  225. case '802': # 神秘商城物品
  226. $item = GameConfig::secretshop_typeId_getItem($product_id);
  227. break;
  228. case '801': # 商城物品
  229. $item = GameConfig::shop_getItem($product_id);
  230. break;
  231. default :
  232. return Resp::err(ErrCode::pay_systembusy_err);
  233. }
  234. if (!$item) {
  235. return Resp::err(ErrCode::pay_shopItem_cosnt_goods_err);
  236. }
  237. if ($item->pricetype != 0) { # 并非人民币定价
  238. CLog::pay(" 道具付费类型异常:" . $product_id);
  239. return Resp::err(ErrCode::pay_m_type_err);
  240. }
  241. for ($i = 0; $i < $product_count; $i++) { # 默认为1,还没有设计为n的情况
  242. StoreProc::AddMultiItemInStore($req, $item->goods, 5); # 发货
  243. }
  244. $goods .= $item->goods;
  245. $n = daoInst()->update(self::orderTab) # 更新订单状态
  246. ->data(array('drawed_ts' => now()))
  247. ->where('cpOrderId')->eq($order->cpOrderId)
  248. ->exec();
  249. if (!$n) { # 影响条数应为1
  250. CLog::pay($req->uid . ' 登录补发订单失败 ' . $order->cpOrderId);
  251. return Resp::err(ErrCode::err_db); # 数据库操作失败
  252. }
  253. $req->userInfo->game->charge_amt += $order->amount; # 历史充值记录(单位分)
  254. UserProc::updateUserInfo($req); # 回写玩家数据
  255. CLog::pay($req->uid . ' 登录补发订单 ' . $order->cpOrderId);
  256. }
  257. return Resp::ok(# 返回
  258. array('cash' => $req->userInfo->game->cash, # # 直接将游戏币的最新值返回给客户端
  259. 'store' => $req->userInfo->game->store, # # 背包
  260. 'goods' => $goods, # # 发货内容
  261. 'count' => count($orders), # # 发货数量
  262. 'msg' => "找到并处理" . count($orders) . "条未发货订单."
  263. ));
  264. }
  265. return Resp::ok('ok'); # everything is ok!
  266. }
  267. // </editor-fold>
  268. //
  269. // <editor-fold defaultstate="collapsed" desc=" 移动支付 - 商城购买 ">
  270. /**
  271. * 【移动支付】获取神秘商城物品
  272. * 刷新规则: 根据玩家拥有的英雄、装备、道具等数据进行刷新。(因英雄、道具、装备数量不足以支撑该刷新规则,目前先按照随机刷新做,几率平等)
  273. * @param Req $req
  274. */
  275. public static function m_pay_getDynamic($req) {
  276. $user = $req->userInfo->game;
  277. $userSecretshop = new userSecretshopModel($user->userSecretshop);
  278. // 参数提取
  279. $refreshType = $req->paras[0]; # 刷新类型(参数)0,不刷,1,免费刷,2,钻石刷
  280. switch ($refreshType) {
  281. case 1: # 免费刷
  282. if (now() < $userSecretshop->lastRefreshTs + glc()->secretshop_refresh_interval) { // 检查是否达到免费刷新时间了, 执行自动更新
  283. return Resp::err(ErrCode::pay_secretshopt_freeRefresh_Time);
  284. }
  285. break;
  286. case 2: # 钻石刷
  287. if (glc()->secretshop_refresh_maxtimes <= $userSecretshop->refreshedTimes) { // 检查刷新次数, 已达上限, 返回错误信息
  288. return Resp::err(ErrCode::pay_refresh_times);
  289. } # 可以继续刷新,
  290. $cishu = $userSecretshop->refreshedTimes + 1; # 下次
  291. $amt = GameConfig::secretshop_refresh_getItem($cishu)->price;
  292. if (!UserGameModel::Consume_Cash($user, $amt)) { # 扣除本次所需费用, 余额不足, 返回错误信息
  293. return Resp::err(ErrCode::notenough_cash_msg);
  294. }
  295. $userSecretshop->refreshedTimes++; # 增加当天付费刷新计数
  296. break;
  297. case 0: # 不刷
  298. default : # 默认不刷
  299. // do nothing.
  300. break;
  301. }
  302. if ($refreshType != 0) { # 是否刷新
  303. $err = self::refreshDynamicShopItems($req, $userSecretshop); # 更新物品表
  304. if ($err) {
  305. return Resp::err($err);
  306. }
  307. $user->userSecretshop = $userSecretshop;
  308. $req->userInfo->game = $user;
  309. UserProc::updateUserInfo($req);
  310. }
  311. // 返回最新物品表
  312. return Resp::ok(array(# # 成功后将最新的玩家数据返回给客户端
  313. 'gold' => $user->gold,
  314. 'tili' => $user->tili,
  315. 'cash' => $user->cash,
  316. 'uss' => $userSecretshop, # # 当前神秘商城数据
  317. ));
  318. }
  319. /**
  320. * 更新神秘商城物品
  321. * @param Req $req
  322. * @param UserSecretshopModel $userSecretshop Description
  323. */
  324. private static function refreshDynamicShopItems($req, &$userSecretshop) {
  325. $userSecretshop->lastRefreshTs = now();
  326. // todo: 这里补完更新物品的函数, // 第一版: 随机
  327. $userSecretshop->currentItems = ObjectInit();
  328. for ($i = 1; $i <= 3; $i++) { # 3种类型的商品
  329. $arr = GameConfig::secretshop_goodsType_getItem($i);
  330. if (count($arr) > 0) {
  331. $err = self::Dice(GameConfig::secretshop_goodsType_getItem($i), 1, $userSecretshop); # 一个种类一次1个物品
  332. if ($err) {
  333. return $err;
  334. }
  335. }
  336. }
  337. return ErrCode::ok;
  338. }
  339. /**
  340. * 投骰子
  341. * @param assoc_array $arr 奖池物品
  342. * @param int $number 提取数量
  343. * @return string itemid,num;itemid,num;...
  344. */
  345. static function Dice($arr, $number, &$userSecretshop) {
  346. $max = 0; # 计算物品权重总和
  347. array_walk($arr, function ($value) use(&$max) {
  348. $max += $value->probability;
  349. });
  350. if (!$max) { # 配置数据有问题
  351. return ErrCode::const_no_err;
  352. }
  353. for ($i = 0; $i < $number; $i++) {
  354. $rnd = CommUtil::random(1, $max); # 投骰子
  355. $start = 0;
  356. $rew = null;
  357. foreach ($arr as $item) { # 循环判断落入那个物品上
  358. if (CommUtil::isPropertyExists($item, 'probability') // #
  359. && $start < $rnd && $rnd <= $start + $item->probability) { # 落入区间
  360. $rew = $item; # 记录物品
  361. break;
  362. }
  363. $start += $item->probability; # 继续判断是否落入下一物品的区间
  364. } # foreach end
  365. if (!$rew) {
  366. return ErrCode::lottery_noselecteditem;
  367. }
  368. $id = $rew->typeId;
  369. $userSecretshop->currentItems->$id = 0;
  370. } # for end
  371. return ErrCode::ok;
  372. }
  373. /**
  374. * 清理每日各种上限
  375. * @param Req $req
  376. */
  377. private static function clearDailyLimits($req) {
  378. $userSecretshop = new userSecretshopModel($req->userInfo->game->userSecretshop);
  379. $userSecretshop->refreshedTimes = 0;
  380. $req->userInfo->game->userSecretshop = $userSecretshop;
  381. }
  382. /**
  383. * 【移动支付】购买神秘商城物品
  384. * 规则: 商城物品会刷新
  385. * @param Req $req
  386. */
  387. public static function m_pay_buyDynamic($req) {
  388. $user = new UserGameModel($req->userInfo->game);
  389. $userSecretshop = new userSecretshopModel($user->userSecretshop);
  390. // 参数提取
  391. $itemId = $req->paras[0]; # 商品id (点一次购买一个)
  392. $num = 1; # 暂时固定为一次购买一个
  393. #
  394. if (!CommUtil::isPropertyExists($userSecretshop->currentItems, $itemId)) {
  395. return Resp::err(ErrCode::pay_secretshop_noitem_err);
  396. }
  397. $cishu = $userSecretshop->currentItems->$itemId; # 购买次数
  398. if ($cishu >= glc()->secretshop_itembuy_maxtimes) { # 判断购买次数
  399. return Resp::err(ErrCode::pay_secretshop_buytimes);
  400. }
  401. $shopItem = GameConfig::secretshop_typeId_getItem($itemId); # 常量数据
  402. $amt = $shopItem->price * pow(2, $cishu); # 计算价格
  403. switch ($shopItem->pricetype) {
  404. case 1:
  405. if (!UserGameModel::Consume_Cash($user, $amt)) { # 扣除钻石
  406. return Resp::err(ErrCode::notenough_cash_msg);
  407. }
  408. break;
  409. case 2:
  410. if (!UserGameModel::Consume_Gold($user, $amt)) { # 扣除金币
  411. return Resp::err(ErrCode::notenough_gold_msg);
  412. }
  413. break;
  414. default :
  415. return Resp::err(ErrCode::pay_m_type_err);
  416. }
  417. // 道具解包/发货
  418. $err = self::expendSecretShopItem($shopItem, $num, $req); # 发放商品()
  419. if ($err != ErrCode::ok) { # 发货失败
  420. return Resp::err($err);
  421. }
  422. $userSecretshop->currentItems->$itemId += 1; # 购买次数+1
  423. $user->userSecretshop = $userSecretshop;
  424. $req->userInfo->game = $user;
  425. UserProc::updateUserInfo($req); # 回写数据
  426. StatProc::secretShopbuy($req->zoneid, $req->uid, $itemId, $num); # 统计/监控数据
  427. return Resp::ok(array(# # 成功后将最新的玩家数据返回给客户端
  428. 'gold' => $user->gold,
  429. 'tili' => $user->tili,
  430. 'cash' => $user->cash,
  431. 'store' => $user->store, # # 背包,(装备、碎片、。。)
  432. 'heros' => $user->heros # # 角色
  433. ));
  434. //
  435. }
  436. /**
  437. *
  438. * @param sm_secretshop $shopItem
  439. * @param type $num
  440. * @param type $req
  441. */
  442. private static function expendSecretShopItem($shopItem, $num, $req) {
  443. for ($i = 0; $i < $num; $i++) {
  444. $err = StoreProc::AddMultiItemInStore($req, $shopItem->goods, '神秘商城');
  445. if ($err) {
  446. return $err;
  447. }
  448. }
  449. return ErrCode::ok;
  450. }
  451. /**
  452. * 【移动支付】 购买普通商城物品
  453. * @param Req $req
  454. * @return type
  455. */
  456. public static function m_pay($req) {
  457. $zoneid = $req->zoneid;
  458. $uid = $req->uid;
  459. $user = $req->userInfo->game; # user引用
  460. if (count($req->paras) < 3) { # 参数不足
  461. return Resp::err(ErrCode::parasnotenough_msg);
  462. }
  463. $paytype = $req->paras[0]; # 付费类型, 1.钻石, 2.金币
  464. $itemId = $req->paras[1]; # 道具ID
  465. $num = $req->paras[2]; # 数量, 默认为1
  466. if ($num < 1) { # 参数非法,
  467. return Resp::err(ErrCode::paras_err);
  468. }
  469. $shopItem = GameConfig::shop_getItem($itemId); # 取商品的常量数据
  470. if ($shopItem == null) { # 检测是否存在道具的常量数据
  471. return Resp::err(ErrCode::const_no_err);
  472. }
  473. if ($shopItem->pricetype != $paytype) { # 商品定价类型检查
  474. return Resp::err(ErrCode::pay_price_err);
  475. }
  476. $amt = $shopItem->price; # 道具价格(钻石)
  477. if ($amt <= 0) { # 商品定价数值检查
  478. return Resp::err(ErrCode::pay_price_err);
  479. }
  480. $bDeal = false; # 成交标志位
  481. switch ($paytype) { # 1. 钻石, 2. 金币, other:非法
  482. case 1: # 钻石
  483. $err = self::_SaveUserCash($req, $amt * $num); # 更新(扣除)玩家游戏币(钻石)余额
  484. if (ErrCode::ok != $err) {
  485. return Resp::err($err);
  486. }
  487. $bDeal = true;
  488. break;
  489. case 2: # 金币
  490. if (!UserGameModel::Consume_Gold($user, $amt * $num)) { # 更新玩家金币余额
  491. return Resp::err(ErrCode::notenough_gold_msg);
  492. } # 更新(扣除)玩家游戏币(金币)余额
  493. $bDeal = true;
  494. break;
  495. default : # 未知的支付类型
  496. return Resp::err(ErrCode::pay_m_type_err);
  497. }
  498. if ($bDeal) {
  499. // var_dump($shopItem);
  500. $err = self::expendShopItem($shopItem, $num, $req); # 发放商品(普通商城只有金币和体力)
  501. if ($err != ErrCode::ok) { # 发货失败
  502. return Resp::err($err);
  503. }
  504. UserProc::updateUserInfo($req); # 回写数据
  505. StatProc::shopbuy($zoneid, $uid, $itemId, $num); # 统计/监控数据
  506. return Resp::ok(array(# # 成功后将最新的玩家数据返回给客户端
  507. 'gold' => $user->gold,
  508. 'tili' => $user->tili,
  509. 'cash' => $user->cash,
  510. 'store' => $user->store
  511. ));
  512. }
  513. return Resp::err(ErrCode::err_innerfault);
  514. }
  515. /**
  516. * 解包商城物品
  517. * @param sm_Shop $shopItem
  518. * @param int $num 数量
  519. * @param Req $req
  520. */
  521. static function expendShopItem($shopItem, $num, $req) {
  522. for ($i = 0; $i < $num; $i++) {
  523. $err = StoreProc::AddMultiItemInStore($req, $shopItem->goods, '商城');
  524. if ($err) {
  525. return $err;
  526. }
  527. }
  528. return ErrCode::ok;
  529. }
  530. /**
  531. * 扣除玩家钻石
  532. * @param Req $req
  533. * @param int $amt
  534. * @return int
  535. */
  536. static function _SaveUserCash($req, $amt) {
  537. $err = ErrCode::ok;
  538. if ($amt > 0) { # 防御,数量不可能小于0
  539. $user = $req->userInfo->game;
  540. if ($user->cash < $amt) { # 余额不足
  541. $err = ErrCode::notenough_cash_msg;
  542. } else { # 更新玩家游戏币余额
  543. UserGameModel::set_Cash($user, $user->cash - $amt);
  544. }
  545. }
  546. return $err;
  547. }
  548. /**
  549. * 扣除玩家金币
  550. * @param type $req
  551. * @param type $amt
  552. * @param type $source
  553. * @param type $itemId
  554. * @return type
  555. */
  556. static function _SaveUserGold($req, $amt) {
  557. $err = ErrCode::ok;
  558. $user = $req->userInfo->game;
  559. if (!UserGameModel::Consume_Gold($user, $amt)) { # 更新玩家金币余额
  560. $err = ErrCode::notenough_gold_msg;
  561. }
  562. return $err;
  563. }
  564. // </editor-fold>
  565. //
  566. // <editor-fold defaultstate="collapsed" desc=" 移动支付 - 插入日志 ">
  567. /**
  568. * Sql语句移动支付插入一条log日志。
  569. * @var string
  570. */
  571. const SQL_M_LOG = "INSERT INTO `tab_mpaylog_%s` (zoneid,type,result,amt,balance,giftedcash,chargedcash,source,oid,itemid) VALUES (%d,%d,%d,%d,%d,%d,%d,'%s','%s','%s')";
  572. /**
  573. * 移动支付插入一条记录
  574. * @param int $zoneid 分区ID
  575. * @param string $uid 玩家ID
  576. * @param int $type 记录类型
  577. * @param int $amt 发生金额
  578. * @param int $balance 账号当前余额(钻石)
  579. * @param int $giftedcash 游戏内赠送游戏币总额
  580. * @param int $chargedcash 历史充值游戏币总额
  581. * @param int $source 记录发生来源(起因)
  582. */
  583. public static function _mChargeLog($zoneid, $uid, $type, $result, $amt, $balance, $giftedcash, $chargedcash, $source = "srcUnKnown", $itemid = "") {
  584. // throw new Exception("Method must be completed before online.");
  585. // $month = date("Ym");
  586. // $sql = sprintf(self::SQL_M_LOG, $month, $zoneid, $type, $result, $amt, $balance, $giftedcash, $chargedcash, $source, $uid, $itemid);
  587. // $paydb = CPayInit();
  588. // $paydb->query($sql);
  589. // $paydb->close();
  590. }
  591. // </editor-fold>
  592. //
  593. //
  594. // <editor-fold defaultstate="collapsed" desc=" 支付活动 - 首付礼包">
  595. /**
  596. * 领取首付礼包
  597. * @param Req $req
  598. * @return Resp
  599. */
  600. public static function m_GetFirstPayGift($req) {
  601. $itemId = glc()->FirstPay_ItemId;
  602. $privateState = $req->userInfo->game->privateState;
  603. if (CommUtil::isPropertyExists($privateState, "firstPayGift") #
  604. && $privateState->firstPayGift) { # 如果已经领取首付礼包
  605. return Resp::err(ErrCode::pay_firstpaygetted);
  606. }
  607. if ($req->userInfo->game->charge_amt <= 0) { # 如果尚未完成首付
  608. return Resp::err(ErrCode::pay_firstpayno_err);
  609. }
  610. $itemModel = GameConfig::shop_getItem($itemId); # 取商品常量
  611. if ($itemModel == null) { # 检测首付礼包是否存在
  612. return Resp::err(ErrCode::const_no_err);
  613. }
  614. $req->userInfo->game->privateState->firstPayGift = true; # 设置首付标志
  615. StoreProc::AddMultiItemInStore($req, $itemModel->goods); # 发放首付礼包到玩家仓库
  616. UserProc::updateUserInfo($req); # 更新玩家数据
  617. return Resp::ok(array('itemid' => $itemId,
  618. 'rewardstr' => $itemModel->goods,
  619. 'store' => $req->userInfo->game->store)); # 回送成功信息
  620. }
  621. // </editor-fold>
  622. //
  623. //
  624. //
  625. }