php微信公眾賬號(hào)開發(fā)之前五個(gè)坑(一)
直入主題:
微信公眾賬號(hào)開發(fā)文檔,官方版(https://mp.weixin.qq.com/wiki),相信我,我已經(jīng)無力吐槽寫這個(gè)文檔的人了,我真心想雜碎這個(gè)鍵盤,但是下手之后才發(fā)現(xiàn),原來鍵盤是我自己花錢買的。。。。尷尬了。
廢話不說,直接說怎么部署,怎么開發(fā)。
首先,你得有一個(gè)公眾平臺(tái)賬號(hào),好了,開始計(jì)坑。
第一坑,不要以為不是企業(yè)號(hào)就不能開發(fā)了,可以申請(qǐng)測(cè)試號(hào)的,比所謂的訂閱號(hào)接口多多了。

進(jìn)入后臺(tái)管理之后,點(diǎn)擊開發(fā)者工具,可以看到公眾平臺(tái)測(cè)試賬號(hào),直接進(jìn)入即可。開始填寫自己的配置。


注意涂鴉部分,這部分是程序中必須要配置的東東,如果沒有配置的話,這是一定不成功的。
第二坑,當(dāng)然,你這么配置也一定是不成功的,不要問我為什么。沒圖說個(gè)幾把。。。

請(qǐng)不要認(rèn)為企鵝帝鬧著玩,這是真的,必須是80端口,其實(shí)也就發(fā)布一個(gè)域名的網(wǎng)站即可。因?yàn)橛蛎木W(wǎng)站都是80端口出來的,繼續(xù)說正題。
企鵝帝告訴我們,要用微信賬號(hào),必須有一臺(tái)服務(wù)器,然后配置我們發(fā)布的網(wǎng)站就行了,請(qǐng)注意,token是自己設(shè)定的,這個(gè)不是自動(dòng)生成的,自己設(shè)定。。URL就是我們發(fā)布的網(wǎng)站名稱
第三坑,網(wǎng)站不發(fā)布,接口配置信息是永遠(yuǎn)配置不過去的,記住,是永遠(yuǎn)。
JS接口安全域名,這個(gè)請(qǐng)直接參考文檔(http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html)。
JS接口安全域名的目的是為了下載圖片,調(diào)用微信圖片接口等等,比如當(dāng)你需要調(diào)用攝像頭的時(shí)候,或者說說需要上傳照片的時(shí)候,這時(shí)候就需要JS安全接口了,關(guān)于具體的內(nèi)容暫不做詳細(xì)描述。
在微信公眾賬號(hào)測(cè)試號(hào)的版本后臺(tái)中,有一個(gè)體驗(yàn)接口權(quán)限表里面的這一項(xiàng)也是必須配置的。也不算是必須配置,而是這個(gè)接口可以獲取到微信用戶的部分信息。值得提醒的是每個(gè)公眾賬號(hào)對(duì)應(yīng)的每個(gè)ID是唯一的,也就是說,即便網(wǎng)站內(nèi)網(wǎng)不變,如果換了公眾號(hào),那么,這時(shí)候的微信公眾號(hào)的數(shù)據(jù)是不能共通的,只是相對(duì)公共號(hào)唯一。

第四坑,申請(qǐng)微信網(wǎng)頁(yè)授權(quán)的時(shí)候,這里的網(wǎng)頁(yè)授權(quán)用戶基本信息,這個(gè)本身沒問題,但是沒有提示就有問題了。

