首页 > 其他分享 >关注微信公众号推送消息

关注微信公众号推送消息

时间:2023-08-28 09:22:05浏览次数:49  
标签:return string int 微信 公众 var new 推送 public

微信关注二维码的主要开发思路:

第一步,向用户展示要扫的二维码:通过提前申请的appid和秘钥去拿token,通过token再去微信服务上拿要关注的图片二维码,将二维码展示在你系统中。

第二步,用户扫码: 用户扫码时会向微信发信息,并且微信会回调你的自己的服务,需要你将关注的用户信息保存下来; 

第三步,给用户发送信息:通过用户标识,找到第二步中保存下来的用户,给微信接口发指定的模版信息,关注的用户会接收到信息,并且会回调我们的服务。

一、获取微信关注二维码

1、在获取二维码之前要通过企业申请的appid和秘钥拿到token

 /// <summary>
        /// 获得微信AccessToken
        /// </summary>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpGet("GetAccessToken")]
        public string GetAccessToken()
        {
            return _cache.GetOrCreate(CacheKeys.WeChatAccessToken, entry =>
            {
                string appId = HPDHttpContext.AppSettings.Value.WeChatOAConfig.AppID;
                string secret = HPDHttpContext.AppSettings.Value.WeChatOAConfig.AppSecret;
                string strUrl = string.Format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}", appId, secret);
                var token = HttpHelper.Get<WeChatToken>(strUrl);
                entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(token.expires_in - 180);
                return token.access_token;
            });
        }

2、在1中拿到token后用它获取二维码

 /// <summary>
        /// 获得微信关注二维码
        /// </summary>
        /// <returns>Base64字符串图片</returns>
        [AllowAnonymous]
        [HttpPost("GetWeChatFollowQRCode")]
        public string GetWeChatFollowQRCode(WeChatQRCodeRequest request)
        {
            string token = GetAccessToken();
            //创建二维码ticket
            string strUrl = string.Format("https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token={0}", token);
            var data = new
            {
                expire_seconds = 60,
                action_name = "QR_STR_SCENE",
                action_info = new
                {
                    scene = new
                    {
                        scene_str = JsonUtil.JsonSerializeObject(request)
                    }
                }
            };
            string result = HttpHelper.PostJson(strUrl, JsonUtil.JsonSerializeObject(data));
            var objResult = JsonConvert.DeserializeObject(result) as JObject;
            string ticket = (string)objResult["ticket"];
            //通过ticket换取二维码
            string qrCodeUrl = string.Format("https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket={0}", ticket);
            byte[] qrCode = HttpHelper.GetByte(qrCodeUrl);
            //using (FileStream fs = new FileStream("C:\\Users\\houzhipeng\\Desktop\\1.jpg", FileMode.Create, FileAccess.Write))
            //{
            //    fs.Write(qrCode, 0, qrCode.Length);
            //    fs.Flush();
            //    fs.Close();
            //}
            return Convert.ToBase64String(qrCode);
        }

3、获取到二维码图片后在页面上显示

$('#img').attr('src', `data:;base64,${url}`);

 

二、用户扫码

1、用户扫码后会回调我们自己开发的接口,我们将用户信息保存到自己开发的数据库中

 /// <summary>
        /// 接收微信消息
        /// </summary>
        [AllowAnonymous]
        [HttpPost("WeChatMessage")]
        public ActionResult WeChatMessage(string msg_signature, string signature, string timestamp, string nonce, string token = null)
        {
            token = HPDHttpContext.AppSettings.Value.WeChatOAConfig.Token;
            if (!CheckSignature.Check(signature, timestamp, nonce, token))
            {
                return Content("参数错误!");
            }
            try
            {
                string encodingAESKey = HPDHttpContext.AppSettings.Value.WeChatOAConfig.EncodingAESKey;
                string appId = HPDHttpContext.AppSettings.Value.WeChatOAConfig.AppID;
                string content = "";

                using (StreamReader reader = new StreamReader(HttpContext.Request.Body))
                {
                    string s = reader.ReadToEndAsync().Result;
                    using (MemoryStream memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(s)))
                    {
                        content = Encoding.UTF8.GetString(memoryStream.ToArray());
                    }
                }
                LogUtil.WriteLog(content);
                XmlDocument document = new XmlDocument();
                if (!string.IsNullOrWhiteSpace(msg_signature)) // 消息加密模式
                {
                    string decryptMsg = string.Empty;
                    var wxBizMsgCrypt = new WXBizMsgCrypt(token, encodingAESKey, appId);
                    int decryptResult = wxBizMsgCrypt.DecryptMsg(msg_signature, timestamp, nonce, content, ref decryptMsg);
                    if (decryptResult == 0 && !string.IsNullOrWhiteSpace(decryptMsg))
                    {
                        LogUtil.WriteLog(decryptMsg);
                        document.LoadXml(decryptMsg);
                        var messageProcess = CommonMessageFactory.CreateMessageProcess(document);
                        string returnResult = messageProcess.ExecuteResult();
                        LogUtil.WriteLog(returnResult);
                        return Content(returnResult);
                    }
                }
                else // 消息未加密处理
                {
                    document.LoadXml(content);
                    var messageProcess = CommonMessageFactory.CreateMessageProcess(document);
                    string returnResult = messageProcess.ExecuteResult();
                    return Content(returnResult);
                }
            }
            catch (Exception ex)
            {
                LogUtil.WriteLog("接收消息并处理和返回相应结果异常:" + ex);
            }
            return Content("");
        }

