<?php namespace app\api\controller; use app\common\controller\Api; use EasyWeChat\Factory; use function GuzzleHttp\Promise\inspect; use think\Db; use app\admin\model\User; use think\Log; use fast\Http; use think\Validate; use Exception; use function EasyWeChat\Kernel\Support\generate_sign; use app\nsms\nsms; /** * 支付接口 */ class Pay extends Api { protected $noNeedLogin = ['test','payOrderNotify','vippayOrderNotify','picOrderNotify','videoOrderNotify','sms','send_sms']; protected $noNeedRight = ['*']; protected $uid = '';//token存贮uid protected $order_status = [];//订单状态 public function _initialize() { parent::_initialize(); $this->uid = $this->auth->getUserId(); } /** * @ApiTitle (充值支付) * @ApiSummary (充值支付) * @ApiMethod (POST) * @ApiRoute (/api/pay/pay) * @ApiHeaders (name=token, type=string, required=true, description="请求的Token") * * @ApiParams (name="order_id", type="inter", required=true, description="订单id") * */ public function pay(){ $rule = config('verify.path'); if($this->request->isPost()){ $order_id = $this->request->post('order_id'); $openid = $this->getopenid(); if(empty($openid)){ $this->error(['code'=>2,'msg'=>'openid不能为空']); } $data = Db::name('toporder')->where('id',$order_id)->find(); if($data){ if($data['status'] == 2){ $this->error('该订单已支付过了'); }else{ //创建支付对象 $config = config('verify.wx_pay'); $app = Factory::payment($config); $result = $app->order->unify([ 'body' => '山东航拍', 'out_trade_no' => $data['num'],//支付订单号 'total_fee' => $data['money']*100,//单位分 'notify_url' => 'https://areial.w.broing.cn/api/pay/payOrderNotify', // 支付结果通知网址,如果不设置则会使用配置里的默认地址 'trade_type' => 'JSAPI', // 请对应换成你的支付方式对应的值类型 'openid' => $openid['openid'], ]); if($result['return_code'] === 'SUCCESS' && $result['result_code'] === 'SUCCESS'){ $params = [ 'appId' => $config['app_id'], 'timeStamp' => time(), 'nonceStr' => $result['nonce_str'], // 统一下单返回的随机字符串 'package' => 'prepay_id='.$result['prepay_id'], // 统一下单Id 'signType' => 'MD5', // 签名方法 ]; // 注意这里用的是商户平台的Key进行二次签名 $params['paySign'] = generate_sign($params, $config['key']); $this->success('成功',$params); } $this->error($result['err_code_des']); } }else{ $this->error('无效的订单'); } }else{ $this->error('请求方式错误'); } } /** * @ApiTitle (开通会员支付) * @ApiSummary (开通会员支付) * @ApiMethod (POST) * @ApiRoute (/api/pay/vippay) * @ApiHeaders (name=token, type=string, required=true, description="请求的Token") * * @ApiParams (name="order_id", type="inter", required=true, description="订单id") * */ public function vippay(){ $rule = config('verify.path'); if($this->request->isPost()){ $order_id = $this->request->post('order_id'); $openid = $this->getopenid(); if(empty($openid)){ $this->error(['code'=>2,'msg'=>'openid不能为空']); } $data = Db::name('viporder')->where('id',$order_id)->find(); if($data){ if($data['status'] == 2){ $this->error('该订单已支付过了'); }else{ if($data['user_id'] == 12){ $data['total'] = 0.01; } //创建支付对象 $config = config('verify.wx_pay'); $app = Factory::payment($config); $result = $app->order->unify([ 'body' => '山东航拍', 'out_trade_no' => $data['num'],//支付订单号 'total_fee' => $data['total']*100,//单位分 'notify_url' => 'https://areial.w.broing.cn/api/pay/vippayOrderNotify', // 支付结果通知网址,如果不设置则会使用配置里的默认地址 'trade_type' => 'JSAPI', // 请对应换成你的支付方式对应的值类型 'openid' => $openid['openid'], ]); if($result['return_code'] === 'SUCCESS' && $result['result_code'] === 'SUCCESS'){ $params = [ 'appId' => $config['app_id'], 'timeStamp' => time(), 'nonceStr' => $result['nonce_str'], // 统一下单返回的随机字符串 'package' => 'prepay_id='.$result['prepay_id'], // 统一下单Id 'signType' => 'MD5', // 签名方法 ]; // 注意这里用的是商户平台的Key进行二次签名 $params['paySign'] = generate_sign($params, $config['key']); $this->success('成功',$params); } $this->error($result['err_code_des']); } }else{ $this->error('无效的订单'); } }else{ $this->error('请求方式错误'); } } /** * @ApiTitle (购买支付) * @ApiSummary (购买支付) * @ApiMethod (POST) * @ApiRoute (/api/pay/picpay) * @ApiHeaders (name=token, type=string, required=true, description="请求的Token") * * @ApiParams (name="order_id", type="inter", required=true, description="订单id") * @ApiParams (name="type", type="inter", required=true, description="支付方式 1 为余额支付 2为微信支付") * */ public function picpay(){ $rule = config('verify.path'); if($this->request->isPost()){ $order_id = $this->request->post('order_id'); $type = $this->request->post('type'); //判断付费类型 if(empty($type)){ $this->error(['code'=>2,'msg'=>'缺少必要参数']); } $openid = $this->getopenid(); //判断openid if(empty($openid)){ $this->error(['code'=>2,'msg'=>'openid不能为空']); } $data = Db::name('order')->where('id',$order_id)->find(); $pic_id = []; if(!empty($data['pic_id'])){ $pic_id = explode(',',$data['pic_id']); } $video_id = unserialize($data['video_id']); //查询用户表 取出手机号 $user = Db::name('user')->where('id',$data['user_id'])->find(); $mobile = $user['mobile']; $str = "【仁甲看见SHOP】,感谢您购买仁甲看见SHOP素材。"; if($type == 1){ if($data){ if($data['status'] == 2){ $this->error('该订单已支付过了'); }else{ //判断总价是否正确 if($data['total'] > $user['money']){ $this->error(['code'=>2,'msg'=>'余额不足,请充值后重试']); } $money = $user['money'] - $data['total']; $uid = $this->uid; $login = Db::name('user') ->where('id',$uid) ->field('id,is_vip') ->find(); // 启动事务 Db::startTrans(); try{ if(!empty($pic_id)){ //将购买次数加1 foreach ($pic_id as $key => $v){ //非会员 if($login['is_vip'] == 0){ $pic = Db::name('pic')->field('id,price,buy_num,money')->where('id',$v)->find(); Db::name('pic')->where('id',$pic['id'])->update(['buy_num'=>$pic['buy_num']+1,'money'=>$pic['money']+$pic['price']]); }else{ //是会员 $pic = Db::name('pic')->field('id,price,buy_num,money')->where('id',$v)->find(); $total_money = $pic['money'] + ($pic['price']*0.75); Db::name('pic')->where('id',$pic['id'])->update(['buy_num'=>$pic['buy_num']+1,'money'=>$total_money]); } } //拼接发送短信的内容 foreach ($pic_id as $key => $v){ $pic = Db::name('pic')->field('id,title,url,code')->where('id',$v)->find(); $str .= "图片标题:$pic[title],云盘地址:$pic[url],提取码:$pic[code],"; } } if(!empty($video_id)){ //判断是否为会员 if($login['is_vip'] == 0){ //不是会员的情况 //将购买次数加1 foreach ($video_id as $key => $val){ $video = Db::name('video')->field('id,buy_num,price,four_price,eight_price,money')->where('id',$val['id'])->find(); if($val['attr'] == 1){ $video_money = $video['money'] + $video['price']; }elseif ($val['attr'] == 2){ $video_money = $video['money'] + $video['four_price']; }else{ $video_money = $video['money'] + $video['eight_price']; } Db::name('video')->where('id',$video['id'])->update(['buy_num'=>$video['buy_num']+1,'money'=>$video_money]); } }else{ //是会员的情况 //将购买次数加1 foreach ($video_id as $key => $val){ $video = Db::name('video')->field('id,buy_num,price,four_price,eight_price,money')->where('id',$val['id'])->find(); if($val['attr'] == 1){ $video_money = $video['money'] + ($video['price']*0.75); }elseif ($val['attr'] == 2){ $video_money = $video['money'] + ($video['four_price']*0.75); }else{ $video_money = $video['money'] + ($video['eight_price']*0.75); } Db::name('video')->where('id',$video['id'])->update(['buy_num'=>$video['buy_num']+1,'money'=>$video_money]); } } //判断视频的属性 foreach ($video_id as &$val){ if($val['attr'] == 1){ $val['attr'] = '2k'; }elseif ($val['attr'] == 2){ $val['attr'] = '4k'; }else{ $val['attr'] = '8k'; } } //拼接发送短信的内容 foreach ($video_id as $k=>$v){ if($v['attr'] == '4k'){ $video = Db::name('video')->field('id,title,four_url,four_code')->where('id',$v['id'])->find(); $str .= "视频标题:$video[title],云盘地址:$video[four_url],提取码:$video[four_code]"; }elseif ($v['attr'] == '2k'){ $video = Db::name('video')->field('id,title,two_url,two_code')->where('id',$v['id'])->find(); $str .= "视频标题:$video[title],云盘地址:$video[two_url],提取码:$video[two_code]"; }elseif ($v['attr'] == '8k'){ $video = Db::name('video')->field('id,title,eight_url,eight_code')->where('id',$v['id'])->find(); $str .= "视频标题:$video[title],云盘地址:$video[eight_url],提取码:$video[eight_code]"; } } } //发送短信 if(!empty($mobile)){ $result = $this->sms($mobile,$str); } $arr = Db::name('user')->where('id',$data['user_id'])->update(['money'=>$money]); $res = Db::name('order')->where('id',$order_id)->update(['status'=>2,'paytime'=>time()]); if($res && $arr){ true; } // 提交事务 Db::commit(); } catch (\Exception $e) { dump($e->getMessage()); // 回滚事务 Db::rollback(); $this->error('购买失败'); } $this->success('SUCCESS','支付成功'); } }else{ $this->error('无效的订单'); } }else{ if($data){ if($data['status'] == 2){ $this->error('该订单已支付过了'); }else{ //创建支付对象 $config = config('verify.wx_pay'); $app = Factory::payment($config); $result = $app->order->unify([ 'body' => '山东航拍', 'out_trade_no' => $data['num'],//支付订单号 'total_fee' => $data['total']*100,//单位分 'notify_url' => 'https://areial.w.broing.cn/api/pay/picOrderNotify', // 支付结果通知网址,如果不设置则会使用配置里的默认地址 'trade_type' => 'JSAPI', // 请对应换成你的支付方式对应的值类型 'openid' => $openid['openid'], ]); if($result['return_code'] === 'SUCCESS' && $result['result_code'] === 'SUCCESS'){ $params = [ 'appId' => $config['app_id'], 'timeStamp' => time(), 'nonceStr' => $result['nonce_str'], // 统一下单返回的随机字符串 'package' => 'prepay_id='.$result['prepay_id'], // 统一下单Id 'signType' => 'MD5', // 签名方法 ]; // 注意这里用的是商户平台的Key进行二次签名 $params['paySign'] = generate_sign($params, $config['key']); $this->success('成功',$params); } $this->error($result['err_code_des']); } }else{ $this->error('无效的订单'); } } }else{ $this->error('请求方式错误'); } } /** * @ApiTitle (预约拍摄) * @ApiSummary (预约拍摄) * @ApiMethod (POST) * @ApiRoute (/api/pay/appointment) * @ApiHeaders (name=token, type=string, required=true, description="请求的Token") * * @ApiParams (name="phone", type="inter", required=true, description="手机号") * */ public function appointment() { $u_id = $this->uid; $phone = $this->request->param('phone'); if(empty($phone)){ $this->error('缺少必要参数'); } $mobile = 13780608990; $content = "【仁甲看见SHOP】提醒您,您有新预约客户,客户电话为:$phone ,请您及时回复!"; //发送短信 $result = $this->sms($mobile,$content); if($result == 1){ $this->success('success','成功'); }else{ $this->error('失败'); } } //发送短信 public function sms($mobile,$content){ $note = array( 'content' => $content,//短信内容 'mobile' => $mobile,//手机号码 'productid' => '676767',//模板id 'xh' => ''//小号 ); $result = $this->send_sms($note); return $result; } function send_sms($data){ //todo 短信账号密码 // require_once EXTEND_PATH . 'nsms/nsms.php'; $url = "http://www.ztsms.cn/sendNSms.do"; $username = 'hangpai'; $password = 'Cxz307312'; $sendAPI = new nsms($url, $username, $password); $sendAPI->data = $data;/*初始化数据包*/ $return = $sendAPI->sendSMS('POST'); return $return; } //支付订单结果通知(无需调用) public function payOrderNotify(){ $config = config('verify.wx_pay'); $app = Factory::payment($config); $response = $app->handlePaidNotify(function($message, $fail){ Log::write(date('Y-m-d H:i:s').json_encode($message,JSON_UNESCAPED_UNICODE),'notice'); $data = Db::name('toporder') ->where('num',$message['out_trade_no']) ->find(); //return_code 表示通信状态 if ($message['return_code'] === 'SUCCESS') { if ($message['result_code'] === 'SUCCESS') { if($data['status'] == 1) { //支付成功,更新订单状态 $toporder['id'] = $data['id']; $toporder['status'] = 2; $toporder['paytime'] = time(); $money = $data['money']; // 启动事务 Db::startTrans(); try { Db::name('toporder')->update($toporder); //判断用户充值金额是否大于等于8000 if ($data['money'] >= 8000) { //大于等于的情况 $arr = Db::name('user')->where('id', $data['user_id'])->find(); //判断用户是否已经是会员了 if ($arr['is_vip'] == 1) { //已经是会员 $list['money'] = $arr['money'] + $money; Db::name('user')->where('id', $data['user_id'])->update(['money' => $list['money']]); // 提交事务 Db::commit(); } else { //不是会员 $list['money'] = $arr['money'] + $money; $list['is_vip'] = 1; Db::name('user')->where('id', $data['user_id'])->update($list); // 提交事务 Db::commit(); } } else { //小于8000的情况 $arr = Db::name('user')->where('id', $data['user_id'])->find(); $list['money'] = $arr['money'] + $money; Db::name('user')->where('id', $data['user_id'])->update(['money' => $list['money']]); // 提交事务 Db::commit(); } } catch (\Exception $e) { // 回滚事务 Db::rollback(); return false; } } }else{ $toporder['status'] = 1; //支付失败 Db::name('toporder')->where('num',$message['out_trade_no'])->update($toporder); return false; } }else{ return $fail('通信失败,请稍后再通知我'); } return true; }); $response->send(); } //支付开通会员结果通知(无需调用) public function vippayOrderNotify(){ $config = config('verify.wx_pay'); $app = Factory::payment($config); $response = $app->handlePaidNotify(function($message, $fail){ Log::write(date('Y-m-d H:i:s').json_encode($message,JSON_UNESCAPED_UNICODE),'notice'); $data = Db::name('viporder') ->where('num',$message['out_trade_no']) ->find(); //return_code 表示通信状态 if ($message['return_code'] === 'SUCCESS') { if ($message['result_code'] === 'SUCCESS') { if($data['status'] == 1){ //支付成功,更新订单状态 $viporder['status'] = 2; $viporder['paytime'] = time(); $money = $data['total']; // 启动事务 Db::startTrans(); try{ Db::name('viporder')->where('id',$data['id'])->update($viporder); //判断用户充值金额是否大于等于8000 if($data['total']>=8000){ //大于等于的情况 $arr = Db::name('user')->where('id',$data['user_id'])->find(); //不是会员 $list['money'] = $arr['money'] + $money; $list['is_vip'] = 1; Db::name('user')->where('id',$data['user_id'])->update($list); // 提交事务 Db::commit(); }else{ //小于8000的情况 $arr = Db::name('user')->where('id',$data['user_id'])->find(); $list['money'] = $arr['money'] + $money; Db::name('user')->where('id',$data['user_id'])->update(['money'=>$list['money']]); // 提交事务 Db::commit(); } } catch (\Exception $e) { // 回滚事务 Db::rollback(); return false; } } }else{ //支付失败 Db::name('viporder')->where('num',$message['out_trade_no'])->update(['status'=>1]); return false; } }else{ return $fail('通信失败,请稍后再通知我'); } return true; }); $response->send(); } //图片支付订单结果通知(无需调用) public function picOrderNotify(){ $config = config('verify.wx_pay'); $app = Factory::payment($config); $response = $app->handlePaidNotify(function($message, $fail){ //找到该订单信息 $data = Db::name('order')->where('num',$message['out_trade_no'])->find(); $pic_id = []; if(!empty($data['pic_id'])){ $pic_id = explode(',',$data['pic_id']); } $video_id = unserialize($data['video_id']); //查询该用户信息以及是否为会员身份 $user = Db::name('user')->where('id',$data['user_id'])->find(); $mobile = $user['mobile']; $str = "【仁甲看见SHOP】,感谢您购买仁甲看见SHOP素材。"; //return_code 表示通信状态 if ($message['return_code'] === 'SUCCESS') { if ($message['result_code'] === 'SUCCESS') { //图片 if(!empty($pic_id)){ //将购买次数加1 foreach ($pic_id as $key => $v){ //非会员 if($user['is_vip'] == 0){ $pic = Db::name('pic')->field('id,price,buy_num,money')->where('id',$v)->find(); Db::name('pic')->where('id',$pic['id'])->update(['buy_num'=>$pic['buy_num']+1,'money'=>$pic['money']+$pic['price']]); }else{ //是会员 $pic = Db::name('pic')->field('id,price,buy_num,money')->where('id',$v)->find(); $total_money = $pic['money'] + ($pic['price']*0.75); Db::name('pic')->where('id',$pic['id'])->update(['buy_num'=>$pic['buy_num']+1,'money'=>$total_money]); } } //拼接发送短信的内容 foreach ($pic_id as $key => $v){ $pic = Db::name('pic')->field('id,title,url,code')->where('id',$v)->find(); $str .= "图片标题:$pic[title],云盘地址:$pic[url],提取码:$pic[code],"; } } //视频 if(!empty($video_id)){ //判断是否为会员 if($user['is_vip'] == 0){ //不是会员的情况 //将购买次数加1 foreach ($video_id as $key => $val){ $video = Db::name('video')->field('id,buy_num,price,four_price,eight_price,money')->where('id',$val['id'])->find(); if($val['attr'] == 1){ $video_money = $video['money'] + $video['price']; }elseif ($val['attr'] == 2){ $video_money = $video['money'] + $video['four_price']; }else{ $video_money = $video['money'] + $video['eight_price']; } Db::name('video')->where('id',$video['id'])->update(['buy_num'=>$video['buy_num']+1,'money'=>$video_money]); } }else{ //是会员的情况 //将购买次数加1 foreach ($video_id as $key => $val){ $video = Db::name('video')->field('id,buy_num,price,four_price,eight_price,money')->where('id',$val['id'])->find(); if($val['attr'] == 1){ $video_money = $video['money'] + ($video['price']*0.75); }elseif ($val['attr'] == 2){ $video_money = $video['money'] + ($video['four_price']*0.75); }else{ $video_money = $video['money'] + ($video['eight_price']*0.75); } Db::name('video')->where('id',$video['id'])->update(['buy_num'=>$video['buy_num']+1,'money'=>$video_money]); } } //判断视频的属性 foreach ($video_id as &$val){ if($val['attr'] == 1){ $val['attr'] = '2k'; }elseif ($val['attr'] == 2){ $val['attr'] = '4k'; }else{ $val['attr'] = '8k'; } } //拼接发送短信的内容 foreach ($video_id as $k=>$v){ if($v['attr'] == '4k'){ $video = Db::name('video')->field('id,title,four_url,four_code')->where('id',$v['id'])->find(); $str .= "视频标题:$video[title],云盘地址:$video[four_url],提取码:$video[four_code]"; }elseif ($v['attr'] == '2k'){ $video = Db::name('video')->field('id,title,two_url,two_code')->where('id',$v['id'])->find(); $str .= "视频标题:$video[title],云盘地址:$video[two_url],提取码:$video[two_code]"; }elseif ($v['attr'] == '8k'){ $video = Db::name('video')->field('id,title,eight_url,eight_code')->where('id',$v['id'])->find(); $str .= "视频标题:$video[title],云盘地址:$video[eight_url],提取码:$video[eight_code]"; } } } //发送短信 if(!empty($mobile)){ $result = $this->sms($mobile,$str); } //支付成功,更新订单状态 $toporder['status'] = 2; $toporder['paytime'] = time(); }else{ //支付失败 $toporder['status'] = 1; } Db::name('order')->where('num',$message['out_trade_no'])->update($toporder); }else{ return $fail('通信失败,请稍后再通知我'); } return true; }); $response->send(); } //获取用户openid public function getopenid() { $user_id = $this->uid; $openid = Db::name('user') ->where('id',$user_id) ->field('openid') ->find(); return $openid; } }