123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383 |
- <?php
- namespace app\api\controller;
- use think\Controller;
- use think\Db;
- /**
- * 订单支付回调
- */
- class Notify extends Controller
- {
- protected $noNeedLogin = ['*'];
- protected $noNeedRight = ['*'];
- public function checkNotify($args = []){
- $secret = config('hitpay.salt');
- $input_hmac = $args['hmac'];
- unset($args['hmac']);
- //hitpay/client/generateSignatureArray
- $hmacSource = [];
- foreach ($args as $key => $val) {
- $hmacSource[$key] = "{$key}{$val}";
- }
- ksort($hmacSource);
- $sig = implode("", array_values($hmacSource));
- $new_hmac = hash_hmac('sha256', $sig, $secret);
- //判断相等
- if($new_hmac == $input_hmac){
- return true;
- }else{
- return false;
- }
- }
- //主动获取一次
- private function getPaymentStatus($payment_request_id){
- $apiKey = config('hitpay.apikey');
- $hitPayClient = new \HitPay\Client($apiKey, true);
- $data = $hitPayClient->getPaymentStatus($payment_request_id);
- return $data->status;
- }
- //充值金币 异步回调对外方法
- public function recharge_notify_base(){
- //日志
- $paytype = 'hitpay';
- $notify_file = $this->notify_log_start($paytype);
- //接参
- $field = ['payment_id','payment_request_id','phone','amount','currency','status','reference_number','hmac'];
- $notify_data = request_post_hub($field);
- //验签
- $checkNotify = $this->checkNotify($notify_data);
- if ($checkNotify !== true) {
- echo '签名错误';
- exit;
- }
- //检查支付完成 completed / failed
- if($notify_data['status'] != 'completed'){
- $now_status = $this->getPaymentStatus($notify_data['payment_request_id']);
- if($now_status != 'completed'){
- echo '没有支付完成';
- exit;
- }
- }
- //验证,拿订单号等信息
- $out_trade_no = $notify_data['reference_number'];
- $payment_request_id = $notify_data['payment_request_id'];
- $payment_id = $notify_data['payment_id'];
- //订单查询
- $map = [
- 'out_trade_no' => $out_trade_no,
- 'payment_request_id' => $payment_request_id,
- ];
- $info = Db::name('pay_order')->where($map)->find();
- if(empty($info)){
- echo 'success';
- exit;
- }
- if($info['order_status'] != 0)
- {
- echo 'success';
- exit;
- }
- //你可以在此编写订单逻辑
- $rs = $this->recharge_notify_do($out_trade_no,$payment_request_id,$payment_id);
- if($rs === false){
- //不论结果都应返回success
- echo 'success';
- exit;
- }else{
- //不论结果都应返回success
- echo 'success';
- exit;
- }
- //默认
- echo 'success';
- exit;
- }
- public function recharge_notify_base_test(){
- //验证,拿订单号等信息
- $out_trade_no = input('out_trade_no','');
- //订单查询
- $map = [
- 'out_trade_no' => $out_trade_no,
- ];
- $info = Db::name('pay_order')->where($map)->find();
- if(empty($info)){
- echo '订单为空';
- exit;
- }
- if($info['order_status'] != 0)
- {
- echo '处理过了';
- exit;
- }
- //你可以在此编写订单逻辑
- $rs = $this->recharge_notify_do($out_trade_no,'',time());
- if($rs === false){
- //不论结果都应返回success
- echo '错了';
- exit;
- }else{
- //不论结果都应返回success
- echo '没错';
- exit;
- }
- //默认
- echo '默认成功';
- exit;
- }
- //充值金币 逻辑
- private function recharge_notify_do($out_trade_no,$payment_request_id,$payment_id){
- $time = time();
- Db::startTrans();
- $orderInfo = Db::name('pay_order')->where(['out_trade_no' => $out_trade_no])->lock(true)->find();
- if (empty($orderInfo)) {
- Db::rollback();
- return false;
- }
- if($orderInfo['order_status'] != 0){
- Db::rollback();
- return false;
- }
- //逻辑开始
- //试课预约
- if($orderInfo['table_name'] == 'trylesson_order'){
- $update = [
- 'order_status' => 10,
- 'paytime' => $time,
- 'updatetime' => $time,
- ];
- $rs = Db::name('trylesson_order')->where('id',$orderInfo['table_id'])->update($update);
- if($rs === false){
- Db::rollback();
- return false;
- }
- }
- //售课预约
- if($orderInfo['table_name'] == 'lesson_order'){
- $update = [
- 'order_status' => 10,
- 'paytime' => $time,
- 'updatetime' => $time,
- ];
- $rs = Db::name('lesson_order')->where('id',$orderInfo['table_id'])->update($update);
- if($rs === false){
- Db::rollback();
- return false;
- }
- //更新已预约人数
- $lesson_order = Db::name('lesson_order')->where('id',$orderInfo['table_id'])->find();
- $pay_number = Db::name('lesson_order')->where('slot_id',$lesson_order['slot_id'])->where('order_status',10)->sum('usernumber');
- $rs_slot = Db::name('lesson_slot')->where('id',$lesson_order['slot_id'])->update(['bookednum' => $pay_number]);
- if($rs_slot === false){
- Db::rollback();
- return false;
- }
- //预约课程
- $lesson = Db::name('lesson')->where('id',$lesson_order['lesson_id'])->find();
- //赠送积分
- if($orderInfo['order_amount'] > 0){
- $wallet_rs = model('wallet')->lockChangeAccountRemain($orderInfo['user_id'],'score',$orderInfo['order_amount'],3,'线上预约课程:'.$lesson['name'],'lesson_order',$orderInfo['table_id'],'Booking courses online:'.$lesson['name_en']);
- if($wallet_rs['status'] === false){
- Db::rollback();
- return false;
- }
- }
- }
- //售课预约买套餐
- if($orderInfo['table_name'] == 'package_order'){
- //配套主订单
- $package_order = Db::name('package_order')->where('id',$orderInfo['table_id'])->find();
- //修改套餐订单支付状态
- $update = [
- 'order_status' => 1,
- 'paytime' => $time,
- 'updatetime' => $time,
- ];
- //小配套自动激活
- if($package_order['remain'] < 5){
- $update['use_status'] = 1;
- $update['starttime'] = $time;
- $update['endtime'] = $time + ($package_order['days'] * 86400); //主配套与赠品的时间保持一样就可以
- }
- $lesson_package = Db::name('lesson_package')->where('id',$package_order['package_id'])->find();
- //初次购买,主订单增加赠送小时数
- $check_first = Db::name('package_order')->where('user_id',$package_order['user_id'])->where('package_id',$package_order['package_id'])->where('order_status',1)->where('is_gift',0)->find();
- if(empty($check_first)){
- $sessions_first = $lesson_package['sessions_first'];
- if($sessions_first > 0){
- $first_update = [
- 'sessions'=>$package_order['sessions'] + $sessions_first,
- 'remain' =>$package_order['remain'] + $sessions_first,
- ];
- $rs_first = Db::name('package_order')->where('id',$orderInfo['table_id'])->update($first_update);
- if($rs_first === false){
- Db::rollback();
- return false;
- }
- }
- }
- //修改套餐订单支付状态
- $rs = Db::name('package_order')->where('order_no',$orderInfo['out_trade_no'])->update($update); //这里不用id,是因为另有赠品单,两个一起更新
- if($rs === false){
- Db::rollback();
- return false;
- }
- //大于等于5小时的
- if($package_order['remain'] >= 5){
- //赠送积分
- if($orderInfo['order_amount'] > 0){
- $wallet_rs = model('wallet')->lockChangeAccountRemain($orderInfo['user_id'],'score',$orderInfo['order_amount'],2,'线上购买配套:' . $lesson_package['name'],'package_order',$orderInfo['table_id'],'Buy package online:'.$lesson_package['name_en']);
- if($wallet_rs['status'] === false){
- Db::rollback();
- return false;
- }
- }
- //新会员变成旧会员
- $oldstatus = Db::name('user')->where('id',$orderInfo['user_id'])->value('oldstatus');
- if($oldstatus == 0){
- $user_rs = Db::name('user')->where('id',$orderInfo['user_id'])->update(['oldstatus'=>1]);
- if($user_rs === false){
- Db::rollback();
- return false;
- }
- }
- }
- //小于五小时的,因为已激活。修改预约单状态,减掉相应课时
- $args = json_decode($orderInfo['args'],true);
- if($package_order['remain'] < 5 && isset($args['lesson_order_id']) && !empty($args['lesson_order_id'])){
- // $package_order = Db::name('package_order')->where('order_no',$orderInfo['out_trade_no'])->where('is_gift',0)->find();
- $lesson_order = Db::name('lesson_order')->where('id',$args['lesson_order_id'])->find();
- //课时能够支撑报名人数
- if($package_order['remain'] >= $lesson_order['usernumber_hours']){
- //扣除一节
- $update = [
- 'remain' => bcsub($package_order['remain'],$lesson_order['usernumber_hours'],1),
- 'updatetime' => time(),
- ];
- $rs1 = Db::name('package_order')->where('id',$package_order['id'])->update($update);
- if($rs1 === false){
- Db::rollback();
- return false;
- }
- //修改预约单状态
- $update = [
- 'order_status' => 10,
- 'paytime' => $time,
- 'updatetime' => $time,
- 'package_order_id' => $package_order['id'],
- 'paytype' => 1, //从购买套餐中3,改为 课程套餐1
- ];
- $update['package_remark'] = ($package_order['sessions'] - $package_order['remain']) . '-' . ($package_order['sessions'] - $package_order['remain'] + $lesson_order['usernumber_hours']) .'/'. $package_order['sessions'];
- $rs = Db::name('lesson_order')->where('id',$args['lesson_order_id'])->update($update);
- if($rs === false){
- Db::rollback();
- return false;
- }
- //更新已预约人数
- $pay_number = Db::name('lesson_order')->where('slot_id',$lesson_order['slot_id'])->where('order_status',10)->sum('usernumber');
- $rs_slot = Db::name('lesson_slot')->where('id',$lesson_order['slot_id'])->update(['bookednum' => $pay_number]);
- if($rs_slot === false){
- Db::rollback();
- return false;
- }
- }else{
- //新买的课时不足以支撑这次的报名人数,不处理
- }
- }
- }
- //逻辑结束
- //状态
- $ros = Db::name('pay_order')->where(['out_trade_no' => $out_trade_no])->update(['order_status'=>1,'notifytime'=>$time,'payment_id'=>$payment_id]);
- if($ros === false) {
- Db::rollback();
- return false;
- }
- //默认提交
- Db::commit();
- return true;
- }
- //异步日志
- private function notify_log_start($paytype = 'wechat'){
- //记录支付回调数据
- ignore_user_abort(); // run script in background
- set_time_limit(30);
- // 日志文件 start
- $log_base_dir = '../paylog/'.$paytype.'/';
- if (!is_dir($log_base_dir))
- {
- mkdir($log_base_dir, 0770, true);
- @chmod($log_base_dir, 0770);
- }
- $notify_file = $log_base_dir.'notify.txt';
- if(!file_exists($notify_file)) {
- @touch($notify_file);
- @chmod($notify_file, 0770);
- }
- if(filesize($notify_file)>5242880)//大于5M自动切换
- {
- rename($notify_file, $log_base_dir.'notify_'.date('Y_m_d_H_i_s').'.txt');
- }
- if(!file_exists($notify_file)) {
- @touch($notify_file);
- @chmod($notify_file, 0770);
- }
- // 日志文件 end
- //开始写入
- $xml = file_get_contents("php://input");
- file_put_contents($notify_file, "\r\n\r\n".date('Y-m-d H:i:s')." [notify][入口接收php://input流原始数据] \n".$xml, FILE_APPEND);
- ini_set('display_errors','On');
- return $notify_file;
- }
- }
|