最近需求是 用戶兌換微信紅包,需要一些驗證,加密,以及證書;
工欲善其事必先利其器
感謝前輩的微信SDK 已經維護三年了,還在維護中!
官方文檔走一波
文檔還是一如既往的 坑人啊,寫的很簡單,對簡單明了。 有接口 有提交方式 有參數類型
開發前的准備:首先需要讀一下開發文檔,調用任何接口前 都應該仔細看看人家的開發文檔,我們可以得到知道,發送紅包不是根據微信號,而是根據openid ,openid的獲取 是調用微信網頁授權的接口 看這里,另外需要微信商戶,提前開通現金紅包功能,跟以前一樣要設置ip白名單;
先上一波成功圖:
好了重點來了 開始開發
假設你已經設置好了 ip 白名單 , 已經拿到了用戶openid 還有商戶號,商戶key 有SDK的話很簡單一段代碼 就實現了
先簡單點 實現功能 ,再去讀前輩寫的SDK 研究代碼, 通過查找 SDK里有封裝好的api
SDK
1 /** 2 * 現金紅包 <br> 3 * 4 * 1.發送頻率限制------默認1800/min <br> 5 * 2.發送個數上限------按照默認1800/min算<br> 6 * 3.金額上限------根據傳入場景id不同默認上限不同,可以在商戶平台產品設置進行設置和申請,最大不大於4999元/個<br> 7 * 4.其他的“量”上的限制還有哪些?------用戶當天的領取上限次數,默認是10<br> 8 * 5.如果量上滿足不了我們的需求,如何提高各個上限?------金額上限和用戶當天領取次數上限可以在商戶平台進行設置<br> 9 * 注 <br> 10 * 1:如果你是服務商,希望代你的特約商戶發紅包,你可以申請獲得你特約商戶的“現金紅包產品授權”。操作路徑如下:【登錄商戶平台-產品中心- 11 * 特約商戶授權產品】(即將上線) <br> 12 * 2:紅包金額大於200時,請求參數scene_id必傳 13 * 14 * @param sendredpack 15 * sendredpack 16 * @param key 17 * key 18 * @return SendredpackResult 19 */ 20 public static SendredpackResult mmpaymkttransfersSendredpack(Sendredpack sendredpack,String key){ 21 Map<String,String> map = MapUtil.objectToMap( sendredpack); 22 String sign = SignatureUtil.generateSign(map,sendredpack.getSign_type(),key); 23 sendredpack.setSign(sign); 24 String secapiPayRefundXML = XMLConverUtil.convertToXML( sendredpack); 25 HttpUriRequest httpUriRequest = RequestBuilder.post() 26 .setHeader(xmlHeader) 27 .setUri(baseURI()+ "/mmpaymkttransfers/sendredpack") 28 .setEntity(new StringEntity(secapiPayRefundXML,Charset.forName("utf-8"))) 29 .build(); 30 return LocalHttpClient.keyStoreExecuteXmlResult(sendredpack.getMch_id(),httpUriRequest,SendredpackResult.class,sendredpack.getSign_type(),key); 31 }
簡單看一下 需要傳入參數 ,一個是封裝好的紅包實體類 一個是商戶Key
開始寫
1 //兌換微信紅包 2 3 Sendredpack redpack=new Sendredpack(); //微信紅包信息 4 redpack.setNonce_str(UUID.randomUUID().toString()); //隨機字符串\ 5 redpack.setMch_billno(UUID.randomUUID().toString());//商戶單號 6 redpack.setMch_id(mch_id); //商戶號 7 redpack.setWxappid(wxappid); //公眾號appid 8 redpack.setSend_name(send_name); //商戶名稱 9 redpack.setRe_openid(user.getOpenid()); //用戶openid 10 redpack.setTotal_amount(wxred.getRmb()*num*100); //付款金額 11 redpack.setTotal_num(total_num); //紅包發送人數 12 redpack.setWishing("恭喜您兌換成功!"); //紅包祝福語 13 redpack.setClient_ip(localIp()); //ip地址 14 redpack.setAct_name("積分兌換紅包活動"); //活動名稱 15 redpack.setRemark("備注"); //備注 16 SendredpackResult result= PayMchAPI.mmpaymkttransfersSendredpack(redpack,key); 17 if(result==null){ 18 return ajax; //未知錯誤 19 20 } 21 System.out.println("************ 返回數據**************"); 22 System.out.println("返回信息:"+result.getReturn_msg()+" 返回狀態碼:"+result.getReturn_code()+" 業務結果:"+result.getResult_code()+"錯誤代碼:"+result.getErr_code()+" 錯誤代碼描述:"+result.getErr_code_des()); 23 24 if(!"SUCCESS".equals(result.getReturn_code())){ 25 ajax.setMsg(result.getReturn_msg()); //錯誤原因 26 27 ajax.setData(result); 28 return ajax; 29 }
按道理說 這么寫沒問題 然而 ,請求api方法的時候 報錯了,
說是找不到類 org.apache.http.util.Args, 看了看項目 是引用的 HttpClient jar 沖突了,因為SDK里也引用的有這個包
刪除 ok ,接着走
問題來了 這時候 報了一個空指針 ,是SDK里報的 ,這就納悶了, 寫好的SDK 怎么會報空指針。
順着 代碼 打斷點 調試 ,
發現問題了 , 是因為 調用微信這個接口的時候 需要從連接池里 獲取一個連接, 但是連接池是空的 ,所以空指針了,恩,現在需要做的,就是初始化連接池
在Git 上看到了 設置API HttpClient 請求池大小 的代碼
1 LocalHttpClient.init(100,10); 2 LocalHttpClient.initMchKeyStore("1329266801","C:\\Users\\Administrator\\Desktop\\cert\\apiclient_cert.p12"); 3 LocalHttpClient.setTimeout(5000); 4 5 //@since 2.7.0 6 7 //異常重試次數 2 8 9 LocalHttpClient.setRetryExecutionCount(2); 10 //設置請求連接池
好了 ,前邊是 商戶id 后邊是 證書位置
在測試一波 ,, 還是沒有成功
看日志
看到了我們傳遞給微信的數據 所有的數據都在 沒有空數據
接着看
這就有點坑了 , 微信文檔明明是說 返回sunccess 就是成功,明明說 單號長度可以為32位 我才用了UUid 好了不多說 ,看到了成功的希望,
改下 繼續
這個參數也是有的 長度也沒有超出 , 不知道為什么給我報了錯, 參數長度減少了一點 好了
到此為止,借用SDK的情況下 ,實現了微信公眾號現金紅包的 功能 ,
但是 這顯然不是我們所想的, 因為我們對實現過程一無所知,所以 我決定 應該往下看 , 看看SDK里是怎么實現的,讀人家的代碼