public void UpdateMember(MemberEntity member, AddMemberArgs args)
        {
            if (member == null || args == null)
            {
                Debug.Assert(false, "UpdateMember member== null || args == null");
                return;
            }

            member.NickName      = args.WeixinUser.Nickname;
            member.Sex           = args.WeixinUser.Sex;
            member.City          = args.WeixinUser.City;
            member.Country       = args.WeixinUser.Country;
            member.Province      = args.WeixinUser.Province;
            member.Language      = args.WeixinUser.Language;
            member.Headimgurl    = args.WeixinUser.Headimgurl;
            member.SubscribeTime = args.WeixinUser.SubscribeTime;
            member.Remark        = args.WeixinUser.Remark;
            member.GroupId       = args.WeixinUser.GroupId;
            member.TagList       = args.WeixinUser.GetTagListString();
            member.Attention     = true;
            member.SyncFlag      = args.SyncFlag;

            if (args.ScenicQRCodeId.HasValue)
            {
                member.ScenicQRCodeId = args.ScenicQRCodeId;
            }

            if (args.RefereeMemberId.HasValue)
            {
                member.RefereeMemberId = args.RefereeMemberId;
            }

            _dataBase.Update(member);
        }
Example #2
0
        public void Execute(IJobExecutionContext context)
        {
            List <MemberEntity> needUpdateMemberList = _memberManager.GetNeedUpdateList();

            if (needUpdateMemberList == null || needUpdateMemberList.Count == 0)
            {
                return;
            }

            _log.Write("更新会员信息", String.Format("取得待更新会员数:{0}", needUpdateMemberList.Count), TraceEventType.Verbose);

            foreach (MemberEntity member in needUpdateMemberList)
            {
                DomainContext domainContext = _domainPool.GetDomainContext(member.Domain);

                if (domainContext == null)
                {
                    _memberManager.NeedUpdate(member.Id, false);
                    _log.Write("更新会员信息失败", "没有Domain信息\r\n" + JsonHelper.Serializer(member), TraceEventType.Warning);
                    continue;
                }

                RequestApiResult <WeixinUser> getUserInfoResult =
                    UserApiWrapper.GetUserInfo(domainContext, member.OpenId);

                if (getUserInfoResult.Success == false)
                {
                    _log.Write("更新会员信息失败", JsonHelper.Serializer(getUserInfoResult), TraceEventType.Warning);
                    continue;
                }

                if (getUserInfoResult.ApiResult.Subscribe == 0)
                {
                    _memberManager.NeedUpdate(member.Id, false);
                    continue;
                }

                AddMemberArgs args = new AddMemberArgs();
                args.WeixinUser = getUserInfoResult.ApiResult;
                //更新当前用户信息
                _memberManager.UpdateMember(member, args);

                _memberManager.NeedUpdate(member.Id, false);
            }

            _log.Write("更新会员信息", "更新完毕。", TraceEventType.Verbose);
        }
        public MemberEntity AddMember(DomainContext domainContext, AddMemberArgs args)
        {
            if (args == null)
            {
                Debug.Assert(false, "AddMember args == null");
                return(null);
            }

            MemberEntity member = new MemberEntity();

            member.Domain          = domainContext.Domain.Id;
            member.AppId           = domainContext.AppId;
            member.OpenId          = args.WeixinUser.OpenId;
            member.NickName        = args.WeixinUser.Nickname;
            member.Sex             = args.WeixinUser.Sex;
            member.City            = args.WeixinUser.City;
            member.Country         = args.WeixinUser.Country;
            member.Province        = args.WeixinUser.Province;
            member.Language        = args.WeixinUser.Language;
            member.Headimgurl      = args.WeixinUser.Headimgurl;
            member.SubscribeTime   = args.WeixinUser.SubscribeTime;
            member.Remark          = args.WeixinUser.Remark;
            member.GroupId         = args.WeixinUser.GroupId;
            member.TagList         = args.WeixinUser.GetTagListString();
            member.ScenicQRCodeId  = args.ScenicQRCodeId;
            member.RefereeMemberId = args.RefereeMemberId;
            member.Attention       = true;
            member.Point           = domainContext.InitialMemberPoint;
            member.CardNumber      = GetMemberCardNumber(domainContext.Domain.Id, domainContext.AppId);
            member.SyncFlag        = args.SyncFlag;

            //TODO:初始积分要写记录表

            _dataBase.Insert(member);

            return(member);
        }
