C# MVC 微信支付之微信模板消息推送

微信支付之微信模板消息推送
 
        
        今天我要跟你們分享的是「模板消息」的推送,這玩意呢,你說用途嘛,那仍是真真的牛逼吶。緣由在哪?就是由於它是依賴微信生存的呀,因此他能不牛逼嗎?如今的社會,人多多少少都有或輕或重的「強迫症」。就是,看到有未讀消息,都要去看一下。特別是如今的微信,大部分能夠幾個小時不看手機QQ有沒有新消息來,可是這大部分人絕對作不到一個小時不看微信有沒有消息來。如今的微信,真特麼是神同樣的存在,幾乎人人手機上都會有微信。並且,若是你的公衆號是服務號的話,這個推送消息會顯示在首頁列表中(若是有新的消息,會把公衆號顯示在最頂端,並提示有新消息),不像訂閱好,會放在一個小盒子裏面。成熟的例子也有許多,例如一些商業銀行的刷卡消費提醒這些。好,這方面是他微信的優點,就是,you can't miss it.另一個優點就是:只要你給他推送了,他的到達率是很是的高,幾乎能夠保證,100%送達(鑑於天朝的相關法規,這種100%的東西,是沒人敢說的,因此,通常都和諧的說99.97%的樣子)。因此,以這樣的送達率,秒殺傳統的短信通知。更有甚者,就是,他的推送,徹底免費,徹底免費,徹底免費!並且,速度極快,速度極快,速度極快。。。好了,再說下去,估計等下大家覺得我是騰訊的員工了。好了,這些我就很少說了,下面,咱們進入主題吧。
 
        首先,新建一個MVC的項目,以下圖(在第二個頁面裏面,身份認證,改成不須要身份驗證):
 
 
        而後咱們去把官方demo(demo地址: https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1)中的business和lib拷貝到咱們的項目中,並新建一個文件夾WxLib,放到裏面去,以下圖:
 
 
        而後咱們再「從新生成」如下項目,或者快捷鍵:ctrl+shift+b,這時候,會提下以下錯誤:
 
 
這時候,咱們去添加引用,把 WxLib/ lib文件夾中的 LitJson.dll 添加上便可,以下圖:
 
 
 
到這裏,咱們就基本把官方的demo的環境給搭建好了,接下來,咱們就要開始編寫代碼了。
 
首先,咱們來看看官方文檔,怎麼介紹這個模板消息的,查看步驟(這個是須要登陸公衆平臺才能看到的),以下圖:
 
 
 
        經過API文檔,咱們得知,咱們推送模板消息,有三個必需要獲取到的參數,他們分別是: ACCESS_TOKEN和OPENID,以及template_id,
ACCESS_TOKEN和OPENID,咱們前面的額公衆號支付已經演示過如何獲取,若是忘了,能夠回頭看看( 微信支付教程系列之公衆號支付),
        
        下面,我來說講怎麼獲取這個template_id。template_id是模板消息的ID,咱們推送消息,不像咱們發短信同樣,能夠隨意編輯內容,想說啥就說啥,必需要符合模板消息的規則。例如,咱們此次選擇一個「賬戶資金變更提醒」,添加操做以下:
點擊」添加「以後,就會在」個人模板」裏面出現,以下圖:
 
 
這個「lypG1jYyOEfYsr*********jOK7-LhEwpPeVNHHxemSI」就是咱們的模板ID了,也就是:template_id。
 
        好,如今,咱們知道 ACCESS_TOKEN和OPENID以及template_id了,理論上,咱們就有了能夠發送推送消息的前提了。下面,咱們來進入代碼部分,以下:
 
 
        首先,新建一個HomeController.cs,代碼以下:
複製代碼
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace 微信支付之模板消息推送.Controllers
{
    public class HomeController : Controller
    {
        // GET: Home
        public ActionResult Index()
        {
            return View();
        }
    }
} 
複製代碼

 

 
 
        而後添加一個View,代碼以下:
         
