西部猎手 發表於 2022-10-29 14:45:00

微信公众号开发

<h2>1.<span class="md-plain md-expand">微信公众平台测试帐号</span></h2>
<h3><span class="md-plain md-expand">1.1 申请测试账号</span></h3>
<p><span class="md-plain md-expand"><span class="md-plain md-expand">微信公众平台接口测试帐号:<span class="md-link md-pair-s md-expand">https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login&amp;token=399029368&amp;lang=zh_CN</span></span></span></p>
<h3><span class="md-plain md-expand"><span class="md-plain md-expand"><span class="md-link md-pair-s md-expand">1.2&nbsp;</span></span></span><span class="md-plain md-expand">查看测试号管理</span></h3>
<p class="md-end-block md-p md-focus"><span class="md-plain">(1)其中appID和appsecret用于后面菜单开发使用</span></p>
<p class="md-end-block md-p"><span class="md-plain">(2)其中URL是开发者用来接收微信消息和事件的接口URL。Token可由开发者可以任意填写,用作生成签名(该Token会和接口URL中包含的Token进行比对,从而验证安全性)。本地测试,url改为内网穿透地址。</span></p>
<p class="md-end-block md-p"><span class="md-plain"><img src="https://img2022.cnblogs.com/blog/1783594/202210/1783594-20221007090924478-1484668869.png" alt="" width="745" height="501" loading="lazy"></span></p>
<p>&nbsp;</p>
<h2><span class="md-plain">2.微信公众号菜单开发</span></h2>
<h3><span class="md-plain"><span class="md-plain">2.1 公众号自定义菜单说明<br></span></span></h3>
<p class="md-end-block md-p md-focus"><span class="md-plain md-expand">微信自定义菜单文档地址:<span class="md-link md-pair-s md-expand">https://developers.weixin.qq.com/doc/offiaccount/Custom_Menus/Creating_Custom-Defined_Menu.html</span></span></p>
<p class="md-end-block md-p"><span class="md-plain">微信自定义菜单注意事项:</span></p>
<ol class="ol-list" start="">
<li class="md-list-item">
<p class="md-end-block md-p"><span class="md-plain">自定义菜单最多包括3个一级菜单,每个一级菜单最多包含5个二级菜单。</span></p>



</li>
<li class="md-list-item">
<p class="md-end-block md-p"><span class="md-plain">一级菜单最多4个汉字,二级菜单最多8个汉字,多出来的部分将会以“...”代替。</span></p>



</li>
<li class="md-list-item">
<p class="md-end-block md-p"><span class="md-plain">创建自定义菜单后,菜单的刷新策略是,在用户进入公众号会话页或公众号profile页时,如果发现上一次拉取菜单的请求在5分钟以前,就会拉取一下菜单,如果菜单有更新,就会刷新客户端的菜单。测试时可以尝试取消关注公众账号后再次关注,则可以看到创建后的效果。</span></p>



</li>



</ol>
<h3><span class="md-plain">2.2 数据格式</span></h3>
<p>在数据库新建一张menu表,用来存放菜单信息</p>
<p><img src="https://img2022.cnblogs.com/blog/1783594/202210/1783594-20221007091306608-1294617467.png" alt="" width="929" height="263" loading="lazy"></p>
<p>&nbsp;</p>
<p>&nbsp;具体数据格式如下:</p>
<p><img src="https://img2022.cnblogs.com/blog/1783594/202210/1783594-20221007091400742-930737633.png" alt="" width="883" height="338" loading="lazy"></p>
<p>&nbsp;</p>
<h3>2.3 导入依赖</h3>
<p>导入微信公众号开发相关依赖</p>
<div class="cnblogs_code">
<pre>    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">dependencies</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">dependency</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
            <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>com.github.binarywang<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
            <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>weixin-java-mp<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
            <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">version</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>4.1.0<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">version</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">dependency</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">dependencies</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span></pre>
</div>
<p>在yml中定义公众号id和密钥</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">wechat.mpAppId: wx09f201e9013e81d8

wechat.mpAppSecret: 6c999765c12c51850d28055e8b6e2eda</span></pre>
</div>
<h3>2.4 添加工具类</h3>
<p>该工具类提供从yml中解析出id和密钥的功能</p>
<div class="cnblogs_code"><img src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" id="code_img_closed_cf338e5e-db99-4d29-a1be-2f1b3501bdf8" class="code_img_closed"><img src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" id="code_img_opened_cf338e5e-db99-4d29-a1be-2f1b3501bdf8" class="code_img_opened" style="display: none">
<div id="cnblogs_code_open_cf338e5e-db99-4d29-a1be-2f1b3501bdf8" class="cnblogs_code_hide">
<pre><span style="color: rgba(0, 0, 255, 1)">package</span><span style="color: rgba(0, 0, 0, 1)"> com.gh.ggkt.wechat.utils;

</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.springframework.beans.factory.InitializingBean;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.springframework.beans.factory.annotation.Value;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.springframework.stereotype.Component;

</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
* 常量类,读取配置文件application.properties中的配置
</span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
@Component
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span> ConstantPropertiesUtil <span style="color: rgba(0, 0, 255, 1)">implements</span><span style="color: rgba(0, 0, 0, 1)"> InitializingBean {

    @Value(</span>"${wechat.mpAppId}"<span style="color: rgba(0, 0, 0, 1)">)
    </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> String appid;

    @Value(</span>"${wechat.mpAppSecret}"<span style="color: rgba(0, 0, 0, 1)">)
    </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> String appsecret;

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> String ACCESS_KEY_ID;
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> String ACCESS_KEY_SECRET;

    @Override
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span> afterPropertiesSet() <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> Exception {
      ACCESS_KEY_ID </span>=<span style="color: rgba(0, 0, 0, 1)"> appid;
      ACCESS_KEY_SECRET </span>=<span style="color: rgba(0, 0, 0, 1)"> appsecret;
    }
}</span></pre>
</div>
<span class="cnblogs_code_collapse">View Code</span></div>
<p>HttpClientUtils用于微信公众号发送请求</p>
<div class="cnblogs_code"><img src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" id="code_img_closed_0f1e780b-2179-4eab-8dbd-b4746b6baad1" class="code_img_closed"><img src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" id="code_img_opened_0f1e780b-2179-4eab-8dbd-b4746b6baad1" class="code_img_opened" style="display: none">
<div id="cnblogs_code_open_0f1e780b-2179-4eab-8dbd-b4746b6baad1" class="cnblogs_code_hide">
<pre><span style="color: rgba(0, 0, 255, 1)">package</span><span style="color: rgba(0, 0, 0, 1)"> com.gh.ggkt.wechat.utils;

