ホームページ >php教程 >php手册 >微信公众号开发总结

微信公众号开发总结

WBOY
WBOYオリジナル
2016-06-13 09:35:35942ブラウズ

最近公司用到了微信公众平台,所以研究了一下微信公众号的开发技术,总体来说比较简单,结合现有的平台核技术,实现起来非常方便。

首先先来了解一下微信公众平台。

“微信,是一个生活方式” ,这是微信的自我评价,是不是觉得如果那天不在朋友圈里分享一下自己的最新状态, 
并且收到几个赞和评价的话,会觉得空虚寂寞呢?它实实在在的改变了我们的生活方式。

“ 微信,也是一个生意方式 ”,在微信成为我们日常必备之app的同时,它同样具备巨大的的商业 
或许不应该称为潜力,因为有很多人已经获利,名人们在微信上开设公众账户来吸金,商家来做推广, 
服务行业借此拓展渠道,甚至微信已经支持支付了, 还有越来越的自媒体在微信平台涌现出来。 

这篇文章就是介绍如何快速的成为公众平台开发者,由于个人只能申请订阅号,因此本文是以订阅号为例。
关于订阅号和服务号的区别,请参见 微信公众平台服务号、订阅号的相关说明

从微信用户角度简单来说:

订阅号 主要用于信息辐射,典型的如各家 新闻媒体 。 
服务号 主要由于自助服务,典型的如 招商银行 。

申请公众平台账户

  • 到 微信公众平台填写注册信息
  • 按照提示激活邮箱

  • 上传个人照片,需要有清晰的身份证照片

  • 选择公众账户的类型,对于个人账户只能选择 订阅号

  • 最后你会看到自己账户的所有信息,请上传账号的头像,否则无法完成开发者的申请

  • 等待审核通过,这个过程大约需要2~3天,当你收到如下通知,那么恭喜你,你已经成功的申请到了微信公众账户了

关于微信公众帐号注册的步骤就不再多说了,可以找到大量的图文教程。

帐号注册成功之后,需要验证自己的服务器,如果你没有自己的服务器,那可以用新浪SAE或者百度BAE,本文采用的是新浪SAE平台来搭建服务器。

注册过程略,使用新浪SAE创建应用,可以选择应用开发框架,选项中有比较热门的开发框架,选择微信公众平台phpSDK,点击后跳转到介绍页面,点击安装框架,系统会生成一个搭建好的微信公众平台应用,为了方便开发,我们可以使用svn来管理此应用代码,关于svn搭建可参见sae代码部署手册。

使用新浪SAE是比较方便的,如果我们有自己的服务器,可以把代码clone到自己的服务器上,下面来看一下代码

首先定义一个Wechat的基类