複製代碼
@{
    Layout = null;
}
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    <div> 
    </div>
</body>
</html>
複製代碼

 

 
 
 
 
 
        再說多幾句,咱們此次選的是一個「賬戶資金變更提醒」,他的傳參類型以下:
 
在此以前:因爲咱們這裏面的文字,還能夠設定顏色,咱們從這裏(模板裏面看不到,可是能夠從官方的demo)能夠看出來:
可是,咱們本次用的模板不是這個,是「賬戶資金變更提醒」,可是道理相同,因此,咱們也要新建一個類,文件名字就叫作:DataFontStyle.cs吧,代碼以下:
複製代碼
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace 微信支付之模板消息推送.Models
{
    public class DataFontStyle
    {
        public string value { get; set; }
        public string color { get; set; }
    }
}  
複製代碼

 

再分析他的參數,分別有:first,date,adCharge,type,cashBalance以及remark,因此,咱們給他新建一個Model,到時候會用到的,新建的Model的文件名字就叫作:CashModel.cs,代碼以下:
複製代碼
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
 
namespace 微信支付之模板消息推送.Models
{
    /// <summary>
    /// 賬戶資金變更提醒Model
    /// </summary>
    public class CashModel
    {
        public DataFontStyle first { get; set; }
        public DataFontStyle date { get; set; }
        public DataFontStyle adCharge { get; set; }
        public DataFontStyle type { get; set; }
        public DataFontStyle cashBalance { get; set; }
        public DataFontStyle remark { get; set; }
    }
}  
 
複製代碼

 

 
 
 
 
此外,還有最後一個,那就是這個推送的Model,也要新建一個類,文件名,咱們就叫作PushMess.cs吧,代碼以下:
 
複製代碼
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace 微信支付之模板消息推送.Models
{
    public class PushMessage
    {
        public string touser { get; set; }
        public string template_id { get; set; }
        public string url { get; set; }
        public string topcolor { get; set; }
        /// <summary>
        /// 注意,這裏是CashModel,你若是要通用,有多個推送模板要用,那你就用object
        /// </summary>
        public CashModel data { get; set; }
   
    }
}  
複製代碼

 

漏了一個類,如今補回來,咱們命名爲:WxResult.cs,代碼以下:
 
   public class WxResult
    {
        public int? errcode { get; set; }
        public string errmsg { get; set; }
        public int? msgid { get; set; }
    }  

 

 
 
文件物理路徑邏輯以下,檢查一下,看看有無誤差,以下圖:
 
        說明一下:一些推送必須的代碼,我就直接貼出(例如後去Access_token和推送代碼),再也不說明了,由於在前面幾篇都有說明,若是看不懂,請翻閱前面的教程。
 
        如今,咱們來編輯一下先後端的代碼,前端的代碼的邏輯,仍是跟往常同樣,我代碼儘可能精簡,本次,那個推送,我只傳一個參數到後臺,那就是first,其餘的,都是在後臺固定,實際項目中應用,到時候,大家再行修改便可,前臺代碼:
 
 
 
複製代碼
@{
    Layout = null;
}
 
<!DOCTYPE html>
 
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>身份認證</title>
    <link href="~/Scripts/jquery-easyui-1.4.5/themes/bootstrap/easyui.css" rel="stylesheet" />
    <link href="~/Scripts/jquery-easyui-1.4.5/themes/mobile.css" rel="stylesheet" />
    <link href="~/Scripts/jquery-easyui-1.4.5/themes/icon.css" rel="stylesheet" />
    <style type="text/css">
 
        .line {
            width: 100%;
            float: left;
            height: auto;
            text-align: center;
            margin-top: 15pt;
            font-size: x-large;
        }
 
        .lineText {
            width: 100%;
            float: left;
            height: auto;
            text-indent: 5%;
            text-align: left;
            font-size: x-large;
            margin: 0;
        }
 
        a {
            text-decoration: none;
            color: white;
        }
 
        .input {
            height: 30pt;
            width: 90%;
            font-size: x-large;
            border-radius: 10px;
            margin: 0;
            padding: 0;
        }
 
        .btn {
            width: 90%;
            height: 35pt;
            font-size: x-large;
            background-color: green;
            color: white;
            border: none;
            border-radius: 10px;
        }
    </style>
