php微信公众账号开发之前五个坑(一)

前端之家收集整理的这篇文章主要介绍了php微信公众账号开发之前五个坑(一)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

直入主题

微信公众账号开发文档,官方版(https://mp.weixin.qq.com/wiki),相信我,我已经无力吐槽写这个文档的人了,我真心想杂碎这个键盘,但是下手之后才发现,原来键盘是我自己花钱买的。。。。尴尬了。

废话不说,直接说怎么部署,怎么开发。

首先,你得有一个公众平台账号,好了,开始计坑。

第一坑,

不要以为不是企业号就不能开发了,可以申请测试号的,比所谓的订阅号接口多多了。

进入后台管理之后,点击开发者工具,可以看到公众平台测试账号,直接进入即可。开始填写自己的配置。

注意涂鸦部分,这部分是程序中必须要配置的东东,如果没有配置的话,这是一定不成功的。

第二坑

,当然,你这么配置也一定是不成功的,不要问我为什么。没图说个几把。。。

请不要认为企鹅帝闹着玩,这是真的,必须是80端口,其实也就发布一个域名的网站即可。因为域名的网站都是80端口出来的,继续说正题。

企鹅帝告诉我们,要用微信账号,必须有一台服务器,然后配置我们发布的网站就行了,请注意,token是自己设定的,这个不是自动生成的,自己设定。。URL就是我们发布的网站名称

第三坑,

网站不发布,接口配置信息是永远配置不过去的,记住,是永远。

JS接口安全域名,这个请直接参考文档(http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html)。

JS接口安全域名的目的是为了下载图片调用微信图片接口等等,比如当你需要调用摄像头的时候,或者说说需要上传照片的时候,这时候就需要JS安全接口了,关于具体的内容暂不做详细描述。

在微信公众账号测试号的版本后台中,有一个体验接口权限表里面的这一项也是必须配置的。也不算是必须配置,而是这个接口可以获取到微信用户的部分信息。值得提醒的是每个公众账号对应的每个ID是唯一的,也就是说,即便网站内网不变,如果换了公众号,那么,这时候的微信公众号的数据是不能共通的,

第四坑,

申请微信网页授权的时候,这里的网页授权用户基本信息,这个本身没问题,但是没有提示就有问题了。

这里的网址,请注意,一定是不含www的,而且后面没有反斜杠,也就是说这里的网址的回调格式是 abc.com OK,请记住这个格式,必须这么干。好了,服务器暂且这样,暂开始用代码说话。

首先从服务器验证说起。这个在官网是有例子的,不过是PHP的,其实说白了首先就是验证一个随机数,然后在POST的情况下,检测返回值即可。直接上代码

PHP;"> public ActionResult Index() { if (Request.HttpMethod.ToLower() == "post") { if (CheckSignature())//验证服务器是否通过 { GetMenuList();//加载菜单 } else { Response.Write("

Oh

我们相遇在火星吧!!!

"); Response.End(); } } else { CheckWechat(); } return View(); }

///


/// 返回随机数表示验证成功
///

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();
}
}

///


/// 验证微信签名
///

///
/// 将token、timestamp、nonce三个参数进行字典序排序
/// 将三个参数字符串拼接成一个字符串进行sha1加密
/// 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信。
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;
}
}

然后,公众平台在有权限的情况下是自定义菜单的,但是一旦开始自定义菜单,原来的手动编辑的菜单是不能用的,也就是说,如果服务器验证通过,那么必须用自己的代码控制。

我们一起来看GetMenuList()这个方法,这个其实很简单的,就是随便凭借一个JSON格式字符串。然后调用微信的接口即可。 public void GetMenuList()

PHP;"> }]
}] }";

string access_token = Tools.WA_GetAccess_Token.IsExistAccess_Token();
string i = this.MenuCreate(menu,access_token);
Response.Write(i);
}


PHP;"> 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 respDic = (Dictionary)Jss.DeserializeObject(respText); return respDic["errcode"].ToString();//返回0发布成功 }

///


/// Post/get 提交调用抓取
///

/// <param name="url">提交地址
/// <param name="param">参数
/// string
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段内的内存
{
reqStream.Write(bt,bt.Length);
reqStream.Flush();
}
try
{
using (WebResponse res = req.GetResponse())
{
//在这里对接收到的页面内容进行处理
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错误时候回报错
}

}

好吧,我承认我是一个不明真相的吃货,怎么又多了一个access_token=IsExistAccess_Token();呢,莫着急,宝宝告诉你。

当我们阅读文档的时候,我们会发现,这里的Access_Token是每两个小时就过期的。这里的方法就是让他过期的时候自动获取

第五坑

,这里的JSON字符串,也就是要展示的菜单,我希望大家都用小写,如果用了大写,那么,呵呵,哈哈了真心的,很操蛋的,他会告诉你没有用UTF8编码,但是你真心是编码过的,可惜还是出错,所以,还是小写吧,唉

继续说两个小时自动获取之后,就是通过MenuCreate(调用微信菜单接口)输出即可。上代码

PHP;"> /// /// 防止每次请求的token两个小时的变化 /// 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(content); entity.access_token = token.access_token; entity.expires_in = token.expires_in; }

}

catch{ //记录日志}
return entity;

}

///


/// 根据当前日期 判断Access_Token 是否超期 如果超期返回新的Access_Token 否则返回之前的Access_Token
///

/// <param name="datetime">
///
public static string IsExistAccess_Token()
{
try
{
string Token = string.Empty;
DateTime YouXRQ;
//读取XML文件中的数据,并显示出来
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
{
///


/// 生成Json格式
///

/// <typeparam name="T">
/// <param name="obj">
///
public static string GetJson(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;
}
}
///


/// 获取Json的Model
///

/// <typeparam name="T">
/// <param name="szJson">
///
public static T ParseFromJson(string szJson)
{
T obj = Activator.CreateInstance();
using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(szJson)))
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(obj.GetType());
return (T)serializer.ReadObject(ms);
}
}

}

原谅我又不明真相了,所谓的XMLFile.xml这又是什么鬼,好吧,我其实不想说的这么直白的,还是代码直接上比较好。

获取TOKEN 2015/9/12 17:56:31

我确定这个你真心不想说什么了

好吧,默默的吃着瓜子,静静的看着你们继续,今天就先到这里,随后我们继续走起,已经五个坑了呀,宝宝心里苦呀。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程之家。

原文链接:https://www.f2er.com/php/19023.html

猜你在找的PHP相关文章