refill.php 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623
  1. <?php
  2. require_once(BASE_HELPER_PATH . '/refill/RefillFactory.php');
  3. require_once(BASE_HELPER_PATH . '/mtopcard/mtopcard.php');
  4. require_once(BASE_HELPER_PATH . '/model/member_info.php');
  5. //商家充值接口中心
  6. class refillControl extends merchantControl
  7. {
  8. public function __construct()
  9. {
  10. parent::__construct();
  11. }
  12. public function goodsOp()
  13. {
  14. $goods_list = refill\RefillFactory::instance()->goods();
  15. $sorter = function (array $items)
  16. {
  17. $ret = [];
  18. foreach ($items as $key => $val) {
  19. sort($val);
  20. $ret[$key] = $val;
  21. }
  22. return $ret;
  23. };
  24. $goods_list = $sorter($goods_list);
  25. $result = [];
  26. $mchid = $this->mchid();
  27. $merchant_goods = rcache('merchant_goods', 'refill-', $mchid);
  28. $goods = $merchant_goods[$mchid] ?? serialize([]);
  29. $goods = unserialize($goods);
  30. foreach ($goods_list as $card_type => $value) {
  31. $key = mtopcard\scard_type($card_type);
  32. if (array_key_exists($key, $goods)) {
  33. $result[$key] = $goods[$key];
  34. } else {
  35. $result[$key] = $value;
  36. }
  37. }
  38. $thrid_refill = Model('thrid_refill');
  39. $pcode = $thrid_refill->getMerchantPcode($mchid);
  40. $result['third'] = $pcode;
  41. return self::outsuccess($result);
  42. }
  43. private function check_params($params)
  44. {
  45. if(empty($params['cardno'])) {
  46. return [false,'参数没有包含cardno'];
  47. }
  48. if(empty($params['amount'])) {
  49. return [false,'参数没有包含充值金额:amount'];
  50. }
  51. $card_no = $_GET['cardno'];
  52. $card_type = mtopcard\simple_card_type($card_no);
  53. if($card_type == mtopcard\UnknownCard) {
  54. return [false,'卡类型无法识别'];
  55. }
  56. if(empty($params['notifyurl'])) {
  57. return [false,'参数没有包含notifyurl'];
  58. }
  59. if(empty($params['order_sn'])) {
  60. return [false,'参数没有包含贵方唯一订单号:order_sn'];
  61. }
  62. return [true,""];
  63. }
  64. public function addOp()
  65. {
  66. [$success,$error] = $this->check_params($_GET);
  67. if($success === false) {
  68. return self::outerr(201,$error);
  69. }
  70. $amount = intval($_GET['amount']);
  71. $card_no = trim($_GET['cardno']);
  72. $notify_url = $_GET['notifyurl'];
  73. $mch_order = $_GET['order_sn']; //对方的order编号
  74. $quality = $_GET['quality'] ?? 0;
  75. $bind_phone = $_GET['bind_phone'] ?? '';
  76. if(!$this->check_mchorder($this->mchid(),$mch_order)) {
  77. return self::outerr(205,"客户订单号重复或者为空.");
  78. }
  79. $card_type = mtopcard\simple_card_type($card_no);
  80. if($card_type === mtopcard\SinopecCard || $card_type === mtopcard\PetroChinaCard)
  81. {
  82. refill\util::write_card($card_no,$card_type,$bind_phone);
  83. if(!$this->can_refill($card_no)) {
  84. return self::outerr(206,"平台不支持该卡充值.");
  85. }
  86. $allow = true;
  87. if(!$allow)
  88. {
  89. if ($card_type === mtopcard\SinopecCard) {
  90. $text = "中石化";
  91. }
  92. else {
  93. $text = "中石油";
  94. }
  95. return self::outerr(207,"今日贵司$amount {$text}充值库存已经用完.");
  96. }
  97. }
  98. $order_time = time();
  99. $params = ['mchid' => $this->mchid(),
  100. 'buyer_id' => $this->adminid(),
  101. 'amount' => $amount,
  102. 'card_no' => $card_no,
  103. 'mch_order' => $mch_order,
  104. 'notify_url' => $notify_url,
  105. 'org_quality' => $quality,
  106. 'order_time' => $order_time
  107. ];
  108. refill\util::push_queue_order($this->mchid(),$mch_order,ORDER_STATE_QUEUE);
  109. Model('refill_order')->add_detail($this->mchid(),$mch_order,$order_time,$params,ORDER_STATE_QUEUE);
  110. [$can_refill, $period] = refill\util::can_commit($card_no, $card_type);
  111. if ($can_refill === false) {
  112. $state = refill\util::async_add($params, $period);
  113. } else {
  114. $state = refill\util::push_add($params);
  115. }
  116. $mchid = $this->mchid();
  117. if ($state === true) {
  118. Log::record("refill::util::push_add success mchid={$mchid} mch_order={$mch_order} state={$state}",Log::DEBUG);
  119. return self::outsuccess(['state' => true]);
  120. } else {
  121. refill\util::del_queue_order($this->mchid(),$mch_order);
  122. Model('refill_order')->del_detail($this->mchid(),$mch_order);
  123. Log::record("refill::util::push_add error mchid={$mchid} mch_order={$mch_order} state={$state}",Log::DEBUG);
  124. return self::outerr(208, '提交失败');
  125. }
  126. }
  127. private function check_third($params)
  128. {
  129. if(empty($params['product_code'])) {
  130. return [false,'参数没有包含product_code'];
  131. }
  132. $pcode = $params['product_code'];
  133. if($this->check_pcode($pcode) == false) {
  134. return [false,"对应的产品编码{$pcode}"];
  135. }
  136. if(empty($params['quantity']) || intval($params['quantity']) < 1) {
  137. return [false,"购买数量参数不存在,或者小于0"];
  138. }
  139. if(empty($params['notifyurl'])) {
  140. return [false,'参数没有包含notifyurl'];
  141. }
  142. if(empty($params['order_sn'])) {
  143. return [false,'参数没有包含贵方唯一订单号:order_sn'];
  144. }
  145. return [true,""];
  146. }
  147. private function check_pcode($pcode)
  148. {
  149. $mod_third = Model('thrid_refill');
  150. $product = $mod_third->getProduct(['system_code' => $pcode]);
  151. return !empty($product);
  152. }
  153. private function add_third_product($third_product_type)
  154. {
  155. [$success,$error] = $this->check_third($_GET);
  156. if($success === false) {
  157. return self::outerr(201,$error);
  158. }
  159. $amount = refill\util::ThirdRefillAmount;
  160. $notify_url = $_GET['notifyurl'];
  161. $mch_order = $_GET['order_sn']; //对方的order编号
  162. $product_code = $_GET['product_code'];
  163. $card_no = $_GET['cardno'] ?? '';
  164. $quantity = $_GET['quantity'];
  165. $third_card_type = $_GET['card_type'] ?? 1;
  166. //三方充值没有质量
  167. $quality = 1;
  168. $card_type = mtopcard\ThirdRefillCard;
  169. if(!$this->check_mchorder($this->mchid(),$mch_order)) {
  170. return self::outerr(205,"客户订单号重复或者为空.");
  171. }
  172. $order_time = time();
  173. $params = ['mchid' => $this->mchid(),
  174. 'buyer_id' => $this->adminid(),
  175. 'amount' => $amount,
  176. 'mch_order' => $mch_order,
  177. 'notify_url' => $notify_url,
  178. 'org_quality' => $quality,
  179. 'card_type' => $card_type,
  180. 'card_no' => $card_no,
  181. 'product_code' => $product_code,
  182. 'quantity' => $quantity,
  183. 'third_card_type' => $third_card_type,
  184. 'third_product_type' => $third_product_type,
  185. 'order_time' => $order_time
  186. ];
  187. refill\util::push_queue_order($this->mchid(),$mch_order,ORDER_STATE_QUEUE);
  188. Model('refill_order')->add_detail($this->mchid(), $mch_order, $order_time, $params, ORDER_STATE_QUEUE);
  189. $state = refill\util::push_addthird($params);
  190. if ($state === true) {
  191. return self::outsuccess(['state' => true]);
  192. } else {
  193. refill\util::del_queue_order($this->mchid(),$mch_order);
  194. Model('refill_order')->del_detail($this->mchid(),$mch_order);
  195. return self::outerr(208, '提交失败');
  196. }
  197. }
  198. public function add_thirdOp()
  199. {
  200. return $this->add_third_product(mtopcard\ThirdOnlineProduct);
  201. }
  202. public function add_netOp()
  203. {
  204. return $this->add_third_product(mtopcard\ThirdNetTrafficPoroduct);
  205. }
  206. private function check_electirc($params)
  207. {
  208. if(empty($params['cardno'])) {
  209. return [false,'参数没有包含cardno'];
  210. }
  211. if(empty($params['notifyurl'])) {
  212. return [false,'参数没有包含notifyurl'];
  213. }
  214. if(empty($params['order_sn'])) {
  215. return [false,'参数没有包含贵方唯一订单号:order_sn'];
  216. }
  217. if(empty($params['amount']) || intval($params['amount']) <= 0) {
  218. return [false,'参数没有包含充值金额:amount'];
  219. }
  220. if(empty($params['company_type']) || !in_array($params['company_type'],mtopcard\ElectricCompanyTypes)) {
  221. return [false,'没有电卡类型参数(nation,south)'];
  222. }
  223. if(empty($params['use_type']) || !in_array($params['use_type'],mtopcard\ElectricUseTypes)) {
  224. return [false,"没有电卡用途参数(home,commerce,pedlar)"];
  225. }
  226. if(empty($params['province']) || !array_key_exists($params['province'],mtopcard\ProvinceList)) {
  227. return [false,"请传入省份"];
  228. }
  229. if(empty($params['city'])) {
  230. return [false,"请传入城市名称"];
  231. }
  232. //如果是南方电网需要带身份证后六位
  233. if($params['company_type'] === 'south')
  234. {
  235. $card_id = $params['card_id'];
  236. if(empty($card_id) || strlen($card_id) != mtopcard\CardidVerifyLength || !mtopcard\is_alpha($card_id)) {
  237. return [false,"请传入正确的身份证后6位"];
  238. }
  239. }
  240. return [true,""];
  241. }
  242. public function add_electricOp()
  243. {
  244. [$success,$error] = $this->check_electirc($_GET);
  245. if($success === false) {
  246. return self::outerr(201,$error);
  247. }
  248. $notify_url = $_GET['notifyurl'];
  249. $mch_order = $_GET['order_sn']; //对方的order编号
  250. $card_no = $_GET['cardno'] ?? '';
  251. $quantity = 1;
  252. $third_card_type = mtopcard\ThirdCardElect;
  253. $company_type = $_GET['company_type'];
  254. $use_type = $_GET['use_type'];
  255. $province = intval($_GET['province']);
  256. $city = $_GET['city'];
  257. $amount = intval($_GET['amount']);
  258. if($company_type == 'nation') {
  259. $card_id = '';
  260. } else {
  261. $card_id = $_GET['card_id'] ?? '';
  262. }
  263. $product_code = mtopcard\electric_product_code($company_type,$use_type,$amount);
  264. $amount = refill\util::ThirdRefillAmount;
  265. //三方充值没有质量
  266. $quality = 1;
  267. $card_type = mtopcard\ThirdRefillCard;
  268. if(!$this->check_mchorder($this->mchid(),$mch_order)) {
  269. return self::outerr(205,"客户订单号重复或者为空.");
  270. }
  271. $order_time = time();
  272. $params = ['mchid' => $this->mchid(),
  273. 'buyer_id' => $this->adminid(),
  274. 'amount' => $amount,
  275. 'mch_order' => $mch_order,
  276. 'notify_url' => $notify_url,
  277. 'org_quality' => $quality,
  278. 'card_type' => $card_type,
  279. 'card_no' => $card_no,
  280. 'product_code' => $product_code,
  281. 'quantity' => $quantity,
  282. 'third_card_type' => $third_card_type,
  283. 'third_product_type' => mtopcard\ThirdElectricProduct,
  284. 'company_type' => $company_type,
  285. 'use_type' => $use_type,
  286. 'province' => $province,
  287. 'city' => $city,
  288. 'card_id' => $card_id,
  289. 'order_time' => $order_time
  290. ];
  291. refill\util::push_queue_order($this->mchid(), $mch_order, ORDER_STATE_QUEUE);
  292. Model('refill_order')->add_detail($this->mchid(), $mch_order, $order_time, $params, ORDER_STATE_QUEUE);
  293. $state = refill\util::push_addthird($params);
  294. if ($state === true) {
  295. return self::outsuccess(['state' => true]);
  296. } else {
  297. refill\util::del_queue_order($this->mchid(),$mch_order);
  298. Model('refill_order')->del_detail($this->mchid(),$mch_order);
  299. return self::outerr(208, '提交失败');
  300. }
  301. }
  302. private function check_sinopec_coupon($params)
  303. {
  304. if(empty($params['cardno'])) {
  305. return [false,'参数没有包含cardno'];
  306. }
  307. if(empty($params['notifyurl'])) {
  308. return [false,'参数没有包含notifyurl'];
  309. }
  310. if(empty($params['order_sn'])) {
  311. return [false,'参数没有包含贵方唯一订单号:order_sn'];
  312. }
  313. if(empty($params['amount']) || intval($params['amount']) <= 0) {
  314. return [false,'参数没有包含充值金额:amount'];
  315. }
  316. if(empty($params['province']) || !array_key_exists($params['province'],mtopcard\ProvinceList)) {
  317. return [false,"请传入省份"];
  318. }
  319. return [true,""];
  320. }
  321. public function add_sinopec_couponOp()
  322. {
  323. [$success,$error] = $this->check_sinopec_coupon($_GET);
  324. if($success === false) {
  325. return self::outerr(201,$error);
  326. }
  327. $notify_url = $_GET['notifyurl'];
  328. $mch_order = $_GET['order_sn']; //对方的order编号
  329. $card_no = $_GET['cardno'] ?? '';
  330. $quantity = 1;
  331. $third_card_type = mtopcard\ThirdCardPhone;
  332. $province = intval($_GET['province']);
  333. $amount = intval($_GET['amount']);
  334. $product_code = mtopcard\sino_coupon_product_code($amount);
  335. $amount = refill\util::ThirdRefillAmount;
  336. //三方充值没有质量
  337. $quality = 1;
  338. $card_type = mtopcard\ThirdRefillCard;
  339. if(!$this->check_mchorder($this->mchid(),$mch_order)) {
  340. return self::outerr(205,"客户订单号重复或者为空.");
  341. }
  342. $order_time = time();
  343. $params = ['mchid' => $this->mchid(),
  344. 'buyer_id' => $this->adminid(),
  345. 'amount' => $amount,
  346. 'mch_order' => $mch_order,
  347. 'notify_url' => $notify_url,
  348. 'org_quality' => $quality,
  349. 'card_type' => $card_type,
  350. 'card_no' => $card_no,
  351. 'product_code' => $product_code,
  352. 'quantity' => $quantity,
  353. 'third_card_type' => $third_card_type,
  354. 'third_product_type' => mtopcard\ThirdSinopecECouponPoroduct,
  355. 'province' => $province,
  356. 'order_time' => $order_time
  357. ];
  358. refill\util::push_queue_order($this->mchid(),$mch_order,ORDER_STATE_QUEUE);
  359. Model('refill_order')->add_detail($this->mchid(), $mch_order, $order_time, $params, ORDER_STATE_QUEUE);
  360. $state = refill\util::push_addthird($params);
  361. if ($state === true) {
  362. return self::outsuccess(['state' => true]);
  363. } else {
  364. refill\util::del_queue_order($this->mchid(),$mch_order);
  365. Model('refill_order')->partition(refill\util::part_query($order_time))->del_detail($this->mchid(),$mch_order);
  366. return self::outerr(208, '提交失败');
  367. }
  368. }
  369. private function can_refill($cardno)
  370. {
  371. $card_info = refill\util::read_card($cardno);
  372. if(empty($card_info)) return false;
  373. return intval($card_info['black_card']) === 0;
  374. }
  375. private function check_mchorder($mchid,$mch_order)
  376. {
  377. if (empty($mch_order)) {
  378. return false;
  379. } else {
  380. $refill_order = Model('refill_order');
  381. $ret = $refill_order->exist($mchid, $mch_order, refill\util::part_query());
  382. return ($ret == false);
  383. }
  384. }
  385. public function balanceOp()
  386. {
  387. $uid = $this->adminid();
  388. $minfo = new member_info($uid);
  389. $available = $minfo->available_predeposit();
  390. $mchinfo = Model('merchant')->getMerchantInfo(['mchid' => $this->mchid()]);
  391. $available = ncPriceFormat($available - $mchinfo['credit_bonus']);
  392. $credit = ncPriceFormat($mchinfo['credit_bonus']);
  393. return self::outsuccess(['balance' => $available,'credit' => $credit]);
  394. }
  395. public function query_tradeOp()
  396. {
  397. $mchid = $this->mchid();
  398. $trade_no = $_GET['trade_no'];
  399. if(empty($trade_no)) {
  400. return self::outerr(201,"交易号trade_no错误");
  401. }
  402. $mod_refill = Model('refill_order');
  403. $refill_info = $mod_refill->getOrderInfo(['order_sn' => $trade_no,'mchid' => $mchid]);
  404. $vr_order = Model('vr_order');
  405. $order_info = $vr_order->getOrderInfo(['order_sn' => $trade_no]);
  406. if(empty($refill_info) || empty($order_info)) {
  407. return self::outerr(201,"无此交易号");
  408. }
  409. $result = $this->format($order_info,$refill_info);
  410. return self::outsuccess($result);
  411. }
  412. private function format($order_info,$refill_info)
  413. {
  414. $result = [];
  415. $result['mchid'] = $refill_info['mchid'];
  416. $result['trade_no'] = $refill_info['order_sn'];
  417. $result['order_sn'] = $refill_info['mch_order'];
  418. $result['card_no'] = $refill_info['card_no'];
  419. $result['card_type'] = $refill_info['card_type'];
  420. $result['refill_amount'] = $refill_info['refill_amount'];
  421. $result['order_amount'] = $refill_info['mch_amount'];
  422. $result['order_time'] = $refill_info['order_time'];
  423. $result['success_time'] = $refill_info['notify_time'];
  424. $result['official_sn'] = $refill_info['official_sn'] ?? "";
  425. $result['order_state'] = $order_info['order_state'];
  426. return $result;
  427. }
  428. private function format_success($order_info,$refill_info)
  429. {
  430. $result = [];
  431. $result['mchid'] = $refill_info['mchid'];
  432. $result['trade_no'] = $refill_info['order_sn'];
  433. $result['order_sn'] = $refill_info['mch_order'];
  434. $result['card_no'] = $refill_info['card_no'];
  435. $result['card_type'] = $refill_info['card_type'];
  436. $result['refill_amount'] = $refill_info['refill_amount'];
  437. $result['order_amount'] = $refill_info['mch_amount'];
  438. $result['order_time'] = $refill_info['order_time'];
  439. $result['success_time'] = $refill_info['notify_time'];
  440. $result['official_sn'] = "";
  441. $result['order_state'] = ORDER_STATE_SUCCESS;
  442. return $result;
  443. }
  444. public function queryOp()
  445. {
  446. $detail_checker = function($mchid, $mch_order)
  447. {
  448. $mod_refill = Model('refill_order');
  449. $detail = $mod_refill->get_detail($mchid,$mch_order);
  450. if (empty($detail)) {
  451. return false;
  452. } else {
  453. return true;
  454. }
  455. };
  456. $mchid = $this->mchid();
  457. $mch_order = $_GET['order_sn']; //用户方的订单号,对应数据库中的mch_order
  458. if(empty($mch_order)) {
  459. return self::outerr(201,"客户订单号order_sn错误");
  460. }
  461. $send = ['mchid' => $mchid,'order_sn' => $mch_order,'order_state' => ORDER_STATE_SEND];
  462. $order_state = refill\util::query_queue_order($mchid,$mch_order);
  463. if ($order_state == ORDER_STATE_QUEUE || $order_state == ORDER_STATE_SEND) {
  464. Log::record("query_state in queue mchid=$mchid mch_order=$mch_order order_state=$order_state" ,Log::DEBUG);
  465. return self::outsuccess($send);
  466. }
  467. elseif($order_state == ORDER_STATE_TIMEOUT) //超时预回调的单子
  468. {
  469. $mod_refill = Model('refill_order');
  470. $refill_info = $mod_refill->partition(refill\util::part_query())->getOrderInfo(['mch_order' => $mch_order,'mchid' => $mchid,'inner_status' => 0]);
  471. $vr_order = Model('vr_order');
  472. $order_info = $vr_order->partition(refill\util::part_query())->getOrderInfo(['order_sn' => $refill_info['order_sn']]);
  473. $result = $this->format_success($order_info, $refill_info);
  474. return self::outsuccess($result);
  475. }
  476. else
  477. {
  478. $mod_refill = Model('refill_order');
  479. $refill_info = $mod_refill->partition(refill\util::part_query())->getOrderInfo(['mch_order' => $mch_order,'mchid' => $mchid,'inner_status' => 0]);
  480. if(empty($refill_info))
  481. {
  482. $mod_qerr = Model('refill_query_err');
  483. $insert = ['mch_order' => $mch_order,'mchid' => $mchid];
  484. $items = $mod_refill->getOrderInfo(['mch_order' => $mch_order,'mchid' => $mchid]);
  485. if (empty($items)) {
  486. Log::record("query_state in db no order mchid=$mchid mch_order=$mch_order", Log::DEBUG);
  487. $insert['code'] = 202;
  488. $insert['msg'] = "检索充值中的单子,查不到任何订单信息.";
  489. $mod_qerr->add($insert);
  490. $detail = $detail_checker($mchid,$mch_order);
  491. if($detail == false) {
  492. return self::outerr(202, "无此订单,请人工确认处理.");
  493. }
  494. else {
  495. return self::outsuccess($send);
  496. }
  497. }
  498. else {
  499. Log::record("DEBUG_TAG: query_state in db mchid=$mchid mch_order=$mch_order order_state not completed.", Log::DEBUG);
  500. $insert['code'] = 200;
  501. $insert['msg'] = "检索充值中的单子能查到,但inner_status=0时查不到,回调充值中状态.";
  502. $mod_qerr->add($insert);
  503. return self::outsuccess($send);
  504. }
  505. }
  506. else
  507. {
  508. $vr_order = Model('vr_order');
  509. $order_info = $vr_order->partition(refill\util::part_query())->getOrderInfo(['order_sn' => $refill_info['order_sn']]);
  510. Log::record("query_state in db mchid=$mchid mch_order=$mch_order order_state={$order_info['order_state']}" ,Log::DEBUG);
  511. if (empty($order_info))
  512. {
  513. $mod_qerr = Model('refill_query_err');
  514. $insert = ['mch_order' => $mch_order, 'mchid' => $mchid];
  515. $insert['code'] = 203;
  516. $insert['msg'] = "检索充值中的单子能查到,但inner_status=0时查不到vr_order中的订单.";
  517. $mod_qerr->add($insert);
  518. return self::outsuccess($send);
  519. } else {
  520. $result = $this->format($order_info, $refill_info);
  521. return self::outsuccess($result);
  522. }
  523. }
  524. }
  525. }
  526. }