</head>
<body>
    <div style="width: 100%; text-align: center;">
        <form id="form1">
            <div class="line">
                <div class="lineText">*接收者openid:</div>
            </div>
            <div class="line">
                <input type="text" id="openid" name="openid" class="input" />
            </div>
            <div class="line">
                <div class="lineText">*first.DATA:</div>
            </div>
            <div class="line">
                <input type="text" id="first" name="first" class="input" />
            </div>
        </form>
 
    </div>
    <div class="line">
        <input type="button" id="btnSave" class="btn" value="推送" onclick="fPush()" />
    </div>
    <script src="~/Scripts/jquery-easyui-1.4.5/jquery.min.js"></script>
    <script src="~/Scripts/jquery-easyui-1.4.5/jquery.easyui.min.js"></script>
    <script src="~/Scripts/jquery-easyui-1.4.5/jquery.easyui.mobile.js"></script>
    <script src="~/Scripts/jquery-easyui-1.4.5/easyloader.js"></script>
    <script type="text/javascript">
        $(function () {
            var vCode = getQueryString("code");
            if (vCode != "" && vCode != null) {
                $.ajax({
                    type: 'post',
                    data: {
                        code: vCode
                    },
                    url: '/Home/getWxInfo',
                    success: function (sjson) {
                        $.messager.show({
                            title: '提示',
                            msg: '歡迎您的到來(看到這個提示,表明已經成功獲取openid和access_token了)。'
                        });
                        $("#openid").val(sjson.openid);
                    }
                })
            }
            else {
                $.ajax({
                    type: 'post',
                    url: '/Home/getCode',
                    success: function (sjson) {
                        location.href = sjson;
                    }
                })
            }
        })
        //獲取url的參數
        function getQueryString(name) {
            var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
            var r = window.location.search.substr(1).match(reg);
            if (r != null) return unescape(r[2]); return null;
        }
 
        //推送
        function fPush() {
            var vTtile = $("#first").val();
            $.ajax({
                type: 'post',
                data: {
                    first: vTtile
                },
                url: '/Home/Push',
                success: function (sjson) {
                    if (sjson.result) {
                        $.messager.alert("提示", sjson.msg, 'info');
                    }
                    else {
                        $.messager.alert("提示", sjson.msg, 'warning');
                    }
                }
            })
        }
    </script>
</body>
</html>
複製代碼

 

 
 
後臺代碼:
 
複製代碼
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;
using System.Web.Mvc;
using System.Web.Script.Serialization;
using WxPayAPI;
using 微信支付之模板消息推送.Models;
 
namespace 微信支付之模板消息推送.Controllers
{
    public class HomeController : Controller
    {
        JsApiPay jsApiPay = new JsApiPay();
 
        JavaScriptSerializer JsonHelper = new JavaScriptSerializer();
        /// <summary>
        /// 最後更新Access_token的時間
        /// </summary>
        public static DateTime dtAccess_token;
        /// <summary>
        /// Access_token的值
        /// </summary>
        public static string strAccess_token;
        // GET: Home
        public ActionResult Index()
        {
            if (Session["openid"] == null)
            {
                try
                {
                    //調用【網頁受權獲取用戶信息】接口獲取用戶的openid和access_token
                    GetOpenidAndAccessToken();
 
                }
                catch (Exception ex)
                {
                    //Response.Write(ex.ToString());
                    //throw;
                }
            }
            return View();
        }
 