</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.apache.commons.io.IOUtils;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.apache.commons.lang.StringUtils;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.apache.http.Consts;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.apache.http.HttpEntity;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.apache.http.HttpResponse;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.apache.http.NameValuePair;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.apache.http.client.HttpClient;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.apache.http.client.config.RequestConfig;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.apache.http.client.config.RequestConfig.Builder;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.apache.http.client.entity.UrlEncodedFormEntity;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.apache.http.client.methods.HttpGet;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.apache.http.client.methods.HttpPost;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.apache.http.conn.ConnectTimeoutException;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.apache.http.conn.ssl.SSLConnectionSocketFactory;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.apache.http.conn.ssl.SSLContextBuilder;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.apache.http.conn.ssl.TrustStrategy;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.apache.http.conn.ssl.X509HostnameVerifier;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.apache.http.entity.ContentType;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.apache.http.entity.StringEntity;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.apache.http.impl.client.CloseableHttpClient;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.apache.http.impl.client.HttpClients;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.apache.http.message.BasicNameValuePair;

</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> javax.net.ssl.SSLContext;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> javax.net.ssl.SSLException;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> javax.net.ssl.SSLSession;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> javax.net.ssl.SSLSocket;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.io.IOException;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.net.SocketTimeoutException;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.security.GeneralSecurityException;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.security.cert.CertificateException;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.security.cert.X509Certificate;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.util.ArrayList;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.util.List;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.util.Map;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.util.Map.Entry;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.util.Set;