在注册微信公众号时还会要求有一个可以调通的服务,从而验证服务器配置是否正常,代码如下:

 /// <summary>
        /// 服务器配置验证
        /// </summary>
        /// <param name="signature"></param>
        /// <param name="timestamp"></param>
        /// <param name="nonce"></param>
        /// <param name="echostr"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpGet("WeChatMessage")]
        public ActionResult WeChatMessage(string signature, string timestamp, string nonce, string echostr)
        {
            string token = HPDHttpContext.AppSettings.Value.WeChatOAConfig.Token;
            if (CheckSignature.Check(signature, timestamp, nonce, token))
            {
                return Content(echostr); //返回随机字符串则表示验证通过
            }
            else
            {
                return Content("");
            }
        }

 

 

2、获取微信消息的相关方法中的类

检查签名:

 public class CheckSignature
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="signature"></param>
        /// <param name="timestamp"></param>
        /// <param name="nonce"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        public static bool Check(string signature, string timestamp, string nonce, string token)
        {
            return signature == GetSignature(timestamp, nonce, token);
        }

        /// <summary>
        /// 返回正确的签名
        /// </summary>
        /// <param name="timestamp"></param>
        /// <param name="nonce"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        public static string GetSignature(string timestamp, string nonce, string token)
        {
            var arr = new[] { token, timestamp, nonce }.OrderBy(z => z).ToArray();
            var arrString = string.Join("", arr);
            //var enText = FormsAuthentication.HashPasswordForStoringInConfigFile(arrString, "SHA1");//使用System.Web.Security程序集
            var sha1 = SHA1.Create();
            var sha1Arr = sha1.ComputeHash(Encoding.UTF8.GetBytes(arrString));
            StringBuilder enText = new StringBuilder();
            foreach (var b in sha1Arr)
            {
                enText.AppendFormat("{0:x2}", b);
            }
            return enText.ToString();
        }
    }