        /**
        * 
        * 網頁受權獲取用戶基本信息的所有過程
        * 詳情請參看網頁受權獲取用戶基本信息:http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html
        * 第一步:利用url跳轉獲取code
        * 第二步:利用code去獲取openid和access_token
        * 
        */
        public void GetOpenidAndAccessToken()
        {
            if (Session["code"] != null)
            {
                //獲取code碼,以獲取openid和access_token
                string code = Session["code"].ToString();
                Log.Debug(this.GetType().ToString(), "Get code : " + code);
                jsApiPay.GetOpenidAndAccessTokenFromCode(code);
            }
            else
            {
                //構造網頁受權獲取code的URL
                string host = Request.Url.Host;
                string path = Request.Path;
                string redirect_uri = HttpUtility.UrlEncode("http://" + host + path);
                WxPayData data = new WxPayData();
                data.SetValue("appid", WxPayConfig.APPID);
                data.SetValue("redirect_uri", redirect_uri);
                data.SetValue("response_type", "code");
                data.SetValue("scope", "snsapi_base");
                data.SetValue("state", "STATE" + "#wechat_redirect");
                string url = "https://open.weixin.qq.com/connect/oauth2/authorize?" + data.ToUrl();
                Log.Debug(this.GetType().ToString(), "Will Redirect to URL : " + url);
                Session["url"] = url;
            }
        }
 
 
        /// <summary>
        /// 獲取code
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public ActionResult getCode()
        {
            object objResult = "";
            if (Session["url"] != null)
            {
                objResult = Session["url"].ToString();
            }
            else
            {
                objResult = "url爲空。";
            }
            return Json(objResult);
        }
 
        /// <summary>
        /// 經過code換取網頁受權access_token和openid的返回數據
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public ActionResult getWxInfo()
        {
            object objResult = "";
            string strCode = Request.Form["code"];
            string strAccess_Token = "";
            string strOpenid = "";
            if (Session["access_token"] == null || Session["openid"] == null)
            {
                jsApiPay.GetOpenidAndAccessTokenFromCode(strCode);
                strAccess_Token = Session["access_token"].ToString();
                strOpenid = Session["openid"].ToString();
            }
            else
            {
                strAccess_Token = Session["access_token"].ToString();
                strOpenid = Session["openid"].ToString();
            }
            objResult = new { openid = strOpenid, access_token = strAccess_Token };
            return Json(objResult);
        }
 
        /// <summary>
        /// 推送
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public ActionResult Push()
        {
            object objResult = "";
            string strFirst = Request.Form["first"];
            string strMsg = "";
            bool bResult = false;
            //這個是推送消息的類
            PushMessage aPushMessage = new PushMessage()
            {
                template_id = "lypG1jYyOEfY********OK7-LhEwpPeVNHHxemSI",//模板ID
                //data=,//暫時不賦值
                topcolor = "#FF0000",//頭部顏色
                touser = Session["openid"].ToString(),//用戶的Openid
                url = "http://www.baidu.com"//用途是當用戶點擊推送消息的時候,會進入這個頁面,具體用途,本身拓展
            };
 
            //構造要推送的內容
            CashModel aCachData = new CashModel()
            {
                adCharge = new DataFontStyle()
                {
                    color = "#589E63",
                    value = "對應變更金額"
                },
                cashBalance = new DataFontStyle()
                {
                    color = "#589E63",
                    value = "對應賬戶餘額"
                },
                date = new DataFontStyle()
                {
                    color = "#589E63",
                    value = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
                },
                first = new DataFontStyle()
                {
                    color = "#589E63",
                    value = strFirst
                },
                remark = new DataFontStyle()
                {
                    color = "#589E63",
                    value = "對應:點擊「查看詳情「當即查閱您的賬戶財務記錄。"
                },
                type = new DataFontStyle()
                {
                    color = "#589E63",
                    value = "對應「現金」"
                }
            };
            //這時候,把要推送的內容,賦值給push,這樣,咱們要推送的內容就完成了。
            aPushMessage.data = aCachData;
 
            string strUrl = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + GetLatestAccess_token();
            
            string strJsonData = JsonHelper.Serialize(aPushMessage);
            string strResult = HttpPost(strUrl, strJsonData);
            WxResult aResult = JsonHelper.Deserialize<WxResult>(strResult);
            if (aResult != null)
            {
                if (aResult.errcode == 0)
                {
                    bResult = true;
                }
                else
                {
                    bResult = false;
                    strMsg = aResult.errmsg;
                }
            }
            else
            {
                bResult = false;
                strMsg = "通信失敗,請重試。";
            }
 
            objResult = new { result = bResult, msg = strMsg };
            return Json(objResult);
        }
 
 
 
