微信公众平台开发者中心安全模式消息体加解密实现,公众开发者
微信公众平台开发者中心安全模式消息体加解密实现,公众开发者
关键字:微信公众平台 消息体签名 消息体加解密 EncodingAESKey 安全模式
原文 http://www.cnblogs.com/txw1958/p/weixin-aes-encrypt-decrypt.html
一、消息体加解密
微信公众平台在配置服务器时,提供了3种加解密的模式供开发者选择,即明文模式、兼容模式、安全模式,选择兼容模式和安全模式前,需在开发者中心填写消息加解密密钥EncodingAESKey。
- 明文模式:维持现有模式,没有适配加解密新特性,消息体明文收发,默认设置为明文模式
- 兼容模式:公众平台发送消息内容将同时包括明文和密文,消息包长度增加到原来的3倍左右;公众号回复明文或密文均可,不影响现有消息收发;开发者可在此模式下进行调试
- 安全模式(推荐):公众平台发送消息体的内容只含有密文,公众账号回复的消息体也为密文,建议开发者在调试成功后使用此模式收发消息
什么是EncodingAESKey?
- 微信公众平台采用AES对称加密算法对推送给公众帐号的消息体对行加密,EncodingAESKey则是加密所用的秘钥。公众帐号用此秘钥对收到的密文消息体进行解密,回复消息体也用此秘钥加密。AES对称加密算法的原理可以参考 http://www.cnblogs.com/txw1958/p/aes.html
加解密的详细技术方案可以参考官方文档 http://mp.weixin.qq.com/wiki/index.php?title=%E6%8A%80%E6%9C%AF%E6%96%B9%E6%A1%88
适用公众账号类型
- 已认证订阅号
- 服务号
不能用于未认证订阅号,因为其没有appid参数
二、开发实现及数据分析
1. 配置
假设本次的开发配置中URL为
http:<span>//</span><span>www.fangbei.org/index.php</span>
接口程序中需要配置以下三项参数
<span>/*</span><span> 方倍工作室 http://www.cnblogs.com/txw1958/ CopyRight 2014 All Rights Reserved </span><span>*/</span> <span>define</span>("TOKEN", "weixin"<span>); </span><span>define</span>("AppID", "wxbad0b45542aa0b5e"<span>); </span><span>define</span>("EncodingAESKey", "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFG"<span>); </span><span>require_once</span>('wxBizMsgCrypt.php');
2. 加解密实现
当用户向公众账号发送消息时,微信公众账号将会在URL中带上signature、timestamp、nonce、encrypt_type、msg_signature等参数,如下所示
http:<span>//</span><span>www.fangbei.org/index.php?signature=35703636de2f9df2a77a662b68e521ce17c34db4×tamp=1414243737&nonce=1792106704&encrypt_type=aes&msg_signature=6147984331daf7a1a9eed6e0ec3ba69055256154</span>
同时向该接口推送如下XML消息 ,即一个已加密的消息
<span><</span><span>xml</span><span>></span> <span><</span><span>ToUserName</span><span>></span><span><![CDATA[</span><span>gh_680bdefc8c5d</span><span>]]></span><span></</span><span>ToUserName</span><span>></span> <span><</span><span>Encrypt</span><span>></span><span><![CDATA[</span><span>MNn4+jJ/VsFh2gUyKAaOJArwEVYCvVmyN0iXzNarP3O6vXzK62ft1/KG2/XPZ4y5bPWU/jfIfQxODRQ7sLkUsrDRqsWimuhIT8Eq+w4E/28m+XDAQKEOjWTQIOp1p6kNsIV1DdC3B+AtcKcKSNAeJDr7x7GHLx5DZYK09qQsYDOjP6R5NqebFjKt/NpEl/GU3gWFwG8LCtRNuIYdK5axbFSfmXbh5CZ6Bk5wSwj5fu5aS90cMAgUhGsxrxZTY562QR6c+3ydXxb+GHI5w+qA+eqJjrQqR7u5hS+1x5sEsA7vS+bZ5LYAR3+PZ243avQkGllQ+rg7a6TeSGDxxhvLw+mxxinyk88BNHkJnyK//hM1k9PuvuLAASdaud4vzRQlAmnYOslZl8CN7gjCjV41skUTZv3wwGPxvEqtm/nf5fQ=</span><span>]]></span><span></</span><span>Encrypt</span><span>></span> <span></</span><span>xml</span><span>></span>
这时,程序需要从url中获得以下参数
<span>$timestamp</span> = <span>$_GET</span>['timestamp'<span>]; </span><span>$nonce</span> = <span>$_GET</span>["nonce"<span>]; </span><span>$msg_signature</span> = <span>$_GET</span>['msg_signature'<span>]; </span><span>$encrypt_type</span> = <span>$_GET</span>['encrypt_type'];
这些参数将用于加解密过程
收到消息后,先进行解密,解密部分代码如下
<span>$postStr</span> = <span>$GLOBALS</span>["HTTP_RAW_POST_DATA"<span>]; </span><span>if</span> (<span>$encrypt_type</span> == 'aes'<span>){ </span><span>$pc</span> = <span>new</span> WXBizMsgCrypt(TOKEN, EncodingAESKey,<span> AppID); </span><span>$this</span>->logger(" D \r\n".<span>$postStr</span><span>); </span><span>$decryptMsg</span> = ""; <span>//</span><span>解密后的明文</span> <span>$errCode</span> = <span>$pc</span>->DecryptMsg(<span>$msg_signature</span>, <span>$timestamp</span>, <span>$nonce</span>, <span>$postStr</span>, <span>$decryptMsg</span><span>); </span><span>$postStr</span> = <span>$decryptMsg</span><span>; }</span>
解密完成后,把解密内容又返回给$postStr,这是为了保证将消息中解密后的内容和明文模式时的消息统一,方便后续处理,解密后的XML如下
<span><</span><span>xml</span><span>></span> <span><</span><span>ToUserName</span><span>></span><span><![CDATA[</span><span>gh_680bdefc8c5d</span><span>]]></span><span></</span><span>ToUserName</span><span>></span> <span><</span><span>FromUserName</span><span>></span><span><![CDATA[</span><span>oIDrpjpQ8j8mBuQ8nM26HWzNEZgg</span><span>]]></span><span></</span><span>FromUserName</span><span>></span> <span><</span><span>CreateTime</span><span>></span>1414243737<span></</span><span>CreateTime</span><span>></span> <span><</span><span>MsgType</span><span>></span><span><![CDATA[</span><span>text</span><span>]]></span><span></</span><span>MsgType</span><span>></span> <span><</span><span>Content</span><span>></span><span><![CDATA[</span><span>?</span><span>]]></span><span></</span><span>Content</span><span>></span> <span><</span><span>MsgId</span><span>></span>6074130599188426998<span></</span><span>MsgId</span><span>></span> <span></</span><span>xml</span><span>></span>
对消息在自己的原来代码中处理,完成之后,要回复的消息如下
<span><</span><span>xml</span><span>></span> <span><</span><span>ToUserName</span><span>></span><span><![CDATA[</span><span>oIDrpjpQ8j8mBuQ8nM26HWzNEZgg</span><span>]]></span><span></</span><span>ToUserName</span><span>></span> <span><</span><span>FromUserName</span><span>></span><span><![CDATA[</span><span>gh_680bdefc8c5d</span><span>]]></span><span></</span><span>FromUserName</span><span>></span> <span><</span><span>CreateTime</span><span>></span>1414243733<span></</span><span>CreateTime</span><span>></span> <span><</span><span>MsgType</span><span>></span><span><![CDATA[</span><span>text</span><span>]]></span><span></</span><span>MsgType</span><span>></span> <span><</span><span>Content</span><span>></span><span><![CDATA[</span><span>2014-10-25 21:28:53 技术支持 方倍工作室 http://www.fangbei.org/</span><span>]]></span><span></</span><span>Content</span><span>></span> <span></</span><span>xml</span><span>></span>
把上述消息进行加密,返回给微信公众账号
<span>//</span><span>加密</span> <span>if</span> (<span>$encrypt_type</span> == 'aes'<span>){ </span><span>$encryptMsg</span> = ''; <span>//</span><span>加密后的密文</span> <span>$errCode</span> = <span>$pc</span>->encryptMsg(<span>$result</span>, <span>$timeStamp</span>, <span>$nonce</span>, <span>$encryptMsg</span><span>); </span><span>$result</span> = <span>$encryptMsg</span><span>; </span><span>$this</span>->logger(" E \r\n".<span>$result</span><span>); }</span>
加密后的内容如下
<span><</span><span>xml</span><span>></span> <span><</span><span>Encrypt</span><span>></span><span><![CDATA[</span><span>pE6gp6qvVBMHwCXwnM7illFBrh9LmvlKFlPUDuyQo9EKNunqbUFMd2KjiYoz+3K1B+93JbMWHt+19TI8awdRdyopRS4oUNg5M2jwpwXTmc6TtafkKNjvqlvPXIWmutw0tuMXke1hDgsqz0SC8h/QjNLxECuwnczrfCMJlt+APHnX2yMMaq/aYUNcndOH387loQvl2suCGucXpglnbxf7frTCz9NQVgKiYrvKOhk6KFiVMnzuxy6WWmoe3GBiUCPTtYf5b1CxzN2IHViEBm28ilV9wWdNOM9TPG7BSSAcpgY4pcwdIG5+4KhgYmnVU3bc/ZJkk42TIdidigOfFpJwET4UWVrLB/ldUud4aPexp3aPCR3Fe53S2HHcl3tTxh4iRvDftUKP3svYPctt1MlYuYv/BZ4JyzUQV03H+0XrVyDY2tyVjimgCrA2c1mZMgHttOHTQ6VTnxrMq0GWlRlH0KPQKqtjUpNQzuOH4upQ8boPsEtuY3wDA2RaXQPJrXon</span><span>]]></span><span></</span><span>Encrypt</span><span>></span> <span><</span><span>MsgSignature</span><span>></span><span><![CDATA[</span><span>6c46904dc1f58b2ddf2dd0399f1c6cf41f33ecb9</span><span>]]></span><span></</span><span>MsgSignature</span><span>></span> <span><</span><span>TimeStamp</span><span>></span>1414243733<span></</span><span>TimeStamp</span><span>></span> <span><</span><span>Nonce</span><span>></span><span><![CDATA[</span><span>1792106704</span><span>]]></span><span></</span><span>Nonce</span><span>></span> <span></</span><span>xml</span><span>></span>
这样,一个安全模式下的加解密消息就完成了。
三、完整代码
<span> 1</span> <?<span>php </span><span> 2</span> <span>/*</span> <span> 3</span> <span> 方倍工作室 http://www.cnblogs.com/txw1958/ </span><span> 4</span> <span> CopyRight 2014 All Rights Reserved </span><span> 5</span> <span>*/</span> <span> 6</span> <span>define</span>("TOKEN", "weixin"<span>); </span><span> 7</span> <span>define</span>("AppID", "wxbad0b45542aa0b5e"<span>); </span><span> 8</span> <span>define</span>("EncodingAESKey", "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFG"<span>); </span><span> 9</span> <span>require_once</span>('wxBizMsgCrypt.php'<span>); </span><span> 10</span> <span> 11</span> <span>$wechatObj</span> = <span>new</span><span> wechatCallbackapiTest(); </span><span> 12</span> <span>if</span> (!<span>isset</span>(<span>$_GET</span>['echostr'<span>])) { </span><span> 13</span> <span>$wechatObj</span>-><span>responseMsg(); </span><span> 14</span> }<span>else</span><span>{ </span><span> 15</span> <span>$wechatObj</span>-><span>valid(); </span><span> 16</span> <span>} </span><span> 17</span> <span> 18</span> <span>class</span><span> wechatCallbackapiTest </span><span> 19</span> <span>{ </span><span> 20</span> <span>//</span><span>验证签名</span> <span> 21</span> <span>public</span> <span>function</span><span> valid() </span><span> 22</span> <span> { </span><span> 23</span> <span>$echoStr</span> = <span>$_GET</span>["echostr"<span>]; </span><span> 24</span> <span>$signature</span> = <span>$_GET</span>["signature"<span>]; </span><span> 25</span> <span>$timestamp</span> = <span>$_GET</span>["timestamp"<span>]; </span><span> 26</span> <span>$nonce</span> = <span>$_GET</span>["nonce"<span>]; </span><span> 27</span> <span>$tmpArr</span> = <span>array</span>(TOKEN, <span>$timestamp</span>, <span>$nonce</span><span>); </span><span> 28</span> <span>sort</span>(<span>$tmpArr</span><span>); </span><span> 29</span> <span>$tmpStr</span> = <span>implode</span>(<span>$tmpArr</span><span>); </span><span> 30</span> <span>$tmpStr</span> = <span>sha1</span>(<span>$tmpStr</span><span>); </span><span> 31</span> <span>if</span>(<span>$tmpStr</span> == <span>$signature</span><span>){ </span><span> 32</span> <span>echo</span> <span>$echoStr</span><span>; </span><span> 33</span> <span>exit</span><span>; </span><span> 34</span> <span> } </span><span> 35</span> <span> } </span><span> 36</span> <span> 37</span> <span>//</span><span>响应消息</span> <span> 38</span> <span>public</span> <span>function</span><span> responseMsg() </span><span> 39</span> <span> { </span><span> 40</span> <span>$timestamp</span> = <span>$_GET</span>['timestamp'<span>]; </span><span> 41</span> <span>$nonce</span> = <span>$_GET</span>["nonce"<span>]; </span><span> 42</span> <span>$msg_signature</span> = <span>$_GET</span>['msg_signature'<span>]; </span><span> 43</span> <span>$encrypt_type</span> = (<span>isset</span>(<span>$_GET</span>['encrypt_type']) && (<span>$_GET</span>['encrypt_type'] == 'aes')) ? "aes" : "raw"<span>; </span><span> 44</span> <span> 45</span> <span>$postStr</span> = <span>$GLOBALS</span>["HTTP_RAW_POST_DATA"<span>]; </span><span> 46</span> <span>if</span> (!<span>empty</span>(<span>$postStr</span><span>)){ </span><span> 47</span> <span>//</span><span>解密</span> <span> 48</span> <span>if</span> (<span>$encrypt_type</span> == 'aes'<span>){ </span><span> 49</span> <span>$pc</span> = <span>new</span> WXBizMsgCrypt(TOKEN, EncodingAESKey,<span> AppID); </span><span> 50</span> <span>$this</span>->logger(" D \r\n".<span>$postStr</span><span>); </span><span> 51</span> <span>$decryptMsg</span> = ""; <span>//</span><span>解密后的明文</span> <span> 52</span> <span>$errCode</span> = <span>$pc</span>->DecryptMsg(<span>$msg_signature</span>, <span>$timestamp</span>, <span>$nonce</span>, <span>$postStr</span>, <span>$decryptMsg</span><span>); </span><span> 53</span> <span>$postStr</span> = <span>$decryptMsg</span><span>; </span><span> 54</span> <span> } </span><span> 55</span> <span>$this</span>->logger(" R \r\n".<span>$postStr</span><span>); </span><span> 56</span> <span>$postObj</span> = <span>simplexml_load_string</span>(<span>$postStr</span>, 'SimpleXMLElement',<span> LIBXML_NOCDATA); </span><span> 57</span> <span>$RX_TYPE</span> = <span>trim</span>(<span>$postObj</span>-><span>MsgType); </span><span> 58</span> <span> 59</span> <span>//</span><span>消息类型分离</span> <span> 60</span> <span>switch</span> (<span>$RX_TYPE</span><span>) </span><span> 61</span> <span> { </span><span> 62</span> <span>case</span> "event": <span> 63</span> <span>$result</span> = <span>$this</span>->receiveEvent(<span>$postObj</span><span>); </span><span> 64</span> <span>break</span><span>; </span><span> 65</span> <span>case</span> "text": <span> 66</span> <span>$result</span> = <span>$this</span>->receiveText(<span>$postObj</span><span>); </span><span> 67</span> <span>break</span><span>; </span><span> 68</span> <span> } </span><span> 69</span> <span>$this</span>->logger(" R \r\n".<span>$result</span><span>); </span><span> 70</span> <span>//</span><span>加密</span> <span> 71</span> <span>if</span> (<span>$encrypt_type</span> == 'aes'<span>){ </span><span> 72</span> <span>$encryptMsg</span> = ''; <span>//</span><span>加密后的密文</span> <span> 73</span> <span>$errCode</span> = <span>$pc</span>->encryptMsg(<span>$result</span>, <span>$timeStamp</span>, <span>$nonce</span>, <span>$encryptMsg</span><span>); </span><span> 74</span> <span>$result</span> = <span>$encryptMsg</span><span>; </span><span> 75</span> <span>$this</span>->logger(" E \r\n".<span>$result</span><span>); </span><span> 76</span> <span> } </span><span> 77</span> <span>echo</span> <span>$result</span><span>; </span><span> 78</span> }<span>else</span><span> { </span><span> 79</span> <span>echo</span> ""<span>; </span><span> 80</span> <span>exit</span><span>; </span><span> 81</span> <span> } </span><span> 82</span> <span> } </span><span> 83</span> <span> 84</span> <span>//</span><span>接收事件消息</span> <span> 85</span> <span>private</span> <span>function</span> receiveEvent(<span>$object</span><span>) </span><span> 86</span> <span> { </span><span> 87</span> <span>$content</span> = ""<span>; </span><span> 88</span> <span>switch</span> (<span>$object</span>-><span>Event) </span><span> 89</span> <span> { </span><span> 90</span> <span>case</span> "subscribe": <span> 91</span> <span>$content</span> = "欢迎关注方倍工作室 "<span>; </span><span> 92</span> <span>break</span><span>; </span><span> 93</span> <span> } </span><span> 94</span> <span> 95</span> <span>$result</span> = <span>$this</span>->transmitText(<span>$object</span>, <span>$content</span><span>); </span><span> 96</span> <span>return</span> <span>$result</span><span>; </span><span> 97</span> <span> } </span><span> 98</span> <span> 99</span> <span>//</span><span>接收文本消息</span> <span>100</span> <span>private</span> <span>function</span> receiveText(<span>$object</span><span>) </span><span>101</span> <span> { </span><span>102</span> <span>$keyword</span> = <span>trim</span>(<span>$object</span>-><span>Content); </span><span>103</span> <span>if</span> (<span>strstr</span>(<span>$keyword</span>, "文本"<span>)){ </span><span>104</span> <span>$content</span> = "这是个文本消息"<span>; </span><span>105</span> }<span>else</span> <span>if</span> (<span>strstr</span>(<span>$keyword</span>, "单图文"<span>)){ </span><span>106</span> <span>$content</span> = <span>array</span><span>(); </span><span>107</span> <span>$content</span>[] = <span>array</span>("Title"=>"单图文标题", "Description"=>"单图文内容", "PicUrl"=>"http://discuz.comli.com/weixin/weather/icon/cartoon.jpg", "Url" =>"http://m.cnblogs.com/?u=txw1958"<span>); </span><span>108</span> }<span>else</span> <span>if</span> (<span>strstr</span>(<span>$keyword</span>, "图文") || <span>strstr</span>(<span>$keyword</span>, "多图文"<span>)){ </span><span>109</span> <span>$content</span> = <span>array</span><span>(); </span><span>110</span> <span>$content</span>[] = <span>array</span>("Title"=>"多图文1标题", "Description"=>"", "PicUrl"=>"http://discuz.comli.com/weixin/weather/icon/cartoon.jpg", "Url" =>"http://m.cnblogs.com/?u=txw1958"<span>); </span><span>111</span> <span>$content</span>[] = <span>array</span>("Title"=>"多图文2标题", "Description"=>"", "PicUrl"=>"http://d.hiphotos.bdimg.com/wisegame/pic/item/f3529822720e0cf3ac9f1ada0846f21fbe09aaa3.jpg", "Url" =>"http://m.cnblogs.com/?u=txw1958"<span>); </span><span>112</span> <span>$content</span>[] = <span>array</span>("Title"=>"多图文3标题", "Description"=>"", "PicUrl"=>"http://g.hiphotos.bdimg.com/wisegame/pic/item/18cb0a46f21fbe090d338acc6a600c338644adfd.jpg", "Url" =>"http://m.cnblogs.com/?u=txw1958"<span>); </span><span>113</span> }<span>else</span> <span>if</span> (<span>strstr</span>(<span>$keyword</span>, "音乐"<span>)){ </span><span>114</span> <span>$content</span> = <span>array</span><span>(); </span><span>115</span> <span>$content</span> = <span>array</span>("Title"=>"最炫民族风", "Description"=>"歌手:凤凰传奇", "MusicUrl"=>"http://121.199.4.61/music/zxmzf.mp3", "HQMusicUrl"=>"http://121.199.4.61/music/zxmzf.mp3"<span>); </span><span>116</span> }<span>else</span><span>{ </span><span>117</span> <span>$content</span> = <span>date</span>("Y-m-d H:i:s",<span>time</span>())."\n".<span>$object</span>->FromUserName."\n技术支持 方倍工作室"<span>; </span><span>118</span> <span> } </span><span>119</span> <span>120</span> <span>if</span>(<span>is_array</span>(<span>$content</span><span>)){ </span><span>121</span> <span>if</span> (<span>isset</span>(<span>$content</span>[0<span>])){ </span><span>122</span> <span>$result</span> = <span>$this</span>->transmitNews(<span>$object</span>, <span>$content</span><span>); </span><span>123</span> }<span>else</span> <span>if</span> (<span>isset</span>(<span>$content</span>['MusicUrl'<span>])){ </span><span>124</span> <span>$result</span> = <span>$this</span>->transmitMusic(<span>$object</span>, <span>$content</span><span>); </span><span>125</span> <span> } </span><span>126</span> }<span>else</span><span>{ </span><span>127</span> <span>$result</span> = <span>$this</span>->transmitText(<span>$object</span>, <span>$content</span><span>); </span><span>128</span> <span> } </span><span>129</span> <span>return</span> <span>$result</span><span>; </span><span>130</span> <span> } </span><span>131</span> <span>132</span> <span>//</span><span>回复文本消息</span> <span>133</span> <span>private</span> <span>function</span> transmitText(<span>$object</span>, <span>$content</span><span>) </span><span>134</span> <span> { </span><span>135</span> <span>$xmlTpl</span> = "<span><xml> </span><span>136</span> <span> <ToUserName><![CDATA[%s]]></ToUserName> </span><span>137</span> <span> <FromUserName><![CDATA[%s]]></FromUserName> </span><span>138</span> <span> <CreateTime>%s</CreateTime> </span><span>139</span> <span> <MsgType><![CDATA[text]]></MsgType> </span><span>140</span> <span> <Content><![CDATA[%s]]></Content> </span><span>141</span> </xml>"<span>; </span><span>142</span> <span>$result</span> = <span>sprintf</span>(<span>$xmlTpl</span>, <span>$object</span>->FromUserName, <span>$object</span>->ToUserName, <span>time</span>(), <span>$content</span><span>); </span><span>143</span> <span>return</span> <span>$result</span><span>; </span><span>144</span> <span> } </span><span>145</span> <span>146</span> <span>//</span><span>回复图文消息</span> <span>147</span> <span>private</span> <span>function</span> transmitNews(<span>$object</span>, <span>$newsArray</span><span>) </span><span>148</span> <span> { </span><span>149</span> <span>if</span>(!<span>is_array</span>(<span>$newsArray</span><span>)){ </span><span>150</span> <span>return</span><span>; </span><span>151</span> <span> } </span><span>152</span> <span>$itemTpl</span> = "<span> <item> </span><span>153</span> <span> <Title><![CDATA[%s]]></Title> </span><span>154</span> <span> <Description><![CDATA[%s]]></Description> </span><span>155</span> <span> <PicUrl><![CDATA[%s]]></PicUrl> </span><span>156</span> <span> <Url><![CDATA[%s]]></Url> </span><span>157</span> <span> </item> </span><span>158</span> "<span>; </span><span>159</span> <span>$item_str</span> = ""<span>; </span><span>160</span> <span>foreach</span> (<span>$newsArray</span> <span>as</span> <span>$item</span><span>){ </span><span>161</span> <span>$item_str</span> .= <span>sprintf</span>(<span>$itemTpl</span>, <span>$item</span>['Title'], <span>$item</span>['Description'], <span>$item</span>['PicUrl'], <span>$item</span>['Url'<span>]); </span><span>162</span> <span> } </span><span>163</span> <span>$xmlTpl</span> = "<span><xml> </span><span>164</span> <span> <ToUserName><![CDATA[%s]]></ToUserName> </span><span>165</span> <span> <FromUserName><![CDATA[%s]]></FromUserName> </span><span>166</span> <span> <CreateTime>%s</CreateTime> </span><span>167</span> <span> <MsgType><![CDATA[news]]></MsgType> </span><span>168</span> <span> <ArticleCount>%s</ArticleCount> </span><span>169</span> <span> <Articles> </span><span>170</span> <span>$item_str</span><span> </Articles> </span><span>171</span> </xml>"<span>; </span><span>172</span> <span>173</span> <span>$result</span> = <span>sprintf</span>(<span>$xmlTpl</span>, <span>$object</span>->FromUserName, <span>$object</span>->ToUserName, <span>time</span>(), <span>count</span>(<span>$newsArray</span><span>)); </span><span>174</span> <span>return</span> <span>$result</span><span>; </span><span>175</span> <span> } </span><span>176</span> <span>177</span> <span>//</span><span>回复音乐消息</span> <span>178</span> <span>private</span> <span>function</span> transmitMusic(<span>$object</span>, <span>$musicArray</span><span>) </span><span>179</span> <span> { </span><span>180</span> <span>$itemTpl</span> = "<span><Music> </span><span>181</span> <span> <Title><![CDATA[%s]]></Title> </span><span>182</span> <span> <Description><![CDATA[%s]]></Description> </span><span>183</span> <span> <MusicUrl><![CDATA[%s]]></MusicUrl> </span><span>184</span> <span> <HQMusicUrl><![CDATA[%s]]></HQMusicUrl> </span><span>185</span> </Music>"<span>; </span><span>186</span> <span>187</span> <span>$item_str</span> = <span>sprintf</span>(<span>$itemTpl</span>, <span>$musicArray</span>['Title'], <span>$musicArray</span>['Description'], <span>$musicArray</span>['MusicUrl'], <span>$musicArray</span>['HQMusicUrl'<span>]); </span><span>188</span> <span>189</span> <span>$xmlTpl</span> = "<span><xml> </span><span>190</span> <span> <ToUserName><![CDATA[%s]]></ToUserName> </span><span>191</span> <span> <FromUserName><![CDATA[%s]]></FromUserName> </span><span>192</span> <span> <CreateTime>%s</CreateTime> </span><span>193</span> <span> <MsgType><![CDATA[music]]></MsgType> </span><span>194</span> <span>$item_str</span> <span>195</span> </xml>"<span>; </span><span>196</span> <span>197</span> <span>$result</span> = <span>sprintf</span>(<span>$xmlTpl</span>, <span>$object</span>->FromUserName, <span>$object</span>->ToUserName, <span>time</span><span>()); </span><span>198</span> <span>return</span> <span>$result</span><span>; </span><span>199</span> <span> } </span><span>200</span> <span>201</span> <span>//</span><span>日志记录</span> <span>202</span> <span>public</span> <span>function</span> logger(<span>$log_content</span><span>) </span><span>203</span> <span> { </span><span>204</span> <span>if</span>(<span>isset</span>(<span>$_SERVER</span>['HTTP_APPNAME'])){ <span>//</span><span>SAE</span> <span>205</span> sae_set_display_errors(<span>false</span><span>); </span><span>206</span> sae_debug(<span>$log_content</span><span>); </span><span>207</span> sae_set_display_errors(<span>true</span><span>); </span><span>208</span> }<span>else</span> <span>if</span>(<span>$_SERVER</span>['REMOTE_ADDR'] != "127.0.0.1"){ <span>//</span><span>LOCAL</span> <span>209</span> <span>$max_size</span> = 500000<span>; </span><span>210</span> <span>$log_filename</span> = "log.xml"<span>; </span><span>211</span> <span>if</span>(<span>file_exists</span>(<span>$log_filename</span>) and (<span>abs</span>(<span>filesize</span>(<span>$log_filename</span>)) > <span>$max_size</span>)){<span>unlink</span>(<span>$log_filename</span><span>);} </span><span>212</span> <span>file_put_contents</span>(<span>$log_filename</span>, <span>date</span>('Y-m-d H:i:s').<span>$log_content</span>."\r\n",<span> FILE_APPEND); </span><span>213</span> <span> } </span><span>214</span> <span> } </span><span>215</span> <span>} </span><span>216</span> ?>
你是新注册的账号吗?要是新账号,不显示应该是因为还没被审核通过吧。要不是新账号,就清理下浏览器缓存,要么就换台机器试试。应该不会有别的原因了。
可以将单个图文消息抽象出来作为一个循环, 把每篇文章的内容填写进去好了后, 再拼接起来, 这样是最快的. 我也是做微信开发模式第三方开发的, 可以看我的资料, 个人简介.

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

AI Hentai Generator
Menjana ai hentai secara percuma.

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas

Terima kasih kepada netizen Qing Qiechensi, HH_KK, Satomi Ishihara dan Wu Yanzu dari China Selatan kerana menyerahkan petunjuk! Menurut berita pada 2 September, terdapat khabar angin baru-baru ini bahawa "iPhone 16 mungkin tidak menyokong WeChat." Sebagai tindak balas kepada ini, seorang wartawan dari Shell Finance memanggil talian panas rasmi Apple di China menjawab bahawa sama ada sistem iOS atau peranti Apple boleh teruskan menggunakan WeChat, dan WeChat Isu sama ada ia boleh terus disenaraikan dan dimuat turun di Apple App Store memerlukan komunikasi dan perbincangan antara Apple dan Tencent untuk menentukan situasi masa depan. Perisian App Store dan WeChat Perihalan Masalah Perisian Perunding teknikal App Store menegaskan bahawa pembangun mungkin perlu membayar yuran untuk meletakkan perisian pada Apple Store. Selepas mencapai bilangan muat turun tertentu, Apple perlu membayar yuran yang sepadan untuk muat turun berikutnya. Apple sedang aktif berkomunikasi dengan Tencent,

DeepSeek: Alat Generasi Imej AI yang kuat! DeepSeek sendiri bukan alat penjanaan imej, tetapi teknologi terasnya yang kuat memberikan sokongan yang mendasari untuk banyak alat lukisan AI. Ingin tahu cara menggunakan DeepSeek untuk menjana imej secara tidak langsung? Sila teruskan membaca! Menjana imej dengan alat AI berasaskan DeepSeek: Langkah-langkah berikut akan membimbing anda untuk menggunakan alat ini: Lancarkan alat lukisan AI: Cari dan buka alat lukisan AI berasaskan Deepseek (contohnya, cari "AI Simple"). Pilih Mod Lukisan: Pilih "Lukisan AI" atau fungsi yang serupa, dan pilih Jenis Imej mengikut keperluan anda, seperti "Anime Avatar", "Landskap"

Khabar angin WeChat menyokong iPhone 16 telah ditolak Terima kasih kepada netizen Xi Chuang Jiu Shi dan HH_KK kerana menyerahkan petunjuk! Menurut berita pada 2 September, terdapat khabar angin hari ini bahawa WeChat mungkin tidak menyokong iPhone 16. Setelah iPhone dinaik taraf kepada sistem iOS 18.2, ia tidak akan dapat menggunakan WeChat. Menurut "Berita Ekonomi Harian", diketahui daripada orang yang biasa dengan perkara itu bahawa khabar angin ini adalah khabar angin. Maklum balas Apple: Menurut Shell Finance, perunding teknikal Apple di China menjawab bahawa isu sama ada WeChat boleh terus digunakan pada sistem iOS atau peranti Apple, dan sama ada WeChat boleh terus disenaraikan dan dimuat turun di Apple App Store, perlu diselesaikan antara Apple dan Tencent Hanya melalui komunikasi dan perbincangan kita boleh menentukan situasi masa depan. Pada masa ini, Apple sedang aktif berkomunikasi dengan Tencent untuk mengesahkan sama ada Tencent akan meneruskan

Reka bentuk rangka kerja Java membolehkan keselamatan dengan mengimbangi keperluan keselamatan dengan keperluan perniagaan: mengenal pasti keperluan perniagaan utama dan mengutamakan keperluan keselamatan yang berkaitan. Membangunkan strategi keselamatan yang fleksibel, bertindak balas terhadap ancaman secara berlapis, dan membuat pelarasan tetap. Pertimbangkan fleksibiliti seni bina, menyokong evolusi perniagaan dan fungsi keselamatan abstrak. Utamakan kecekapan dan ketersediaan, mengoptimumkan langkah keselamatan dan meningkatkan keterlihatan.

Gate.io, sebuah platform perdagangan cryptocurrency terkemuka yang ditubuhkan pada tahun 2013, menyediakan pengguna Cina dengan laman web rasmi Cina yang lengkap. Laman web ini menyediakan pelbagai perkhidmatan, termasuk perdagangan tempat, perdagangan niaga hadapan dan pinjaman, dan menyediakan ciri khas seperti antara muka Cina, sumber yang kaya dan sokongan masyarakat.

Syiling SHIB sudah tidak asing lagi kepada pelabur Ia adalah token konsep yang sama dengan Dogecoin Dengan perkembangan pasaran, nilai pasaran semasa SHIB dapat dilihat bahawa pasaran SHIB sedang hangat dan menarik pelaburan yang tidak terkira . pelabur mengambil bahagian dalam pelaburan. Pada masa lalu, sering berlaku transaksi dan insiden keselamatan dompet di pasaran Ramai pelabur bimbang tentang masalah penyimpanan SHIB Mereka tertanya-tanya dompet mana yang lebih selamat untuk menyimpan syiling SHIB pada masa ini. Menurut analisis data pasaran, dompet yang agak selamat adalah terutamanya dompet OKXWeb3Wallet, imToken, dan MetaMask, yang akan menjadi agak selamat Seterusnya, editor akan membincangkannya secara terperinci. Dompet manakah yang lebih selamat untuk syiling SHIB? Pada masa ini, syiling SHIB diletakkan di OKXWe

Saluran muat turun aplikasi gerbang untuk versi lama, meliputi pasaran aplikasi rasmi, pihak ketiga, komuniti forum dan saluran lain.

Gate.io (Pintu Terbuka Sesame) adalah platform perdagangan cryptocurrency terkemuka di dunia. Tutorial ini meliputi langkah -langkah seperti pendaftaran akaun dan log masuk, pensijilan KYC, mata wang fiat dan mata wang digital, pemilihan pasangan dagangan, pesanan urus niaga/pasaran, dan pesanan dan rekod transaksi melihat, membantu anda memulakan platform GATE.IO untuk perdagangan cryptocurrency. Sama ada pemula atau veteran, anda boleh mendapat manfaat daripada tutorial ini dan mudah menguasai kemahiran perdagangan Gate.io.
