OrderController.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  1. <?php
  2. /**
  3. * OrderController.php UTF-8
  4. * 小程序订单接口
  5. *
  6. * @date : 2018/8/9 22:38
  7. *
  8. * @license 这不是一个自由软件,未经授权不许任何使用和传播。
  9. * @author : wuyonghong <wyh@huosdk.com>
  10. * @version : HuoMp 1.0
  11. */
  12. namespace mini\sdk\controller;
  13. use huo\controller\common\HuoSession;
  14. use huo\controller\game\GameCache;
  15. use huo\controller\game\GamePaySwitchCache;
  16. use huo\controller\member\MemCache;
  17. use huo\controller\pay\GamePay;
  18. use huo\controller\pay\Notify;
  19. use huo\controller\pay\PaySwitch;
  20. use huo\controller\pay\PtbPay;
  21. use huo\controller\pay\Sdk;
  22. use huo\controller\pay\SdkOrderCache;
  23. use huo\model\member\MemGameModel;
  24. use huo\model\member\MemoauthModel;
  25. use huo\model\order\OrderModel;
  26. use huoAgentSwitch\controller\AgentSwitchController;
  27. use huolib\constant\CacheConst;
  28. use huolib\constant\CommonConst;
  29. use huolib\constant\GameConst;
  30. use huolib\constant\MemConst;
  31. use huolib\constant\MpConfConst;
  32. use huolib\constant\OauthConst;
  33. use huolib\constant\OrderConst;
  34. use huolib\constant\PaywayConst;
  35. use huolib\constant\WalletConst;
  36. use huolib\pay\Pay;
  37. use huolib\status\CommonStatus;
  38. use huolib\status\MemberStatus;
  39. use huolib\status\OrderStatus;
  40. use huolib\tool\RateLimit;
  41. use huolib\utils\OrderUtils;
  42. use huomp\controller\game\GameMini;
  43. use huomp\controller\order\OrderOut;
  44. use huomp\controller\share\QrCodeOut;
  45. use huomp\model\game\GameMiniModel;
  46. use huomp\model\weixin\MpConfModel;
  47. use huoMpQr\QrCode;
  48. use mini\common\controller\V2ApiBaseController;
  49. use think\Cache;
  50. use think\Log;
  51. class OrderController extends V2ApiBaseController {
  52. public function _initialize() {
  53. parent::_initialize();
  54. // Log::write(
  55. // $this->request->scheme().'://'.$this->request->server('HTTP_HOST').$this->request->server('REQUEST_URI').'?'
  56. // .$this->request->getContent(),
  57. // Log::LOG
  58. // );
  59. }
  60. /**
  61. * 预下单
  62. * http://doc.1tsdk.com/159?page_id=4381
  63. * 【域名】/mp/preorder
  64. */
  65. public function preorder() {
  66. $this->checkLogin();
  67. $_rs = (new RateLimit())->rateLimit($this->mem_id, true, true, 1, 3);
  68. if (false == $_rs) {
  69. $_code = CommonStatus::TOO_MANY_REQUESTS;
  70. $this->error(CommonStatus::getMsg($_code));
  71. }
  72. $_game_rq = $this->setGameData();
  73. $_channel_rq = $this->setChannelData();
  74. $_device_rq = $this->setDeviceData();
  75. $_mem_rq = $this->setMemData();
  76. $_role_rq = $this->setRoleData();
  77. $_order_rq = $this->setOrderData();
  78. $_mem_data = MemCache::ins()->getInfoById($this->mem_id);
  79. if (isset($_mem_data['status']) && $_mem_data['status'] == MemConst::STATUS_FORBID) {
  80. $_code = MemberStatus::LOGIN_IS_OUT;
  81. $this->error(lang(MemberStatus::getMsg($_code)), [], $_code);
  82. }
  83. $_mem_game_info = (new MemGameModel())->getInfoByAppMemId($_game_rq->getHAppId(), $this->mem_id);
  84. $_agent_id = $_mem_game_info['guided_agent_id'] ?? 0;
  85. if (empty($_agent_id)) {
  86. $_agent_id = $_mem_data['agent_id'] ?? 0;
  87. }
  88. $_mem_rq->setAgentId($_agent_id);
  89. $_channel_rq->setAgentId($_agent_id);
  90. $_order = new Sdk();
  91. $_pay_check = OrderConst::PAY_SWITCH_NO;
  92. /* 判断支付切换 */
  93. if (GameConst::GAME_MP_GAME == $_game_rq->getPkgName()) {
  94. $_pay_check = (new PaySwitch())->getPaySwitch(
  95. $_order_rq, $_role_rq, $_mem_rq, $_game_rq, $_channel_rq, $_device_rq
  96. );
  97. }
  98. $_is_sand = false;
  99. if (GameConst::GAME_MP_GAME == $_game_rq->getPkgName()) {
  100. /* 判断是否上线 上线使用正式环境 未上线使用沙盒环境 */
  101. $_game_data = GameCache::ins()->getInfoByAppId($_game_rq->getHAppId());
  102. $_pay_way = PaywayConst::PAYWAY_MPAY;
  103. if (GameConst::GAME_STATUS_ACCESS == $_game_data['status']) {
  104. $_is_sand = true;
  105. $_pay_way = PaywayConst::PAYWAY_MPAY_TEST;
  106. }
  107. $_order_rq->setPayway($_pay_way);
  108. }
  109. $_preorder_rs = $_order->preorder($_order_rq, $_role_rq, $_mem_rq, $_game_rq, $_channel_rq, $_device_rq);
  110. if (OrderStatus::NO_ERROR != $_preorder_rs['code']) {
  111. $this->returnData($_preorder_rs);
  112. }
  113. $_order_id = $_preorder_rs['data']['order_id'];
  114. $_pay_token = $_order_rq->genPayToken($_order_id);
  115. $_rdata['order_id'] = $_order_id;
  116. $_rdata['pay_token'] = $_pay_token;
  117. $_rdata['check'] = $_pay_check;
  118. $_rdata['pay_url'] = '';
  119. if (GameConst::GAME_MP_GAME == $_game_rq->getPkgName()) {
  120. $_mp_data = (new OrderOut())->getMpayData($_order_id, $_is_sand);
  121. $_rdata = array_merge($_rdata, $_mp_data['data']);
  122. }
  123. $this->success(lang('SUCCESS'), $_rdata);
  124. }
  125. /**
  126. * 获取订单ID
  127. *
  128. * @return mixed|string
  129. */
  130. protected function getOrderId() {
  131. $_order_rq = $this->setOrderData();
  132. $_order_id = $_order_rq->getOrderId();
  133. if (empty($_order_id)) {
  134. $_order_id = get_val($this->rq_data, 'order_id');
  135. }
  136. $_order_id = urldecode($_order_id);
  137. if (strpos($_order_id, '&')) {
  138. $_mem_app_arr = explode('&', $_order_id);
  139. $_mem_id = $_mem_app_arr['0'];
  140. $_app_id = $_mem_app_arr['1'];
  141. $_order_id = (new OrderModel())->getLastOrderId($_mem_id, $_app_id);
  142. }
  143. return $_order_id;
  144. }
  145. /**
  146. * 点击支付
  147. * http://doc.1tsdk.com/159?page_id=4383
  148. *【域名】/mp/wx/pay
  149. */
  150. public function pay() {
  151. $this->checkLogin();
  152. $_rs = (new RateLimit())->rateLimit($this->mem_id, true, true, 1, 3);
  153. if (false == $_rs) {
  154. $_code = CommonStatus::TOO_MANY_REQUESTS;
  155. $this->error(CommonStatus::getMsg($_code));
  156. }
  157. $_game_rq = $this->setGameData();
  158. $_app_id = $_game_rq->getHAppId();
  159. $_order_rq = $this->setOrderData();
  160. $_order_id = $this->getOrderId();
  161. $_payway = get_val($this->rq_data, 'payway', '');
  162. $_pw_check_rs = OrderUtils::checkPayway($_payway);
  163. if (OrderStatus::NO_ERROR != $_pw_check_rs) {
  164. $this->error(OrderStatus::getMsg($_pw_check_rs), [], $_pw_check_rs);
  165. }
  166. /* 判断是否使用平台币 */
  167. $_has_ptb = get_val($this->rq_data, 'has_ptb', 1);
  168. if (OrderConst::PAY_HAS_PTB == $_has_ptb) {
  169. /* 使用平台币 先记录入缓存 */
  170. $_rdata = (new PtbPay())->PtbOrder($_order_id);
  171. if (OrderStatus::NO_ERROR != $_rdata['code']) {
  172. $this->returnData($_rdata);
  173. }
  174. }
  175. $_order_data = SdkOrderCache::ins()->getInfoByOrderId($_order_id);
  176. if (empty($_order_data)) {
  177. $_code = OrderStatus::ORDER_NOT_EXISTS;
  178. $this->error(OrderStatus::getMsg($_code), [], $_code);
  179. }
  180. if ($_order_data['real_amount'] <= CommonConst::CONST_ZERO_COMPARE) {
  181. /* 完全使用平台币支付 */
  182. $_rs = (new PtbPay())->ptbSdkPay($_order_id);
  183. $this->returnData($_rs);
  184. }
  185. /* 游戏币消费 特有流程 */
  186. if (PaywayConst::PAYWAY_GAMEPAY == strtolower($_payway)) {
  187. $_rs = (new GamePay())->GameSdkPay($_order_id);
  188. $this->returnData($_rs);
  189. }
  190. $_order_rq->setDataFromOrder($_order_data);
  191. $_pay_class = Pay::ins()->get($_payway);
  192. /* 微信支付 小程序支付 */
  193. $_func = 'mpPay';
  194. $_config = (new GameMini())->getPayConf($_app_id);
  195. $_show_url = url(
  196. 'sdk/'.$_payway.'/showUrl', ['order_id' => $_order_id],
  197. false, MPSITE
  198. );
  199. $_return_url = url(
  200. 'sdk/'.$_payway.'/returnUrl',
  201. ['order_id' => $_order_id], false, MPSITE
  202. );
  203. $_notify_url = url('sdk/'.$_payway.'/notifyUrl', '', false, MPSITE);
  204. // Log::write(
  205. // array($_show_url, $_return_url, $_notify_url),
  206. // Log::ERROR
  207. // );
  208. $_pay_class->setNotifyUrl($_notify_url);
  209. $_pay_class->setReturnUrl($_return_url);
  210. $_pay_class->setShowUrl($_show_url);
  211. $_pay_class->setOrderId($_order_id);
  212. $_pay_class->setProductName($_order_rq->getProductName());
  213. $_pay_class->setProductDesc($_order_rq->getProductDesc());
  214. $_pay_class->setRealAmount($_order_rq->getProductRealPrice());
  215. $_pay_class->setProductPrice($_order_rq->getProductPrice());
  216. $_pay_class->setProductId(WalletConst::WALLET_PRODUCT_MP);
  217. $_pay_class->setIp($this->request->ip());
  218. $_pay_class->setPayway($_payway);
  219. //$_pay_class->setOpenId((new HuoSession($this->mem_id, $_app_id))->getOpenId());
  220. $_conf_id = (new MpConfModel())->getIdByAppId($_app_id, MpConfConst::MP_CONF_TYPE_6);
  221. $_openid = (new MemoauthModel())->getOpenidByMemId(OauthConst::OAUTH_MP, $this->mem_id, $_conf_id);
  222. $_pay_class->setOpenId($_openid);
  223. // Log::write(
  224. // array($_config, $_pay_class),
  225. // Log::ERROR
  226. // );
  227. $_pay_rs = $_pay_class->$_func($_config);
  228. if (empty($_pay_rs)) {
  229. $_code = OrderStatus::PAYWAY_PREORDER_ERROR;
  230. $this->error(OrderStatus::getMsg($_code), [], $_code);
  231. }
  232. /* 更新支付方式 */
  233. $_pay_alias = $_pay_rs['pay_type'];
  234. $_order_data['payway'] = $_pay_alias;
  235. $_order_data = (new AgentSwitchController())->orderSwitch($_order_data);
  236. SdkOrderCache::ins()->updateOrder($_order_id, $_order_data);
  237. $_code = OrderStatus::NO_ERROR;
  238. $this->success(OrderStatus::getMsg($_code), $_pay_rs, $_code);
  239. }
  240. /**
  241. * 查询支付结果
  242. * http://doc.1tsdk.com/159?page_id=4384
  243. * 【域名】/mp/order/query
  244. */
  245. public function read() {
  246. $_rs = (new RateLimit())->rateLimit($this->mem_id, true, true, 1, 3);
  247. if (false == $_rs) {
  248. $_code = CommonStatus::TOO_MANY_REQUESTS;
  249. $this->error(CommonStatus::getMsg($_code));
  250. }
  251. $_order_rq = $this->setOrderData();
  252. $_order = new Sdk();
  253. $_rdata = $_order->getStatus($_order_rq->getOrderId());
  254. if (false == $_rdata) {
  255. $this->error('ERROR');
  256. }
  257. if (OrderConst::CP_STATUS_SUC != $_rdata['cp_status'] && OrderConst::PAY_STATUS_SUC == $_rdata['status']) {
  258. $_rs = (new Notify())->notify($_order_rq->getOrderId());
  259. if (OrderStatus::NO_ERROR == $_rs['code']) {
  260. $_rdata['status'] = OrderConst::PAY_STATUS_SUC;
  261. $_rdata['cp_status'] = OrderConst::CP_STATUS_SUC;
  262. }
  263. }
  264. $_rdata['order_id'] = $_order_rq->getOrderId();
  265. $this->success(lang('SUCCESS'), $_rdata);
  266. }
  267. /**
  268. * 获取订单信息
  269. * http://doc.1tsdk.com/159?page_id=4465
  270. * 【域名】/mp/pay/info
  271. */
  272. public function getInfo() {
  273. $this->checkLogin();
  274. $_order_id = $this->getOrderId();
  275. $_rdata = (new Sdk())->getPayInfo($_order_id);
  276. $this->returnData($_rdata);
  277. }
  278. /**
  279. * 获取跳转支付信息
  280. * http://doc.1tsdk.com/159?page_id=4805
  281. * 【域名】/mp/order/checkinfo
  282. */
  283. public function getSwitchInfo() {
  284. $_game_rq = $this->setGameData();
  285. $_path = 'pages/pay/index';
  286. $_order_rq = $this->setOrderData();
  287. $_order_id = $_order_rq->getOrderId();
  288. if (empty($_order_id)) {
  289. $_order_id = get_val($this->rq_data, 'order_id');
  290. }
  291. $_switch_rule = GamePaySwitchCache::ins()->getInfoByAppId($_game_rq->getHAppId());
  292. $_rdata['mp_id'] = '';
  293. $_rdata['pay_type'] = 0;
  294. if (!empty($_switch_rule)) {
  295. $_rdata['pay_type'] = $_switch_rule['pay_type'];
  296. if (OrderConst::PAY_SWITCH_PAY_TYPE_2 != $_switch_rule['pay_type']) {
  297. $_path = $_switch_rule['pages'];
  298. $_switch_app_id = $_switch_rule['switch_app_id'];
  299. $_rdata['mp_id'] = (new GameMiniModel())->getMpIdByAppId($_switch_app_id);
  300. }
  301. if (OrderConst::PAY_SWITCH_PAY_TYPE_4 == $_switch_rule['pay_type']) {
  302. /* 客服跳转充值 需将当前单号写入缓存,缓存时间为5分钟,缓存失效前每次进入客服都将弹出该未支付订单 */
  303. $_key = CacheConst::CACHE_CUSTOMER_ORDER_PAY_PREFIX.$this->mem_id;
  304. Cache::set($_key, $_order_id, CommonConst::CONST_5_MINUTE_SECONDS);
  305. }
  306. }
  307. $_rdata['path'] = $_path.'?orderId='.$_order_id.'&from=2';
  308. $_rdata['intro'] = '点击二维码,长按识别支付';
  309. $_order_data = SdkOrderCache::ins()->getInfoByOrderId($_order_id);
  310. if (!empty($_order_data)) {
  311. $_order_out = new OrderOut();
  312. $_image = $_order_out->getMemAppQrCode($_order_data['mem_id'], $_order_data['app_id']);
  313. if (!empty($_image)) {
  314. $_rdata['image'] = $_image;
  315. #$_rdata['poster_img'] = (new QrCode())->getPosterImg($_image);
  316. $_rdata['poster_img'] = $_rdata['image'];
  317. }
  318. }
  319. $this->success(lang('SUCCESS'), $_rdata);
  320. }
  321. /**
  322. * 获取切换二维码
  323. * http://doc.1tsdk.com/159?page_id=4491
  324. * 【域名】/mp/order/qrcode
  325. */
  326. public function getQrCode() {
  327. $_game_rq = $this->setGameData();
  328. $_order_rq = $this->setOrderData();
  329. $_order_id = $_order_rq->getOrderId();
  330. if (empty($_order_id)) {
  331. $_order_id = get_val($this->rq_data, 'order_id');
  332. }
  333. $_is_last = $this->request->param('is_last/d', 0);
  334. if (OrderConst::ORDER_SWITCH_LAST == $_is_last) {
  335. $_rdata['code'] = CommonStatus::INVALID_PARAMS;
  336. $_rdata['msg'] = CommonStatus::getMsg($_rdata['code']);
  337. $_rdata['data'] = [];
  338. $_order_data = SdkOrderCache::ins()->getInfoByOrderId($_order_id);
  339. if (!empty($_order_data)) {
  340. $_image = (new OrderOut())->getMemAppQrCode($_order_data['mem_id'], $_order_data['app_id'], true);
  341. if (!empty($_image)) {
  342. $_rdata['code'] = CommonStatus::NO_ERROR;
  343. $_rdata['msg'] = CommonStatus::getMsg($_rdata['code']);
  344. $_rdata['data']['image'] = $_image;
  345. }
  346. }
  347. } else {
  348. $_path = 'pages/pay/index';
  349. $_switch_rule = GamePaySwitchCache::ins()->getInfoByAppId($_game_rq->getHAppId());
  350. $_rdata['mp_id'] = '';
  351. $_switch_app_id = 0;
  352. if (!empty($_switch_rule)) {
  353. $_path = $_switch_rule['pages'];
  354. $_switch_app_id = $_switch_rule['switch_app_id'];
  355. }
  356. $_width = get_val($this->rq_data, 'width', 430);
  357. $_a_color = get_val($this->rq_data, 'auto_color', 1);
  358. $_line_color = get_val($this->rq_data, 'line_color', '{"r":"0","g":"0","b":"0"}');
  359. $_hyaline = get_val($this->rq_data, 'is_hyaline', 1);
  360. $_auto_color = false;
  361. $_is_hyaline = false;
  362. if (2 == $_a_color) {
  363. $_auto_color = true;
  364. }
  365. if (2 == $_hyaline) {
  366. $_is_hyaline = true;
  367. }
  368. $_rdata = (new QrCodeOut())->getOrderQrCode(
  369. $_order_id, $_switch_app_id, $_path, $_width, $_auto_color, $_line_color, $_is_hyaline
  370. );
  371. }
  372. $this->returnData($_rdata);
  373. }
  374. }