加密:

 public class WXBizMsgCrypt
    {
        string m_sToken;
        string m_sEncodingAESKey;
        string m_sAppID;
        enum WXBizMsgCryptErrorCode
        {
            WXBizMsgCrypt_OK = 0,
            WXBizMsgCrypt_ValidateSignature_Error = -40001,
            WXBizMsgCrypt_ParseXml_Error = -40002,
            WXBizMsgCrypt_ComputeSignature_Error = -40003,
            WXBizMsgCrypt_IllegalAesKey = -40004,
            WXBizMsgCrypt_ValidateAppid_Error = -40005,
            WXBizMsgCrypt_EncryptAES_Error = -40006,
            WXBizMsgCrypt_DecryptAES_Error = -40007,
            WXBizMsgCrypt_IllegalBuffer = -40008,
            WXBizMsgCrypt_EncodeBase64_Error = -40009,
            WXBizMsgCrypt_DecodeBase64_Error = -40010
        };

        //构造函数
        // @param sToken: 公众平台上,开发者设置的Token
        // @param sEncodingAESKey: 公众平台上,开发者设置的EncodingAESKey
        // @param sAppID: 公众帐号的appid
        public WXBizMsgCrypt(string sToken, string sEncodingAESKey, string sAppID)
        {
            m_sToken = sToken;
            m_sAppID = sAppID;
            m_sEncodingAESKey = sEncodingAESKey;
        }


        // 检验消息的真实性,并且获取解密后的明文
        // @param sMsgSignature: 签名串,对应URL参数的msg_signature
        // @param sTimeStamp: 时间戳,对应URL参数的timestamp
        // @param sNonce: 随机串,对应URL参数的nonce
        // @param sPostData: 密文,对应POST请求的数据
        // @param sMsg: 解密后的原文,当return返回0时有效
        // @return: 成功0,失败返回对应的错误码
        public int DecryptMsg(string sMsgSignature, string sTimeStamp, string sNonce, string sPostData, ref string sMsg)
        {
            if (m_sEncodingAESKey.Length!=43)
            {
                return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_IllegalAesKey;
            }
            XmlDocument doc = new XmlDocument();
            XmlNode root;
            string sEncryptMsg;
            try
            {
                doc.LoadXml(sPostData);
                root = doc.FirstChild;
                sEncryptMsg = root["Encrypt"].InnerText;
            }
            catch (Exception)
            {
                return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_ParseXml_Error;
            }
            //verify signature
            int ret = 0;
            ret = VerifySignature(m_sToken, sTimeStamp, sNonce, sEncryptMsg, sMsgSignature);
            if (ret != 0)
                return ret;
            //decrypt
            string cpid = "";
            try
            {
                sMsg = Cryptography.AES_decrypt(sEncryptMsg, m_sEncodingAESKey, ref cpid);
            }
            catch (FormatException)
            {
                return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_DecodeBase64_Error;
            }
            catch (Exception)
            {
                return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_DecryptAES_Error;
            }
            if (cpid != m_sAppID)
                return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_ValidateAppid_Error;
            return 0;
        }

        //将企业号回复用户的消息加密打包
        // @param sReplyMsg: 企业号待回复用户的消息,xml格式的字符串
        // @param sTimeStamp: 时间戳,可以自己生成,也可以用URL参数的timestamp
        // @param sNonce: 随机串,可以自己生成,也可以用URL参数的nonce
        // @param sEncryptMsg: 加密后的可以直接回复用户的密文,包括msg_signature, timestamp, nonce, encrypt的xml格式的字符串,
        //                        当return返回0时有效
        // return:成功0,失败返回对应的错误码
        public int EncryptMsg(string sReplyMsg, string sTimeStamp, string sNonce, ref string sEncryptMsg)
        {
            if (m_sEncodingAESKey.Length!=43)
            {
                return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_IllegalAesKey;
            }
            string raw = "";
            try
            {
                raw = Cryptography.AES_encrypt(sReplyMsg, m_sEncodingAESKey, m_sAppID);
            }
            catch (Exception)
            {
                return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_EncryptAES_Error;
            }
            string MsgSigature = "";
            int ret = 0;
            ret = GenarateSinature(m_sToken, sTimeStamp, sNonce, raw, ref MsgSigature);
            if (0 != ret)
                return ret;
            sEncryptMsg = "";

            string EncryptLabelHead = "<Encrypt><![CDATA[";
            string EncryptLabelTail = "]]></Encrypt>";
            string MsgSigLabelHead = "<MsgSignature><![CDATA[";
            string MsgSigLabelTail = "]]></MsgSignature>";
            string TimeStampLabelHead = "<TimeStamp><![CDATA[";
            string TimeStampLabelTail = "]]></TimeStamp>";
            string NonceLabelHead = "<Nonce><![CDATA[";
            string NonceLabelTail = "]]></Nonce>";
            sEncryptMsg = sEncryptMsg + "<xml>" + EncryptLabelHead + raw + EncryptLabelTail;
            sEncryptMsg = sEncryptMsg + MsgSigLabelHead + MsgSigature + MsgSigLabelTail;
            sEncryptMsg = sEncryptMsg + TimeStampLabelHead + sTimeStamp + TimeStampLabelTail;
            sEncryptMsg = sEncryptMsg + NonceLabelHead + sNonce + NonceLabelTail;
            sEncryptMsg += "</xml>";
            return 0;
        }

        public class DictionarySort : System.Collections.IComparer
        {
            public int Compare(object oLeft, object oRight)
            {
                string sLeft = oLeft as string;
                string sRight = oRight as string;
                int iLeftLength = sLeft.Length;
                int iRightLength = sRight.Length;
                int index = 0;
                while (index < iLeftLength && index < iRightLength)
                {
                    if (sLeft[index] < sRight[index])
                        return -1;
                    else if (sLeft[index] > sRight[index])
                        return 1;
                    else
                        index++;
                }
                return iLeftLength - iRightLength;

            }
        }
        //Verify Signature
        private static int VerifySignature(string sToken, string sTimeStamp, string sNonce, string sMsgEncrypt, string sSigture)
        {
            string hash = "";
            int ret = 0;
            ret = GenarateSinature(sToken, sTimeStamp, sNonce, sMsgEncrypt, ref hash);
            if (ret != 0)
                return ret;
            //System.Console.WriteLine(hash);
            if (hash == sSigture)
                return 0;
            else
            {
                return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_ValidateSignature_Error;
            }
        }

        public static int GenarateSinature(string sToken, string sTimeStamp, string sNonce, string sMsgEncrypt ,ref string sMsgSignature)
        {
            ArrayList AL = new ArrayList();
            AL.Add(sToken);
            AL.Add(sTimeStamp);
            AL.Add(sNonce);
            AL.Add(sMsgEncrypt);
            AL.Sort(new DictionarySort());
            string raw = "";
            for (int i = 0; i < AL.Count; ++i)
            {
                raw += AL[i];
            }

            SHA1 sha;
            ASCIIEncoding enc;
            string hash = "";
            try
            {
                sha = new SHA1CryptoServiceProvider();
                enc = new ASCIIEncoding();
                byte[] dataToHash = enc.GetBytes(raw);
                byte[] dataHashed = sha.ComputeHash(dataToHash);
                hash = BitConverter.ToString(dataHashed).Replace("-", "");
                hash = hash.ToLower();
            }
            catch (Exception)
            {
                return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_ComputeSignature_Error;
            }
            sMsgSignature = hash;
            return 0;
        }
    }

消息处理工厂类

public class CommonMessageFactory
    {
        public static ICommonMessageProcess CreateMessageProcess(XmlDocument document)
        {
            if (document == null)
                return null;
            ICommonMessageProcess messageProcess = null;
            XmlElement rootElement = document.DocumentElement;
            string msgType = rootElement.SelectSingleNode("MsgType").InnerText;
            switch (msgType)
            {
                case "text":
                    messageProcess = new TextMessageProcess();
                    break;
                case "image":
                    break;
                case "voice":
                    break;
                case "video":
                    break;
                case "shortvideo":
                    break;
                case "location":
                    break;
                case "link":
                    break;
                case "event":
                    switch (rootElement.SelectSingleNode("Event").InnerText)
                    {
                        case "subscribe":
                            messageProcess = new SubscribeMessageProcess(document.InnerXml);
                            break;
                        case "unsubscribe":
                            break;
                        case "SCAN":
                            messageProcess = new ScanMessageProcess(document.InnerXml);
                            break;
                        case "LOCATION":
                            break;
                        case "CLICK":
                            break;
                        case "VIEW":
                            break;
                        case "TEMPLATESENDJOBFINISH":
                            messageProcess = new TemplateSendResultMessageProcess(document.InnerXml);
                            break;
                        default:
                            break;
                    }
                    break;
                default:
                    //result = "没有识别的类型消息:" + xmlElement.SelectSingleNode("MsgType").InnerText;
                    //WriteLog(result);
                    break;
             }
            return messageProcess;
        }
    }

