'朋友圈', 1 => '门店', 0 => '公众号', 3 => '淘宝', ]; //用户来源分类 public static $userSource = [ 0 => ['name' => 'official', 'title' => '公众号'], 1 => ['name' => 'alipay', 'title' => '支付宝'], 2 => ['name' => 'mini', 'title' => '小程序'], 3 => ['name' => 'friend', 'title' => '朋友圈'], 4 => ['name' => 'meituan', 'title' => '美团'], 5 => ['name' => 'system', 'title' => '系统'], ]; //用户来源分类ID public static $userSourceId = [ 'official' => ['id' => 0, 'name' => 'official'], 'alipay' => ['id' => 1, 'name' => 'alipay'], 'mini' => ['id' => 2, 'name' => 'mini'], 'friend' => ['id' => 3, 'name' => 'friend'], 'meituan' => ['id' => 4, 'name' => 'meituan'], 'system' => ['id' => 5, 'name' => 'system'], ]; //组合客户基本和资产信息 public static function groupUserBaseInfo($list, $sensitive = true) { //取客户资产 $ids = array_column($list, 'id'); $ids = array_unique($ids); $asset = UserAssetClass::getByUserIds($ids, 'userId'); $merchantIdList = array_column($list, 'merchantId'); $merchantIdList = array_filter(array_unique($merchantIdList)); $merchantList = MerchantService::getByIds($merchantIdList, null, 'id'); foreach ($list as $key => $val) { $userId = $val['id']; //访问时间 $visitTime = date("m-d H:i", $val['visitTime']); if (date("m-d") == date("m-d", $val['visitTime'])) { $visitTime = '今天 ' . date("H:i", $val['visitTime']); } $list[$key]['visitTimeFormat'] = $visitTime; $list[$key]['userAsset'] = isset($asset[$userId]) ? $asset[$userId] : []; //客户发来新消息数 $list[$key]['unReadNum'] = ChatClass::getUnreadNum($userId); $list[$key] = business::formatUserAvatar($list[$key]); $merchantId = $val['merchantId']; $list[$key]['merchantName'] = isset($merchantList[$merchantId]['merchantName']) ? $merchantList[$merchantId]['merchantName'] : ''; //敏感信息不要输出 if ($sensitive) { unset($list[$key]['password']); unset($list[$key]['payPassword']); } } return $list; } //获取客户基本和资产信息 shish 2019.11.30 public static function getUserInfo($id, $sensitive = true) { $list = self::getByIds([$id]); $data = self::groupUserBaseInfo($list, $sensitive); return current($data); } //根据手机号查询客户 shish 2019.12.1 public static function getByMobile($mobile, $merchantId) { return self::getByCondition(['merchantId' => $merchantId, 'mobile' => $mobile]); } public static function generateUser($getUserInfo, $merchantId) { $date = date("Y-m-d H:i:s"); $time = time(); //替换掉微信名称不支持的图片 $userName = isset($getUserInfo['userName']) ? preg_replace('/[\x{10000}-\x{10FFFF}]/u', '', $getUserInfo['userName']) : ''; $getUserInfo['userName'] = $userName; $getUserInfo['nickName'] = $userName; $getUserInfo['realName'] = isset($getUserInfo['realName']) && !empty($getUserInfo['realName']) ? $getUserInfo['realName'] : ''; $getUserInfo['sex'] = isset($getUserInfo['sex']) ? $getUserInfo['sex'] : 0;//未知 $getUserInfo['identity'] = 0; $subscribe = isset($getUserInfo['subscribe']) ? $getUserInfo['subscribe'] : 0; $getUserInfo['subscribe'] = $subscribe; $getUserInfo['merchantId'] = $merchantId; $getUserInfo['status'] = 0; //默认没有完整用户信息 $isFull = isset($getUserInfo['headImgUrl']) && !empty($getUserInfo['headImgUrl']) ? 1 : 0; $getUserInfo['isFull'] = $isFull; $getUserInfo['createTime'] = $date; $getUserInfo['avatar'] = ''; $getUserInfo['password'] = ''; $getUserInfo['payPassword'] = ''; $getUserInfo['mobile'] = isset($getUserInfo['mobile']) ? $getUserInfo['mobile'] : ''; $getUserInfo['addTime'] = $time; $getUserInfo['visitTime'] = $time; $getUserInfo['source'] = isset($getUserInfo['source']) ? $getUserInfo['source'] : 0; $getUserInfo['hasSubscribe'] = 0; //生成用户基础信息 $user = self::add($getUserInfo); $userId = $user['id']; if (empty($user['userName'])) { self::updateById($userId, ['userName' => $userId, 'nickName' => $userId]); } $assetData = ['userId' => $userId, 'merchantId' => $merchantId, 'createTime' => $date]; //生成用户资产信息 UserAssetClass::add($assetData); //保存头像 if (isset($getUserInfo['headImgUrl']) && !empty($getUserInfo['headImgUrl'])) { if (empty($preUser) || (isset($preUser['avatar']) && empty($preUser['avatar']))) { $imgUrl = $getUserInfo['headImgUrl']; $currentImg = ImageService::generateAvatar($merchantId, $imgUrl); if (!empty($currentImg)) { self::updateById($userId, ['avatar' => $currentImg]); } } } //客户数粉丝数增加 MerchantAssetClass::addUser($merchantId, $subscribe, true); return $user; } public static function updateUser($originalUser, $getUserInfo, $merchantId) { $data = []; $assetData = []; $userId = $originalUser['id']; //替换掉微信不支持的图片 $userName = isset($getUserInfo['userName']) ? preg_replace('/[\x{10000}-\x{10FFFF}]/u', '', $getUserInfo['userName']) : ''; if (!empty($userName)) { $data['userName'] = $userName; $data['nickName'] = $userName; } if (isset($getUserInfo['openId']) && !empty($getUserInfo['openId'])) { $openId = $getUserInfo['openId']; $data['openId'] = $openId; } if (isset($getUserInfo['miniOpenId']) && !empty($getUserInfo['miniOpenId'])) { $data['miniOpenId'] = $getUserInfo['miniOpenId']; } if (isset($getUserInfo['unionId']) && !empty($getUserInfo['unionId'])) { $data['unionId'] = $getUserInfo['unionId']; } if (isset($getUserInfo['sex'])) { $data['sex'] = $getUserInfo['sex']; } if (isset($getUserInfo['subscribe'])) { $data['subscribe'] = $getUserInfo['subscribe']; } if (isset($getUserInfo['subscribeTime'])) { $data['subscribeTime'] = $getUserInfo['subscribeTime']; } $data['merchantId'] = $merchantId; if (isset($getUserInfo['alipayId']) && !empty($getUserInfo['alipayId'])) { $data['alipayId'] = $getUserInfo['alipayId']; } if (isset($getUserInfo['isFull'])) { $data['isFull'] = $getUserInfo['isFull']; } if (isset($getUserInfo['headImgUrl']) && !empty($getUserInfo['headImgUrl'])) { $data['isFull'] = 1; } //更新头像 if (isset($originalUser['avatar']) == false || empty($originalUser['avatar'])) { if (isset($getUserInfo['headImgUrl']) && !empty($getUserInfo['headImgUrl'])) { $imgUrl = $getUserInfo['headImgUrl']; $name = ImageService::generateAvatar($merchantId, $imgUrl); if (!empty($name)) { $data['avatar'] = $name; } } } //增加粉丝数 if (isset($originalUser['subscribe']) && $originalUser['subscribe'] == 0 && isset($getUserInfo['subscribe']) && $getUserInfo['subscribe'] == 1) { MerchantAssetClass::addUser($merchantId, 1, false); } self::updateById($userId, $data); if (!empty($assetData)) { UserAssetClass::updateByUserId($userId, $assetData); } $user = self::getById($userId); return $user; } public static function getByMiniOpenId($miniOpenId) { return self::getByCondition(['miniOpenId' => $miniOpenId]); } public static function getByAlipayId($alipayId, $merchantId) { return self::getByCondition(['merchantId' => $merchantId, 'alipayId' => $alipayId]); } public static function getByOpenId($openId, $merchantId) { return self::getByCondition(['merchantId' => $merchantId, 'openId' => $openId]); } public static function getByUnionId($unionId) { return self::getByCondition(['unionId' => $unionId]); } //合并用户 public static function mergeUser($delUser, $retainUser) { $connection = Yii::$app->db;//事务处理 $transaction = $connection->beginTransaction(); try { $delUserId = $delUser['id']; $retainUserId = $retainUser['id']; $userName = $retainUser['userName']; $merchantId = $retainUser['merchantId']; //合并记录 $return = UserMergeClass::add([ 'delUserId' => $delUserId, 'merchantId' => $merchantId, 'retainUserId' => $retainUserId, 'addTime' => time(), 'createTime' => date("Y-m-d H:i:s") ]); $targetId = $return['id']; $typeList = configDict::getConfig('capitalType'); $capitalType = $typeList['xhMergeUser']['id']; $now = time(); $date = date("Y-m-d H:i:s"); //数据迁移 $updateData = []; $updateKey = [ 'mobile', 'password', 'payPassword', 'subscribe', 'hasSubscribe', 'subscribeTime', 'alipayId', 'openId', 'miniOpenId', 'unionId', ]; foreach ($updateKey as $key) { if (isset($delUser[$key]) && !empty($delUser[$key])) { $updateData[$key] = $delUser[$key]; } } if (!empty($updateData)) { $updateData['visitTime'] = time(); self::updateById($retainUserId, $updateData); } //资产累加 $addData = []; $delUserAsset = UserAssetClass::getByUserId($delUserId); $retainUserAsset = UserAssetClass::getByUserId($retainUserId); if (!empty($delUserAsset)) { //累计消费 $delTotalExpend = isset($delUserAsset['totalExpend']) ? $delUserAsset['totalExpend'] : 0; if (!empty($delTotalExpend)) { $addData['totalExpend'] = $retainUserAsset['totalExpend'] + $delTotalExpend; //变化记录要增加 } //累计收入 $delTotalIncome = isset($delUserAsset['totalIncome']) ? $delUserAsset['totalIncome'] : 0; if (!empty($delTotalIncome)) { $addData['totalIncome'] = $retainUserAsset['totalIncome'] + $delTotalIncome; //变化记录要增加 } //累计充值 $delTotalRecharge = isset($delUserAsset['totalRecharge']) ? $delUserAsset['totalRecharge'] : 0; if (!empty($delTotalRecharge)) { $addData['totalRecharge'] = $retainUserAsset['totalRecharge'] + $delTotalRecharge; //变化记录要增加 } //累计购买数量 $delTotalBuyNum = isset($delUserAsset['totalBuyNum']) ? $delUserAsset['totalBuyNum'] : 0; if (!empty($delTotalBuyNum)) { $addData['totalBuyNum'] = $retainUserAsset['totalBuyNum'] + $delTotalBuyNum; //变化记录要增加 } //余额 $delBalance = isset($delUserAsset['balance']) ? $delUserAsset['balance'] : 0; if (!empty($delBalance)) { $addData['balance'] = $retainUserAsset['balance'] + $delBalance; //变化记录要增加 $userCapitalData = [ 'relateId' => $targetId, 'balance' => $addData['balance'], 'totalIncome' => $retainUserAsset['totalIncome'] + $delBalance, 'totalExpend' => $retainUserAsset['totalExpend'], 'amount' => $delBalance, 'io' => 1, 'payWay' => 0, 'event' => '帐号合并', 'merchantId' => $merchantId, 'userId' => $retainUserId, 'alipayId' => '', 'userName' => $userName, 'operateId' => 0, 'createTime' => $date, 'addTime' => $now, 'capitalType' => $capitalType, ]; xhUserCapitalService::add($userCapitalData);//用户资金流水增加 } //成长值 $delGrowth = isset($delUserAsset['growth']) ? $delUserAsset['growth'] : 0; if (!empty($delGrowth)) { $addData['growth'] = $retainUserAsset['growth'] + $delGrowth; //注意会员等级要进行重新计算!!!!!还有积分变化记录要增加 $growthData = [ 'userId' => $retainUserId, 'userName' => $userName, 'merchantId' => $merchantId, 'relateId' => $targetId, 'integral' => $addData['growth'], 'num' => $delGrowth, 'io' => 1, 'payWay' => 0, 'alipayId' => '', 'event' => '帐号合并', 'operatorId' => 0, 'createTime' => $date, 'capitalType' => $capitalType, 'addTime' => $now, ]; UserGrowthClass::add($growthData); //成长值增加升级 $preLevel = $retainUserAsset['member']; $preGrowth = $retainUserAsset['growth']; $merchantExtend = xhMerchantExtendService::getByMerchantId($merchantId); UserIntegralService::increaseToUpgrade($preGrowth, $addData['growth'], $preLevel, $retainUserId, $merchantId, $merchantExtend); } if (!empty($addData)) { UserAssetClass::updateByUserId($retainUserId, $addData); } } //删除用户 $clearData = ['openId' => '', 'miniOpenId' => '', 'unionId' => '', 'alipayId' => '', 'merchantId' => 0, 'mobile' => '']; self::updateById($delUserId, $clearData); UserAssetClass::updateByUserId($delUserId, ['merchantId' => 0]); //如果有支付宝信息则清除支付宝用户 UserAlipayClass::updateByUserId($delUserId, ['alipayId' => '', 'alipayAccount' => '', 'merchantId' => 0]); //合并帐号减少客户数 shish 2020.5.13 MerchantAssetClass::mergeToReduceUser($merchantId); $transaction->commit(); return self::getById($retainUserId); } catch (Exception $e) { $transaction->rollBack(); Yii::info("合并userid $delUserId $retainUserId 时事务回滚,原因:" . $e->getMessage()); return []; } } //找出相同unionId的用户 public static function getSameUnionId($unionId) { return self::getAllByCondition(['unionId' => $unionId], 'addTime desc', '*', 'id'); } public static function valid($info, $merchantId) { if (empty($info)) { util::fail('找不到客户'); } if ($info['merchantId'] != $merchantId) { util::fail('这个客户您没有权限操作'); } } //根据消费次数和有没领优惠券来判断是不是新人 public static function newUser($userInfo) { $asset = isset($userInfo['userAsset']) ? $userInfo['userAsset'] : []; $totalBuyNum = isset($asset['totalBuyNum']) ? $asset['totalBuyNum'] : 0; if ($totalBuyNum > 0) { return false; } $getCouponNum = isset($asset['getCouponNum']) ? $asset['getCouponNum'] : 0; if ($getCouponNum) { return false; } return true; } public static function getUserByIds($ids) { $info = self::getByIds($ids, null, 'id'); if (empty($info)) { return []; } $data = self::groupUserBaseInfo($info); return $data; } //将微信和小程序获取的用户信息转成可以保存的用户信息 public static function switchUserInfo($info, $source) { $openId = ''; if (isset($info['openid']) && !empty($info['openid'])) { $openId = $info['openid']; unset($info['openid']); } if (isset($info['openId']) && !empty($info['openId'])) { $openId = $info['openId']; unset($info['openId']); } if (!empty($openId)) { $userSource = self::$userSourceId; switch ($source) { case $userSource['mini']['name']: $info['miniOpenId'] = $openId; break; case $userSource['official']['name']: $info['openId'] = $openId; break; default: } } if (isset($info['miniOpenId'])) { $info['miniOpenId'] = $info['miniOpenId']; } if (isset($info['nickName'])) { $info['userName'] = $info['nickName']; $info['nickName'] = $info['nickName']; } if (isset($info['unionid'])) { $info['unionId'] = $info['unionid']; } if (isset($info['unionId'])) { $info['unionId'] = $info['unionId']; } if (isset($info['headimgurl'])) { $info['headImgUrl'] = $info['headimgurl']; } if (isset($info['avatarUrl'])) { $info['headImgUrl'] = $info['avatarUrl']; } if (isset($info['subscribe_time'])) { $info['subscribeTime'] = $info['subscribe_time']; } if (isset($info['subscribe'])) { $info['subscribe'] = $info['subscribe']; } return $info; } //创建以及更新用户 shish 2020.2.7 public static function replaceUser($userInfo, $source, $merchantId) { $userInfo = self::switchUserInfo($userInfo, $source); $unionId = isset($userInfo['unionId']) && !empty($userInfo['unionId']) ? $userInfo['unionId'] : ''; $unionUser = []; if (!empty($unionId)) { $unionUser = self::getByUnionId($unionId); } $userSource = self::$userSourceId; switch ($source) { case $userSource['mini']['name']: $sourceId = $userSource['mini']['id']; $miniOpenId = $userInfo['miniOpenId']; $user = self::getByMiniOpenId($miniOpenId); break; case $userSource['alipay']['name']: $sourceId = $userSource['alipay']['id']; $alipayId = $userInfo['alipayId']; $user = self::getByAlipayId($alipayId, $merchantId); break; case $userSource['official']['name']: $sourceId = $userSource['official']['id']; //后台添加的客户没有openId $openId = isset($userInfo['openId']) ? $userInfo['openId'] : ''; $user = []; if (!empty($openId)) { $user = self::getByOpenId($openId, $merchantId); } break; case $userSource['system']['name']: $sourceId = $userSource['system']['id']; $mobile = isset($userInfo['mobile']) && !empty($userInfo['mobile']) ? $userInfo['mobile'] : ''; $user = []; if (!empty($mobile)) { $user = self::getByCondition(['merchantId' => $merchantId, 'mobile' => $mobile]); } break; default: throw new \Exception('未知来源的用户'); } //支付宝暂时获取不到很多客户信息不进行更新 if ($source == $userSource['alipay']['name']) { if (!empty($user)) { return $user; } } if (empty($user)) { if (!empty($unionUser)) { //1、在小程序端已经授权用户信息和unionId之后,关注公众号时走这里 //2、关注了公众号或者H5已经授权时,并首次访问小程序 $user = self::updateUser($unionUser, $userInfo, $merchantId); } else { $userInfo['sourceType'] = $sourceId; $userInfo['merchantId'] = $merchantId; $user = self::generateUser($userInfo, $merchantId); } } else { if (!empty($unionUser)) { if (isset($unionUser['id']) && isset($user['id']) && $user['id'] != $unionUser['id']) { //合并相同客户 $user = self::mergeUser($unionUser, $user); } } $user = self::updateUser($user, $userInfo, $merchantId); } return $user; } //拉取粉丝 shish 2020.2.7 public static function syncWxUser($merchantId, $nextOpenId = '') { $merchant = MerchantClass::getMerchantById($merchantId); //一次拉取调用最多拉取10000个关注者的OpenID $result = wxUtil::getSubscribeUserList($merchant, $nextOpenId); $total = isset($result['total']) ? $result['total'] : 0; $next_openid = isset($result['next_openid']) ? $result['next_openid'] : ''; $count = isset($result['count']) ? $result['count'] : 0; $openIdList = isset($result['data']['openid']) ? $result['data']['openid'] : []; $currentTotal = count($openIdList); if ($count == 0 || $currentTotal == 0) { return ['total' => $total, 'count' => $count, 'nextOpenId' => $next_openid]; } $currentTotalPage = $currentTotal > 100 ? ceil($currentTotal / 100) : 1; $userSource = Yii::$app->dict->getValue('userSourceGetId', 'official'); $source = $userSource['name']; for ($m = 1; $m <= $currentTotalPage; $m++) { $offset = ($m - 1) * 100; $subIdList = array_slice($openIdList, $offset, 100); $info = wxUtil::batchGetUserInfo($merchant, $subIdList); if (empty($info) || isset($info['user_info_list']) == false || empty($info['user_info_list'])) { continue; } $user_info_list = $info['user_info_list']; foreach ($user_info_list as $val) { $val['isFull'] = 1; $val['unionId'] = $val['unionid']; $val['headImgUrl'] = $val['headimgurl']; $val['openId'] = $val['openid']; $val['nickName'] = $val['nickName']; $val['merchantId'] = $merchantId; self::replaceUser($val, $source, $merchantId); } } return ['total' => $total, 'count' => $count, 'nextOpenId' => $next_openid]; } }