uid], ['stage_id', $ings['ing']], ])->whereNotNull('assoc_id')->exists(); $week4_18 = mktime(18, 0, 0, date('m'), date('d') - date('w') + 4, date('Y')); $week5_10 = mktime(10, 0, 0, date('m'), date('d') - date('w') + 5, date('Y')); if ( (time() < $week4_18 || time() > $week5_10) && $exists && (array_key_exists('sex', $data) || array_key_exists('sxo', $data) || array_key_exists('age', $data) || array_key_exists('address', $data) || array_key_exists('home', $data)) ) { throw new AlertException("72小时活动进行或预匹配期间,不允许修改敏感信息", 102); } } // 提交素材审核事件 $this->auditDiscribute($user, $data); // 是否修改了认证消息 if (!empty($user->identity_auth)) { $identitys = explode(',', $user->identity_auth); $ids = array_flip($identitys); foreach ($identitys as $identity) { if (array_key_exists($identity, $data)) { unset($ids[$identity]); } } $identitys = array_flip($ids); $user->identity_auth = implode(",", $identitys); } if (array_key_exists('weixin', $data) && $user->weixin != $data['weixin']) { $data['wx_auth'] = 0; } isset($data['photo_src']) && UserPhotoLogModel::create(['uid' => $user->uid, 'src' => $data['photo_src']]); isset($data['photo_1']) && UserPhotoLogModel::create(['uid' => $user->uid, 'src' => $data['photo_1']]); isset($data['photo_2']) && UserPhotoLogModel::create(['uid' => $user->uid, 'src' => $data['photo_2']]); isset($data['photo_3']) && UserPhotoLogModel::create(['uid' => $user->uid, 'src' => $data['photo_3']]); isset($data['photo_4']) && UserPhotoLogModel::create(['uid' => $user->uid, 'src' => $data['photo_4']]); $age = $data['age'] ?? $user->age ?? null; if ($age) { $data['star'] = Birthday::star(strtotime($age)); } $user->fill($data); // 更改定位后处理feed流池 if ((isset($data['lat']) && isset($data['lng']) && isset($data['location']))) { $rank1 = Redis::zrank("fpdx:user:locations:sell:girl", $user->uid); $rank2 = Redis::zrank("fpdx:user:locations:sell:boy", $user->uid); if ($rank1 || $rank2) { if ($user->sex == 1) { Redis::zrem("fpdx:user:locations:sell:girl", $user->uid); Redis::geoAdd("fpdx:user:locations:sell:boy", $user->lng, $user->lat, $user->uid); } elseif ($user->sex == 2) { Redis::zrem("fpdx:user:locations:sell:boy", $user->uid); Redis::geoAdd("fpdx:user:locations:sell:girl", $user->lng, $user->lat, $user->uid); } } } $user->save(); $syncFields = array( 'home', 'address', 'sex', 'photo_src', 'photo_1', 'photo_2', 'photo_3', 'photo_4', 'voice', 'school', 'subject', 'grade', 'height', 'age', 'star', 'introduce', 'expect', 'qq', 'weixin', 'education', ); if (isset($syncFields['sex'])) { dispatch_now(new UserInfoReportJob([ [ 'loginUserId' => $user->uid, 'gender' => $syncFields['sex'] == 1 ? '男性' : ($syncFields['sex'] == 2 ? '女性' : '未知'), ], ])); } // 同步更新卡片 if ( isset($user->partner_id) && $user->partner_id > 0 && !empty(array_intersect( array_keys($data), $syncFields )) ) { $ps = new PartnerService(); $ps->updatePartner($user->partner_id, $data); } } /** * 提交素材审核事件 * @param $user * @param $data * @throws AlertException */ private function auditDiscribute($user, $data) { // 昵称 if (array_key_exists('nickname', $data) && $data['nickname']) { event(new AuditMedia($user->uid, 'text', $data['nickname'], 'nickname', "uid={$user->uid}")); } // 头像 if (array_key_exists('headimgurl', $data) && $data['headimgurl']) { event(new AuditMedia($user->uid, 'image', $data['headimgurl'], 'headimgurl', "uid={$user->uid}")); } // 个性签名 if (array_key_exists('introduce', $data) && $data['introduce']) { event(new AuditMedia($user->uid, 'text', $data['introduce'], 'introduce', "uid={$user->uid}")); } } public function toggleTag(int $uid, $tag_id, $group) { $user = UserModel::findOrFail($uid, ['tag_1', 'tag_2', 'tag_3', 'tag_4']); $taged = explode(',', $user->{"tag_{$group}"}); if (in_array($tag_id, $taged)) { $key = array_search($tag_id, $taged); array_splice($taged, $key, 1); $is_add = false; } else { array_push($taged, $tag_id); $is_add = true; } UserModel::where('uid', $uid)->update(["tag_{$group}" => ltrim(trim(implode(',', $taged)), ',')]); $tagModel = new TagModel(); $tagModel->flushTagByUser($uid, compact('group', 'tag_id'), $is_add); } /** * 删除照片 * @param int $uid * @param string $pField * @return bool * @throws \Exception */ public function deletePhoto(int $uid, string $pField) { $fields = ['photo_src', 'photo_1', 'photo_2', 'photo_3', 'photo_4']; $checks = array( 'photo_src' => 'check_photo', 'photo_1' => 'photo_1_check', 'photo_2' => 'photo_2_check', 'photo_3' => 'photo_3_check', 'photo_4' => 'photo_4_check', ); $user = UserModel::findOrFail($uid); $identitys = array_flip(explode(',', $user->identity_auth)); $partner = PartnerModel::find($user->partner_id); $photos = array( 'photo_src' => [ 'field' => 'photo_src', 'src' => $user->photo_src, 'check' => $partner->check_photo ?? -1, 'identity_auth' => isset($identitys['photo_src']) ? true : false, ], 'photo_1' => [ 'field' => 'photo_1', 'src' => $user->photo_1, 'check' => $partner->photo_1_check ?? -1, 'identity_auth' => isset($identitys['photo_1']) ? true : false, ], 'photo_2' => [ 'field' => 'photo_2', 'src' => $user->photo_2, 'check' => $partner->photo_2_check ?? -1, 'identity_auth' => isset($identitys['photo_2']) ? true : false, ], 'photo_3' => [ 'field' => 'photo_3', 'src' => $user->photo_3, 'check' => $partner->photo_3_check ?? -1, 'identity_auth' => isset($identitys['photo_3']) ? true : false, ], 'photo_4' => [ 'field' => 'photo_4', 'src' => $user->photo_4, 'check' => $partner->photo_4_check ?? -1, 'identity_auth' => isset($identitys['photo_4']) ? true : false, ], ); unset($photos[$pField]); $u_save = $p_save = $u_identity = array(); foreach ($fields as $field) { $photo = array_shift($photos); if (is_null($photo)) { $u_save[$field] = null; $p_save[$field] = null; $p_save[$checks[$field]] = -1; } else { $u_save[$field] = $photo['src']; $p_save[$field] = $photo['src']; $p_save[$checks[$field]] = $photo['check']; if ($photo['identity_auth']) { array_push($u_identity, $field); } } } $u_save['identity_auth'] = implode(",", $u_identity); DB::beginTransaction(); try { $user->fill($u_save); $partner->fill($p_save); // 修正上架状态 if ( 1 == $partner->is_sell && (empty($partner->qq) && empty($partner->weixin)) || !(1 == $partner->check_photo || 1 == $partner->photo_1_check || 1 == $partner->photo_2_check || 1 == $partner->photo_3_check || 1 == $partner->photo_4_check || 1 == $partner->voice_check) ) { $partner->is_sell = 0; Redis::zrem("fpdx:user:locations:sell:boy", $partner->uid); Redis::zrem("fpdx:user:locations:sell:girl", $partner->uid); } // 修正审核状态 if ( 1 == $partner->is_commit_check && 0 != $partner->check_photo && 0 != $partner->photo_1_check && 0 != $partner->photo_2_check && 0 != $partner->photo_3_check && 0 != $partner->photo_4_check && 0 != $partner->voice_check ) { $partner->is_commit_check = 0; } $user->save(); $partner->save(); AppearanceUserJob::dispatch($user->uid)->onQueue('{appearance:user}'); DB::commit(); return true; } catch (\Exception $exception) { DB::rollBack(); throw $exception; } } /** * 活体身份认证 * @param int $uid 用户信息 * @param string $face_url 用于活体检测的图片 * @param string $photo_field 用于对比的图片字段 * @return bool * @throws AlertException */ public function fatchmatch(int $uid, string $face_url, string $photo_field) { $checks = array( 'photo_src' => 'check_photo', 'photo_1' => 'photo_1_check', 'photo_2' => 'photo_2_check', 'photo_3' => 'photo_3_check', 'photo_4' => 'photo_4_check', ); $user = UserModel::findOrFail($uid); $isfield = true; if (in_array($photo_field, ['photo_src', 'photo_1', 'photo_2', 'photo_3', 'photo_4'])) { if (empty($user->{$photo_field})) { throw new AlertException("没有找到可对比的图片", 101); } else { $match_photo = "https://oss.pocketuniversity.cn" . $user->{$photo_field}; } } else { $isfield = false; $match_photo = $photo_field; } $fs = new FaceService(); $images = array( [ 'image' => $face_url, 'image_type' => 'URL', 'face_type' => 'LIVE', 'quality_control' => 'NONE', 'liveness_control' => 'LOW', ], [ 'image' => $match_photo, 'image_type' => 'URL', 'face_type' => 'LIVE', 'quality_control' => 'NONE', 'liveness_control' => 'NONE', ], ); $data = $fs->match($images); $fmm = new FaceMatchModel(); $md = $fmm->fill([ 'uid' => $user->uid, 'check_img' => $match_photo, 'match_img' => $face_url, ]); if ($data['error_code'] == 0) { $md->score = $data['result']['score'] ?? 0; $md->save(); if ($data['result']['score'] > 69) { if ($isfield) { if (empty($user->identity_auth)) { $user->identity_auth = $photo_field; } else { $identity = explode(',', $user->identity_auth); array_push($identity, $photo_field); $user->identity_auth = implode(",", array_unique($identity)); } $user->save(); $ns = new NoticeService(); if ($user->partner_id > 0) { $ps = new PartnerService(); $ps->check($user->partner_id, $checks[$photo_field], 1); } if ($user->wx_auth == 1) { $ns->authenticationSuccess($user->uid); } } return true; } else { throw new AlertException("与上传照片相似度低", 101); } } else { if ($isfield && $data['error_code'] == 222204) { FaceVerifyJob::dispatch($uid, $face_url, $user->{$photo_field}, 0)->delay(Carbon::now()->addMinutes(1)); throw new AlertException("图片加载失败,已加入审核队列", 102); } $md->score = 0; $md->save(); throw new AlertException("请确保光线充足,没有翻拍照片", 101); } } /** * 微信认证 * @param int $uid * @param string $wxid * @param string $wxkf * @return array * @throws \Exception */ public function wxverify(int $uid, string $wxid, string $wxkf): array { $user = UserModel::findOrFail($uid); $before_auth = 0; $after_auth = 0; if ($user->identity_auth && $user->wx_auth == 1) { $before_auth = 1; } if ($user->wx_auth == 1) { return array( "code" => 200, "message" => "验证成功", ); } $userinfo = UserInfoModel::where('wxid', $wxid)->first(); if (collect($userinfo)->isEmpty()) { app('sentry')->captureMessage("微信客服验证异常日志:%s", array("无法验证的微信号"), array( 'level' => 'info', 'extra' => array( '用户' => $uid, '微信id' => $wxid, '服务微信客服' => $wxkf, ), 'tags' => array( 'uid' => $uid, ), )); $kfmsg = array( 'task_type' => 1, 'task_dict' => array( 'wxid_to' => $wxid, 'at_list' => "", 'msg_list' => array( [ 'msg_type' => 1, 'msg' => "很抱歉,认证失败。\n\n可能原因:\n\n小遇出错了,暂时没有能够检测到您设置的微信号。\n\n请确保您已设置微信号后,👇点击下方链接提醒小象导帮您人工审核。", ], [ 'msg_type' => 1, 'msg' => "点击链接提醒小遇人工审核\nhttps://m.fenpeiduixiang.com/fpdx-wxauth/artifical.html?wxid={$wxid}&kf={$wxkf}", ], ), ), ); Redis::sadd("wehub:task:list:{$wxkf}", [json_encode($kfmsg)]); return array( "code" => 101, "message" => "已提交验证,请耐心等待", ); } DB::beginTransaction(); try { // 无微信号且wxid为默认值 if (empty($userinfo->wx_alias) && preg_match("/^wxid_/", $userinfo->wxid)) { $kfmsg = array( 'task_type' => 1, 'task_dict' => array( 'wxid_to' => $wxid, 'at_list' => "", 'msg_list' => array( [ 'msg_type' => 1, 'msg' => "你还没有设置微信号哦,请在微信客户端设置微信号【点此链接参阅设置方法:https://jingyan.baidu.com/article/a948d6512dd2d50a2dcd2e8a.html】后,向我回复“认证”再试。\n\n若多次尝试失败,可向我回复\"人工认证\",辅助认证。", ], ), ), ); Redis::sadd("wehub:task:list:{$wxkf}", [json_encode($kfmsg)]); return array( "code" => 101, "message" => "已提交验证,请耐心等待", ); } // 无微信号且wxid不为默认值 if (empty($userinfo->wx_alias) && !preg_match("/^wxid_/", $userinfo->wxid)) { $wx_alias = $userinfo->wxid; } elseif (empty($userinfo->wx_alias)) { $kfmsg = array( 'task_type' => 1, 'task_dict' => array( 'wxid_to' => $wxid, 'at_list' => "", 'msg_list' => array( array( 'msg_type' => 1, 'msg' => "很抱歉,认证失败。\n\n可能原因:\n\n小遇出错了,暂时没有能够检测到您设置的微信号。\n\n请确保您已设置微信号后,👇点击下方链接提醒小象导帮您人工审核", ), [ 'msg_type' => 1, 'msg' => "点击链接提醒小遇人工审核\nhttps://m.fenpeiduixiang.com/fpdx-wxauth/artifical.html?wxid={$wxid}&kf={$wxkf}", ], ), ), ); Redis::sadd("wehub:task:list:{$wxkf}", [json_encode($kfmsg)]); return array( "code" => 101, "message" => "已提交验证,请耐心等待", ); } else { $wx_alias = $userinfo->wx_alias; } $user->wx_auth = 1; $user->weixin = $wx_alias; $user->save(); if ($user->partner_id > 0) { $ps = new PartnerService(); $ps->updatePartner($user->partner_id, ['weixin' => $wx_alias]); } DB::commit(); (new NoticeService())->partnerCheckLog($user->uid, $user->partner_id, 'weixin', 1, 1); if ($user->identity_auth && $user->wx_auth == 1) { $after_auth = 1; } $kfmsg = array( 'task_type' => 1, 'task_dict' => array( 'wxid_to' => $wxid, 'at_list' => "", 'msg_list' => array( [ 'msg_type' => 1, 'msg' => "恭喜你已完成微信认证,现在你可以回到小程序向喜欢的ta发起“心动邀请”啦。补全信息会帮助认识彼此,同时将获得更高的曝光度。\n\n小遇祝你早日脱单哦!加油~\n\n👇👇👇👇👇", ], [ 'msg_type' => 3, 'msg' => "https://oss.pocketuniversity.cn/media/2019-01-09/5c35d017d6771.png", ], ), ), ); Redis::sadd("wehub:task:list:{$wxkf}", [json_encode($kfmsg)]); // 发送认证通知 try { if ($before_auth == 0 && $after_auth == 1) { (new NoticeService())->authenticationSuccess($user->uid); } } catch (\Exception $e) { app('sentry')->captureException($e); } return array( "code" => 200, "message" => "验证成功", ); } catch (\Exception $exception) { app('sentry')->captureException($exception); $kfmsg = array( 'task_type' => 1, 'task_dict' => array( 'wxid_to' => $wxid, 'at_list' => "", 'msg_list' => array( [ 'msg_type' => 1, 'msg' => "很抱歉,认证失败。\n\n可能原因:\n①您未设置微信号,请在微信客户端【我-微信号】设置。\n②小遇出错了,暂时没有能够检测到您设置的微信号。\n\n请确保您已设置微信号后,👇点击下方链接提醒小象导帮您人工审核", ], [ 'msg_type' => 1, 'msg' => "点击链接提醒小遇人工审核:\nhttps://m.fenpeiduixiang.com/fpdx-wxauth/artifical.html?uid={$user->uid}&wxid={$wxid}&kf={$wxkf}", ], ), ), ); Redis::sadd("wehub:task:list:{$wxkf}", [json_encode($kfmsg)]); return array( "code" => 101, "message" => "已提交验证,请耐心等待", ); } } /** * 申请人工认证微信提醒 * @param array $content * @param string $url * @throws \Exception */ public function wxverifyWarn(array $content, string $url) { $admins = array( 10002 => "oCyEB1S75zmwncQpLI8ljxq-4oPg", 103143 => "oCyEB1ebnmeW_OUXZuaGq6-Hb-5Y", ); $public_id = "gh_43ba50c16fba"; $access_token = TokenModel::getToken($public_id); $apiurl = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token={$access_token}"; foreach ($admins as $admin) { $data = [ 'touser' => $admin, 'template_id' => 'DhPjGWXQZqKd4ic9hSTccOOSm3AGHiYjM1ppb7td8Wo', 'url' => $url, 'data' => $content, ]; \Curl::to($apiurl)->withData($data)->asJson()->post(); } } /** * 成为vip * @param int $uid * @param bool $bevip 是否成为vip * @param bool $isAllNotice * @return bool */ public function beVip(int $uid, $bevip = true, $isAllNotice = false) { $ns = new \App\Services\User\NoticeService(); /** @var UserModel $user */ $user = UserModel::findOrFail($uid); $platform = \Config::get('platform'); if ($user->be_vip_at > 0 && $bevip === true) { if ($isAllNotice) { $ns->bevip($user->uid); } return true; } if ($bevip) { $user->be_vip_at = time(); VipLogModel::openVip($uid); try { $ns->bevip($user->uid); dispatch_now(new UserVipReportJob($user, true, $platform)); } catch (\Exception $exception) { } } else { $auth = AuthKey::where([['auth_type', 'kdgx_unionid'], ['uid', $uid]])->first(); if ( $auth && !Openid::where([['unionid', $auth->auth_key], ['subscribe', 1]])->whereIn( 'public_id', ['gh_c94c95866ca5', 'gh_b598cb7474d8'] )->exists() ) { $user->be_vip_at = 0; VipLogModel::closeVip($uid); try { $ns->outvip($user->uid); dispatch_now(new UserVipReportJob($user, false, $platform)); } catch (\Exception $exception) { SentryFacade::captureMessage($exception); } } else { return false; } } $user->save(); return false; } }