官方api文檔:https://files.cnblogs.com/files/guoxiaoyu/掃碼點餐數據上報API_渠道商_v1.3.rar
使用算法:加密解密都不是使用的商戶平台的API秘鑰,一定要使用微信給自己的證書,一個是p12、cert.pem、key.pem(這個是自己使用方法的私鑰ps:記得將里面的頭和尾沒用的信息去掉,只要里面的字符串把換行也去掉就可以),只有在下載證書后用的是apiV3秘鑰解密密文的。ps:如果沒有記得v3秘鑰讓微信給自己開通白名單,自己踩了個坑
1、sha256withrsa
/** * 加簽 * * @param signData 需要簽名的源數據 * @param privateKey 私鑰(base64加密) * @return 加簽后的簽名 */ public static String sign(String signData, String privateKey) { try { PKCS8EncodedKeySpec PKCS8Key = new PKCS8EncodedKeySpec(org.apache.commons.codec.binary.Base64.decodeBase64(privateKey .getBytes())); KeyFactory key = KeyFactory.getInstance("RSA"); PrivateKey priKey = key.generatePrivate(PKCS8Key); Signature signature = Signature.getInstance("sha256withrsa"); signature.initSign(priKey); signature.update(signData.getBytes("UTF-8")); byte[] signed = signature.sign(); return new String(Base64.encodeBase64(signed)); } catch (Exception e) { e.printStackTrace(); } return null; }
2、AEAD_AES_256_GCM
1 /** 2 * 三個都是接口所給 3 * @param aad associatedData 固定字符串 4 * @param iv nonce 隨機字符串 5 * @param cipherText cipherText 密文 6 * @return 7 * @throws Exception 8 */ 9 private static String aesgcmDecrypt(String aad, String iv, String cipherText) { 10 try { 11 final Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "SunJCE"); 12 SecretKeySpec key = new SecretKeySpec(AES_KEY.getBytes(), "AES");//AES_KEY為APIV3秘鑰--如果秘鑰錯誤,解密時會返回tag mismatch 13 GCMParameterSpec spec = new GCMParameterSpec(128, iv.getBytes()); 14 cipher.init(Cipher.DECRYPT_MODE, key, spec); 15 cipher.updateAAD(aad.getBytes()); 16 return new String(cipher.doFinal(Base64.getDecoder().decode(cipherText))); 17 } catch (Exception e) { 18 return "fail"; 19 } 20 }
3、sha256withrsa
1 /** 2 * 簽名字符串 3 * 4 * @param content 需要簽名的字符串 5 * @param sign 客戶簽名結果 6 * @param publicKeypath 公鑰cert證書文件地址 ,也可以自己寫純證書字符串,方法自己可以截取 7 * @return 驗簽結果 8 */ 9 public static boolean verify(String content, String sign, String publicKeypath) { 10 try { 11 File cert = new File(publicKeypath); 12 FileInputStream fileInputStream = new FileInputStream(cert); 13 byte[] PublicKeyBytes = new byte[Integer.valueOf(String.valueOf(cert.length()))]; 14 fileInputStream.read(PublicKeyBytes); 15 X509Certificate certificate = X509Certificate.getInstance(PublicKeyBytes); 16 PublicKey pubKey = certificate.getPublicKey(); 17 System.out.println(new String(org.apache.commons.codec.binary.Base64.encodeBase64(pubKey.getEncoded()))); 18 Signature signature = Signature.getInstance("sha256withrsa"); 19 signature.initVerify(pubKey); 20 signature.update(content.getBytes("UTF-8")); 21 return signature.verify(org.apache.commons.codec.binary.Base64.decodeBase64(sign)); 22 } catch (Exception e) { 23 return false; 24 } 25 }
如果這些算法完事之后就是自己真正的業務邏輯了,以post接口方式為例(get方法請求參數為空,但是也要有“\n”不然會解析失敗),一定寫好請求頭中的Auth串,寫對了才可以將數據給微信方
1 HttpPost post = new HttpPost(HTTP_ADDRESS); 2 //生產簽名串 3 long currentTimeMillis = System.currentTimeMillis()/1000; 4 String randomUUID = UUID.randomUUID().toString().replaceAll("-", ""); 5 StringBuffer signStr = new StringBuffer(); 6 signStr.append(HTTP_METHOD_SIGN).append(END_SYMBOL_SIGN) 7 .append(URL_SIGN).append(END_SYMBOL_SIGN) 8 .append(currentTimeMillis).append(END_SYMBOL_SIGN) 9 .append(randomUUID).append(END_SYMBOL_SIGN) 10 .append(paramJson).append(END_SYMBOL_SIGN); 11 //簽名 12 String signature = RSAUtils.sign(signStr.toString(), privateKey); 13 //授權串 14 StringBuffer authStr = new StringBuffer(); 15 authStr.append(AUTHORIZATION_TYPE).append(" ").append("mchid=\"") 16 .append(MERCHANT_ID).append("\",nonce_str=\"").append(randomUUID) 17 .append("\",signature=\"").append(signature).append("\",timestamp=\"") 18 .append(currentTimeMillis).append("\",serial_no=\"").append(CER_SERIAL_NO).append("\""); 19 20 post.setHeader("Authorization", authStr.toString()); 21 post.setHeader("Content-Type", "application/json"); 22 post.setHeader("User-Agent", "curl/7.54.0"); 23 post.setHeader("Accept", "application/json"); 24 post.setEntity(new StringEntity(paramJson, Consts.UTF_8));
寫個接口踩了好幾個坑,比如秘鑰寫錯、微信沒有開白名單自己卻不知道、參數寫的不規范導致微信驗簽老失敗。希望大家可以少才幾個坑
有什么問題,博客回復太慢,可以加一下本人微信:請備注問題,謝謝!
編寫不易,轉載請寫明出處,謝謝;
ps:關注一下本人公眾號,每周都有新更新哦!