1.開通開發者帳號
注意:開通微信公衆號必須是“個體戶”或“企業性質”。
- 通過個人微信號掃碼登錄並開通微信服務號
- 開通成功後,此時的公衆號是【未認證狀態】
- 未認證與認證的公衆號的主要區別
在【開發—接口權限】菜單中,可查看到使用各接口的權限。
我們要進行二次開發,不申請開通“開發者帳號”,你的公衆號就只是個擺設。 - 認證服務號並開通開發者帳號
服務號的認證:無論是“個體戶”還是“企業”,最好是首先將公司的對公帳戶開通好。
因爲如果你的系統還要申請微信支付功能的話,開通了對公帳戶,後面的操作會簡單很多。
- 服務號認證成功後,我們會看到接口權限基本上全部都可使用了
2.程序與公衆號聯合調試
2.1 準備聯調的服務器
注意:微信公衆號與服務器交互時,只能訪問你服務器的 80端口
雲服務器
雲服務器聯調,則在調試中,可能要多打些log日誌來調試
2.2 配置公衆平臺
2.2.1 菜單: 開發-- 基本配置
```
IP白名單:公衆號允許指定外網訪問的IP地址(官方要求必須配置)
注意:如果你用的是雲服務器,直接將服務器的公網IP配置此處即可。
2.2.2 服務器配置(重點)
URL: 公衆號默認將訪問的服務器的地址。
注意:這裏是公衆號與後臺連接的總入口
Token:類似票據,可自行設置並系統自行保留
EncodingAESKey:隨機生成即可,這個值應該是給公衆號來用的,系統聯調時,不會用到該值。
在配置上面的URL時,必須先確保你的服務器已成功啓動
如果你服務器連接的URL配置錯誤,【提交】按鈕就無法成功點擊,公衆平臺會報錯。
2.2.3 服務器後臺核心代碼
注:這裏以springboot工程爲例
因爲公衆號訪問我們服務器,都走的統一的一個接口,就是我們上面配置的URL,所以在項目中,我們可以創建一個Servlet來專門接收和處理公衆號的請求。
具體代碼步驟如下
- 在啓動類上添加註解
@SpringBootApplication
@ServletComponentScan
public class WXApplication {
public static void main(String[] args) {
SpringApplication.run(WXApplication.class, args);
}
}
- 創建一個servlet並編寫連接所需的核心代碼:WechatCallbackApi.java
@WebServlet("/wechat")
public class WechatCallbackApi extends HttpServlet {
@Autowired
private WeixinGZHService weixinGZHService;
@Override//不添加此方法,直接注入service會報空指針
public void init(ServletConfig config) {
try {
SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, config.getServletContext());
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
doGet(req, resp);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
try {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
//進行簽名校驗
weixinGZHService.validateWeixinServer(request, response);
//處理菜單響應操作
/*
<xml>
<ToUserName><![CDATA[gh_409cf2d2d396]]></ToUserName>
<FromUserName><![CDATA[o64up1E1tBRXaLhRne9Dm9rrcp5g]]></FromUserName>
<CreateTime>1558324778</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[CLICK]]></Event>
<EventKey><![CDATA[V1001_GET_ORDER]]></EventKey>
</xml>
*/
String message = IOUtils.toString(request.getInputStream(), "utf-8");
//先轉成map對象
Map<String, String> xmlToMap = WeChatXMLUtils.xmlToMap(message);
//在調用模板消息時,有個非常坑的地方,就是微信公衆號服務器每向微信用戶發送消息後,必須要有迴應,無迴應微信那邊則會報異常
if (xmlToMap == null || StringUtils.isBlank(xmlToMap.get("EventKey"))) {
return;
}
WeixinResult weixinResult = WeChatXMLUtils.xmlToBean(message, WeixinResult.class);
//發送模板消息時,也會向公衆號返回一條消息,但此消息的數據類型與 click事件的返回類型不同。需要判斷eventKey的值
if (weixinResult != null && StringUtils.isNotBlank(weixinResult.getEventKey())) {
switch (weixinResult.getEventKey()) {
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
- 實體類WeixinResult .java
/*
<xml>
<ToUserName><![CDATA[gh_409cf2d2d396]]></ToUserName>
<FromUserName><![CDATA[o64up1E1tBRXaLhRne9Dm9rrcp5g]]></FromUserName>
<CreateTime>1558324778</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[CLICK]]></Event>
<EventKey><![CDATA[V1001_GET_ORDER]]></EventKey>
</xml>
*/
//設置根據字段還是方法生成
//設置生成的xml的根節點的名稱
@XmlRootElement(name = "xml")
@XmlAccessorType(XmlAccessType.FIELD)
public class WeixinResult implements Serializable {
private String ToUserName;
private String FromUserName;
private String MsgType;
private long CreateTime;
private String Event;
private String EventKey;
private String Content;
// view類型時,需要這個字段
private String MenuId;
}
注意: 上面實體類的屬性名,其實就是根據調用公衆號接口返回的統一XML命名。實體類屬性名,最好是與XML數據中返回的字段名保持一致,這樣後面在接收數據並進行轉換時就非常方便
- 簽名校驗方法weixinGZHService.validateWeixinServer
weixinGZHService.java類中核心代碼
下面方法上會用到一個參數 TOKEN,這個值就是我們在公衆號中配置的token值
/**
* 驗證當前微信服務器是否正常
*
* @param request
* @param response
* @throws IOException
*/
public void validateWeixinServer(HttpServletRequest request, HttpServletResponse response) throws IOException {
String signature = request.getParameter("signature");
String timestamp = request.getParameter("timestamp");
String nonce = request.getParameter("nonce");
String echostr = request.getParameter("echostr");
ArrayList<String> array = new ArrayList<String>();
array.add(signature);
array.add(timestamp);
array.add(nonce);
//排序
String sortString = sort(TOKEN, timestamp, nonce);
//加密
String mytoken = SHA1.SHA1(sortString);
//校驗簽名
if (mytoken != null && mytoken != "" && mytoken.equals(signature)) {
response.getWriter().println(echostr); //如果檢驗成功輸出echostr,微信服務器接收到此輸出,纔會確認檢驗完成。
}
}
/**
* 排序方法
*
* @param token
* @param timestamp
* @param nonce
* @return
*/
private String sort(String token, String timestamp, String nonce) {
String[] strArray = {token, timestamp, nonce};
Arrays.sort(strArray);
StringBuilder sbuilder = new StringBuilder();
for (String str : strArray) {
sbuilder.append(str);
}
return sbuilder.toString();
}
- 實體類SHA1.java
public class SHA1 {
public static String SHA1(String decript) {
try {
MessageDigest digest = MessageDigest
.getInstance("SHA-1");
digest.update(decript.getBytes());
byte messageDigest[] = digest.digest();
// Create Hex String
StringBuffer hexString = new StringBuffer();
// 字節數組轉換爲 十六進制 數
for (int i = 0; i < messageDigest.length; i++) {
String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
if (shaHex.length() < 2) {
hexString.append(0);
}
hexString.append(shaHex);
}
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return "";
}
}
2.2.4 聯調檢測
在上面的後臺代碼都配置好後,此時,再回到公衆平臺【開發–基本配置—服務器配置】
當修改配置成功後,點修改配置,彈出【提交成功提示】則表示配置成功。
到此,公衆平臺與我們服務器的整體聯調測試就全部完成。
後面,會再教如何進行自定義菜單開發。