Payment.php 20 KB

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