From ae22ba2b6d43958908548dd9def05a3ed5021e42 Mon Sep 17 00:00:00 2001 From: devil_gong Date: Fri, 28 Sep 2018 14:31:41 +0800 Subject: [PATCH] pay --- .../OrderNotifyController.class.php | 11 +- .../Application/Common/Common/function.php | 13 +- service/Application/Common/Lang/zh-cn.php | 1 + .../Home/Controller/OrderController.class.php | 46 +++- .../Home/View/Default/Order/Index.html | 26 +++ .../Home/View/Default/Public/PayError.html | 34 +++ .../Home/View/Default/Public/PaySuccess.html | 34 +++ .../Library/Payment/Alipay.class.php | 83 +++++-- .../Service/OrderService.class.php | 207 +++++++++++++++++- service/Notify/order.php | 18 -- service/Public/Home/Default/Css/Common.css | 9 +- service/Respond/order.php | 0 service/notify_order.php | 18 ++ service/respond_order.php | 18 ++ 14 files changed, 460 insertions(+), 58 deletions(-) create mode 100644 service/Application/Home/View/Default/Order/Index.html create mode 100644 service/Application/Home/View/Default/Public/PayError.html create mode 100644 service/Application/Home/View/Default/Public/PaySuccess.html delete mode 100755 service/Notify/order.php delete mode 100644 service/Respond/order.php create mode 100644 service/notify_order.php create mode 100644 service/respond_order.php diff --git a/service/Application/Api/Controller/OrderNotifyController.class.php b/service/Application/Api/Controller/OrderNotifyController.class.php index f6213fe41..f7f9861dc 100755 --- a/service/Application/Api/Controller/OrderNotifyController.class.php +++ b/service/Application/Api/Controller/OrderNotifyController.class.php @@ -2,6 +2,8 @@ namespace Api\Controller; +use Service\ResourcesService; + /** * 订单支付异步通知 * @author Devil @@ -25,15 +27,18 @@ class OrderNotifyController extends CommonController } /** - * [PayNotify 支付异步处理] + * [Notify 支付异步处理] * @author Devil * @blog http://gong.gg/ * @version 1.0.0 * @datetime 2018-03-04T14:35:38+0800 */ - public function PayNotify() + public function Notify() { - $data = (new \Library\Alipay())->Respond(C("alipay_key_secret")); + $payment = ResourcesService::PaymentList(['where'=>['id'=>34]]); + $ret = (new \Library\Payment\Alipay($payment[0]['config']))->Respond(); + file_put_contents(ROOT_PATH.'order-pay-notify-'.rand().'.txt', json_encode($ret)); + die; if($data == 'no') exit('error'); // 开始处理支付信息 diff --git a/service/Application/Common/Common/function.php b/service/Application/Common/Common/function.php index 2831e0b8d..4c7038325 100755 --- a/service/Application/Common/Common/function.php +++ b/service/Application/Common/Common/function.php @@ -70,7 +70,18 @@ function DataReturn($msg = '', $code = 0, $data = '') */ function HomeUrl($c='Index', $a='Index', $params=[]) { - return str_replace('admin.php', 'index.php', U("Home/{$c}/{$a}", $params)); + $url = U("Home/{$c}/{$a}", $params); + $location = stripos($url, '.php'); + if($location !== false) + { + $before = substr($url, 0, $location+4); + $suffix = substr($before, strrpos($before, '/')+1); + if(!empty($suffix)) + { + $url = str_replace($suffix, 'index.php', $url); + } + } + return $url; } /** diff --git a/service/Application/Common/Lang/zh-cn.php b/service/Application/Common/Lang/zh-cn.php index 63634ca98..9b615e9b7 100755 --- a/service/Application/Common/Lang/zh-cn.php +++ b/service/Application/Common/Lang/zh-cn.php @@ -277,6 +277,7 @@ return array( 'common_so_tips' => '其实搜索很简单 ^_^!', 'common_go_top_text' => '回到顶部', 'common_toview_home_text' => '查看首页', + 'common_go_home_text' => '回到首页', 'common_email_send_user_reg_title' => '用户注册', 'common_email_send_user_forget_title'=> '密码找回', 'common_layout_slider_more_text' => '了解更多', diff --git a/service/Application/Home/Controller/OrderController.class.php b/service/Application/Home/Controller/OrderController.class.php index f66c0e1b1..631133245 100644 --- a/service/Application/Home/Controller/OrderController.class.php +++ b/service/Application/Home/Controller/OrderController.class.php @@ -3,6 +3,7 @@ namespace Home\Controller; use Service\OrderService; +use Service\ResourcesService; /** * 订单管理 @@ -30,11 +31,25 @@ class OrderController extends CommonController } /** - * [Index 首页] + * 订单列表 * @author Devil - * @blog http://gong.gg/ - * @version 0.0.1 - * @datetime 2017-02-25T15:30:36+0800 + * @blog http://gong.gg/ + * @version 1.0.0 + * @date 2018-09-28 + * @desc description + */ + public function Index() + { + $this->display('Index'); + } + + /** + * 订单支付 + * @author Devil + * @blog http://gong.gg/ + * @version 1.0.0 + * @date 2018-09-28 + * @desc description */ public function Pay() { @@ -49,5 +64,28 @@ class OrderController extends CommonController $this->display('/Public/TipsError'); } } + + /** + * 支付同步返回处理 + * @author Devil + * @blog http://gong.gg/ + * @version 1.0.0 + * @date 2018-09-28 + * @desc description + */ + public function Respond() + { + $params = $_REQUEST; + $params['user'] = $this->user; + $ret = OrderService::Respond($params); + if($ret['code'] == 0) + { + $this->assign('msg', '支付成功'); + $this->display('/Public/PaySuccess'); + } else { + $this->assign('msg', $ret['msg']); + $this->display('/Public/PayError'); + } + } } ?> \ No newline at end of file diff --git a/service/Application/Home/View/Default/Order/Index.html b/service/Application/Home/View/Default/Order/Index.html new file mode 100644 index 000000000..c6dadd2a2 --- /dev/null +++ b/service/Application/Home/View/Default/Order/Index.html @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + +
+ + 订单管理 + +
{{:L('common_not_data_tips')}}
+
+
+ + + + \ No newline at end of file diff --git a/service/Application/Home/View/Default/Public/PayError.html b/service/Application/Home/View/Default/Public/PayError.html new file mode 100644 index 000000000..38f852ac8 --- /dev/null +++ b/service/Application/Home/View/Default/Public/PayError.html @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + +
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/service/Application/Home/View/Default/Public/PaySuccess.html b/service/Application/Home/View/Default/Public/PaySuccess.html new file mode 100644 index 000000000..139e8df69 --- /dev/null +++ b/service/Application/Home/View/Default/Public/PaySuccess.html @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + +
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/service/Application/Library/Payment/Alipay.class.php b/service/Application/Library/Payment/Alipay.class.php index c41b5965b..4f9b22acf 100644 --- a/service/Application/Library/Payment/Alipay.class.php +++ b/service/Application/Library/Payment/Alipay.class.php @@ -61,16 +61,6 @@ class Alipay 'is_required' => 1, 'message' => '请填写支付宝账号', ], - [ - 'element' => 'input', - 'type' => 'text', - 'default' => '', - 'name' => 'key', - 'placeholder' => '交易安全校验码 key', - 'title' => '交易安全校验码 key', - 'is_required' => 1, - 'message' => '请填写交易安全校验码 key', - ], [ 'element' => 'input', 'type' => 'text', @@ -81,6 +71,16 @@ class Alipay 'is_required' => 1, 'message' => '请填写合作者身份 partner ID', ], + [ + 'element' => 'input', + 'type' => 'text', + 'default' => '', + 'name' => 'key', + 'placeholder' => '交易安全校验码 key', + 'title' => '交易安全校验码 key', + 'is_required' => 1, + 'message' => '请填写交易安全校验码 key', + ], [ 'element' => 'input', // 表单标签 'type' => 'text', // input类型 @@ -217,7 +217,7 @@ class Alipay 'service' => 'alipay.wap.auth.authAndExecute', 'format' => 'xml', 'v' => '2.0', - 'partner' => $this->config['key'], + 'partner' => $this->config['partner'], 'sec_id' => 'MD5', 'req_data' => $req_data, 'request_token' => $ret['data'] @@ -242,7 +242,7 @@ class Alipay 'service' => 'alipay.wap.trade.create.direct', 'format' => 'xml', 'v' => '2.0', - 'partner' => $this->config['key'], + 'partner' => $this->config['partner'], 'req_id' => $params['order_sn'], 'sec_id' => 'MD5', 'req_data' => $this->GetReqData($params), @@ -320,7 +320,7 @@ class Alipay { $parameter = array( 'service' => 'create_direct_pay_by_user', - 'partner' => $this->config['key'], + 'partner' => $this->config['partner'], '_input_charset' => C('DEFAULT_CHARSET'), 'notify_url' => $params['notify_url'], 'return_url' => $params['call_back_url'], @@ -334,12 +334,12 @@ class Alipay 'payment_type' => 1, /* 物流参数 */ - 'logistics_type' => 'EXPRESS', - 'logistics_fee' => 0, - 'logistics_payment' => 'BUYER_PAY_AFTER_RECEIVE', + // 'logistics_type' => 'EXPRESS', + // 'logistics_fee' => 0, + // 'logistics_payment' => 'BUYER_PAY_AFTER_RECEIVE', /* 买卖双方信息 */ - 'seller_email' => $this->config['account'] + 'seller_email' => $this->config['account'], ); $param = $this->GetParamSign($parameter); @@ -371,9 +371,9 @@ class Alipay 'urlcode' => substr($urlcode, 0, -1), 'url' => substr($url, 0, -1), ); - if(!empty($this->config['partner'])) + if(!empty($this->config['key'])) { - $result['sign'] = $result['url'].$this->config['partner']; + $result['sign'] = $result['url'].$this->config['key']; } return $result; } @@ -389,9 +389,48 @@ class Alipay */ public function Respond($params = []) { - // 编写代码 - - return 'Respond success'; + if(empty($this->config)) + { + return DataReturn('配置有误', -1); + } + + $data = empty($_POST) ? $_GET : array_merge($_GET, $_POST); + ksort($data); + + $sign = ''; + if(isset($data['sec_id']) && $data['sec_id'] == 'MD5') + { + $data_xml = json_decode(json_encode((array) simplexml_load_string($data['notify_data'])), true); + $data = array_merge($data, $data_xml); + $sign = 'service='.$data['service'].'&v='.$data['v'].'&sec_id='.$data['sec_id'].'¬ify_data='.$data['notify_data']; + } else { + foreach($data AS $key=>$val) + { + if ($key != 'sign' && $key != 'sign_type' && $key != 'code') + { + $sign .= "$key=$val&"; + } + } + $sign = substr($sign, 0, -1); + } + + // 签名校验 + if(!isset($data['sign']) || md5($sign.$this->config['key']) != $data['sign']) + { + return DataReturn('签名校验失败', -1); + } + + // 支付状态 + $status = isset($data['trade_status']) ? $data['trade_status'] : $data['result']; + switch($status) + { + case 'TRADE_SUCCESS': + case 'TRADE_FINISHED': + case 'success': + return DataReturn('支付成功', 0, $data); + break; + } + return DataReturn('处理异常错误', -100); } } ?> \ No newline at end of file diff --git a/service/Application/Service/OrderService.class.php b/service/Application/Service/OrderService.class.php index 3e1c2610e..46c69f3c5 100644 --- a/service/Application/Service/OrderService.class.php +++ b/service/Application/Service/OrderService.class.php @@ -25,14 +25,28 @@ class OrderService */ public static function Pay($params = []) { - if(empty($params['id'])) + // 请求参数 + $p = [ + [ + 'checked_type' => 'empty', + 'key_name' => 'id', + 'error_msg' => '订单id有误', + ], + [ + 'checked_type' => 'empty', + 'key_name' => 'user', + 'error_msg' => '用户信息有误', + ], + ]; + $ret = params_checked($params, $p); + if($ret !== true) { - return DataReturn('订单id有误', -1); + return DataReturn($ret, -1); } - $m = M('Order'); + // 获取订单信息 $where = ['id'=>intval($params['id']), 'user_id' => $params['user']['id']]; - $data = $m->where($where)->field('id,status,total_price,payment_id')->find(); + $data = M('Order')->where($where)->field('id,status,total_price,payment_id')->find(); if(empty($data)) { return DataReturn(L('common_data_no_exist_error'), -1); @@ -60,16 +74,191 @@ class OrderService 'order_sn' => date('YmdHis').$data['id'], 'name' => '订单支付', 'total_price' => $data['total_price'], - 'notify_url' => __MY_URL__.'Notify/order.php', - 'call_back_url' => __MY_URL__.'Respond/order.php', + 'notify_url' => __MY_URL__.'notify_order.php', + 'call_back_url' => __MY_URL__.'respond_order.php', ); $pay_name = '\Library\Payment\\'.$payment[0]['payment']; $ret = (new $pay_name($payment[0]['config']))->Pay($pay_data); - if(empty($ret)) + if(isset($ret['code']) && $ret['code'] == 0) { - return DataReturn('支付接口异常', -1); + // 存储session订单id + $_SESSION['payment_order_id'] = $data['id']; + return $ret; } - return $ret; + return DataReturn('支付接口异常', -1); + } + + /** + * 支付同步处理 + * @author Devil + * @blog http://gong.gg/ + * @version 1.0.0 + * @date 2018-09-28 + * @desc description + * @param [array] $params [输入参数] + */ + public static function Respond($params = []) + { + // 请求参数 + $p = [ + [ + 'checked_type' => 'empty', + 'key_name' => 'user', + 'error_msg' => '用户信息有误', + ], + [ + 'checked_type' => 'empty', + 'key_name' => 'out_trade_no', + 'error_msg' => '支付回调参数缺失[out_trade_no]', + ], + ]; + $ret = params_checked($params, $p); + if($ret !== true) + { + return DataReturn($ret, -1); + } + + // 获取订单信息 + $where = ['id'=>self::OutTradeNoParsing($params['out_trade_no']), 'user_id' => $params['user']['id']]; + $data = M('Order')->where($where)->field('id,status,payment_id')->find(); + if(empty($data)) + { + return DataReturn(L('common_data_no_exist_error'), -1); + } + if($data['status'] > 1) + { + $status_text = L('common_order_user_status')[$data['status']]['name']; + return DataReturn('状态不可操作['.$status_text.']', -1); + } + + // 支付方式 + $payment = ResourcesService::PaymentList(['where'=>['id'=>$data['payment_id']]]); + if(empty($payment[0])) + { + return DataReturn('支付方式有误', -1); + } + + // 支付数据校验 + $pay_name = '\Library\Payment\\'.$payment[0]['payment']; + return (new $pay_name($payment[0]['config']))->Respond(); + } + + /** + * 支付异步处理 + * @author Devil + * @blog http://gong.gg/ + * @version 1.0.0 + * @date 2018-09-28 + * @desc description + * @param [array] $params [输入参数] + */ + public static function Notify($params = []) + { + // 请求参数 + $p = [ + [ + 'checked_type' => 'empty', + 'key_name' => 'out_trade_no', + 'error_msg' => '支付回调参数缺失[out_trade_no]', + ], + ]; + $ret = params_checked($params, $p); + if($ret !== true) + { + return $ret; + } + + // 获取订单信息 + $m = M('Order'); + $where = ['id'=>self::OutTradeNoParsing($params['out_trade_no'])]; + $data = $m->where($where)->field('id,status,total_price,payment_id,user_id,shop_id')->find(); + if(empty($data)) + { + return DataReturn(L('common_data_no_exist_error'), -1); + } + if($data['status'] > 1) + { + $status_text = L('common_order_user_status')[$data['status']]['name']; + return DataReturn('状态不可操作['.$status_text.']', -1); + } + + // 支付方式 + $payment = ResourcesService::PaymentList(['where'=>['id'=>$data['payment_id']]]); + if(empty($payment[0])) + { + return DataReturn('支付方式有误', -1); + } + + // 支付数据校验 + $pay_name = '\Library\Payment\\'.$payment[0]['payment']; + $ret = (new $pay_name($payment[0]['config']))->Respond(); + if(!isset($ret['code']) || $ret['code'] != 0) + { + return $ret; + } + + // 兼容web版本支付参数 + $buyer_email = isset($ret['data']['buyer_logon_id']) ? $ret['data']['buyer_logon_id'] : (isset($ret['data']['buyer_email']) ? $ret['data']['buyer_email'] : ''); + $total_amount = isset($ret['data']['total_amount']) ? $ret['data']['total_amount'] : (isset($ret['data']['total_fee']) ? $ret['data']['total_fee'] : ''); + + // 写入支付日志 + $pay_log_data = [ + 'user_id' => $pay_order['user_id'], + 'order_id' => $out_trade_no, + 'trade_no' => $ret['data']['trade_no'], + 'user' => $buyer_email, + 'total_fee' => $total_amount, + 'amount' => $pay_order['total_price'], + 'subject' => $ret['data']['subject'], + 'pay_type' => 0, + 'business_type' => 0, + 'add_time' => time(), + ]; + M('PayLog')->add($pay_log_data); + + // 消息通知 + $detail = '订单支付成功,金额'.PriceBeautify($pay_order['total_price']).'元'; + CommonMessageAdd('订单支付', $detail, $pay_order['user_id']); + + // 开启事务 + $m->startTrans(); + + // 更新支付状态 + $where = array('id' => $out_trade_no); + $upd_data = array( + 'status' => 2, + 'pay_status'=> 1, + 'pay_price' => $total_amount, + 'pay_time' => time(), + 'upd_time' => time(), + ); + if($m->where($where)->save($upd_data)) + { + // 提交事务 + $m->commit(); + + // 成功 + return DataReturn('处理成功', 0); + } + // 事务回滚 + $m->rollback(); + + // 处理失败 + return DataReturn('处理失败', -100); + } + + /** + * 订单号解析 + * @author Devil + * @blog http://gong.gg/ + * @version 1.0.0 + * @date 2018-09-28 + * @desc description + * @param [string] $out_trade_no [支付回传订单号] + */ + public static function OutTradeNoParsing($out_trade_no) + { + return substr($out_trade_no, 14); } } ?> \ No newline at end of file diff --git a/service/Notify/order.php b/service/Notify/order.php deleted file mode 100755 index 522d6a6fc..000000000 --- a/service/Notify/order.php +++ /dev/null @@ -1,18 +0,0 @@ - \ No newline at end of file diff --git a/service/Public/Home/Default/Css/Common.css b/service/Public/Home/Default/Css/Common.css index 3556a7697..d190e8924 100755 --- a/service/Public/Home/Default/Css/Common.css +++ b/service/Public/Home/Default/Css/Common.css @@ -414,7 +414,14 @@ background:url(../Images/ibar_sprites.png) no-repeat;background-position:0px -23 .price strong {color: #E4393C; font-weight: 600; } /* 公共错误提示页面 */ -.tips-error { margin: 10% 0; } +.tips-error, .tips-success { margin: 10% 0; } +.tips-pay-success, .tips-pay-error { box-shadow: none; text-align: center; } +.tips-error i.am-icon-times-circle, .tips-success i.am-icon-check-circle { font-size: 32px; } +.tips-error i.am-icon-times-circle { color: #F44336; } +.tips-success i.am-icon-check-circle { color: #4CAF50; } +.tips-error span.msg, .tips-success span.msg { font-size: 22px; margin-left: 10px; } +.tips-error .tips-nav, .tips-success .tips-nav { margin-top: 20px; } +.tips-error .tips-nav .am-btn:not(:last-child), .tips-success .tips-nav .am-btn:not(:last-child) { margin-right: 20px; } /* 页面加载数据 */ .loding-view { text-align: center; color: #888; padding: 10px 0; } diff --git a/service/Respond/order.php b/service/Respond/order.php deleted file mode 100644 index e69de29bb..000000000 diff --git a/service/notify_order.php b/service/notify_order.php new file mode 100644 index 000000000..9703594bd --- /dev/null +++ b/service/notify_order.php @@ -0,0 +1,18 @@ + \ No newline at end of file diff --git a/service/respond_order.php b/service/respond_order.php new file mode 100644 index 000000000..64b22b089 --- /dev/null +++ b/service/respond_order.php @@ -0,0 +1,18 @@ + \ No newline at end of file