ASP.NET MVC5+EF6+EasyUI 后台管理系统(75)-微信公众平台开发-用户管理
系列目录
前言
本节主要是关注者(即用户)和用户组的管理,微信公众号提供了用户和用户组的管理,我们可以在微信公众号官方里面进行操作,添加备注和标签,以及移动用户组别,同时,微信公众号也提供了相应的接口另我们本地可以操作.我们主要是同步到本地,这样我们可以自己为用户定义更多的信息,以及与本地的业务更好的对接起来.
实现
一、关注与订阅事件
看到我们之前的消息处理类 我们需要扩展一个事件类,这个类与之前消息处理类是一样的分部类,同样来自Senpars微信的SDK
/*----------------------------------------------------------------
Copyright (C) 2016 Senparc 文件名:CustomMessageHandler_Events.cs
文件功能描述:自定义MessageHandler 创建标识:Senparc - 20150312
----------------------------------------------------------------*/ using System;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using Senparc.Weixin.MP.Agent;
using Senparc.Weixin.Context;
using Senparc.Weixin.MP.Entities;
using Senparc.Weixin.MP.Helpers;
using Senparc.Weixin.MP.MessageHandlers;
using Senparc.Weixin.MP;
using Apps.WC.DAL;
using Apps.WC.IDAL;
using System.Collections.Generic;
using Apps.Models;
using Apps.WC.IBLL;
using Apps.WC.BLL;
using Apps.Models.WC;
using Apps.Models.Enum;
using Apps.Common;
using Senparc.Weixin.MP.AdvancedAPIs;
using Senparc.Weixin.MP.AdvancedAPIs.User; namespace Apps.Web.Areas.WC.Core
{
/// <summary>
/// 自定义MessageHandler
/// </summary>
public partial class CustomMessageHandler
{
public override IResponseMessageBase OnTextOrEventRequest(RequestMessageText requestMessage)
{
// 预处理文字或事件类型请求。
// 这个请求是一个比较特殊的请求,通常用于统一处理来自文字或菜单按钮的同一个执行逻辑,
// 会在执行OnTextRequest或OnEventRequest之前触发,具有以下一些特征:
// 1、如果返回null,则继续执行OnTextRequest或OnEventRequest
// 2、如果返回不为null,则终止执行OnTextRequest或OnEventRequest,返回最终ResponseMessage
// 3、如果是事件,则会将RequestMessageEvent自动转为RequestMessageText类型,其中RequestMessageText.Content就是RequestMessageEvent.EventKey if (requestMessage.Content == "OneClick")
{
var strongResponseMessage = CreateResponseMessage<ResponseMessageText>();
strongResponseMessage.Content = "您点击了底部按钮。\r\n为了测试微信软件换行bug的应对措施,这里做了一个——\r\n换行";
return strongResponseMessage;
}
return null;//返回null,则继续执行OnTextRequest或OnEventRequest
} public override IResponseMessageBase OnEvent_ClickRequest(RequestMessageEvent_Click requestMessage)
{
IResponseMessageBase reponseMessage = null;
////菜单点击,需要跟创建菜单时的Key匹配
//switch (requestMessage.EventKey)
//{
// case "OneClick":
// {
// //这个过程实际已经在OnTextOrEventRequest中完成,这里不会执行到。
// var strongResponseMessage = CreateResponseMessage<ResponseMessageText>();
// reponseMessage = strongResponseMessage;
// strongResponseMessage.Content = "您点击了底部按钮。\r\n为了测试微信软件换行bug的应对措施,这里做了一个——\r\n换行";
// }
// break;
// case "SubClickRoot_Text":
// {
// var strongResponseMessage = CreateResponseMessage<ResponseMessageText>();
// reponseMessage = strongResponseMessage;
// strongResponseMessage.Content = "您点击了子菜单按钮。";
// }
// break;
// case "SubClickRoot_News":
// {
// var strongResponseMessage = CreateResponseMessage<ResponseMessageNews>();
// reponseMessage = strongResponseMessage;
// strongResponseMessage.Articles.Add(new Article()
// {
// Title = "您点击了子菜单图文按钮",
// Description = "您点击了子菜单图文按钮,这是一条图文信息。",
// PicUrl = "http://sdk.weixin.senparc.com/Images/qrcode.jpg",
// Url = "http://sdk.weixin.senparc.com"
// });
// }
// break;
// case "SubClickRoot_Music":
// {
// //上传缩略图
// var accessToken = Senparc.Weixin.MP.Containers.AccessTokenContainer.TryGetAccessToken(appId, appSecret);
// var uploadResult = Senparc.Weixin.MP.AdvancedAPIs.MediaApi.UploadTemporaryMedia(accessToken, UploadMediaFileType.thumb,
// Server.GetMapPath("~/Images/Logo.jpg"));
// //设置音乐信息
// var strongResponseMessage = CreateResponseMessage<ResponseMessageMusic>();
// reponseMessage = strongResponseMessage;
// strongResponseMessage.Music.Title = "天籁之音";
// strongResponseMessage.Music.Description = "真的是天籁之音";
// strongResponseMessage.Music.MusicUrl = "http://sdk.weixin.senparc.com/Content/music1.mp3";
// strongResponseMessage.Music.HQMusicUrl = "http://sdk.weixin.senparc.com/Content/music1.mp3";
// strongResponseMessage.Music.ThumbMediaId = uploadResult.thumb_media_id;
// }
// break;
// case "SubClickRoot_Image":
// {
// //上传图片
// var accessToken = Senparc.Weixin.MP.Containers.AccessTokenContainer.TryGetAccessToken(appId, appSecret);
// var uploadResult = Senparc.Weixin.MP.AdvancedAPIs.MediaApi.UploadTemporaryMedia(accessToken, UploadMediaFileType.image,
// Server.GetMapPath("~/Images/Logo.jpg"));
// //设置图片信息
// var strongResponseMessage = CreateResponseMessage<ResponseMessageImage>();
// reponseMessage = strongResponseMessage;
// strongResponseMessage.Image.MediaId = uploadResult.media_id;
// }
// break;
// case "SubClickRoot_Agent"://代理消息
// {
// //获取返回的XML
// DateTime dt1 = DateTime.Now;
// reponseMessage = MessageAgent.RequestResponseMessage(this, agentUrl, agentToken, RequestDocument.ToString());
// //上面的方法也可以使用扩展方法:this.RequestResponseMessage(this,agentUrl, agentToken, RequestDocument.ToString()); // DateTime dt2 = DateTime.Now; // if (reponseMessage is ResponseMessageNews)
// {
// (reponseMessage as ResponseMessageNews)
// .Articles[0]
// .Description += string.Format("\r\n\r\n代理过程总耗时:{0}毫秒", (dt2 - dt1).Milliseconds);
// }
// }
// break;
// case "Member"://托管代理会员信息
// {
// //原始方法为:MessageAgent.RequestXml(this,agentUrl, agentToken, RequestDocument.ToString());//获取返回的XML
// reponseMessage = this.RequestResponseMessage(agentUrl, agentToken, RequestDocument.ToString());
// }
// break;
// case "OAuth"://OAuth授权测试
// {
// var strongResponseMessage = CreateResponseMessage<ResponseMessageNews>();
// strongResponseMessage.Articles.Add(new Article()
// {
// Title = "OAuth2.0测试",
// Description = "点击【查看全文】进入授权页面。\r\n注意:此页面仅供测试(是专门的一个临时测试账号的授权,并非Senparc.Weixin.MP SDK官方账号,所以如果授权后出现错误页面数正常情况),测试号随时可能过期。请将此DEMO部署到您自己的服务器上,并使用自己的appid和secret。",
// Url = "http://sdk.weixin.senparc.com/oauth2",
// PicUrl = "http://sdk.weixin.senparc.com/Images/qrcode.jpg"
// });
// reponseMessage = strongResponseMessage;
// }
// break;
// case "Description":
// {
// var strongResponseMessage = CreateResponseMessage<ResponseMessageText>();
// strongResponseMessage.Content = "GetWelcomeInfo";
// reponseMessage = strongResponseMessage;
// }
// break;
// case "SubClickRoot_PicPhotoOrAlbum":
// {
// var strongResponseMessage = CreateResponseMessage<ResponseMessageText>();
// reponseMessage = strongResponseMessage;
// strongResponseMessage.Content = "您点击了【微信拍照】按钮。系统将会弹出拍照或者相册发图。";
// }
// break;
// case "SubClickRoot_ScancodePush":
// {
// var strongResponseMessage = CreateResponseMessage<ResponseMessageText>();
// reponseMessage = strongResponseMessage;
// strongResponseMessage.Content = "您点击了【微信扫码】按钮。";
// }
// break;
// case "ConditionalMenu_Male":
// {
// var strongResponseMessage = CreateResponseMessage<ResponseMessageText>();
// reponseMessage = strongResponseMessage;
// strongResponseMessage.Content = "您点击了个性化菜单按钮,您的微信性别设置为:男。";
// }
// break;
// case "ConditionalMenu_Femle":
// {
// var strongResponseMessage = CreateResponseMessage<ResponseMessageText>();
// reponseMessage = strongResponseMessage;
// strongResponseMessage.Content = "您点击了个性化菜单按钮,您的微信性别设置为:女。";
// }
// break;
// default:
// {
// var strongResponseMessage = CreateResponseMessage<ResponseMessageText>();
// strongResponseMessage.Content = "您点击了按钮,EventKey:" + requestMessage.EventKey;
// reponseMessage = strongResponseMessage;
// }
// break;
//} return reponseMessage;
} public override IResponseMessageBase OnEvent_EnterRequest(RequestMessageEvent_Enter requestMessage)
{
var responseMessage = ResponseMessageBase.CreateFromRequestMessage<ResponseMessageText>(requestMessage);
responseMessage.Content = "您刚才发送了ENTER事件请求。";
return responseMessage;
} public override IResponseMessageBase OnEvent_LocationRequest(RequestMessageEvent_Location requestMessage)
{
//这里是微信客户端(通过微信服务器)自动发送过来的位置信息
var responseMessage = CreateResponseMessage<ResponseMessageText>();
responseMessage.Content = "这里写什么都无所谓,比如:上帝爱你!";
return responseMessage;//这里也可以返回null(需要注意写日志时候null的问题)
} public override IResponseMessageBase OnEvent_ScanRequest(RequestMessageEvent_Scan requestMessage)
{
//通过扫描关注
var responseMessage = CreateResponseMessage<ResponseMessageText>(); responseMessage.Content = responseMessage.Content ?? string.Format("通过扫描二维码进入,场景值:{0}", requestMessage.EventKey); return responseMessage;
} public override IResponseMessageBase OnEvent_ViewRequest(RequestMessageEvent_View requestMessage)
{
//说明:这条消息只作为接收,下面的responseMessage到达不了客户端,类似OnEvent_UnsubscribeRequest
var responseMessage = CreateResponseMessage<ResponseMessageText>();
responseMessage.Content = "您点击了view按钮,将打开网页:" + requestMessage.EventKey;
return responseMessage;
} public override IResponseMessageBase OnEvent_MassSendJobFinishRequest(RequestMessageEvent_MassSendJobFinish requestMessage)
{
var responseMessage = CreateResponseMessage<ResponseMessageText>();
responseMessage.Content = "接收到了群发完成的信息。";
return responseMessage;
} /// <summary>
/// 订阅(关注)事件
/// </summary>
/// <returns></returns>
public override IResponseMessageBase OnEvent_SubscribeRequest(RequestMessageEvent_Subscribe requestMessage)
{
var responseMessage = base.CreateResponseMessage<ResponseMessageText>();
responseMessage.Content = "欢迎关注";
return responseMessage;
} /// <summary>
/// 退订
/// 实际上用户无法收到非订阅账号的消息,所以这里可以随便写。
/// unsubscribe事件的意义在于及时删除网站应用中已经记录的OpenID绑定,消除冗余数据。并且关注用户流失的情况。
/// </summary>
/// <returns></returns>
public override IResponseMessageBase OnEvent_UnsubscribeRequest(RequestMessageEvent_Unsubscribe requestMessage)
{
var responseMessage = base.CreateResponseMessage<ResponseMessageText>();
responseMessage.Content = "有空再来";
return responseMessage;
} /// <summary>
/// 事件之扫码推事件(scancode_push)
/// </summary>
/// <param name="requestMessage"></param>
/// <returns></returns>
public override IResponseMessageBase OnEvent_ScancodePushRequest(RequestMessageEvent_Scancode_Push requestMessage)
{
var responseMessage = base.CreateResponseMessage<ResponseMessageText>();
responseMessage.Content = "事件之扫码推事件";
return responseMessage;
} /// <summary>
/// 事件之扫码推事件且弹出“消息接收中”提示框(scancode_waitmsg)
/// </summary>
/// <param name="requestMessage"></param>
/// <returns></returns>
public override IResponseMessageBase OnEvent_ScancodeWaitmsgRequest(RequestMessageEvent_Scancode_Waitmsg requestMessage)
{
var responseMessage = base.CreateResponseMessage<ResponseMessageText>();
responseMessage.Content = "事件之扫码推事件且弹出“消息接收中”提示框";
return responseMessage;
} /// <summary>
/// 事件之弹出拍照或者相册发图(pic_photo_or_album)
/// </summary>
/// <param name="requestMessage"></param>
/// <returns></returns>
public override IResponseMessageBase OnEvent_PicPhotoOrAlbumRequest(RequestMessageEvent_Pic_Photo_Or_Album requestMessage)
{
var responseMessage = base.CreateResponseMessage<ResponseMessageText>();
responseMessage.Content = "事件之弹出拍照或者相册发图";
return responseMessage;
} /// <summary>
/// 事件之弹出系统拍照发图(pic_sysphoto)
/// 实际测试时发现微信并没有推送RequestMessageEvent_Pic_Sysphoto消息,只能接收到用户在微信中发送的图片消息。
/// </summary>
/// <param name="requestMessage"></param>
/// <returns></returns>
public override IResponseMessageBase OnEvent_PicSysphotoRequest(RequestMessageEvent_Pic_Sysphoto requestMessage)
{
var responseMessage = base.CreateResponseMessage<ResponseMessageText>();
responseMessage.Content = "事件之弹出系统拍照发图";
return responseMessage;
} /// <summary>
/// 事件之弹出微信相册发图器(pic_weixin)
/// </summary>
/// <param name="requestMessage"></param>
/// <returns></returns>
public override IResponseMessageBase OnEvent_PicWeixinRequest(RequestMessageEvent_Pic_Weixin requestMessage)
{
var responseMessage = base.CreateResponseMessage<ResponseMessageText>();
responseMessage.Content = "事件之弹出微信相册发图器";
return responseMessage;
} /// <summary>
/// 事件之弹出地理位置选择器(location_select)
/// </summary>
/// <param name="requestMessage"></param>
/// <returns></returns>
public override IResponseMessageBase OnEvent_LocationSelectRequest(RequestMessageEvent_Location_Select requestMessage)
{
var responseMessage = base.CreateResponseMessage<ResponseMessageText>();
responseMessage.Content = "事件之弹出地理位置选择器";
return responseMessage;
}
}
}
CustomMessageHandler.cs
/// <summary>
/// 订阅(关注)事件
/// </summary>
/// <returns></returns>
public override IResponseMessageBase OnEvent_SubscribeRequest(RequestMessageEvent_Subscribe requestMessage)
{
var responseMessage = base.CreateResponseMessage<ResponseMessageText>();
responseMessage.Content = "欢迎关注";
return responseMessage;
} /// <summary>
/// 退订
/// 实际上用户无法收到非订阅账号的消息,所以这里可以随便写。
/// unsubscribe事件的意义在于及时删除网站应用中已经记录的OpenID绑定,消除冗余数据。并且关注用户流失的情况。
/// </summary>
/// <returns></returns>
public override IResponseMessageBase OnEvent_UnsubscribeRequest(RequestMessageEvent_Unsubscribe requestMessage)
{
var responseMessage = base.CreateResponseMessage<ResponseMessageText>();
responseMessage.Content = "有空再来";
return responseMessage;
}
里面有2个事件,一个用户关注时触发,一个退订时候触发,所以基本我们无需要进行什么配置,只要加入这个类就可以了
二、本地数据库表
CREATE TABLE [dbo].[WC_Group](
[Id] [varchar](50) NOT NULL,
[Name] [varchar](200) NOT NULL,
[Count] [int] NOT NULL,
[OfficalAccountId] [varchar](50) NOT NULL,
CONSTRAINT [PK_WC_Group] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] GO SET ANSI_PADDING OFF
GO ALTER TABLE [dbo].[WC_Group] WITH CHECK ADD CONSTRAINT [FK_WC_Group_WC_OfficalAccounts] FOREIGN KEY([OfficalAccountId])
REFERENCES [dbo].[WC_OfficalAccounts] ([Id])
GO ALTER TABLE [dbo].[WC_Group] CHECK CONSTRAINT [FK_WC_Group_WC_OfficalAccounts]
GO
分组表
CREATE TABLE [dbo].[WC_User](
[Id] [varchar](50) NOT NULL,
[OpenId] [varchar](50) NOT NULL,
[NickName] [varchar](200) NULL,
[Sex] [int] NOT NULL,
[Language] [varchar](50) NULL,
[City] [varchar](50) NULL,
[Province] [varchar](50) NULL,
[Country] [varchar](50) NULL,
[HeadImgUrl] [varchar](1000) NULL,
[SubscribeTime] [datetime] NOT NULL,
[UnionId] [varchar](200) NULL,
[Remark] [varchar](1000) NULL,
[GroupId] [varchar](50) NULL,
[TagidList] [varchar](1000) NULL,
[Subscribe] [int] NOT NULL,
[OfficalAccountId] [varchar](50) NOT NULL,
CONSTRAINT [PK_WC_User] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] GO SET ANSI_PADDING OFF
GO ALTER TABLE [dbo].[WC_User] WITH NOCHECK ADD CONSTRAINT [FK_WC_User_WC_Group] FOREIGN KEY([GroupId])
REFERENCES [dbo].[WC_Group] ([Id])
GO ALTER TABLE [dbo].[WC_User] NOCHECK CONSTRAINT [FK_WC_User_WC_Group]
GO ALTER TABLE [dbo].[WC_User] WITH CHECK ADD CONSTRAINT [FK_WC_User_WC_OfficalAccounts] FOREIGN KEY([OfficalAccountId])
REFERENCES [dbo].[WC_OfficalAccounts] ([Id])
GO ALTER TABLE [dbo].[WC_User] CHECK CONSTRAINT [FK_WC_User_WC_OfficalAccounts]
GO
用户表
表字段是根据官网,用户管理对应字段而建立,基本与官方提供的用户信息是一样的,无非是存点用户的姓名,籍贯,头像,关注事件等
三、同步数据
这时我们就可以实现OnEvent_SubscribeRequest (关注时)的代码,基本没有实现难度,步骤如下:
- 获得OpenID(requestMessage.FromUserName)
- 调用信息接口( UserInfoJson userJson = UserApi.Info(account.AccessToken, requestMessage.FromUserName);)
- 把信息添加到本地
- 启用订阅时回复的内容(回复在前面已经放出)
/// <summary>
/// 订阅(关注)事件
/// </summary>
/// <returns></returns>
public override IResponseMessageBase OnEvent_SubscribeRequest(RequestMessageEvent_Subscribe requestMessage)
{
ValidationErrors errors = new ValidationErrors(); using (DBContainer db = new DBContainer())
{ IWC_OfficalAccountsBLL account_BLL = new WC_OfficalAccountsBLL()
{
m_Rep = new WC_OfficalAccountsRepository(db)
}; //获得当前公众号
WC_OfficalAccountsModel account = account_BLL.GetById(Id); //将用户提取到本地数据库
WC_UserModel userModel = new WC_UserModel();
IWC_UserBLL user_BLL = new WC_UserBLL()
{
m_Rep = new WC_UserRepository(db)
};
user_BLL.Create(ref errors, userModel);
UserInfoJson userJson = UserApi.Info(account.AccessToken, requestMessage.FromUserName);
userModel.Id = ResultHelper.NewId;
userModel.OpenId = userJson.openid;
userModel.NickName = userJson.nickname;
userModel.Sex = userJson.sex;
userModel.Language = userJson.language;
userModel.City = userJson.city;
userModel.Province = userJson.province;
userModel.Country = userJson.country;
userModel.HeadImgUrl = userJson.headimgurl;
userModel.SubscribeTime = ResultHelper.GetTimeByLong(userJson.subscribe_time);
userModel.UnionId = userJson.unionid;
userModel.Remark = userJson.remark;
userModel.GroupId = userJson.groupid.ToString();
userModel.TagidList = string.Join(",", userJson.tagid_list.ToArray());
userModel.Subscribe = userJson.subscribe;
userModel.OfficalAccountId = account.Id;
IWC_MessageResponseRepository m_Rep = new WC_MessageResponseRepository(db);
//订阅回复
List<WC_MessageResponse> messageList = m_Rep.GetSubscribeResponseContent(account.Id);
if (messageList.Count() > )
{
if (messageList[].Category == (int)WeChatReplyCategory.Text)
{
var responseMessage = base.CreateResponseMessage<ResponseMessageText>();
responseMessage.CreateTime = ResultHelper.NowTime;
responseMessage.ToUserName = requestMessage.FromUserName;
responseMessage.FromUserName = account.OfficalId;
responseMessage.Content = messageList[].TextContent;
return responseMessage;
}
//图文方式
else if (messageList[].Category == (int)WeChatReplyCategory.Image)
{
var responseMessage = CreateResponseMessage<ResponseMessageNews>();
foreach (var model in messageList)
{
responseMessage.Articles.Add(new Article()
{
Title = model.TextContent,
Description = model.ImgTextContext,
PicUrl = WebChatPara.SiteUrl + model.ImgTextUrl,
Url = model.ImgTextLink
});
}
return responseMessage;
}//一般很少用到
else if (messageList[].Category == (int)WeChatReplyCategory.Voice)
{
var responseMessage = base.CreateResponseMessage<ResponseMessageMusic>();
responseMessage.Music.MusicUrl = WebChatPara.SiteUrl + messageList[].MeidaUrl;
responseMessage.Music.Title = messageList[].TextContent;
responseMessage.Music.Description = messageList[].Remark;
return responseMessage;
}
}
var errorResponseMessage = requestMessage.CreateResponseMessage<ResponseMessageText>();
return errorResponseMessage;
}
}
退订事件:OnEvent_UnsubscribeRequest(退订没有什么代码,只是标记这个openID已经取消关注)
/// <summary>
/// 订阅(关注)事件
/// </summary>
/// <returns></returns>
public override IResponseMessageBase OnEvent_SubscribeRequest(RequestMessageEvent_Subscribe requestMessage)
{
ValidationErrors errors = new ValidationErrors(); using (DBContainer db = new DBContainer())
{ IWC_OfficalAccountsBLL account_BLL = new WC_OfficalAccountsBLL()
{
m_Rep = new WC_OfficalAccountsRepository(db)
};
//获得当前公众号
WC_OfficalAccountsModel account = account_BLL.GetById(Id);
//将用户提取到本地数据库
IWC_UserBLL user_BLL = new WC_UserBLL()
{
m_Rep = new WC_UserRepository(db)
};
WC_UserModel userModel = user_BLL.GetById(Id);
//标记为取消关注
userModel.Subscribe = ;
user_BLL.Edit(ref errors, userModel);
var errorResponseMessage = requestMessage.CreateResponseMessage<ResponseMessageText>();
return errorResponseMessage;
}
}
后台管理
后台管理最直接的效益是分析统计用户的数据状况,这里只演示从服务器同步用户信息,其他都是以前写得发愁的,增删改查了
前端JS
$("#btnSync").click(function () {
var rows = $('#List').datagrid('getSelections');
if (rows.length > 0) {
var ids = rows.join(",");
$.each(rows, function (index, row) {
ids = ids + row.value + ",";
});
$.post("@Url.Action("SyncUser")?ids=" + ids, function (data) {
if (data.type == 1)
$("#List").datagrid('load');
$.messageBox5s('@Resource.Tip', data.message);
}, "json");
} else { $.messageBox5s('@Resource.Tip', '@Resource.PlaseChooseToOperatingRecords'); }
});
后端控制器代码
public JsonResult SyncUser(string ids,string officeId)
{
if (!string.IsNullOrWhiteSpace(ids))
{
//填充数据
string[] arrs = ids.Split(',');
List<BatchGetUserInfoData> list = new List<BatchGetUserInfoData>();
foreach (var m in arrs)
{
list.Add(new BatchGetUserInfoData() {
openid = m
});
} //批量同步数据
WC_OfficalAccountsModel accountModel = account_BLL.GetById(officeId);
var batchList = Senparc.Weixin.MP.AdvancedAPIs.UserApi.BatchGetUserInfo(accountModel.AccessToken, list);
foreach (var info in batchList.user_info_list)
{
WC_UserModel userModel = m_BLL.GetById(info.openid);
if (userModel != null)
{
userModel.City = info.city;
userModel.OpenId = info.openid;
userModel.Id = info.openid;
userModel.HeadImgUrl = info.headimgurl;
userModel.Language = info.language;
userModel.NickName = info.nickname;
userModel.Province = info.province;
userModel.Sex = info.sex;
m_BLL.Edit(ref errors, userModel);
}
} LogHandler.WriteServiceLog(GetUserId(), "Ids:" + ids, "成功", "删除", "WC_User");
return Json(JsonHandler.CreateMessage(, Resource.SaveSucceed));
}
else
{
return Json(JsonHandler.CreateMessage(, Resource.SaveFail));
} }
代码简单易懂:通过OpenID到公众号同步到数据,再将本地数据修改
同步接口在Senparc WX SDK下的Senparc.Weixin.MP.AdvancedAPIs UserApi
同时这个类也提供了:获取用户信息,获取关注者OpenId信息,修改关注者备注信息,批量获取用户基本信息
ASP.NET MVC5+EF6+EasyUI 后台管理系统(75)-微信公众平台开发-用户管理的更多相关文章
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(66)-MVC WebApi 用户验证 (2)
系列目录 前言: 回顾上一节,我们利用webapi简单的登录并进行了同域访问与跨域访问来获得Token,您可以跳转到上一节下载代码来一起动手. 继续上一篇的文章,我们接下来演示利用拿到的Token来访 ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(65)-MVC WebApi 用户验证 (1)
系列目录 前言: WebAPI主要开放数据给手机APP,其他需要得知数据的系统,或者软件应用,所以移动端与系统的数据源往往是相通的. Web 用户的身份验证,及页面操作权限验证是B/S系统的基础功能, ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(1)-前言与目录(持续更新中...)
开发工具:VS2015(2012以上)+SQL2008R2以上数据库 您可以有偿获取一份最新源码联系QQ:729994997 价格 666RMB 升级后界面效果如下: 任务调度系统界面 http: ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(1)-前言与目录(转)
开发工具:VS2015(2012以上)+SQL2008R2以上数据库 您可以有偿获取一份最新源码联系QQ:729994997 价格 666RMB 升级后界面效果如下: 日程管理 http://ww ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统-WebApi的用法与调试
1:ASP.NET MVC5+EF6+EasyUI 后台管理系统(1)-WebApi与Unity注入 使用Unity是为了使用我们后台的BLL和DAL层 2:ASP.NET MVC5+EF6+Easy ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(63)-Excel导入和导出-自定义表模导入
系列目录 前言 上一节使用了LinqToExcel和CloseXML对Excel表进行导入和导出的简单操作,大家可以跳转到上一节查看: ASP.NET MVC5+EF6+EasyUI 后台管理系统(6 ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(51)-系统升级
系统很久没有更新内容了,期待已久的更新在今天发布了,最近花了2个月的时间每天一点点,从原有系统 MVC4+EF5+UNITY2.X+Quartz 2.0+easyui 1.3.4无缝接入 MVC5+E ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(70)-微信公众平台开发-成为开发者
系列目录 前言: 一.阅读这段系列之前,你必须花半天时间大致阅读微信公众平台的API文档,我尽量以简短快速的语言与大家分享一个过程 二.借助微信公众平台SDK Senparc.Weixin for C ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统 (源码购买说明)
系列目录 升级日志 !!!重大版本更新:于2016-12-20日完成了系统的结构重构并合并简化了T4(这是一次重要的更新,不需要修改现有功能的代码),代码总行数比上个版本又少了1/3.更新了代码生成器 ...
随机推荐
- SQL Server技术内幕笔记合集
SQL Server技术内幕笔记合集 发这一篇文章主要是方便大家找到我的笔记入口,方便大家o(∩_∩)o Microsoft SQL Server 6.5 技术内幕 笔记http://www.cnbl ...
- .NET Core & ASP.NET Core 1.0在Redhat峰会上正式发布
众所周知,Red Hat和微软正在努力使.NET Core成为Red Hat企业版Linux (RHEL)系统上的一流开发平台选项.这个团队已经一起工作好几个月了,RHEL对.NET有许多需求.今天在 ...
- Entity Framework 6 Recipes 2nd Edition 译 -> 目录 -持续更新
因为看了<Entity Framework 6 Recipes 2nd Edition>这本书前面8章的翻译,感谢china_fucan. 从第九章开始,我是边看边译的,没有通读,加之英语 ...
- 【资源】.Net 入门@提高 - 逆天的高薪之路!
入门看视频,提高看书籍,飘升做项目.老练研开源,高手读外文,大牛讲低调~ 官方学习计划 http://www.cnblogs.com/dunitian/p/5667901.html ----- ...
- ExtJS 4.2 介绍
本篇介绍ExtJS相关知识,是以ExtJS4.2.1版本为基础进行说明,包括:ExtJS的特点.MVC模式.4.2.1GPL版本资源的下载和说明以及4种主题的演示. 目录 1. 介绍 1.1 说明 1 ...
- css实现单行,多行文本溢出显示省略号……
1.单行文本溢出显示省略号我们可以直接用text-overflow: ellipsis 实现方法: <style> .div_text{width: 300px; padding:10px ...
- 千呼万唤始出来,微软Power BI简体中文版官网终于上线了,中文文档也全了。。
前几个月时间,研究微软Power BI技术,由于没有任何文档和资料,只能在英文官网瞎折腾,同时也发布了英文文档的相关文章:系列文章,刚好上周把文章发布完,结果简体中文版上线了.哈哈,心里有苦啊,早知道 ...
- 独立开发 一个社交 APP 的架构分享 (已实现)
(本博客为原创:http://www.cnblogs.com/linguanh/) My BananaCloud Android Application 前言: 这算是我的第一个 完完全全 由自 ...
- 纯javaScript、jQuery实现个性化图片轮播
纯javaScript实现个性化图片轮播 轮播原理说明<如上图所示>: 1. 画布部分(可视区域)属性说明:overflow:hidden使得超出画布部分隐藏或说不可见.position: ...
- Win10提示没有权限使用网络资源问题解决
借鉴链接:http://www.cr173.com/html/67361_1.html Win10提示没有权限使用网络资源解决方法 1.打开控制面板; 2.在所有控制面板项中找到凭据管理器; 3.添加 ...