Payment.php 20 KB

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