张书华 發表於 2020-7-13 10:14:00

微信公众号开发经验总结

<h1>&nbsp;</h1>
<h2>1.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 快捷访问</h2>
<p>1.1&nbsp;&nbsp; 测试公众号注册:</p>
<p align="left"><strong>http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login</strong></p>
<p align="left">1.2&nbsp;&nbsp; 微信公众号开发指南:</p>
<p align="left">https://mp.weixin.qq.com/wiki?t=resource/res_main&amp;id=mp1445241432</p>
<p align="left">1.3&nbsp;&nbsp; 微信全局返回码说明:</p>
<p align="left">https://mp.weixin.qq.com/wiki?t=resource/res_main&amp;id=mp1433747234</p>
<p align="left">1.4&nbsp;&nbsp; 微信公众号接口权限说明:</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;https://mp.weixin.qq.com/wiki?t=resource/res_main&amp;id=mp1433401084</p>
<p>&nbsp;</p>
<h2>2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;注册一个公众号账户(也可先用测试公众号调试环境)</h2>
<h3>2.1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 账户注册</h3>
<p align="left">2.1.1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 正确填写下列信息</p>
<p>&nbsp;</p>
<p>注意:</p>
<p>URL必须以http:// 或者https:// 开头,分别支持80端口和443端口;</p>
<p>Token必须为英文或者数字,长度为3-32字符;</p>
<p>&nbsp;</p>
<p>2.1.2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 开发过程中,需要注意接口的调用次数,</p>
<p>&nbsp;</p>
<p>2.1.3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 注意检查URL和JS接口安全域名,可以保持一致,也可以不一样,个人建议最好保持一致;</p>
<p>&nbsp;</p>
<h2>3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 测试开发环境</h2>
<p>Eg:</p>
<p>微信网页授权access_token和普通access_token区别</p>
<p>https://blog.csdn.net/benben_2015/article/details/79703508</p>
<p>微信获取用户信息的两个接口和两个ACCESS_TOKEN</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;https://www.cnblogs.com/sxmny/articles/4969119.html</p>
<p>&nbsp;</p>
<h3>2.1 记录全局定量(获取Token的两个定量,在微信公众号-账户信息处可以查询):</h3>
<p>Appid&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 应用ID</p>
<p>AppSecret&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 应用密匙</p>
<h3>2.2 获取普通access_token(access_token是公众号的全局唯一接口调用凭据,公众号调用各接口时都需要使用access_token)</h3>
<p align="left">调用接口:</p>
<p align="left">URL:&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;https://api.weixin.qq.com/cgi-bin/token</p>
<p align="left">参数: &nbsp;&nbsp;&nbsp; grant_type : “client_credential”--------获取access_token填写client_credential&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Appid : Appid---------第三方用户唯一凭证</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AppSecret : AppSecret-----------第三方用户唯一凭证密钥,即appsecret</p>
<p align="left">返回参数:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; access_token---------获取到的凭证</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; expires_in----------凭证有效事件,单位:秒</p>
<p align="left">注:公众号对此接口的调用是有次数限制的,默认是2000,花钱可增加次数,获取的access_token的有效期默认是2小时,故而,在开发过程中,可将调用此接口的access_token设为全局变量,并将次接口的调用方法设为全局自动调用,独立出来;</p>
<p align="left">Eg(将获取access_token的接口独立,并调整为100分钟自动刷新):</p>
<p align="left"><strong>package</strong>&nbsp;com.gzh.api.utils;</p>
<p align="left">&nbsp;</p>
<p align="left"><strong>import</strong>&nbsp;java.util.Map;</p>
<p align="left"><strong>import</strong>&nbsp;java.util.Timer;</p>
<p align="left"><strong>import</strong>&nbsp;java.util.TimerTask;</p>
<p align="left"><strong>import</strong>&nbsp;java.util.concurrent.atomic.AtomicInteger;</p>
<p align="left">&nbsp;</p>
<p align="left"><strong>import</strong>&nbsp;com.alibaba.fastjson.JSONObject;</p>
<p align="left"><strong>import</strong>&nbsp;com.google.common.collect.Maps;</p>
<p align="left"><strong>import</strong>&nbsp;com.jfinal.kit.Prop;</p>
<p align="left"><strong>import</strong>&nbsp;com.jfinal.kit.PropKit;</p>
<p align="left">&nbsp;</p>
<p align="left"><strong>import</strong>&nbsp;cn.hutool.http.HttpUtil;</p>
<p align="left">&nbsp;</p>
<p align="left">/**</p>
<p align="left">&nbsp;* access_token 自动刷新</p>
<p align="left">&nbsp;*&nbsp;<strong>@author</strong>&nbsp;Administrator</p>
<p align="left">&nbsp;*</p>
<p align="left">&nbsp;*/</p>
<p align="left"><strong>public</strong>&nbsp;<strong>class</strong>&nbsp;WxToken {</p>
<p align="left">&nbsp;</p>
<p align="left">&nbsp;&nbsp;&nbsp;<strong>public</strong>&nbsp;<strong>static</strong>&nbsp;String&nbsp;<em>globalTokenObject</em>&nbsp;= "";//调取接口的返回值参数(access_token、expires_in)</p>
<p align="left">&nbsp;&nbsp;&nbsp;<strong>public</strong>&nbsp;<strong>static</strong>&nbsp;String&nbsp;<em>globalToken</em>&nbsp;= "";// access_token</p>
<p align="left">&nbsp;&nbsp;&nbsp;<strong>public</strong>&nbsp;<strong>static</strong>&nbsp;AtomicInteger&nbsp;<em>atomicInteger</em>&nbsp;=&nbsp;<strong>new</strong>&nbsp;AtomicInteger();//计数器,统计接口调用的次数</p>
<p align="left">&nbsp;&nbsp;&nbsp;<strong>public</strong>&nbsp;<strong>static</strong>&nbsp;String appid = "**************";</p>
<p align="left">&nbsp;&nbsp;&nbsp;<strong>public</strong>&nbsp;<strong>static</strong>&nbsp;String appsecret = "*************";</p>
<p align="left">&nbsp;&nbsp;&nbsp;<strong>static</strong>&nbsp;{</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>new</strong>&nbsp;Timer().schedule(<strong>new</strong>&nbsp;TimerTask() {</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @Override</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>public</strong>&nbsp;<strong>void</strong>&nbsp;run() {</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Map&lt;String,Object&gt; paramMap = Maps.<em>newHashMap</em>();</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; paramMap.put("appid", appid);</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; paramMap.put("secret", appsecret);</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; paramMap.put("grant_type", "client_credential");</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<em>globalTokenObject</em>&nbsp;= HttpUtil.<em>get</em>("https://api.weixin.qq.com/cgi-bin/token", paramMap);</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JSONObject wxToken = JSONObject.<em>parseObject</em>(<em>globalTokenObject</em>);</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<em>globalToken</em>&nbsp;= HttpUtil.<em>get</em>("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + wxToken.getString("access_token") + "&amp;type=jsapi");&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<em>atomicInteger</em>.incrementAndGet();</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }, 0, 2*50*60*1000);</p>
<p align="left">&nbsp;&nbsp; }&nbsp;</p>
<p align="left">}</p>
<p align="left">&nbsp;</p>
<h3>2.3 获取用户Code/微信访问公众号地址</h3>
<p align="left">使用微信打开如下地址https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&amp;redirect_uri=REDIRECT_URI&amp;response_type=code&amp;scope=SCOPE&amp;state=STATE#wechat_redirect</p>
<p align="left">&nbsp;</p>
<p align="left">参数:appid---------appid</p>
<p align="left">redirect_uri-------系统路径,需与微信公中号绑定路径一致</p>
<p align="left">response_type-------“code”字符串</p>
<p align="left">scope------“snsapi_userinfo”字符串</p>
<p align="left">state------“1”字符串</p>
<p align="left">&nbsp;</p>
<p align="left">(注意这个接口中有个参数scope 默认有2个值snsapi_base和snsapi_userinfo,这个接口会根据scope 来生成不同的code并且获取不同作用的access_token&nbsp;,不管scope传什么值都能在得到对应access_token的同时得到open_id, 如果你只需要得到opend_id 那使用snsapi_base参数到此结束了,如果需要获取用户的其他信息比如 昵称 地址 就要snsapi_userinfo 会弹出授权)</p>
<p align="left">eg:</p>
<p align="left">https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx97967746637ee7c4&amp;redirect_uri=http://www.HuaLuo.com/gzh/gzh/app.html&amp;response_type=code&amp;scope=snsapi_userinfo&amp;state=1#wechat_redirect</p>
<p align="left">直接在微信中访问,系统中用如下方法接收:</p>
<p align="left">//获取用户code&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --var code = getCode(‘code’);</p>
<p align="left">Function getCode(name){</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var reg = new RegExp("(^|&amp;)" + name + "=([^&amp;]*)(&amp;|$)", "i");</p>
<p align="left">var r = window.location.search.substr(1).match(reg);</p>
<p align="left">if (r != null) return unescape(r); return null;</p>
<p align="left">}</p>
<p align="left">即可拿到用户Code;</p>
<h3>2.4 获取openid</h3>
<p align="left">简单的实现微信获取openid</p>
<p align="left">https://blog.csdn.net/z880698223/article/details/78485243/</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1.调用https://open.weixin.qq.com/connect/oauth2/authorize接口获取到code</p>
<p align="left">《参数2.3》</p>
<p align="left">2.得到code作为一个参数调用https://api.weixin.qq.com/sns/oauth2/access_token接口获取到openid 《参照2.5》</p>
<h3>2.5 获取微信网页授权access_token</h3>
<p align="left">调用接口:</p>
<p align="left">URL: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;https://api.weixin.qq.com/sns/oauth2/access_token</p>
<p align="left">参数:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p align="left">grant_type : “authorization_code”--------填写client_credential</p>
<p align="left">Appid : Appid---------第三方用户唯一凭证</p>
<p align="left">AppSecret : AppSecret-----------第三方用户唯一凭证密钥,即appsecret</p>
<p align="left">Code:Code----------标识不同的用户code 《参照2.3》</p>
<p align="left">返回参数:</p>
<p align="left">Openid</p>
<p align="left">access_token</p>
<p align="left">&nbsp;</p>
<h3>2.6 获取微信用户信息</h3>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EG:</p>
<p>https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&amp;openid=OPENID&amp;lang=zh_CN</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 调用接口:</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; URL: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;https://api.weixin.qq.com/sns/userinfo</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 参数:</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Openid-----《参照2.5》</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Lang----“zh_CN”字符串</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; access_token------《参照2》&gt;(注:此access_token网上资料说需要普通access_token,及调用《2.2》接口返回的普通access_token,但是实际中发现调用《2.5》接口返回的网页授权access_token也可以拿到用户信息,故而实际开发中可换着调用调试,个人建议使用普通access_token,因为开文提出将此参数定义为全局变量,故而对代码一致性维护较方便)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 返回参数:</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Subscribe--------用户是否订阅该公众号标识,值为0时,代表此用户没有关注该公众号,拉取不到其余信息</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Openid----------用户的标识,对当前公众号唯一</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Nickname-----------用户的昵称</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Sex----------用户的性别,值为1时是男性,值为2时是女性,值为0时是未知</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; City----------用户所在城市</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Country-------------用户所在国家</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Province-----------用户所在省份</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Language---------用户的语言,简体中文为zh_CN</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Headimgurl-----------用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空。若用户更换头像,原有头像URL将失效</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; subscribe_time-------------用户关注时间,为时间戳。如果用户曾多次关注,则取最后关注时间</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unionid------------只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; remark-----------公众号运营者对粉丝的备注,公众号运营者可在微信公众平台用户管理界面对粉丝添加备注</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; groupid ------------- 用户所在的分组ID(兼容旧的用户分组接口)</p>
<p>tagid_list ------------用户被打上的标签ID列表</p>
<p>subscribe_scene----------- 返回用户关注的渠道来源,ADD_SCENE_SEARCH 公众号搜索,ADD_SCENE_ACCOUNT_MIGRATION 公众号迁移,ADD_SCENE_PROFILE_CARD 名片分享,ADD_SCENE_QR_CODE 扫描二维码,ADD_SCENEPROFILE LINK 图文页内名称点击,ADD_SCENE_PROFILE_ITEM 图文页右上角菜单,ADD_SCENE_PAID 支付后关注,ADD_SCENE_OTHERS 其他</p>
<p>qr_scene ------------二维码扫码场景(开发者自定义)</p>
<p>qr_scene_str------------ 二维码扫码场景描述(开发者自定义)</p>
<p>&nbsp;</p>
<h3>2.7 调用微信JS-SDK,获取jsapi_ticket</h3>
<p align="left">微信公众平台jsapi开发教程(1)获取:</p>
<p>https://blog.csdn.net/linfanhehe/article/details/52354848</p>
<p>生成签名之前必须先了解一下jsapi_ticket,jsapi_ticket是公众号用于调用微信JS接口的临时票据。正常情况下,jsapi_ticket的有效期为7200秒,通过access_token来获取。由于获取jsapi_ticket的api调用次数非常有限,频繁刷新jsapi_ticket会导致api调用受限,影响自身业务,开发者必须在自己的服务全局缓存jsapi_ticket 。《参照2.2》和我们获取普通access_token类似,由于有访问次数的限制,我们将次参数调为全局自动触发;</p>
<p>&nbsp;</p>
<p>接口:</p>
<p>URL:&nbsp;https://api.weixin.qq.com/cgi-bin/ticket/getticket</p>
<p>参数: access_token-----《参照2.2》</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Type----“jsapi”字符串</p>
<p>返回参数:ticket------------<code>调用微信</code><code>jsapi</code><code>的凭证票</code></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<h3>2.8 初始化微信config配置</h3>
<p>所有需要使用JS-SDK的页面必须先注入配置信息,否则将无法调用(同一个url仅需调用一次,对于变化url的SPA的web app可在每次url变化时进行调用,目前Android微信客户端不支持pushState的H5新特性,所以使用pushState来实现web app的页面会导致签名失败,此问题会在Android6.2中修复)。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 微信调取音频、视频、分享等接口前,需要先初始化验证</p>
<p>JS:</p>
<p align="left">app.ajax('/wxInitConfig.action',{'url':location.href},<strong>function</strong>(configDate){</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wx.config({</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; debug:&nbsp;<strong>true</strong>, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; appId: configDate.appid, // 必填,公众号的唯一标识</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timestamp: configDate.timestamp, // 必填,生成签名的时间戳</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nonceStr: configDate.nonceStr, // 必填,生成签名的随机串</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; signature: configDate.signature,// 必填,签名,见附录1</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jsApiList: ['onMenuShareQQ', 'onMenuShareWeibo', 'onMenuShareTimeline','onMenuShareAppMessage','startRecord','stopRecord','onVoiceRecordEnd','playVoice','stopVoice','onVoicePlayEnd','uploadVoice','onMenuShareQZone'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2 https://mp.weixin.qq.com/wiki?t=resource/res_main&amp;id=mp1421141115</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; });</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; });</p>
<p>ACTION:</p>
<p align="left"><strong>public</strong>&nbsp;<strong>void</strong>&nbsp;wxInitConfig(){</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JSONObject wxToken = JSONObject.<em>parseObject</em>(WxToken.<em>globalToken</em>);《参照2.2代码,获取全局ticket》</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String jsapi_ticket = wxToken.getString("ticket");</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>//</strong><strong>此处如果没有正常获取到</strong>jsapi_ticket,请查看返回码,在微信公众号中查找错误信息</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //前台传过来的当前URL访问路径</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String url = Dto.<em>getParam</em>().getString("url");</p>
<p align="left">&nbsp;</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //算法生成时间戳、签名等信息,见下列代码,直接附源码,不多说</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Map&lt;String, String&gt; ret = Sign.<em>sign</em>(jsapi_ticket, url);</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>for</strong>&nbsp;(@SuppressWarnings("rawtypes") Map.Entry entry : ret.entrySet()) {</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.<strong><em>err</em></strong>.println(entry.getKey().toString() + " : " + entry.getValue());</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Dto.<em>getResult</em>().set(entry.getKey().toString(), entry.getValue());</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dto.<em>getResult</em>().set("appid",&nbsp;<em>wxProp</em>.get("appid"));</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>this</strong>.renderJson(Dto.<em>getResult</em>().getData());</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;</p>
<p>///////////////算法生成时间戳、签名等信息/////////////////////////////</p>
<p align="left">////过程中可能调用MessageDigest&nbsp;包,请自行Baidu下载////////////////</p>
<p align="left"><strong>package</strong>&nbsp;com.gzh.api.utils;</p>
<p align="left">&nbsp;</p>
<p align="left"><strong>import</strong>&nbsp;java.util.UUID;</p>
<p align="left"><strong>import</strong>&nbsp;java.util.Map;</p>
<p align="left"><strong>import</strong>&nbsp;java.util.HashMap;</p>
<p align="left"><strong>import</strong>&nbsp;java.util.Formatter;</p>
<p align="left"><strong>import</strong>&nbsp;java.security.MessageDigest;</p>
<p align="left"><strong>import</strong>&nbsp;java.security.NoSuchAlgorithmException;</p>
<p align="left"><strong>import</strong>&nbsp;java.io.UnsupportedEncodingException;&nbsp;</p>
<p align="left">&nbsp;</p>
<p align="left"><strong>public</strong>&nbsp;<strong>class</strong>&nbsp;Sign {</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;<strong>public</strong>&nbsp;<strong>static</strong>&nbsp;<strong>void</strong>&nbsp;main(String[] args) {</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String jsapi_ticket = "jsapi_ticket";</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 注意 URL 一定要动态获取,不能&nbsp;hardcode</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String url = "http://example.com";</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Map&lt;String, String&gt; ret =&nbsp;<em>sign</em>(jsapi_ticket, url);</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>for</strong>&nbsp;(Map.Entry&nbsp;entry : ret.entrySet()) {</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.<strong><em>out</em></strong>.println(entry.getKey() + ", " + entry.getValue());</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p align="left">&nbsp;&nbsp;&nbsp; };</p>
<p align="left">&nbsp;</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;<strong>public</strong>&nbsp;<strong>static</strong>&nbsp;Map&lt;String, String&gt; sign(String jsapi_ticket, String url) {</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Map&lt;String, String&gt; ret =&nbsp;<strong>new</strong>&nbsp;HashMap&lt;String, String&gt;();</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String nonce_str =&nbsp;<em>create_nonce_str</em>();</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String timestamp =&nbsp;<em>create_timestamp</em>();</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String string1;</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String signature = "";</p>
<p align="left">&nbsp;</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //注意这里参数名必须全部小写,且必须有序</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string1 = "jsapi_ticket=" + jsapi_ticket +</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "&amp;noncestr=" + nonce_str +</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "&amp;timestamp=" + timestamp +</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "&amp;url=" + url;</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.<strong><em>out</em></strong>.println(string1);</p>
<p align="left">&nbsp;</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>try</strong></p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MessageDigest crypt = MessageDigest.<em>getInstance</em>("SHA-1");</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; crypt.reset();</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; crypt.update(string1.getBytes("UTF-8"));</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; signature =&nbsp;<em>byteToHex</em>(crypt.digest());</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>catch</strong>&nbsp;(NoSuchAlgorithmException e)</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.printStackTrace();</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>catch</strong>&nbsp;(UnsupportedEncodingException e)</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.printStackTrace();</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p align="left">&nbsp;</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret.put("url", url);</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret.put("jsapi_ticket", jsapi_ticket);</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret.put("nonceStr", nonce_str);</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret.put("timestamp", timestamp);</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret.put("signature", signature);</p>
<p align="left">&nbsp;</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>return</strong>&nbsp;ret;</p>
<p align="left">&nbsp;&nbsp;&nbsp; }</p>
<p align="left">&nbsp;</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;<strong>private</strong>&nbsp;<strong>static</strong>&nbsp;String byteToHex(<strong>final</strong>&nbsp;<strong>byte</strong>[] hash) {</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Formatter formatter =&nbsp;<strong>new</strong>&nbsp;Formatter();</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>for</strong>&nbsp;(<strong>byte</strong>&nbsp;b : hash)</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; formatter.format("%02x", b);</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String result = formatter.toString();</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; formatter.close();</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>return</strong>&nbsp;result;</p>
<p align="left">&nbsp;&nbsp;&nbsp; }</p>
<p align="left">&nbsp;</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;<strong>private</strong>&nbsp;<strong>static</strong>&nbsp;String create_nonce_str() {</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>return</strong>&nbsp;UUID.<em>randomUUID</em>().toString();</p>
<p align="left">&nbsp;&nbsp;&nbsp; }</p>
<p align="left">&nbsp;</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;<strong>private</strong>&nbsp;<strong>static</strong>&nbsp;String create_timestamp() {</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>return</strong>&nbsp;Long.<em>toString</em>(System.<em>currentTimeMillis</em>() / 1000);</p>
<p align="left">&nbsp;&nbsp;&nbsp; }</p>
<p>}</p>
<p>&nbsp;</p>
<h3>2.9 调用微信JS-SDK实例(以录音为例);</h3>
<p>参考微信开发说明文档</p>
<p>https://mp.weixin.qq.com/wiki?t=resource/res_main&amp;id=mp1421141115</p>
<p>&nbsp;</p>
<p align="left">/* 开启录音*/</p>
<p>wx.startRecord({</p>
<p>success:<strong>function</strong>() {</p>
<p>&nbsp;&nbsp; alert(“接口调用成功”);</p>
<p>},</p>
<p>Fail:function(){</p>
<p>&nbsp;&nbsp; alert(“接口调用失败”);//可以检查access_token权限或者弹出调试,具体问题具体分析《参照2.8》,开启调试模式</p>
<p>},</p>
<p>Cancel:function(){</p>
<p>&nbsp;&nbsp; alert(“用户拒绝提供录音权限”);</p>
<p>}</p>
<p>});</p>
<p align="left">/* 停止录音*/</p>
<p align="left">wx.stopRecord({</p>
<p align="left"><br>success: function (res) {</p>
<p align="left"><br>var localId = res.localId;</p>
<p align="left"><br>}<br>});</p>
<p align="left">/* 监听录音自动停止(由于微信有录音时限限制,一次录音最大时长为1分钟,若超过此时=时限未停止录音,则执行此接口方法)*/</p>
<pre><code class="hljs css"><span class="hljs-selector-tag">wx<span class="hljs-selector-class">.onVoiceRecordEnd({</span></span></code><br>
<code class="hljs javascript"><span class="hljs-comment">// </span></code><code class="hljs">录音时间超过一分钟没有停止的时候会执行 complete 回调</code><br>
<code class="hljs javascript">complete: <span class="hljs-function"><span class="hljs-keyword">function (<span class="hljs-params">res) {</span></span></span></code><br>
<code class="hljs javascript"><span class="hljs-keyword">var localId = res.localId;</span></code><br>
<code class="hljs">}</code><br>
<code class="hljs">});</code></pre>
<p>注:我在此处有一个录音时长大于一分钟的问题,目前没有好的解决方案,楼主在此处的解决方案是:当执行上述大于一分钟回调时,重新开启录音接口,直至手动关闭录音;将几个录音的<code>localId</code><code>存起来,一并发至后台获取录音文件,合成一份音频文件,合成代码网上找,但这个方法有一个Bug,在重新开启录音,即转换的这个时间段,有大概1~2秒的录音失效期;</code></p>
<pre><code class="hljs">&nbsp;</code></pre>
<pre>/* 播放录音 */<code class="hljs"></code></pre>
<pre><code class="hljs css"><span class="hljs-selector-tag">wx<span class="hljs-selector-class">.playVoice({</span></span></code><br>
<code class="hljs less"><span class="hljs-attribute">localId: <span class="hljs-string">'' <span class="hljs-comment">// </span></span></span></code><code class="hljs">需要播放的音频的本地ID,由stopRecord接口获得</code><br>
<code class="hljs">});</code></pre>
<pre>&nbsp;</pre>
<pre>/* 暂停播放录音 */<code class="hljs"></code></pre>
<pre><code class="hljs css"><span class="hljs-selector-tag">wx<span class="hljs-selector-class">.pauseVoice({</span></span></code><br>
<code class="hljs less"><span class="hljs-attribute">localId: <span class="hljs-string">'' <span class="hljs-comment">// </span></span></span></code><code class="hljs">需要暂停的音频的本地ID,由stopRecord接口获得</code><br>
<code class="hljs">});</code></pre>
<p align="left">&nbsp;</p>
<pre>/* 停止播放录音 */</pre>
<pre><code class="hljs css"><span class="hljs-selector-tag">wx<span class="hljs-selector-class">.stopVoice({</span></span></code><br>
<code class="hljs less"><span class="hljs-attribute">localId: <span class="hljs-string">'' <span class="hljs-comment">// </span></span></span></code><code class="hljs">需要停止的音频的本地ID,由stopRecord接口获得</code><br>
<code class="hljs">});</code></pre>
<pre>/* 监听录音播放完毕接口 */</pre>
<pre><code class="hljs css"><span class="hljs-selector-tag">wx<span class="hljs-selector-class">.onVoicePlayEnd({</span></span></code><br>
<code class="hljs javascript">success: <span class="hljs-function"><span class="hljs-keyword">function (<span class="hljs-params">res) {</span></span></span></code><br>
<code class="hljs javascript"><span class="hljs-keyword">var localId = res.localId; <span class="hljs-comment">// </span></span></code><code class="hljs">返回音频的本地ID</code><br>
<code class="hljs">}</code><br>
<code class="hljs">});</code></pre>
<pre><code class="hljs">&nbsp;</code></pre>
<pre>/* 上传录音接口 */<code class="hljs"></code></pre>
<pre><code class="hljs css"><span class="hljs-selector-tag">wx<span class="hljs-selector-class">.uploadVoice({</span></span></code><br>
<code class="hljs less"><span class="hljs-attribute">localId: <span class="hljs-string">'', <span class="hljs-comment">// </span></span></span></code><code class="hljs">需要上传的音频的本地ID,由stopRecord接口获得</code><br>
<code class="hljs less"><span class="hljs-attribute">isShowProgressTips: <span class="hljs-number">1, <span class="hljs-comment">// </span></span></span></code><code class="hljs">默认为1,显示进度提示</code><br>
<code class="hljs javascript">success: <span class="hljs-function"><span class="hljs-keyword">function (<span class="hljs-params">res) {</span></span></span></code><br>
<code class="hljs javascript"><span class="hljs-keyword">var serverId = res.serverId; <span class="hljs-comment">// </span></span></code><code class="hljs">返回音频的服务器端ID</code><br>
<code class="hljs">}</code><br>
<code class="hljs">});</code></pre>
<pre>备注:上传语音有效期3天,可用微信多媒体接口下载语音到自己的服务器,此处获得的 serverId 即 media_id,参考文档 .目前多媒体文件下载接口的频率限制为10000次/天,如需要调高频率,请登录微信公众平台,在开发 - 接口权限的列表中,申请提高临时上限。</pre>
<pre>&nbsp;</pre>
<pre>根据<code class="hljs">serverId获取微信服务器上的录音文件;</code></pre>
<pre><code class="hljs">调用接口:</code></pre>
<pre><code class="hljs groovy">URL: <span class="hljs-string">http:<span class="hljs-comment">//file.api.weixin.qq.com/cgi-bin/media/get</span></span></code></pre>
<pre>参数: access_token------参照《2.2》</pre>
<pre>media_id----------<code class="hljs">serverId</code></pre>
<pre><code class="hljs">返回参数是文件流,需自行解析;附实例;</code></pre>
<pre><code class="hljs">Eg:</code></pre>
<p align="left">/* (non-Javadoc)</p>
<p align="left">&nbsp;&nbsp; &nbsp;* @see com.gzh.api.service.ReciteContentService#saveRecite(com.sdp.core.dt.DtoParam)</p>
<p align="left">&nbsp;&nbsp; &nbsp;*/</p>
<p align="left">&nbsp;&nbsp; @Override</p>
<p align="left">&nbsp;&nbsp;&nbsp;<strong>public</strong>&nbsp;DtoResult saveRecite(DtoParam param)&nbsp;<strong>throws</strong>&nbsp;Exception{</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /** 参数接收*/</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String contentName = Dto.<em>getParam</em>().getString("contentName");//诗词名称</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String contentId = Dto.<em>getParam</em>().getString("contentId");//诗词ID</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String fansId = Dto.<em>getParam</em>().getString("fansId");//粉丝ID</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String serverId = Dto.<em>getParam</em>().getString("serverId");</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Record isFans = api.findFirst("select * from gzh_personalcenter where loginid = ?", fansId);</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>if</strong>(isFans !=&nbsp;<strong>null</strong>&nbsp;&amp;&amp; isFans.get("department") !=&nbsp;<strong>null</strong>&nbsp;&amp;&amp; !isFans.get("department").equals("")){</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String[] serverIds = Str.<em>isNotAnyEmpty</em>(serverId)?serverId.split(","):<strong>null</strong>;/* 当传过来的serverId有效时执行*/</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>if</strong>(serverIds !=&nbsp;<strong>null</strong>&nbsp;&amp;&amp; serverIds.length &gt; 0){</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.<strong><em>err</em></strong>.println("正在上传录音文件...");</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>long</strong>&nbsp;time1 = System.<em>currentTimeMillis</em>();</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 删除旧录音文件及数据*/</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; List&lt;Record&gt; deleteList = api.find("select * from gzh_recitecontent where fansid = ? and contentid = ?", fansId, contentId);</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>for</strong>(Record re : deleteList){</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; File file =&nbsp;<strong>new</strong>&nbsp;File(fileRoot + re.getStr("path"));</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>if</strong>(file.exists()) file.delete();</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; api.deleteById("gzh_recitecontent", re.getStr("id"));</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //String token = HttpUtil.get("https://api.weixin.qq.com/cgi-bin/token", paramMap);</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JSONObject wxToken = JSONObject.<em>parseObject</em>(WxToken.<em>globalTokenObject</em>);</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; List&lt;String&gt; tempRecites =&nbsp;<strong>new</strong>&nbsp;ArrayList&lt;&gt;();/*&nbsp;amr文件集合*/</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; List&lt;String&gt; newRecites =&nbsp;<strong>new</strong>&nbsp;ArrayList&lt;&gt;();/* mp3文件集合*/</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 进行临时目录创建*/</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String tempResPath = fileRoot + tempPath;</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>if</strong>(!<strong>new</strong>&nbsp;File(tempResPath).exists())&nbsp;<strong>new</strong>&nbsp;File(tempResPath).mkdirs();</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 进行录音文件目录创建*/</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String realResPath = fileRoot + fileStore + recitePath + "/" + contentId + "/" + fansId;//文件实际存储目录</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>if</strong>(!<strong>new</strong>&nbsp;File(realResPath).exists())&nbsp;<strong>new</strong>&nbsp;File(realResPath).mkdirs();//先进行目录创建操作</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>int</strong>&nbsp;size = 0;/* 记录所有文件输入流大小*/</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 定义输出流写入参数*/</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FileOutputStream fileOutputStream =&nbsp;<strong>null</strong>;</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; InputStream inputStream =&nbsp;<strong>null</strong>;</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String fileName = ID.<em>get</em>();/* 文件名称*/</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 将文件分批取出并保存为MP3文件*/</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>for</strong>(<strong>int</strong>&nbsp;i = 0; i &lt; serverIds.length; i++){</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>try</strong>{</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 从微信服务器获取录音文件,格式为amr*/</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String url = "http://file.api.weixin.qq.com/cgi-bin/media/get?access_token="</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + wxToken.getString("access_token") + "&amp;media_id=" + serverIds;</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; URL urlGet =&nbsp;<strong>new</strong>&nbsp;URL(url);</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpURLConnection http = (HttpURLConnection) urlGet.openConnection();</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; http.setRequestMethod("GET"); // 必须是get方式请求</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; http.setDoOutput(<strong>true</strong>);</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; http.setDoInput(<strong>true</strong>);</p>
<p align="left">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.setProperty("sun.net.client.defaultConnectTimeout", "3000");// 连接超时30秒</p>
<p align="left">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.setProperty("sun.net.client.defaultReadTimeout", "3000"); // 读取超时30秒</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; http.connect();</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 获取文件转化为byte流</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inputStream = http.getInputStream();</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; size += inputStream.available();</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String tempFileName = tempResPath + "/" + fileName + (i+1) + ".amr";</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String recitFileName = tempResPath + "/" + fileName + (i+1) + ".mp3";</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>if</strong>(serverIds.length == 1){</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; recitFileName = realResPath + "/" + fileName + ".mp3";</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tempRecites.add(tempFileName);</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newRecites.add(recitFileName);</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>byte</strong>[] data =&nbsp;<strong>new</strong>&nbsp;<strong>byte</strong>;</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>int</strong>&nbsp;len = 0;</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fileOutputStream =&nbsp;<strong>new</strong>&nbsp;FileOutputStream(tempFileName);</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>while</strong>&nbsp;((len = inputStream.read(data)) != -1) {</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fileOutputStream.write(data, 0, len);</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 关闭流资源*/</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>if</strong>(inputStream !=&nbsp;<strong>null</strong>) inputStream.close();</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>if</strong>(fileOutputStream !=&nbsp;<strong>null</strong>) fileOutputStream.close();</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*&nbsp;amr格式转换成mp3格式*/</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; File source =&nbsp;<strong>new</strong>&nbsp;File(tempFileName);</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; File target =&nbsp;<strong>new</strong>&nbsp;File(recitFileName);</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AudioAttributes audio =&nbsp;<strong>new</strong>&nbsp;AudioAttributes();</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Encoder encoder =&nbsp;<strong>new</strong>&nbsp;Encoder();</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; audio.setCodec("libmp3lame");</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EncodingAttributes attrs =&nbsp;<strong>new</strong>&nbsp;EncodingAttributes();</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; attrs.setFormat("mp3");</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; attrs.setAudioAttributes(audio);</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; encoder.encode(source, target, attrs);/* 执行转换*/</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<strong>catch</strong>(Exception e) {</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.<strong><em>err</em></strong>.println(e.getMessage());</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.<strong><em>err</em></strong>.println("输入流大小:" + size);</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; File file =&nbsp;<strong>new</strong>&nbsp;File(realResPath + "/" + fileName + ".mp3");</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>if</strong>(newRecites.size() &gt; 1){</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>try</strong>&nbsp;{</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<em>combine</em>(file.getPath(), newRecites);</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;<strong>catch</strong>&nbsp;(Exception e) {</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.<strong><em>err</em></strong>.println(e.getMessage());</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p align="left">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.<strong><em>err</em></strong>.println("音频大小:" + file.length()/1024 + "KB");</p>
<p align="left">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //信息保存数据库表</p>
<p align="left">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; Record record =&nbsp;<strong>new</strong>&nbsp;Record();</p>
<p align="left">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; record.set("id", ID.<em>get</em>());</p>
<p align="left">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; record.set("contentname", contentName);//诗词名称</p>
<p align="left">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; record.set("contentid", contentId);//诗词ID</p>
<p align="left">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; record.set("fansid", fansId);//粉丝ID</p>
<p align="left">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; record.set("path", fileStore + recitePath + "/" + contentId + "/" + fansId + "/" + fileName + ".mp3");//吟诵录音路径</p>
<p align="left">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; record.set("uploaddate",&nbsp;<strong>new</strong>&nbsp;Timestamp(<strong>new</strong>&nbsp;java.util.Date().getTime()));//吟诵时间</p>
<p align="left">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; api.save(getTableName(), record);</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>long</strong>&nbsp;time2 = System.<em>currentTimeMillis</em>();</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.<strong><em>out</em></strong>.println("上传时间:" + (time2 - time1)/1000 + "s");</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 删除临时文件*/</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>for</strong>(<strong>int</strong>&nbsp;i = 0; i &lt; tempRecites.size(); i++){</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; File tempFile =&nbsp;<strong>new</strong>&nbsp;File(tempRecites.get(i));</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>if</strong>(tempFile.exists()){</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.<strong><em>out</em></strong>.println("删除AMR临时文件结果[" + tempRecites.get(i) + ":" + tempFile.delete() + "]");</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>if</strong>(tempRecites.size() &gt; 1){</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tempFile =&nbsp;<strong>new</strong>&nbsp;File(newRecites.get(i));</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>if</strong>(tempFile.exists()){</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.<strong><em>out</em></strong>.println("删除MP3临时文件结果[" + newRecites.get(i) + ":" + tempFile.delete() + "]");</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p align="left">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<strong>else</strong>{</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dto.<em>getResult</em>().setSuccessStatus("请完善个人信息");</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>return</strong>&nbsp;Dto.<em>getResult</em>();</p>
<p align="left">&nbsp;&nbsp; }</p>
<p align="left">&nbsp;&nbsp;</p>
<p align="left">&nbsp;&nbsp; /*将多个MP3文件合并*/</p>
<p align="left">&nbsp;&nbsp;&nbsp;<strong>private</strong>&nbsp;<strong>static</strong>&nbsp;<strong>boolean</strong>&nbsp;combine(String outFile, List&lt;String&gt; inFiles)&nbsp;<strong>throws</strong>&nbsp;Exception{</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; File[] files =&nbsp;<strong>new</strong>&nbsp;File;</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>for</strong>(<strong>int</strong>&nbsp;i = 0; i &lt; files.length; i++){</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; files =&nbsp;<strong>new</strong>&nbsp;File(inFiles.get(i));</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FileInputStream fis =&nbsp;<strong>null</strong>;</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FileOutputStream fos =&nbsp;<strong>new</strong>&nbsp;FileOutputStream(outFile,&nbsp;<strong>true</strong>);//合并其实就是文件的续写,写成true</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>for</strong>&nbsp;(<strong>int</strong>&nbsp;i = 0; i &lt; files.length; i++){</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fis =&nbsp;<strong>new</strong>&nbsp;FileInputStream(files);</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>int</strong>&nbsp;len = 0;</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>for</strong>&nbsp;(<strong>byte</strong>[] buf =&nbsp;<strong>new</strong>&nbsp;<strong>byte</strong>; (len = fis.read(buf)) != -1;){</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fos.write(buf, 0, len);</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fis.close();</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fos.close();</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>return</strong>&nbsp;<strong>true</strong>;</p>
<pre>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</pre>
<pre>&nbsp;</pre>
<pre>/* 下载录音接口 */</pre>
<pre><code class="hljs css"><span class="hljs-selector-tag">wx<span class="hljs-selector-class">.downloadVoice({</span></span></code><br>
<code class="hljs less"><span class="hljs-attribute">serverId: <span class="hljs-string">'', <span class="hljs-comment">// </span></span></span></code><code class="hljs">需要下载的音频的服务器端ID,由uploadVoice接口获得</code><br>
<code class="hljs less"><span class="hljs-attribute">isShowProgressTips: <span class="hljs-number">1, <span class="hljs-comment">// </span></span></span></code><code class="hljs">默认为1,显示进度提示</code><br>
<code class="hljs javascript">success: <span class="hljs-function"><span class="hljs-keyword">function (<span class="hljs-params">res) {</span></span></span></code><br>
<code class="hljs javascript"><span class="hljs-keyword">var localId = res.localId; <span class="hljs-comment">// </span></span></code><code class="hljs">返回音频的本地ID</code><br>
<code class="hljs">}</code><br>
<code class="hljs">});</code></pre>
<pre>/* 此下载接口只是返回微信服务器端的文件<code class="hljs erlang-repl">localId ,然后调用播放接口读取localId ,但是微信服务器端的录音文件只保留<span class="hljs-number">3天,请知晓!</span></code>*/</pre><br><br>
来源:https://www.cnblogs.com/onesea/p/13291820.html
頁: [1]
查看完整版本: 微信公众号开发经验总结