在消息处理工厂类中有一个非常重要的子类就是扫码后回调的信息处理类:ScanMessageProcess,在此类中可以看到,当我们扫码后信息保存到数据库中

public class ScanMessageProcess : ICommonMessageProcess
    {
        private SubscribeOrScanXmlModel _scanXmlModel;

        public ScanMessageProcess(string xmlString)
        {
            _scanXmlModel = XmlUtil.XmlDeserialize<SubscribeOrScanXmlModel>(xmlString);
        }

        public string ExecuteResult()
        {
            var qrCodeParam = JsonUtil.JsonDeserialize<WeChatQRCodeRequest>(_scanXmlModel.EventKey);

            string content = "";
            var msgInfo = ComUserUtil.SaveUserInfo(_scanXmlModel, qrCodeParam);
            if (msgInfo.State)
            {
                //content = "扫码成功!场景值:" + _scanXmlModel.EventKey + ",OPEN_ID:" + _scanXmlModel.FromUserName;
                content = "扫码成功!我们将及时为您推送订单,证照等消息。";
            }
            else
            {
                content = "扫码失败!场景值:" + _scanXmlModel.EventKey + "  " + msgInfo.Message;
            }

            TextXml xml = new TextXml();
            xml.FromUserName = _scanXmlModel.ToUserName;
            xml.ToUserName = _scanXmlModel.FromUserName;
            xml.CreateTime = DateTime.Now.Ticks;
            xml.Content = content;
            string xmlString = xml.ToXml();
            return xmlString;
        }
    }

另外,有一个发送信息后的回调类:TemplateSendResultMessageProcess

public class TemplateSendResultMessageProcess : ICommonMessageProcess
    {
        TemplateSendResultXmlModel _xmlModel = null;
        public TemplateSendResultMessageProcess(string xmlString)
        {
            _xmlModel = XmlUtil.XmlDeserialize<TemplateSendResultXmlModel>(xmlString);
        }

        public string ExecuteResult()
        {
            var msgInfo = ComMessageUtil.UpdateWeChatMPMessageState(_xmlModel.MsgID, _xmlModel.Status);
            //调用通知接口

            if (_xmlModel.Status == "success")
            {
                return "OK";
            }
            else 
            {
                
            }
            return "NO";
        }
    }
 [XmlRoot(ElementName = "xml")]
    public class TemplateSendResultXmlModel : BaseRequestXml
    {
        public string Event { get; set; }
        public string MsgID { get; set; }
        public string Status { get; set; }
    }

扫码还可能回调的事件,对应的处理类是:SubscribeMessageProcess

/// <summary>
    /// 用户扫码关注消息处理
    /// </summary>
    public class SubscribeMessageProcess : ICommonMessageProcess
    {
        private SubscribeOrScanXmlModel _scanXmlModel;

        public SubscribeMessageProcess(string xmlString)
        {
            _scanXmlModel = XmlUtil.XmlDeserialize<SubscribeOrScanXmlModel>(xmlString);
        }

        public string ExecuteResult()
        {
            if (_scanXmlModel.EventKey.StartsWith("qrscene_"))
            {
                _scanXmlModel.EventKey = _scanXmlModel.EventKey.Substring(8);
            }
            var qrCodeParam = JsonUtil.JsonDeserialize<WeChatQRCodeRequest>(_scanXmlModel.EventKey);
            string content = "";
            var msgInfo = ComUserUtil.SaveUserInfo(_scanXmlModel, qrCodeParam);
            if (msgInfo.State)
            {
                //content = "关注成功!场景值:" + _scanXmlModel.EventKey;

                content = "感谢您的关注!我们将及时为您推送订单,证照等消息。";
            }
            else
            {
                content = "关注失败!场景值:" + _scanXmlModel.EventKey + "  " + msgInfo.Message;
            }
            TextXml xml = new TextXml();
            xml.FromUserName = _scanXmlModel.ToUserName;
            xml.ToUserName = _scanXmlModel.FromUserName;
            xml.CreateTime = DateTime.Now.Ticks;
            xml.Content = content;
            string xmlString = xml.ToXml();
            return xmlString;
        }
    }