</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
*依赖的jar包有:commons-lang-2.6.jar、httpclient-4.3.2.jar、httpcore-4.3.1.jar、commons-io-2.4.jar
* </span><span style="color: rgba(128, 128, 128, 1)">@author</span><span style="color: rgba(0, 128, 0, 1)"> zhaoyb
*
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> HttpClientUtils {

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> <span style="color: rgba(0, 0, 255, 1)">int</span> connTimeout=10000<span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> <span style="color: rgba(0, 0, 255, 1)">int</span> readTimeout=10000<span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> String charset="UTF-8"<span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> HttpClient client = <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;

    </span><span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> {
      PoolingHttpClientConnectionManager cm </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> PoolingHttpClientConnectionManager();
      cm.setMaxTotal(</span>128<span style="color: rgba(0, 0, 0, 1)">);
      cm.setDefaultMaxPerRoute(</span>128<span style="color: rgba(0, 0, 0, 1)">);
      client </span>=<span style="color: rgba(0, 0, 0, 1)"> HttpClients.custom().setConnectionManager(cm).build();
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> String postParameters(String url, String parameterStr) <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> ConnectTimeoutException, SocketTimeoutException, Exception{
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> post(url,parameterStr,"application/x-www-form-urlencoded"<span style="color: rgba(0, 0, 0, 1)">,charset,connTimeout,readTimeout);
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> String postParameters(String url, String parameterStr,String charset, Integer connTimeout, Integer readTimeout) <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> ConnectTimeoutException, SocketTimeoutException, Exception{
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> post(url,parameterStr,"application/x-www-form-urlencoded"<span style="color: rgba(0, 0, 0, 1)">,charset,connTimeout,readTimeout);
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> String postParameters(String url, Map&lt;String, String&gt; params) <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> ConnectTimeoutException,
            SocketTimeoutException, Exception {
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> postForm(url, params, <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">, connTimeout, readTimeout);
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> String postParameters(String url, Map&lt;String, String&gt; params, Integer connTimeout,Integer readTimeout) <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> ConnectTimeoutException,
            SocketTimeoutException, Exception {
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> postForm(url, params, <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">, connTimeout, readTimeout);
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> String get(String url) <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> Exception {
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> get(url, charset, <span style="color: rgba(0, 0, 255, 1)">null</span>, <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">);
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> String get(String url, String charset) <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> Exception {
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> get(url, charset, connTimeout, readTimeout);
    }

    </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
   * 发送一个 Post 请求, 使用指定的字符集编码.
   *
   * </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> url
   * </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> body RequestBody
   * </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> mimeType 例如 application/xml "application/x-www-form-urlencoded" a=1&amp;b=2&amp;c=3
   * </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> charset 编码
   * </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> connTimeout 建立链接超时时间,毫秒.
   * </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> readTimeout 响应超时时间,毫秒.
   * </span><span style="color: rgba(128, 128, 128, 1)">@return</span><span style="color: rgba(0, 128, 0, 1)"> ResponseBody, 使用指定的字符集编码.
   * </span><span style="color: rgba(128, 128, 128, 1)">@throws</span><span style="color: rgba(0, 128, 0, 1)"> ConnectTimeoutException 建立链接超时异常
   * </span><span style="color: rgba(128, 128, 128, 1)">@throws</span><span style="color: rgba(0, 128, 0, 1)"> SocketTimeoutException响应超时
   * </span><span style="color: rgba(128, 128, 128, 1)">@throws</span><span style="color: rgba(0, 128, 0, 1)"> Exception
   </span><span style="color: rgba(0, 128, 0, 1)">*/</span>
    <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> String post(String url, String body, String mimeType,String charset, Integer connTimeout, Integer readTimeout)
            </span><span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> ConnectTimeoutException, SocketTimeoutException, Exception {
      HttpClient client </span>= <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
      HttpPost post </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> HttpPost(url);
      String result </span>= ""<span style="color: rgba(0, 0, 0, 1)">;
      </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
            </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (StringUtils.isNotBlank(body)) {
                HttpEntity entity </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> StringEntity(body, ContentType.create(mimeType, charset));
                post.setEntity(entity);
            }
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 设置参数</span>
            Builder customReqConf =<span style="color: rgba(0, 0, 0, 1)"> RequestConfig.custom();
            </span><span style="color: rgba(0, 0, 255, 1)">if</span> (connTimeout != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
                customReqConf.setConnectTimeout(connTimeout);
            }
            </span><span style="color: rgba(0, 0, 255, 1)">if</span> (readTimeout != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
                customReqConf.setSocketTimeout(readTimeout);
            }
            post.setConfig(customReqConf.build());

            HttpResponse res;
            </span><span style="color: rgba(0, 0, 255, 1)">if</span> (url.startsWith("https"<span style="color: rgba(0, 0, 0, 1)">)) {
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 执行 Https 请求.</span>
                client =<span style="color: rgba(0, 0, 0, 1)"> createSSLInsecureClient();
                res </span>=<span style="color: rgba(0, 0, 0, 1)"> client.execute(post);
            } </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 执行 Http 请求.</span>
                client =<span style="color: rgba(0, 0, 0, 1)"> HttpClientUtils.client;
                res </span>=<span style="color: rgba(0, 0, 0, 1)"> client.execute(post);
            }
            result </span>=<span style="color: rgba(0, 0, 0, 1)"> IOUtils.toString(res.getEntity().getContent(), charset);
      } </span><span style="color: rgba(0, 0, 255, 1)">finally</span><span style="color: rgba(0, 0, 0, 1)"> {
            post.releaseConnection();
            </span><span style="color: rgba(0, 0, 255, 1)">if</span> (url.startsWith("https") &amp;&amp; client != <span style="color: rgba(0, 0, 255, 1)">null</span>&amp;&amp; client <span style="color: rgba(0, 0, 255, 1)">instanceof</span><span style="color: rgba(0, 0, 0, 1)"> CloseableHttpClient) {
                ((CloseableHttpClient) client).close();
            }
      }
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> result;
    }


    </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
   * 提交form表单
   *
   * </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> url
   * </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> params
   * </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> connTimeout
   * </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> readTimeout
   * </span><span style="color: rgba(128, 128, 128, 1)">@return</span><span style="color: rgba(0, 128, 0, 1)">
   * </span><span style="color: rgba(128, 128, 128, 1)">@throws</span><span style="color: rgba(0, 128, 0, 1)"> ConnectTimeoutException
   * </span><span style="color: rgba(128, 128, 128, 1)">@throws</span><span style="color: rgba(0, 128, 0, 1)"> SocketTimeoutException
   * </span><span style="color: rgba(128, 128, 128, 1)">@throws</span><span style="color: rgba(0, 128, 0, 1)"> Exception
   </span><span style="color: rgba(0, 128, 0, 1)">*/</span>
    <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> String postForm(String url, Map&lt;String, String&gt; params, Map&lt;String, String&gt; headers, Integer connTimeout,Integer readTimeout) <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> ConnectTimeoutException,
            SocketTimeoutException, Exception {

      HttpClient client </span>= <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
      HttpPost post </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> HttpPost(url);
      </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
            </span><span style="color: rgba(0, 0, 255, 1)">if</span> (params != <span style="color: rgba(0, 0, 255, 1)">null</span> &amp;&amp; !<span style="color: rgba(0, 0, 0, 1)">params.isEmpty()) {
                List</span>&lt;NameValuePair&gt; formParams = <span style="color: rgba(0, 0, 255, 1)">new</span> ArrayList&lt;NameValuePair&gt;<span style="color: rgba(0, 0, 0, 1)">();
                Set</span>&lt;Entry&lt;String, String&gt;&gt; entrySet =<span style="color: rgba(0, 0, 0, 1)"> params.entrySet();
                </span><span style="color: rgba(0, 0, 255, 1)">for</span> (Entry&lt;String, String&gt;<span style="color: rgba(0, 0, 0, 1)"> entry : entrySet) {
                  formParams.add(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> BasicNameValuePair(entry.getKey(), entry.getValue()));
                }
                UrlEncodedFormEntity entity </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> UrlEncodedFormEntity(formParams, Consts.UTF_8);
                post.setEntity(entity);
            }

            </span><span style="color: rgba(0, 0, 255, 1)">if</span> (headers != <span style="color: rgba(0, 0, 255, 1)">null</span> &amp;&amp; !<span style="color: rgba(0, 0, 0, 1)">headers.isEmpty()) {
                </span><span style="color: rgba(0, 0, 255, 1)">for</span> (Entry&lt;String, String&gt;<span style="color: rgba(0, 0, 0, 1)"> entry : headers.entrySet()) {
                  post.addHeader(entry.getKey(), entry.getValue());
                }
            }
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 设置参数</span>
            Builder customReqConf =<span style="color: rgba(0, 0, 0, 1)"> RequestConfig.custom();
            </span><span style="color: rgba(0, 0, 255, 1)">if</span> (connTimeout != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
                customReqConf.setConnectTimeout(connTimeout);
            }
            </span><span style="color: rgba(0, 0, 255, 1)">if</span> (readTimeout != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
                customReqConf.setSocketTimeout(readTimeout);
            }
            post.setConfig(customReqConf.build());
            HttpResponse res </span>= <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
            </span><span style="color: rgba(0, 0, 255, 1)">if</span> (url.startsWith("https"<span style="color: rgba(0, 0, 0, 1)">)) {
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 执行 Https 请求.</span>
                client =<span style="color: rgba(0, 0, 0, 1)"> createSSLInsecureClient();
                res </span>=<span style="color: rgba(0, 0, 0, 1)"> client.execute(post);
            } </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 执行 Http 请求.</span>
                client =<span style="color: rgba(0, 0, 0, 1)"> HttpClientUtils.client;
                res </span>=<span style="color: rgba(0, 0, 0, 1)"> client.execute(post);
            }
            </span><span style="color: rgba(0, 0, 255, 1)">return</span> IOUtils.toString(res.getEntity().getContent(), "UTF-8"<span style="color: rgba(0, 0, 0, 1)">);
      } </span><span style="color: rgba(0, 0, 255, 1)">finally</span><span style="color: rgba(0, 0, 0, 1)"> {
            post.releaseConnection();
            </span><span style="color: rgba(0, 0, 255, 1)">if</span> (url.startsWith("https") &amp;&amp; client != <span style="color: rgba(0, 0, 255, 1)">null</span>
                  &amp;&amp; client <span style="color: rgba(0, 0, 255, 1)">instanceof</span><span style="color: rgba(0, 0, 0, 1)"> CloseableHttpClient) {
                ((CloseableHttpClient) client).close();
            }
      }
    }




    </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
   * 发送一个 GET 请求
   *
   * </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> url
   * </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> charset
   * </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> connTimeout建立链接超时时间,毫秒.
   * </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> readTimeout响应超时时间,毫秒.
   * </span><span style="color: rgba(128, 128, 128, 1)">@return</span><span style="color: rgba(0, 128, 0, 1)">
   * </span><span style="color: rgba(128, 128, 128, 1)">@throws</span><span style="color: rgba(0, 128, 0, 1)"> ConnectTimeoutException   建立链接超时
   * </span><span style="color: rgba(128, 128, 128, 1)">@throws</span><span style="color: rgba(0, 128, 0, 1)"> SocketTimeoutException   响应超时
   * </span><span style="color: rgba(128, 128, 128, 1)">@throws</span><span style="color: rgba(0, 128, 0, 1)"> Exception
   </span><span style="color: rgba(0, 128, 0, 1)">*/</span>
    <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> String get(String url, String charset, Integer connTimeout,Integer readTimeout)
            </span><span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> ConnectTimeoutException,SocketTimeoutException, Exception {

      HttpClient client </span>= <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
      HttpGet get </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> HttpGet(url);
      String result </span>= ""<span style="color: rgba(0, 0, 0, 1)">;
      </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 设置参数</span>
            Builder customReqConf =<span style="color: rgba(0, 0, 0, 1)"> RequestConfig.custom();
            </span><span style="color: rgba(0, 0, 255, 1)">if</span> (connTimeout != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
                customReqConf.setConnectTimeout(connTimeout);
            }
            </span><span style="color: rgba(0, 0, 255, 1)">if</span> (readTimeout != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
                customReqConf.setSocketTimeout(readTimeout);
            }
            get.setConfig(customReqConf.build());

            HttpResponse res </span>= <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;

            </span><span style="color: rgba(0, 0, 255, 1)">if</span> (url.startsWith("https"<span style="color: rgba(0, 0, 0, 1)">)) {
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 执行 Https 请求.</span>
                client =<span style="color: rgba(0, 0, 0, 1)"> createSSLInsecureClient();
                res </span>=<span style="color: rgba(0, 0, 0, 1)"> client.execute(get);
            } </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 执行 Http 请求.</span>
                client =<span style="color: rgba(0, 0, 0, 1)"> HttpClientUtils.client;
                res </span>=<span style="color: rgba(0, 0, 0, 1)"> client.execute(get);
            }

            result </span>=<span style="color: rgba(0, 0, 0, 1)"> IOUtils.toString(res.getEntity().getContent(), charset);
      } </span><span style="color: rgba(0, 0, 255, 1)">finally</span><span style="color: rgba(0, 0, 0, 1)"> {
            get.releaseConnection();
            </span><span style="color: rgba(0, 0, 255, 1)">if</span> (url.startsWith("https") &amp;&amp; client != <span style="color: rgba(0, 0, 255, 1)">null</span> &amp;&amp; client <span style="color: rgba(0, 0, 255, 1)">instanceof</span><span style="color: rgba(0, 0, 0, 1)"> CloseableHttpClient) {
                ((CloseableHttpClient) client).close();
            }
      }
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> result;
    }


    </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
   * 从 response 里获取 charset
   *
   * </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> ressponse
   * </span><span style="color: rgba(128, 128, 128, 1)">@return</span>
   <span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
    @SuppressWarnings(</span>"unused"<span style="color: rgba(0, 0, 0, 1)">)
    </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> String getCharsetFromResponse(HttpResponse ressponse) {
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Content-Type:text/html; charset=GBK</span>
      <span style="color: rgba(0, 0, 255, 1)">if</span> (ressponse.getEntity() != <span style="color: rgba(0, 0, 255, 1)">null</span>&amp;&amp; ressponse.getEntity().getContentType() != <span style="color: rgba(0, 0, 255, 1)">null</span> &amp;&amp; ressponse.getEntity().getContentType().getValue() != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
            String contentType </span>=<span style="color: rgba(0, 0, 0, 1)"> ressponse.getEntity().getContentType().getValue();
            </span><span style="color: rgba(0, 0, 255, 1)">if</span> (contentType.contains("charset="<span style="color: rgba(0, 0, 0, 1)">)) {
                </span><span style="color: rgba(0, 0, 255, 1)">return</span> contentType.substring(contentType.indexOf("charset=") + 8<span style="color: rgba(0, 0, 0, 1)">);
            }
      }
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
    }



    </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
   * 创建 SSL连接
   * </span><span style="color: rgba(128, 128, 128, 1)">@return</span><span style="color: rgba(0, 128, 0, 1)">
   * </span><span style="color: rgba(128, 128, 128, 1)">@throws</span><span style="color: rgba(0, 128, 0, 1)"> GeneralSecurityException
   </span><span style="color: rgba(0, 128, 0, 1)">*/</span>
    <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> CloseableHttpClient createSSLInsecureClient() <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> GeneralSecurityException {
      </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
            SSLContext sslContext </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> SSLContextBuilder().loadTrustMaterial(<span style="color: rgba(0, 0, 255, 1)">null</span>, <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> TrustStrategy() {
                </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">boolean</span> isTrusted(X509Certificate[] chain,String authType) <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> CertificateException {
                  </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">;
                }
            }).build();

            SSLConnectionSocketFactory sslsf </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> SSLConnectionSocketFactory(sslContext, <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> X509HostnameVerifier() {

                @Override
                </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">boolean</span><span style="color: rgba(0, 0, 0, 1)"> verify(String arg0, SSLSession arg1) {
                  </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">;
                }

                @Override
                </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> verify(String host, SSLSocket ssl)
                        </span><span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> IOException {
                }

                @Override
                </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> verify(String host, X509Certificate cert)
                        </span><span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> SSLException {
                }

                @Override
                </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> verify(String host, String[] cns,
                                 String[] subjectAlts) </span><span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> SSLException {
                }

            });

            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> HttpClients.custom().setSSLSocketFactory(sslsf).build();

      } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (GeneralSecurityException e) {
            </span><span style="color: rgba(0, 0, 255, 1)">throw</span><span style="color: rgba(0, 0, 0, 1)"> e;
      }
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> main(String[] args) {
      </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
            String str</span>= post("https://localhost:443/ssl/test.shtml","name=12&amp;page=34","application/x-www-form-urlencoded", "UTF-8", 10000, 10000<span style="color: rgba(0, 0, 0, 1)">);
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">String str= get("</span><span style="color: rgba(0, 128, 0, 1); text-decoration: underline">https://localhost</span><span style="color: rgba(0, 128, 0, 1)">:443/ssl/test.shtml?name=12&amp;page=34","GBK");</span>
            <span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">Map&lt;String,String&gt; map = new HashMap&lt;String,String&gt;();
            map.put("name", "111");
            map.put("page", "222");
            String str= postForm("</span><span style="color: rgba(0, 128, 0, 1); text-decoration: underline">https://localhost</span><span style="color: rgba(0, 128, 0, 1)">:443/ssl/test.shtml",map,null, 10000, 10000);</span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
            System.out.println(str);
      } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (ConnectTimeoutException e) {
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> TODO Auto-generated catch block</span>
<span style="color: rgba(0, 0, 0, 1)">            e.printStackTrace();
      } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (SocketTimeoutException e) {
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> TODO Auto-generated catch block</span>
<span style="color: rgba(0, 0, 0, 1)">            e.printStackTrace();
      } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (Exception e) {
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> TODO Auto-generated catch block</span>
<span style="color: rgba(0, 0, 0, 1)">            e.printStackTrace();
      }
    }

}</span></pre>
</div>
<span class="cnblogs_code_collapse">View Code</span></div>
<h3>2.5 添加配置类</h3>
<div class="cnblogs_code"><img src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" id="code_img_closed_469b1c2c-1f23-42f3-ab88-ea81ec8bbb07" class="code_img_closed"><img src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" id="code_img_opened_469b1c2c-1f23-42f3-ab88-ea81ec8bbb07" class="code_img_opened" style="display: none">
<div id="cnblogs_code_open_469b1c2c-1f23-42f3-ab88-ea81ec8bbb07" class="cnblogs_code_hide">
<pre><span style="color: rgba(0, 0, 255, 1)">package</span><span style="color: rgba(0, 0, 0, 1)"> com.gh.ggkt.wechat.config;

