Payment.php 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574
  1. <?php
  2. /*
  3. * 支付相关处理
  4. */
  5. namespace app\home\controller;
  6. use think\facade\View;
  7. use think\facade\Lang;
  8. use think\facade\Db;
  9. /**
  10. *
  11. *
  12. * ----------------------------------------------------------------------------
  13. *
  14. * 控制器
  15. */
  16. class Payment extends BaseMall
  17. {
  18. public function initialize()
  19. {
  20. parent::initialize(); // TODO: Change the autogenerated stub
  21. Lang::load(base_path() . 'home/lang/' . config('lang.default_lang') . '/buy.lang.php');
  22. }
  23. private function use_predeposit($order_info, $post, $virtual = 0)
  24. {
  25. if ($virtual == 1) {
  26. $logic_buy = model('buyvirtual', 'logic');
  27. } elseif ($virtual == 2) {
  28. $logic_buy = model('storejoinin');
  29. } else {
  30. $logic_buy = model('buy_1', 'logic');
  31. }
  32. if (empty($post['password'])) {
  33. return $order_info;
  34. }
  35. $member_model = model('member');
  36. $buyer_info = $member_model->getMemberInfoByID(session('member_id'));
  37. if ($buyer_info['member_paypwd'] == '' || $buyer_info['member_paypwd'] != md5($post['password'])) {
  38. return $order_info;
  39. }
  40. if ($buyer_info['available_rc_balance'] == 0) {
  41. $post['rcb_pay'] = null;
  42. }
  43. if ($buyer_info['available_predeposit'] == 0) {
  44. $post['pd_pay'] = null;
  45. }
  46. try {
  47. Db::startTrans();
  48. if (!empty($post['rcb_pay'])) {
  49. $order_info = $logic_buy->rcbPay($order_info, $post, $buyer_info);
  50. }
  51. if (!empty($post['pd_pay'])) {
  52. $order_info = $logic_buy->pdPay($order_info, $post, $buyer_info);
  53. }
  54. Db::commit();
  55. } catch (\Exception $e) {
  56. Db::rollback();
  57. exit($e->getMessage());
  58. }
  59. return $order_info;
  60. }
  61. private function get_order_info($result)
  62. {
  63. //计算本次需要在线支付的订单总金额
  64. $pay_amount = 0;
  65. $pay_order_id_list = array();
  66. if (!empty($result['data']['order_list'])) {
  67. foreach ($result['data']['order_list'] as $order_info) {
  68. if ($order_info['order_state'] == ORDER_STATE_NEW || $order_info['order_state'] == ORDER_STATE_DEPOSIT || $order_info['order_state'] == ORDER_STATE_REST) {
  69. $pay_amount += ($order_info['order_state'] == ORDER_STATE_DEPOSIT ? $order_info['presell_deposit_amount'] : ($order_info['order_amount'] - $order_info['presell_deposit_amount'] + $order_info['presell_rcb_amount'] + $order_info['presell_pd_amount'])) - $order_info['pd_amount'] - $order_info['rcb_amount'];
  70. $pay_order_id_list[] = $order_info['order_id'];
  71. }
  72. }
  73. }
  74. if (round($pay_amount, 2) == 0) {
  75. $result['data']['pay_end'] = 1;
  76. } else {
  77. $result['data']['pay_end'] = 0;
  78. }
  79. $result['data']['api_pay_amount'] = ds_price_format($pay_amount);
  80. //临时注释
  81. if (!empty($pay_order_id_list)) {
  82. $update = model('order')->editOrder(array('payment_time' => TIMESTAMP), array(array('order_id', 'in', $pay_order_id_list)));
  83. // if (!$update) {
  84. // exit('更新订单信息发生错误,请重新支付');//因为微信支付时会重定向获取openid所以会更新两次
  85. // }
  86. }
  87. //如果是开始支付尾款,则把支付单表重置了未支付状态,因为支付接口通知时需要判断这个状态
  88. if (isset($result['data']['if_buyer_repay'])) {
  89. $update = model('order')->editOrderpay(array('api_paystate' => 0), array('pay_id' => $result['data']['pay_id']));
  90. if (!$update) {
  91. exit(lang('order_pay_fail'));
  92. }
  93. $result['data']['api_paystate'] = 0;
  94. }
  95. return $result;
  96. }
  97. private function get_vr_order_info($result)
  98. {
  99. //计算本次需要在线支付的订单总金额
  100. $pay_amount = 0;
  101. if ($result['data']['order_state'] == ORDER_STATE_NEW) {
  102. $pay_amount += $result['data']['order_amount'] - $result['data']['pd_amount'] - $result['data']['rcb_amount'];
  103. }
  104. if ($pay_amount == 0) {
  105. $result['data']['pay_end'] = 1;
  106. } else {
  107. $result['data']['pay_end'] = 0;
  108. }
  109. $result['data']['api_pay_amount'] = ds_price_format($pay_amount);
  110. //临时注释
  111. //$update = model('order')->editOrder(array('api_pay_time'=>TIMESTAMP),array('order_id'=>$result['data']['order_id']));
  112. //if(!$update) {
  113. // return array('error' => '更新订单信息发生错误,请重新支付');
  114. //}
  115. //计算本次需要在线支付的订单总金额
  116. $pay_amount = $result['data']['order_amount'] - $result['data']['pd_amount'] - $result['data']['rcb_amount'];
  117. $result['data']['api_pay_amount'] = ds_price_format($pay_amount);
  118. return $result;
  119. }
  120. private function get_sj_order_info($result)
  121. {
  122. //计算本次需要在线支付的订单总金额
  123. $pay_amount = 0;
  124. if ($result['data']['joinin_state'] == STORE_JOIN_STATE_VERIFY_SUCCESS) {
  125. $pay_amount += $result['data']['paying_amount'] - $result['data']['pd_amount'] - $result['data']['rcb_amount'];
  126. }
  127. if ($pay_amount == 0) {
  128. $result['data']['pay_end'] = 1;
  129. } else {
  130. $result['data']['pay_end'] = 0;
  131. }
  132. $result['data']['api_pay_amount'] = ds_price_format($pay_amount);
  133. return $result;
  134. }
  135. /**
  136. * 店铺入驻
  137. */
  138. public function sj_order()
  139. {
  140. $storejoinin_model = model('storejoinin');
  141. $joinin_detail = $storejoinin_model->getOneStorejoinin(array('member_id' => session('member_id')));
  142. if (!$joinin_detail) {
  143. $this->error('店铺入驻不存在');
  144. }
  145. $payment_code = input('post.payment_code');
  146. $url = (string)url('Seller/index');
  147. $pay_sn = $joinin_detail['pay_sn'];
  148. if (!$pay_sn) {
  149. $pay_sn = makePaySn(session('member_id'));
  150. $storejoinin_model->editStorejoinin(array('pay_sn' => $pay_sn), array('member_id' => session('member_id'), 'pay_sn' => ''));
  151. }
  152. $logic_payment = model('payment', 'logic');
  153. $result = $logic_payment->getPaymentInfo($payment_code);
  154. if (!$result['code']) {
  155. $this->error($result['msg'], $url);
  156. }
  157. $payment_info = $result['data'];
  158. //计算所需支付金额等支付单信息
  159. $result = $logic_payment->getSjOrderInfo($pay_sn);
  160. if (!$result['code']) {
  161. $this->error($result['msg'], $url);
  162. }
  163. if ($result['data']['joinin_state'] != STORE_JOIN_STATE_VERIFY_SUCCESS || empty($result['data']['api_pay_amount'])) {
  164. $this->error(lang('no_payment_required_this_order'), $url);
  165. }
  166. $result['data'] = $this->use_predeposit($result['data'], input('param.'), 2);
  167. $result = $this->get_sj_order_info($result);
  168. if ($result['data']['pay_end'] == 1) {
  169. $this->redirect($url);
  170. return;
  171. }
  172. //转到第三方API支付
  173. $this->_api_pay($result['data'], $payment_info);
  174. }
  175. /**
  176. * 实物商品订单
  177. */
  178. public function real_order()
  179. {
  180. $pay_sn = input('post.pay_sn');
  181. $payment_code = input('post.payment_code');
  182. $url = (string)url('Memberorder/index');
  183. if (!preg_match('/^\d{20}$/', $pay_sn)) {
  184. $this->error(lang('param_error'), $url);
  185. }
  186. $logic_payment = model('payment', 'logic');
  187. $result = $logic_payment->getPaymentInfo($payment_code);
  188. if (!$result['code']) {
  189. $this->error($result['msg'], $url);
  190. }
  191. $payment_info = $result['data'];
  192. //计算所需支付金额等支付单信息
  193. $result = $logic_payment->getRealOrderInfo($pay_sn, session('member_id'));
  194. if (!$result['code']) {
  195. $this->error($result['msg'], $url);
  196. }
  197. if ($result['data']['api_paystate'] || empty($result['data']['api_pay_amount'])) {
  198. $this->error(lang('no_payment_required_this_order'), $url);
  199. }
  200. $result['data']['order_list'] = $this->use_predeposit($result['data']['order_list'], input('param.'), 0);
  201. $result = $this->get_order_info($result);
  202. if ($result['data']['pay_end'] == 1) {
  203. //站内支付了全款
  204. $this->redirect($url);
  205. return;
  206. }
  207. //转到第三方API支付
  208. $this->_api_pay($result['data'], $payment_info);
  209. }
  210. /**
  211. * 虚拟商品购买
  212. */
  213. public function vr_order()
  214. {
  215. $order_sn = input('post.order_sn');
  216. $payment_code = input('post.payment_code');
  217. $url = (string)url('Membervrorder/index');
  218. if (!preg_match('/^\d{20}$/', $order_sn)) {
  219. $this->error(lang('param_error'));
  220. }
  221. $logic_payment = model('payment', 'logic');
  222. $result = $logic_payment->getPaymentInfo($payment_code);
  223. if (!$result['code']) {
  224. $this->error($result['msg'], $url);
  225. }
  226. $payment_info = $result['data'];
  227. //计算所需支付金额等支付单信息
  228. $result = $logic_payment->getVrOrderInfo($order_sn, session('member_id'));
  229. if (!$result['code']) {
  230. $this->error($result['msg'], $url);
  231. }
  232. if ($result['data']['order_state'] != ORDER_STATE_NEW || empty($result['data']['api_pay_amount'])) {
  233. $this->error(lang('no_payment_required_this_order'), $url);
  234. }
  235. $result['data'] = $this->use_predeposit($result['data'], input('param.'), 1);
  236. $result = $this->get_vr_order_info($result);
  237. if ($result['data']['pay_end'] == 1) {
  238. $this->redirect($url);
  239. return;
  240. }
  241. //转到第三方API支付
  242. $this->_api_pay($result['data'], $payment_info);
  243. }
  244. /**
  245. * 预存款充值
  246. */
  247. public function pd_order()
  248. {
  249. $pdr_sn = input('param.pdr_sn');
  250. $payment_code = input('param.payment_code');
  251. $url = (string)url('Predeposit/index');
  252. if (!preg_match('/^\d{20}$/', $pdr_sn)) {
  253. $this->error(lang('param_error'), $url);
  254. }
  255. $logic_payment = model('payment', 'logic');
  256. $result = $logic_payment->getPaymentInfo($payment_code);
  257. if (!$result['code']) {
  258. $this->error($result['msg'], $url);
  259. }
  260. $payment_info = $result['data'];
  261. $result = $logic_payment->getPdOrderInfo($pdr_sn, session('member_id'));
  262. if (!$result['code']) {
  263. $this->error($result['msg'], $url);
  264. }
  265. if ($result['data']['pdr_payment_state'] || empty($result['data']['api_pay_amount'])) {
  266. $this->error(lang('no_payment_required'), $url);
  267. }
  268. //转到第三方API支付
  269. $this->_api_pay($result['data'], $payment_info);
  270. }
  271. /**
  272. * 第三方在线支付接口
  273. *
  274. */
  275. private function _api_pay($order_info, $payment_info)
  276. {
  277. try {
  278. $payment_api = new $payment_info['payment_code']($payment_info);
  279. } catch (\Exception $e) {
  280. $this->error($e->getMessage());
  281. }
  282. if (in_array($payment_info['payment_code'], array('wxpay_native', 'allinpay'))) {
  283. if (!extension_loaded('curl')) {
  284. $this->error(lang('please_check_system_configuration'));
  285. }
  286. if (array_key_exists('order_list', $order_info)) {
  287. View::assign('order_list', $order_info['order_list']);
  288. View::assign('args', 'buyer_id=' . session('member_id') . '&pay_id=' . $order_info['pay_id']);
  289. } else {
  290. View::assign('order_list', array());
  291. if ($order_info['order_type'] == 'pd_order') {
  292. View::assign('args', 'buyer_id=' . session('member_id') . '&pdr_sn=' . $order_info['pdr_sn']);
  293. } else {
  294. View::assign('args', 'buyer_id=' . session('member_id') . '&order_id=' . (isset($order_info['order_id']) ? $order_info['order_id'] : ''));
  295. }
  296. }
  297. View::assign('api_pay_amount', $order_info['api_pay_amount']);
  298. try {
  299. $pay_url = base64_encode(ds_encrypt($payment_api->get_payform($order_info), MD5_KEY));
  300. } catch (\Exception $e) {
  301. $this->error($e->getMessage());
  302. }
  303. View::assign('pay_url', $pay_url);
  304. View::assign('nav_list', rkcache('nav', true));
  305. if ($payment_info['payment_code'] == 'wxpay_native') {
  306. $pay_method = lang('pay_method_wechat');
  307. } elseif ($payment_info['payment_code'] == 'allinpay') {
  308. $paytype = input('param.paytype');
  309. switch ($paytype) {
  310. case 'W01':
  311. $pay_method = lang('pay_method_wechat');
  312. break;
  313. case 'A01':
  314. $pay_method = lang('pay_method_alipay');
  315. break;
  316. case 'Q01':
  317. $pay_method = lang('pay_method_tenpay');
  318. break;
  319. case 'U01':
  320. $pay_method = lang('pay_method_unionpay');
  321. break;
  322. default:
  323. $this->error(lang('please_check_system_configuration'));
  324. }
  325. }
  326. View::assign('pay_method', $pay_method);
  327. echo View::fetch($this->template_dir . 'wxpay');
  328. } else {
  329. try {
  330. $pay_url = $payment_api->get_payform($order_info);
  331. } catch (\Exception $e) {
  332. $this->error($e->getMessage());
  333. }
  334. @header("Location: " . $pay_url);
  335. }
  336. exit();
  337. }
  338. /**
  339. * 二维码显示(微信扫码支付)
  340. */
  341. public function qrcode()
  342. {
  343. $data = base64_decode(input('data'));
  344. $data = ds_decrypt($data, MD5_KEY, 30);
  345. include_once root_path() . 'extend/qrcode/phpqrcode.php';
  346. \QRcode::png($data);
  347. }
  348. /**
  349. * 扫码支付结果判断
  350. */
  351. public function query_state()
  352. {
  353. if (intval(input('param.pay_id')) > 0) {
  354. $info = model('order')->getOrderpayInfo(array(
  355. 'pay_id' => intval(input('param.pay_id')),
  356. 'buyer_id' => intval(input('param.buyer_id'))
  357. ));
  358. exit(json_encode(array(
  359. 'state' => ($info['api_paystate'] == '1'), 'pay_sn' => $info['pay_sn'], 'type' => 'real_order'
  360. )));
  361. } elseif (intval(input('param.order_id')) > 0) {
  362. $info = model('vrorder')->getVrorderInfo(array(
  363. 'order_id' => intval(input('param.order_id')),
  364. 'buyer_id' => intval(input('param.buyer_id'))
  365. ));
  366. exit(json_encode(array(
  367. 'state' => ($info['order_state'] == '20'), 'pay_sn' => $info['order_sn'], 'type' => 'vr_order'
  368. )));
  369. } else {
  370. $result = model('payment', 'logic')->getPdOrderInfo(input('param.pdr_sn'), input('param.buyer_id'));
  371. exit(json_encode(array('state' => $result['code'] && $result['data']['pdr_payment_state'], 'pdr_sn' => $result['code'] ? $result['data']['pay_sn'] : '', 'type' => 'pd_order')));
  372. }
  373. }
  374. /**
  375. *
  376. * @param type $payment_code 共用回调方法
  377. * @param type $show_code 实际支付方式名称
  378. */
  379. public function notify($payment_code, $show_code = '')
  380. {
  381. $logic_payment = model('payment', 'logic');
  382. $result = $logic_payment->getPaymentInfo($payment_code);
  383. $payment_info = $result['data'];
  384. if ($show_code) {
  385. $result = $logic_payment->getPaymentInfo($show_code);
  386. $payment_info['payment_config'] = array_merge($payment_info['payment_config'], $result['data']['payment_config']);
  387. }
  388. //创建支付接口对象
  389. $payment_api = new $payment_code($payment_info);
  390. //对进入的参数进行远程数据判断
  391. $verify = $payment_api->verify_notify();
  392. if ($verify['trade_status'] != 1) {
  393. exit;
  394. }
  395. $out_trade_no = $verify['out_trade_no']; #内部订单号
  396. $trade_no = $verify['trade_no']; #交易订单号
  397. $order_type = $verify['order_type']; #交易类型
  398. $update_result = $logic_payment->updateOrder($out_trade_no, $trade_no, $order_type, $show_code ? $show_code : $payment_code);
  399. exit($update_result ? 'success' : 'fail');
  400. }
  401. /**
  402. * 支付接口同步返回路径
  403. */
  404. public function alipay_return()
  405. {
  406. $this->return_verify('alipay');
  407. }
  408. /**
  409. * 银联同步通知
  410. */
  411. public function unionpay_return()
  412. {
  413. $this->return_verify('unionpay');
  414. }
  415. public function return_verify($payment_code)
  416. {
  417. $logic_payment = model('payment', 'logic');
  418. //取得支付方式
  419. $result = $logic_payment->getPaymentInfo($payment_code);
  420. if (!$result['code']) {
  421. $this->error($result['msg'], 'Memberorder/index');
  422. }
  423. $payment_info = $result['data'];
  424. //创建支付接口对象
  425. $payment_api = new $payment_info['payment_code']($payment_info);
  426. //返回参数判断
  427. $verify = $payment_api->return_verify();
  428. if (!$verify || $verify['trade_status'] == '0') {
  429. $this->error(lang('payment_data_validation_failed'), 'Memberorder/index');
  430. }
  431. $order_type = $verify['order_type'];
  432. $out_trade_no = $verify['out_trade_no'];
  433. $order_amount = $verify['total_fee'];
  434. //支付成功后跳转
  435. if ($order_type == 'real_order') {
  436. $pay_ok_url = HOME_SITE_URL . '/buy/pay_ok?pay_sn=' . $out_trade_no . '&pay_amount=' . ds_price_format($order_amount);
  437. } elseif ($order_type == 'sj_order') {
  438. $pay_ok_url = HOME_SITE_URL . '/Seller/index.html';
  439. } elseif ($order_type == 'vr_order') {
  440. $pay_ok_url = HOME_SITE_URL . '/buyvirtual/pay_ok?order_sn=' . $out_trade_no . '&order_amount=' . ds_price_format($order_amount);
  441. } elseif ($order_type == 'pd_order') {
  442. $pay_ok_url = HOME_SITE_URL . '/predeposit/index';
  443. }
  444. header("Location:$pay_ok_url");
  445. exit;
  446. }
  447. /**
  448. * 通联异步通知
  449. */
  450. public function allinpay_notify()
  451. {
  452. $this->notify('allinpay');
  453. }
  454. /**
  455. * 银联异步通知
  456. */
  457. public function unionpay_notify()
  458. {
  459. $this->notify('unionpay');
  460. }
  461. /**
  462. * 微信扫码支付异步通知
  463. */
  464. public function wxpay_native_notify()
  465. {
  466. $this->notify('wxpay_native');
  467. }
  468. /**
  469. * 小程序支付异步通知
  470. */
  471. public function wxpay_minipro_notify()
  472. {
  473. $this->notify('wxpay_native', 'wxpay_minipro');
  474. }
  475. /**
  476. * 微信支付支付异步通知
  477. */
  478. public function wxpay_jsapi_notify()
  479. {
  480. $this->notify('wxpay_native', 'wxpay_jsapi');
  481. }
  482. /**
  483. * 微信H5支付异步通知
  484. */
  485. public function wxpay_h5_notify()
  486. {
  487. $this->notify('wxpay_native', 'wxpay_h5');
  488. }
  489. /**
  490. * 微信APP支付异步通知
  491. */
  492. public function wxpay_app_notify()
  493. {
  494. $this->notify('wxpay_native', 'wxpay_app');
  495. }
  496. /**
  497. * 通知处理(支付宝异步对账)
  498. */
  499. public function alipay_notify()
  500. {
  501. $this->notify('alipay');
  502. }
  503. /**
  504. * 支付宝APP支付异步通知
  505. */
  506. public function alipay_app_notify()
  507. {
  508. $this->notify('alipay', 'alipay_app');
  509. }
  510. /**
  511. * 支付宝wap支付异步通知
  512. */
  513. public function alipay_h5_notify()
  514. {
  515. $this->notify('alipay', 'alipay_h5');
  516. }
  517. }