First of all, the development mode of WeChat enterprise accounts is divided into: editing mode (normal mode) and development mode (callback mode) . In editing mode, you can only make simple custom menus and automatically reply messages. To realize other functions, you must turn on the developer mode.
1. Editing mode and development mode to process messages
1. In edit mode, all business processes are configured on the WeChat server and processed by it.
2. Development mode, messages are processed through third-party servers, and finally messages are sent to users through WeChat servers.
The development mode can process more messages than the edit mode, so you must first enable the development mode to develop more functions.
2. The development model is started
In callback mode, enterprises can not only actively call the enterprise number interface, but also receive messages or events from users. The received information is encoded in XML data format, UTF8, and encrypted in AES .
1. After turning on callback mode, the parameters must be configured as follows:
The url is the servlet to be accessed, and the token and EncodingAESKey are randomly obtained, but must be consistent with the project.
2. Verify the validity of the URL
When you submit the above information, the enterprise number will send a GET request to the filled-in URL. The GET request carries four parameters. The enterprise needs to do urldecode processing when obtaining it , otherwise the verification will not be successful.
3. Code
CoreServlet1 class
public class CoreServlet1 extends HttpServlet { private static final long serialVersionUID = 4440739483644821986L; String sToken = "weixinCourse"; String sCorpID = "wxe510946434680dab"; String sEncodingAESKey = "DjlyZxgKiWRESIW2VnV9dSr7HsS7usWDfnwA8Q1ove1"; public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { WXBizMsgCrypt wxcpt; try { wxcpt = new WXBizMsgCrypt(sToken, sEncodingAESKey, sCorpID); String sVerifyMsgSig = request.getParameter("msg_signature"); String sVerifyTimeStamp = request.getParameter("timestamp"); String sVerifyNonce = request.getParameter("nonce"); String sVerifyEchoStr = request.getParameter("echostr"); String sEchoStr; sEchoStr = wxcpt.VerifyURL(sVerifyMsgSig, sVerifyTimeStamp, sVerifyNonce, sVerifyEchoStr); System.out.println("verifyurl echostr: " + sEchoStr); PrintWriter out = response.getWriter(); out.print(sEchoStr); out.close(); out = null; } catch (AesException e1) { e1.printStackTrace(); } }} Tools:
/** * Sample code for encrypting and decrypting messages sent to public accounts by public platforms. * * @copyright Copyright (c) 1998-2014 Tencent Inc. */// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- com.qq.weixin.mp.aes;import java.nio.charset.Charset;import java.util.Arrays;import java.util.Random;import javax.crypto.Cipher;import javax.crypto.spec.IvParameterSpec;import javax.crypto.spec.SecretKeySpec;import org.apache.commons.codec.binary.Base64;/** * Provides an encryption and decryption interface (UTF8-encoded string) for receiving and pushing messages to the public platform. * <ol> * <li>Third-party reply to encrypted messages to the public platform</li> * <li>The third party receives messages sent by the public platform to verify the security of the messages and decrypts the messages. </li> * </ol> * Description: Exception java.security.InvalidKeyException: solution to illegal Key Size* <ol> * <li>Download JCE unlimited permission policy file on the official website (the download address of JDK7: * http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html</li> * <li>Decompress after downloading, you can see local_policy.jar, US_export_policy.jar and readme.txt</li> * <li>If JRE is installed, place the two jar files in the %JRE_HOME%/lib/security directory to overwrite the original file</li> * <li>If JDK is installed, place the two jar files in the %JDK_HOME%/jre/lib/security directory to overwrite the original file</li> * </ol> */public class WXBizMsgCrypt { static Charset CHARSET = Charset.forName("utf-8"); Base64 base64 = new Base64(); byte[] aesKey; String token; String corpId; /** * Constructor* @param token On the public platform, the token set by the developer * @param encodingAesKey On the public platform, the EncodingAESKey set by the developer * @param corpId The corporate corpid * * @throws AesException The execution failed, please check the error code and specific error information of the exception */ public WXBizMsgCrypt(String token, String encodingAesKey, String corpId) throws AesException { if (encodingAesKey.length() != 43) { throw new AesException(AesException.IllegalAesKey); } this.token = token; this.corpId = corpId; aesKey = Base64.decodeBase64(encodingAesKey + "="); } /** * Decrypt the ciphertext. * * @param text The ciphertext that needs to be decrypted* @return The plaintext obtained by decryption* @throws AesException aes failed to decrypt*/ String decrypt(String text) throws AesException { byte[] original; try { // Set the decryption mode to AES CBC mode Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); SecretKeySpec key_spec = new SecretKeySpec(aesKey, "AES"); IvParameterSpec iv = new IvParameterSpec(Arrays.copyOfRange(aesKey, 0, 16)); cipher.init(Cipher.DECRYPT_MODE, key_spec, iv); // Use BASE64 to decode the ciphertext byte[] encrypted = Base64.decodeBase64(text); // Decrypt original = cipher.doFinal(encrypted); } catch (Exception e) { e.printStackTrace(); throw new AesException(AesException.DecryptAESError); } String xmlContent, from_corpid; try { // Remove the complement character byte[] bytes = PKCS7Encoder.decode(original); // Separate 16-bit random strings, network endianness and corpId byte[] networkOrder = Arrays.copyOfRange(bytes, 16, 20); int xmlLength = recoverNetworkBytesOrder(networkOrder); xmlContent = new String(Arrays.copyOfRange(bytes, 20, 20 + xmlLength), CHARSET); from_corpid = new String(Arrays.copyOfRange(bytes, 20 + xmlLength, bytes.length), CHARSET); } catch (Exception e) { e.printStackTrace(); throw new AesException(AesException.IllegalBuffer); } // case where corpid is different if (!from_corpid.equals(corpId)) { throw new AesException(AesException.ValidateCorpidError); } return xmlContent; } /** * Verify URL * @param msgSignature signature string, corresponding to URL parameters msg_signature * @param timeStamp timestamp, corresponding to URL parameters timestamp * @param nonce Random string, corresponding to URL parameters nonce * @param echoStr Random string, corresponding to URL parameters echostr * * @return echostr after decryption * @throws AesException execution failed, please check the error code and specific error information of the exception */ public String VerifyURL(String msgSignature, String timeStamp, String nonce, String echoStr) throws AesException { String signature = SHA1.getSHA1(token, timeStamp, nonce, echoStr); if (!signature.equals(msgSignature)) { throw new AesException(AesException.ValidateSignatureError); } String result = decrypt(echoStr); return result; }} /** * Sample code for encrypting and decrypting messages sent to public accounts by public platforms. * * @copyright Copyright (c) 1998-2014 Tencent Inc. */// --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @param encrypt ciphertext* @return Secure signature* @throws AesException */ public static String getSHA1(String token, String timestamp, String nonce, String encrypt) throws AesException { try { String[] array = new String[] { token, timestamp, nonce, encrypt }; StringBuffer sb = new StringBuffer(); // String sort Arrays.sort(array); for (int i = 0; i < 4; i++) { sb.append(array[i]); } String str = sb.toString(); // SHA1 signature generation MessageDigest md = MessageDigest.getInstance("SHA-1"); md.update(str.getBytes()); byte[] digest = md.digest(); StringBuffer hexstr = new StringBuffer(); String shaHex = ""; for (int i = 0; i < digest.length; i++) { shaHex = Integer.toHexString(digest[i] & 0xFF); if (shaHex.length() < 2) { hexstr.append(0); } hexstr.append(shaHex); } return hexstr.toString(); } catch (Exception e) { e.printStackTrace(); throw new AesException(AesException.ComputeSignatureError); } }} class PKCS7Encoder { static Charset CHARSET = Charset.forName("utf-8"); static int BLOCK_SIZE = 32;/** * Delete the complement character of the decrypted plaintext* * @param decrypted The decrypted plaintext* @return plaintext after deleting the fill character*/ static byte[] decode(byte[] decrypted) { int pad = (int) decrypted[decrypted.length - 1]; if (pad < 1 || pad > 32) { pad = 0; } return Arrays.copyOfRange(decrypted, 0, decrypted.length - pad); }} 3. Summary
The enterprise verifies the request through the parameter msg_signature. If it is confirmed that the GET request is from the enterprise number, then the enterprise application decrypts the echostr parameter and returns the echostr plaintext as it is (quoted cannot be added), then the access verification takes effect and the callback mode can be enabled. After turning on, some functions will be implemented one after another, so stay tuned!
The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.