</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> com.gh.ggkt.wechat.utils.ConstantPropertiesUtil;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> me.chanjar.weixin.mp.api.WxMpService;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> me.chanjar.weixin.mp.config.WxMpConfigStorage;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.springframework.beans.factory.annotation.Autowired;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.springframework.context.annotation.Bean;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.springframework.context.annotation.Configuration;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.springframework.stereotype.Component;

</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
* </span><span style="color: rgba(128, 128, 128, 1)">@author</span><span style="color: rgba(0, 128, 0, 1)"> Eric Fang
* @date 2022/10/6 14:05
</span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
@Component
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> WechatMpConfig {


    @Autowired
    </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> ConstantPropertiesUtil constantPropertiesUtil;

    @Bean
    </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> WxMpService wxMpService(){
      WxMpService wxMpService </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> WxMpServiceImpl();
      wxMpService.setWxMpConfigStorage(wxMpConfigStorage());
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> wxMpService;
    }
    @Bean
    </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> WxMpConfigStorage wxMpConfigStorage(){
      WxMpDefaultConfigImpl wxMpConfigStorage </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> WxMpDefaultConfigImpl();
      wxMpConfigStorage.setAppId(ConstantPropertiesUtil.ACCESS_KEY_ID);
      wxMpConfigStorage.setSecret(ConstantPropertiesUtil.ACCESS_KEY_SECRET);
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> wxMpConfigStorage;
    }
}</span></pre>
</div>
<span class="cnblogs_code_collapse">View Code</span></div>
<h3>2.6 代码实现</h3>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> List&lt;Menu&gt;<span style="color: rgba(0, 0, 0, 1)"> findOneMenuInfo() {
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">查询parent_id为0的</span>
      LambdaQueryWrapper&lt;Menu&gt; queryWrapper = <span style="color: rgba(0, 0, 255, 1)">new</span> LambdaQueryWrapper&lt;&gt;<span style="color: rgba(0, 0, 0, 1)">();
      queryWrapper.eq(Menu::getParentId, </span>0<span style="color: rgba(0, 0, 0, 1)">);
      List</span>&lt;Menu&gt; menuList =<span style="color: rgba(0, 0, 0, 1)"> baseMapper.selectList(queryWrapper);
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> menuList;
    }

    @Override
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> syncMenu() {
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取所有的菜单列表</span>
      List&lt;MenuVo&gt; menuInfoList = <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.findMenuInfo();
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">菜单</span>
      JSONArray buttonList = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> JSONArray();
      </span><span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> (MenuVo oneMenuVo : menuInfoList) {
            JSONObject one </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> JSONObject();
            one.put(</span>"name"<span style="color: rgba(0, 0, 0, 1)">, oneMenuVo.getName());
            JSONArray subButton </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> JSONArray();
            </span><span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> (MenuVo twoMenuVo : oneMenuVo.getChildren()) {
                JSONObject two </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> JSONObject();
                two.put(</span>"type"<span style="color: rgba(0, 0, 0, 1)">, twoMenuVo.getType());
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">菜单的响应动作类型,view表示网页类型,click表示点击类型,miniprogram表示小程序类型</span>
                <span style="color: rgba(0, 0, 255, 1)">if</span> (twoMenuVo.getType().equals("view"<span style="color: rgba(0, 0, 0, 1)">)) {
                  two.put(</span>"name"<span style="color: rgba(0, 0, 0, 1)">, twoMenuVo.getName());
                  two.put(</span>"url", "http://ggkt2.vipgz1.91tunnel.com/#"
                            +<span style="color: rgba(0, 0, 0, 1)"> twoMenuVo.getUrl());
                } </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
                  two.put(</span>"name"<span style="color: rgba(0, 0, 0, 1)">, twoMenuVo.getName());
                  two.put(</span>"key"<span style="color: rgba(0, 0, 0, 1)">, twoMenuVo.getMeunKey());
                }
                subButton.add(two);
            }
            one.put(</span>"sub_button"<span style="color: rgba(0, 0, 0, 1)">, subButton);
            buttonList.add(one);
      }
      JSONObject button </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> JSONObject();
      button.put(</span>"button"<span style="color: rgba(0, 0, 0, 1)">, buttonList);
      </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
            wxMpService.getMenuService().menuCreate(button.toJSONString());
      } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (WxErrorException e) {
            e.printStackTrace();
      }
    }</span></pre>
