using CallCenter.Utility; using CallCenterAPI.WechatSDK.Models; using Senparc.Weixin; using Senparc.Weixin.MP; using Senparc.Weixin.MP.AdvancedAPIs; using Senparc.Weixin.MP.AdvancedAPIs.CustomService; using Senparc.Weixin.MP.CommonAPIs; using Senparc.Weixin.MP.TenPayLibV3; using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; using System.Net; using System.Net.Security; using System.Security.Cryptography.X509Certificates; using System.Text; using System.Web; using System.Xml.Linq; namespace CallCenterAPI.WechatSDK { public static class WxHelper { public static string WxId; public static string AppId; public static string AppSecret; public static string WechatMchid; public static string WechatKey; public static string WechatPath; public static string WechatClientIp; public static string WechatSendName; public static string WechatWishing; public static string WechatActName; public static string WechatRemark; public static string CommonToken;//Common的Token public static DateTime GetCommonTokenDate;//获取CommonToken的时间 public static int CommonTokenExpiresIn;//有效时间(s) static WxHelper() { AppId = Configs.GetValue("WechatAppid"); AppSecret = Configs.GetValue("WechatAppsecret"); WechatMchid= Configs.GetValue("WechatMchid"); WechatKey = Configs.GetValue("WechatKey"); WechatPath = Configs.GetValue("WechatPath"); WechatClientIp = Configs.GetValue("WechatClientIp"); WechatSendName = Configs.GetValue("WechatSendName"); WechatWishing = Configs.GetValue("WechatWishing"); WechatActName = Configs.GetValue("WechatActName"); WechatRemark = Configs.GetValue("WechatRemark"); } /// /// 获取openid /// /// /// public static WxLoginDto GetOpenId(WxLoginDto wxLoginDto) { if (string.IsNullOrWhiteSpace(wxLoginDto.Code)) { var url = OAuthApi.GetAuthorizeUrl(AppId, wxLoginDto.RedirectUrl, "qwertyuidfghjkl", OAuthScope.snsapi_base); wxLoginDto.RedirectUrl = url; return wxLoginDto; } var access = OAuthApi.GetAccessToken(AppId, AppSecret, wxLoginDto.Code); wxLoginDto.OpenId = access.openid; return wxLoginDto; } /// /// 获取common的token /// /// public static string GetCommonToken() { double ss = DateTime.Now.Subtract(GetCommonTokenDate).TotalSeconds; if (ss > CommonTokenExpiresIn) { var obj = CommonApi.GetToken(AppId, AppSecret); if (obj != null && obj.errcode == ReturnCode.请求成功) { GetCommonTokenDate = DateTime.Now.AddSeconds(-1); CommonTokenExpiresIn = obj.expires_in; CommonToken = obj.access_token; } else { CommonToken = ""; } } return CommonToken; } public static bool CheckSignature(string signature, string timestamp, string nonce, string token) { bool bl = false; string accesstoken = GetCommonToken(); if (accesstoken != "") { bl = Senparc.Weixin.MP.CheckSignature.Check(signature, timestamp, nonce, token); } return bl; } #region 多客服 /// /// 创建客服会话 /// /// /// public static bool CreateSession(string openid) { bool bl = false; string accesstoken = GetCommonToken(); if (accesstoken != "") { CustomApi.SendText(accesstoken, openid, "您好,正在为您接通人工客服,请稍候......"); var zxlist = CustomServiceApi.GetCustomOnlineInfo(accesstoken).kf_online_list;//在线客服列表 if (zxlist.Count > 0) { var kf = zxlist.OrderBy(p => p.accepted_case).FirstOrDefault();//获取当前已经接入用户最少的客服 if (kf != null) { var obj = CustomServiceApi.CreateSession(accesstoken, openid, kf.kf_account);//创建客服和用户之间的会话 if (obj.errcode == ReturnCode.请求成功) { bl = true; } else { CustomApi.SendText(accesstoken, openid, "接通人工客服异常,请重试"); } } else { CustomApi.SendText(accesstoken, openid, "人工客服正在忙碌中,请稍候联系"); } } } return bl; } /// /// 关闭客服会话 /// /// /// public static bool CloseSession(string openid, string kf_account) { bool bl = false; string accesstoken = GetCommonToken(); if (accesstoken != "") { var obj = CustomServiceApi.CloseSession(accesstoken, openid, kf_account); if (obj.errcode == ReturnCode.请求成功) { bl = true; CustomApi.SendText(accesstoken, openid, "已经关闭与人工客服的会话"); } else { CustomApi.SendText(accesstoken, openid, "关闭会话异常,请重试"); } } return bl; } /// /// 获取用户聊天记录 /// /// /// /// /// /// public static List GetRecord(DateTime stime, DateTime etime, int pageSize, int pageIndex) { List list = new List(); string accesstoken = GetCommonToken(); if (accesstoken != "") { var result = CustomServiceApi.GetRecord(accesstoken, stime, etime, pageSize, pageIndex); if (result.errcode == ReturnCode.请求成功) { list = result.recordlist.Select(p => { var binfo = CustomServiceApi.GetCustomBasicInfo(accesstoken).kf_list.Where(d => d.kf_account == p.worker).FirstOrDefault(); var uinfo = UserApi.Info(accesstoken, p.openid); return new { p.openid, p.opercode, p.text, p.worker, time = GetTime(p.time).ToString("yyyy-MM-dd HH:mm:ss"), receiver = p.opercode == Opercode.客服收到消息 ? binfo.kf_nick + "(客服)" : uinfo.nickname, sender = p.opercode == Opercode.客服发送消息 ? binfo.kf_nick + "(客服)" : uinfo.nickname }; }).ToList(); } } return list; } /// /// 获取聊天记录 /// /// /// /// /// /// public static List GetMsgList(DateTime stime, DateTime etime, long msgid, int number) { List list = new List(); string accesstoken = GetCommonToken(); if (accesstoken != "") { var result = CustomServiceApi.GetMsgList(accesstoken, stime, etime, msgid, number); if (result.errcode == ReturnCode.请求成功) { list = result.recordList.Select(p => new { p.openid, p.opercode, p.text, p.worker, time = p.time.ToString("yyyy-MM-dd HH:mm:ss"), name = UserApi.Info(accesstoken, p.openid).nickname, kfname = CustomServiceApi.GetCustomBasicInfo(accesstoken).kf_list.Where(d => d.kf_account == p.worker).FirstOrDefault().kf_nick }).ToList(); } } return list; } /// /// 获取时间 /// /// /// public static DateTime GetTime(double dt) { DateTime time = DateTime.MinValue; DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); time = startTime.AddSeconds(dt); return time; } #endregion #region 企业向用户发红包 public static string TenPay(decimal amount,string openid) { #region 发送红包 bool fals = false; //记录发送红包是否成功 string msg = ""; string xmlResult = null; //现金红包接口返回的xml string certPath = null; //证书在服务器的物理位置 string data = null; //调用现金红包接口需要的数据 string reeee = ""; try { //创建支付应答对象 CallCenter.Utility.RequestHandler packageReqHandler = new CallCenter.Utility.RequestHandler(null); //初始化 packageReqHandler.Init(); string nonceStr = TenPayV3Util.GetNoncestr(); //时间戳 //设置package订单参数 packageReqHandler.SetParameter("nonce_str", nonceStr); //随机字符串,不长于32位 var r = new Random(Guid.NewGuid().GetHashCode());//随机数 var dd = DateTime.Now.ToString("yyyymmdd");//日期yyyymmdd packageReqHandler.SetParameter("mch_billno", WechatMchid + dd+ r.Next(0, 10));//商户订单号(每个订单号必须唯一)组成:mch_id+yyyymmdd+10位一天内不能重复的数字。接口根据商户订单号支持重入,如出现超时可再调用。 packageReqHandler.SetParameter("mch_id", WechatMchid); //微信支付分配的商户号 packageReqHandler.SetParameter("wxappid", AppId);//微信分配的公众账号ID(企业号corpid即为此appId)。接口传入的所有appid应该为公众号的appid(在mp.weixin.qq.com申请的),不能为APP的appid(在open.weixin.qq.com申请的)。 packageReqHandler.SetParameter("send_name", WechatSendName);//商户名称 packageReqHandler.SetParameter("re_openid", openid); //用户openid 接受红包的用户用户在wxappid下的openid packageReqHandler.SetParameter("total_amount", Convert.ToInt32(amount * 100M).ToString(CultureInfo.InvariantCulture));//红包类型 packageReqHandler.SetParameter("total_num", "1");//红包发放总人数 packageReqHandler.SetParameter("wishing", WechatWishing); //红包祝福语 packageReqHandler.SetParameter("client_ip", WechatClientIp);//Ip地址 packageReqHandler.SetParameter("act_name", WechatActName); //活动名称 packageReqHandler.SetParameter("remark", WechatRemark); //备注 string sign = packageReqHandler.CreateMd5Sign("key", WechatKey); packageReqHandler.SetParameter("sign", sign); //签名:生成签名方式查看签名算法 data = packageReqHandler.ParseXML(); certPath = WechatPath; xmlResult = Sendredpack(data, WechatMchid, certPath); var res = XDocument.Parse(xmlResult); reeee = res.ToString(); string return_code = res.Element("xml").Element("return_code").Value; if ("SUCCESS".Equals(return_code)) { string result_code = res.Element("xml").Element("result_code").Value; if ("SUCCESS".Equals(result_code)) { fals = true; } else { msg += res.Element("xml").Element("err_code").Value + res.Element("xml").Element("err_code_des").Value; } } else { msg += res.Element("xml").Element("err_code").Value + res.Element("xml").Element("err_code_des").Value; } } catch (Exception exception) { msg += exception.Message; } #endregion return fals.ToString() + "|" + msg; } /// /// 用于企业向微信用户个人发红包 /// 目前支持向指定微信用户的openid个人发红包 /// /// apiclient_cert.p12证书密码即商户号 /// 微信支付需要post的xml数据 /// apiclient_cert.p12的证书物理位置(例如:E:\projects\文档\微信商户平台证书\商户平台API证书 /// /// public static string Sendredpack(string data, string certPassword, string certPath, int timeOut = Config.TIME_OUT) { var urlFormat = "https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack"; string cert = HttpContext.Current.Request.PhysicalApplicationPath+ certPath; ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult); X509Certificate2 cer = new X509Certificate2(cert, certPassword, X509KeyStorageFlags.MachineKeySet); var formDataBytes = data == null ? new byte[0] : Encoding.UTF8.GetBytes(data); MemoryStream ms = new MemoryStream(); ms.Write(formDataBytes, 0, formDataBytes.Length); ms.Seek(0, SeekOrigin.Begin);//设置指针读取位置 HttpWebRequest request = (HttpWebRequest)WebRequest.Create(urlFormat); request.ClientCertificates.Add(cer); request.Method = "POST"; request.Timeout = timeOut; request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36"; #region 输入二进制流 if (ms != null) { ms.Position = 0; //直接写入流 Stream requestStream = request.GetRequestStream(); byte[] buffer = new byte[1024]; int bytesRead = 0; while ((bytesRead = ms.Read(buffer, 0, buffer.Length)) != 0) { requestStream.Write(buffer, 0, bytesRead); } ms.Close();//关闭文件访问 } #endregion HttpWebResponse response = (HttpWebResponse)request.GetResponse(); using (Stream responseStream = response.GetResponseStream()) { using (StreamReader myStreamReader = new StreamReader(responseStream, Encoding.GetEncoding("utf-8"))) { string retString = myStreamReader.ReadToEnd(); return retString; } } } private static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors) { if (errors == SslPolicyErrors.None) return true; return false; } #endregion } }