PayProc.php 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940
  1. <?php
  2. namespace loyalsoft;
  3. require_once __DIR__ . '/../service_call/pay/official/pay_op.php'; # 封装渠道支付模块的操作
  4. /**
  5. * 付费、游戏内消费相关处理
  6. * 全部动态交易数据需要保存到db作为[存根]
  7. * @version <br/>
  8. * 6.0.0 第六版: 引入currency字段, 增加出海结算支持. 2022.11
  9. * 5.0.0 第五版: 全部动态交易数据存入mysql. 2021.11
  10. * 4.0.0 第四版: 言灵世界 商城模块. 2020.08
  11. * 2.2.0 第三版: 独立的游戏币<元宝>, 面向多渠道的充值模式, 拉起充值成功后, 给玩家发放元宝. 游戏内部消费元宝,钻石和金币.可以用元宝购买金币和钻石.这一版在上面的PayProc中 * 2015年9月23日 <br/>
  12. * 2.1.0 mn_pay mn_AddUserCash ... 以 mn_ 打头的函数是第二版, 修改为伪托管模式,除了充值的时候跟腾讯通讯,其余时间自己管理游戏币:钻石. * 2015年7月23日 <br/>
  13. * 2.0.1 m_pay m_AddUserCash ... 以 m_ 打头的函数是第一版, 完全按照应用宝官方要求托管游戏币的模式开发的. * 2015年4月23日 <br/>
  14. * 1.0.0 Created at 2016-4-20. by --gwang <br/>
  15. * @author gwang (mail@wanggangzero.cn)
  16. * @copyright © 2016-4-20, SJZ LoyalSoft Corporation & gwang. All rights reserved.
  17. */
  18. class PayProc {
  19. const orderTab = 'tab_order_tab';
  20. /**
  21. * 逻辑分发
  22. * 所有的Proc中必须有这样一个方法
  23. */
  24. public static function procMain() {
  25. switch (req()->cmd) {
  26. // 支付相关的活动
  27. case CmdCode::cmd_pay_getfirstpaygift: # 8802 领取首充礼包
  28. return PayProc::m_GetFirstPayGift();
  29. case CmdCode::cmd_pay_resetFirstRechargeUI_OpenTip: # 8803 重置弹框
  30. return PayProc::resetFirstRechargeUI_OpenTip();
  31. case CmdCode::cmd_pay_accumulateRechargeRewardReceived: # 8804 累计充值领取奖励
  32. return PayProc::accumulateRechargeRewardReceived();
  33. // 游戏内二级货币消费
  34. case CmdCode::cmd_mpay_pay: # 8807 消费..
  35. return self::m_pay(); # ::==> 购买普通商城物品
  36. case CmdCode::cmd_mpay_buyDynamic: # 8809 购买动态商城物品
  37. return self::m_pay_buyDynamic();
  38. case CmdCode::cmd_mpay_getDynamic: # 8810 刷新神秘商城物品
  39. return self::m_pay_getDynamic();
  40. // 充值消费
  41. case CmdCode::cmd_mpay_get_balance: # 8808 刷新账号余额
  42. return self::m_refreshChargeOrders(); # ::==> 刷新订单-领取充值金额
  43. case CmdCode::cmd_mpay_selfCheckOrders: # 8811 自助检查异常订单
  44. return self::selfhelpCheckOrders();
  45. case CmdCode::cmd_mpay_getPayRecords: # 8812 查询订单记录
  46. return self::GetPayRecoreds();
  47. case CmdCode::cmd_mpay_PayDeliverGoods: # 8813 查询订单并发货
  48. return self::PayDeliverGoods();
  49. case CmdCode::cmd_mpay_UserRechargeDrawPrize: # 8814 充值领奖励 2022.10
  50. return self::UserRechargeDrawPrize();
  51. case CmdCode::cmd_mpay_NewFirstRecharge: # 8815 新首充功能 2022.10
  52. return self::NewFirstRecharge();
  53. default:
  54. return Resp::err(ErrCode::cmd_err);
  55. }
  56. }
  57. /**
  58. * 8804 累计充值
  59. */
  60. static function accumulateRechargeRewardReceived() {
  61. list($id) = req()->paras;
  62. $mo = GameConfig::accumulaterecharge_getItem($id); # 用yuanbao做的key
  63. my_Assert($mo != null, ErrCode::err_const_no);
  64. my_Assert(ctx()->baseInfo->accumulateYuanBao >= $id, ErrCode::pay_accumulateYuanBaoNotEnough);
  65. my_Assert(!in_array($id, ctx()->privateState->accumulateRechargeRewardRecord), ErrCode::pay_repeatReceive);
  66. ctx()->privateData(true)->accumulateRechargeRewardRecord[] = $id;
  67. StoreProc::AddMultiItemInStore($mo->reward);
  68. $reset = true;
  69. $dic = GameConfig::accumulaterecharge();
  70. $max_yuanbao = 0;
  71. foreach ($dic as $aMo) {
  72. if (!in_array($aMo->yuanbao, ctx()->privateState->accumulateRechargeRewardRecord)) {
  73. $reset = false;
  74. }
  75. if ($aMo->yuanbao > $max_yuanbao) {
  76. $max_yuanbao = $aMo->yuanbao;
  77. }
  78. }
  79. if ($reset) {
  80. ctx()->privateData(true)->accumulateRechargeRewardRecord = array();
  81. ctx()->baseInfo->accumulateYuanBao -= $max_yuanbao;
  82. if (ctx()->baseInfo->accumulateYuanBao <= 0) {
  83. ctx()->baseInfo->accumulateYuanBao = 0;
  84. }
  85. }
  86. UserProc::updateUserInfo();
  87. return Resp::ok(array('gold' => ctx()->baseInfo->gold,
  88. 'cash' => ctx()->baseInfo->cash,
  89. 'tili' => ctx()->baseInfo->tili,
  90. 'tili_ts' => ctx()->baseInfo->tili_ts,
  91. 'accumulateYuanBao' => ctx()->baseInfo->accumulateYuanBao,
  92. 'store' => ctx()->store,
  93. 'privateState' => ctx()->privateState,
  94. 'reward' => StoreProc::$reward,
  95. 'reward_Gem' => StoreProc::$reward_Gem,
  96. 'reward_equip' => StoreProc::$reward_equip,
  97. ));
  98. }
  99. /**
  100. * 8803 重置弹框
  101. */
  102. static function resetFirstRechargeUI_OpenTip() {
  103. ctx()->privateData(true)->firstRechargeUI_OpenTip = 0;
  104. UserProc::updateUserInfo();
  105. return Resp::ok();
  106. }
  107. static $retArr;
  108. /**
  109. * 8815 新首冲功能5点前不能领取奖励,则该请求只是为了首充开发界面时获得最新时间戳
  110. */
  111. static function NewFirstRecharge() {
  112. UserProc::updateUserInfo();
  113. return Resp::ok(array(
  114. "ret" => 'true',
  115. ));
  116. }
  117. /**
  118. * [8814]领取奖励 (新版2021)
  119. */
  120. static function UserRechargeDrawPrize() {
  121. list($type, $typeId) = req()->paras;
  122. $user = ctx();
  123. self::$retArr = array();
  124. switch ($type) {
  125. case Enum_Recharge::FirstRecharge://首冲
  126. my_Assert($user->pay->firstRechage == 0, ErrCode::shop_firstRechargeNotRepeat);
  127. StoreProc::AddMultiItemInStore(GameConfig::globalsettings()->firstRechargePrizes);
  128. $user->pay->firstRechage = 1;
  129. self::$retArr[] = GameConfig::globalsettings()->firstRechargePrizes;
  130. break;
  131. case Enum_Recharge::DaliySpecialPackages://每日特惠
  132. my_Assert(!in_array($typeId, $user->shopdata->daliySpecialPackages), ErrCode::shop_daliySpecialRewardNotRepeat);
  133. $mo = GameConfig::shop_limit_getItem($typeId);
  134. my_Assert($mo != null, ErrCode::err_const_no);
  135. if ($mo->price != 0) {//购买60元7天特惠,则不是免费的礼包现在也可以领取。这里校验一下
  136. //my_Assert($user->shopdata->daliySpecial_ts!= 0, ErrCode::shop_daliySpecialRewardNotRepeat);
  137. $ts = $user->shopdata->daliySpecial_ts + 7 * 24 * 60 * 60;
  138. my_Assert(now() < $ts, ErrCode::shop_daliySpecialRewardNotRepeat);
  139. }
  140. $itemid = explode(',', $mo->reward)[0];
  141. $itemMO = GameConfig::item_package_getItem($itemid);
  142. my_Assert(null != $itemMO, ErrCode::err_const_no);
  143. StoreProc::AddMultiItemInStore($itemMO->contents);
  144. self::$retArr[] = $itemMO->contents;
  145. $shopdata = new Info_UserShop(ctx()->shopdata);
  146. $shopdata->daliySpecialPackages[] = $typeId;
  147. ctx()->shopdata = $shopdata;
  148. break;
  149. case Enum_Recharge::RechargeRebate://充值返利
  150. $mo = GameConfig::rechargeRebate_getItem(3, $typeId);
  151. my_Assert($mo != null, ErrCode::err_const_no);
  152. my_Assert($user->baseInfo->charge_amt >= $mo->rmb, ErrCode::shop_RechargeRebateRmbNotEnough);
  153. my_Assert(!in_array($typeId, $user->shopdata->rechargeRebateRewardsList), ErrCode::shop_RechargeRebateRewardNotRepeat);
  154. StoreProc::AddMultiItemInStore($mo->rewards);
  155. self::$retArr[] = $mo->rewards;
  156. break;
  157. case Enum_Recharge::LimitBuy://限购中免费礼包领取
  158. $packageCfg = GameConfig::shop_limit_getItem($typeId);
  159. my_Assert(null != $packageCfg, ErrCode::err_const_no);
  160. my_Assert($packageCfg->price == 0, ErrCode::shop_limit_NotFree);
  161. self::checklimitBuyRecharge($typeId);
  162. break;
  163. case Enum_Recharge::Accumulate: # 累充, gwang 2022.10.18
  164. // list($amount, $day) = explode('-', $typeId); # 拆分key1,key2
  165. // $cfg = GameConfig::shop_accumulating_getItem($amount, $day); # 配置对象
  166. // my_Assert(null != $cfg, ErrCode::err_const_no); # 防御null
  167. //
  168. // $acc = new Ins_Accumulate($user->shopdata->shopAccumulateData); # 累充对象
  169. // my_Assert(!$acc->IsDrawed($amount, $day), ErrCode::active_hasgetted); # 防御: 已经领取
  170. // my_Assert($user->baseInfo->rechargeFun_amt >= $cfg->amount, "累充金额不足!"); # 校验: 金额
  171. // my_Assert($acc->EndDay() >= tsDay(), "领取时间已过!"); # 校验: 时间
  172. // StoreProc::AddMultiItemInStore($cfg->goods); # 发放奖品
  173. // $user->shopdata->shopAccumulateData = $acc->SetDrawd($amount, $day); # 更新数据
  174. // self::$retArr[] = $cfg->goods;
  175. $mo = GameConfig::rechargeRebate_getItem(Enum_Recharge::Accumulate, $typeId);
  176. my_Assert($mo != null, ErrCode::err_const_no);
  177. my_Assert($user->baseInfo->charge_amt >= $mo->rmb, ErrCode::shop_RechargeRebateRmbNotEnough);
  178. my_Assert(!in_array($typeId, $user->shopdata->rechargeRebateRewardsList), ErrCode::shop_RechargeRebateRewardNotRepeat);
  179. $user->shopdata->rechargeRebateRewardsList[] = $typeId;
  180. StoreProc::AddMultiItemInStore($mo->rewards);
  181. self::$retArr[] = $mo->rewards;
  182. break;
  183. case Enum_Recharge::FirstRecharge_new:
  184. $mo = GameConfig::shop_accumulating_getItem($typeId);
  185. my_Assert(null != $mo, ErrCode::err_const_no);
  186. $shopdata = new Info_UserShop(ctx()->shopdata);
  187. $amount = $mo->amount;
  188. if (!StlUtil::dictHasProperty($shopdata->fRechargeRecord, $amount)) {
  189. $shopdata->fRechargeRecord->$amount = array();
  190. }
  191. my_Assert(!in_array($typeId, $shopdata->fRechargeRecord->$amount), ErrCode::active_FirstRechargeRewardRepeat);
  192. $shopdata->fRechargeRecord->$amount[] = $typeId;
  193. StoreProc::AddMultiItemInStore($mo->goods); # 发放奖品
  194. ctx()->shopdata = $shopdata;
  195. self::$retArr[] = $mo->goods;
  196. break;
  197. case Enum_Recharge::DayAccumulateRecharge: #每周累计金额奖励
  198. $mo = GameConfig::rechargeRebate_getItem($type, $typeId);
  199. my_Assert($mo != null, ErrCode::err_const_no);
  200. my_Assert($user->shopdata->dayRechargeAmt >= $mo->rmb, ErrCode::shop_RechargeRebateRmbNotEnough);
  201. my_Assert(!in_array($typeId, $user->shopdata->dayRechargeReceived), ErrCode::shop_RechargeRebateRewardNotRepeat);
  202. $user->shopdata->dayRechargeReceived[] = $typeId;
  203. // if ($rechargeType == 1) {
  204. // my_Assert($user->shopdata->dayRechargeAmt >= $mo->rmb, ErrCode::shop_RechargeRebateRmbNotEnough);
  205. // my_Assert(!in_array($rmb, $user->shopdata->dayRechargeReceived), ErrCode::shop_RechargeRebateRewardNotRepeat);
  206. // $user->shopdata->dayRechargeReceived[] = $rmb;
  207. // } else if($rechargeType == 2){
  208. // my_Assert($user->shopdata->weekRechargeAmt >= $mo->rmb, ErrCode::shop_RechargeRebateRmbNotEnough);
  209. // my_Assert(!in_array($rmb, $user->shopdata->weekRechargeReceived), ErrCode::shop_RechargeRebateRewardNotRepeat);
  210. // $user->shopdata->weekRechargeReceived[] = $rmb;
  211. // }
  212. StoreProc::AddMultiItemInStore($mo->rewards);
  213. self::$retArr[] = $mo->rewards;
  214. break;
  215. case Enum_Recharge::WeekAccumulateRecharge: #每周累计金额奖励
  216. $mo = GameConfig::rechargeRebate_getItem($type, $typeId);
  217. my_Assert($mo != null, ErrCode::err_const_no);
  218. my_Assert($user->shopdata->weekRechargeAmt >= $mo->rmb, ErrCode::shop_RechargeRebateRmbNotEnough);
  219. my_Assert(!in_array($typeId, $user->shopdata->weekRechargeReceived), ErrCode::shop_RechargeRebateRewardNotRepeat);
  220. $user->shopdata->weekRechargeReceived[] = $typeId;
  221. StoreProc::AddMultiItemInStore($mo->rewards);
  222. self::$retArr[] = $mo->rewards;
  223. break;
  224. default:
  225. break;
  226. }
  227. ctx($user);
  228. UserProc::updateUserInfo();
  229. return Resp::ok(array(
  230. "ret" => self::$retArr,
  231. "pay" => $user->pay,
  232. "shopdata" => ctx()->shopdata,
  233. "base" => $user->baseInfo,
  234. "store" => $user->store,
  235. ));
  236. }
  237. /**
  238. * 限购礼包--终身礼包--套装礼包--校验
  239. * @param type $packageId
  240. */
  241. private static function checklimitBuyRecharge($packageId) { # 参数; 礼包id
  242. $shopdata = new Info_UserShop(ctx()->shopdata);
  243. $packageCfg = GameConfig::shop_limit_getItem($packageId);
  244. my_Assert(null != $packageCfg, ErrCode::err_const_no);
  245. $arr = array();
  246. if ($packageCfg->goodsType == Enum_Recharge::LifelongGift) {
  247. $shopdata->lifelongGiftReceived[] = $packageId;
  248. $arr = $shopdata->lifelongGiftReceived;
  249. } elseif ($packageCfg->goodsType == Enum_Recharge::SuitGift) {
  250. $ts = now() - $shopdata->suitGiftStartTs;
  251. my_Assert($ts <= $packageCfg->limit_ts, ErrCode::shop_limit_TsMax); # 校验时间
  252. $shopdata->suitGiftReceived[] = $packageId;
  253. $arr = $shopdata->suitGiftReceived;
  254. } else {
  255. switch ((int) $packageCfg->subType) {
  256. case 1:
  257. $shopdata->purchasedDailyLimitPackages[] = $packageId;
  258. $arr = $shopdata->purchasedDailyLimitPackages;
  259. break;
  260. case 2:
  261. $shopdata->purchasedWeeklyLimitPackages[] = $packageId;
  262. $arr = $shopdata->purchasedWeeklyLimitPackages;
  263. break;
  264. case 3:
  265. $shopdata->purchasedMonthlyLimitPackages[] = $packageId;
  266. $arr = $shopdata->purchasedMonthlyLimitPackages;
  267. break;
  268. default:
  269. Err(ErrCode::err_innerfault);
  270. }
  271. }
  272. $hasN = count(array_filter($arr, function ($val)use ($packageId) { # 计数:筛选条件
  273. return $val == $packageId;
  274. }));
  275. my_Assert($hasN <= $packageCfg->limit_num, ErrCode::shop_limit_max); # 校验购买数量
  276. $itemid = explode(',', $packageCfg->reward)[0]; # 奖励礼包Id
  277. $itemMO = GameConfig::item_package_getItem($itemid);
  278. my_Assert(null != $itemMO, ErrCode::err_const_no);
  279. $err = StoreProc::AddMultiItemInStore($itemMO->contents); # 发放奖励
  280. self::$retArr[] = $itemMO->contents;
  281. my_Assert(ErrCode::ok == $err, $err);
  282. ctx()->shopdata = $shopdata; # 回写数据
  283. }
  284. /**
  285. * [8813] 充值发货 (新版2021)
  286. */
  287. static function PayDeliverGoods() {
  288. list($cpOrderId) = req()->paras;
  289. $result = pay_op::CheckAndDrawOrder(req()->uid, $cpOrderId, array(new PayProc, 'distributePayGoods'));
  290. CLog::pay($result);
  291. my_Assert($result->err == 0, $result->err); # 发货失败
  292. $user = ctx();
  293. NormalEventProc::OnPaySuccess();
  294. UserProc::updateUserInfo(); # 回写玩家数据
  295. return Resp::ok(array(
  296. "ret" => self::$retArr, # # 奖励串
  297. "mod" => $result->result, # # 商品刷新模块名
  298. "baseInfo" => $user->baseInfo,
  299. // "shopdata" => $user->shopdata,
  300. "store" => $user->store,
  301. 'task' => ctx()->task,
  302. 'heros' => ctx()->heros,
  303. 'privateState' => $user->privateState,
  304. ));
  305. }
  306. /**
  307. * 发货
  308. * @param \loyalsoft\pay\dbOrder $order
  309. * @return bool
  310. */
  311. static function distributePayGoods($order = null) {
  312. my_Assert($order->product_id != null, ErrCode::pay_order_product_id);
  313. $user = ctx();
  314. self::$retArr = array();
  315. $shopItem = GameConfig::shop_getItem($order->product_id); # 商城总表中查找下配置数据
  316. $mod = "";
  317. if (null != $shopItem) {
  318. $mod = $shopItem->shopItemType;
  319. switch ($shopItem->shopItemType) {
  320. case 'cash': # 充值二级货币
  321. $cashMo = GameConfig::shop_cash_getItem($shopItem->shopItemTypeId);
  322. my_Assert(null != $cashMo, ErrCode::err_const_no);
  323. // StoreProc::AddMultiItemInStore($cashMo->reward, "付费");
  324. self::$retArr[] = ShopProc::BuyShop_Cash(EnumShopGift::Cash_Shop, $shopItem->shopItemTypeId, $order->product_count);
  325. break;
  326. case 'monthcard': # 月卡
  327. $monthCardMo = GameConfig::shop_monthcard_getItem($shopItem->shopItemTypeId);
  328. my_Assert(null != $monthCardMo, ErrCode::err_const_no);
  329. ShopProc::BuyShop_MonthCard(EnumShopGift::MonthCard_Shop, $shopItem->shopItemTypeId, $order->product_count);
  330. break;
  331. case 'battlePass_gate':
  332. ctx()->privateData(true)->battlePass_gate_cost_ts = now();
  333. break;
  334. case 'battlePass_activePoint':
  335. ctx()->privateData(true)->battlePass_activePoint_cost_ts = now();
  336. break;
  337. case 'battlePass_tili':
  338. ctx()->privateData(true)->battlePass_tili_cost_ts = now();
  339. break;
  340. case 'box':
  341. case 'daily':
  342. case 'gategift':
  343. case 'gold':
  344. case 'junbei':
  345. case 'supply' :
  346. default:
  347. my_Assert(false, "该道具并非现金充值类!");
  348. break;
  349. }
  350. }
  351. $user->baseInfo->charge_amt += $order->amount; # 统计下累充金额
  352. if ($order->amount > 0) {
  353. if (ctx()->privateState->firstRecharge_receiveTag == 0) {
  354. ctx()->privateState->firstRechargeUI_OpenTip = 1;
  355. ctx()->privateState->firstRecharge_receiveTag = 1;
  356. }
  357. // if (ctx()->privateState->firstRecharge_receiveTag < 1) {
  358. // ctx()->privateState->firstRecharge_receiveTag = 1;
  359. // }
  360. }
  361. ctx($user);
  362. return [true, $mod];
  363. }
  364. static function suitGiftCheck() {
  365. $shopdata = new Info_UserShop(ctx()->shopdata);
  366. $cost = 0;
  367. $dic = GameConfig::shop_accumulating();
  368. foreach ($dic as $k => $item) {
  369. if ($cost <= $item->amount) {
  370. $cost = $item->amount;
  371. }
  372. }
  373. if (StlUtil::dictHasProperty($shopdata->fRechargeTime, $cost)) {
  374. if ($shopdata->suitGiftStartTs == 0) {
  375. $shopdata->suitGiftStartTs = now();
  376. }
  377. } else {
  378. $shopdata->suitGiftStartTs = 0;
  379. }
  380. ctx()->shopdata = $shopdata;
  381. }
  382. static function checkAmount($order) {
  383. my_Assert($order->product_id != null, ErrCode::pay_order_product_id);
  384. if ($order->product_id >= 6 && $order->product_id <= 1000) {//充值表
  385. $mo = GameConfig::recharge_getItem($order->product_id);
  386. my_Assert($mo != null, ErrCode::err_const_no);
  387. my_Assert($order->amount == $mo->rmd, ErrCode::pay_price_err);
  388. } elseif ($order->product_id >= 801001 && $order->product_id <= 801999) {//限购
  389. //该功能暂时没有开发
  390. } elseif ($order->product_id >= 804001 && $order->product_id <= 804999) {//每日特惠
  391. $mo = GameConfig::shop_limit_getItem($order->product_id);
  392. my_Assert($mo->price == $order->amount, ErrCode::pay_price_err);
  393. } elseif ($order->product_id >= 805001 && $order->product_id <= 805999) {//限时
  394. //该功能暂时没有开发
  395. } elseif ($order->product_id >= 901001 && $order->product_id <= 999999) {//月卡
  396. $packageCfg = GameConfig::shop_monthVIP_getItem($order->product_id);
  397. my_Assert(null != $packageCfg, ErrCode::err_const_no);
  398. my_Assert($packageCfg->price == $order->amount, ErrCode::pay_price_err);
  399. }
  400. return true;
  401. }
  402. /**
  403. * 礼包有了的第一次登录记录
  404. */
  405. static function SuitGiftTsRecord() {
  406. $shopdata = new Info_UserShop(ctx()->shopdata);
  407. if (!StlUtil::dictHasProperty($shopdata, 'suitGiftStartTs')) {
  408. $shopdata->suitGiftStartTs = 0;
  409. }
  410. if ($shopdata->suitGiftStartTs == 0) {
  411. $shopdata->suitGiftStartTs = now();
  412. }
  413. ctx()->shopdata = $shopdata;
  414. }
  415. /**
  416. * 8812 查询充值记录
  417. */
  418. static function GetPayRecoreds() {
  419. $uid = req()->uid;
  420. $arr = daoInst()->select(" cpOrderId as '订单' ,product_name as '道具',amount as '金额' ,from_unixtime(order_ts) as '时间' ")->from(self::orderTab)
  421. ->where("uid")->eq($uid)
  422. ->andWhere("status")->eq(1)
  423. ->fetchall();
  424. return Resp::ok($arr);
  425. }
  426. //
  427. // <editor-fold defaultstate="collapsed" desc=" 移动支付 - 刷新订单 ">
  428. /**
  429. * 刷新充值订单(领取充值结果)
  430. * @deprecated since version 2024.12.20
  431. */
  432. public static function m_refreshChargeOrders() {
  433. # 客户端参数解析
  434. $uid = req()->uid; # userID
  435. $zoneid = req()->zoneid; # 分区Id
  436. if (count(req()->paras) <= 0) { # 参数为空, 执行自检逻辑
  437. return self::selfhelpCheckOrders();
  438. }
  439. $cpOrderId = req()->paras[0]; # 后台订单编号
  440. if (!$uid || ($zoneid < 1) || strlen($cpOrderId) != 16) { # 订单编号长16位
  441. return Resp::err(ErrCode::paras_err);
  442. }
  443. $order = daoInst()->select()->from(self::orderTab) # 取订单数据
  444. ->where('cpOrderId')->eq($cpOrderId)
  445. ->limit(1)->fetch();
  446. if (!$order) {
  447. // var_dump($order);
  448. CLog::pay(' 订单不存在! ' . $cpOrderId);
  449. return Resp::err(ErrCode::pay_order_no);
  450. }
  451. if (false === strpos($uid, $order->uid)) { # UID不符
  452. return Resp::err(ErrCode::pay_order_uid);
  453. }
  454. if ($order->status != 1) {
  455. CLog::pay(' 订单尚未完成支付!');
  456. return Resp::err(ErrCode::pay_order_paystatus);
  457. }
  458. if ($order->drawed_ts > 0) { # 定单已经发过货了
  459. CLog::pay(' 订单重复请求发货!' . $cpOrderId);
  460. return Resp::err(ErrCode::pay_order_drawed);
  461. }
  462. // 准备发货
  463. $product_id = $order->product_id;
  464. $product_count = $order->product_count;
  465. $typid = substr("$product_id", 0, 3); # 提取商品编号前缀
  466. switch ($typid) {
  467. case '802': # 神秘商城物品
  468. $item = GameConfig::secretshop_typeId_getItem($product_id);
  469. break;
  470. case '801': # 商城物品
  471. $item = GameConfig::shop_getItem($product_id);
  472. break;
  473. default :
  474. return Resp::err(ErrCode::pay_systembusy_err);
  475. }
  476. my_Assert(isset($item), ErrCode::pay_shopItem_cosnt_goods_err);
  477. if ($item->pricetype != 0) {
  478. CLog::pay(" 道具付费类型异常:" . $product_id);
  479. return Resp::err(ErrCode::pay_m_type_err);
  480. }
  481. for ($i = 0; $i < $product_count; $i++) { # 默认为1,还没有设计为n的情况
  482. StoreProc::AddMultiItemInStore($item->goods, 5); # 发货
  483. }
  484. $n = daoInst()->update(self::orderTab)
  485. ->data(array('drawed_ts' => now()))
  486. ->where('cpOrderId')->eq($cpOrderId)
  487. ->exec();
  488. my_Assert($n > 0, ErrCode::err_db); # 数据库操作失败
  489. ctx()->baseInfo->charge_amt += $order->amount; # 历史充值记录(单位分)
  490. UserProc::updateUserInfo(); # 更新玩家数据信息
  491. Event::trigger('pay', array('amt' => $order->amount)); # 触发充值事件
  492. CLog::pay("订单发货成功: $cpOrderId");
  493. return Resp::ok(# 返回
  494. array('cash' => ctx()->baseInfo->cash, # # 直接将游戏币的最新值返回给客户端
  495. 'charge_amt' => ctx()->baseInfo->charge_amt, # 充值总记录
  496. 'store' => ctx()->store, # # 背包
  497. 'goods' => $item->goods, # # 发货内容
  498. 'count' => $product_count, # # 发货数量
  499. )
  500. );
  501. }
  502. /**
  503. * 检查删档内测订单
  504. */
  505. static function checkDeltest() {
  506. $uid = req()->uid;
  507. if (ctx()->privateState->deltest == 1) {
  508. $orders = daoInst()->select()->from('tpl_order_tab_deltest')
  509. ->where('uid')->eq($uid)
  510. ->andwhere('status')->eq(1)
  511. ->fetchall();
  512. if (count($orders) > 0) { # 有充值记录
  513. foreach ($orders as $order) {
  514. // 翻倍发放砖石
  515. isEditor() and $order = new pay\dbOrder();
  516. $rmb = intval($order->amount / 100); # 计算充值金额(元)
  517. EmailProc::SendDelTestMail(req()->zoneid, $uid, $rmb);
  518. CLog::pay(req()->uid . '发送删档内侧补偿邮件' . $order->cpOrderId);
  519. }
  520. }
  521. ctx()->privateData(true)->deltest = 0;
  522. }
  523. // CLog::pay('删档内测补偿检查');
  524. }
  525. /**
  526. * [8811] 检查异常订单, 补发道具
  527. */
  528. public static function selfhelpCheckOrders() {
  529. $uid = req()->uid;
  530. $orders = daoInst()->select()
  531. ->from(self::orderTab)
  532. ->where('uid')->eq($uid)
  533. ->andWhere('status')->eq(1)
  534. ->andWhere('drawed_ts')->le(0)
  535. ->fetchAll();
  536. if (count($orders) > 0) {
  537. foreach ($orders as $order) {
  538. $result = pay_op::CheckAndDrawOrder(req()->uid, $order->cpOrderId, array(new PayProc, 'distributePayGoods'));
  539. CLog::pay($result);
  540. my_Assert($result->err == 0, $result->err); # 发货失败
  541. UserProc::updateUserInfo(); # 回写玩家数据
  542. CLog::pay(req()->uid . ' 登录补发订单 ' . $order->cpOrderId);
  543. }
  544. }
  545. return Resp::ok(array(
  546. "ret" => self::$retArr, # # 奖励串
  547. "mod" => '', # # 商品刷新模块名
  548. "baseInfo" => ctx()->baseInfo,
  549. // "shopdata" => $user->shopdata,
  550. "store" => ctx()->store,
  551. 'task' => ctx()->task,
  552. 'heros' => ctx()->heros,
  553. 'privateState' => ctx()->privateState,
  554. ));
  555. // return Resp::ok('ok'); # everything is ok!
  556. }
  557. // </editor-fold>
  558. //
  559. // <editor-fold defaultstate="collapsed" desc=" 移动支付 - 商城购买 ">
  560. /**
  561. * 8810 免费或利用【游戏内货币】获取神秘商城物品
  562. * 刷新规则: 根据玩家拥有的英雄、装备、道具等数据进行刷新。(因英雄、道具、装备数量不足以支撑该刷新规则,目前先按照随机刷新做,几率平等)
  563. */
  564. public static function m_pay_getDynamic() {
  565. $user = ctx();
  566. $userSecretshop = new Info_UserSecretshop($user->userSecretshop);
  567. // 参数提取
  568. $refreshType = req()->paras[0]; # 刷新类型(参数)0,不刷,1,免费刷,2,钻石刷
  569. switch ($refreshType) {
  570. case 1: # 免费刷
  571. if (now() < $userSecretshop->lastRefreshTs + glc()->secretshop_refresh_interval) { // 检查是否达到免费刷新时间了, 执行自动更新
  572. return Resp::err(ErrCode::pay_secretshopt_freeRefresh_Time);
  573. }
  574. break;
  575. case 2: # 钻石刷
  576. if (glc()->secretshop_refresh_maxtimes <= $userSecretshop->refreshedTimes) { // 检查刷新次数, 已达上限, 返回错误信息
  577. return Resp::err(ErrCode::pay_refresh_times);
  578. } # 可以继续刷新,
  579. $cishu = $userSecretshop->refreshedTimes + 1; # 下次
  580. $amt = GameConfig::secretshop_refresh_getItem($cishu)->price;
  581. if (!$user->base(true)->Consume_Cash($amt)) { # 扣除本次所需费用, 余额不足, 返回错误信息
  582. return Resp::err(ErrCode::notenough_cash_msg);
  583. }
  584. $userSecretshop->refreshedTimes++; # 增加当天付费刷新计数
  585. break;
  586. case 0: # 不刷
  587. default : # 默认不刷
  588. // do nothing.
  589. break;
  590. }
  591. if ($refreshType != 0) { # 是否刷新
  592. $err = self::refreshDynamicShopItems($userSecretshop); # 更新物品表
  593. if ($err) {
  594. return Resp::err($err);
  595. }
  596. $user->userSecretshop = $userSecretshop;
  597. ctx($user);
  598. UserProc::updateUserInfo();
  599. }
  600. // 返回最新物品表
  601. return Resp::ok(array(# # 成功后将最新的玩家数据返回给客户端
  602. 'gold' => $user->baseInfo->gold,
  603. 'tili' => $user->baseInfo->tili,
  604. 'cash' => $user->baseInfo->cash,
  605. 'uss' => $userSecretshop, # # 当前神秘商城数据
  606. ));
  607. }
  608. /**
  609. * 更新神秘商城物品
  610. * @param Info_UserSecretshop $userSecretshop Description
  611. */
  612. private static function refreshDynamicShopItems(&$userSecretshop) {
  613. $userSecretshop->lastRefreshTs = now();
  614. // todo: 这里补完更新物品的函数, // 第一版: 随机
  615. $userSecretshop->currentItems = ObjectInit();
  616. for ($i = 1; $i <= 3; $i++) { # 3种类型的商品
  617. $arr = GameConfig::secretshop_goodsType_getItem($i);
  618. if (count($arr) > 0) {
  619. $err = self::Dice(GameConfig::secretshop_goodsType_getItem($i), 1, $userSecretshop); # 一个种类一次1个物品
  620. if ($err) {
  621. return $err;
  622. }
  623. }
  624. }
  625. return ErrCode::ok;
  626. }
  627. /**
  628. * 投骰子
  629. * @param assoc_array $arr 奖池物品
  630. * @param int $number 提取数量
  631. * @return string itemid,num;itemid,num;...
  632. */
  633. private static function Dice($arr, $number, &$userSecretshop) {
  634. $max = 0; # 计算物品权重总和
  635. array_walk($arr, function ($value) use (&$max) {
  636. $max += $value->probability;
  637. });
  638. if (!$max) { # 配置数据有问题
  639. return ErrCode::err_const_no;
  640. }
  641. for ($i = 0; $i < $number; $i++) {
  642. $rnd = CommUtil::random(1, $max); # 投骰子
  643. $start = 0;
  644. $rew = null;
  645. foreach ($arr as $item) { # 循环判断落入那个物品上
  646. if (CommUtil::isPropertyExists($item, 'probability') // #
  647. && $start < $rnd && $rnd <= $start + $item->probability) { # 落入区间
  648. $rew = $item; # 记录物品
  649. break;
  650. }
  651. $start += $item->probability; # 继续判断是否落入下一物品的区间
  652. } # foreach end
  653. if (!$rew) {
  654. return ErrCode::lottery_noselecteditem;
  655. }
  656. $id = $rew->typeId;
  657. $userSecretshop->currentItems->$id = 0;
  658. } # for end
  659. return ErrCode::ok;
  660. }
  661. /**
  662. * 清理每日各种上限
  663. */
  664. private static function clearDailyLimits() {
  665. $userSecretshop = new Info_UserSecretshop(ctx()->userSecretshop);
  666. $userSecretshop->refreshedTimes = 0;
  667. ctx()->userSecretshop = $userSecretshop;
  668. }
  669. /**
  670. * [8809]【游戏内货币】购买神秘商城物品
  671. * 规则: 商城物品会刷新
  672. */
  673. public static function m_pay_buyDynamic() {
  674. $user = new Data_UserGame(ctx());
  675. $userSecretshop = new Info_UserSecretshop($user->userSecretshop);
  676. $itemId = req()->paras[0]; # 商品id (点一次购买一个)
  677. $num = 1; # 暂时固定为一次购买一个
  678. #
  679. my_Assert(CommUtil::isPropertyExists($userSecretshop->currentItems, $itemId), ErrCode::pay_secretshop_noitem_err);
  680. $cishu = $userSecretshop->currentItems->$itemId; # 购买次数
  681. my_Assert($cishu < glc()->secretshop_itembuy_maxtimes, ErrCode::pay_secretshop_buytimes); # 判断购买次数
  682. $shopItem = GameConfig::secretshop_typeId_getItem($itemId); # 常量数据
  683. $amt = $shopItem->price * pow(2, $cishu); # 计算价格
  684. switch ($shopItem->pricetype) {
  685. case 1:
  686. my_Assert($user->base(true)->Consume_Cash($amt), ErrCode::notenough_cash_msg); # 扣除钻石
  687. break;
  688. case 2:
  689. my_Assert($user->base(true)->Consume_Gold($amt), ErrCode::notenough_gold_msg); # 扣除金币
  690. break;
  691. default :
  692. return Resp::err(ErrCode::pay_m_type_err);
  693. }
  694. // 道具解包/发货
  695. $err = self::expendSecretShopItem($shopItem, $num); # 发放商品
  696. if ($err != ErrCode::ok) { # 发货失败
  697. return Resp::err($err);
  698. }
  699. $userSecretshop->currentItems->$itemId += 1; # 购买次数+1
  700. $user->userSecretshop = $userSecretshop;
  701. ctx($user);
  702. UserProc::updateUserInfo(); # 回写数据
  703. // StatProc::secretShopbuy($req->zoneid, $req->uid, $itemId, $num); # 统计/监控数据
  704. return Resp::ok(array(# # 成功后将最新的玩家数据返回给客户端
  705. 'gold' => $user->baseInfo->gold,
  706. 'tili' => $user->baseInfo->tili,
  707. 'cash' => $user->baseInfo->cash,
  708. 'store' => $user->baseInfo->store, # # 背包,(装备、碎片、。。)
  709. 'heros' => $user->baseInfo->heros # # 角色
  710. ));
  711. //
  712. }
  713. /**
  714. * [8807]【游戏内货币】购买普通商城物品
  715. */
  716. public static function m_pay() {
  717. $user = ctx(); # user引用
  718. my_Assert(count(req()->paras) >= 3, ErrCode::parasnotenough_msg); # 参数不足
  719. list($paytype, $itemId, $num) = req()->paras; # 付费类型, 1.钻石, 2.金币 ,道具ID ,数量, 默认为1
  720. my_Assert($num >= 1, ErrCode::paras_err); # 参数非法,
  721. $shopItem = GameConfig::shop_getItem($itemId); # 取商品的常量数据
  722. my_Assert(isset($shopItem), ErrCode::err_const_no); # 检测是否存在道具的常量数据
  723. my_Assert($shopItem->pricetype == $paytype, ErrCode::pay_price_err); # 商品定价类型检查
  724. $amt = $shopItem->price; # 道具价格(钻石)
  725. my_Assert($amt > 0, ErrCode::pay_price_err); # 商品定价数值检查
  726. $bDeal = false; # 成交标志位
  727. switch ($paytype) { # 1. 钻石, 2. 金币, other:非法
  728. case 1: # 钻石
  729. $bDeal = ctx()->base(true)->Consume_Cash($amt); # 更新(扣除)玩家游戏币(钻石)余额
  730. my_Assert($bDeal, ErrCode::notenough_cash_msg); # 防范扣除失败
  731. break;
  732. case 2: # 金币
  733. $bDeal = $user->base(true)->Consume_Gold($amt * $num); # 更新玩家金币余额
  734. my_Assert($bDeal, ErrCode::notenough_gold_msg); # 防范扣除失败
  735. break;
  736. default : # 未知的支付类型
  737. return Resp::err(ErrCode::pay_m_type_err);
  738. }
  739. my_Assert($bDeal, ErrCode::err_innerfault); # 交易失败
  740. $err = self::expendShopItem($shopItem, $num); # 发放商品(普通商城只有金币和体力)
  741. my_Assert(ErrCode::ok == $err, $err); # 防范发货失败
  742. UserProc::updateUserInfo(); # 回写数据
  743. // StatProc::shopbuy($zoneid, $uid, $itemId, $num); # 统计/监控数据
  744. return Resp::ok(array(# # 成功后将最新的玩家数据返回给客户端
  745. 'gold' => $user->baseInfo->gold,
  746. 'tili' => $user->baseInfo->tili,
  747. 'cash' => $user->baseInfo->cash,
  748. 'store' => $user->store
  749. ));
  750. }
  751. /**
  752. * 解包商城物品并发货
  753. * @param sm_Shop $shopItem
  754. * @param int $num 数量
  755. */
  756. private static function expendShopItem($shopItem, $num) {
  757. for ($i = 0; $i < $num; $i++) {
  758. $err = StoreProc::AddMultiItemInStore($shopItem->goods, '商城');
  759. my_Assert(ErrCode::ok == $err, $err);
  760. }
  761. return ErrCode::ok;
  762. }
  763. /**
  764. * 道具解包并发货(神秘商城)
  765. * @param sm_secretshop $shopItem
  766. * @param type $num
  767. */
  768. private static function expendSecretShopItem($shopItem, $num) {
  769. for ($i = 0; $i < $num; $i++) {
  770. $err = StoreProc::AddMultiItemInStore($shopItem->goods, '神秘商城');
  771. if ($err) {
  772. return $err;
  773. }
  774. }
  775. return ErrCode::ok;
  776. }
  777. // </editor-fold>
  778. //
  779. //
  780. // <editor-fold defaultstate="collapsed" desc=" 支付活动 - 首付礼包">
  781. /**
  782. * [8802] 领取首付礼包
  783. */
  784. public static function m_GetFirstPayGift() {
  785. //list($day) = req()->paras;
  786. // $itemId = glc()->FirstPay_ItemId;
  787. // $privateState = ctx()->privateState;
  788. //
  789. // if (CommUtil::isPropertyExists($privateState, "firstPayGift") #
  790. // && $privateState->firstPayGift) { # 如果已经领取首付礼包
  791. // return Resp::err(ErrCode::pay_firstpaygetted);
  792. // }
  793. // my_Assert(ctx()->baseInfo->charge_amt > 0, ErrCode::pay_firstpayno_err); # 如果尚未完成首付
  794. //
  795. // $itemModel = GameConfig::shop_getItem($itemId); # 取商品常量
  796. // if ($itemModel == null) { # 检测首付礼包是否存在
  797. // return Resp::err(ErrCode::err_const_no);
  798. // }
  799. // ctx()->privateState->firstPayGift = true; # 设置首付标志
  800. my_Assert(ctx()->baseInfo->charge_amt != 0, ErrCode::pay_firstpayno_err);
  801. //my_Assert(!in_array($day, ctx()->privateState->firstRechargeRewardRecord), ErrCode::pay_repeatReceive);
  802. // $ts = TimeUtil::totalDays(ctx()->privateState->firstRechargeTs);
  803. // $sTs = $ts + $day -1;
  804. // my_Assert(TimeUtil::totalDays() >= $sTs, ErrCode::pay_rewardReceive_ts_limit);
  805. for ($i = 1; $i <= ctx()->privateState->firstRecharge_receiveTag; $i++) {
  806. if (!in_array($i, ctx()->privateState->firstRechargeRewardRecord)) {
  807. ctx()->privateData(true)->firstRechargeRewardRecord[] = $i;
  808. $mo = GameConfig::firstrecharge_reward_getItem($i);
  809. my_Assert($mo != null, ErrCode::err_const_no);
  810. StoreProc::AddMultiItemInStore($mo->reward); # 发放首付礼包到玩家仓库
  811. }
  812. }
  813. ctx()->privateData(true)->firstRechargeUI_OpenTip = 0;
  814. UserProc::updateUserInfo(); # 更新玩家数据
  815. return Resp::ok(array('gold' => ctx()->baseInfo->gold,
  816. 'cash' => ctx()->baseInfo->cash,
  817. 'tili' => ctx()->baseInfo->tili,
  818. 'tili_ts' => ctx()->baseInfo->tili_ts,
  819. 'accumulateYuanBao' => ctx()->baseInfo->accumulateYuanBao,
  820. 'store' => ctx()->store,
  821. 'privateState' => ctx()->privateState,
  822. 'reward' => StoreProc::$reward,
  823. 'reward_Gem' => StoreProc::$reward_Gem,
  824. 'reward_equip' => StoreProc::$reward_equip,
  825. 'heros' => ctx()->heros,
  826. ));
  827. }
  828. public static function setFirstRechargeLoginTag() {
  829. if (ctx()->baseInfo->charge_amt == 0) {
  830. return;
  831. }
  832. if (ctx()->privateState->firstRecharge_receiveTag == 3) {
  833. return;
  834. }
  835. if (ctx()->privateState->firstRecharge_receiveTag < 1) {
  836. return;
  837. }
  838. ctx()->privateData(true)->firstRecharge_receiveTag += 1;
  839. }
  840. // </editor-fold>
  841. //
  842. //
  843. //
  844. }