最近公司用到了微信公众平台,所以研究了一下微信公众号的开发技术,总体来说比较简单,结合现有的平台核技术,实现起来非常方便。
首先先来了解一下微信公众平台。
“微信,是一个生活方式” ,这是微信的自我评价,是不是觉得如果那天不在朋友圈里分享一下自己的最新状态,
并且收到几个赞和评价的话,会觉得空虚寂寞呢?它实实在在的改变了我们的生活方式。
“ 微信,也是一个生意方式 ”,在微信成为我们日常必备之app的同时,它同样具备巨大的的商业
或许不应该称为潜力,因为有很多人已经获利,名人们在微信上开设公众账户来吸金,商家来做推广,
服务行业借此拓展渠道,甚至微信已经支持支付了, 还有越来越的自媒体在微信平台涌现出来。
这篇文章就是介绍如何快速的成为公众平台开发者,由于个人只能申请订阅号,因此本文是以订阅号为例。
关于订阅号和服务号的区别,请参见 微信公众平台服务号、订阅号的相关说明。
从微信用户角度简单来说:
订阅号 主要用于信息辐射,典型的如各家 新闻媒体 。
服务号 主要由于自助服务,典型的如 招商银行 。
关于微信公众帐号注册的步骤就不再多说了,可以找到大量的图文教程。
帐号注册成功之后,需要验证自己的服务器,如果你没有自己的服务器,那可以用新浪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(∩_∩)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方法只是第一次验证服务器调用,验证完后即可删掉。