        /// <summary>
        /// HttpPost
        /// </summary>
        /// <param name="Url"></param>
        /// <param name="postDataStr"></param>
        /// <returns></returns>
        public static string HttpPost(string Url, string postDataStr)
        {
            byte[] postData = Encoding.UTF8.GetBytes(postDataStr);//編碼,尤爲是漢字,事先要看下抓取網頁的編碼方式   
            WebClient webClient = new WebClient();
            webClient.Headers.Add("Content-Type", "application/x-www-form-urlencoded");//採起POST方式必須加的header,若是改成GET方式的話就去掉這句話便可  
            byte[] responseData = webClient.UploadData(Url, "POST", postData);//獲得返回字符流             
            string srcString = Encoding.UTF8.GetString(responseData);//解碼 
            return srcString;
           
        }
 
 
        /// <summary>
        /// 返回最新的Access_token
        /// </summary>
        /// <returns></returns>
        public string GetLatestAccess_token()
        {
            if (dtAccess_token == null || dtAccess_token <= DateTime.Now.AddHours(-1) || string.IsNullOrWhiteSpace(strAccess_token))
            {
                string strUrl = string.Format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}", WxPayConfig.APPID, WxPayConfig.APPSECRET);
                string strAccess_tokenData = HttpGet(strUrl, "");
                ModelForAccess_token aToken = JsonHelper.Deserialize<ModelForAccess_token>(strAccess_tokenData);
                dtAccess_token = DateTime.Now;
                strAccess_token = aToken.access_token;
                return strAccess_token;
            }
            else
            {
                return strAccess_token;
            }
        }
 
        /// <summary>
        /// WebGet
        /// </summary>
        /// <param name="Url"></param>
        /// <param name="postDataStr"></param>
        /// <returns></returns>
        public static string HttpGet(string Url, string postDataStr)
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url + (postDataStr == "" ? "" : "?") + postDataStr);
            request.Method = "GET";
            request.ContentType = "text/html;charset=UTF-8";
 
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            Stream myResponseStream = response.GetResponseStream();
            StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.GetEncoding("utf-8"));
            string retString = myStreamReader.ReadToEnd();
            myStreamReader.Close();
            myResponseStream.Close();
 
            return retString;
        }
 
        public class ModelForAccess_token
        {
            public string access_token { get; set; }
            public int? expires_in { get; set; }
        }
    }
} 
複製代碼

 

 
 
代碼已完整提供,若是有缺漏的,請在評論中指出或者進羣來告訴我。若是代碼提供正常,應該就能推送到的了,目前這個代碼,只能給本身推送。實際應用中,能夠經過這個頁面,而後綁定用戶,這樣,咱們就能夠經過用戶名字,給他們的openid推送消息。下面貼出推送的截圖
 
 
 
對了,忘記了一點,這個要發佈到IIS上,而後你發佈的域名,要在公衆平臺裏面,那個獲取用戶權限(前面博文說起到)的網址裏面,改爲你發佈的網址,例如:push.lmx.ren ,不然是獲取不到用戶信息的。
相關文章
相關標籤/搜索