米斯特雷格 發表於 2022-1-12 17:24:00

微信公众号开发接入(一)

<h2 id="微信公众号基本原理">微信公众号基本原理</h2>
<blockquote>
<p>以前申请开发过小程序 好像是由于小程序有了,就不能开发公众号,所以我的小程序注销了</p>
</blockquote>
<div class="mermaid"> graph LR

A(微信用户)--&gt;|1.发送消息给公众号|B[公众号] --&gt;|2.发送请求|C[微信服务器Server] --&gt;|3.转发请求|D[自己的应用服务器Server]

D[自己的应用服务器Server]--&gt;|4.处理信息返回响应消息|C[微信服务器Server]--&gt;|5.接收响应消息|B[公众号] --&gt;|6.查看到公众号显示的信息|A(微信用户)

</div><p>1)用户在微信的手机里发送一条消息给公众账号<br>
2)后台接收到这条消息之后,微信服务器把消息转发到<br>
3)公众账号服务器收到请求后,解析消息格式,根据用户内容和自己的服务器逻辑,计算出需要返回给用户的消息,然后封装消息,返回给微信后台;<br>
4)微信后台把公众账号服务发来的消息转发给用户的微信手机客户端,这样用户在手机客户端上就可以看到公众账号发来的微信消息了。<br>
公众账号服务器要做的事情有三件:</p>
<ul>
<li>获取微信后台发过来的消息;</li>
<li>实现自己的业务逻辑;</li>
<li>发送返回消息给微信后台。</li>
</ul>
<blockquote>
<p>各公众号区别:<br>
1、订阅号:为媒体和个人提供一种信息传播方式,主要偏于为用户传达资讯(类似报纸杂志),主要的定位是阅读,每天可以群发1条消息;<br>
2、服务号:为企业,政府或组织提供对用户进行服务,主要偏于服务交互(类似银行提供服务查询),每个月只可群发4条消息;<br>
3、企业号:为企业,政府,事业单位,实现生产管理和协作运营的移动化,主要用于公司内部通讯使用,旨在为用户提供移动办公,需要先有成员的通讯信息验证才可以关注成功企业号;</p>
</blockquote>
<p>这个是微信公众号官方文档</p>
<p><img src="https://img2020.cnblogs.com/blog/1898315/202201/1898315-20220113110446741-226912964.png" alt="" loading="lazy"></p>
<h2 id="现在需要做开发接入">现在需要做开发接入</h2>
<ul>
<li>1、填写服务器配置</li>
<li>2、验证服务器地址的有效性</li>
<li>3、依据接口文档实现业务逻辑</li>
</ul>
<h2 id="以下步骤使用springboot项目做接入">以下步骤使用springboot项目做接入</h2>
<blockquote>
<p>开发者通过检验signature对请求进行校验(下面有校验方式)。若确认此次GET请求来自微信服务器,请原样返回echostr参数内容,则接入生效,成为开发者成功,否则接入失败。加密/校验流程如下:</p>
</blockquote>
<ul>
<li>1)将token、timestamp、nonce三个参数进行字典序排序</li>
<li>2)将三个参数字符串拼接成一个字符串进行sha1加密</li>
<li>3)开发者获得加密后的字符串可与signature对比,标识该请求来源于微信</li>
</ul>
<table>
<thead>
<tr>
<th>参数</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>signature</td>
<td>微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。</td>
</tr>
<tr>
<td>timestamp</td>
<td>时间戳</td>
</tr>
<tr>
<td>nonce</td>
<td>随机数</td>
</tr>
<tr>
<td>echostr</td>
<td>随机字符串</td>
</tr>
</tbody>
</table>
<h2 id="使用springbootdocker阿里云服务器">使用springboot+docker+阿里云服务器</h2>
<blockquote>
<p>springboot打成jar包,上传到阿里云服务器上,使用dockerFile打成镜像,运行容器访问</p>
</blockquote>
<h3 id="pomxml项目依赖">Pom.xml项目依赖</h3>
<blockquote>
<p>pom.xml</p>
</blockquote>
<pre><code class="language-java">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"&gt;
    &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;
    &lt;parent&gt;
      &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
      &lt;artifactId&gt;spring-boot-starter-parent&lt;/artifactId&gt;
      &lt;version&gt;2.6.2&lt;/version&gt;
      &lt;relativePath/&gt; &lt;!-- lookup parent from repository --&gt;
    &lt;/parent&gt;
    &lt;groupId&gt;com.rzk&lt;/groupId&gt;
    &lt;artifactId&gt;wxserver&lt;/artifactId&gt;
    &lt;version&gt;0.0.1-SNAPSHOT&lt;/version&gt;
    &lt;name&gt;wxserver&lt;/name&gt;
    &lt;description&gt;wxserver&lt;/description&gt;
    &lt;properties&gt;
      &lt;java.version&gt;1.8&lt;/java.version&gt;
    &lt;/properties&gt;
    &lt;dependencies&gt;
      &lt;dependency&gt;
            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;
      &lt;/dependency&gt;

      &lt;dependency&gt;
            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-devtools&lt;/artifactId&gt;
            &lt;scope&gt;runtime&lt;/scope&gt;
            &lt;optional&gt;true&lt;/optional&gt;
      &lt;/dependency&gt;
      &lt;dependency&gt;
            &lt;groupId&gt;org.projectlombok&lt;/groupId&gt;
            &lt;artifactId&gt;lombok&lt;/artifactId&gt;
            &lt;optional&gt;true&lt;/optional&gt;
      &lt;/dependency&gt;
      &lt;dependency&gt;
            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-starter-test&lt;/artifactId&gt;
            &lt;scope&gt;test&lt;/scope&gt;
      &lt;/dependency&gt;
    &lt;/dependencies&gt;

    &lt;build&gt;
      &lt;plugins&gt;
            &lt;plugin&gt;
                &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
                &lt;artifactId&gt;spring-boot-maven-plugin&lt;/artifactId&gt;
                &lt;configuration&gt;
                  &lt;excludes&gt;
                        &lt;exclude&gt;
                            &lt;groupId&gt;org.projectlombok&lt;/groupId&gt;
                            &lt;artifactId&gt;lombok&lt;/artifactId&gt;
                        &lt;/exclude&gt;
                  &lt;/excludes&gt;
                &lt;/configuration&gt;
            &lt;/plugin&gt;
      &lt;/plugins&gt;
    &lt;/build&gt;