<span   1</span> <?<span php
</span><span   2</span> <span /*</span><span *
</span><span   3</span> <span  * 微信公众平台 PHP SDK
</span><span   4</span> <span  *
</span><span   5</span> <span  * @author hanc <congcongsky2010@gmail.com>
</span><span   6</span>  <span */</span>
<span   7</span> 
<span   8</span>   <span /*</span><span *
</span><span   9</span> <span    * 微信公众平台处理类
</span><span  10</span>    <span */</span>
<span  11</span>   <span class</span><span  Wechat {
</span><span  12</span> 
<span  13</span>     <span /*</span><span *
</span><span  14</span> <span      * 调试模式,将错误通过文本消息回复显示
</span><span  15</span> <span      *
</span><span  16</span> <span      * @var boolean
</span><span  17</span>      <span */</span>
<span  18</span>     <span private</span> <span $debug</span><span ;
</span><span  19</span> 
<span  20</span>     <span /*</span><span *
</span><span  21</span> <span      * 以数组的形式保存微信服务器每次发来的请求
</span><span  22</span> <span      *
</span><span  23</span> <span      * @var array
</span><span  24</span>      <span */</span>
<span  25</span>     <span private</span> <span $request</span><span ;
</span><span  26</span> 
<span  27</span>     <span /*</span><span *
</span><span  28</span> <span      * 初始化,判断此次请求是否为验证请求,并以数组形式保存
</span><span  29</span> <span      *
</span><span  30</span> <span      * @param string $token 验证信息
</span><span  31</span> <span      * @param boolean $debug 调试模式,默认为关闭
</span><span  32</span>      <span */</span>
<span  33</span>     <span public</span> <span function</span> __construct(<span $token</span>, <span $debug</span> = <span FALSE</span><span ) {
</span><span  34</span>       <span if</span> (<span $this</span>->isValid() && <span $this</span>->validateSignature(<span $token</span><span )) {
</span><span  35</span>         <span exit</span>(<span $_GET</span>['echostr'<span ]);
</span><span  36</span> <span       }
</span><span  37</span> 
<span  38</span>       <span $this</span>->debug = <span $debug</span><span ;
</span><span  39</span>       <span set_error_handler</span>(<span array</span>(&<span $this</span>, 'errorHandler'<span ));
</span><span  40</span>       <span //</span><span  设置错误处理函数,将错误通过文本消息回复显示</span>
<span  41</span> 
<span  42</span>       <span $xml</span> = (<span array</span>) <span simplexml_load_string</span>(<span $GLOBALS</span>['HTTP_RAW_POST_DATA'], 'SimpleXMLElement',<span  LIBXML_NOCDATA);
</span><span  43</span> 
<span  44</span>       <span $this</span>->request = <span array_change_key_case</span>(<span $xml</span>,<span  CASE_LOWER);
</span><span  45</span>       <span //</span><span  将数组键名转换为小写,提高健壮性,减少因大小写不同而出现的问题</span>
<span  46</span> <span     }
</span><span  47</span> 
<span  48</span>     <span /*</span><span *
</span><span  49</span> <span      * 判断此次请求是否为验证请求
</span><span  50</span> <span      *
</span><span  51</span> <span      * @return boolean
</span><span  52</span>      <span */</span>
<span  53</span>     <span private</span> <span function</span><span  isValid() {
</span><span  54</span>       <span return</span> <span isset</span>(<span $_GET</span>['echostr'<span ]);
</span><span  55</span> <span     }
</span><span  56</span> 
<span  57</span>     <span /*</span><span *
</span><span  58</span> <span      * 判断验证请求的签名信息是否正确
</span><span  59</span> <span      *
</span><span  60</span> <span      * @param  string $token 验证信息
</span><span  61</span> <span      * @return boolean
</span><span  62</span>      <span */</span>
<span  63</span>     <span private</span> <span function</span> validateSignature(<span $token</span><span ) {
</span><span  64</span>       <span $signature</span> = <span $_GET</span>['signature'<span ];
</span><span  65</span>       <span $timestamp</span> = <span $_GET</span>['timestamp'<span ];
</span><span  66</span>       <span $nonce</span> = <span $_GET</span>['nonce'<span ];
</span><span  67</span> 
<span  68</span>       <span $signatureArray</span> = <span array</span>(<span $token</span>, <span $timestamp</span>, <span $nonce</span><span );
</span><span  69</span>       <span sort</span>(<span $signatureArray</span><span );
</span><span  70</span> 
<span  71</span>       <span return</span> <span sha1</span>(<span implode</span>(<span $signatureArray</span>)) == <span $signature</span><span ;
</span><span  72</span> <span     }
</span><span  73</span> 
<span  74</span>     <span /*</span><span *
</span><span  75</span> <span      * 获取本次请求中的参数,不区分大小
</span><span  76</span> <span      *
</span><span  77</span> <span      * @param  string $param 参数名,默认为无参
</span><span  78</span> <span      * @return mixed
</span><span  79</span>      <span */</span>
<span  80</span>     <span protected</span> <span function</span> getRequest(<span $param</span> = <span FALSE</span><span ) {
</span><span  81</span>       <span if</span> (<span $param</span> === <span FALSE</span><span ) {
</span><span  82</span>         <span return</span> <span $this</span>-><span request;
</span><span  83</span> <span       }
</span><span  84</span> 
<span  85</span>       <span $param</span> = <span strtolower</span>(<span $param</span><span );
</span><span  86</span> 
<span  87</span>       <span if</span> (<span isset</span>(<span $this</span>->request[<span $param</span><span ])) {
</span><span  88</span>         <span return</span> <span $this</span>->request[<span $param</span><span ];
</span><span  89</span> <span       }
</span><span  90</span> 
<span  91</span>       <span return</span> <span NULL</span><span ;
</span><span  92</span> <span     }
</span><span  93</span> 
<span  94</span>     <span /*</span><span *
</span><span  95</span> <span      * 用户关注时触发,用于子类重写
</span><span  96</span> <span      *
</span><span  97</span> <span      * @return void
</span><span  98</span>      <span */</span>
<span  99</span>     <span protected</span> <span function</span><span  onSubscribe() {}
</span><span 100</span> 
<span 101</span>     <span /*</span><span *
</span><span 102</span> <span      * 用户取消关注时触发,用于子类重写
</span><span 103</span> <span      *
</span><span 104</span> <span      * @return void
</span><span 105</span>      <span */</span>
<span 106</span>     <span protected</span> <span function</span><span  onUnsubscribe() {}
</span><span 107</span>     
<span 108</span>     <span /*</span><span *
</span><span 109</span> <span      * 用户自动上报地理位置触发,用于子类重写
</span><span 110</span> <span      *
</span><span 111</span> <span      * @return void
</span><span 112</span>      <span */</span>
<span 113</span>     <span protected</span> <span function</span><span  onAutoloaction() {}
</span><span 114</span>       
<span 115</span>     <span /*</span><span *
</span><span 116</span> <span      * 用户点击菜单时触发,用于子类重写
</span><span 117</span> <span      *
</span><span 118</span> <span      * @return void
</span><span 119</span>      <span */</span>
<span 120</span>     <span protected</span> <span function</span><span  onClick() {}
</span><span 121</span>     
<span 122</span>     <span /*</span><span *
</span><span 123</span> <span      * 用户点击跳转链接时触发,用于子类重写
</span><span 124</span> <span      *
</span><span 125</span> <span      * @return void
</span><span 126</span>      <span */</span>
<span 127</span>     <span protected</span> <span function</span><span  onView() {}
</span><span 128</span> 
<span 129</span>     <span /*</span><span *
</span><span 130</span> <span      * 收到文本消息时触发,用于子类重写
</span><span 131</span> <span      *
</span><span 132</span> <span      * @return void
</span><span 133</span>      <span */</span>
<span 134</span>     <span protected</span> <span function</span><span  onText() {}
</span><span 135</span> 
<span 136</span>     <span /*</span><span *
</span><span 137</span> <span      * 收到图片消息时触发,用于子类重写
</span><span 138</span> <span      *
</span><span 139</span> <span      * @return void
</span><span 140</span>      <span */</span>
<span 141</span>     <span protected</span> <span function</span><span  onImage() {}
</span><span 142</span> 
<span 143</span>     <span /*</span><span *
</span><span 144</span> <span      * 收到地理位置消息时触发,用于子类重写
</span><span 145</span> <span      *
</span><span 146</span> <span      * @return void
</span><span 147</span>      <span */</span>
<span 148</span>     <span protected</span> <span function</span><span  onLocation() {}
</span><span 149</span> 
<span 150</span>     <span /*</span><span *
</span><span 151</span> <span      * 收到链接消息时触发,用于子类重写
</span><span 152</span> <span      *
</span><span 153</span> <span      * @return void
</span><span 154</span>      <span */</span>
<span 155</span>     <span protected</span> <span function</span><span  onLink() {}
</span><span 156</span>     <span /*</span><span *
</span><span 157</span> <span      * 收到语音消息时触发,用于子类重写
</span><span 158</span> <span      *
</span><span 159</span> <span      * @return void
</span><span 160</span>      <span */</span>
<span 161</span>     <span protected</span> <span function</span><span  onVoice() {}
</span><span 162</span> 
<span 163</span>     <span /*</span><span *
</span><span 164</span> <span      * 收到未知类型消息时触发,用于子类重写
</span><span 165</span> <span      *
</span><span 166</span> <span      * @return void
</span><span 167</span>      <span */</span>
<span 168</span>     <span protected</span> <span function</span><span  onUnknown() {}
</span><span 169</span> 
<span 170</span>     <span /*</span><span *
</span><span 171</span> <span      * 回复文本消息
</span><span 172</span> <span      *
</span><span 173</span> <span      * @param  string  $content  消息内容
</span><span 174</span> <span      * @param  integer $funcFlag 默认为0,设为1时星标刚才收到的消息
</span><span 175</span> <span      * @return void
</span><span 176</span>      <span */</span>
<span 177</span>     <span protected</span> <span function</span> responseText(<span $content</span>, <span $funcFlag</span> = 0<span ) {
</span><span 178</span>       <span exit</span>(<span new</span> TextResponse(<span $this</span>->getRequest('fromusername'), <span $this</span>->getRequest('tousername'), <span $content</span>, <span $funcFlag</span><span ));
</span><span 179</span> <span     }
</span><span 180</span> 
<span 181</span>     <span /*</span><span *
</span><span 182</span> <span      * 回复音乐消息
</span><span 183</span> <span      *
</span><span 184</span> <span      * @param  string  $title       音乐标题
</span><span 185</span> <span      * @param  string  $description 音乐描述
</span><span 186</span> <span      * @param  string  $musicUrl    音乐链接
</span><span 187</span> <span      * @param  string  $hqMusicUrl  高质量音乐链接,Wi-Fi 环境下优先使用
</span><span 188</span> <span      * @param  integer $funcFlag    默认为0,设为1时星标刚才收到的消息
</span><span 189</span> <span      * @return void
</span><span 190</span>      <span */</span>
<span 191</span>     <span protected</span> <span function</span> responseMusic(<span $title</span>, <span $description</span>, <span $musicUrl</span>, <span $hqMusicUrl</span>, <span $funcFlag</span> = 0<span ) {
</span><span 192</span>       <span exit</span>(<span new</span> MusicResponse(<span $this</span>->getRequest('fromusername'), <span $this</span>->getRequest('tousername'), <span $title</span>, <span $description</span>, <span $musicUrl</span>, <span $hqMusicUrl</span>, <span $funcFlag</span><span ));
</span><span 193</span> <span     }
</span><span 194</span> 
<span 195</span>     <span /*</span><span *
</span><span 196</span> <span      * 回复图文消息
</span><span 197</span> <span      * @param  array   $items    由单条图文消息类型 NewsResponseItem() 组成的数组
</span><span 198</span> <span      * @param  integer $funcFlag 默认为0,设为1时星标刚才收到的消息
</span><span 199</span> <span      * @return void
</span><span 200</span>      <span */</span>
<span 201</span>     <span protected</span> <span function</span> responseNews(<span $items</span>, <span $funcFlag</span> = 0<span ) {
</span><span 202</span>       <span exit</span>(<span new</span> NewsResponse(<span $this</span>->getRequest('fromusername'), <span $this</span>->getRequest('tousername'), <span $items</span>, <span $funcFlag</span><span ));
</span><span 203</span> <span     }
</span><span 204</span>     <span /*</span><span *
</span><span 205</span> <span      * 回复语音识别消息
</span><span 206</span> <span      * @param  array   $recognition  系统接收到语音后识别的字符串
</span><span 207</span> <span      * @param  integer $funcFlag     默认为0,设为1时星标刚才收到的消息
</span><span 208</span> <span      * @return void
</span><span 209</span>      <span */</span>
<span 210</span>     <span protected</span> <span function</span> responseVoice(<span $recognition</span>, <span $funcFlag</span> = 0<span ) {
</span><span 211</span>       <span exit</span>(<span new</span> TextResponse(<span $this</span>->getRequest('fromusername'), <span $this</span>->getRequest('tousername'), <span $recognition</span>, <span $funcFlag</span><span ));
</span><span 212</span> <span     }
</span><span 213</span> 
<span 214</span>     <span /*</span><span *
</span><span 215</span> <span      * 分析消息类型,并分发给对应的函数
</span><span 216</span> <span      *
</span><span 217</span> <span      * @return void
</span><span 218</span>      <span */</span>
<span 219</span>     <span public</span> <span function</span><span  run() {
</span><span 220</span>       <span switch</span> (<span $this</span>->getRequest('msgtype'<span )) {
</span><span 221</span> 
<span 222</span>         <span case</span> 'event':
<span 223</span>           <span switch</span> (<span $this</span>->getRequest('event'<span )) {
</span><span 224</span> 
<span 225</span>             <span case</span> 'subscribe':
<span 226</span>               <span $this</span>-><span onSubscribe();
</span><span 227</span>               <span break</span><span ;
</span><span 228</span> 
<span 229</span>             <span case</span> 'unsubscribe':
<span 230</span>               <span $this</span>-><span onUnsubscribe();
</span><span 231</span>               <span break</span><span ;
</span><span 232</span>               
<span 233</span>             <span case</span> 'LOCATION':
<span 234</span>               <span $this</span>-><span onAutoloaction();
</span><span 235</span>               <span break</span><span ;
</span><span 236</span>               
<span 237</span>             <span case</span> 'CLICK':
<span 238</span>               <span $this</span>-><span onClick();
</span><span 239</span>               <span break</span><span ;
</span><span 240</span>               
<span 241</span>             <span case</span> 'VIEW':
<span 242</span>               <span $this</span>-><span onView();
</span><span 243</span>               <span break</span><span ;
</span><span 244</span> 
<span 245</span> <span           }
</span><span 246</span>           <span break</span><span ;
</span><span 247</span> 
<span 248</span>         <span case</span> 'text':
<span 249</span>           <span $this</span>-><span onText();
</span><span 250</span>           <span break</span><span ;
</span><span 251</span> 
<span 252</span>         <span case</span> 'image':
<span 253</span>           <span $this</span>-><span onImage();
</span><span 254</span>           <span break</span><span ;
</span><span 255</span> 
<span 256</span>         <span case</span> 'location':
<span 257</span>           <span $this</span>-><span onLocation();
</span><span 258</span>           <span break</span><span ;
</span><span 259</span> 
<span 260</span>         <span case</span> 'link':
<span 261</span>           <span $this</span>-><span onLink();
</span><span 262</span>           <span break</span><span ;
</span><span 263</span> 
<span 264</span>         <span case</span> 'voice':
<span 265</span>           <span $this</span>-><span onVoice();
</span><span 266</span>           <span break</span><span ;
</span><span 267</span>           
<span 268</span>         <span default</span>:
<span 269</span>           <span $this</span>-><span onUnknown();
</span><span 270</span>           <span break</span><span ;
</span><span 271</span> 
<span 272</span> <span       }
</span><span 273</span> <span     }
</span><span 274</span> 
<span 275</span>     <span /*</span><span *
</span><span 276</span> <span      * 自定义的错误处理函数,将 PHP 错误通过文本消息回复显示
</span><span 277</span> <span      * @param  int $level   错误代码
</span><span 278</span> <span      * @param  string $msg  错误内容
</span><span 279</span> <span      * @param  string $file 产生错误的文件
</span><span 280</span> <span      * @param  int $line    产生错误的行数
</span><span 281</span> <span      * @return void
</span><span 282</span>      <span */</span>
<span 283</span>     <span protected</span> <span function</span> errorHandler(<span $level</span>, <span $msg</span>, <span $file</span>, <span $line</span><span ) {
</span><span 284</span>       <span if</span> ( ! <span $this</span>-><span debug) {
</span><span 285</span>         <span return</span><span ;
</span><span 286</span> <span       }
</span><span 287</span> 
<span 288</span>       <span $error_type</span> = <span array</span><span (
</span><span 289</span>         <span //</span><span  E_ERROR             => 'Error',</span>
<span 290</span>         <span E_WARNING</span>           => 'Warning',
<span 291</span>         <span //</span><span  E_PARSE             => 'Parse Error',</span>
<span 292</span>         <span E_NOTICE</span>            => 'Notice',
<span 293</span>         <span //</span><span  E_CORE_ERROR        => 'Core Error',
</span><span 294</span> <span         // E_CORE_WARNING      => 'Core Warning',
</span><span 295</span> <span         // E_COMPILE_ERROR     => 'Compile Error',
</span><span 296</span> <span         // E_COMPILE_WARNING   => 'Compile Warning',</span>
<span 297</span>         <span E_USER_ERROR</span>        => 'User Error',
<span 298</span>         <span E_USER_WARNING</span>      => 'User Warning',
<span 299</span>         <span E_USER_NOTICE</span>       => 'User Notice',
<span 300</span>         <span E_STRICT</span>            => 'Strict',
<span 301</span>         E_RECOVERABLE_ERROR => 'Recoverable Error',
<span 302</span>         E_DEPRECATED        => 'Deprecated',
<span 303</span>         E_USER_DEPRECATED   => 'User Deprecated',
<span 304</span> <span       );
</span><span 305</span> 
<span 306</span>       <span $template</span> = <<<<span ERR
</span><span 307</span> <span PHP 报错啦!
</span><span 308</span> 
<span 309</span> %s: %<span s
</span><span 310</span> <span File</span>: %<span s
</span><span 311</span> Line: %<span s
</span><span 312</span> <span ERR;
</span><span 313</span> 
<span 314</span>       <span $this</span>->responseText(<span sprintf</span>(<span $template</span>,
<span 315</span>         <span $error_type</span>[<span $level</span>],
<span 316</span>         <span $msg</span>,
<span 317</span>         <span $file</span>,
<span 318</span>         <span $line</span>
<span 319</span> <span       ));
</span><span 320</span> <span     }
</span><span 321</span> 
<span 322</span> <span   }
</span><span 323</span> 
<span 324</span>   <span /*</span><span *
</span><span 325</span> <span    * 用于回复的基本消息类型
</span><span 326</span>    <span */</span>
<span 327</span>   <span abstract</span> <span class</span><span  WechatResponse {
</span><span 328</span> 
<span 329</span>     <span protected</span> <span $toUserName</span><span ;
</span><span 330</span>     <span protected</span> <span $fromUserName</span><span ;
</span><span 331</span>     <span protected</span> <span $funcFlag</span><span ;
</span><span 332</span> 
<span 333</span>     <span public</span> <span function</span> __construct(<span $toUserName</span>, <span $fromUserName</span>, <span $funcFlag</span><span ) {
</span><span 334</span>       <span $this</span>->toUserName = <span $toUserName</span><span ;
</span><span 335</span>       <span $this</span>->fromUserName = <span $fromUserName</span><span ;
</span><span 336</span>       <span $this</span>->funcFlag = <span $funcFlag</span><span ;
</span><span 337</span> <span     }
</span><span 338</span> 
<span 339</span>     <span abstract</span> <span public</span> <span function</span><span  __toString();
</span><span 340</span> 
<span 341</span> <span   }
</span><span 342</span> 
<span 343</span> 
<span 344</span>   <span /*</span><span *
</span><span 345</span> <span    * 用于回复的文本消息类型
</span><span 346</span>    <span */</span>
<span 347</span>   <span class</span> TextResponse <span extends</span><span  WechatResponse {
</span><span 348</span> 
<span 349</span>     <span protected</span> <span $content</span><span ;
</span><span 350</span> 
<span 351</span>     <span protected</span> <span $template</span> = <<<<span XML
</span><span 352</span> <xml>
<span 353</span>   <ToUserName><![CDATA[%s]]></ToUserName>
<span 354</span>   <FromUserName><![CDATA[%s]]></FromUserName>
<span 355</span>   <CreateTime>%s</CreateTime>
<span 356</span>   <MsgType><![CDATA[text]]></MsgType>
<span 357</span>   <Content><![CDATA[%s]]></Content>
<span 358</span>   <FuncFlag>%s<FuncFlag>
<span 359</span> </xml>
<span 360</span> <span XML;
</span><span 361</span> 
<span 362</span>     <span public</span> <span function</span> __construct(<span $toUserName</span>, <span $fromUserName</span>, <span $content</span>, <span $funcFlag</span> = 0<span ) {
</span><span 363</span>       parent::__construct(<span $toUserName</span>, <span $fromUserName</span>, <span $funcFlag</span><span );
</span><span 364</span>       <span $this</span>->content = <span $content</span><span ;
</span><span 365</span> <span     }
</span><span 366</span> 
<span 367</span>     <span public</span> <span function</span><span  __toString() {
</span><span 368</span>       <span return</span> <span sprintf</span>(<span $this</span>->template,
<span 369</span>         <span $this</span>->toUserName,
<span 370</span>         <span $this</span>->fromUserName,
<span 371</span>         <span time</span>(),
<span 372</span>         <span $this</span>->content,
<span 373</span>         <span $this</span>-><span funcFlag
</span><span 374</span> <span       );
</span><span 375</span> <span     }
</span><span 376</span> 
<span 377</span> <span   }
</span><span 378</span> 
<span 379</span>   <span /*</span><span *
</span><span 380</span> <span    * 用于回复的音乐消息类型
</span><span 381</span>    <span */</span>
<span 382</span>   <span class</span> MusicResponse <span extends</span><span  WechatResponse {
</span><span 383</span> 
<span 384</span>     <span protected</span> <span $title</span><span ;
</span><span 385</span>     <span protected</span> <span $description</span><span ;
</span><span 386</span>     <span protected</span> <span $musicUrl</span><span ;
</span><span 387</span>     <span protected</span> <span $hqMusicUrl</span><span ;
</span><span 388</span> 
<span 389</span>     <span protected</span> <span $template</span> = <<<<span XML
</span><span 390</span> <xml>
<span 391</span>   <ToUserName><![CDATA[%s]]></ToUserName>
<span 392</span>   <FromUserName><![CDATA[%s]]></FromUserName>
<span 393</span>   <CreateTime>%s</CreateTime>
<span 394</span>   <MsgType><![CDATA[music]]></MsgType>
<span 395</span>   <Music>
<span 396</span>     <Title><![CDATA[%s]]></Title>
<span 397</span>     <Description><![CDATA[%s]]></Description>
<span 398</span>     <MusicUrl><![CDATA[%s]]></MusicUrl>
<span 399</span>     <HQMusicUrl><![CDATA[%s]]></HQMusicUrl>
<span 400</span>   </Music>
<span 401</span>   <FuncFlag>%s<FuncFlag>
<span 402</span> </xml>
<span 403</span> <span XML;
</span><span 404</span> 
<span 405</span>     <span public</span> <span function</span> __construct(<span $toUserName</span>, <span $fromUserName</span>, <span $title</span>, <span $description</span>, <span $musicUrl</span>, <span $hqMusicUrl</span>, <span $funcFlag</span><span ) {
</span><span 406</span>       parent::__construct(<span $toUserName</span>, <span $fromUserName</span>, <span $funcFlag</span><span );
</span><span 407</span>       <span $this</span>->title = <span $title</span><span ;
</span><span 408</span>       <span $this</span>->description = <span $description</span><span ;
</span><span 409</span>       <span $this</span>->musicUrl = <span $musicUrl</span><span ;
</span><span 410</span>       <span $this</span>->hqMusicUrl = <span $hqMusicUrl</span><span ;
</span><span 411</span> <span     }
</span><span 412</span> 
<span 413</span>     <span public</span> <span function</span><span  __toString() {
</span><span 414</span>       <span return</span> <span sprintf</span>(<span $this</span>->template,
<span 415</span>         <span $this</span>->toUserName,
<span 416</span>         <span $this</span>->fromUserName,
<span 417</span>         <span time</span>(),
<span 418</span>         <span $this</span>->title,
<span 419</span>         <span $this</span>->description,
<span 420</span>         <span $this</span>->musicUrl,
<span 421</span>         <span $this</span>->hqMusicUrl,
<span 422</span>         <span $this</span>-><span funcFlag
</span><span 423</span> <span       );
</span><span 424</span> <span     }
</span><span 425</span> 
<span 426</span> <span   }
</span><span 427</span> 
<span 428</span> 
<span 429</span>   <span /*</span><span *
</span><span 430</span> <span    * 用于回复的图文消息类型
</span><span 431</span>    <span */</span>
<span 432</span>   <span class</span> NewsResponse <span extends</span><span  WechatResponse {
</span><span 433</span> 
<span 434</span>     <span protected</span> <span $items</span> = <span array</span><span ();
</span><span 435</span> 
<span 436</span>     <span protected</span> <span $template</span> = <<<<span XML
</span><span 437</span> <xml>
<span 438</span>   <ToUserName><![CDATA[%s]]></ToUserName>
<span 439</span>   <FromUserName><![CDATA[%s]]></FromUserName>
<span 440</span>   <CreateTime>%s</CreateTime>
<span 441</span>   <MsgType><![CDATA[news]]></MsgType>
<span 442</span>   <ArticleCount>%s</ArticleCount>
<span 443</span>   <Articles>
<span 444</span>     %<span s
</span><span 445</span>   </Articles>
<span 446</span>   <FuncFlag>%s<FuncFlag>
<span 447</span> </xml>'
<span 448</span> <span XML;
</span><span 449</span> 
<span 450</span> <span     public function __construct($toUserName, $fromUserName, $items, $funcFlag) {
</span><span 451</span> <span       parent::__construct($toUserName, $fromUserName, $funcFlag);
</span><span 452</span> <span       $this->items = $items;
</span><span 453</span> <span     }
</span><span 454</span> 
<span 455</span> <span     public function __toString() {
</span><span 456</span> <span       return sprintf($this->template,
</span><span 457</span> <span         $this->toUserName,
</span><span 458</span> <span         $this->fromUserName,
</span><span 459</span> <span         time(),
</span><span 460</span> <span         count($this->items),
</span><span 461</span> <span         implode($this->items),
</span><span 462</span> <span         $this->funcFlag
</span><span 463</span> <span       );
</span><span 464</span> <span     }
</span><span 465</span> 
<span 466</span> <span   }
</span><span 467</span> 
<span 468</span> 
<span 469</span> <span   /**
</span><span 470</span> <span    * 单条图文消息类型
</span><span 471</span> <span    */
</span><span 472</span> <span   class NewsResponseItem {
</span><span 473</span> 
<span 474</span> <span     protected $title;
</span><span 475</span> <span     protected $description;
</span><span 476</span> <span     protected $picUrl;
</span><span 477</span> <span     protected $url;
</span><span 478</span> 
<span 479</span> <span     protected $template = <<<XML
</span><span 480</span> <span <item>
</span><span 481</span> <span   <Title><![CDATA[%s]]></Title>
</span><span 482</span> <span   <Description><![CDATA[%s]]></Description>
</span><span 483</span> <span   <PicUrl><![CDATA[%s]]></PicUrl>
</span><span 484</span> <span   <Url><![CDATA[%s]]></Url>
</span><span 485</span> <span </item>
</span><span 486</span> <span XML;
</span><span 487</span> 
<span 488</span> <span     public function __construct($title, $description, $picUrl, $url) {
</span><span 489</span> <span       $this->title = $title;
</span><span 490</span> <span       $this->description = $description;
</span><span 491</span> <span       $this->picUrl = $picUrl;
</span><span 492</span> <span       $this->url = $url;
</span><span 493</span> <span     }
</span><span 494</span> 
<span 495</span> <span     public function __toString() {
</span><span 496</span> <span       return sprintf($this->template,
</span><span 497</span> <span         $this->title,
</span><span 498</span> <span         $this->description,
</span><span 499</span> <span         $this->picUrl,
</span><span 500</span> <span         $this->url
</span><span 501</span> <span       );
</span><span 502</span> <span     }
</span><span 503</span> 
<span 504</span>   }

