盤查過后發現只是自己支付中心的提供者代碼的回調地址配置的是生產環境 實際需要是開發環境
但是!!! 微信文檔中明確說明 微信不保證通知最終一定能成功 需要自己主動調用微信方法查詢是否支付成功 之前沒有做這部分處理
按照微信說的 也會存在客戶端支付成功后 后台收不到回調從而無法修改訂單狀態等信息 微信的解釋大致意思是:
微信推送支付數據流的時候是后台通知交互時,如果微信收到商戶的應答不符合規范或超時,微信會判定本次通知失敗,重新發送通知,直到成功為止(在通知一直不成功的情況下,微信總共會發起10次通知,
通知頻率為15s/15s/30s/3m/10m/20m/30m/30m/30m/60m/3h/3h/3h/6h/6h - 總計 24h4m)
所以這里就需要我們自己主動去查詢:接口詳細說明地址(http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_2)
//支付中心寫一個方法 參數:String 訂單號 (這里我只是做一個說明 實際要加密之類)
//創建一個API接口 參數和支付中心新寫的方法一致 調用支付中心新寫方法
//支付中心新方法 :創建定時任何防止一次查詢有延遲
//當小程序或者app 支付成功回調后調用API 這個接口 上傳一個訂單號
Timer timer = new Timer(); timer.schedule(new TimerTask() { //最大重試次數 int MAX_RETRY = 5; @Override public void run() { MAX_RETRY--; //檢查訂單系統 WxpOrderDTO wxpOrderDTO = wxpOrderMapper.selectWxpOrder(orderNo); if (wxpOrderDTO.getStatus().equals("1")) { //取消定時器(訂單支付成功) timer.cancel(); } else { //查詢訂單狀態 WxMpPayResult payResult = wxMpService.getJSSDKPayResult(null, orderNo); if (payResult.getReturn_code().equals("SUCCESS")) { //已經支付,更新訂單狀態 SUCCESS ==成功 REFUND==轉入退款 NOTPAY==未支付 CLOSED==訂單已關閉 ACCESP==等待扣款 PAY_FAIL==支付失敗 if (payResult.getResult_code().equals("SUCCESS")) { wxpOrderMapper.updateOrderStatus(orderNo); } } } if (MAX_RETRY == 0) { //取消定時器(用戶取消支付) timer.cancel(); } } }, 2000, 5000);//實際處理要按照自己的業務來寫 這里只是舉個例子
微信的接口 參數:
/** * 該接口提供所有微信支付訂單的查詢,當支付通知處理異常或丟失的情時,商戶可以通過該接口查詢訂單支付狀態。 * 詳見http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_2 * @param transactionId * @param outTradeNo */ WxMpPayResult getJSSDKPayResult(String transactionId, String outTradeNo);
@Override public WxMpPayResult getJSSDKPayResult(String transactionId, String outTradeNo) { String nonce_str = System.currentTimeMillis() + ""; SortedMap<String, String> packageParams = new TreeMap<String, String>(); packageParams.put("appid", wxMpConfigStorage.getAppId()); packageParams.put("mch_id", wxMpConfigStorage.getPartnerId()); if (transactionId != null && !"".equals(transactionId.trim())) packageParams.put("transaction_id", transactionId); else if (outTradeNo != null && !"".equals(outTradeNo.trim())) packageParams.put("out_trade_no", outTradeNo); else throw new IllegalArgumentException("Either 'transactionId' or 'outTradeNo' must be given."); packageParams.put("nonce_str", nonce_str); packageParams.put("sign", WxCryptUtil.createSign(packageParams, wxMpConfigStorage.getPartnerKey())); StringBuilder request = new StringBuilder("<xml>"); for (Entry<String, String> para : packageParams.entrySet()) { request.append(String.format("<%s>%s</%s>", para.getKey(), para.getValue(), para.getKey())); } request.append("</xml>"); HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/pay/orderquery"); if (httpProxy != null) { RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build(); httpPost.setConfig(config); } StringEntity entity = new StringEntity(request.toString(), Consts.UTF_8); httpPost.setEntity(entity); try { CloseableHttpResponse response = httpClient.execute(httpPost); String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); XStream xstream = XStreamInitializer.getInstance(); xstream.alias("xml", WxMpPayResult.class); WxMpPayResult wxMpPayResult = (WxMpPayResult) xstream.fromXML(responseContent); return wxMpPayResult; } catch (IOException e) { throw new RuntimeException("Failed to query order due to IO exception.", e); } }