</div>
<h3>2.7 删除菜单</h3>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">@SneakyThrows
@Override
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> removeMenu() {
    wxMpService.getMenuService().menuDelete();
}</span></pre>
</div>
<h2>3.内网穿透工具</h2>
<p>发送微信公众号消息需要使用到内网穿透服务器,这里使用的是ngrok,注册<span class="md-plain md-expand">网址:<span class="md-link md-pair-s md-expand">https://ngrok.cc/login/register</span></span></p>
<h3><span class="md-plain"><span class="md-plain">3.1 实名认证</span></span></h3>
<p><span class="md-plain"><span class="md-plain">登录进去后,首先需要进行实名认证,认证费2元</span></span></p>
<p><span class="md-plain"><span class="md-plain"><img src="https://img2022.cnblogs.com/blog/1783594/202210/1783594-20221027113327784-736147785.png" alt="" width="820" height="360" loading="lazy"></span></span></p>
<p>&nbsp;</p>
<h3>3.2 开通隧道</h3>
<p>选择 隧道管理--&gt;开通隧道,<strong>最后一个是免费服务器,建议选择付费服务器,10元/月,因为免费服务器使用人数很多,经常掉线</strong></p>
<p><img src="https://img2022.cnblogs.com/blog/1783594/202210/1783594-20221027113620978-1967381939.png" alt="" width="986" height="403" loading="lazy"></p>
<p>&nbsp;</p>
<p>&nbsp;点击立即购买,输入相关信息</p>
<p><img src="https://img2022.cnblogs.com/blog/1783594/202210/1783594-20221027113753616-1685213320.png" alt="" width="957" height="585" loading="lazy"></p>
<p>&nbsp;</p>
<p>开通成功后,查看开通的隧道</p>
<p><img src="https://img2022.cnblogs.com/blog/1783594/202210/1783594-20221027113912454-363373850.png" alt="" width="1104" height="170" loading="lazy"></p>
<p>&nbsp;</p>
<h3>3.3 隧道启动</h3>
<p>下载客户端工具,选择windows版进行下载</p>
<p><img src="https://img2022.cnblogs.com/blog/1783594/202210/1783594-20221027114111674-569434481.png" alt="" width="1026" height="473" loading="lazy"></p>
<p>&nbsp;</p>
<p>&nbsp;下载完成之后进行解压</p>
<p><img src="https://img2022.cnblogs.com/blog/1783594/202210/1783594-20221027114144999-1367772713.png" alt="" width="794" height="161" loading="lazy"></p>
<p>&nbsp;</p>
<p>&nbsp;下载之后得到两个文件,可以通过cmd命令行进到sunny.exe所在的目录执行</p>
<div class="cnblogs_code">
<pre>sunny.exe clientid 隧道id</pre>
</div>
<p><img src="https://img2022.cnblogs.com/blog/1783594/202210/1783594-20221027114305207-1393586195.png" alt="" width="1041" height="317" loading="lazy"></p>
<p>&nbsp;</p>
<p>&nbsp;看到如图所示界面代表启动成功</p>
<h2>4.公众号普通消息</h2>
<h3>4.1 消息接入</h3>
<p><span class="md-plain md-expand">参考文档:<span class="md-link md-pair-s md-expand">https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Access_Overview.html</span></span></p>
<p class="md-end-block md-p md-focus"><span class="md-plain">接入微信公众平台开发,开发者需要按照如下步骤完成:</span></p>
<p class="md-end-block md-p"><span class="md-plain">1、填写服务器配置</span></p>
<p class="md-end-block md-p"><span class="md-plain md-expand">2、验证服务器地址的有效性</span></p>
<p class="md-end-block md-p"><span class="md-plain">3、依据接口文档实现业务逻辑</span></p>
<h3><span class="md-plain"><span class="md-plain">4.2 公众号服务器配置</span></span></h3>
<p><span class="md-plain"><span class="md-plain">需要填写url和token,url为内网穿透地址,token自己随意定</span></span></p>
<p><span class="md-plain"><span class="md-plain"><img src="https://img2022.cnblogs.com/blog/1783594/202210/1783594-20221027140738132-1508058870.png" alt="" width="834" height="205" loading="lazy"></span></span></p>
<h3>4.3 代码实现</h3>
<p><span class="md-plain"><span class="md-plain">创建MessageController</span></span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">@RestController
@RequestMapping(</span>"/api/wechat/message"<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> MessageController {

    </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> String token = "ggkt"<span style="color: rgba(0, 0, 0, 1)">;

    </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
   * 服务器有效性验证
   * </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> request
   * </span><span style="color: rgba(128, 128, 128, 1)">@return</span>
   <span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
    @GetMapping
    </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String verifyToken(HttpServletRequest request) {
      String signature </span>= request.getParameter("signature"<span style="color: rgba(0, 0, 0, 1)">);
      String timestamp </span>= request.getParameter("timestamp"<span style="color: rgba(0, 0, 0, 1)">);
      String nonce </span>= request.getParameter("nonce"<span style="color: rgba(0, 0, 0, 1)">);
      String echostr </span>= request.getParameter("echostr"<span style="color: rgba(0, 0, 0, 1)">);
      log.info(</span>"signature: {} nonce: {} echostr: {} timestamp: {}"<span style="color: rgba(0, 0, 0, 1)">, signature, nonce, echostr, timestamp);
      </span><span style="color: rgba(0, 0, 255, 1)">if</span> (<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.checkSignature(signature, timestamp, nonce)) {
            log.info(</span>"token ok"<span style="color: rgba(0, 0, 0, 1)">);
            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> echostr;
      }
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> echostr;
    }

    </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">boolean</span><span style="color: rgba(0, 0, 0, 1)"> checkSignature(String signature, String timestamp, String nonce) {
      String[] str </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> String[]{token, timestamp, nonce};
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">排序</span>
<span style="color: rgba(0, 0, 0, 1)">      Arrays.sort(str);
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">拼接字符串</span>
      StringBuffer buffer = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> StringBuffer();
      </span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = 0; i &lt; str.length; i++<span style="color: rgba(0, 0, 0, 1)">) {
            buffer.append(str);
      }
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">进行sha1加密</span>
      String temp =<span style="color: rgba(0, 0, 0, 1)"> SHA1.encode(buffer.toString());
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">与微信提供的signature进行匹对</span>
      <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> signature.equals(temp);
    }
}</span></pre>
</div>
<p>完成之后,我们的校验接口就算是开发完成了。接下来就可以开发消息接收接口了。</p>
<p>接收消息</p>
<p>接下来我们来开发消息接收接口,消息接收接口和上面的服务器校验接口地址是一样的,都是我们一开始在公众号后台配置的地址。只不过消息接收接口是一个 POST 请求。</p>
<div class="cnblogs_code">
<pre>   <span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
   * 接收微信服务器发送来的消息
   * </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> request
   * </span><span style="color: rgba(128, 128, 128, 1)">@return</span><span style="color: rgba(0, 128, 0, 1)">
   * </span><span style="color: rgba(128, 128, 128, 1)">@throws</span><span style="color: rgba(0, 128, 0, 1)"> Exception
   </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
    @PostMapping
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> String receiveMessage(HttpServletRequest request) <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> Exception {

      WxMpXmlMessage wxMpXmlMessage </span>=<span style="color: rgba(0, 0, 0, 1)"> WxMpXmlMessage.fromXml(request.getInputStream());
      System.out.println(JSONObject.toJSONString(wxMpXmlMessage));
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> "success"<span style="color: rgba(0, 0, 0, 1)">;
    }

    </span><span style="color: rgba(0, 0, 255, 1)">private</span> Map&lt;String, String&gt; parseXml(HttpServletRequest request) <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> Exception {
      Map</span>&lt;String, String&gt; map = <span style="color: rgba(0, 0, 255, 1)">new</span> HashMap&lt;String, String&gt;<span style="color: rgba(0, 0, 0, 1)">();
      InputStream inputStream </span>=<span style="color: rgba(0, 0, 0, 1)"> request.getInputStream();
      SAXReader reader </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SAXReader();
      Document document </span>=<span style="color: rgba(0, 0, 0, 1)"> reader.read(inputStream);
      Element root </span>=<span style="color: rgba(0, 0, 0, 1)"> document.getRootElement();
      List</span>&lt;Element&gt; elementList =<span style="color: rgba(0, 0, 0, 1)"> root.elements();
      </span><span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> (Element e : elementList) {
            map.put(e.getName(), e.getText());
      }
      inputStream.close();
      inputStream </span>= <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> map;
    }</span></pre>