Example #4
0
        private void SyncUserList(string next_openid)
        {
            RequestApiResult <WeixinGetUserListResult> getUserListResult =
                UserApiWrapper.GetUserList(this, next_openid);

            if (getUserListResult.Success == false)
            {
                EndSyncUserList("用户列表同步失败:" + getUserListResult.Message);
                return;
            }

            if (getUserListResult.ApiResult.Count == 0)
            {
                //将取消了关注的用户剔出来
                _memberManager.UpdateUnsubscribeMemberList(this.Domain.Id, this.AppId, _syncFlag);

                EndSyncUserList("用户列表同步成功。");
                return;
            }

            foreach (string openId in getUserListResult.ApiResult.Data.OpenIdList)
            {
                RequestApiResult <WeixinUser> getUserInfoResult = UserApiWrapper.GetUserInfo(this, openId);
                if (getUserInfoResult.Success == false)
                {
                    _logService.Write("用户列表同步失败", getUserInfoResult.Message, TraceEventType.Error);

                    EndSyncUserList("用户列表同步失败:" + getUserInfoResult.Message);
                    return;
                }

                //值为0时,代表此用户没有关注该公众号,拉取不到其余信息。
                if (getUserInfoResult.ApiResult.Subscribe == 0)
                {
                    continue;
                }

                //根据OpenId获取用户信息
                MemberEntity  member = _memberManager.GetMemberByOpenId(this.Domain.Id, this.AppId, openId);
                AddMemberArgs args   = new AddMemberArgs();
                args.WeixinUser = getUserInfoResult.ApiResult;
                args.SyncFlag   = _syncFlag;

                if (member == null)
                {
                    //添加新用户
                    member = _memberManager.AddMember(this, args);
                }
                else
                {
                    //更新当前用户信息
                    _memberManager.UpdateMember(member, args);
                }
            }

            //事实上微信接口永远会返回 NextOpenId,哪怕数据只有几条不需要分次获取
            if (String.IsNullOrEmpty(getUserListResult.ApiResult.NextOpenId) == false)
            {
                SyncUserList(getUserListResult.ApiResult.NextOpenId);
            }
        }