此基类我稍作了更改,包含了能实现的微信所有的接口,通过继承 `Wechat` 类进行扩展,例如通过重写 `onSubscribe()` 等方法响应关注等请求,下面是实现的示例代码:

<span   1</span> <?<span php
</span><span   2</span> <span /*</span><span *
</span><span   3</span> <span  * 微信公众平台 PHP SDK 示例文件
</span><span   4</span> <span  *
</span><span   5</span> <span  * @author hanc <congcongsky2010@gmail.com>
</span><span   6</span>  <span */</span>
<span   7</span> 
<span   8</span>   <span require</span>('src/Wechat.php'<span );
</span><span   9</span> 
<span  10</span>   <span /*</span><span *
</span><span  11</span> <span    * 微信公众平台演示类
</span><span  12</span>    <span */</span>
<span  13</span>   <span class</span> MyWechat <span extends</span><span  Wechat {
</span><span  14</span> 
<span  15</span>     <span /*</span><span *
</span><span  16</span> <span      * 用户关注时触发,回复「欢迎关注」
</span><span  17</span> <span      *
</span><span  18</span> <span      * @return void
</span><span  19</span>      <span */</span>
<span  20</span>     <span protected</span> <span function</span><span  onSubscribe() {
</span><span  21</span>       <span $this</span>->responseText('欢迎关注韩聪的微信号'<span );
</span><span  22</span> <span     }
</span><span  23</span> 
<span  24</span>     <span /*</span><span *
</span><span  25</span> <span      * 用户取消关注时触发
</span><span  26</span> <span      *
</span><span  27</span> <span      * @return void
</span><span  28</span>      <span */</span>
<span  29</span>     <span protected</span> <span function</span><span  onUnsubscribe() {
</span><span  30</span>       <span //</span><span  「悄悄的我走了,正如我悄悄的来;我挥一挥衣袖,不带走一片云彩。」</span>
<span  31</span> <span     }
</span><span  32</span> 
<span  33</span>     <span /*</span><span *
</span><span  34</span> <span      * 用户自动上报地理位置时触发
</span><span  35</span> <span      *
</span><span  36</span> <span      * @return void
</span><span  37</span>      <span */</span>
<span  38</span>     <span protected</span> <span function</span><span  onAutoloaction() {
</span><span  39</span> 
<span  40</span>       <span $this</span>->responseText('您的地理位置为:' . <span $this</span>->getRequest('Latitude') . ',' . <span $this</span>->getRequest('Longitude'<span ));
</span><span  41</span> <span     }
</span><span  42</span>       
<span  43</span>     <span /*</span><span *
</span><span  44</span> <span      * 用户点击菜单时触发
</span><span  45</span> <span      *
</span><span  46</span> <span      * @return void
</span><span  47</span>      <span */</span>
<span  48</span>     <span protected</span> <span function</span><span  onClick() {
</span><span  49</span>        <span $eventKey</span>=<span $this</span>->getRequest('EventKey'<span );
</span><span  50</span>        <span switch</span>(<span $eventKey</span><span ){
</span><span  51</span>          <span case</span> 'C001':
<span  52</span>            <span $this</span>->responseText('我赢了'<span );
</span><span  53</span>            <span break</span><span ;
</span><span  54</span>          <span case</span> 'C002':
<span  55</span>            <span $this</span>->responseText('我最近很好o(&cap;_&cap;)o '<span );
</span><span  56</span>            <span break</span><span ;
</span><span  57</span>          <span case</span> 'C003':
<span  58</span>            <span $this</span>->responseText('谢谢(*^__^*) 嘻嘻'<span );
</span><span  59</span>            <span break</span><span ;
</span><span  60</span> <span        }
</span><span  61</span> <span     }
</span><span  62</span>     
<span  63</span>     <span /*</span><span *
</span><span  64</span> <span      * 收到文本消息时触发,回复收到的文本消息内容
</span><span  65</span> <span      *
</span><span  66</span> <span      * @return void
</span><span  67</span>      <span */</span>
<span  68</span>     <span protected</span> <span function</span><span  onText() {
</span><span  69</span>       <span $this</span>->responseText('收到了文字消息:' . <span $this</span>->getRequest('content'<span ));
</span><span  70</span> <span     }
</span><span  71</span> 
<span  72</span>     <span /*</span><span *
</span><span  73</span> <span      * 收到图片消息时触发,回复由收到的图片组成的图文消息
</span><span  74</span> <span      *
</span><span  75</span> <span      * @return void
</span><span  76</span>      <span */</span>
<span  77</span>     <span protected</span> <span function</span><span  onImage() {
</span><span  78</span>       <span $items</span> = <span array</span><span (
</span><span  79</span>         <span new</span> NewsResponseItem('标题一', '描述一', <span $this</span>->getRequest('picurl'), <span $this</span>->getRequest('picurl')),
<span  80</span>         <span new</span> NewsResponseItem('标题二', '描述二', <span $this</span>->getRequest('picurl'), <span $this</span>->getRequest('picurl')),
<span  81</span> <span       );
</span><span  82</span> 
<span  83</span>       <span $this</span>->responseNews(<span $items</span><span );
</span><span  84</span> <span     }
</span><span  85</span> 
<span  86</span>     <span /*</span><span *
</span><span  87</span> <span      * 收到地理位置消息时触发,回复收到的地理位置
</span><span  88</span> <span      *
</span><span  89</span> <span      * @return void
</span><span  90</span>      <span */</span>
<span  91</span>     <span protected</span> <span function</span><span  onLocation() {
</span><span  92</span>         <span //</span><span $num = 1 / 0;
</span><span  93</span> <span       // 故意触发错误,用于演示调试功能</span>
<span  94</span> 
<span  95</span>       <span $this</span>->responseText('收到了位置消息:' . <span $this</span>->getRequest('location_x') . ',' . <span $this</span>->getRequest('location_y'<span ));
</span><span  96</span> <span     }
</span><span  97</span> 
<span  98</span>     <span /*</span><span *
</span><span  99</span> <span      * 收到链接消息时触发,回复收到的链接地址
</span><span 100</span> <span      *
</span><span 101</span> <span      * @return void
</span><span 102</span>      <span */</span>
<span 103</span>     <span protected</span> <span function</span><span  onLink() {
</span><span 104</span>       <span $this</span>->responseText('收到了链接:' . <span $this</span>->getRequest('url'<span ));
</span><span 105</span> <span     }
</span><span 106</span>       
<span 107</span>      <span /*</span><span *
</span><span 108</span> <span      * 收到语音消息时触发,回复收到的语音
</span><span 109</span> <span      *
</span><span 110</span> <span      * @return void
</span><span 111</span>      <span */</span>
<span 112</span>     <span protected</span> <span function</span><span  onVoice() {
</span><span 113</span>       <span $this</span>->responseVoice('收到了语音:' . <span $this</span>->getRequest('recognition'<span ));
</span><span 114</span> <span     }
</span><span 115</span> 
<span 116</span>     <span /*</span><span *
</span><span 117</span> <span      * 收到未知类型消息时触发,回复收到的消息类型
</span><span 118</span> <span      *
</span><span 119</span> <span      * @return void
</span><span 120</span>      <span */</span>
<span 121</span>     <span protected</span> <span function</span><span  onUnknown() {
</span><span 122</span>       <span $this</span>->responseText('收到了未知类型消息:' . <span $this</span>->getRequest('msgtype'<span ));
</span><span 123</span> <span     }
</span><span 124</span> 
<span 125</span> <span   }
</span><span 126</span> 
<span 127</span>   <span $wechat</span> = <span new</span> MyWechat('hancong', <span TRUE</span><span );
</span><span 128</span>   <span $wechat</span>->run();

以上代码部分功能需要开通服务号并且申请认证,比如语音识别,地理信息,添加菜单的功能,申请认证需要300元/年,可以享受微信所有的接口功能。

 

注:如果验证服务器URL,需要修改一句代码

<span $wechat</span> = <span new</span> MyWechat('hancong', <span TRUE</span><span );
</span><span //</span><span $wechat->run();</span>
<span $wechat</span>->validateSignature('hancong');<span //</span><span 参数为填写的token</span>

验证完后回复调用run方法,validateSignature方法只是第一次验证服务器调用,验证完后即可删掉。

 

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。