</div>
<p>这样我们就完成了接收消息的代码开发,于是就可以测试了,在微信公众号进行发消息,就可以看到后台消息接收了</p>
<div class="cnblogs_code">
<pre>{"content":"哈哈哈哈","createTime":1666851473,"fromUser":"o5Gkj5wvS1C9FIbTflNPryZTX5lQ","hardWare":{},"msgId":23863574950788803,"msgType":"text","scanCodeInfo":{},"sendLocationInfo":{},"sendPicsInfo":{"picList":[]},"toUser":"gh_53dbd8c5c889"}</pre>
</div>
<p><img src="https://img2022.cnblogs.com/blog/1783594/202210/1783594-20221027142301350-1683130517.png" alt="" width="736" height="319" loading="lazy"></p>
<p>&nbsp;</p>
<h3>4.4 模板消息</h3>
<p>打开文档可以下载一个模板</p>
<p><img src="https://img2022.cnblogs.com/blog/1783594/202210/1783594-20221028100420908-248289297.png" alt="" width="920" height="473" loading="lazy"></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>首先进入微信公众平台新增一个模板</p>
<p><img src="https://img2022.cnblogs.com/blog/1783594/202210/1783594-20221027223847299-528963528.png" alt="" width="800" height="244" loading="lazy"></p>
<p>编写代码进行</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">    @SneakyThrows
    @Override
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span> pushPayMessage(<span style="color: rgba(0, 0, 255, 1)">long</span><span style="color: rgba(0, 0, 0, 1)"> orderId) {
      String openid </span>= "o5Gkj5wvS1C9FIbTflNPryZTX5lQ"<span style="color: rgba(0, 0, 0, 1)">;
      WxMpTemplateMessage templateMessage </span>=<span style="color: rgba(0, 0, 0, 1)"> WxMpTemplateMessage.builder()
                .toUser(openid)</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">要推送的用户openid</span>
                .templateId("VEjM8ScQLwpP4b9hMqpWgSJVuZT17hfbtx4BoErcj80")<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">模板id</span>
                .url("https://www.baidu.com")<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">点击模板消息要访问的网址</span>
<span style="color: rgba(0, 0, 0, 1)">                .build();
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">3,如果是正式版发送消息,,这里需要配置你的信息</span>
      templateMessage.addData(<span style="color: rgba(0, 0, 255, 1)">new</span> WxMpTemplateData("first", "亲爱的用户:您有一笔订单支付成功", "#272727"<span style="color: rgba(0, 0, 0, 1)">));
      templateMessage.addData(</span><span style="color: rgba(0, 0, 255, 1)">new</span> WxMpTemplateData("keyword1", "java基础课程", "#272727"<span style="color: rgba(0, 0, 0, 1)">));
      templateMessage.addData(</span><span style="color: rgba(0, 0, 255, 1)">new</span> WxMpTemplateData("keyword2", "1314520", "#272727"<span style="color: rgba(0, 0, 0, 1)">));
      templateMessage.addData(</span><span style="color: rgba(0, 0, 255, 1)">new</span> WxMpTemplateData("keyword3", "100", "#272727"<span style="color: rgba(0, 0, 0, 1)">));
      templateMessage.addData(</span><span style="color: rgba(0, 0, 255, 1)">new</span> WxMpTemplateData("keyword4", <span style="color: rgba(0, 0, 255, 1)">new</span> SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(<span style="color: rgba(0, 0, 255, 1)">new</span> Date()), "#272727"<span style="color: rgba(0, 0, 0, 1)">));
      templateMessage.addData(</span><span style="color: rgba(0, 0, 255, 1)">new</span> WxMpTemplateData("remark", "感谢你购买课程,如有疑问,随时咨询!", "#272727"<span style="color: rgba(0, 0, 0, 1)">));
      String msg </span>=<span style="color: rgba(0, 0, 0, 1)"> wxMpService.getTemplateMsgService().sendTemplateMsg(templateMessage);
      System.out.println(msg);
    }</span></pre>