xml处理工具类:xmlUtil

 public class XmlUtil
    {
        /// <summary>
        /// 对象转换为XML
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static string XmlSerialize<T>(T obj)
        {
            try
            {
                XmlSerializer ser = new XmlSerializer(obj.GetType());
                MemoryStream ms = new MemoryStream();
                ser.Serialize(ms, obj);
                ms.Close();
                return Encoding.UTF8.GetString(ms.ToArray());
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 转换XML为对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="xmlString"></param>
        /// <returns></returns>
        public static T XmlDeserialize<T>(string xmlString)
        {
            try
            {
                XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
                Stream xmlStream = new MemoryStream(Encoding.UTF8.GetBytes(xmlString));
                XmlReader xmlReader = XmlReader.Create(xmlStream);
                Object obj = xmlSerializer.Deserialize(xmlReader);

                xmlReader.Close();
                xmlStream.Close();
                return (T)obj;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
    }

json处理工具类:

 public static class JsonUtil
    {
        /// <summary>
        /// 使用Newtonsoft.Json序列化对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static string JsonSerializeObject(object obj)
        {
            return Newtonsoft.Json.JsonConvert.SerializeObject(obj);
        }

        /// <summary>
        /// 使用Newtonsoft.Json反序列化对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="text"></param>
        /// <returns></returns>
        public static List<T> JsonDeserializeList<T>(string text)
        {
            return Newtonsoft.Json.JsonConvert.DeserializeObject<List<T>>(text);
        }
        /// <summary>
        /// 使用Newtonsoft.Json反序列化对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="text"></param>
        /// <returns></returns>
        public static T JsonDeserialize<T>(string text)
        {
            return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(text);
        }
        
        /// <summary>
        /// 读取JSON文件
        /// </summary>
        /// <param name="key">JSON文件中的key值</param>
        /// <returns>JSON文件中的value值</returns>
        public static string ReadJsonFile(string jsonPath, string key)
        {
            if (!File.Exists(jsonPath))
                throw new Exception(jsonPath + "未找到文件!");
            using (StreamReader file = File.OpenText(jsonPath))
            {
                using (Newtonsoft.Json.JsonTextReader reader = new Newtonsoft.Json.JsonTextReader(file))
                {
                    Newtonsoft.Json.Linq.JObject o = (Newtonsoft.Json.Linq.JObject)Newtonsoft.Json.Linq.JToken.ReadFrom(reader);
                    var value = o[key].ToString();
                    return value;
                }
            }
        }
        /// <summary>
        /// 读取JSON文件
        /// </summary>
        /// <param name="jsonPath"></param>
        /// <returns></returns>
        public static string ReadJsonFile(string jsonPath)
        {
            if (!File.Exists(jsonPath))
                throw new Exception(jsonPath + "未找到文件!");
            string strJson = "";
            using (StreamReader file = File.OpenText(jsonPath))
            {
                strJson = file.ReadToEnd();
            }
            return strJson;
        }
    }

 

三、向用户发送模版消息

/// <summary>
        /// 发送模板消息
        /// </summary>
        /// <param name="requestParam"></param>
        [HttpPost("SendWeChatMPTemplateMessage")]
        public string SendWeChatMPTemplateMessage(WeChatTemplateMessageRequest requestParam)
        {
            BaseResponse response = new BaseResponse();
            var msgInfo = RequestHelper.NotnullValidate<WeChatTemplateMessageRequest>(requestParam);
            if (!msgInfo.State)
            {
                response.ResultCode = "-1";
                response.ResultMessage = msgInfo.Message;
                return JsonUtil.JsonSerializeObject(response);
            }



            const string WeChatHttpUrl = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token={0}";
            string token = GetAccessToken();

            string templateId = string.Empty;
            if (!string.IsNullOrEmpty(requestParam.TemplateId))
            {
                templateId = requestParam.TemplateId;
            }
            else
            {
                templateId = GetTemplateId(requestParam.TemplateType);
            }

            string openId = requestParam.OpenId;
            if (string.IsNullOrEmpty(openId))
            {
                var dataAccess = JZTHttpContext.DataAccess;
                var user = dataAccess.GetByParam<COM_USER>(new { ORGAN_ID = requestParam.OrganId, USER_ID = requestParam.UserId });
                if (user == null)
                {
                    response.ResultCode = "-1";
                    response.ResultMessage = "无此用户";
                    return JsonUtil.JsonSerializeObject(response);
                }
                openId = user.OPEN_ID;
            }

            Data data = new Data();
            data.first = new First() { value = requestParam.First };
            data.keyword1 = new Keyword1 { value = requestParam.Keyword1 };
            data.keyword2 = new Keyword2 { value = requestParam.Keyword2 };
            data.keyword3 = new Keyword3 { value = requestParam.Keyword3 };
            data.keyword4 = new Keyword4 { value = requestParam.Keyword4 };
            data.keyword5 = new Keyword5 { value = requestParam.Keyword5 };
            data.remark = new Remark { value = requestParam.Remark };

            TemplateMessageModel messageModel = new TemplateMessageModel();
            messageModel.touser = openId;
            messageModel.template_id = templateId;
            messageModel.url = requestParam.CallbackUrl;
            messageModel.data = data;

            string jsonData = JsonUtil.JsonSerializeObject(messageModel);
            string url = string.Format(WeChatHttpUrl, token);
            string returnResult = HttpHelper.PostJson(url, jsonData);

            LogUtil.WriteLog(returnResult);

            var tmResponse = JsonUtil.JsonDeserialize<TemplateMessageResponse>(returnResult);
            if (tmResponse.errcode == "0")
            {
                msgInfo = ComMessageUtil.SaveWeChatMPMessage(requestParam, tmResponse.msgid);
                if (!msgInfo.State)
                {
                    response.ResultCode = "-1";
                    response.ResultMessage = msgInfo.Message;
                }
            }
            else
            {
                response.ResultCode = "-1";
                response.ResultMessage = tmResponse.errmsg;
            }
            return JsonUtil.JsonSerializeObject(response);
        }
 private string GetTemplateId(int messageType)
        {
            string templateId = "";
            switch (messageType)
            {
                case (int)模板消息类型.关注消息:
                    templateId = HPDHttpContext.AppSettings.Value.WeChatOAConfig.GZTemplateId;
                    break;
                case (int)模板消息类型.扫码消息:
                    templateId = HPDHttpContext.AppSettings.Value.WeChatOAConfig.SMTemplateId;
                    break;
                case (int)模板消息类型.证照到期提醒:
                    templateId = HPDHttpContext.AppSettings.Value.WeChatOAConfig.ZZDQTemplateId;
                    break;
                case (int)模板消息类型.订单生成通知:
                    templateId = HPDHttpContext.AppSettings.Value.WeChatOAConfig.DDSCTemplateId;
                    break;
                case (int)模板消息类型.订单确认通知:
                    templateId = HPDHttpContext.AppSettings.Value.WeChatOAConfig.DDQRTemplateId;
                    break;
                case (int)模板消息类型.单据审核结果通知:
                    templateId = HPDHttpContext.AppSettings.Value.WeChatOAConfig.DDSHTemplateId;
                    break;
                case (int)模板消息类型.订单配送提醒:
                    templateId = HPDHttpContext.AppSettings.Value.WeChatOAConfig.DDPSTemplateId;
                    break;
                default:
                    break;
            }
            return templateId;
        }

 

四、客户端的使用

 1、获取二维码

 /// <summary>
        /// 获取二维码
        /// </summary>
        /// <returns></returns>
        public async Task<ResponseResult<string>> GetQrcode()
        {
         
            var json = (new
            {
                organId = "CX2023071900000001C",
                userId = CurrentUser.Id,
            }).ToJson();
            var recordRes = await _commonSpeedHttpClient.PostAsync($"{_appSettingConfig.WeixinServiceUrl}GetWeChatFollowQRCode", json);
            return ResponseResult<string>.Success("ok", recordRes);

        }

2、发送模版消息

 /// <summary>
        /// 发送模板消息
        /// </summary>
        /// <returns></returns>
        [RemoteService(IsMetadataEnabled = true)]
        [HttpPost]
        public async Task<ResponseResult> SendTemplateMsg(SendTemplateMsgInput param)
        {
            if (param == null)
            {
                return ResponseResult.Fail("参数不能为空");
            }

     

            var templateId = EnumHelper.GetDisplayAttributeDescription(typeof(TemplateTypeEnum), param.TemplateType);
            if (string.IsNullOrEmpty(templateId))
            {
                _logger.LogInformation($"找不到对应的模板id");
                return ResponseResult<string>.Fail("找不到对应的模板id");
            }
            var messageId = Guid.NewGuid().ToString();
            var json = (new
            {
                OrganId = "CX2023071900000001C",
                TemplateId = templateId,
                UserId = param.UserId,
                MessageId = messageId,
                First = param.Data.ContainsKey("first") ? param.Data["first"] : string.Empty,
                Keyword1 = param.Data.ContainsKey("keyword1") ? param.Data["keyword1"] : string.Empty,
                Keyword2 = param.Data.ContainsKey("keyword2") ? param.Data["keyword2"] : string.Empty,
                Keyword3 = param.Data.ContainsKey("keyword3") ? param.Data["keyword3"] : string.Empty,
                Keyword4 = param.Data.ContainsKey("keyword4") ? param.Data["keyword4"] : string.Empty,
                Keyword5 = param.Data.ContainsKey("keyword5") ? param.Data["keyword5"] : string.Empty,
                Remark = param.Data.ContainsKey("remark") ? param.Data["remark"] : string.Empty,
            }).ToJson();

            _logger.LogInformation($"发送消息请求参数:{json}");

            var recordRes = await _commonSpeedHttpClient.PostAsync($"{_appSettingConfig.WeixinServiceUrl}SendWeChatMPTemplateMessage", json);
            _logger.LogInformation($"发送模板消息返回:{recordRes}");

            return ResponseResult.Success();

        }

模版枚举类:

 public enum TemplateTypeEnum
    {
        /// <summary>
        /// 新订单通知
        /// </summary>
        [Display(Name = "新订单通知", Description = "M81T0LJjYvT94OzCzEBALxUVOTt2tkHD-iInhmclabg")]
        OrderAuth = 1,
        /// <summary>
        /// 订单确认通知
        /// </summary>
        [Display(Name = "订单确认通知", Description = "upxpP6h1g6KWcOJ6IErnt9CpudwTDoL6c58Dc57RnvQ")]
        OrderConfirm = 2,
        

    }

枚举工具类:

/// <summary>
    /// 枚举帮助类
    /// </summary>
    public class EnumHelper
    {
        public static List<Type> EnumTypes = null;

        static EnumHelper()
        {
            EnumTypes = Assembly.GetExecutingAssembly().GetTypes().Where(p => p.BaseType == typeof(System.Enum)).ToList(); 
        }


        /// <summary>
        /// 通过枚举名称获取字典信息
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static List<EnumItem> GetEnumItemListByEnumName(string name)
        {
            var list = new List<EnumItem>();
            var lowerName = name.ToLower();
            if (!lowerName.EndsWith("enum"))
            {
                lowerName += "enum";
            }

            Type type = EnumTypes.FirstOrDefault(p => p.Name.ToLower() == lowerName || p.Name.ToLower() == name.ToLower());
            if (type == null)
            {
                throw new Exception("枚举类型不存在");
            }
        
            var members = type.GetMembers();

            foreach (var member in members)
            {
                DisplayAttribute attribute = Attribute.GetCustomAttribute(member, typeof(DisplayAttribute)) as DisplayAttribute;

                if (attribute != null)
                {
                    var returnValues = new EnumItem
                    {
                        Key = member.Name,
                        Value = Convert.ToInt32(System.Enum.Parse(type, member.Name)).ToString()
                    };

                    if (attribute.Name != null)
                    {
                        returnValues.Desc = attribute.Name;
                    }
                    else if (attribute.Description != null)
                    {
                        returnValues.Desc = attribute.Description;
                    }
                    else
                    {
                        returnValues.Desc = member.Name;
                    }

                    list.Add(returnValues);

                }
            }

            return list;
        }

        /// <summary>
        /// 通过枚举名称获取字典信息
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static Dictionary<string, string> GetEnumDataListByEnumName(string name)
        { 

            var lowerName = name.ToLower();
            if (!lowerName.EndsWith("enum"))
            {
                lowerName += "enum";
            }

            Type type = EnumTypes.FirstOrDefault(p => p.Name.ToLower() == lowerName || p.Name.ToLower() == name.ToLower());
            if (type == null)
            {
                throw new Exception("枚举类型不存在");
            }
            var dic = GetCommonEnumMembers(type);

            return dic;
        }

        public static Dictionary<string, string> GetCommonEnumMembers(Type type)
        {
            var returnValues = new Dictionary<string, string>();
            var members = type.GetMembers();

            foreach (var member in members)
            {
                DisplayAttribute attribute = Attribute.GetCustomAttribute(member, typeof(DisplayAttribute)) as DisplayAttribute;

                if (attribute != null)
                {
                    if (attribute.Name != null)
                    {
                        returnValues.Add(Convert.ToInt32(System.Enum.Parse(type, member.Name)).ToString(), attribute.Name);
                    }
                    else if (attribute.Description != null)
                    {
                        returnValues.Add(Convert.ToInt32(System.Enum.Parse(type, member.Name)).ToString(), attribute.Description);
                    }
                    else
                    {
                        returnValues.Add(Convert.ToInt32(System.Enum.Parse(type, member.Name)).ToString(), member.Name);
                    }
                    
                }
            }

            return returnValues;
        }

        /// <summary>
        /// 获取Display名
        /// </summary>
        /// <param name="type"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string GetDisplayAttributeName(Type type, object value)
        {

            string name = System.Enum.GetName(type, value);
            if (name == null)
            {
                return null;
            }
            FieldInfo field = type.GetField(name);
            DisplayAttribute attribute = Attribute.GetCustomAttribute(field, typeof(DisplayAttribute)) as DisplayAttribute;

            return attribute == null ? null : attribute.Name;
        }
        /// <summary>
        /// 获取display描述
        /// </summary>
        /// <param name="type"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string GetDisplayAttributeDescription(Type type, object value)
        {
            string name = System.Enum.GetName(type, value);
            if (name == null)
            {
                return null;
            }
            FieldInfo field = type.GetField(name);
            DisplayAttribute attribute = Attribute.GetCustomAttribute(field, typeof(DisplayAttribute)) as DisplayAttribute;

            return attribute == null ? null : attribute.Description;
        }

        /// <summary>
        /// 获取枚举字典信息
        /// key 枚举值 value 枚举DisPlay
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        static public Dictionary<string, string> GetEnumMembers(Type type)
        {
            var returnValues = new Dictionary<string, string>();
            var members = type.GetMembers();

            foreach (var member in members)
            {
                DisplayAttribute attribute = Attribute.GetCustomAttribute(member, typeof(DisplayAttribute)) as DisplayAttribute;

                if (attribute != null)
                {
                    returnValues.Add(Convert.ToInt32(System.Enum.Parse(type, member.Name)).ToString(), attribute.Name);
                }
            }

            return returnValues;
        }

        /// <summary>
        /// 获取枚举字典信息
        /// key 枚举值 value 枚举DisPlay
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        static public List<KeyValuePair<string, string>> GetEnumMembersKeyValuePair(Type type)
        {
            var returnValues = new List<KeyValuePair<string, string>>();
            var members = type.GetMembers();

            foreach (var member in members)
            {
                DisplayAttribute attribute = Attribute.GetCustomAttribute(member, typeof(DisplayAttribute)) as DisplayAttribute;

                if (attribute != null)
                {
                    returnValues.Add(new KeyValuePair<string, string>(Convert.ToInt32(System.Enum.Parse(type, member.Name)).ToString(), attribute.Name));
                }
            }

            return returnValues;
        }

        /// <summary>
        /// 获取枚举字典信息
        /// key 枚举值 value 枚举DisPlay
        /// </summary>
        /// <param name="type"></param>
        /// <param name="isShowAll">0:返回枚举类型,1:返回带全部都枚举类型</param>
        /// <returns></returns>
        static public Dictionary<string, string> GetEnumMembersList(Type type,int isShowAll=0)
        {
            var returnValues = new Dictionary<string, string>();
            if (isShowAll == 1)
            {
                returnValues.Add("0", "--请选择--");
            }
            var members = type.GetMembers();
            foreach (var member in members)
            {
                DisplayAttribute attribute = Attribute.GetCustomAttribute(member, typeof(DisplayAttribute)) as DisplayAttribute;

                if (attribute != null)
                {
                    returnValues.Add(Convert.ToInt32(System.Enum.Parse(type, member.Name)).ToString(), attribute.Name);
                }
            }
            return returnValues;
        }

        /// <summary>
        /// 获取枚举字典信息
        /// key 枚举属性名 value 枚举DisPlay
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        static public Dictionary<string, string> GetEnumKeyValuePair(Type type)
        {
            var returnValues = new Dictionary<string, string>();
            var members = type.GetMembers();

            foreach (var member in members)
            {
                DisplayAttribute attribute = Attribute.GetCustomAttribute(member, typeof(DisplayAttribute)) as DisplayAttribute;

                if (attribute != null)
                {
                    returnValues.Add(member.Name, attribute.Name);
                }
            }

            return returnValues;
        }

        /// <summary>
        /// 是否合法枚举
        /// </summary>
        /// <returns></returns>
        public static bool IsValidEnumValue(Type type, int value)
        {
            var list = GetEnumMembers(type);
            if (list != null && list.Any())
            {
                return list.ContainsKey(value.ToString());
            }
            return false;
        }


        /// <summary>
        /// 将枚举转为集合
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static List<EnumEntity> EnumToList<T>()
        {
            List<EnumEntity> list = new List<EnumEntity>();

            foreach (var e in System.Enum.GetValues(typeof(T)))
            {
                EnumEntity m = new EnumEntity();
                object[] objArr = e.GetType().GetField(e.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), true);
                if (objArr != null && objArr.Length > 0)
                {
                    DescriptionAttribute da = objArr[0] as DescriptionAttribute;
                    m.Desction = da.Description;
                }
                m.EnumValue = Convert.ToInt32(e);
                m.EnumName = e.ToString();
                list.Add(m);
            }
            return list;
        }


        /// <summary>
        /// 枚举实体
        /// </summary>
        public class EnumEntity
        {
            /// <summary>  
            /// 枚举的描述  
            /// </summary>  
            public string Desction { set; get; }

            /// <summary>  
            /// 枚举名称  
            /// </summary>  
            public string EnumName { set; get; }

            /// <summary>  
            /// 枚举对象的值  
            /// </summary>  
            public int EnumValue { set; get; }
        }

    }

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

标签:return,string,int,微信,公众,var,new,推送,public
From: https://www.cnblogs.com/zhengwei-cq/p/17575733.html

相关文章

  • 手把手教你如何实现企业微信Jenkins 构建发布通知
    一.前言在企业项目发版本过程中,以Jenkins为例,个别项目构建时间较长,不想时刻关注构建情况,或构建成功后移交其他人继续处理,需要配置企业微信通知功能,本篇主要是针对pipeline流水线项目,如何实现Jenkins构建成功与否通知到消息至企业微信指定人二.实现过程2.1企业微信创建机器人这里采......
  • 微信小程序 type="nickname" 点击后,获取不到最新值
    在uniapp开发微信小程序,或是使用小程序开发平台开发,会涉及到获取用户的头像和昵称,而在最新的微信小程序基础库,getUserInfo等不能在获取这些信息,官方推荐使用头像昵称填写能力(基础库2.21.2版本开始支持,覆盖iOS与安卓微信8.0.16以上版本),下面讲讲我在使用过程中遇到的问题。<bu......
  • vue微信H5项目使用腾讯地图获取当前位置经纬度
    1.在index.html引入js文件<scriptsrc="https://3gimg.qq.com/lightmap/components/geolocation/geolocation.min.js"></script>2.在需要页面中你自己的key要去腾讯地图工具去申请https://lbs.qq.com/webApi/component/componentGuide/componentPickercreated(){this.getM......
  • Winform微信扫码支付
    微信扫码支付引用的是第三方的:Senparc.Weixin引用:usingSenparc.Weixin.MP.TenPayLibV3;首先,在Form_Load里面调用生成支付二维码的方法:///<summary>///Form_Load事件///</summary>///<paramname="sender"></param>///<......
  • 微信开发之一键邀请好友加入群聊的技术实现
    邀请群成员(开启群验证)若群开启邀请确认,仅能通过本接口邀请群成员请求URL:http://域名/addChatRoomMemberVerify请求方式:POST请求头Headers:Content-Type:application/jsonAuthorization:login接口返回参数:参数名必选类型说明wId是String登录实例标识chatRoomId是String群iduserList是nu......
  • 微信开发之一键修改群聊备注的技术实现
    修改群备注修改群名备注后,如看到群备注未更改,是手机缓存问题,可以连续点击进入其他群,在点击进入修改的群,再返回即可看到修改后的群备注名,群名称的备注仅自己可见请求URL:http://域名地址/modifyGroupRemark请求方式:POST请求头Headers:Content-Type:application/jsonAuthorization:login......
  • 微信开发之一键修改群聊备注的技术实现
    修改群备注 修改群名备注后,如看到群备注未更改,是手机缓存问题,可以连续点击进入其他群,在点击进入修改的群,再返回即可看到修改后的群备注名,群名称的备注仅自己可见请求URL:http://域名地址/modifyGroupRemark请求方式:POST请求头Headers:Content-Type:application/json......
  • 微信开发之一键创建微信群聊的技术实现
    创建微信群本接口为敏感接口,请查阅调用规范手册创建后,手机上不会显示该群,往该群主动发条消息显示。请求URL:http://域名地址/createChatroom请求方式:POST请求头Headers:Content-Type:application/jsonAuthorization:login接口返回参数:参数名必选类型说明wId是String登录实例标识userLis......
  • 实现windows客户端微信多开
    实现windows客户端微信多开1、右键点击微信图标——属性——目标,复制下来2、右键——新建txt文件3、打开txt文件——输入以下内容:@echooffstart"""C:\ProgramFiles(x86)\Tencent\WeChat\WeChat.exe"start"""C:\ProgramFiles(x86)\Tencent\WeChat\WeCha......
  • c# WinForm--微信Native支付
    c#WinForm--微信Native支付 一、了解Native支付流程我用的是模式二,模式二的流程如下二、如何将Demo用在我的WinForm里面打开Demo工程,复制里面的lib、third文件夹到我的工程下,添加引用,引用的内容就是third文件夹里的。还有Demo里面的business文件夹,里面的代码可以参考(复......