&lt;/project&gt;

</code></pre>
<h3 id="配置文件">配置文件</h3>
<pre><code class="language-xml">server:
port: 80
servlet:
    context-path: /wxserver

wx:
signature:
timestamp:
nonce:
echostr:
Token: rzk
appid:
secret:
</code></pre>
<h3 id="工具类">工具类</h3>
<pre><code class="language-java">public class SignUtil {
    /**
   * 排序方法
   *
   * @param token
   * @param timestamp
   * @param nonce
   * @return
   */
    public String sort(String token, String timestamp, String nonce) {
      //将token, timestamp, nonce三个参数进行字典序排序
      String[] strArray = {token, timestamp, nonce};
      Arrays.sort(strArray);
      StringBuilder sb = new StringBuilder();
      for (String str : strArray) {
            sb.append(str);
      }

      return sb.toString();
    }

    /**
   * 将字符串进行sha1加密
   *
   * @param str 需要加密的字符串
   * @return 加密后的内容
   */
    public String sha1(String str) {
      try {
            MessageDigest digest = MessageDigest.getInstance("SHA-1");
            digest.update(str.getBytes());
            byte messageDigest[] = digest.digest();
            // Create Hex String
            StringBuffer hexString = new StringBuffer();
            // 字节数组转换为 十六进制 数
            for (int i = 0; i &lt; messageDigest.length; i++) {
                String shaHex = Integer.toHexString(messageDigest &amp; 0xFF);
                if (shaHex.length() &lt; 2) {
                  hexString.append(0);
                }
                hexString.append(shaHex);
            }
            return hexString.toString();

      } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
      }
      return "";
    }
}
</code></pre>
<h3 id="验证消息是否是来自微信服务器">验证消息是否是来自微信服务器</h3>
<blockquote>
<p>请求成功要返回echostr参数内容</p>
</blockquote>
<pre><code class="language-java">
@RestController
@RequestMapping("/wx/")
public class WxServerController {

    private Logger logger = LoggerFactory.getLogger(WxServerController.class);
   
    @Resource
    private Environment environment;

