diff --git a/src/main/java/chanjarster/weixin/api/WxService.java b/src/main/java/chanjarster/weixin/api/WxService.java index 6300310f..48588a72 100644 --- a/src/main/java/chanjarster/weixin/api/WxService.java +++ b/src/main/java/chanjarster/weixin/api/WxService.java @@ -9,6 +9,18 @@ import chanjarster.weixin.exception.WxErrorException; */ public interface WxService { + /** + *
+   * 验证推送过来的消息的正确性
+   * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=接入指南
+   * 
+ * @param timestamp + * @param nonce + * @param signature + * @return + */ + public boolean checkSignature(String timestamp, String nonce, String signature); + /** *
    * 获取access_token,本方法线程安全
diff --git a/src/main/java/chanjarster/weixin/api/WxServiceImpl.java b/src/main/java/chanjarster/weixin/api/WxServiceImpl.java
index 1c203ef4..27debf4e 100644
--- a/src/main/java/chanjarster/weixin/api/WxServiceImpl.java
+++ b/src/main/java/chanjarster/weixin/api/WxServiceImpl.java
@@ -1,6 +1,8 @@
 package chanjarster.weixin.api;
 
 import java.io.IOException;
+import java.security.MessageDigest;
+import java.util.Arrays;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.apache.commons.lang3.StringUtils;
@@ -35,6 +37,35 @@ public class WxServiceImpl implements WxService {
   
   protected WxConfigStorage wxConfigProvider;
   
+  public boolean checkSignature(String timestamp, String nonce, String signature) {
+    try {
+      String token = wxConfigProvider.getToken();
+      MessageDigest sha1 = MessageDigest.getInstance("SHA1");
+      String[] arr = new String[] { token, timestamp, nonce };
+      Arrays.sort(arr);
+      StringBuilder sb = new StringBuilder();
+      for(String a : arr) {
+        sb.append(a);
+      }
+      sha1.update(sb.toString().getBytes());
+      byte[] output = sha1.digest();
+      return bytesToHex(output).equals(signature);
+    } catch (Exception e) {
+      return false;
+    }
+  }
+  
+  protected static String bytesToHex(byte[] b) {
+    char hexDigit[] = {'0', '1', '2', '3', '4', '5', '6', '7',
+                       '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+    StringBuffer buf = new StringBuffer();
+    for (int j = 0; j < b.length; j++) {
+      buf.append(hexDigit[(b[j] >> 4) & 0x0f]);
+      buf.append(hexDigit[b[j] & 0x0f]);
+    }
+    return buf.toString();
+ }
+  
   public void refreshAccessToken() throws WxErrorException {
     if (!GLOBAL_ACCESS_TOKEN_REFRESH_FLAG.getAndSet(true)) {
       try {
diff --git a/src/test/java/chanjarster/weixin/api/WxServiceTest.java b/src/test/java/chanjarster/weixin/api/WxServiceTest.java
index 58650bee..a9290c18 100644
--- a/src/test/java/chanjarster/weixin/api/WxServiceTest.java
+++ b/src/test/java/chanjarster/weixin/api/WxServiceTest.java
@@ -69,6 +69,14 @@ public class WxServiceTest {
     wxService.deleteMenu();
   }
   
+  @Test
+  public void testCheckSignature() throws WxErrorException {
+    String timestamp = "23234235423246";
+    String nonce = "y7didfkcmvnbd90sdofjkiefhsd";
+    String signature = "77b6651628dfb9a64bfb0d3432ee053ac566a459";
+    Assert.assertTrue(wxService.checkSignature(timestamp, nonce, signature));
+  }
+  
   @DataProvider(name="menu")
   public Object[][] getMenu() throws JAXBException {
     WxMenu menu = new WxMenu();
@@ -116,7 +124,6 @@ public class WxServiceTest {
   
   }
   
-  
   @XmlRootElement(name = "xml")
   @XmlAccessorType(XmlAccessType.FIELD)
   public static class WxXmlConfigStorage extends WxInMemoryConfigStorage {