這里的網(wǎng)址,請(qǐng)注意,一定是不含www的,而且后面沒有反斜杠,也就是說這里的網(wǎng)址的回調(diào)格式是 abc.com OK,請(qǐng)記住這個(gè)格式,必須這么干。好了,服務(wù)器暫且這樣,暫開始用代碼說話。
首先從服務(wù)器驗(yàn)證說起。這個(gè)在官網(wǎng)是有例子的,不過是PHP的,其實(shí)說白了首先就是驗(yàn)證一個(gè)隨機(jī)數(shù),然后在POST的情況下,檢測(cè)返回值即可。直接上代碼
public ActionResult Index()
{
if (Request.HttpMethod.ToLower() == "post")
{
if (CheckSignature())//驗(yàn)證服務(wù)器是否通過
{
GetMenuList();//加載菜單
}
else
{
Response.Write("<h1>Oh</h1><h2>我們相遇在火星吧?。?!</h2>");
Response.End();
}
}
else
{
CheckWechat();
}
return View();
}
/// <summary>
/// 返回隨機(jī)數(shù)表示驗(yàn)證成功
/// </summary>
private void CheckWechat()
{
if (string.IsNullOrEmpty(Request.QueryString["echoStr"]))
{
Response.Write("消息并非來自微信");
Response.End();
}
string echoStr = Request.QueryString["echoStr"];
if (CheckSignature())
{
Response.Write(echoStr);
Response.End();
}
}
/// <summary>
/// 驗(yàn)證微信簽名
/// </summary>
/// <returns></returns>
/// 將token、timestamp、nonce三個(gè)參數(shù)進(jìn)行字典序排序
/// 將三個(gè)參數(shù)字符串拼接成一個(gè)字符串進(jìn)行sha1加密
/// 開發(fā)者獲得加密后的字符串可與signature對(duì)比,標(biāo)識(shí)該請(qǐng)求來源于微信。
private bool CheckSignature()
{
string signature = Convert.ToString(Request["signature"]);
string timestamp = Convert.ToString(Request["timestamp"]);
string nonce = Convert.ToString(Request["nonce"]);
string[] ArrTmp = { Token, timestamp, nonce };
Array.Sort(ArrTmp); //字典排序
string tmpStr = string.Join("", ArrTmp);
tmpStr = FormsAuthentication.HashPasswordForStoringInConfigFile(tmpStr, "SHA1");
tmpStr = tmpStr.ToLower();
if (tmpStr == signature)
{
return true;
}
else
{
return false;
}
}
然后,公眾平臺(tái)在有權(quán)限的情況下是自定義菜單的,但是一旦開始自定義菜單,原來的手動(dòng)編輯的菜單是不能用的,也就是說,如果服務(wù)器驗(yàn)證通過,那么必須用自己的代碼控制。
我們一起來看GetMenuList()這個(gè)方法,這個(gè)其實(shí)很簡(jiǎn)單的,就是隨便憑借一個(gè)JSON格式字符串。然后調(diào)用微信的接口即可。 public void GetMenuList()
<em id="__mceDel"> {
string weixin1 = "";
weixin1 = @" {
""button"":[
{
""type"":""click"",
""name"":""你好!"",
""key"":""hello""
},
{
""type"":""view"",
""name"":""公司簡(jiǎn)介"",
""url"":""http://www.xnfhtech.com""
},
{
""name"":""產(chǎn)品介紹"",
""sub_button"":[
{
""type"":""click"",
""name"":""產(chǎn)品1"",
""key"":""p1""
},
{
""type"":""click"",
""name"":""產(chǎn)品2"",
""key"":""p2""
}]
}] }";
string access_token = Tools.WA_GetAccess_Token.IsExistAccess_Token();
string i = this.MenuCreate(menu, access_token);
Response.Write(i);
}<br><br>
</em>
public string MenuCreate(string MenuJson, string access_token)
{
JavaScriptSerializer Jss = new JavaScriptSerializer();
string setMenuUrl = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token={0}";
setMenuUrl = string.Format(setMenuUrl, access_token);//獲取token、拼湊url
string respText = WebRequestPostOrGet(setMenuUrl, MenuJson);
Dictionary<string, object> respDic = (Dictionary<string, object>)Jss.DeserializeObject(respText);
return respDic["errcode"].ToString();//返回0發(fā)布成功
}
/// <summary>
/// Post/get 提交調(diào)用抓取
/// </summary>
/// <param name="url">提交地址</param>
/// <param name="param">參數(shù)</param>
/// <returns>string</returns>
public string WebRequestPostOrGet(string sUrl, string sParam)
{
byte[] bt = System.Text.Encoding.UTF8.GetBytes(sParam);
Uri uriurl = new Uri(sUrl);
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(uriurl);//HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(url + (url.IndexOf("?") > -1 ? "" : "?") + param);
req.Method = "Post";
req.Timeout = 120 * 1000;
req.ContentType = "application/x-www-form-urlencoded;";
req.ContentLength = bt.Length;
using (Stream reqStream = req.GetRequestStream())//using 使用可以釋放using段內(nèi)的內(nèi)存
{
reqStream.Write(bt, 0, bt.Length);
reqStream.Flush();
}
try
{
using (WebResponse res = req.GetResponse())
{
//在這里對(duì)接收到的頁(yè)面內(nèi)容進(jìn)行處理
Stream resStream = res.GetResponseStream();
StreamReader resStreamReader = new StreamReader(resStream, System.Text.Encoding.UTF8);
string resLine;
System.Text.StringBuilder resStringBuilder = new System.Text.StringBuilder();
while ((resLine = resStreamReader.ReadLine()) != null)
{
resStringBuilder.Append(resLine + System.Environment.NewLine);
}
resStream.Close();
resStreamReader.Close();
return resStringBuilder.ToString();
}
}
catch (Exception ex)
{
return ex.Message;//url錯(cuò)誤時(shí)候回報(bào)錯(cuò)
}
}
好吧,我承認(rèn)我是一個(gè)不明真相的吃貨,怎么又多了一個(gè)access_token=IsExistAccess_Token();呢,莫著急,寶寶告訴你。
當(dāng)我們閱讀文檔的時(shí)候,我們會(huì)發(fā)現(xiàn),這里的Access_Token是每?jī)蓚€(gè)小時(shí)就過期的。這里的方法就是讓他過期的時(shí)候自動(dòng)獲取。
第五坑,這里的JSON字符串,也就是要展示的菜單,我希望大家都用小寫,如果用了大寫,那么,呵呵,哈哈了真心的,很操蛋的,他會(huì)告訴你沒有用UTF8編碼,但是你真心是編碼過的,可惜還是出錯(cuò),所以,還是小寫吧,唉
繼續(xù)說兩個(gè)小時(shí)自動(dòng)獲取之后,就是通過MenuCreate(調(diào)用微信菜單接口)輸出即可。上代碼。
/// <summary>
/// 防止每次請(qǐng)求的token兩個(gè)小時(shí)的變化
/// </summary>
public class WA_GetAccess_Token
{
public WA_GetAccess_Token()
{
}
public static WAEntity.Access_token GetAccess_Token()
{
string url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+ ConfigurationManager.AppSettings["AppID"] + "&secret="+ ConfigurationManager.AppSettings["AppSecret"];
Access_token entity = new Access_token();
try
{
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(url);
req.Method = "GET";
using (WebResponse wr = req.GetResponse())
{
HttpWebResponse myResponse = (HttpWebResponse)req.GetResponse();
StreamReader reader = new StreamReader(myResponse.GetResponseStream(), System.Text.Encoding.UTF8);
string content = reader.ReadToEnd();
Access_token token = new Access_token();
token = JsonHelper.ParseFromJson<Access_token>(content);
entity.access_token = token.access_token;
entity.expires_in = token.expires_in;
}
}
catch{ //記錄日志}
return entity;
}
/// <summary>
/// 根據(jù)當(dāng)前日期 判斷Access_Token 是否超期 如果超期返回新的Access_Token 否則返回之前的Access_Token
/// </summary>
/// <param name="datetime"></param>
/// <returns></returns>
public static string IsExistAccess_Token()
{
try
{
string Token = string.Empty;
DateTime YouXRQ;
//讀取XML文件中的數(shù)據(jù),并顯示出來
string filepath = HttpContext.Current.Request.MapPath("~/XMLFile.xml");
StreamReader str = new StreamReader(filepath, System.Text.Encoding.UTF8);
XmlDocument xml = new XmlDocument();
xml.Load(str);
str.Close();
str.Dispose();
Token = xml.SelectSingleNode("xml").SelectSingleNode("Access_Token").InnerText;
YouXRQ = Convert.ToDateTime(xml.SelectSingleNode("xml").SelectSingleNode("Access_YouXRQ").InnerText);
if (DateTime.Now > YouXRQ)
{
DateTime _youxrq = DateTime.Now;
WAEntity.Access_token mode = GetAccess_Token();
xml.SelectSingleNode("xml").SelectSingleNode("Access_Token").InnerText = mode.access_token;
_youxrq = _youxrq.AddSeconds(Convert.ToInt32(mode.expires_in));
xml.SelectSingleNode("xml").SelectSingleNode("Access_YouXRQ").InnerText = _youxrq.ToString();
xml.Save(filepath);
Token = mode.access_token;
}
return Token;
}
catch (Exception ex)
{
return "";//記錄日志
}
}
}
public class Access_token
{
public Access_token()
{ }
public string access_token { get; set; }
public string expires_in { get; set; }
}
public class JsonHelper
{
/// <summary>
/// 生成Json格式
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj"></param>
/// <returns></returns>
public static string GetJson<T>(T obj)
{
DataContractJsonSerializer json = new DataContractJsonSerializer(obj.GetType());
using (MemoryStream stream = new MemoryStream())
{
json.WriteObject(stream, obj);
string szJson = Encoding.UTF8.GetString(stream.ToArray()); return szJson;
}
}
/// <summary>
/// 獲取Json的Model
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="szJson"></param>
/// <returns></returns>
public static T ParseFromJson<T>(string szJson)
{
T obj = Activator.CreateInstance<T>();
using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(szJson)))
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(obj.GetType());
return (T)serializer.ReadObject(ms);
}
}
}
原諒我又不明真相了,所謂的XMLFile.xml這又是什么鬼,好吧,我其實(shí)不想說的這么直白的,還是代碼直接上比較好。
<?xml version="1.0" encoding="utf-8"?> <xml> <Access_Token>獲取TOKEN</Access_Token> <Access_YouXRQ>2015/9/12 17:56:31</Access_YouXRQ> </xml>
我確定這個(gè)你真心不想說什么了
好吧,默默的吃著瓜子,靜靜的看著你們繼續(xù),今天就先到這里,隨后我們繼續(xù)走起,已經(jīng)五個(gè)坑了呀,寶寶心里苦呀。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- php微信公眾賬號(hào)開發(fā)之五個(gè)坑(二)
- php版微信公眾號(hào)自定義分享內(nèi)容實(shí)現(xiàn)方法
- 微信公眾號(hào)開發(fā)之文本消息自動(dòng)回復(fù)php代碼
- 微信公眾號(hào)開發(fā)之語(yǔ)音消息識(shí)別php代碼
- Thinkphp微信公眾號(hào)支付接口
- php判斷用戶是否關(guān)注微信公眾號(hào)
- php實(shí)現(xiàn)微信公眾號(hào)主動(dòng)推送消息
- 微信支付PHP SDK之微信公眾號(hào)支付代碼詳解
- php版微信公眾平臺(tái)接口參數(shù)調(diào)試實(shí)現(xiàn)判斷用戶行為的方法
- php使用CURL模擬GET與POST向微信接口提交及獲取數(shù)據(jù)的方法
- php版微信公眾賬號(hào)第三方管理工具開發(fā)簡(jiǎn)明教程
相關(guān)文章
ThinkPHP實(shí)現(xiàn)將本地文件打包成zip下載
這篇文章主要介紹了ThinkPHP實(shí)現(xiàn)將本地文件打包成zip下載的方法,需要的朋友可以參考下2014-06-06
PHP執(zhí)行系統(tǒng)命令函數(shù)實(shí)例講解
這篇文章主要介紹了PHP執(zhí)行系統(tǒng)命令函數(shù)實(shí)例講解,列舉的都是一些常用的函數(shù),有感興趣的同學(xué)可以學(xué)習(xí)下2021-03-03
thinkPHP中create方法與令牌驗(yàn)證實(shí)例淺析
這篇文章主要介紹了thinkPHP中create方法與令牌驗(yàn)證,以一個(gè)簡(jiǎn)單實(shí)例形式分析了thinkPHP中create方法與令牌驗(yàn)證增加表單安全性的相關(guān)技巧,代碼備有詳盡注釋說明,需要的朋友可以參考下2015-12-12
Kindeditor編輯器添加圖片上傳水印功能(php代碼)
這篇文章主要為大家詳細(xì)介紹了Kindeditor編輯器加圖片上傳水印功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08

