902 lines
		
	
	
		
			36 KiB
		
	
	
	
		
			PHP
		
	
	
			
		
		
	
	
			902 lines
		
	
	
		
			36 KiB
		
	
	
	
		
			PHP
		
	
	
| <?php
 | ||
| namespace app\controller\api;
 | ||
| 
 | ||
| use app\exception\RepositoryException;
 | ||
| use app\model\Account;
 | ||
| use app\model\Coupon as CouponModel;
 | ||
| use app\model\CouponBill;
 | ||
| use app\model\CouponMain;
 | ||
| use app\model\Deduction;
 | ||
| use app\model\Redpack;
 | ||
| use app\model\Business as BusinessModel;
 | ||
| use app\model\Score;
 | ||
| use app\model\UsingRule;
 | ||
| use app\repository\AccountRepository;
 | ||
| use app\repository\BusinessRepository;
 | ||
| use app\repository\CouponRepository;
 | ||
| use app\service\wx\WechatPay;
 | ||
| use app\validate\CouponRelease;
 | ||
| use app\validate\CouponUsingRule;
 | ||
| 
 | ||
| use think\Exception;
 | ||
| use think\facade\Config;
 | ||
| use think\facade\Db;
 | ||
| use think\facade\Log;
 | ||
| 
 | ||
| /**
 | ||
|  * 优惠卷相关
 | ||
|  * Class Coupon
 | ||
|  * @package app\controller\api
 | ||
|  */
 | ||
| class Coupon extends Base
 | ||
