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 = ['is_verificated'=>'asc','id' => '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" => function ($q) { $q->field("id,name,image_url,type_name"); }, "scoreModel", "business" => function ($q) { $q->field("code,id,business_name,business_subtitle"); } ]) ->where(function ($q){ $notUsedWhereMap = [];//未过期 未使用 $notUsedWhereMap[] = ['is_verificated', '=', self::BOOL_FALSE]; $notUsedWhereMap[] = ['end_time', '> TIME', date('Y-m-d H:i:s')]; $usedWhereMap = [];//已使用 7天内 $usedWhereMap[] = ['is_verificated', '=', self::BOOL_TRUE]; $usedWhereMap[] = ['verificate_time', '> TIME', date('Y-m-d H:i:s',time() - (7 * 86400)) ]; $beOverdueWhereMap = [];//未使用 已过期7天内 $beOverdueWhereMap[] = ['is_verificated', '=', self::BOOL_FALSE]; $beOverdueWhereMap[] = ['end_time', '> TIME', date('Y-m-d H:i:s',time() - (7 * 86400))];; $q->whereOr(function ($q)use($notUsedWhereMap){ $q->where($notUsedWhereMap); })//未使用未过期 ->whereOr(function ($q)use($usedWhereMap){ $q->where($usedWhereMap); })//已使用 7天内 ->whereOr(function ($q)use($usedWhereMap){ $q->where($usedWhereMap); });//已过期 }) //->fetchSql(true) ; }, $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 = ''; $status = CouponModel::status_success;//默认未使用 $endTime = strtotime($item->endTime); $ExpirationTime = abs(($endTime - $time) / 86400); if (($endTime > $time) ) { $expirationStr = "还有".ceil($ExpirationTime)."天过期"; } else { $status = CouponModel::status_be_overdue; $expirationStr = "已过期" . ceil($ExpirationTime) . "天"; } $item->expirationStr = $expirationStr; if($item->isVerificated == CouponModel::is_verificated_on){ $status = CouponModel::status_used; } $item->status = $status; //商家简称 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'] ?? ''; $time = time(); try { $whereMap = []; $fields = [ 'id', 'coupon_id', 'business_code', '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]; $whereMap[] = ['end_time', '> TIME', date("Y-m-d H:i:s")]; $sortOrder = ['sort_weight' => 'desc', 'end_time' => 'asc']; $res = CouponRepository::getInstance()->findList($whereMap, $fields, $page, $size,function ($q){ return $q->with( [ "couponMain" => function ($q) { $q->field("id,name,image_url,type_name"); }, "scoreModel", "business" => function ($q) { $q->field("id,code,business_name,business_subtitle"); } ]); }, $sortOrder); $res['list'] ->each(function ($item) use($time){ //重置过期时间 $item->endTimeText = date("Y-m-d",strtotime($item->endTime)); $status = CouponModel::status_success;//默认未使用 $endTime = strtotime($item->endTime); $ExpirationTime = abs(($endTime - $time) / 86400); if (($endTime > $time) ) { $expirationStr = "还有".ceil($ExpirationTime)."天过期"; } else { $status = CouponModel::status_be_overdue; $expirationStr = "已过期" . ceil($ExpirationTime) . "天"; } $item->expirationStr = $expirationStr; if($item->isVerificated == CouponModel::is_verificated_on){ $status = CouponModel::status_used; } $item->status = $status; //重置签到券名称 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() . ''; } }); $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); $distributionUserCode = input("distribution_user_code/s",''); $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 { //1写入领取记录 $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,//是否验证 ]; //如果商家指派了渠道商 分销人重新定义为空 if ($couponMain->business->is_assign == BusinessModel::COMMON_ON){ $data["is_distribution_coupon"] = couponMain::COMMON_OFF;//是否是分销签到券 $data["distribution_user_code"] = '';//分销人user_code }else{ $data["is_distribution_coupon"] = couponMain::COMMON_ON;//是否是分销签到券 $data["distribution_user_code"] = $distributionUserCode;//分销人user_code } $couponMain->save(["received_count"=>Db::raw("received_count + 1")]); $receiveCoupon = CouponRepository::getInstance()->receiveCoupon($data); 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); $userTimeStamp = input("userTimeStamp/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"])->lock(true); }); 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; $signTimeStamp = config('wechat.signTimeStamp') ?? 0; $msectime = msectime();//毫秒时间戳 //签到距离 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}"); } } //签到时间戳 if($signTimeStamp > 0 ){ if(abs($userTimeStamp - $msectime) > $signTimeStamp){ //.abs($userTimeStamp - $msectime) return $this->json(4001, "时间戳验证失败"); } } $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, "商家已禁用"); } $businessModel = $business["model"]; // 指定时间段内发布的签到券个数 $TimeListModeReleaseCount = BusinessRepository::getInstance() ->getTimeListModeReleaseCount($business["code"],$business["time_limit_start"],$business["time_limit_end"]); if ( $business["model"] == BusinessModel::model_ordinary || ( $business["model"] == BusinessModel::model_time_limit && ( strtotime($business["time_limit_end"]) < $time || $TimeListModeReleaseCount >= $business["time_limit_release_count"] ) ) ) { $businessModel = BusinessModel::model_ordinary; } if ($business['balance'] < $coupon->couponMain->deduction_money) { return $this->json(4001, "商家余额不足"); } $deductionMoney = $coupon->couponMain->deduction_money; $returnConsumerMoney = 0;//需要返回提示的金额 //未开启分销状态 $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); //四舍五入 精确到分 //开启分销状态 $disAdminMoney = (($deductionMoney/100) * $coupon->couponMain->commission_dis_admin); $disDistributionMoney = (($deductionMoney/100) * $coupon->couponMain->commission_dis_distribution); $disDistributedMoney = (($deductionMoney/100) * $coupon->couponMain->commission_dis_distributed); $disAgencyMoney = 0 ;//渠道商就没得钱 $disAdminMoney = round($disAdminMoney,2); //四舍五入 精确到分 $disDistributionMoney = round($disDistributionMoney,2); //四舍五入 精确到分 $disDistributedMoney = round($disDistributedMoney,2); //四舍五入 精确到分 $consumerRedpackUser = $account; $distributionRedpackUser = []; $agencyRedpackUser = []; //开启了分销 if( $business->is_assign == BusinessModel::COMMON_OFF || (!empty($coupon->distribution_user_code)&&$coupon->is_distribution_coupon == CouponMain::COMMON_ON) ){ $distributionRedpackUser = Account::findOne([["user_code","=",$coupon->distribution_user_code]]); //如果没有分销人 就全是平台 和分销人的 if(empty($distributionRedpackUser)){ $confirmAdminMoney = $disAdminMoney + $disDistributionMoney; $confirmDistributionMoney = 0; $confirmDistributedMoney = $disDistributedMoney; $confirmAgencyMoney = $disAgencyMoney; }else{//存在分销人 就走分销人 $confirmAdminMoney = $disAdminMoney; $confirmDistributionMoney = $disDistributionMoney; $confirmDistributedMoney = $disDistributedMoney; $confirmAgencyMoney = $disAgencyMoney; } }else{ $confirmAdminMoney = $adminMoney; $confirmDistributionMoney = 0; $confirmDistributedMoney = $consumerMoney; $confirmAgencyMoney = $agencyMoney; if(isset($business->agency) && $business->agency){ $agencyRedpackUser = Account::findOne([ ["business_code","=",$business->agency->code], ["type","=",Account::type_business], ]); } } //开始数据操作 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 ]); // $couponBill = CouponBill::getUserOne($account->user_code,$coupon->couponMain->id,$coupon->id); // if(empty($couponBill)){ //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, "commission_dis_admin" => $coupon->couponMain->commission_dis_admin, "commission_dis_distribution" => $coupon->couponMain->commission_dis_distribution, "commission_dis_distributed" => $coupon->couponMain->commission_dis_distributed, "money" => $coupon->couponMain->money, "agency_money" => $confirmAgencyMoney, "admin_money" => $confirmAdminMoney, "consumer_money" => $confirmDistributedMoney, "distribution_money" => $confirmDistributionMoney, "lat" => $lat, "lng" => $lng, "create_time" => date("Y-m-d H:i:s" ,$time), ]; $couponBill = CouponBill::create($couponBillData); // }else{ // $couponBillData = [ // "agency_money" => $agencyMoney, // "admin_money" => $adminMoney, // "consumer_money" => $consumerMoney, // "lat" => $lat, // "lng" => $lng, // ]; // $couponBill->save($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. 商家扣钱 所有模式商家都要扣钱 $businessSaveData = [ "balance" => Db::raw("balance - " . $deductionMoney,), ]; //是否要变更模式 if ($businessModel == BusinessModel::model_ordinary) { $businessSaveData["model"] = BusinessModel::model_ordinary; } $business->save($businessSaveData); $payment = WechatPay::getInstance(); //5. 渠道商加钱 【只要指派了渠道商 并且没有分销人 渠道商才能加钱 红包方式直接打款 成功失败不管】 //$business->agency->inc("balance",$agencyMoney)->update(); //修改成直接大款到关联的用户 if($confirmAgencyMoney > 0 && !empty($agencyRedpackUser)) { $agencyRedpack = Redpack::getDistributionRedpack( Redpack::userTypeAgency,$agencyRedpackUser->user_code,$coupon->id); //如果付款过一次了 就用同一个订单号发起 if(!empty($agencyRedpack)){ $mch_billno = $agencyRedpack->mch_billno; }else{ $mch_billno = createUuid(); } $agencyPayAmount = $confirmAgencyMoney * 100 ; $agencyToBalanceData = [ 'partner_trade_no' => $mch_billno,// 商户订单号,需保持唯一性(只能是字母或者数字,不能包含有符号) 'openid' => $agencyRedpackUser->open_id, 'check_name' => 'NO_CHECK',// NO_CHECK:不校验真实姓名, FORCE_CHECK:强校验真实姓名 'amount' => $agencyPayAmount , //单位为分,不小于300 'desc' => '用户核销签到券,渠道商奖励', ]; // 写入红包 $agencyRedpackData = [ "coupon_id" => $coupon->id, "mch_billno" => $mch_billno, "openid" => $agencyRedpackUser->open_id, "user_code" => $agencyRedpackUser->user_code, "money" => $agencyPayAmount, //单位为分,不小于300 "create_time" => date("Y-m-d H:i:s",$time), "pay_time" => '0000-00-00 00:00:00', "user_type" => Redpack::userTypeAgency, ]; //发起支付 $agencyResult = $payment->transfer->toBalance($agencyToBalanceData); //付款成功才提交!!!!!伪装成功 if( isset($agencyResult['payment_no']) ){ $agencyRedpackData['pay_time'] = date("Y-m-d H:i:s",$time); }else{ $agencyRedpackData['failure_reason'] = json_encode($agencyResult,JSON_UNESCAPED_UNICODE); //否则失败 记录失败原因 Log::info("企业发起付款【渠道商红包】失败:" . json_encode($agencyResult,JSON_UNESCAPED_UNICODE)); } // 不管成功还是失败 都要写入 if(empty($agencyRedpack)){ Redpack::create($agencyRedpackData); }else{ $agencyRedpack->save($agencyRedpackData); } } //6. 核销用户提现到零钱 写入红包记录 if($confirmDistributedMoney > 0 && !empty($consumerRedpackUser)){ $distributedRedpack = Redpack::getDistributionRedpack( Redpack::userTypeDistributed,$consumerRedpackUser->user_code,$coupon->id); //如果付款过一次了 就查询付款状态 if(!empty($distributedRedpack)){ $consumerMchBillno = $distributedRedpack->mch_billno; }else{ $consumerMchBillno = createUuid(); } $consumerAmount = $confirmDistributedMoney * 100; $consumerToBalanceData = [ 'partner_trade_no' => $consumerMchBillno,// 商户订单号,需保持唯一性(只能是字母或者数字,不能包含有符号) 'openid' => $consumerRedpackUser->open_id, 'check_name' => 'NO_CHECK',// NO_CHECK:不校验真实姓名, FORCE_CHECK:强校验真实姓名 'amount' => $consumerAmount, //单位为分,不小于300 'desc' => '验证签到券签到奖励', ]; // 写入红包 $consumerRedpackData = [ "coupon_id" => $coupon->id, "mch_billno" => $consumerMchBillno, "openid" => $consumerRedpackUser->open_id, "user_code" => $consumerRedpackUser->user_code, "money" => $consumerAmount, //单位为分,不小于300 "create_time" => date("Y-m-d H:i:s",$time), "pay_time" => '0000-00-00 00:00:00', ]; //发起支付 $consumerResult = $payment->transfer->toBalance($consumerToBalanceData); //付款成功才提交!!!!!伪装成功 if( isset($consumerResult['payment_no']) ){ $returnConsumerMoney = $confirmDistributedMoney; $consumerRedpackData['pay_time'] = date("Y-m-d H:i:s",$time); }else{ $consumerRedpackData['failure_reason'] = json_encode($consumerResult,JSON_UNESCAPED_UNICODE); //否则失败 记录失败原因 Log::info("企业发起付款【渠道商红包】失败:" . json_encode($consumerResult,JSON_UNESCAPED_UNICODE)); } if(empty($distributedRedpack)){ Redpack::create($consumerRedpackData); }else{ $distributedRedpack->save($consumerRedpackData); } } //7 分销者用户提现到零钱 写入红包记录 if($confirmDistributionMoney > 0 && !empty($distributionRedpackUser)){ $distributionRedpack = Redpack::getDistributionRedpack( Redpack::userTypeDistribution,$distributionRedpackUser->user_code,$coupon->id); //如果付款过一次了 就用同一个订单号发起 if(!empty($distributionRedpack)){ $distributionMchBillno = $distributionRedpack->mch_billno; }else{ $distributionMchBillno = createUuid(); } $distributionToBalanceData = [ 'partner_trade_no' => $distributionMchBillno,// 商户订单号,需保持唯一性(只能是字母或者数字,不能包含有符号) 'openid' => $distributionRedpackUser->open_id, 'check_name' => 'NO_CHECK',// NO_CHECK:不校验真实姓名, FORCE_CHECK:强校验真实姓名 'amount' => $confirmDistributionMoney * 100, //单位为分,不小于300 'desc' => '签到券分销奖励', ]; // 写入红包 $distributionRedpackData = [ "coupon_id" => 0, "mch_billno" => $distributionMchBillno, "openid" => $distributionRedpackUser->open_id, "user_code" => $distributionRedpackUser->user_code, "money" => $confirmDistributionMoney * 100, //单位为分,不小于300 "create_time" => date("Y-m-d H:i:s",$time), "pay_time" => '0000-00-00 00:00:00', "user_type" => Redpack::userTypeDistribution, ]; //发起支付 $distributionResult = $payment->transfer->toBalance($distributionToBalanceData); //var_dump($result); //付款成功才提交!!!!!伪装成功 if( isset($distributionResult['payment_no']) ){ $distributionRedpackData['pay_time'] = date("Y-m-d H:i:s",$time); if(empty($distributionRedpack)){ Redpack::create($distributionRedpackData); }else{ $distributionRedpack->save($distributionRedpackData); } }else{ $distributionRedpackData['failure_reason'] = json_encode($distributionResult,JSON_UNESCAPED_UNICODE); //否则失败 记录失败原因 Log::info("企业发起付款【领券分销者红包】失败:" . json_encode($distributionResult,JSON_UNESCAPED_UNICODE)); //默认回滚 Db::rollback(); //失败也要写入红包记录 if(empty($distributionRedpack)){ Redpack::create($distributionRedpackData); }else{ $distributionRedpack->save($distributionRedpackData); } return $this->json(5003, "领取失败"); } } Db::commit(); return $this->json( 0, "签到券签到使用成功,您获得{$returnConsumerMoney}元红包,已存入您的零钱", [ "redpack" =>$returnConsumerMoney, "user_coupon_id" =>$couponId, ]); }catch (RepositoryException $e){ Db::rollback(); return $this->json(5001, "Repository服务器错误"); }catch (\Exception $e){ Log::error('核销签到券失败:'.$e->getMessage()); 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(); $time = time(); Config::load("extra/distribution_proportion","distribution_proportion"); Config::load("extra/distribution_proportion_user","distribution_proportion_user"); $distributionProportion = config("distribution_proportion"); $distributionProportionUser = config("distribution_proportion_user"); $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'] ?? '', "content" => $data['content'] ?? '', "white_list" => $data['white_list'] ?? '', "status" => CouponMain::status_on, "on_shelf" => CouponMain::on_shelf_off,//默认下架 后台审核上架 "on_screen" => CouponMain::on_screen_yes, "is_distribution" => //根据是否指派了渠道商 判断是否开启分销 指派了渠道商就不能开启分销 ($account->business->is_assign == BusinessModel::COMMON_ON) ? CouponMain::COMMON_OFF : CouponMain::COMMON_ON, //下面是分配比例 "commission_agency" => $distributionProportion['agency'], "commission_admin" => $distributionProportion['admin'], "commission_consumer" => $distributionProportion['consumer'], "commission_dis_admin" => $distributionProportionUser['admin'], "commission_dis_distribution" => $distributionProportionUser['distribution'], "commission_dis_distributed" => $distributionProportionUser['distributed'], ]; //$usingRule = input("using_rule/a"); $businessModel = $account->business["model"]; // 指定时间段内发布的签到券个数 $TimeListModeReleaseCount = BusinessRepository::getInstance() ->getTimeListModeReleaseCount($account->business["code"],$account->business["time_limit_start"],$account->business["time_limit_end"]); if($account->business["model"] == BusinessModel::model_time_limit){ //如果到了时间 或者发布数量到达规定 更改商家模式 if( strtotime($account->business["time_limit_end"] ) < $time || (($TimeListModeReleaseCount ) >= $account->business["time_limit_release_count"]) ){ $businessModel = BusinessModel::model_ordinary; } } $validate = new CouponRelease(); //普通商家要验证扣除金额 if (!$validate->scene(($businessModel == 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()); //} //检查类型 if(CouponTypeModel::checkType($couponMain['type']) !== true){ return $this->json(4001, '签到券类型不存在'); } $type = CouponRepository::getInstance()->getCouponTypeAll(); $type = array_column($type->toArray(), null, "id"); $couponMain['type_name'] = $type[$couponMain['type']]['name']; //验证通过 $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['deduction_money'] = floor($couponMain['deduction_money'] * 100) / 100; $totalMoney = $couponMain['deduction_money'] * $couponMain['count']; //如果开启了分销 //if($couponMain['commission_dis_distributed'] < $couponMain['commission_dis_distribution']){ //检测 【核销分销者】部分是否最少0.3元 $distributedMoney = ($couponMain['commission_dis_distributed'] / 100) * $couponMain['deduction_money']; if ($distributedMoney != 0 && $distributedMoney < CouponMain::min_redpack_money) { return $this->json(4002, "扣除金额最低" . (CouponMain::min_redpack_money * (100 / ($couponMain['commission_dis_distributed']))) . "元"); } //}else{ //检测 【领券分销者】部分是否最少0.3元 $distributionMoney = ($couponMain['commission_dis_distribution'] / 100) * $couponMain['deduction_money']; if ($distributionMoney != 0 && $distributionMoney < CouponMain::min_redpack_money) { return $this->json(4002, "扣除金额最低" . (CouponMain::min_redpack_money * (100 / ($couponMain['commission_dis_distribution']))) . "元"); } //} //if($couponMain['commission_consumer'] < $couponMain['commission_agency']){ //检测 【消费者】部分是否最少0.3元 $consumerMoney = ($couponMain['commission_consumer']/100) * $couponMain['deduction_money']; if ($consumerMoney != 0 && $consumerMoney < CouponMain::min_redpack_money) { return $this->json(4002, "扣除金额最低" . (CouponMain::min_redpack_money * (100 / ($couponMain['commission_consumer']))) . "元"); } //}else{ //检测 【渠道商】部分是否最少0.3元 $agencyMoney = ($couponMain['commission_agency']/100) * $couponMain['deduction_money']; if ($agencyMoney != 0 && $agencyMoney < CouponMain::min_redpack_money) { return $this->json(4002, "扣除金额最低" . (CouponMain::min_redpack_money * (100 / ($couponMain['commission_agency']))) . "元"); } //} //未领取的签到券 $NotClaimedMoney = CouponRepository::getInstance()->getBusinessNotClaimedCoupon($account->business["code"]); // if( // $account->business["model"] == BusinessModel::model_ordinary // || // ( // $account->business["model"] == BusinessModel::model_time_limit // && // ( // (strtotime($account->business["time_limit_end"]) < $time) // || // ($TimeListModeReleaseCount >= $account->business["time_limit_release_count"]) // ) // ) // ) { // if ($account->business["balance"] < ($totalMoney + $NotClaimedMoney)) { // return $this->json(4001, '商家余额不足'); // } // } if ($account->business["balance"] < ($totalMoney + $NotClaimedMoney)) { return $this->json(4001, '商家余额不足'); } Db::startTrans(); try { //CouponRepository::getInstance()->releaseCouponMain($couponMain, $totalMoney, $usingRule); CouponRepository::getInstance()->releaseCouponMain($couponMain); if($account->business["model"] == BusinessModel::model_time_limit){ //如果到了时间 或者发布数量到达规定 更改商家模式 if( strtotime($account->business["time_limit_end"] ) < $time || (($TimeListModeReleaseCount + 1) >= $account->business["time_limit_release_count"]) ){ $account->business->save(["model"=>BusinessModel::model_ordinary]); } } 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,[]); 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'] ?? '', "content" => $data['content'] ?? '', "white_list" => $data['white_list'] ?? '', "on_screen" => $data['on_screen'] ?? 1, ]; //$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()); //} //检查类型 if(CouponTypeModel::checkType($couponMainData['type']) !== true){ return $this->json(4001, '签到券类型不存在'); } $type = CouponRepository::getInstance()->getCouponTypeAll(); $type = array_column($type->toArray(), null, "id"); $couponMainData['type_name'] = $type[$data['type']]['name']; //验证通过 Db::startTrans(); try { $couponMain->save($couponMainData); //$couponMain->usingRule->save($usingRule); CouponRepository::getInstance()->getModel()->where("coupon_id",$couponMain->id)->update(["end_time"=>$couponMainData["end_time"]." 00:00:00"]); 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(["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); } catch (RepositoryException | \Exception $e) { echo $e->getMessage(); return $this->json(5001, '优惠卷查询失败!'); } } /** * 签到券的领取 使用记录列表 * */ public function getShopCouponList() { $accountId = $this->request->user['user_id'] ?? 0; $keyword = input("key/s"); $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] ]; if(!empty($keyword)){ $whereMap[] = ["consumer_name", "like", "%{$keyword}%"]; } 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","consumer_name","id"]; $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(["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, "评分失败"); } } }