微信服務接入教程文檔
文章目錄 微信服務接入教程文檔 微信開發技術文檔官網 注冊成為微信開發者 natapp下載,使用 后臺構建 后臺配置微信推送消息服務器 接受消息推送 操作對象,獲取請求類型(比如文本、圖片等)進行相應的處理,進行數據的變更處理 數據返回 自定義菜單 訂閱消息事件,返回創建自定義菜單json數據 用戶點擊自定義菜單事件 && 用戶點擊自定義鏈接事件
前言
本人不喜歡網絡上的各種文章,上來就把完整代碼放臉上,讓你琢磨不懂,這篇文章會盡量讓你不要出現這種情況。
微信開發技術文檔官網
https://mp.weixin.qq.com/
注冊成為微信開發者
普通用戶建議注冊訂閱號 文中后半部分的菜單配置等,需要其權限,可以用公司的公眾號來實驗 打開基本配置菜單,成為開發者
配置接受推送消息服務器
URL必須有域名,且必須在外網可以訪問到,因此我們需要natapp 來進行內網穿透 ,簡單點說就是把外網的IP映射到你當前的內網下,外網ip接受的內容會被轉到你映射的內網ip:端口下。 Token 隨便填 key隨便填 建議選擇明文模式 此時提交之后由于后端沒有對應的服務,所有無法成功,待下文可以開始提交的時候建議大家再進行提交
natapp下載,使用
官網:https://natapp.cn
點擊客戶端下載即可,先不用急著點教程/文檔,里面并沒有我們當前想要的 選擇系統對應的版本,這里使用的是win64,之后點擊箭頭指向的地方進行快速的安裝使用教程! 安裝教程里面第一步是需要注冊 購買隧道是有免費的和付費的,但是免費的需要進行支付寶實名認證,乍一看似乎能白嫖,但是我本人使用的時候,一到支付寶登陸的時候就顯示我支付寶賬號有危險,要我改密碼,死活上不去,無奈只好購買付費的。
我也對客服進行了郵箱反饋,但是只是建議我進行付費的購買,并沒有說排查錯誤什么的! 2. 隧道協議選擇Web即可 二級域名如果沒有先選擇不需要,如果你有自然更好。 本地端口填寫一個即可,本人這里選擇的80 帶寬&流量選擇小流量即可 購買完之后進行注冊域名 4. 選擇一個可用于微信開發的即可 之后再回到我的隧道里面進行綁定域名即可
后臺構建
構建之前,請大家大致的看微信開發平臺文檔一遍,比避免有些地方不懂 (強烈告誡至少看一遍) 本教程只需要大家看以上四個大章即可 本教程以大家都有一個springboot的基本啟動程序,為前提(能啟動,controller能返回個hello,world即可) 先給出本教程需要的全部maven 包 —jdk 1.8 開發工具 idea
< dependency> < groupId> org.springframework.boot
</ groupId> < artifactId> spring-boot-devtools
</ artifactId> < optional> true
</ optional> < scope> true
</ scope> </ dependency> < dependency> < groupId> org.dom4j
</ groupId> < artifactId> dom4j
</ artifactId> < version> 2.1.1
</ version> </ dependency> < dependency> < groupId> com.thoughtworks.xstream
</ groupId> < artifactId> xstream
</ artifactId> < version> 1.4.11.1
</ version> </ dependency> < dependency> < groupId> org.apache.commons
</ groupId> < artifactId> commons-lang3
</ artifactId> < version> 3.4
</ version> </ dependency> < dependency> < groupId> com.alibaba
</ groupId> < artifactId> fastjson
</ artifactId> < version> 1.2.62
</ version> </ dependency> < dependency> < groupId> org.projectlombok
</ groupId> < artifactId> lombok
</ artifactId> < optional> true
</ optional> </ dependency> < dependency> < groupId> org.springframework.boot
</ groupId> < artifactId> spring-boot-starter-test
</ artifactId> < scope> test
</ scope> </ dependency> < dependency> < groupId> org.springframework.boot
</ groupId> < artifactId> spring-boot-starter-web
</ artifactId> </ dependency> < dependency> < groupId> org.springframework.boot
</ groupId> < artifactId> spring-boot-starter-web-services
</ artifactId> </ dependency> < dependency> < groupId> org.springframework.boot
</ groupId> < artifactId> spring-boot-starter-websocket
</ artifactId> </ dependency> < dependency> < groupId> org.mybatis.spring.boot
</ groupId> < artifactId> mybatis-spring-boot-starter
</ artifactId> < version> 2.1.4
</ version> </ dependency> < dependency> < groupId> org.springframework.session
</ groupId> < artifactId> spring-session-core
</ artifactId> </ dependency>
后臺配置微信推送消息服務器
import org
. springframework
. web
. bind
. annotation
. GetMapping
;
import org
. springframework
. web
. bind
. annotation
. PostMapping
;
import org
. springframework
. web
. bind
. annotation
. RequestMapping
;
import org
. springframework
. web
. bind
. annotation
. RestController
;
import java
. util
. List
;
import java
. util
. Map
;
import javax
. servlet
. http
. HttpServletRequest
;
import javax
. servlet
. http
. HttpServletResponse
;
import lombok
. extern
. slf4j
. Slf4j
;
import org
. springframework
. beans
. factory
. annotation
. Autowired
;
import java
. io
. IOException
;
import com
. alibaba
. fastjson
. JSON
;
@Slf4j
@RestController
@RequestMapping ( "/springsecurity/test" )
public class HelloController { @GetMapping ( "/weixin" ) public String
weixin ( HttpServletRequest request
, HttpServletResponse response
) { return null
; }
}
先定義這樣的一個類,加上一個接受微信推送消息服務器接口匹配的方法(暫時不需要定義其他類)
按要求填寫這些輸入框 建議大家先點擊提交,查看是否已經進入此方法 完整代碼:
@GetMapping ( "/weixin" ) public String
weixin ( HttpServletRequest request
, HttpServletResponse response
) { String echostr
= null
; try { log
. info ( "請求已到達,開始校驗token" ) ; if ( StringUtils
. isNotBlank ( request
. getParameter ( "signature" ) ) ) { String signature
= request
. getParameter ( "signature" ) ; String timestamp
= request
. getParameter ( "timestamp" ) ; String nonce
= request
. getParameter ( "nonce" ) ; echostr
= request
. getParameter ( "echostr" ) ; log
. info ( "signature[{}], timestamp[{}], nonce[{}], echostr[{}]" , signature
, timestamp
, nonce
, echostr
) ; if ( SignUtil
. checkSignature ( signature
, timestamp
, nonce
) ) { log
. info ( "數據源為微信后臺,將echostr[{}]返回!" , echostr
) ; response
. getOutputStream ( ) . println ( echostr
) ; return echostr
; } } } catch ( IOException e
) { log
. error ( "校驗出錯" ) ; e
. printStackTrace ( ) ; } return echostr
;
}
接受消息推送
接受信息推送這里需要進行新加類:
新建utils package(包) 在utils包下新建messagehandle 包 在messagehandle包下,新建ParseXml 類內容為:
import java
. io
. InputStream
;
import java
. util
. HashMap
;
import java
. util
. List
;
import java
. util
. Map
;
import javax
. servlet
. http
. HttpServletRequest
;
import lombok
. extern
. slf4j
. Slf4j
;
import org
. dom4j
. Document
;
import org
. dom4j
. DocumentHelper
;
import org
. dom4j
. Element
;
import org
. dom4j
. io
. SAXReader
;
@Slf4j
public class ParseXml { public static Map
< String, String> parseXml ( HttpServletRequest request
) throws Exception
{ Map
< String, String> map
= new HashMap < String, String> ( ) ; InputStream inputStream
= request
. getInputStream ( ) ; SAXReader reader
= new SAXReader ( ) ; Document document
= reader
. read ( inputStream
) ; Element root
= document
. getRootElement ( ) ; List
< Element> elementList
= root
. elements ( ) ; for ( Element e
: elementList
) { map
. put ( e
. getName ( ) , e
. getText ( ) ) ; log
. info ( "name:" + e
. getName ( ) + " value:" + map
. get ( e
. getName ( ) ) ) ; } inputStream
. close ( ) ; return map
; }
}
然后在上文的HelloController 中新建方法如下:
@PostMapping ( "/weixin" ) public void message ( HttpServletRequest request
, HttpServletResponse response
) { try { Map
< String, String> paramMap
= ParseXml
. parseXml ( request
) ; log
. info ( JSON
. toJSONString ( paramMap
) ) ; } catch ( Exception e
) { e
. printStackTrace ( ) ; } }
附圖供大家看! 根據官方文檔可知: 基本每一個消息都會有一個MsgType來確定是什么類型的,所以我們這里要獲取它:
Map
< String, String> paramMap
= ParseXml
. parseXml ( request
) ;
String type
= paramMap
. get ( "MsgType" ) ;
看被動回復用戶消息 章節文檔,我們最后是需要返回xml形式的給微信服務器。 所以我們的大體步驟是:
獲取微信服務器的請求,解析xml為對象 操作對象,獲取請求類型(比如文本、圖片等)進行相應的處理,進行數據的變更 把對象變為xml形式返回
操作對象,獲取請求類型(比如文本、圖片等)進行相應的處理,進行數據的變更處理
操作對象
首先每個返回的事件類型有一個自己的返回格式,但是都有幾個共同的字段,所以我們可以先定一個實體基類,然后其他的各種格式來繼承它,獲取共同的屬性(這里的思路出自網絡代碼,但是網絡代碼完整性,實用性比較低,擴展性也不行所以我進行了大幅的修改 )。 實體基類BaseMessage 代碼如下(請自行新建包來進行放置,建議不要和utils放置在一起):
import lombok
. Data
;
@Data
public class BaseMessage { private String ToUserName
; private String FromUserName
; private Long CreateTime
; private String MsgType
; private Long MsgId
; }
@Data
public class TextMessage extends BaseMessage { private String Content
; public String
toString ( ) { return super . toString ( ) + "[TextMessage]:" + " Content:" + this . Content
; }
}
@Data
public class ImageMessage extends BaseMessage { private String PicUrl
; private String MediaId
; public String
toString ( ) { return super . toString ( ) + "[ImageMessage]:" + " PriUrl:" + this . PicUrl
+ " MediaId:" + this . MediaId
; }
}
@Data
public class VoiceMessage extends BaseMessage { private String MediaId
; private String Format
; public String
toString ( ) { return super . toString ( ) + "[VoiceMessage]:" + " MediaId:" + this . MediaId
+ " Format:" + this . Format
; }
}
@Data
public class VideoMessage extends BaseMessage { private String MediaId
; private String ThumbMediaId
; public String
toString ( ) { return super . toString ( ) + "[VideoMessage]:" + " MediaId:" + this . MediaId
+ " ThumbMediaId:" + this . ThumbMediaId
; } }
暫時不提供小視頻處理類,請自行添加 地理位置處理類LocationMessage :
@Data
public class LocationMessage extends BaseMessage { private String Location_X
; private String Location_Y
; private String Scale
; private String Label
; public String
toString ( ) { return super . toString ( ) + "[LocationMessage]:" + " Location_X:" + this . Location_X
+ " Location_Y:" + this . Location_Y
+ " Scale:" + this . Scale
+ " Lable:" + this . Label
; }
}
@Data
public class LinkMessage extends BaseMessage { private String Title
; private String Description
; private String Url
; public String
toString ( ) { return super . toString ( ) + "[LinkMessage]:" + " Title:" + this . Title
+ " Description:" + this . Description
+ " Url:" + this . Url
; }
}
@Slf4j
public class MessageCode { public static final String REQ_MESSAGE_TYPE_TEXT
= "text" ; public static final String REQ_MESSAGE_TYPE_IMAGE
= "image" ; public static final String REQ_MESSAGE_TYPE_VOICE
= "voice" ; public static final String REQ_MESSAGE_TYPE_VIDEO
= "video" ; public static final String REQ_MESSAGE_TYPE_SHORTVIDEO
= "shortvideo" ; public static final String REQ_MESSAGE_TYPE_LOCATION
= "location" ; public static final String REQ_MESSAGE_TYPE_LINK
= "link" ; public static final String REQ_MESSAGE_TYPE_EVENT
= "event" ; public static final String EVENT_TYPE_SUBSCRIBE
= "subscribe" ; public static final String EVENT_TYPE_UNSUBSCRIBE
= "unsubscribe" ; public static final String EVENT_TYPE_CLICK
= "CLICK" ; public static final String EVENT_TYPE_SCAN
= "SCAN" ; public static final String EVENT_TYPE_LOCATION
= "LOCATION" ; public static final String EVENT_TYPE_VIEW
= "VIEW" ; }
此時我們就可以在helloController里面進行事件類型的判斷了,代碼如下:
try { Map
< String, String> paramMap
= ParseXml
. parseXml ( request
) ; String type
= paramMap
. get ( "MsgType" ) ; if ( MessageCode
. REQ_MESSAGE_TYPE_TEXT
. equals ( type
) ) { log
. warn ( "進入消息事件!" ) ; } } catch ( Exception e
) { e
. printStackTrace ( ) ; } }
這里我們已經進行成功的判斷了,那么接下來就需要根據傳來的參數對象,進行返回參數xml的構建 utils 包新建msghandle 包msghandle包下,新建MsgHandle ,MsgHelpClass 2個類 MsgHandle : 處理消息的分發,因為每一個消息類型的返回值,各有個的特點 MsgHelpClass:每一個消息類型的返回值,雖然各有各的特點,但是依然有共同的地方,用于輔助MsgHandle 類 MsgHandle 代碼如下:
import java
. util
. Date
;
import java
. util
. Map
;
import lombok
. Data
;
import lombok
. extern
. slf4j
. Slf4j
;
import com
. alibaba
. fastjson
. JSONObject
;
@Data
@Slf4j
public class MsgHandle { private String FromUserName
; private String ToUserName
; private long CreateTime
; private String MsgType
; private long MsgId
; }
此類有4個共同的屬性,下面的代碼直接加在此類中即可,分開只是為了更好理解,避免第一眼看上去太多,難以理解
public String
processMessage ( Map
< String, String> map
) throws InstantiationException
, IllegalAccessException
{ this . FromUserName
= map
. get ( "ToUserName" ) ; this . ToUserName
= map
. get ( "FromUserName" ) ; this . MsgType
= map
. get ( "MsgType" ) ; this . CreateTime
= Long
. valueOf ( map
. get ( "CreateTime" ) ) ; this . MsgId
= Long
. valueOf ( map
. get ( "MsgId" ) ) ; BaseMessage baseMessage
= null
; if ( this . MsgType
. equals ( MessageCode
. REQ_MESSAGE_TYPE_TEXT
) ) { log
. info ( "這是文本消息!" ) ; baseMessage
= MsgHelpClass
. setAttribute ( this , TextMessage
. class ) ; TextMessage textMessage
= ( TextMessage
) baseMessage
; textMessage
. setContent ( "這里是測試回復" ) ; return ParseXml
. textMessageToXml ( textMessage
) ; } if ( this . MsgType
. equals ( MessageCode
. REQ_MESSAGE_TYPE_IMAGE
) ) { log
. info ( "這是圖片消息!" ) ; } if ( this . MsgType
. equals ( MessageCode
. REQ_MESSAGE_TYPE_LINK
) ) { log
. info ( "這是鏈接消息!" ) ; } if ( this . MsgType
. equals ( MessageCode
. REQ_MESSAGE_TYPE_LOCATION
) ) { log
. info ( "這是位置消息!" ) ; } if ( this . MsgType
. equals ( MessageCode
. REQ_MESSAGE_TYPE_VIDEO
) ) { log
. info ( "這是視頻消息!" ) ; } if ( this . MsgType
. equals ( MessageCode
. REQ_MESSAGE_TYPE_VOICE
) ) { log
. info ( "這是語音消息!" ) ; } return "" ; }
import java
. util
. Date
;
import lombok
. extern
. slf4j
. Slf4j
;
@Slf4j
public class MsgHelpClass { public static < E
extends BaseMessage > E
setAttribute ( MsgHandle msgHandle
, Class
< E> eClass
) throws IllegalAccessException
, InstantiationException
{ BaseMessage baseMessage
= eClass
. newInstance ( ) ; baseMessage
. setCreateTime ( new Date ( ) . getTime ( ) ) ; baseMessage
. setFromUserName ( msgHandle
. getFromUserName ( ) ) ; baseMessage
. setMsgId ( msgHandle
. getMsgId ( ) ) ; baseMessage
. setToUserName ( msgHandle
. getToUserName ( ) ) ; baseMessage
. setMsgType ( msgHandle
. getMsgType ( ) ) ; log
. warn ( "MsgHelpClass-setAttribute方法返回值如下:\n" + baseMessage
. toString ( ) ) ; return ( E
) baseMessage
; }
}
上面兩個類就是處理分發的類,但是上面我們也提到了一個把數據處理返回為xml,ParseXml類的靜態方法 此方法在ParseXml類中為:
public static String
textMessageToXml ( TextMessage textMessage
) { log
. warn ( "ParseXml類TextMressage對象值如下:\n" + textMessage
. toString ( ) ) ; return XmlHandleFun ( textMessage
) ; }
public static String
imageMessageToXml ( ImageMessage imageMessage
) { log
. warn ( "ParseXml類ImageMessage對象值如下:\n" + imageMessage
. toString ( ) ) ; return "" ; }
public static String
voiceMessageToXml ( VoiceMessage voiceMessage
) { log
. warn ( "ParseXml類VoiceMessage對象值如下:\n" + voiceMessage
. toString ( ) ) ; return "" ;
}
public static String
videoMessageToXml ( VideoMessage videoMessage
) { log
. warn ( "ParseXml類VideoMessage對象值如下:\n" + videoMessage
. toString ( ) ) ; return "" ;
}
private static < T
extends BaseMessage > String
XmlHandleFun ( T object
) { Document dou
= null
; boolean isif
= true ; try { dou
= DocumentHelper
. createDocument ( ) ; Element root
= dou
. addElement ( "xml" ) ; Element emp
= root
. addElement ( "ToUserName" ) . addText ( "<![CDATA[" + object
. getToUserName ( ) + "]]>" ) ; Element emp1
= root
. addElement ( "FromUserName" ) . addText ( "<![CDATA[" + object
. getFromUserName ( ) + "]]>" ) ; Element emp2
= root
. addElement ( "CreateTime" ) . addText ( String
. valueOf ( object
. getCreateTime ( ) ) ) ; Element emp3
= root
. addElement ( "MsgType" ) . addText ( "<![CDATA[" + object
. getMsgType ( ) + "]]>" ) ; if ( object
instanceof TextMessage && isif
) { TextMessage textMessage
= ( TextMessage
) object
; Element emp4
= root
. addElement ( "Content" ) . addText ( "<![CDATA[" + textMessage
. getContent ( ) + "]]>" ) ; isif
= false ; } if ( object
instanceof ImageMessage && isif
) { ImageMessage imageMessage
= ( ImageMessage
) object
; Element emp4
= root
. addElement ( "Image" ) ; emp4
. addElement ( "MediaId" ) . addText ( "<![CDATA[" + imageMessage
. getMediaId ( ) + "]]>" ) ; isif
= false ; } if ( object
instanceof VoiceMessage && isif
) { VoiceMessage voiceMessage
= ( VoiceMessage
) object
; Element emp4
= root
. addElement ( "Voice" ) ; emp4
. addElement ( "MediaId" ) . addText ( "<![CDATA[" + voiceMessage
. getMediaId ( ) + "]]>" ) ; isif
= false ; } if ( object
instanceof VideoMessage && isif
) { VideoMessage videoMessage
= ( VideoMessage
) object
; Element emp4
= root
. addElement ( "Video" ) ; emp4
. addElement ( "MediaId" ) . addText ( "<![CDATA[" + videoMessage
. getMediaId ( ) + "]]>" ) ; emp4
. addElement ( "Title" ) . addText ( "<![CDATA[" + videoMessage
. getTitle ( ) + "]]>" ) ; emp4
. addElement ( "Description" ) . addText ( "<![CDATA[" + videoMessage
. getDescription ( ) + "]]>" ) ; isif
= false ; } } catch ( Exception e
) { log
. error ( "出現錯誤!XmlHandleFun" ) ; e
. printStackTrace ( ) ; } int count
= "encoding=\"UTF-8\"?" . length ( ) ; String result
= dou
. asXML ( ) ; result
= result
. substring ( result
. indexOf ( "encoding=\"UTF-8\"?" ) + count
+ 1 ) ; return result
. trim ( ) ;
}
數據返回
以上配置完成之后我們就可以進行HelloController剩下的部分了
if ( MessageCode
. REQ_MESSAGE_TYPE_TEXT
. equals ( type
) ) { MsgHandle msgHandle
= new MsgHandle ( ) ; ResultRes
. response ( msgHandle
. processMessage ( paramMap
) , response
) ;
}
看到這里你可以會說這ResultRes.response 又是個什么東西,都配置怎么多了怎么還有,我答應你們這真的是最后一個了,別罵了別罵了! 在utilsl 包新建reresult 包(我承認我這個名字不規范,不合適 …) 在reresult 包下新建ResultRes 類 ResultRes類代碼如下:
import java
. io
. IOException
;
import java
. io
. PrintWriter
;
import java
. io
. StringReader
;
import java
. io
. StringWriter
;
import javax
. servlet
. http
. HttpServletResponse
;
import lombok
. extern
. slf4j
. Slf4j
;
import org
. apache
. commons
. lang3
. StringEscapeUtils
;
import org
. dom4j
. Document
;
import org
. dom4j
. io
. OutputFormat
;
import org
. dom4j
. io
. SAXReader
;
import org
. dom4j
. io
. XMLWriter
;
import org
. thymeleaf
. util
. StringUtils
;
@Slf4j
public class reresult { public static void response ( String data
, HttpServletResponse response
) { data
= StringEscapeUtils
. unescapeXml ( data
) ; log
. info ( data
) ; if ( StringUtils
. isEmpty ( data
) ) { log
. error ( "數據為空!" ) ; return ; } try { response
. setCharacterEncoding ( "UTF-8" ) ; PrintWriter printWriter
= response
. getWriter ( ) ; printWriter
. print ( data
) ; printWriter
. close ( ) ; } catch ( IOException io
) { log
. error ( io
. getMessage ( ) ) ; io
. printStackTrace ( ) ; } } public static String
format ( String str
) throws Exception
{ SAXReader reader
= new SAXReader ( ) ; StringReader in
= new StringReader ( str
) ; Document doc
= reader
. read ( in
) ; OutputFormat formater
= OutputFormat
. createPrettyPrint ( ) ; formater
. setEncoding ( "utf-8" ) ; StringWriter out
= new StringWriter ( ) ; XMLWriter writer
= new XMLWriter ( out
, formater
) ; writer
. write ( doc
) ; writer
. close ( ) ; return out
. toString ( ) ; }
}
到這里正常情況下,已經可以對用戶輸入的普通文本消息進行自動回復了!
自定義菜單
在HelloController 類**message(get)**方法里,String type = paramMap.get("MsgType");下加入 String event = null;
if ( paramMap. get ( "Event" ) != null) {
event = paramMap. get ( "Event" ) ;
}
獲取事件字符串之后,我們需要進行匹配,來進入相應的處理
訂閱消息事件,返回創建自定義菜單json數據
if ( MessageCode
. EVENT_TYPE_SUBSCRIBE
. equals ( event
) ) { String token
= GetBodyMessage
. getAcces_Token ( "wx59fa3e56c3448f46" ) ; String body
= GetBodyMessage
. getBodyJson ( ) ; String s
= httpsRequest
. httpsRequests ( "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=" + token
, "POST" , body
) ; System
. err
. println ( s
) ;
}
我們需要新建GetBodyMessage 類,代碼如下:
import com
. alibaba
. fastjson
. JSON
;
import com
. alibaba
. fastjson
. JSONArray
;
import java
. util
. HashMap
;
import java
. util
. Map
;
import lombok
. extern
. slf4j
. Slf4j
; @Slf4j
public class GetBodyMessage { public static String
getBodyJson ( ) { Map
< String, Object> mapbutton
= new HashMap < > ( ) ; Map
< String, Object> mapbody
= new HashMap < > ( ) ; Map
[ ] strargs
= new Map [ 1 ] ; mapbody
. put ( "type" , "view" ) ; mapbody
. put ( "name" , "成績查詢!" ) ; mapbody
. put ( "key" , "message" ) ; mapbody
. put ( "url" , "http://www.baidu.com" ) ; strargs
[ 0 ] = mapbody
; mapbutton
. put ( "button" , strargs
) ; String body
= JSON
. toJSONString ( mapbutton
) ; log
. error ( body
) ; return body
; } public static String
getAcces_Token ( String appid
) { String token
= "grant_type=client_credential&appid=" + appid
+ "&secret=xxxxxxxxxxxxxxxxxxxxxx" ; String result
= httpRequest
. httpRequests ( "https://api.weixin.qq.com/cgi-bin/token" , "GET" , token
) ; Map map
= JSONArray
. parseObject ( result
) ; System
. out
. println ( map
. get ( "access_token" ) ) ; return ( String
) map
. get ( "access_token" ) ; } }
getBodyJson 方法返回的json結構如下:** 官網token獲取請求實例如下: 創建httpRequest 類和httpsRequest 類,代碼如下(代碼源自網絡): 網址:鏈接
import java
. io
. BufferedReader
;
import java
. io
. InputStream
;
import java
. io
. InputStreamReader
;
import java
. io
. OutputStream
;
import java
. net
. HttpURLConnection
;
import java
. net
. URL
; public class httpRequest { public static String
httpRequests ( String requestUrl
, String requestMethod
, String outputStr
) { StringBuffer buffer
= null
; try { URL url
= new URL ( requestUrl
) ; HttpURLConnection conn
= ( HttpURLConnection
) url
. openConnection ( ) ; conn
. setDoOutput ( true ) ; conn
. setDoInput ( true ) ; conn
. setRequestMethod ( requestMethod
) ; conn
. connect ( ) ; if ( null
!= outputStr
) { OutputStream os
= conn
. getOutputStream ( ) ; os
. write ( outputStr
. getBytes ( "utf-8" ) ) ; os
. close ( ) ; } InputStream is
= conn
. getInputStream ( ) ; InputStreamReader isr
= new InputStreamReader ( is
, "utf-8" ) ; BufferedReader br
= new BufferedReader ( isr
) ; buffer
= new StringBuffer ( ) ; String line
= null
; while ( ( line
= br
. readLine ( ) ) != null
) { buffer
. append ( line
) ; } } catch ( Exception e
) { e
. printStackTrace ( ) ; } return buffer
. toString ( ) ; } }
import java
. io
. BufferedReader
;
import java
. io
. InputStream
;
import java
. io
. InputStreamReader
;
import java
. io
. OutputStream
;
import java
. net
. URL
;
import javax
. net
. ssl
. HttpsURLConnection
;
import javax
. net
. ssl
. SSLContext
;
import javax
. net
. ssl
. SSLSocketFactory
;
import javax
. net
. ssl
. TrustManager
; public class httpsRequest { public static String
httpsRequests ( String requestUrl
, String requestMethod
, String outputStr
) { StringBuffer buffer
= null
; try { SSLContext sslContext
= SSLContext
. getInstance ( "SSL" ) ; TrustManager
[ ] tm
= { new MyX509TrustManager ( ) } ; sslContext
. init ( null
, tm
, new java. security. SecureRandom ( ) ) ; ; SSLSocketFactory ssf
= sslContext
. getSocketFactory ( ) ; URL url
= new URL ( requestUrl
) ; HttpsURLConnection conn
= ( HttpsURLConnection
) url
. openConnection ( ) ; conn
. setDoOutput ( true ) ; conn
. setDoInput ( true ) ; conn
. setUseCaches ( false ) ; conn
. setRequestMethod ( requestMethod
) ; conn
. setSSLSocketFactory ( ssf
) ; conn
. connect ( ) ; if ( null
!= outputStr
) { OutputStream os
= conn
. getOutputStream ( ) ; os
. write ( outputStr
. getBytes ( "utf-8" ) ) ; os
. close ( ) ; } InputStream is
= conn
. getInputStream ( ) ; InputStreamReader isr
= new InputStreamReader ( is
, "utf-8" ) ; BufferedReader br
= new BufferedReader ( isr
) ; buffer
= new StringBuffer ( ) ; String line
= null
; while ( ( line
= br
. readLine ( ) ) != null
) { buffer
. append ( line
) ; } } catch ( Exception e
) { e
. printStackTrace ( ) ; } return buffer
. toString ( ) ; }
}
https請求如果報錯,可能還需要導入服務端的安全證書步驟如下:
例:點擊下圖中紅線指向的小鎖(谷歌瀏覽器) 點擊證書 一行 點擊詳細信息 點擊復制到文件 先下一步 然后來到下圖頁面 選擇DER編碼二進制X.509 后點擊下一步 隨意選擇一個文件名和文件路徑。 打開cmd進入剛剛創建的文件路徑,命令行輸入Keytool -import -alias 文件名 -file 文件名.cer -keystore cacerts 回車之后會讓輸入口令,一般口令默認是changeit 。輸入密鑰時并不會顯示在界面上。 輸入正確之后會讓你選擇是否信任該證書,輸入y,會提示導入成功!
用戶點擊自定義菜單事件 && 用戶點擊自定義鏈接事件
由于上文新建的菜單里面包括了用戶點擊自定義菜單事件 && 用戶點擊自定義鏈接事件 這兩個,所以我們只需要添加如下代碼,觀察到用戶的操作即可:
if ( MessageCode
. EVENT_TYPE_CLICK
. equals ( event
) ) { String eventKey
= "message" ; log
. warn ( JSON
. toJSONString ( paramMap
) ) ; if ( eventKey
. equals ( paramMap
. get ( "EventKey" ) ) ) { log
. warn ( "進入成績查詢點擊事件,開始處理并返回!" ) ; }
}
if ( MessageCode
. EVENT_TYPE_VIEW
. equals ( event
) ) { log
. warn ( "進入百度頁面跳轉事件!" ) ;
}
總結
以上是生活随笔 為你收集整理的全网最全java Springboot对接微信公众号开发平台(可能是最全)! 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。