Example #5
0
        protected override string Handle(ReceivingXMLMessage_SubscribeEventMessage message, ClientDomainContext domainContext)
        {
            //用户管理-获取用户基本信息
            //未认证订阅号 未认证服务号 没有此权限

            RequestApiResult <WeixinUser> getUserInfoResult =
                UserApiWrapper.GetUserInfo(domainContext, message.FromUserName);

            if (getUserInfoResult.Success == false)
            {
                return(String.Empty);
            }

            if (getUserInfoResult.ApiResult.Subscribe == 0)
            {
                return(String.Empty);
            }

            #region 判断是否是扫描带参数二维码事件

            //扫描带参数二维码事件
            string strScenicQRCodeId = String.Empty;
            if (String.IsNullOrEmpty(message.EventKey) == false)
            {
                //用户未关注时,进行关注后的事件推送
                if (message.EventKey.StartsWith("qrscene_"))
                {
                    strScenicQRCodeId = message.EventKey.Remove(0, "qrscene_".Length);
                }
            }

            //获取场景二维码Id
            Guid?scenicQRCodeId = null;
            ScenicQRCodeLandingLogEntity scenicQRCodeLandingLog = null;
            if (String.IsNullOrEmpty(strScenicQRCodeId) == false)
            {
                Guid scenicQRCodeId2;
                if (Guid.TryParse(strScenicQRCodeId, out scenicQRCodeId2))
                {
                    scenicQRCodeId = scenicQRCodeId2;

                    scenicQRCodeLandingLog               = new ScenicQRCodeLandingLogEntity();
                    scenicQRCodeLandingLog.Domain        = domainContext.Domain.Id;
                    scenicQRCodeLandingLog.QRCodeId      = scenicQRCodeId.Value;
                    scenicQRCodeLandingLog.VisitorOpenId = message.FromUserName;
                    scenicQRCodeLandingLog.LandingTime   = DateTime.Now;
                }
            }

            #endregion

            #region 判断是否是通过RecomendUrl引流关注的

            Guid?refereeMemberId = null;
            //如果有场景二维码ID就不用判断RecomendUrl了
            if (String.IsNullOrEmpty(strScenicQRCodeId))
            {
                RecommendUrlLogEntity recomendUrlLog = _recommendUrlManager.GetLogByOpenId(getUserInfoResult.ApiResult.OpenId);
                if (recomendUrlLog != null)
                {
                    refereeMemberId = recomendUrlLog.UrlOwnMember;
                }
            }

            #endregion

            //根据OpenId获取用户信息
            MemberEntity member = _memberManager.GetMemberByOpenId(domainContext.Domain.Id, domainContext.AppId, getUserInfoResult.ApiResult.OpenId);

            AddMemberArgs args = new AddMemberArgs();
            args.WeixinUser      = getUserInfoResult.ApiResult;
            args.ScenicQRCodeId  = scenicQRCodeId;
            args.RefereeMemberId = refereeMemberId;

            if (member == null)
            {
                //添加新用户
                member = _memberManager.AddMember(domainContext, args);

                //更新场景二维码计数
                if (scenicQRCodeId.HasValue)
                {
                    _scenicQRCodeManager.IncrementAttentionPerson(scenicQRCodeId.Value, scenicQRCodeLandingLog);
                }

                //如果通过RecomendUrl引流关注的,奖励积分
                if (refereeMemberId.HasValue && domainContext.RecommendUrlSettings != null &&
                    domainContext.RecommendUrlSettings.AttentionPoint > 0)
                {
                    PointTrackArgs pointTrackArgs = new PointTrackArgs();
                    pointTrackArgs.DomainId = domainContext.Domain.Id;
                    pointTrackArgs.MemberId = refereeMemberId.Value;
                    pointTrackArgs.Quantity = domainContext.RecommendUrlSettings.AttentionPoint;
                    pointTrackArgs.Type     = MemberPointTrackType.RecommendUrl;
                    pointTrackArgs.TagName  = member.NickName;
                    pointTrackArgs.TagId    = member.Id;
                    _memberManager.PointTrack(pointTrackArgs);
                }

                //判断是否有二级上线,对其奖励积分
                if (refereeMemberId.HasValue && domainContext.RecommendUrlSettings != null &&
                    domainContext.RecommendUrlSettings.Level2AttentionPoint > 0)
                {
                    RefereeUplineWrapper refereeUplineWrapper =
                        _recommendUrlManager.GetRefereeUplineList(domainContext.Domain.Id, domainContext.AppId, refereeMemberId.Value);
                    if (refereeUplineWrapper.Upline != null)
                    {
                        PointTrackArgs pointTrackArgs = new PointTrackArgs();
                        pointTrackArgs.DomainId = domainContext.Domain.Id;
                        pointTrackArgs.MemberId = refereeUplineWrapper.Upline.MemberId;
                        pointTrackArgs.Quantity = domainContext.RecommendUrlSettings.Level2AttentionPoint;
                        pointTrackArgs.Type     = MemberPointTrackType.RecommendUrl;
                        pointTrackArgs.TagName  = member.NickName;
                        pointTrackArgs.TagId    = member.Id;
                        _memberManager.PointTrack(pointTrackArgs);
                    }
                }
            }
            else
            {
                //更新当前用户信息
                _memberManager.UpdateMember(member, args);

                //更新场景二维码计数
                if (scenicQRCodeId.HasValue)
                {
                    _scenicQRCodeManager.IncrementLanding(scenicQRCodeId.Value, scenicQRCodeLandingLog);
                }
            }

            #region 关注时的自动回复

            if (domainContext.AutoReplyOnSubscribe != null &&
                String.IsNullOrEmpty(domainContext.AutoReplyOnSubscribe.Content) == false)
            {
                ResponsiveXMLMessageBase replyMessage =
                    AutoReplyHelper.GetXMLMessage(domainContext, message.FromUserName, domainContext.AutoReplyOnSubscribe);

                if (replyMessage != null)
                {
                    return(XMLMessageHelper.XmlSerialize(replyMessage));
                }
                else
                {
                    return(String.Empty);
                }
            }
            else
            {
                return(String.Empty);
            }

            #endregion
        }
        /// <summary>
        ///微信网页授权回调
        ///如果用户同意授权,页面将跳转至 redirect_uri/?code=CODE&state=STATE。
        ///若用户禁止授权,则重定向后不会带上code参数,仅会带上state参数redirect_uri?state=STATE
        ///http://mp.weixin.qq.com/wiki/9/01f711493b5a02f24b04365ac5d8fd95.html
        /// </summary>
        /// <returns></returns>
        public ActionResult OAuthCallback()
        {
            _log.Write("微信网页授权接口发起回调", HttpContext.Request.Url.ToString(), TraceEventType.Verbose);

            string code  = HttpContext.Request.QueryString["code"];
            string state = HttpContext.Request.QueryString["state"];

            //第为第三方平台运营时,会返回 appId
            string appId = HttpContext.Request.QueryString["appid"];

            //完成网页鉴权后要转回的页面地址
            string redirectUrl = null;

            if (String.IsNullOrEmpty(state) == false)
            {
                redirectUrl = _cachingService.Get(state);
            }
            else
            {
                _log.Write("微信网页授权接口发起回调",
                           "没有指定完成网页鉴权后要转回的页面地址: state" + HttpContext.Request.Url.ToString(),
                           TraceEventType.Warning);
                return(new HttpStatusCodeResult(404));
            }

            string domainId = HttpContext.Request.QueryString["domainId"];

            if (String.IsNullOrEmpty(domainId))
            {
                _log.Write("微信网页授权接口发起回调", "没有指定 domainId ", TraceEventType.Warning);
                return(new HttpStatusCodeResult(404));
            }

            DomainContext domainContext = _domainPool.GetDomainContext(Guid.Parse(domainId));

            if (domainContext == null)
            {
                _log.Write("微信网页授权接口发起回调", "指定的 domainId 不存在", TraceEventType.Warning);
                return(new HttpStatusCodeResult(404));
            }

            if (domainContext.Authorizer == null)
            {
                //重定向到错误页面
                return(new RedirectResult(String.Format(
                                              "~/Home/ErrorView/{0}?message={1}", domainContext.Domain.Id, "td5")));
            }

            //只有微信认证服务号具备此权限
            //用户管理-网页授权获取用户openid/用户基本信息
            if (domainContext.Authorizer.AuthorizationType != EnumAuthorizationType.AuthorizedService)
            {
                //重定向到错误页面
                return(new RedirectResult(String.Format(
                                              "~/Home/ErrorView/{0}?message={1}", domainContext.Domain.Id, "td4")));
            }

            if (String.IsNullOrEmpty(code))
            {
                //重定向到错误页面
                return(new RedirectResult(String.Format(
                                              "~/Home/ErrorView/{0}?message={1}", domainContext.Domain.Id, "td1")));
            }

            /*
             * 此处偶发 40029 错误,不合法的oauth_code
             * 40029-invalid code, hints: [ req_id: Ft6quA0644ns67 ]
             * https://segmentfault.com/q/1010000002739502?foxhandler=RssReadRenderProcessHandler
             * http://mp.weixin.qq.com/qa/11/3c20059cc944d6edf4a1124c2fd09253.html
             * redirect_uri后面加个随机数没用
             * 通过尝试发起两次请求的方式解决
             */
            //通过code换取网页access_token
            RequestApiResult <WeixinWebAccessTokenResult> getWebAccessToken =
                TokenApi.GetThirdPartyWebAccessToken(domainContext.AppId, code, _configuration.ThirdParty.AppId,
                                                     ThirdPartyAccessTokenGetter.Get());

            if (getWebAccessToken.Success == false)
            {
                //再来一次,防止死循环,只重试一次,在URL后面加个参数以标记
                if (redirectUrl.Contains("RetryGetWebAccessToken"))
                {
                    _log.Write("请求网页AccessToken失败。", getWebAccessToken.Message, TraceEventType.Warning);
                    //重定向到错误页面
                    return(new RedirectResult(String.Format(
                                                  "~/Home/ErrorView/{0}?message={1}", domainContext.Domain.Id, "td2")));
                }
                else
                {
                    if (redirectUrl.IndexOf('?') >= 0)
                    {
                        redirectUrl += "&RetryGetWebAccessToken=1";
                    }
                    else
                    {
                        redirectUrl += "?RetryGetWebAccessToken=1";
                    }

                    return(new RedirectResult(redirectUrl));
                }
            }

            //将OpenId保存到Session
            SessionContainer.SetOpenId(HttpContext, getWebAccessToken.ApiResult.OpenId);

            //先判断本地数据库中是否已经有了此用户信息
            MemberContext memberContext = null;
            MemberEntity  member        = _memberManager.GetMemberByOpenId(domainContext.Domain.Id, domainContext.AppId, getWebAccessToken.ApiResult.OpenId);

            if (member != null)
            {
                if (member.Attention)
                {
                    //为提高鉴权性能,此处不更新用户信息,只作标记,用windows服务后台更新
                    _memberManager.NeedUpdate(member.Id, true);

                    memberContext = new MemberContext(member);
                    SessionContainer.SetMemberContext(HttpContext, memberContext);

                    //转回初始业务页面
                    return(new RedirectResult(redirectUrl));
                }
                else
                {
                    //如果用户已经取消关注,此处就不需要再调用微信的 GetUserInfo 接口了
                    //直接判断能不能匿名浏览即可
                    return(RedirectUrlOnlyOpenId(redirectUrl, domainId));
                }
            }

            //在本地没有用户信息的情况下,调用weixinApi去取
            //此处拿到OpenId了,接下来判断该用户是否是已关注用户
            RequestApiResult <WeixinUser> getUserInfoResult =
                UserApiWrapper.GetUserInfo(domainContext, getWebAccessToken.ApiResult.OpenId);

            if (getUserInfoResult.Success == false)
            {
                //重定向到错误页面
                return(new RedirectResult(String.Format(
                                              "~/Home/ErrorView/{0}?message={1}", domainContext.Domain.Id, "td3")));
            }

            //值为0时,代表此用户没有关注该公众号,拉取不到其余信息。
            //跳转到引导关注页面
            if (getUserInfoResult.ApiResult.Subscribe == 0)
            {
                //用户取消关注有消息推送
                //在那时设置member中是否在关注为false

                return(RedirectUrlOnlyOpenId(redirectUrl, domainId));
            }
            else
            {
                //根据OpenId获取用户信息
                //添加新用户
                AddMemberArgs args = new AddMemberArgs();
                args.WeixinUser = getUserInfoResult.ApiResult;
                member          = _memberManager.AddMember(domainContext, args);

                memberContext = new MemberContext(member);
                SessionContainer.SetMemberContext(HttpContext, memberContext);

                //转回初始业务页面
                return(new RedirectResult(redirectUrl));
            }
        }