| {
 | ||
|     protected $noNeedLogin = [];
 | ||
| 
 | ||
|     /**
 | ||
|      * 我的优惠卷列表
 | ||
|      *
 | ||
|      * type in ['', 'notUsed', 'normal', 'used']
 | ||
|      */
 | ||
|     public function getCouponList()
 | ||
|     {
 | ||
|         $page       = $this->request->param('page/d', 1);
 | ||
|         $size       = $this->request->param('size/d', 10);
 | ||
|         $type       = $this->request->param('type', '');
 | ||
| 
 | ||
|         $page       = $page < 1 ? 1 : $page;
 | ||
|         $size       = $size < 1 ? 10 : $size;
 | ||
|         $accountCode    = $this->request->user['user_code'] ?? '';
 | ||
| 
 | ||
| 
 | ||
|         try {
 | ||
|             $whereMap   = [];
 | ||
|             $sortOrder  = ['received_time' => 'desc'];
 | ||
|             $fields     = [
 | ||
|                 'id',
 | ||
|                 'is_verificated as isVerificated',
 | ||
|                 'type_name',
 | ||
|                 'money',
 | ||
|                 'name as couponName',
 | ||
|                 'business_code',
 | ||
|                 'business_code as businessCode',
 | ||
|                 'coupon_id',
 | ||
|                 'end_time as endTime',
 | ||
|                 'consumer_name as consumerName',
 | ||
|                 'verificate_time as verificateTime',
 | ||
|                 '(end_time > NOW()) as sort_weight'];
 | ||
| 
 | ||
|             $whereMap[] = ['consumer_code', '=', $accountCode];
 | ||
|             switch ($type) {
 | ||
|                 case 'all':
 | ||
|                     // 全部持有优惠券
 | ||
|                     $sortOrder  = ['sort_weight' => 'desc', 'end_time' => 'asc'];
 | ||
|                     break;
 | ||
|                 case 'notUsed':
 | ||
|                     // 未使用(包含已过期)
 | ||
|                     $whereMap[] = ['is_verificated', '=', self::BOOL_FALSE];
 | ||
|                     $sortOrder  = ['sort_weight' => 'desc', 'end_time' => 'asc'];
 | ||
|                     break;
 | ||
|                 case 'normal':
 | ||
|                     // 未使用且未过期
 | ||
|                     $whereMap[] = ['is_verificated', '=', self::BOOL_FALSE];
 | ||
|                     $whereMap[] = ['end_time', '< TIME', date('Y-m-d H:i:s')];
 | ||
|                     break;
 | ||
|                 case 'used':
 | ||
|                     // 已使用
 | ||
|                     $whereMap[] = ['is_verificated', '=', self::BOOL_TRUE];
 | ||
|                     $sortOrder  = ['verificate_time' => 'desc'];
 | ||
|                     break;
 | ||
|             }
 | ||
| 
 | ||
|             $res    = CouponRepository::getInstance()->findList($whereMap, $fields, $page, $size,function ($q){
 | ||
|                 return $q->with(["couponMain","scoreModel","business"]);
 | ||
|             }, $sortOrder);
 | ||
|             $time = time();
 | ||
|             $res['list'] ->each(function ($item) use($time){
 | ||
|                 //重置优惠券名称
 | ||
|                 if(isset($item->couponMain) && $item->couponMain){
 | ||
|                     $item->couponName =  $item->couponMain->name;
 | ||
|                     $item->image_url = $this->request->domain() . $item->couponMain->image_url;
 | ||
|                 }else{
 | ||
|                     $item->image_url = $this->request->domain() . '';
 | ||
|                 }
 | ||
|                 //是否已经打分过了
 | ||
|                 if(isset($item->scoreModel) && $item->scoreModel){
 | ||
|                     $item->scored   =  true;
 | ||
|                     $item->score    =  $item->scoreModel->score;
 | ||
|                 }else{
 | ||
|                     $item->scored   =  false;
 | ||
|                     $item->score    =  Score::COMMON_OFF;
 | ||
|                 }
 | ||
| 
 | ||
| 
 | ||
|                 //到期状态
 | ||
|                 $expirationStr = '';
 | ||
|                 $endTime = strtotime($item->endTime);
 | ||
|                 $ExpirationTime = abs(($endTime - $time) / 86400);
 | ||
|                 if (($endTime > $time) ) {
 | ||
|                     $expirationStr = "还有".ceil($ExpirationTime)."天过期期";
 | ||
|                 } else {
 | ||
|                     $expirationStr = "已过期" . ceil($ExpirationTime) . "天";
 | ||
|                 }
 | ||
|                 $item->expirationStr =$expirationStr;
 | ||
| 
 | ||
| 
 | ||
|                 //商家简称
 | ||
|                 if(!empty($item->business)){
 | ||
|                     $item->business_subtitle = $item->business->business_subtitle;
 | ||
|                 }else{
 | ||
|                     $item->business_subtitle = '';
 | ||
|                 }
 | ||
| 
 | ||
|                 //图片
 | ||
|                 if(!empty($item->business)){
 | ||
|                     $item->business_subtitle = $item->business->business_subtitle;
 | ||
|                 }else{
 | ||
|                     $item->business_subtitle = '';
 | ||
|                 }
 | ||
| 
 | ||
|             });
 | ||
| 
 | ||
|             $res['list']    = multiTwoArrayKeysExcludeFilter($res['list']->toArray(), ['sort_weight']);
 | ||
|             return $this->json(0, 'success', $res);
 | ||
|         } catch (RepositoryException | \Exception $e) {
 | ||
|             return $this->json(5001, '优惠卷查询失败!');
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * 我的优惠卷列表  指定商家  未验证
 | ||
|      *
 | ||
|      */
 | ||
|     public function getCouponListByBusinessCode()
 | ||
|     {
 | ||
|         $page           = $this->request->param('page/d', 1);
 | ||
|         $size           = $this->request->param('size/d', 10);
 | ||
|         $businessCode   = $this->request->param('business_code/s', '');
 | ||
| 
 | ||
| 
 | ||
|         $page       = $page < 1 ? 1 : $page;
 | ||
|         $size       = $size < 1 ? 10 : $size;
 | ||
|         $accountCode    = $this->request->user['user_code'] ?? '';
 | ||
| 
 | ||
| 
 | ||
|         try {
 | ||
|             $whereMap   = [];
 | ||
|             $fields     = [
 | ||
|                 'id',
 | ||
|                 'is_verificated as isVerificated',
 | ||
|                 'money',
 | ||
|                 'name as couponName',
 | ||
|                 'business_code as businessCode',
 | ||
|                 'end_time as endTime',
 | ||
|                 'consumer_name as consumerName',
 | ||
|                 'verificate_time as verificateTime',
 | ||
|                 '(end_time > NOW()) as sort_weight'];
 | ||
| 
 | ||
|             $whereMap[] = ['consumer_code', '=', $accountCode];
 | ||
|             $whereMap[] = ['business_code', '=', $businessCode];
 | ||
|             $whereMap[] = ['is_verificated', '=', CouponModel::is_verificated_off];
 | ||
|             $sortOrder  = ['sort_weight' => 'desc', 'end_time' => 'asc'];
 | ||
| 
 | ||
|             $res    = CouponRepository::getInstance()->findList($whereMap, $fields, $page, $size,function ($q){
 | ||
|                 return $q->with(["couponMain","scoreModel"]);
 | ||
|             }, $sortOrder);
 | ||
| 
 | ||
|             $res['list'] ->each(function ($item){
 | ||
|                 //重置优惠券名称
 | ||
|                 if(isset($item->couponMain) && $item->couponMain){
 | ||
|                     $item->couponName =  $item->couponMain->name;
 | ||
|                 }
 | ||
|                 //重置过期时间
 | ||
|                 $item->endTimeText = date("Y-m-d",strtotime($item->endTime));
 | ||
|             });
 | ||
| 
 | ||
|             $res['list']    = multiTwoArrayKeysExcludeFilter($res['list']->toArray(), ['sort_weight']);
 | ||
|             return $this->json(0, 'success', $res);
 | ||
|         } catch (RepositoryException | \Exception $e) {
 | ||
|             return $this->json(5001, '优惠卷查询失败!');
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * 领取优惠券
 | ||
|      * */
 | ||
|     public function receiveCoupon()
 | ||
|     {
 | ||
|         $accountId = $this->request->user['user_id'] ?? 0;
 | ||
|         $lat = input("lat/f",0);
 | ||
|         $lng =  input("lng/f",0);
 | ||
|         $account = AccountRepository::getInstance()->findById($accountId, [], function ($q) {
 | ||
|             return $q->with(['business', 'parent']);
 | ||
|         });
 | ||
|         if(empty($account)){
 | ||
|             return $this->json(6001,"无效的用户");
 | ||
|         }
 | ||
| 
 | ||
|         if ($lat <= 0 || $lng <= 0) {
 | ||
|             return $this->json(4001, "请授权定位");
 | ||
|         }
 | ||
| 
 | ||
|         $couponMainId = input("couponId/d", 0);
 | ||
|         $couponMain = CouponMain::findOne(["id" => $couponMainId],[],function ($q){
 | ||
|             //执行领取 开启锁
 | ||
|             return $q->with("business")->lock(true);
 | ||
|         });
 | ||
|         if(!isset($couponMain->business)||empty($couponMain->business)){
 | ||
|             return $this->json(4001, "优惠券所属商家不存在");
 | ||
|         }
 | ||
| 
 | ||
|         if($couponMain->business->enable != BusinessModel::COMMON_OFF){
 | ||
|             return $this->json(4001, "商家已禁用");
 | ||
|         }
 | ||
| 
 | ||
|         try {
 | ||
|             //检查优惠券状态
 | ||
|            CouponRepository::getInstance()->checkCouponMainReceiveStatus($couponMain);
 | ||
|         }catch (RepositoryException $e){
 | ||
|             return $this->json(4001,$e->getMessage());
 | ||
|         }
 | ||
| 
 | ||
| 
 | ||
|         try {
 | ||
|             //检查是否可以领取  0可领取 1已领取
 | ||
|            AccountRepository::getInstance()->getCouponReceiveStatusText($account,$couponMain);//领取状态
 | ||
|         }catch (RepositoryException $e){
 | ||
|             return $this->json(4001,$e->getMessage());
 | ||
|         }
 | ||
| 
 | ||
| 
 | ||
|         //检查通过 执行领取
 | ||
|         $time = time();
 | ||
|         Db::startTrans();
 | ||
|         try {
 | ||
|             //写入领取记录
 | ||
|             $data = [
 | ||
|                 "coupon_id"     =>$couponMain->id,
 | ||
|                 "name"          =>$couponMain->name,
 | ||
|                 "type_id"          =>$couponMain->type,
 | ||
|                 "type_name"          =>$couponMain->type_name,
 | ||
|                 "business_code"          =>$couponMain->business_code,
 | ||
|                 "business_name"          =>$couponMain->business?$couponMain->business->business_name:'',
 | ||
|                 "consumer_code"          =>$account->user_code,
 | ||
|                 "consumer_name"          =>$account->nick_name,
 | ||
|                 "money"          => $couponMain->money,
 | ||
|                 "content"          => createUuid(),//未知作用
 | ||
|                 "received_time"          => date("Y-m-d H:i:s",$time),
 | ||
|                 "lat"          => $lat,
 | ||
|                 "lng"          => $lng,
 | ||
|                 "end_time"          => date($couponMain->end_time . " 00:00:00"),
 | ||
|                 "edition"          => couponMain::COMMON_ON,//版本  未知作用
 | ||
|                 "is_verificated"          => couponMain::COMMON_OFF,//版本  未知作用
 | ||
|             ];
 | ||
|             CouponRepository::getInstance()->receiveCoupon($data);
 | ||
|             $couponMain->save(["received_count"=>Db::raw("received_count + 1")]);
 | ||
|             Db::commit();
 | ||
|             return $this->json();
 | ||
|         }catch (RepositoryException $e){
 | ||
|             Log::error("优惠券领取失败RepositoryException:".$e->getMessage());
 | ||
|             Db::rollback();
 | ||
|             return $this->json(5001,"领取失败");
 | ||
|         }catch (Exception $e){
 | ||
|             Log::error("优惠券领取失败:".$e->getMessage());
 | ||
|             Db::rollback();
 | ||
|             return $this->json(5001,"领取失败");
 | ||
|         }
 | ||
| 
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * 核验优惠券  程序----核心操作----
 | ||
|      * */
 | ||
|     public function verification()
 | ||
|     {
 | ||
|         $accountId      = $this->request->user['user_id'] ?? 0;
 | ||
|         $lat            = input("lat/f",0);
 | ||
|         $lng            =  input("lng/f",0);
 | ||
|         $couponId       =  input("couponId/d",0);
 | ||
|         $account        = AccountRepository::getInstance()->findById($accountId, [], function ($q) {
 | ||
|             return $q->with(['business', 'parent']);
 | ||
|         });
 | ||
|         $time = time();
 | ||
|         if(empty($account)){
 | ||
|             return $this->json(6001,"无效的用户");
 | ||
|         }
 | ||
| 
 | ||
|         if ($lat <= 0 || $lng <= 0) {
 | ||
|             return $this->json(4001, "请授权定位");
 | ||
|         }
 | ||
| 
 | ||
|         $coupon = CouponRepository::getInstance()->findById($couponId,[],function ($q){
 | ||
|             return $q->with(["couponMain","redpack"]);
 | ||
|         });
 | ||
| 
 | ||
|         if(empty($coupon)){
 | ||
|             return $this->json(4001, "优惠券不存在");
 | ||
|         }
 | ||
|         if($coupon->consumer_code != $account->user_code ){
 | ||
|             return $this->json(4001, "参数错误");
 | ||
|         }
 | ||
|         if($coupon->is_verificated != CouponModel::is_verificated_off){
 | ||
|             return $this->json(4001, "优惠券验证");
 | ||
|         }
 | ||
|         if($coupon->status != CouponMain::status_on){
 | ||
|             return $this->json(4001, "优惠券已停用");
 | ||
|         }
 | ||
|         if($coupon->on_shelf != CouponMain::on_shelf_on){
 | ||
|             return $this->json(4001, "优惠券下架");
 | ||
|         }
 | ||
| 
 | ||
| 
 | ||
|         if(!isset($coupon->couponMain) || empty($coupon->couponMain)){
 | ||
|             return $this->json(4001, "商家优惠券信息错误");
 | ||
|         }
 | ||
|         if(strtotime($coupon->couponMain->end_time) < $time){
 | ||
|             return $this->json(4001, "优惠券已过期");
 | ||
|         }
 | ||
|         $usingRule = UsingRule::findOne(["coupon_id"=>$coupon->couponMain->id]);
 | ||
|         if(empty($usingRule)){
 | ||
|             return $this->json(4001, "商家优惠券使用规则信息错误");
 | ||
|         }
 | ||
| 
 | ||
|         //一天的开始时间
 | ||
|         if(strtotime(date("Y-m-d " . $usingRule->day_start_time)) > $time){
 | ||
|             return $this->json(4001, "请在当天{$usingRule->day_start_time}-{$usingRule->day_start_time}使用");
 | ||
|         }
 | ||
|         //一天的结束时间
 | ||
|         if(strtotime(date("Y-m-d ".$usingRule->day_end_time)) < $time){
 | ||
|             return $this->json(4001, "请在当天{$usingRule->day_start_time}-{$usingRule->day_start_time}使用");
 | ||
|         }
 | ||
| 
 | ||
|         //使用周期 周一到周天
 | ||
|         $newW = date("w");
 | ||
|         if(!in_array($newW,$usingRule->cycle)){
 | ||
|             return $this->json(4001, "请在".encodeCouponCycle($usingRule->cycle)."使用");
 | ||
|         }
 | ||
| 
 | ||
| 
 | ||
|         //签到距离
 | ||
|         Config::load('extra/wechat', 'wechat');
 | ||
|         $signDistance = config('wechat.signDistance') ?? 0;
 | ||
| 
 | ||
|         if($signDistance > 0 ){
 | ||
|                 $distance =   get_distance($coupon->couponMain->lat,$coupon->couponMain->lng,$lat,$lng);
 | ||
|                 if($distance > $signDistance){
 | ||
|                     if ($distance >= 1000) {
 | ||
|                         $distanceText = round($distance / 1000, 2) . "千米";
 | ||
|                     } else {
 | ||
|                         $distanceText = $distance . "米";
 | ||
|                     }
 | ||
|                     return $this->json(4001, "您距离商家位置距离超过规定距离{$distanceText}");
 | ||
|                 }
 | ||
|         }
 | ||
| 
 | ||
| 
 | ||
|         $business =  BusinessRepository::getInstance()->getModel()->with(["agency"])->where(["code"=>$coupon->couponMain->business_code])->lock(true)->find();
 | ||
|         if(empty($business)){
 | ||
|             return $this->json(4001, "商家不存在");
 | ||
|         }
 | ||
| 
 | ||
|         if($business->enable != BusinessModel::COMMON_OFF){
 | ||
|             return $this->json(4001, "商家已禁用");
 | ||
|         }
 | ||
| 
 | ||
|         if($business->balance < $coupon->couponMain->deduction_money){
 | ||
|             return $this->json(4001, "商家余额不足");
 | ||
|         }
 | ||
| 
 | ||
|         //开始数据操作
 | ||
|         Db::startTrans();
 | ||
|         try {
 | ||
|             // 1. 修改优惠券状态
 | ||
|             $coupon->save([
 | ||
|                 "is_verificated"        => CouponModel::is_verificated_on,
 | ||
|                 "used_time"             => date("Y-m-d H:i:s" ,$time),
 | ||
|                 "verificate_time"       => date("Y-m-d H:i:s" ,$time),
 | ||
|             ]);
 | ||
|             $coupon->couponMain->save([
 | ||
|                 "verification_count"    => Db::raw("verification_count + 1"),//已验证数量+1
 | ||
|                 "using_count"           => Db::raw("using_count - 1"),//进行中数量-1
 | ||
|             ]);
 | ||
| 
 | ||
| 
 | ||
|             //可分配金额  如果是普通商家
 | ||
|             if($business->model == BusinessModel::model_ordinary) {
 | ||
|                 $deductionMoney     = $coupon->couponMain->deduction_money;
 | ||
|                 $agencyMoney        =  (($deductionMoney/100) * $coupon->couponMain->commission_agency);
 | ||
|                 $adminMoney         =  (($deductionMoney/100) * $coupon->couponMain->commission_admin);
 | ||
|                 $consumerMoney      =  (($deductionMoney/100) * $coupon->couponMain->commission_consumer);
 | ||
|                 $agencyMoney        = round($agencyMoney,2);        //四舍五入 精确到分
 | ||
|                 $adminMoney         = round($adminMoney,2);         //四舍五入 精确到分
 | ||
|                 $consumerMoney      = round($consumerMoney,2);      //四舍五入 精确到分
 | ||
|             }else{
 | ||
|                 $deductionMoney     =  $coupon->couponMain->deduction_money;
 | ||
|                 $adminMoney         =  0;
 | ||
|                 $consumerMoney      =  round($deductionMoney,2) ;
 | ||
|                 $agencyMoney        =  0;        //四舍五入 精确到分
 | ||
|             }
 | ||
| 
 | ||
|             // 2. 写入优惠券流水
 | ||
|             $couponBillData = [
 | ||
|                 "coupon_main_id"            => $coupon->couponMain->id,
 | ||
|                 "coupon_id"                 => $coupon->id,
 | ||
|                 "user_code"                 => $account->user_code,
 | ||
|                 "business_code"             => $business->code,
 | ||
|                 "agency_code"               => $business->agency_code,
 | ||
|                 "commission_agency"         => $coupon->couponMain->commission_agency,
 | ||
|                 "commission_admin"          => $coupon->couponMain->commission_admin,
 | ||
|                 "commission_consumer"       => $coupon->couponMain->commission_consumer,
 | ||
|                 "money"                     => $coupon->couponMain->money,
 | ||
|                 "agency_money"              => $agencyMoney,
 | ||
|                 "admin_money"               => $adminMoney,
 | ||
|                 "consumer_money"            => $consumerMoney,
 | ||
|                 "lat"                       => $lat,
 | ||
|                 "lng"                       => $lng,
 | ||
|                 "create_time"               => date("Y-m-d H:i:s" ,$time),
 | ||
|             ];
 | ||
|            $couponBill = CouponBill::create($couponBillData);
 | ||
| 
 | ||
|             // 3.  写入商家扣费记录
 | ||
|             $deductionData = [
 | ||
|                 "money"                 => $deductionMoney,
 | ||
|                 "user_code"             => $account->user_code,
 | ||
|                 "business_code"         => $business->code,
 | ||
|                 "business_name"         => $business->business_name,
 | ||
|                 "balance"               => $business->balance - $deductionMoney,
 | ||
|                 "reason"                => sprintf("[%s]验证优惠券[%s]扣除[%s]",$account->nick_name, $coupon->couponMain->name,$deductionMoney),
 | ||
|                 "coupon_main_id"        =>  $coupon->couponMain->id,
 | ||
|                 "coupon_id"             =>  $coupon->id,
 | ||
|                 "bill_id"               =>  $couponBill->id,
 | ||
|                 "create_time"           => date("Y-m-d H:i:s",$time),
 | ||
|             ];
 | ||
|             Deduction::create($deductionData);
 | ||
| 
 | ||
|             //4. 商家扣钱
 | ||
|             $business->save(["balance"=>Db::raw("balance - {$deductionMoney}")]);
 | ||
| 
 | ||
|             //5. 渠道商加钱
 | ||
|             if(isset($business->agency) && $business->agency){
 | ||
|                 $business->agency->inc("balance",$agencyMoney)->update();
 | ||
|             }
 | ||
| 
 | ||
|             //6. 用户提现到零钱  写入红包记录
 | ||
|             if($consumerMoney > 0){
 | ||
|                 $payment = WechatPay::getInstance();
 | ||
| 
 | ||
|                 //如果付款过一次了  就查询付款状态
 | ||
|                 if(isset($coupon->redpack) && $coupon->redpack){
 | ||
|                     $result =  $payment->transfer->queryBalanceOrder($coupon->redpack->mch_billno);
 | ||
|                     //var_dump($result);
 | ||
|                     //企业付款成功
 | ||
|                     if(isset($result["status"]) && $result["status"]=="SUCCESS"){
 | ||
|                         Db::commit();
 | ||
|                         return $this->json(0,"优惠券签到使用成功,您获得{$consumerMoney}元红包,已存入您的零钱");
 | ||
|                     }
 | ||
|                     Log::info("查询企业付款失败:".json_encode($result,JSON_UNESCAPED_UNICODE));
 | ||
|                 }else{
 | ||
|                     $mch_billno     = createUuid();
 | ||
|                     $amount         = $consumerMoney*100;
 | ||
|                     $toBalanceData  = [
 | ||
|                         'partner_trade_no'      => $mch_billno,// 商户订单号,需保持唯一性(只能是字母或者数字,不能包含有符号)
 | ||
|                         'openid'                => $account->open_id,
 | ||
|                         'check_name'            => 'NO_CHECK',// NO_CHECK:不校验真实姓名, FORCE_CHECK:强校验真实姓名
 | ||
|                         'amount'                => $amount,  //单位为分,不小于100
 | ||
|                         'desc'                  => '验证优惠券签到',
 | ||
|                     ];
 | ||
|                     $result  =  $payment->transfer->toBalance($toBalanceData);
 | ||
|                     //var_dump($result);
 | ||
| 
 | ||
|                     //付款成功才提交!!!!!伪装成功
 | ||
|                     if(isset($result['payment_no']) || true ){
 | ||
|                         Db::commit();
 | ||
|                         return $this->json(0,"优惠券签到使用成功,您获得{$consumerMoney}元红包,已存入您的零钱");
 | ||
|                     }
 | ||
|                     Log::info("企业发起付款失败:" . json_encode($result,JSON_UNESCAPED_UNICODE));
 | ||
|                 }
 | ||
| 
 | ||
|                 //默认回滚
 | ||
|                 Db::rollback();
 | ||
|                 return $this->json(5001, "验证失败,发放红包失败");
 | ||
|             }
 | ||
|             Db::commit();
 | ||
|             return $this->json();
 | ||
| 
 | ||
|         }catch (RepositoryException $e){
 | ||
|             Db::rollback();
 | ||
|             return $this->json(5001, "Repository服务器错误");
 | ||
|         }catch (\Exception $e){
 | ||
|             Db::rollback();
 | ||
|             return $this->json(5002, "服务器错误");
 | ||
|         }
 | ||
| 
 | ||
| 
 | ||
|     }
 | ||
|     /**
 | ||
|      * 发布优惠券
 | ||
|      * */
 | ||
|     public function add()
 | ||
|     {
 | ||
|         $accountId = $this->request->user['user_id'] ?? 0;
 | ||
|         $account = AccountRepository::getInstance()->findById($accountId, [], function ($q) {
 | ||
|             return $q->with(['business'=>function($q){
 | ||
|                 $q->lock(true);
 | ||
|             }, 'parent']);
 | ||
|         });
 | ||
|         if(empty($account)){
 | ||
|             return  $this->json(6001,"登录失效");
 | ||
|         }
 | ||
|         if ($account->type == Account::type_consumer) {
 | ||
|             return $this->json(4001, "您不是商家");
 | ||
|         }
 | ||
| 
 | ||
|         if (!isset($account->business) || empty($account->business)) {
 | ||
|             return $this->json(4001, "商家信息错误");
 | ||
|         }
 | ||
|         if($account->business->enable != BusinessModel::COMMON_OFF){
 | ||
|             return $this->json(4001, "商家已禁用");
 | ||
|         }
 | ||
|         $data = input();
 | ||
| 
 | ||
|         Config::load("extra/distribution_proportion","distribution_proportion");
 | ||
|         $distributionProportion = config("distribution_proportion");
 | ||
| 
 | ||
|         $totalC = $distributionProportion['agency'] + $distributionProportion['admin'] + $distributionProportion['consumer'];
 | ||
|         if ($totalC != 100) {
 | ||
|             return $this->json(4002, "系统设置分配比例总和不等于100,不能发布");
 | ||
|         }
 | ||
| 
 | ||
|         //持有限量
 | ||
|         Config::load("extra/wechat","wechat");
 | ||
|         $hasCouponMax = config("wechat.hasCouponMax")??0;
 | ||
|         if ($hasCouponMax > 0) {
 | ||
|             $hasCouponCount = CouponRepository::getInstance()->getBusinessOnShelfOnCount($account->business->code);
 | ||
|             if ($hasCouponCount > $hasCouponMax) {
 | ||
|                 return $this->json(4001, "商家持有商家优惠券不能超过{$hasCouponMax}");
 | ||
|             }
 | ||
|         }
 | ||
| 
 | ||
|         //验证通过  不管是商家还是工作人员  都可以发布优惠券
 | ||
|         $couponMain = [
 | ||
|             "name"                  => $data['name'] ?? '',
 | ||
|             "business_code"         => $account->business->code,
 | ||
|             "money"                 => $data['money'] ?? 0,
 | ||
|             "type"                  => $data['type'] ?? 0,
 | ||
|             "count"                 => $data['count'] ?? 0,
 | ||
|             "type_name"             => $data['type_name'] ?? '',
 | ||
|             "start_time"            => $data['start_time'] ?? '',
 | ||
|             "end_time"              => $data['end_time'] ?? '',
 | ||
|             "deduction_money"       => $data['deduction_money'] ?? '',
 | ||
|             "image_url"             => $data['image_url'] ?? '',
 | ||
|             "intro"                 => $data['intro'] ?? '',
 | ||
|             "white_list"            => $data['white_list'] ?? '',
 | ||
|             "status"                => CouponMain::status_on,
 | ||
|             "on_shelf"              => CouponMain::on_shelf_off,//默认下架  后台审核上架
 | ||
|             "commission_agency"     => $distributionProportion['agency'],
 | ||
|             "commission_admin"      => $distributionProportion['admin'],
 | ||
|             "commission_consumer"   => $distributionProportion['consumer'],
 | ||
|         ];
 | ||
| 
 | ||
|         $usingRule = input("using_rule/a");
 | ||
| 
 | ||
|         $validate = new CouponRelease();
 | ||
| 
 | ||
|         //普通商家要验证扣除金额
 | ||
| 
 | ||
|         if (!$validate->scene($account->business["model"] == BusinessModel::model_ordinary ? "ordinary" : "")->check($couponMain)) {
 | ||
|             return $this->json(4001, $validate->getError());
 | ||
|         }
 | ||
| 
 | ||
|         $usingRuleValidate = new CouponUsingRule();
 | ||
|         if (!$usingRuleValidate->check($usingRule)) {
 | ||
|             return $this->json(4001, $usingRuleValidate->getError());
 | ||
|         }
 | ||
| 
 | ||
|         //验证通过
 | ||
|         $couponMain['business_type']            = $account->business['type'];
 | ||
|         $couponMain['business_name']            = $account->business['business_name'];
 | ||
|         $couponMain['lng']                      = $account->business['lng'];
 | ||
|         $couponMain['lat']                      = $account->business['lat'];
 | ||
|         $couponMain['business_circle_id']       = $account->business['business_circle_id'];
 | ||
|         $couponMain['create_time']              = date("Y-m-d H:i:s");
 | ||
| 
 | ||
|         //保留两位小数
 | ||
|         $couponMain['money'] = floor($couponMain['money'] * 100) / 100;
 | ||
|         $totalMoney = $couponMain['money'] * $couponMain['count'];
 | ||
| 
 | ||
|         //未领取的优惠券
 | ||
|         $NotClaimedMoney = CouponRepository::getInstance()->getBusinessNotClaimedCoupon($account->business["code"]);
 | ||
|         if($account->business["model"] == BusinessModel::model_ordinary) {
 | ||
|             if ($account->business["balance"] < ($totalMoney + $NotClaimedMoney)) {
 | ||
|                 return $this->json(4001, '商家余额不足');
 | ||
|             }
 | ||
|         }
 | ||
| 
 | ||
|         Db::startTrans();
 | ||
|         try {
 | ||
|             CouponRepository::getInstance()->releaseCouponMain($couponMain, $totalMoney, $usingRule);
 | ||
|             Db::commit();
 | ||
|             return $this->json();
 | ||
|         } catch (RepositoryException $e) {
 | ||
|             Db::rollback();
 | ||
|             return $this->json(5001, "发布失败" . $e->getMessage());
 | ||
|         } catch (\think\Exception $e) {
 | ||
|             Db::rollback();
 | ||
|             return $this->json(5002, "发布失败" . $e->getMessage());
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * 修改优惠券
 | ||
|      * */
 | ||
|     public function edit()
 | ||
|     {
 | ||
|         $accountId = $this->request->user['user_id'] ?? 0;
 | ||
|         $couponMainId = input("couponMainId/d");
 | ||
|         $account = AccountRepository::getInstance()->findById($accountId, [], function ($q) {
 | ||
|             return $q->with(['business'=>function($q){
 | ||
|                 $q->lock(true);
 | ||
|             }, 'parent']);
 | ||
|         });
 | ||
|         if(empty($account)){
 | ||
|             return  $this->json(6001,"登录失效");
 | ||
|         }
 | ||
|         if ($account->type == Account::type_consumer) {
 | ||
|             return $this->json(4001, "您不是商家");
 | ||
|         }
 | ||
| 
 | ||
|         if (!isset($account->business) || empty($account->business)) {
 | ||
|             return $this->json(4001, "商家信息错误");
 | ||
|         }
 | ||
| 
 | ||
|         $couponMain = CouponMain::findById($couponMainId,[],function ($q){
 | ||
|             return $q->with(["usingRule"]);
 | ||
|         });
 | ||
|         if (empty($couponMain)) {
 | ||
|             return $this->json(4001, "优惠券不存在");
 | ||
|         }
 | ||
|         if (!isset($couponMain->usingRule)||empty($couponMain->usingRule)) {
 | ||
|             return $this->json(4001, "优惠券信息错误");
 | ||
|         }
 | ||
|         $data = input();
 | ||
| 
 | ||
|         //验证通过  不管是商家还是工作人员  都可以修改优惠券  只能修改指定字段
 | ||
|         $couponMainData = [
 | ||
|             "name"                  => $data['name'] ?? '',
 | ||
|             "type"                  => $data['type'] ?? 0,
 | ||
|             "type_name"             => $data['type_name'] ?? '',
 | ||
|             "start_time"            => $data['start_time'] ?? '',
 | ||
|             "end_time"              => $data['end_time'] ?? '',
 | ||
|             "image_url"             => $data['image_url'] ?? '',
 | ||
|             "intro"                 => $data['intro'] ?? '',
 | ||
|             "white_list"            => $data['white_list'] ?? '',
 | ||
|         ];
 | ||
| 
 | ||
|         $usingRule = input("using_rule/a");
 | ||
| 
 | ||
|         $validate = new CouponRelease();
 | ||
|         if (!$validate->scene("api_edit")->check($couponMainData)) {
 | ||
|             return $this->json(4001, $validate->getError());
 | ||
|         }
 | ||
| 
 | ||
|         $usingRuleValidate = new CouponUsingRule();
 | ||
|         if (!$usingRuleValidate->check($usingRule)) {
 | ||
|             return $this->json(4001, $usingRuleValidate->getError());
 | ||
|         }
 | ||
| 
 | ||
| 
 | ||
|         //验证通过
 | ||
|         Db::startTrans();
 | ||
|         try {
 | ||
|             $couponMain->save($couponMainData);
 | ||
|             $couponMain->usingRule->save($usingRule);
 | ||
|             Db::commit();
 | ||
|             return $this->json();
 | ||
|         } catch (RepositoryException $e) {
 | ||
|             Db::rollback();
 | ||
|             return $this->json(5001, "修改失败失败" );
 | ||
|         } catch (\think\Exception $e) {
 | ||
|             Db::rollback();
 | ||
|             return $this->json(5002, "修改失败500" );
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * 商家管理优惠券
 | ||
|      * */
 | ||
|     public function getPageList()
 | ||
|     {
 | ||
|         $accountId = $this->request->user['user_id'] ?? 0;
 | ||
|         $account = AccountRepository::getInstance()->findById($accountId, [], function ($q) {
 | ||
|             return $q->with(['business', 'parent']);
 | ||
|         });
 | ||
|         if(empty($account)){
 | ||
|             return  $this->json(6001,"登录失效");
 | ||
|         }
 | ||
|         if ($account->type == Account::type_consumer) {
 | ||
|             return $this->json(4001, "您不是商家");
 | ||
|         }
 | ||
| 
 | ||
|         if (!isset($account->business) || empty($account->business)) {
 | ||
|             return $this->json(4001, "商家信息错误");
 | ||
|         }
 | ||
| 
 | ||
|         $page       = $this->request->param('page/d', 1);
 | ||
|         $size       = $this->request->param('rows/d', 10);
 | ||
|         $page       = $page < 1 ? 1 : $page;
 | ||
|         $size       = $size < 1 ? 10 : $size;
 | ||
|         $keyword    = $this->request->param('key/s',"");
 | ||
|         $businessCode    = $account->business_code;
 | ||
| 
 | ||
|         try {
 | ||
|             $whereMap   = [];
 | ||
|             $sortOrder  = ['sort' => 'desc'];
 | ||
|             $whereMap[] = ["business_code" ,"=", $businessCode ];
 | ||
|             if(!empty($keyword)){
 | ||
|                 $whereMap[] = ["name" ,"like", "%{$keyword}%" ];
 | ||
|             }
 | ||
|             $res    = CouponRepository::getInstance(new CouponMain())->findList($whereMap, [], $page, $size,function ($q){
 | ||
|                 return $q->with(["usingRule","couponType"]);
 | ||
|             }, $sortOrder);
 | ||
|             $time = time();
 | ||
|             $res['list'] ->each(function ($item) use($time){
 | ||
|                 //已使用张数
 | ||
|                 $item->usingCount = CouponRepository::getInstance()->getCouponMainUsingCount($item->id);
 | ||
|                 if($item->on_shelf === 0 && strtotime($item->start_time) <= $time && strtotime($item->end_time) >= $time){
 | ||
|                     $item->conduct   = true;
 | ||
|                 }else{
 | ||
|                     $item->conduct   = false;
 | ||
|                 }
 | ||
| 
 | ||
|             });
 | ||
| 
 | ||
|             return $this->json(0, 'success', $res["list"]);
 | ||
|         } catch (RepositoryException | \Exception $e) {
 | ||
|             echo $e->getMessage();
 | ||
|             return $this->json(5001, '优惠卷查询失败!');
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * 优惠券的领取  使用记录列表
 | ||
|      * */
 | ||
|     public function getShopCouponList()
 | ||
|     {
 | ||
|         $accountId = $this->request->user['user_id'] ?? 0;
 | ||
|         $account = AccountRepository::getInstance()->findById($accountId, [], function ($q) {
 | ||
|             return $q->with(['business', 'parent']);
 | ||
|         });
 | ||
|         if(empty($account)){
 | ||
|             return  $this->json(6001,"登录失效");
 | ||
|         }
 | ||
|         if ($account->type == Account::type_consumer) {
 | ||
|             return $this->json(4001, "您不是商家");
 | ||
|         }
 | ||
| 
 | ||
|         if (!isset($account->business) || empty($account->business)) {
 | ||
|             return $this->json(4001, "商家信息错误");
 | ||
|         }
 | ||
| 
 | ||
|         $couponMainId  = input("couponId/d");
 | ||
| 
 | ||
|         $couponMain = CouponMain::findById($couponMainId);
 | ||
| 
 | ||
|         if(empty($couponMain)){
 | ||
|             return $this->json(4001, "优惠券不存在");
 | ||
|         }
 | ||
|         if($couponMain->business_code != $account->business->code){
 | ||
|             return $this->json(4001, "优惠券参数信息错误");
 | ||
|         }
 | ||
| 
 | ||
|         $page       = $this->request->param('page/d', 1);
 | ||
|         $size       = $this->request->param('rows/d', 10);
 | ||
|         $type       = $this->request->param('type/s', 10);
 | ||
|         $page       = $page < 1 ? 1 : $page;
 | ||
|         $size       = $size < 1 ? 10 : $size;
 | ||
|         $sortOrder      = ["id"=>"desc"];
 | ||
|         $whereMap = [
 | ||
|             ["coupon_id","=",$couponMainId]
 | ||
|         ];
 | ||
|         switch ($type) {
 | ||
|             case 'all':
 | ||
|                 // 全部持有优惠券
 | ||
|                 $sortOrder  = [ 'end_time' => 'asc'];
 | ||
|                 break;
 | ||
|             case 'notUsed':
 | ||
|                 // 未使用(包含已过期)
 | ||
|                 $whereMap[] = ['is_verificated', '=', self::BOOL_FALSE];
 | ||
|                 $sortOrder  = ['end_time' => 'asc'];
 | ||
|                 break;
 | ||
|             case 'normal':
 | ||
|                 // 未使用且未过期
 | ||
|                 $whereMap[] = ['is_verificated', '=', self::BOOL_FALSE];
 | ||
|                 $whereMap[] = ['end_time', '< TIME', date('Y-m-d H:i:s')];
 | ||
|                 break;
 | ||
|             case 'used':
 | ||
|                 // 已使用
 | ||
|                 $whereMap[] = ['is_verificated', '=', self::BOOL_TRUE];
 | ||
|                 $sortOrder  = ['verificate_time' => 'desc'];
 | ||
|                 break;
 | ||
|         }
 | ||
|         $field = ["is_verificated","received_time","verificate_time","consumer_code"];
 | ||
|         $data  = CouponRepository::getInstance()->findList($whereMap,$field,$page,$size,function($q){
 | ||
|             return $q->withjoin(["account"=>function($q){
 | ||
|                 $q->field(["nick_name","avatar_url","gender","user_code"]);
 | ||
|             }]);
 | ||
|         },$sortOrder);
 | ||
| 
 | ||
|         //所有
 | ||
|         $data["allNum"]     = CouponRepository::getInstance()->getModel()->where(["coupon_id"=>$couponMainId])->count();
 | ||
|         //未使用
 | ||
|         $data["unUsedNum"]  = CouponRepository::getInstance()->getModel()->where(['is_verificated' => self::BOOL_FALSE,"coupon_id"=>$couponMainId])->count();
 | ||
|         //已使用
 | ||
|         $data["usedNum"]    = CouponRepository::getInstance()->getModel()->where(['is_verificated' => self::BOOL_TRUE ,"coupon_id"=>$couponMainId])->count();
 | ||
| 
 | ||
|         return $this->json(0,"success",$data);
 | ||
| 
 | ||
| 
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * 获取优惠券详情
 | ||
|      * */
 | ||
|     public function getCouponMainInfo()
 | ||
|     {
 | ||
|         $couponMainId = input("couponMainId/d");
 | ||
|         $couponMain = CouponMain::findById($couponMainId,[],function ($q){
 | ||
|             return $q->with(["usingRule","business"=>function($q){
 | ||
|                 $q->field("code,business_subtitle");
 | ||
|             }]);
 | ||
|         });
 | ||
|         if(empty($couponMain)){
 | ||
|             return $this->json(4001,"优惠券不存在");
 | ||
|         }
 | ||
| 
 | ||
|         return $this->json(0,"success",$couponMain->toArray());
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * 已使用优惠券 评分
 | ||
|      * */
 | ||
|     public function score()
 | ||
|     {
 | ||
|         $accountId      = $this->request->user['user_id'] ?? 0;
 | ||
|         $couponId       =  input("couponId/d",0);
 | ||
|         $score       =  input("score/d",5);
 | ||
| 
 | ||
|         if($score > 5|| $score <= 0){
 | ||
|             return $this->json(4001, "参数错误");
 | ||
|         }
 | ||
|         $account        = AccountRepository::getInstance()->findById($accountId, [], function ($q) {
 | ||
|             return $q->with(['business', 'parent']);
 | ||
|         });
 | ||
| 
 | ||
|         if(empty($account)){
 | ||
|             return $this->json(6001,"无效的用户");
 | ||
|         }
 | ||
| 
 | ||
|         $coupon = CouponRepository::getInstance()->findById($couponId,[],function ($q){
 | ||
|             return $q->with(["scoreModel"]);
 | ||
|         });
 | ||
| 
 | ||
|         if($coupon->consumer_code != $account->user_code ){
 | ||
|             return $this->json(4001, "参数错误");
 | ||
|         }
 | ||
| 
 | ||
|         if(isset($score->scoreModel) && $score->scoreModel){
 | ||
|             return $this->json(4001, "已经评论过了");
 | ||
|         }
 | ||
|         try {
 | ||
|             $coupon->scoreModel()->save([
 | ||
|                 "user_code"=>$account->user_code,
 | ||
|                 "business_code"=>$coupon->business_code,
 | ||
|                 "score"=>$score,
 | ||
|                 "coupon_id"=>$coupon->id,
 | ||
|                 "create_time"=>date("Y-m-d H:i:s"),
 | ||
|             ]);
 | ||
|             return $this->json();
 | ||
|         }catch (RepositoryException| \Exception $e){
 | ||
|             return $this->json(4001, "评分失败");
 | ||
|         }
 | ||
| 
 | ||
|     }
 | ||
| } |