| @ -0,0 +1,76 @@ | |||
| | |||
| using Forks.EnterpriseServices; | |||
| using Forks.Utils.Configuration; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using TSingSoft.WebPluginFramework; | |||
| namespace BWP.B3WeChat | |||
| { | |||
| [ConfigurationEnabled] | |||
| public class B3WeChatConfig | |||
| { | |||
| public B3WeChatConfig() | |||
| { | |||
| ConfigurationUtil.Fill(this); | |||
| } | |||
| StringConfigRef mToken = new StringConfigRef(string.Empty); | |||
| [LogicName("微信Token")] | |||
| public StringConfigRef Token | |||
| { | |||
| get | |||
| { | |||
| return mToken; | |||
| } | |||
| set | |||
| { | |||
| mToken = value; | |||
| } | |||
| } | |||
| StringConfigRef mAppID = new StringConfigRef(string.Empty); | |||
| [LogicName("微信AppID")] | |||
| public StringConfigRef AppID | |||
| { | |||
| get | |||
| { | |||
| return mAppID; | |||
| } | |||
| set | |||
| { | |||
| mAppID = value; | |||
| } | |||
| } | |||
| StringConfigRef mAppSecret = new StringConfigRef(string.Empty); | |||
| [LogicName("微信AppSecret")] | |||
| public StringConfigRef AppSecret | |||
| { | |||
| get | |||
| { | |||
| return mAppSecret; | |||
| } | |||
| set | |||
| { | |||
| mAppSecret = value; | |||
| } | |||
| } | |||
| StringConfigRef mSelfAppID = new StringConfigRef(string.Empty); | |||
| [LogicName("微信SelfAppID")] | |||
| public StringConfigRef SelfAppID | |||
| { | |||
| get | |||
| { | |||
| return mSelfAppID; | |||
| } | |||
| set | |||
| { | |||
| mSelfAppID = value; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,15 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| namespace BWP.B3WeChat.BO | |||
| { | |||
| class CustomerUser | |||
| { | |||
| public string CustomerNumber { get; set; } | |||
| public string Username { get; set; } | |||
| public string WeixinUsername { get; set; } | |||
| } | |||
| } | |||
| @ -0,0 +1,40 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using Forks.EnterpriseServices; | |||
| using Forks.EnterpriseServices.DataForm; | |||
| using TSingSoft.WebPluginFramework; | |||
| using Forks.EnterpriseServices.DomainObjects2; | |||
| namespace BWP.B3WeChat.BO | |||
| { | |||
| [LogicName("二维码场景信息")] | |||
| [Serializable] | |||
| [DFClass] | |||
| [BOClass] | |||
| [KeyField("ID", KeyGenType.identity)] | |||
| public class QRCodeScene | |||
| { | |||
| [LogicName("场景ID")] | |||
| public int ID { get; set; } | |||
| [LogicName("客户")] | |||
| [DFNotEmpty] | |||
| public string Customer { get; set; } | |||
| [LogicName("用户")] | |||
| [DFNotEmpty] | |||
| public string UserId { get; set; } | |||
| [LogicName("微信号关注ID")] | |||
| public int OppenId { get; set; } | |||
| [LogicName("QRCode图片")] | |||
| public string Path { get; set; } | |||
| [LogicName("QRCode过期时间")] | |||
| public DateTime? OutTime { get; set; } | |||
| } | |||
| } | |||
| @ -0,0 +1,13 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Web; | |||
| namespace BWP.B3WeChat.Entities | |||
| { | |||
| public class ErrorObject | |||
| { | |||
| public string errcode { get; set; } | |||
| public string errmsg { get; set; } | |||
| } | |||
| } | |||
| @ -0,0 +1,32 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Web; | |||
| using System.Xml.Serialization; | |||
| namespace BWP.B3WeChat.Entities | |||
| { | |||
| [XmlRoot("xml")] | |||
| [Serializable] | |||
| public class EventType | |||
| { | |||
| /// <summary> | |||
| /// 事件类型,event | |||
| /// </summary> | |||
| [XmlElement("Event")] | |||
| public string Event { get; set; } | |||
| } | |||
| /// <summary> | |||
| /// 事件类型 | |||
| /// </summary> | |||
| public static class EvtType | |||
| { | |||
| public static string 订阅 { get { return "subscribe"; } } | |||
| public static string 取消订阅 { get { return "unsubscribe"; } } | |||
| public static string 扫描带参数二维码 { get { return "SCAN"; } } | |||
| public static string 上报地理位置 { get { return "LOCATION"; } } | |||
| public static string 点击菜单拉取消息 { get { return "CLICK"; } } | |||
| public static string 点击菜单跳转链接 { get { return "VIEW"; } } | |||
| } | |||
| } | |||
| @ -0,0 +1,35 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Web; | |||
| namespace BWP.B3WeChat.Entities | |||
| { | |||
| /// <summary> | |||
| /// 发送信息模板主体 | |||
| /// </summary> | |||
| public class MeassageBody | |||
| { | |||
| /// <summary> | |||
| /// 接收者openid | |||
| /// </summary> | |||
| public string touser { get; set; } | |||
| /// <summary> | |||
| /// 模板ID | |||
| /// </summary> | |||
| public string template_id { get; set; } | |||
| /// <summary> | |||
| /// 模板跳转链接 | |||
| /// </summary> | |||
| public string url { get; set; } | |||
| /// <summary> | |||
| /// 模板数据 | |||
| /// </summary> | |||
| public Dictionary<string, ValueColor> data { get; set; } | |||
| } | |||
| public class ValueColor | |||
| { | |||
| public string value { get; set; } | |||
| public string color { get; set; } | |||
| } | |||
| } | |||
| @ -0,0 +1,24 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Web; | |||
| using System.Xml.Serialization; | |||
| namespace BWP.B3WeChat.Entities | |||
| { | |||
| [XmlRoot("xml")] | |||
| [Serializable] | |||
| public class MessageType | |||
| { | |||
| /// <summary> | |||
| /// 消息类型,event | |||
| /// </summary> | |||
| [XmlElement("MsgType")] | |||
| public string MsgType { get; set; } | |||
| } | |||
| public static class MsgType | |||
| { | |||
| public static string 文本 { get { return "text"; } } | |||
| public static string 事件 { get { return "event"; } } | |||
| } | |||
| } | |||
| @ -0,0 +1,27 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Web; | |||
| namespace BWP.B3WeChat.Entities | |||
| { | |||
| /// <summary> | |||
| /// OpenID接收到的OpenID对象 | |||
| /// </summary> | |||
| public class OpenIDObject | |||
| { | |||
| /// <summary> | |||
| /// 关注该公众账号的总用户数 | |||
| /// </summary> | |||
| public int total { get; set; } | |||
| /// <summary> | |||
| /// 拉取的OPENID个数,最大值为10000 | |||
| /// </summary> | |||
| public int count { get; set; } | |||
| public OpenIDList data { get; set; } | |||
| } | |||
| public class OpenIDList | |||
| { | |||
| public List<string> openid { get; set; } | |||
| } | |||
| } | |||
| @ -0,0 +1,25 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Web; | |||
| namespace BWP.B3WeChat.Entities | |||
| { | |||
| /// <summary> | |||
| /// 二维码参数 | |||
| /// </summary> | |||
| public class QRCodeArgs | |||
| { | |||
| public int expire_seconds { get; set; } | |||
| public string action_name { get; set; } | |||
| public QRCodeScene action_info { get; set; } | |||
| } | |||
| public class QRCodeScene | |||
| { | |||
| public QRCodeSceneID scene { get; set; } | |||
| } | |||
| public class QRCodeSceneID | |||
| { | |||
| public int scene_id { get; set; } | |||
| } | |||
| } | |||
| @ -0,0 +1,52 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Web; | |||
| using System.Xml.Serialization; | |||
| namespace BWP.B3WeChat.Entities | |||
| { | |||
| /// <summary> | |||
| /// 扫描带参数二维码信息 | |||
| /// </summary> | |||
| [XmlRoot("xml")] | |||
| [Serializable] | |||
| public class QRCodeMessage | |||
| { | |||
| /// <summary> | |||
| /// 开发者微信号 | |||
| /// </summary> | |||
| [XmlElement("ToUserName")] | |||
| public string ToUserName { get; set; } | |||
| /// <summary> | |||
| /// 发送方帐号(一个OpenID) | |||
| /// </summary> | |||
| [XmlElement("FromUserName")] | |||
| public string FromUserName { get; set; } | |||
| /// <summary> | |||
| /// 消息创建时间 (整型) | |||
| /// </summary> | |||
| [XmlElement("CreateTime")] | |||
| public string CreateTime { get; set; } | |||
| /// <summary> | |||
| /// 消息类型,event | |||
| /// </summary> | |||
| [XmlElement("MsgType")] | |||
| public string MsgType { get; set; } | |||
| /// <summary> | |||
| /// 事件类型,SCAN | |||
| /// </summary> | |||
| [XmlElement("Event")] | |||
| public string Event { get; set; } | |||
| /// <summary> | |||
| /// 创建二维码时的二维码scene_id | |||
| /// </summary> | |||
| [XmlElement("EventKey")] | |||
| public string EventKey { get; set; } | |||
| /// <summary> | |||
| /// 二维码的ticket,可用来换取二维码图片 | |||
| /// </summary> | |||
| [XmlElement("Ticket")] | |||
| public string Ticket { get; set; } | |||
| } | |||
| } | |||
| @ -0,0 +1,14 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Web; | |||
| namespace BWP.B3WeChat.Entities | |||
| { | |||
| public class QRCodeResult | |||
| { | |||
| public string ticket { get; set; } | |||
| public int expire_seconds { get; set; } | |||
| public string url { get; set; } | |||
| } | |||
| } | |||
| @ -0,0 +1,47 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Web; | |||
| using System.Xml.Serialization; | |||
| namespace BWP.B3WeChat.Entities | |||
| { | |||
| /// <summary> | |||
| /// 普通消息(文本消息) | |||
| /// </summary> | |||
| [XmlRoot("xml")] | |||
| [Serializable] | |||
| public class ReceivedMsg | |||
| { | |||
| /// <summary> | |||
| /// 开发者微信号 | |||
| /// </summary> | |||
| [XmlElement("ToUserName")] | |||
| public string ToUserName { get; set; } | |||
| /// <summary> | |||
| /// 发送方帐号(一个OpenID) | |||
| /// </summary> | |||
| [XmlElement("FromUserName")] | |||
| public string FromUserName { get; set; } | |||
| /// <summary> | |||
| /// 消息创建时间 (整型) | |||
| /// </summary> | |||
| [XmlElement("CreateTime")] | |||
| public string CreateTime { get; set; } | |||
| /// <summary> | |||
| /// 消息类型,event | |||
| /// </summary> | |||
| [XmlElement("MsgType")] | |||
| public string MsgType { get; set; } | |||
| /// <summary> | |||
| /// 文本消息内容 | |||
| /// </summary> | |||
| [XmlElement("Content")] | |||
| public string Content { get; set; } | |||
| /// <summary> | |||
| /// 消息id,64位整型 | |||
| /// </summary> | |||
| [XmlElement("MsgId")] | |||
| public string MsgId { get; set; } | |||
| } | |||
| } | |||
| @ -0,0 +1,42 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Web; | |||
| using System.Xml.Serialization; | |||
| namespace BWP.B3WeChat.Entities | |||
| { | |||
| /// <summary> | |||
| /// 回复文本消息 | |||
| /// </summary> | |||
| [XmlRoot("xml")] | |||
| [Serializable] | |||
| public class ReplyMsg | |||
| { | |||
| /// <summary> | |||
| /// 接收方帐号(收到的OpenID) | |||
| /// </summary> | |||
| [XmlElement("ToUserName")] | |||
| public string ToUserName { get; set; } | |||
| /// <summary> | |||
| /// 开发者微信号 | |||
| /// </summary> | |||
| [XmlElement("FromUserName")] | |||
| public string FromUserName { get; set; } | |||
| /// <summary> | |||
| /// 消息创建时间 (整型) | |||
| /// </summary> | |||
| [XmlElement("CreateTime")] | |||
| public string CreateTime { get; set; } | |||
| /// <summary> | |||
| /// 消息类型,event | |||
| /// </summary> | |||
| [XmlElement("MsgType")] | |||
| public string MsgType { get; set; } | |||
| /// <summary> | |||
| /// 文本消息内容 | |||
| /// </summary> | |||
| [XmlElement("Content")] | |||
| public string Content { get; set; } | |||
| } | |||
| } | |||
| @ -0,0 +1,17 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Web; | |||
| namespace BWP.B3WeChat.Entities | |||
| { | |||
| /// <summary> | |||
| /// 发送模板信息返回结果 | |||
| /// </summary> | |||
| public class SendTemplateMessageResult | |||
| { | |||
| public string errcode { get; set; } | |||
| public string errmsg { get; set; } | |||
| public int msgid { get; set; } | |||
| } | |||
| } | |||
| @ -0,0 +1,16 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Web; | |||
| namespace BWP.B3WeChat.Entities | |||
| { | |||
| /// <summary> | |||
| /// Token对象 | |||
| /// </summary> | |||
| public class TokenObject | |||
| { | |||
| public string access_token { get; set; } | |||
| public string expires_in { get; set; } | |||
| } | |||
| } | |||
| @ -0,0 +1,68 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Web; | |||
| namespace BWP.B3WeChat.Entities | |||
| { | |||
| public class UserBasicInfo | |||
| { | |||
| /// <summary> | |||
| /// 用户是否订阅该公众号标识,值为0时,代表此用户没有关注该公众号,拉取不到其余信息。默认为1 | |||
| /// </summary> | |||
| public int subscribe { get; set; } | |||
| /// <summary> | |||
| /// 用户的标识,对当前公众号唯一 | |||
| /// </summary> | |||
| public string openid { get; set; } | |||
| /// <summary> | |||
| /// 用户的昵称 | |||
| /// </summary> | |||
| public string nickname { get; set; } | |||
| /// <summary> | |||
| /// 用户的性别,值为1时是男性,值为2时是女性,值为0时是未知 | |||
| /// </summary> | |||
| public int sex { get; set; } | |||
| /// <summary> | |||
| /// 用户所在城市 | |||
| /// </summary> | |||
| public string language { get; set; } | |||
| /// <summary> | |||
| /// 用户所在国家 | |||
| /// </summary> | |||
| public string city { get; set; } | |||
| /// <summary> | |||
| /// 用户所在省份 | |||
| /// </summary> | |||
| public string province { get; set; } | |||
| /// <summary> | |||
| /// 用户的语言,简体中文为zh_CN | |||
| /// </summary> | |||
| public string country { get; set; } | |||
| /// <summary> | |||
| /// 用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空。若用户更换头像,原有头像URL将失效。 | |||
| /// </summary> | |||
| public string headimgurl { get; set; } | |||
| /// <summary> | |||
| /// 用户关注时间,为时间戳。如果用户曾多次关注,则取最后关注时间 | |||
| /// </summary> | |||
| public int subscribe_time { get; set; } | |||
| /// <summary> | |||
| /// 只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。 | |||
| /// </summary> | |||
| public string unionid { get; set; } | |||
| /// <summary> | |||
| /// 公众号运营者对粉丝的备注,公众号运营者可在微信公众平台用户管理界面对粉丝添加备注 | |||
| /// </summary> | |||
| public string remark { get; set; } | |||
| /// <summary> | |||
| /// 用户所在的分组ID(兼容旧的用户分组接口) | |||
| /// </summary> | |||
| public int groupid { get; set; } | |||
| /// <summary> | |||
| /// 用户被打上的标签ID列表 | |||
| /// </summary> | |||
| public List<int> tagid_list { get; set; } | |||
| } | |||
| } | |||
| @ -0,0 +1,12 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Web; | |||
| namespace BWP.B3WeChat.Entities | |||
| { | |||
| public class WeiChartServerList | |||
| { | |||
| public List<string> ip_list { get; set; } | |||
| } | |||
| } | |||
| @ -0,0 +1,147 @@ | |||
| using Bwp.MainSystem.BO; | |||
| using BWP.B3WeChat.BO; | |||
| using BWP.B3WeChat.Utils; | |||
| using Forks.EnterpriseServices.DomainObjects2; | |||
| using Forks.EnterpriseServices.DomainObjects2.DQuery; | |||
| using Forks.EnterpriseServices.JsonRpc; | |||
| using Forks.EnterpriseServices.SqlDoms; | |||
| using Forks.Utils; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.IO; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using TSingSoft.WebPluginFramework; | |||
| namespace BWP.B3WeChat.Rpcs | |||
| { | |||
| [Rpc] | |||
| public static class ClientRpc | |||
| { | |||
| static string GetDeviceNumber() | |||
| { | |||
| var user = BLContext.User; | |||
| var query = new DQueryDom(new JoinAlias(typeof(DeviceAuthentication))); | |||
| query.Where.Conditions.Add(DQCondition.EQ("Ticket", user.UserTag.ToString("N"))); | |||
| query.Columns.Add(DQSelectColumn.Field("DeviceNumber")); | |||
| query.Range = SelectRange.Top(1); | |||
| var deviceNumber = query.EExecuteScalar<string>(); | |||
| return deviceNumber; | |||
| } | |||
| [Rpc] | |||
| public static void Send(string username, string content) | |||
| { | |||
| string oppenid = GetOpenId(username).ToString(); | |||
| string[] param = content.Split('|'); | |||
| switch (param[0]) | |||
| { | |||
| case "SendAgentInfo": SendMessageUtil.SendAgentInfo(oppenid, param[1], param[2], param[3], param[4]); break; | |||
| } | |||
| } | |||
| static int GetOpenId(string username) | |||
| { | |||
| string customer = GetDeviceNumber(); | |||
| var query = new DQueryDom(new JoinAlias(typeof(QRCodeScene))); | |||
| query.Columns.Add(DQSelectColumn.Field("OppenId")); | |||
| query.Where.Conditions.Add(DQCondition.EQ("Customer", customer)); | |||
| query.Where.Conditions.Add(DQCondition.EQ("UserId", username)); | |||
| query.Range = SelectRange.Top(1); | |||
| var OppenId = query.EExecuteScalar<int?>(); | |||
| if (!OppenId.HasValue) | |||
| { | |||
| throw new Exception("未找到该微信用户或者" + username + "未关联微信"); | |||
| } | |||
| return OppenId.Value; | |||
| } | |||
| [Rpc] | |||
| public static String GetQRCodeUrl(string username) | |||
| { | |||
| string url = string.Empty; | |||
| string customer = GetDeviceNumber(); | |||
| if (string.IsNullOrEmpty(customer)) | |||
| return url; | |||
| url = ExistQRCode(customer, username); | |||
| if (!string.IsNullOrEmpty(url)) | |||
| { | |||
| return url; | |||
| } | |||
| int sceneId = GetSceneId(customer, username); | |||
| string ticket = InOutMessageUtil.GenerateEQCode(30, sceneId); | |||
| string name = DateTime.Now.Ticks.ToString() + ".jpg"; | |||
| string path = GetQRCodeDir() + name; | |||
| InOutMessageUtil.GetQRPic(ticket, path); | |||
| url = "/QRCodePic/" + name; | |||
| UpdateQRCode(sceneId, url); | |||
| return url; | |||
| } | |||
| static void UpdateQRCode(int sceneId, string path) | |||
| { | |||
| var update = new DQUpdateDom(typeof(QRCodeScene)); | |||
| update.Where.Conditions.Add(DQCondition.EQ("ID", sceneId)); | |||
| update.Columns.Add(new DQUpdateColumn("Path", path)); | |||
| update.Columns.Add(new DQUpdateColumn("OutTime", DateTime.Now.AddDays(30))); | |||
| using (var session = Dmo.NewSession()) | |||
| { | |||
| session.ExecuteNonQuery(update); | |||
| } | |||
| } | |||
| static string ExistQRCode(string customer, string username) | |||
| { | |||
| string path = string.Empty; | |||
| var query = new DQueryDom(new JoinAlias(typeof(QRCodeScene))); | |||
| query.Columns.Add(DQSelectColumn.Field("Path")); | |||
| query.Columns.Add(DQSelectColumn.Field("OutTime")); | |||
| query.Where.Conditions.Add(DQCondition.EQ("Customer", customer)); | |||
| query.Where.Conditions.Add(DQCondition.EQ("UserId", username)); | |||
| query.Range = SelectRange.Top(1); | |||
| var result = query.EExecuteScalar<string, DateTime?>(); | |||
| if (result.Item2.HasValue && result.Item2.Value > DateTime.Now) | |||
| { | |||
| path = result.Item1; | |||
| } | |||
| return path; | |||
| } | |||
| static int GetSceneId(string customer, string username) | |||
| { | |||
| var query = new DQueryDom(new JoinAlias(typeof(QRCodeScene))); | |||
| query.Columns.Add(DQSelectColumn.Field("ID")); | |||
| query.Where.Conditions.Add(DQCondition.EQ("Customer", customer)); | |||
| query.Where.Conditions.Add(DQCondition.EQ("UserId", username)); | |||
| query.Range = SelectRange.Top(1); | |||
| var sceneId = query.EExecuteScalar<int?>(); | |||
| if (!sceneId.HasValue) | |||
| { | |||
| using (var session = Dmo.NewSession()) | |||
| { | |||
| QRCodeScene newSence = new QRCodeScene() | |||
| { | |||
| Customer = customer, | |||
| UserId = username, | |||
| }; | |||
| session.Insert(newSence); | |||
| session.Commit(); | |||
| sceneId = newSence.ID; | |||
| } | |||
| } | |||
| return sceneId.Value; | |||
| } | |||
| static string GetQRCodeDir() | |||
| { | |||
| string dir = System.Environment.CurrentDirectory + "/QRCodePic/"; | |||
| if (!Directory.Exists(dir)) | |||
| { | |||
| Directory.CreateDirectory(dir); | |||
| } | |||
| return dir; | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,101 @@ | |||
| using Bwp.MainSystem.BO; | |||
| using BWP.B3WeChat.BO; | |||
| using BWP.B3WeChat.Utils; | |||
| using Forks.EnterpriseServices.DomainObjects2; | |||
| using Forks.EnterpriseServices.DomainObjects2.DQuery; | |||
| using Forks.EnterpriseServices.JsonRpc; | |||
| using Forks.EnterpriseServices.SqlDoms; | |||
| using Forks.Utils; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.IO; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using TSingSoft.WebPluginFramework; | |||
| namespace BWP.B3WeChat.Rpcs | |||
| { | |||
| [Rpc] | |||
| public static class ClientRpc | |||
| { | |||
| static string GetDeviceNumber() | |||
| { | |||
| var user = BLContext.User; | |||
| var query = new DQueryDom(new JoinAlias(typeof(DeviceAuthentication))); | |||
| query.Where.Conditions.Add(DQCondition.EQ("Ticket", user.UserTag.ToString("N"))); | |||
| query.Columns.Add(DQSelectColumn.Field("DeviceNumber")); | |||
| query.Range = SelectRange.Top(1); | |||
| var deviceNumber = query.EExecuteScalar<string>(); | |||
| return deviceNumber; | |||
| } | |||
| [Rpc] | |||
| public static void Send(String message, string username) | |||
| { | |||
| } | |||
| [Rpc] | |||
| public static String GetQRCodeUrl(string username) | |||
| { | |||
| string url = string.Empty; | |||
| string customer = GetDeviceNumber(); | |||
| if (string.IsNullOrEmpty(customer)) | |||
| return url; | |||
| string ticket = InOutMessageUtil.GenerateEQCode(30, GetSceneId(customer, username)); | |||
| string name=DateTime.Now.Ticks.ToString() + ".jpg"; | |||
| string path = GetQRCodeDir() + name; | |||
| InOutMessageUtil.GetQRPic(ticket, path); | |||
| return url; | |||
| } | |||
| static string ExistQRCode(string customer, string username) | |||
| { | |||
| var query = new DQueryDom(new JoinAlias(typeof(QRCodeScene))); | |||
| query.Columns.Add(DQSelectColumn.Field("Path")); | |||
| query.Where.Conditions.Add(DQCondition.EQ("Customer", customer)); | |||
| query.Where.Conditions.Add(DQCondition.EQ("UserId", username)); | |||
| query.Where.Conditions.Add(DQCondition.GreaterThan(DQExpression.Field("OutTime"), DQExpression.Value(DateTime.Now))); | |||
| query.Range = SelectRange.Top(1); | |||
| var path = query.EExecuteScalar<string>(); | |||
| return path; | |||
| } | |||
| static int GetSceneId(string customer, string username) | |||
| { | |||
| var query = new DQueryDom(new JoinAlias(typeof(QRCodeScene))); | |||
| query.Columns.Add(DQSelectColumn.Field("ID")); | |||
| query.Where.Conditions.Add(DQCondition.EQ("Customer", customer)); | |||
| query.Where.Conditions.Add(DQCondition.EQ("UserId", username)); | |||
| query.Range = SelectRange.Top(1); | |||
| var sceneId = query.EExecuteScalar<int?>(); | |||
| if (!sceneId.HasValue) | |||
| { | |||
| using (var session = Dmo.NewSession()) | |||
| { | |||
| QRCodeScene newSence = new QRCodeScene() | |||
| { | |||
| Customer = customer, | |||
| UserId = username, | |||
| }; | |||
| session.Insert(newSence); | |||
| session.Commit(); | |||
| sceneId = newSence.ID; | |||
| } | |||
| } | |||
| return sceneId.Value; | |||
| } | |||
| static string GetQRCodeDir() | |||
| { | |||
| string dir = System.Environment.CurrentDirectory + "/QRCodePic/"; | |||
| if (!Directory.Exists(dir)) | |||
| { | |||
| Directory.CreateDirectory(dir); | |||
| } | |||
| return dir; | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,288 @@ | |||
| using BWP.B3WeChat; | |||
| using BWP.B3WeChat.Entities; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.IO; | |||
| using System.Linq; | |||
| using System.Net; | |||
| using System.Text; | |||
| using System.Web; | |||
| using System.Web.Script.Serialization; | |||
| using System.Web.Security; | |||
| namespace BWP.B3WeChat.Utils | |||
| { | |||
| public static class InOutMessageUtil | |||
| { | |||
| static string token; | |||
| static string TOKEN | |||
| { | |||
| get | |||
| { | |||
| if (string.IsNullOrEmpty(token)) | |||
| { | |||
| token = GetToken(); | |||
| } | |||
| return token; | |||
| } | |||
| } | |||
| public static B3WeChatConfig config = new B3WeChatConfig(); | |||
| public static string GetToken() | |||
| { | |||
| string token = string.Empty; | |||
| string uriStr = string.Format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}", config.AppID, config.AppSecret); | |||
| WebClient client = new WebClient(); | |||
| try | |||
| { | |||
| byte[] bytes = client.DownloadData(uriStr); | |||
| string responseBody = Encoding.UTF8.GetString(bytes); | |||
| JavaScriptSerializer jsonHelper = new JavaScriptSerializer(); | |||
| TokenObject obj = jsonHelper.Deserialize<TokenObject>(responseBody); | |||
| if (obj != null) | |||
| { | |||
| token = obj.access_token; | |||
| } | |||
| } | |||
| catch (Exception e) | |||
| { | |||
| throw e; | |||
| } | |||
| return token; | |||
| } | |||
| public static WeiChartServerList GetIPList() | |||
| { | |||
| WeiChartServerList result = new WeiChartServerList(); | |||
| string uriStr = string.Format("https://api.weixin.qq.com/cgi-bin/getcallbackip?access_token={0}", TOKEN); | |||
| WebClient client = new WebClient(); | |||
| try | |||
| { | |||
| byte[] bytes = client.DownloadData(uriStr); | |||
| string responseBody = Encoding.UTF8.GetString(bytes); | |||
| JavaScriptSerializer jsonHelper = new JavaScriptSerializer(); | |||
| result = jsonHelper.Deserialize<WeiChartServerList>(responseBody); | |||
| } | |||
| catch (Exception e) | |||
| { | |||
| throw e; | |||
| } | |||
| return result; | |||
| } | |||
| public static SendTemplateMessageResult SendTemplateMessage(string openID, string templateID, Dictionary<string, ValueColor> dic, string url = "") | |||
| { | |||
| string uriStr = string.Format("https://api.weixin.qq.com/cgi-bin/message/template/send?access_token={0}", TOKEN); | |||
| JavaScriptSerializer jsonHelper = new JavaScriptSerializer(); | |||
| SendTemplateMessageResult result = new SendTemplateMessageResult(); | |||
| MeassageBody body = new MeassageBody(); | |||
| body.touser = openID; | |||
| body.template_id = templateID; | |||
| body.url = url; | |||
| body.data = dic; | |||
| string postData = jsonHelper.Serialize(body); | |||
| string data = string.Empty; | |||
| try | |||
| { | |||
| byte[] byteArray = Encoding.UTF8.GetBytes(postData); | |||
| HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(new Uri(uriStr)); | |||
| webRequest.Method = "post"; | |||
| webRequest.ContentType = "application/x-www-form-urlencoded"; | |||
| webRequest.ContentLength = byteArray.Length; | |||
| System.IO.Stream newStream = webRequest.GetRequestStream(); | |||
| newStream.Write(byteArray, 0, byteArray.Length); | |||
| newStream.Close(); | |||
| HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse(); | |||
| data = new System.IO.StreamReader(response.GetResponseStream(), Encoding.GetEncoding("utf-8")).ReadToEnd(); | |||
| result = jsonHelper.Deserialize<SendTemplateMessageResult>(data); | |||
| } | |||
| catch (Exception e) | |||
| { | |||
| throw e; | |||
| } | |||
| return result; | |||
| } | |||
| public static List<string> GetOpenIDList() | |||
| { | |||
| string openid = string.Empty; | |||
| string uriStr = string.Empty; | |||
| List<string> lstOpenID = new List<string>(); | |||
| JavaScriptSerializer jsonHelper = new JavaScriptSerializer(); | |||
| OpenIDObject result = new OpenIDObject(); | |||
| WebClient client = new WebClient(); | |||
| try | |||
| { | |||
| do | |||
| { | |||
| uriStr = string.Format("https://api.weixin.qq.com/cgi-bin/user/get?access_token={0}&next_openid={1}", TOKEN, openid); | |||
| byte[] bytes = client.DownloadData(uriStr); | |||
| string responseBody = Encoding.UTF8.GetString(bytes); | |||
| result = jsonHelper.Deserialize<OpenIDObject>(responseBody); | |||
| lstOpenID.AddRange(result.data.openid); | |||
| openid = result.data.openid.Last(); | |||
| } while (lstOpenID.Count < result.total); | |||
| } | |||
| catch (Exception e) | |||
| { | |||
| throw e; | |||
| } | |||
| return lstOpenID; | |||
| } | |||
| public static UserBasicInfo GetUserInfo(string openid) | |||
| { | |||
| string uriStr = string.Empty; | |||
| List<string> lstOpenID = new List<string>(); | |||
| JavaScriptSerializer jsonHelper = new JavaScriptSerializer(); | |||
| UserBasicInfo result = new UserBasicInfo(); | |||
| WebClient client = new WebClient(); | |||
| try | |||
| { | |||
| uriStr = string.Format("https://api.weixin.qq.com/cgi-bin/user/info?access_token={0}&openid={1}&lang=zh_CN", TOKEN, openid); | |||
| byte[] bytes = client.DownloadData(uriStr); | |||
| string responseBody = Encoding.UTF8.GetString(bytes); | |||
| result = jsonHelper.Deserialize<UserBasicInfo>(responseBody); | |||
| } | |||
| catch (Exception e) | |||
| { | |||
| throw e; | |||
| } | |||
| return result; | |||
| } | |||
| /// <summary> | |||
| /// 接收消息 | |||
| /// </summary> | |||
| /// <param name="request"></param> | |||
| /// <returns></returns> | |||
| public static object GetMessage(HttpRequest request) | |||
| { | |||
| StreamReader reader = new StreamReader(request.InputStream); | |||
| String xmlData = reader.ReadToEnd(); | |||
| object obj = null; | |||
| MessageType type = XmlUtil.Deserialize<MessageType>(xmlData); | |||
| if (type.MsgType == MsgType.文本) | |||
| { | |||
| obj = XmlUtil.Deserialize<ReceivedMsg>(xmlData); | |||
| } | |||
| else if (type.MsgType == MsgType.事件) | |||
| { | |||
| obj = XmlUtil.Deserialize<QRCodeMessage>(xmlData); | |||
| } | |||
| return obj; | |||
| } | |||
| /// <summary> | |||
| /// 验证微信签名 | |||
| /// </summary> | |||
| /// <returns></returns> | |||
| /// * 将token、timestamp、nonce三个参数进行字典序排序 | |||
| /// * 将三个参数字符串拼接成一个字符串进行sha1加密 | |||
| /// * 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信。 | |||
| public static bool CheckSignature() | |||
| { | |||
| string WeChat_Token = config.Token;//从配置文件获取Token | |||
| string WeChat_Key = HttpContext.Current.Request.QueryString["key"]; | |||
| //从微信服务器接收传递过来的数据 | |||
| string signature = HttpContext.Current.Request.QueryString["signature"]; //微信加密签名 | |||
| string timestamp = HttpContext.Current.Request.QueryString["timestamp"];//时间戳 | |||
| string nonce = HttpContext.Current.Request.QueryString["nonce"];//随机数 | |||
| string[] ArrTmp = { WeChat_Token, timestamp, nonce }; | |||
| Array.Sort(ArrTmp); //字典排序 | |||
| string tmpStr = string.Join("", ArrTmp);//将三个字符串组成一个字符串 | |||
| tmpStr = FormsAuthentication.HashPasswordForStoringInConfigFile(tmpStr, "SHA1");//进行sha1加密 | |||
| tmpStr = tmpStr.ToLower(); | |||
| //加过密的字符串与微信发送的signature进行比较,一样则通过微信验证,否则失败。 | |||
| if (tmpStr == signature) | |||
| { | |||
| return true; | |||
| } | |||
| else | |||
| { | |||
| return false; | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// 生成临时二维码 | |||
| /// </summary> | |||
| /// <param name="days">二维码有效时间</param> | |||
| /// <param name="arg">二维码参数</param> | |||
| /// <returns></returns> | |||
| public static string GenerateEQCode(int days, int arg) | |||
| { | |||
| string ticket = string.Empty; | |||
| string uriStr = string.Format("https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token={0}", TOKEN); | |||
| JavaScriptSerializer jsonHelper = new JavaScriptSerializer(); | |||
| QRCodeResult result = new QRCodeResult(); | |||
| QRCodeArgs body = new QRCodeArgs() | |||
| { | |||
| expire_seconds = 60 * 60 * 24 * days, | |||
| action_name = "QR_SCENE", | |||
| action_info = new QRCodeScene() | |||
| { | |||
| scene = new QRCodeSceneID() | |||
| { | |||
| scene_id = arg | |||
| } | |||
| } | |||
| }; | |||
| string postData = jsonHelper.Serialize(body); | |||
| string data = string.Empty; | |||
| try | |||
| { | |||
| byte[] byteArray = Encoding.UTF8.GetBytes(postData); | |||
| HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(new Uri(uriStr)); | |||
| webRequest.Method = "post"; | |||
| webRequest.ContentType = "application/x-www-form-urlencoded"; | |||
| webRequest.ContentLength = byteArray.Length; | |||
| System.IO.Stream newStream = webRequest.GetRequestStream(); | |||
| newStream.Write(byteArray, 0, byteArray.Length); | |||
| newStream.Close(); | |||
| HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse(); | |||
| data = new System.IO.StreamReader(response.GetResponseStream(), Encoding.GetEncoding("utf-8")).ReadToEnd(); | |||
| result = jsonHelper.Deserialize<QRCodeResult>(data); | |||
| } | |||
| catch (Exception e) | |||
| { | |||
| throw e; | |||
| } | |||
| if (result != null && !string.IsNullOrEmpty(result.ticket)) | |||
| { | |||
| ticket = result.ticket; | |||
| } | |||
| return ticket; | |||
| } | |||
| /// <summary> | |||
| /// 获取二维码图片 | |||
| /// </summary> | |||
| /// <param name="ticket">票据</param> | |||
| /// <param name="path">图片保存路径</param> | |||
| /// <returns></returns> | |||
| public static void GetQRPic(string ticket, string path) | |||
| { | |||
| string uriStr = string.Format("https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket={0}", ticket); | |||
| try | |||
| { | |||
| WebClient webClient = new WebClient(); | |||
| webClient.DownloadFile(uriStr, path); | |||
| } | |||
| catch (Exception e) | |||
| { | |||
| throw e; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,30 @@ | |||
| using BWP.B3WeChat.Entities; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| namespace BWP.B3WeChat.Utils | |||
| { | |||
| public static class SendMessageUtil | |||
| { | |||
| /// <summary> | |||
| /// 发送代办信息 | |||
| /// </summary> | |||
| /// <param name="openid"></param> | |||
| /// <param name="title">题目</param> | |||
| /// <param name="todeal">事项</param> | |||
| /// <param name="delay">未处理时间</param> | |||
| /// <param name="remark">备注</param> | |||
| /// <returns></returns> | |||
| public static SendTemplateMessageResult SendAgentInfo(string openid, string title, string todeal, string delay, string remark) | |||
| { | |||
| Dictionary<string, ValueColor> dic = new Dictionary<string, ValueColor>(); | |||
| dic.Add("first", new ValueColor() { value = title, color = "#173177" }); | |||
| dic.Add("keyword1", new ValueColor() { value = todeal, color = "#173177" }); | |||
| dic.Add("keyword2", new ValueColor() { value = delay, color = "#173177" }); | |||
| dic.Add("remark", new ValueColor() { value = remark, color = "#173177" }); | |||
| return InOutMessageUtil.SendTemplateMessage(openid, "uhy7GuF8zwBA6pjvjQWpn02fiKb0o9cq7dO5DWnUuMg", dic); | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,97 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.IO; | |||
| using System.Linq; | |||
| using System.Web; | |||
| using System.Xml.Serialization; | |||
| namespace BWP.B3WeChat.Utils | |||
| { | |||
| /// <summary> | |||
| /// Xml序列化与反序列化 | |||
| /// </summary> | |||
| public class XmlUtil | |||
| { | |||
| #region 反序列化 | |||
| /// <summary> | |||
| /// 反序列化 | |||
| /// </summary> | |||
| /// <param name="type">类型</param> | |||
| /// <param name="xml">XML字符串</param> | |||
| /// <returns></returns> | |||
| public static object Deserialize(Type type, string xml) | |||
| { | |||
| try | |||
| { | |||
| using (StringReader sr = new StringReader(xml)) | |||
| { | |||
| XmlSerializer xmldes = new XmlSerializer(type); | |||
| return xmldes.Deserialize(sr); | |||
| } | |||
| } | |||
| catch (Exception e) | |||
| { | |||
| return null; | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// 反序列化 | |||
| /// </summary> | |||
| /// <param name="type"></param> | |||
| /// <param name="xml"></param> | |||
| /// <returns></returns> | |||
| public static object Deserialize(Type type, Stream stream) | |||
| { | |||
| XmlSerializer xmldes = new XmlSerializer(type); | |||
| return xmldes.Deserialize(stream); | |||
| } | |||
| /// <summary> | |||
| /// 反序列化 | |||
| /// </summary> | |||
| /// <typeparam name="T"></typeparam> | |||
| /// <param name="xml"></param> | |||
| /// <returns></returns> | |||
| public static T Deserialize<T>(string xml) where T : class | |||
| { | |||
| Type type = typeof(T); | |||
| return (Deserialize(type, xml) as T); | |||
| } | |||
| #endregion | |||
| #region 序列化 | |||
| /// <summary> | |||
| /// 序列化 | |||
| /// </summary> | |||
| /// <param name="type">类型</param> | |||
| /// <param name="obj">对象</param> | |||
| /// <returns></returns> | |||
| public static string Serializer(Type type, object obj) | |||
| { | |||
| MemoryStream Stream = new MemoryStream(); | |||
| XmlSerializer xml = new XmlSerializer(type); | |||
| XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces(); | |||
| namespaces.Add(string.Empty, string.Empty); | |||
| try | |||
| { | |||
| //序列化对象 | |||
| xml.Serialize(Stream, obj, namespaces); | |||
| } | |||
| catch (InvalidOperationException) | |||
| { | |||
| throw; | |||
| } | |||
| Stream.Position = 0; | |||
| StreamReader sr = new StreamReader(Stream); | |||
| string str = sr.ReadToEnd(); | |||
| sr.Dispose(); | |||
| Stream.Dispose(); | |||
| return str; | |||
| } | |||
| #endregion | |||
| } | |||
| } | |||