</div>
<h2>5.微信公众号授权登录</h2>
<p>接口文档:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html</p>
<h3>5.1 配置域名</h3>
<p>打开公众平台的接口测试,找到最下面的网页授权,点击修改,将内网穿透域名配置进去。</p>
<p><img src="https://img2022.cnblogs.com/blog/1783594/202210/1783594-20221028110154038-1902264755.png" alt="" width="896" height="537" loading="lazy"></p>
<p>&nbsp;</p>
<h3>5.2 代码实现</h3>
<p>在pom.xm里面引入相关依赖</p>
<div class="cnblogs_code">
<pre>      &lt;dependency&gt;
            &lt;groupId&gt;com.github.binarywang&lt;/groupId&gt;
            &lt;artifactId&gt;weixin-java-mp&lt;/artifactId&gt;
            &lt;version&gt;2.7.0&lt;/version&gt;
      &lt;/dependency&gt;

      &lt;dependency&gt;
            &lt;groupId&gt;dom4j&lt;/groupId&gt;
            &lt;artifactId&gt;dom4j&lt;/artifactId&gt;
            &lt;version&gt;1.1&lt;/version&gt;
      &lt;/dependency&gt;</pre>
</div>
<p>添加配置</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)"># 微信公众平台appId
wechat.mpAppId: wx1c7aa7341465c97b
##微信公众平台api秘钥
wechat.mpAppSecret: 2a94606076dcd32587228e67645415e0
# 授权回调获取用户信息接口地址
wechat.userInfoUrl: http:</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">savage.free.idcfengye.com/api/user/wechat/userInfo</span></pre>
</div>
<p>添加工具类</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">@Component
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span> ConstantPropertiesUtil <span style="color: rgba(0, 0, 255, 1)">implements</span><span style="color: rgba(0, 0, 0, 1)"> InitializingBean {

    @Value(</span>"${wechat.mpAppId}"<span style="color: rgba(0, 0, 0, 1)">)
    </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> String appid;

    @Value(</span>"${wechat.mpAppSecret}"<span style="color: rgba(0, 0, 0, 1)">)
    </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> String appsecret;

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> String ACCESS_KEY_ID;
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> String ACCESS_KEY_SECRET;

    @Override
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span> afterPropertiesSet() <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> Exception {
      ACCESS_KEY_ID </span>=<span style="color: rgba(0, 0, 0, 1)"> appid;
      ACCESS_KEY_SECRET </span>=<span style="color: rgba(0, 0, 0, 1)"> appsecret;
    }
}</span></pre>
</div>
<p>微信配置类</p>
<div class="cnblogs_code"><img src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" id="code_img_closed_a771619b-d0b0-4718-99de-bf88be1b880c" class="code_img_closed"><img src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" id="code_img_opened_a771619b-d0b0-4718-99de-bf88be1b880c" class="code_img_opened" style="display: none">
<div id="cnblogs_code_open_a771619b-d0b0-4718-99de-bf88be1b880c" class="cnblogs_code_hide">
<pre><span style="color: rgba(0, 0, 0, 1)">@Component
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> WeChatMpConfig {

    @Autowired
    </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> ConstantPropertiesUtil constantPropertiesUtil;

    @Bean
    </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> WxMpService wxMpService(){
      WxMpService wxMpService </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> WxMpServiceImpl();
      wxMpService.setWxMpConfigStorage(wxMpConfigStorage());
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> wxMpService;
    }

    @Bean
    </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> WxMpConfigStorage wxMpConfigStorage(){
      WxMpInMemoryConfigStorage wxMpConfigStorage </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> WxMpInMemoryConfigStorage();
      wxMpConfigStorage.setAppId(ConstantPropertiesUtil.ACCESS_KEY_ID);
      wxMpConfigStorage.setSecret(ConstantPropertiesUtil.ACCESS_KEY_SECRET);
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> wxMpConfigStorage;
    }
}</span></pre>
</div>
<span class="cnblogs_code_collapse">View Code</span></div>
<p>编写controller进行实现</p>
<div class="cnblogs_code"><img src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" id="code_img_closed_7c64a355-f696-43ff-ac22-dc3b40ea09b5" class="code_img_closed"><img src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" id="code_img_opened_7c64a355-f696-43ff-ac22-dc3b40ea09b5" class="code_img_opened" style="display: none">
<div id="cnblogs_code_open_7c64a355-f696-43ff-ac22-dc3b40ea09b5" class="cnblogs_code_hide">
<pre><span style="color: rgba(0, 0, 0, 1)">@Slf4j
@Controller
@RequestMapping(</span>"/api/user/wechat"<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> WechatController {

    @Autowired
    </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> UserInfoService userInfoService;

    @Autowired
    </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> WxMpService wxMpService;

    @Value(</span>"${wechat.userInfoUrl}"<span style="color: rgba(0, 0, 0, 1)">)
    </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> String userInfoUrl;

    @GetMapping(</span>"/authorize"<span style="color: rgba(0, 0, 0, 1)">)
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> String authorize(@RequestParam("returnUrl"<span style="color: rgba(0, 0, 0, 1)">) String returnUrl,
                            HttpServletRequest request) {
      String url </span>=<span style="color: rgba(0, 0, 0, 1)"> wxMpService.oauth2buildAuthorizationUrl(userInfoUrl,
                WxConsts.OAUTH2_SCOPE_USER_INFO,
                URLEncoder.encode(returnUrl.replace(</span>"guiguketan", "#"<span style="color: rgba(0, 0, 0, 1)">)));

      </span><span style="color: rgba(0, 0, 255, 1)">return</span> "redirect:" +<span style="color: rgba(0, 0, 0, 1)"> url;
    }

    @GetMapping(</span>"/userInfo"<span style="color: rgba(0, 0, 0, 1)">)
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> String userInfo(@RequestParam("code"<span style="color: rgba(0, 0, 0, 1)">) String code,
                           @RequestParam(</span>"state"<span style="color: rgba(0, 0, 0, 1)">) String returnUrl) {
      </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">拿着code进行请求</span>
            WxMpOAuth2AccessToken wxMpOAuth2AccessToken =<span style="color: rgba(0, 0, 0, 1)"> wxMpService.oauth2getAccessToken(code);
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取openId</span>
            String openId =<span style="color: rgba(0, 0, 0, 1)"> wxMpOAuth2AccessToken.getOpenId();
            log.info(</span>"获取openId,{}"<span style="color: rgba(0, 0, 0, 1)">, openId);
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取微信信息</span>
            WxMpUser wxMpUser = wxMpService.oauth2getUserInfo(wxMpOAuth2AccessToken, <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">);
            log.info(</span>"wxMpUser:{}"<span style="color: rgba(0, 0, 0, 1)">, wxMpUser);
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取微信信息添加数据库</span>
            UserInfo userInfo =<span style="color: rgba(0, 0, 0, 1)"> userInfoService.getUserInfoOpenId(openId);
            </span><span style="color: rgba(0, 0, 255, 1)">if</span> (userInfo == <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
                userInfo </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> UserInfo();
                userInfo.setOpenId(openId);
                userInfo.setNickName(wxMpUser.getNickname());
                userInfo.setProvince(wxMpUser.getProvince());
                userInfo.setSex(wxMpUser.getSexId());
                userInfo.setUnionId(wxMpUser.getUnionId());
                userInfo.setAvatar(wxMpUser.getHeadImgUrl());
                userInfoService.save(userInfo);
            }
            </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, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">生成token 按照一定规则生产字符串,可以包含用户信息</span>
            String token =<span style="color: rgba(0, 0, 0, 1)"> JwtHelper.createToken(userInfo.getId(), userInfo.getNickName());
            </span><span style="color: rgba(0, 0, 255, 1)">if</span>(returnUrl.indexOf("?")==-1<span style="color: rgba(0, 0, 0, 1)">){
                </span><span style="color: rgba(0, 0, 255, 1)">return</span> "redirect:" + returnUrl + "?token=" +<span style="color: rgba(0, 0, 0, 1)"> token;
            }
            </span><span style="color: rgba(0, 0, 255, 1)">return</span> "redirect:" + returnUrl + "&amp;token=" +<span style="color: rgba(0, 0, 0, 1)"> token;
      } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (WxErrorException e) {
            e.printStackTrace();
      }
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
    }
}</span></pre>
</div>
<span class="cnblogs_code_collapse">View Code</span></div>
<p>&nbsp;</p>

</div>
<div id="MySignature" role="contentinfo">
    <style>
    #MySignature {
      display: block;
            background-color: #95FFE9;
            border-radius: 7px;
            box-shadow: 1px 1px 1px #6B6B6B;
            padding: 10px;
            line-height: 1.5;
            text-shadow: 1px 1px 1px #FFF;
            font-size: 16px;
    }
    #MySignature a {
      margin: 0;
      padding: 0;
      display: contents;
    }
</style>

<p style="color: #8B0011;">一点点学习,一丝丝进步。不懈怠,才不会被时代所淘汰!</p><br><br>
来源:https://www.cnblogs.com/fqh2020/p/16760539.html
頁: [1]
查看完整版本: 微信公众号开发