游厚满 發表於 2021-5-15 13:18:00

在开发环境内网穿透测试微信公众号

<h2><span style="font-size: 1.5em">前言</span></h2>
<p>  上一篇《1个类,2个方法,3句代码,完成微信公众号开发的极简流程》介绍了一个只用很少量的代码,就能实现消息回复和高级接口两大经典微信应用。</p>
<p>  文末,我们对开发完的程序进行了测试,并且抛出了一个问题:</p>
<h2 style="text-align: center"><span style="color: rgba(255, 0, 0, 1)">我没有服务器,也没有注册微信公众号,如何在本地完成以上所有上线操作和测试呢?</span></h2>
<p>&nbsp;  本文就将带你亲自实现内网穿透,在本地环境下,模拟正式环境服务器对接微信,并进行调试。<span style="text-decoration: underline">本文同样适用于微信小程序、企业微信、QQ小程序等其他需要穿透到内网测试的场景。</span></p>
<p>  在上一篇已经完成的基础上,本篇主要内容边看边练习的时间约为 15 分钟,进阶内容约为 10 分钟,源码已经开放:</p>
<ul>
<li>  GitHub:https://github.com/JeffreySu/Senparc.Weixin.Samples/tree/main/Senparc.Weixin.Sample.Net6.MinSample</li>
<li>  Gitee:https://gitee.com/JeffreySu/Senparc.Weixin.Samples/tree/main/Senparc.Weixin.Sample.Net6.MinSample</li>
</ul>
<p>&nbsp;</p>
<h3>内容导航</h3>
<ul>
<li>背景</li>
<li>安装 ngrok</li>
<li>使用 ngrok 进行内网穿透</li>
<li>配置测试号</li>
<li>联机测试</li>
<li>调试</li>
<li>查看日志</li>
<li>进阶</li>
</ul>
<p>&nbsp;</p>
<h2>背景<br></h2>
<p>  微信公众号的服务原理如下图所示:  </p>
<p style="text-align: center"><img src="https://img2020.cnblogs.com/blog/28384/202105/28384-20210514234035519-1647873934.png" alt="" loading="lazy"></p>
<p style="text-align: center">来源:http://book.weixin.senparc.com/BookHelper#c-40</p>
<p style="text-align: center">&nbsp;</p>
<p>  微信用户发送给公众号的信息,经微信服务器中转处理成约定的格式后,转发给开发者的服务器(网站),然后再将网站返回的指定格式的消息经过处理转发给微信用户。</p>
<p>  这个过程中,对于正式的公众号来说,“网站”必须配有经过 ICP 备案的域名,也就是说必须部署在正规机房或特殊地点,而不能是一般的家中或公司中。</p>
<p>  这就带来了篇头所说的问题,如果我现在手里没有服务器、没有域名,或者即使有了,我也不想每次都部署,而是在本地进行运行和调试,那应该怎么做呢?</p>
<p>  这就牵出了一个技术:内网穿透。</p>
<p>  关于内网穿透的方案有很多,这里不一一列举,仅介绍其中我觉得最简便的方案之一:ngrok&nbsp; —— 只需一行命令即可完成整个穿透过程。</p>
<p>  </p>
<h2>安装 ngrok<br></h2>
<p>  ngrok 的官网:https://ngrok.com/</p>
<p>  点击 Download 即可下载,下载后解压安装到本地目录,如 D:\ngrok,文件夹下面只有一个文件,非常清爽:</p>
<p><img src="https://img2020.cnblogs.com/blog/28384/202105/28384-20210514234827521-477167976.png" alt="" width="697" height="108" loading="lazy" style="display: block; margin-left: auto; margin-right: auto"></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>  </p>
<h2>使用 ngrok 进行内网穿透<br></h2>
<p>  按照《1个类,2个方法,3句代码,完成微信公众号开发的极简流程》中的流程,运行项目(<span style="color: rgba(255, 0, 0, 1)">一定要确保正在运行</span>),在运行状态中找到对应的 Url 地址:</p>
<p>  <img src="https://img2020.cnblogs.com/blog/28384/202105/28384-20210514235301067-1721133160.png" alt="" width="882" height="350" loading="lazy" style="display: block; margin-left: auto; margin-right: auto"></p>
<p>&nbsp;</p>
<p>  使用命令行进入 D:\ngrok 目录,输入命令:<span style="color: rgba(255, 0, 0, 1)">ngrok http http://localhost:45638</span></p>
<p style="text-align: center"><span style="color: rgba(255, 0, 0, 1)"><img src="https://img2020.cnblogs.com/blog/28384/202105/28384-20210514235512664-1116814639.png" alt="" loading="lazy"></span></p>
<p>&nbsp;</p>
<p>&nbsp;  注意:这里使用的是 http,而不是 https,至于为什么现在只能使用 http,下文会解释。</p>
<p>  运行之后,即可启动 ngrok 的代理程序:</p>
<p><img src="https://img2020.cnblogs.com/blog/28384/202105/28384-20210514235644100-1154073409.png" alt="" width="685" height="256" loading="lazy" style="display: block; margin-left: auto; margin-right: auto"></p>
<p>&nbsp;  </p>
<p>  此时我们获得了1个随机的公网域名(每次启动 ngrok 都会变),同时支持 http 和 https 访问(映射到的都是内网的 http):</p>
<ul>
<li>http://bb2042af5b6a.ngrok.io&nbsp;</li>
<li>https://bb2042af5b6a.ngrok.io&nbsp;</li>