    /**
   *
   * @param signature
   * @param timestamp
   * @param nonce
   * @param echostr
   * @return
   */
    @RequestMapping("validate")
    public String validate(String signature, String timestamp, String nonce, String echostr) {

      logger.info("参数{}:"+signature+""+timestamp+""+ nonce+""+echostr);
      logger.info("Token参数{}:"+environment.getProperty("wx.Token"));
      //排序
      String sort = SignUtil.sort(
                environment.getProperty("wx.Token"),
                timestamp,
                nonce);

      //加密
      String sha1 = SignUtil.sha1(sort);
      logger.info("sha1{}:"+sha1);
      logger.info("signature{}:"+signature);

      //检验签名
      if (sha1 != null &amp;&amp; sha1 != "" &amp;&amp; sha1.equals(signature)){
            logger.info("检验签名成功:{}"+sha1);
            return echostr;
      }else{
            logger.info("检验签名失败:{}");
            return null;
      }
    }
}
</code></pre>
<h3 id="打成jar包上传到阿里云">打成jar包上传到阿里云</h3>
<h2 id="使用docker发布部署项目">使用docker发布部署项目</h2>
<h3 id="前提需要上传jar包">前提需要上传jar包</h3>
<p><img src="https://img2020.cnblogs.com/blog/1898315/202201/1898315-20220114005839042-1811902655.png" alt="" loading="lazy"></p>
<pre><code class="language-java"># docker build-twxserver .
Sending build context to Docker daemon106.6MB
Step 1/5 : FROM java:8
---&gt; d23bdf5b1b1b
Step 2/5 : COPY wxserver-0.0.1-SNAPSHOT.jar /wxserver.jar
---&gt; 5596a42accd4
Step 3/5 : CMD ["--server.port=80"]
---&gt; Running in 402c2249fc11
Removing intermediate container 402c2249fc11
---&gt; 1b7382d20dd1
Step 4/5 : EXPOSE 80
---&gt; Running in 978ab5d5946c
Removing intermediate container 978ab5d5946c
---&gt; c263859607bc
Step 5/5 : ENTRYPOINT ["java","-jar","/wxserver.jar"]
---&gt; Running in d3c9934d71c5
Removing intermediate container d3c9934d71c5
---&gt; 8a868ff36204
Successfully built 8a868ff36204
Successfully tagged wxserver:latest
# docker images
REPOSITORY                                             TAG       IMAGE ID       CREATED          SIZE
wxserver                                             latest    8a868ff36204   30 seconds ago   661MB
oos                                                    latest    ecc0de11a313   3 months ago   732MB
nacos/nacos-server                                     latest    bdf60dc2ada3   5 months ago   1.05GB
mysql                                                5.7       8cf625070931   5 months ago   448MB
hello-world                                          latest    d1165f221234   10 months ago    13.3kB
java                                                   8         d23bdf5b1b1b   4 years ago      643MB
registry.cn-hangzhou.aliyuncs.com/helowin/oracle_11g   latest    3fa112fd3642   6 years ago      6.85GB
# docker run -d --restart=always --name wxserver -v /usr/local/logs:/home/jar-logs -p 80:80 wxserver
601cb0

</code></pre>
<blockquote>
<p>DockerFile要和 jar包在同一路径</p>
</blockquote>
<h3 id="构建dockerfile">构建DockerFile</h3>
<pre><code class="language-java"># cat Dockerfile
FROM java:8

COPY wxserver-0.0.1-SNAPSHOT.jar /wxserver.jar

CMD ["--server.port=80"]

EXPOSE 80

ENTRYPOINT ["java","-jar","/wxserver.jar"]
</code></pre>
<p>在当前路径构建镜像</p>
<blockquote>
<p># docker build -t wxserver .<br>
# docker images<br>
REPOSITORY                                             TAG       IMAGE ID       CREATED         SIZE<br>
wxserver                                             latest    794c103c981a   23 hours ago    661MB</p>
</blockquote>
<h3 id="运行">运行</h3>
<blockquote>
<p># docker run -d --restart=always --name wxserver -v /usr/local/logs:/home/jar-logs -p 80:80 wxserver<br>
# docker logs -f 45a</p>
</blockquote>
<h3 id="打开微信公众号基本配置">打开微信公众号基本配置</h3>
<p><img src="https://img2020.cnblogs.com/blog/1898315/202201/1898315-20220114020901607-133305854.png" alt="" loading="lazy"></p>
<blockquote>
<p>配置地址<br>
http://ip地址/wxserver/wx/validate<br>
http://ip地址:80/wxserver/wx/validate</p>
</blockquote>
<blockquote>
<p>Token是项目配置的token</p>
</blockquote>
<p><img src="https://img2020.cnblogs.com/blog/1898315/202201/1898315-20220114021122686-1710519890.gif" alt="" loading="lazy"></p>
<h2 id="至此接入完成">至此接入完成</h2><br><br>
来源:https://www.cnblogs.com/rzkwz/p/15793527.html
頁: [1]
查看完整版本: 微信公众号开发接入(一)