</ul>
<p style="text-align: left">  我们访问一下这两个域名,发现都返回了错误:</p>
<p style="text-align: center"><img src="https://img2020.cnblogs.com/blog/28384/202105/28384-20210515000229035-847649363.png" alt="" width="646" height="392" loading="lazy"></p>
<p>&nbsp;&nbsp;  如果看到 400 Bad Request 的错误页面,不用着急,按 Ctrl+C 退出程序,修改一下命令为:</p>
<p style="text-align: center">D:\ngrok&gt;<span style="color: rgba(255, 0, 0, 1)">ngrok&nbsp; http http://localhost:45638 --host-header="localhost:45638"</span></p>
<p style="text-align: center"><span style="color: rgba(0, 0, 0, 1)">(如果端口好不同,对应修改)</span></p>
<p>  重新运行后将获得新的随机域名:</p>
<p><img src="https://img2020.cnblogs.com/blog/28384/202105/28384-20210515000434314-1708358500.png" alt="" width="714" height="292" loading="lazy" style="display: block; margin-left: auto; margin-right: auto"></p>
<p>&nbsp;</p>
<p>&nbsp;  访问 https://704728067974.ngrok.io 临时域名,此时已经又看到了熟悉的画面:</p>
<p><img src="https://img2020.cnblogs.com/blog/28384/202105/28384-20210515000521412-1062255203.png" alt="" width="775" height="700" loading="lazy" style="display: block; margin-left: auto; margin-right: auto"></p>
<p>&nbsp;</p>
<p>&nbsp;  太棒了!得到这个“小确信”的页面后,就可以放心进行配置了。</p>
<p>&nbsp;</p>
<h2>配置测试号</h2>
<p>  由于正式的公众号必须要 ICP 备案的国内域名才可以对接,显然这个域名并不满足条件,但是作为测试,我们可以使用测试账号,为了方便大家查找入口,我们在线上Demo(https://sdk.weixin.senparc.com/)提供了快捷入口:</p>
<p><img src="https://img2020.cnblogs.com/blog/28384/202105/28384-20210515000853052-1940634356.png" loading="lazy" style="display: block; margin-left: auto; margin-right: auto; border: 1px solid rgba(0, 0, 0, 1)"></p>
<p style="text-align: center">&nbsp;</p>
<p>  点击进入后,即可用每个人的个人微信扫码,“领用”到一个测试号(每个个人微信唯一):</p>
<p style="text-align: center">  <img src="https://img2020.cnblogs.com/blog/28384/202105/28384-20210515131150431-447297264.png" alt="" width="1385" height="906" loading="lazy"></p>
<p>&nbsp;&nbsp;</p>
<p>&nbsp;  记录下【测试号信息】中的 appID 和 appsecret 参数,分别填写到 appsetting.json 中的 “WeixinAppId” 和 “WeixinAppSecret” 值中(如果不需要使用高级接口,只处理消息回复的话,则不需要用到这两个参数,可以忽略)。</p>
<p>  同时将 appsettings.json 中的 "Token" 自定义一个更加复杂的值(3-32个字符),稍后会用到。</p>
<p style="text-align: center"><img src="https://img2020.cnblogs.com/blog/28384/202105/28384-20210515120506622-1164606637.png" alt="" loading="lazy"></p>
<p style="text-align: center">&nbsp;&nbsp; 设置 appsetting.json</p>
<p style="text-align: center">&nbsp;</p>
<p>  随后点击页面【接口配置信息】后面的【修改】按钮,输入刚才设置的 Token,以及 ngrok 正在运行中的消息页面地址(注意:必须是带有消息接口完整路径的地址),如本例中的:</p>
<p><img src="https://img2020.cnblogs.com/blog/28384/202105/28384-20210515120357279-843588211.png" alt="" loading="lazy" style="display: block; margin-left: auto; margin-right: auto"></p>
<p style="text-align: center">&nbsp;设置 URL &amp; Token | https://704728067974.ngrok.io/WeixinAsync</p>
<p>&nbsp;</p>
<p>  注意:修改 appsetting.json 之后需要重启站点(此时千万不要重启 ngrok,否则需要重新到后台设置 URL)</p>
<p>  重启后,点击【提交】按钮,即可看到设置成功的界面:</p>
<p><img src="https://img2020.cnblogs.com/blog/28384/202105/28384-20210515120709684-390073681.png" alt="" loading="lazy" style="display: block; margin-left: auto; margin-right: auto"></p>
<p style="text-align: center">设置成功&nbsp;</p>
<h2>联机测试&nbsp;</h2>
<p>&nbsp;  将页面向下拉,可以看到个人测试号的二维码,用微信扫一扫,并关注(最多可以添加100个关注者)</p>
<p><img src="https://img2020.cnblogs.com/blog/28384/202105/28384-20210515120925499-1761805297.png" alt="" loading="lazy" style="display: block; margin-left: auto; margin-right: auto"></p>
<p style="text-align: center">扫码注册</p>
<p style="text-align: center">&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;  关注之后,即可在手机上看到这个测试公众号的界面,每次发送消息后,即可看到两条回复,第一条是通过高级接口(AppId + Secret)发送的,你可以尝试一下一口气多发几条,第二条是正式的回复消息,每次最多只能收到1条,因为程序中是先调用了高级接口(客服消息),然后返回回复信息,因此客户端先收到的就是客服消息。</p>
<p>  如果我们不发送文字信息,而是一个图片信息,系统会发现我们并没有重写图片处理过程,因此返回的是默认消息。</p>
<p><img src="https://img2020.cnblogs.com/blog/28384/202105/28384-20210515121807689-1174608269.png" alt="" loading="lazy" style="display: block; margin-left: auto; margin-right: auto"></p>
<p>&nbsp;</p>
<p>&nbsp;消息回复成功,穿透到内网服务器</p>
<p>&nbsp;</p>
<h2>调试</h2>
<p>  穿透到内网之后,可以非常方便地进行调试,我们使用调试模式打开站点,并且在文字回复信息返回之前设置一个断点:</p>
<p><img src="https://img2020.cnblogs.com/blog/28384/202105/28384-20210515122200093-1477238691.png" alt="" loading="lazy" style="display: block; margin-left: auto; margin-right: auto"></p>
<p style="text-align: center">开始调试&nbsp;</p>
<p>  </p>
<p>  当我们在客户端发送一条文字消息之后,即可在调试模式下看到收到的消息,以及即将回复的信息。其中客服消息应该在断点之前就运行了,因此微信客户端立即就能收到。</p>
<p>  但因为调试时间超过了 5 秒钟,超过了微信服务器等待的时间,因此客户端收到了“该公众号提供的服务出现故障”的提示,此时,我们超时回复的消息将被忽略。</p>
<p><img src="https://img2020.cnblogs.com/blog/28384/202105/28384-20210515122821442-691234862.png" alt="" loading="lazy" style="display: block; margin-left: auto; margin-right: auto"></p>
<p style="text-align: center">&nbsp;发送消息</p>
<p style="text-align: center">&nbsp;</p>
<p style="text-align: left">  下面我们再试一次,在5秒内快速修改返回内容:</p>
<p><img src="https://img2020.cnblogs.com/blog/28384/202105/28384-20210515123821396-1033347112.png" alt="" loading="lazy" style="display: block; margin-left: auto; margin-right: auto"></p>
<p style="text-align: center">&nbsp;成功调试并修改信息</p>
<p style="text-align: left">&nbsp;</p>
<p style="text-align: left">  这一次,前面 2 个步骤和之前是一致的,我们使用【即使窗口】输入命令修改了 responseMessage.Content 的值,然后让程序继续运行,返回属性值后的 responseMessage 对象,最后在手机端收到了被修改的回复信息。</p>
<p style="text-align: left">&nbsp;</p>
<h2>查看日志</h2>
<p>  Senparc.Weixin SDK 在默认设置下,会记录所有的消息和接口调用信息。</p>
<p>  消息发送和返回的日志,可以在 /App_Data/WeChat_OfficialAccount 目录下看到已经按照日期分类的公众号消息日志,以上述经过调试的消息为例:</p>
<p><img src="https://img2020.cnblogs.com/blog/28384/202105/28384-20210515125356290-1575757383.png" alt="" loading="lazy" style="display: block; margin-left: auto; margin-right: auto"></p>
<p style="text-align: center">一组 Request(请求)和 Response(响应)消息日志&nbsp;</p>
<p style="text-align: center">&nbsp;</p>
<p>  高级接口的调用信息默认存放在 /App_Data/SenparcTraceLog 目录下,每天的日志放在一个 .log 文件中:</p>
<p><img src="https://img2020.cnblogs.com/blog/28384/202105/28384-20210515125801338-2104863649.png" alt="" loading="lazy" style="display: block; margin-left: auto; margin-right: auto"></p>
<p style="text-align: center">&nbsp;&nbsp;高级接口的调用及传送信息可以完全透明地看到</p>
<p>&nbsp;</p>
<h2>进阶</h2>
<h3>  1. 如何使用 ngrok 映射到内部 https 协议的网址上?</h3>
<p>  ngrok 默认情况下只支持映射内网的 http 协议,如果强行映射 https,则会提示错误,如果必须要映射内网 https,则需要到官网(https://ngrok.com/)注册一个账号。</p>
<p>  这里有一个小提示:常规注册过程需要使用到 Google 的&nbsp;reCAPTCHA 验证,对于“原始”状态访问互联网的同学可能因此无法完成注册过程,此处建议直接使用 GitHub 等外部账号授权登录,可以跳过这个尴尬的异步。</p>
<p>  注册完成后进入后台(https://dashboard.ngrok.com/get-started/setup)就可以找到一个 authtoken:</p>
<p><img src="https://img2020.cnblogs.com/blog/28384/202105/28384-20210515132616444-552551947.png" alt="" loading="lazy" style="display: block; margin-left: auto; margin-right: auto"></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>  复制这一段令牌信息,打开桌面命令行,进入 ngrok 目录,输入:</p>
<p style="text-align: center">D:\ngrok&gt;<span style="color: rgba(255, 0, 0, 1)">ngrok authtoken 6vwCLn**********************</span></p>
<p style="text-align: center"><img src="https://img2020.cnblogs.com/blog/28384/202105/28384-20210515132946164-683615335.png" alt="" loading="lazy"></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p style="text-align: center">储存 authtoken</p>
<p style="text-align: center">&nbsp;</p>
<p>&nbsp;  ngrok 会把这个令牌自动存入到本地文件中,以后再调用 ngrok 的命令,就是“持证上岗”啦!</p>
<p>  下面我们修改一下之前的 http 绑定为 https 绑定:</p>
<p style="text-align: center">D:\ngrok&gt;<span style="color: rgba(255, 0, 0, 1)">ngrok http https://localhost:44368 -host-header="localhost:44368"</span></p>
<p style="text-align: center">(注意:http 和 https 的端口是不一样的)</p>
<p>  运行后可以看到 ngrok 已经并订到了内网的 https 协议地址上:</p>
<p><img src="https://img2020.cnblogs.com/blog/28384/202105/28384-20210515133436562-448251146.png" alt="" loading="lazy" style="display: block; margin-left: auto; margin-right: auto"></p>
<p>&nbsp;</p>
<p style="text-align: center">成功绑定 https</p>
<p>&nbsp;</p>
<p>&nbsp;  当然,也可以注意到外网域名已经发生了变化,如果需要继续使用的话,需要再次到微信测试号后台绑定新域名。</p>
<p>  如果需要自定义域名(固定),那么需要购买对应的服务才能开通权限。即使每次都变化,如果电脑不重启的话(亲测系统休眠和睡眠都没问题),可以一直使用,所以并不是特别大的痛点。</p>
<p>&nbsp;</p>
<h2>  2. 如何关闭日志?</h2>
<p>  Senparc.Weixin SDK 将日志分为了消息日志和调试日志(包含接口调用信息),默认为开启状态,如果不希望记录消息,可以通过如下方法关闭。</p>
<h4>  2.1 关闭消息日志</h4>
<p>  修改之前写入到 Startup.cs 中的中间件配置,添加禁用代码:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)">1</span>             <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">使用中间件注册 MessageHandler,指定 CustomMessageHandler 为自定义处理方法</span>
<span style="color: rgba(0, 128, 128, 1)">2</span>             app.UseMessageHandlerForMp(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">/WeixinAsync</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 128, 128, 1)">3</span>               (stream, postModel, maxRecordCount, serviceProvider) =&gt; <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> CustomMessageHandler(stream, postModel, maxRecordCount, serviceProvider),
</span><span style="color: rgba(0, 128, 128, 1)">4</span>               options =&gt;
<span style="color: rgba(0, 128, 128, 1)">5</span> <span style="color: rgba(0, 0, 0, 1)">                {
</span><span style="color: rgba(0, 128, 128, 1)">6</span>                     options.AccountSettingFunc = context =&gt;<span style="color: rgba(0, 0, 0, 1)"> senparcWeixinSetting.Value;
</span><span style="color: rgba(0, 128, 128, 1)">7</span>                     options.EnableRequestLog = <span style="color: rgba(0, 0, 255, 1)">false</span>;   <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">关闭请求消息日志</span>
<span style="color: rgba(0, 128, 128, 1)">8</span>                     options.EnbleResponseLog = <span style="color: rgba(0, 0, 255, 1)">false</span>;   <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">关闭响应消息日志</span>
<span style="color: rgba(0, 128, 128, 1)">9</span>               });</pre>
</div>
<p>  为了达到更好的灵活性,我们将 Request(请求)和 Resposne(响应)消息的日志记录状态进行了分离的管理。</p>
<h4>  2.1 关闭接口日志</h4>
<p>  接口日志必须在调试状态下开启,默认为开启状态,如果需要禁用,可以在执行完&nbsp;app.UseSenparcGlobal() 方法后的任意位置调用:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)">1</span>             Senparc.CO2NET.Config.IsDebug = <span style="color: rgba(0, 0, 255, 1)">false</span>;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">关闭全局调试状态,不记录日志</span></pre>
</div>
<p>&nbsp;</p>
<p>  添加以下 3 行代码将全面禁用调试日志(包括接口调用日志)以及消息请求/响应日志:</p>
<p><img src="https://img2020.cnblogs.com/blog/28384/202105/28384-20210515135623019-1050262862.png" alt="" loading="lazy" style="display: block; margin-left: auto; margin-right: auto"></p>
<p>&nbsp;</p>
<blockquote>
<p>&nbsp;<span style="color: rgba(255, 0, 0, 1)">  <strong><span>特别说明:本文所提供的“内网穿透”技术是一项常见的辅助信息调试的技术,仅供用于本项目测试使用,请勿用于违规用途!</span></strong></span></p>
</blockquote>
<p>  </p>
<h2>更多微信开发教程:</h2>
<ol>
<li>Senparc.Weixin.MP SDK&nbsp;微信公众平台开发教程(一):微信公众平台注册</li>
<li>Senparc.Weixin.MP SDK&nbsp;微信公众平台开发教程(二):成为开发者</li>
<li>Senparc.Weixin.MP SDK&nbsp;微信公众平台开发教程(三):微信公众平台开发验证</li>
<li>Senparc.Weixin.MP SDK&nbsp;微信公众平台开发教程(四):Hello World</li>
<li>Senparc.Weixin.MP SDK&nbsp;微信公众平台开发教程(五):使用Senparc.Weixin.MP SDK</li>
<li>Senparc.Weixin.MP SDK&nbsp;微信公众平台开发教程(六):了解MessageHandler</li>
<li>Senparc.Weixin.MP SDK&nbsp;微信公众平台开发教程(七):解决用户上下文(Session)问题</li>
<li>Senparc.Weixin.MP SDK&nbsp;微信公众平台开发教程(八):通用接口说明</li>
<li>Senparc.Weixin.MP SDK&nbsp;微信公众平台开发教程(九):自定义菜单接口说明</li>
<li>Senparc.Weixin.MP SDK&nbsp;微信公众平台开发教程(十):多客服接口说明</li>
<li>Senparc.Weixin.MP SDK&nbsp;微信公众平台开发教程(十一):高级接口说明</li>
<li>Senparc.Weixin.MP SDK&nbsp;微信公众平台开发教程(十二):OAuth2.0说明</li>
<li>Senparc.Weixin.MP SDK&nbsp;微信公众平台开发教程(十三):地图相关接口说明</li>
<li>Senparc.Weixin.MP SDK 微信公众平台开发教程(十四):请求消息去重</li>
<li>Senparc.Weixin.MP SDK 微信公众平台开发教程(十五):消息加密</li>
<li>Senparc.Weixin.MP SDK 微信公众平台开发教程(十六):AccessToken自动管理机制</li>
<li>Senparc.Weixin.MP SDK 微信公众平台开发教程(十七):个性化菜单接口说明</li>
<li>Senparc.Weixin.MP SDK 微信公众平台开发教程(十八):Web代理功能</li>
<li>Senparc.Weixin.MP SDK 微信公众平台开发教程(十九):MessageHandler 的未知类型消息处理</li>
<li>Senparc.Weixin.MP SDK 微信公众平台开发教程(二十):使用菜单消息功能</li>
<li>Senparc.Weixin.MP SDK 微信公众平台开发教程(二十一):在小程序中使用 WebSocket (.NET Core)</li>
<li>Senparc.Weixin.MP SDK 微信公众平台开发教程(二十二):如何安装 Nuget(dll) 后使用项目源代码调试</li>
<li>【番外篇】1个类,2个方法,3句代码,完成微信公众号开发的极简流程&nbsp;</li>
</ol>
<p>&nbsp;</p>

</div>
<div id="MySignature" role="contentinfo">
    <p>&nbsp;</p>

<p>
转载请注明出处和作者,谢谢!<br>
作者:JeffreySu/https://github.com/JeffreySu/<br>
博客:https://szw.cnblogs.com/<br>
</p>

<!--
<p>&nbsp;</p>
<p>
Senparc官方教程《微信开发深度解析:微信公众号、小程序高效开发秘籍》,耗时2年精心打造的微信开发权威教程,点击这里,购买正版!<br>
<img src="https://images2017.cnblogs.com/blog/28384/201707/28384-20170730224601537-1461862917.png" width="300" alt="
微信开发深度解析:微信公众号、小程序高效开发秘籍"><br>

</p>
<p>&nbsp;</p>


<div style="margin-bottom: 30px">
Senparc 官方微信开发视频教程:《微信公众号+小程序快速开发》,点击这里点击观看。<br>

<img src="https://images2017.cnblogs.com/blog/28384/201802/28384-20180208161432998-278885671.png" width="300" alt="Senparc 官方微信开发视频教程:《微信公众号+小程序快速开发》">

</div>--><br><br>
来源:https://www.cnblogs.com/szw/p/Intranet-debugging-wechat.html
頁: [1]
查看完整版本: 在开发环境内网穿透测试微信公众号