diff --git a/mallinkService/src/main/java/com/iformall/pay/WxPay.java b/mallinkService/src/main/java/com/iformall/pay/WxPay.java index 57723f1b7..7879ea763 100644 --- a/mallinkService/src/main/java/com/iformall/pay/WxPay.java +++ b/mallinkService/src/main/java/com/iformall/pay/WxPay.java @@ -46,6 +46,8 @@ public class WxPay { private static final String GETTRANSFERINFO_URL = "https://api.mch.weixin.qq.com/mmpaymkttransfers/gettransferinfo"; //商家转账到零钱 private static final String MERCHANT_TRANSFER_CHANGE_URL = "https://api.mch.weixin.qq.com/v3/transfer/batches"; + //查询商家转账到零钱 + private static final String MERCHANT_TRANSFER_QUERY_URL = "https://api.mch.weixin.qq.com/v3/transfer/batches/out-batch-no/%s"; // 查询代金券批次 private static final String GETCOUPONSTOCK_URL = "https://api.mch.weixin.qq.com/mmpaymkttransfers/query_coupon_stock"; @@ -270,6 +272,24 @@ public class WxPay { } return payService.postV3WithWechatpaySerial(MERCHANT_TRANSFER_CHANGE_URL, JSON.toJSONString(cashOutV3)); } + + /** + * 查询商家转账到零钱 + * https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_5.shtml + * @param params + * 请求参数 + * @param certPath + * 证书文件目录 + * @param certPassword + * 证书密码 + * @return {String} + * @throws WxPayException + */ + public static String merchantTransferInfo(String batchNo, WxPayService payService) throws WxPayException { + Map param = new HashMap(); + param.put("need_query_detail", false); + return payService.postV3WithWechatpaySerial(String.format(MERCHANT_TRANSFER_QUERY_URL, batchNo), JSON.toJSONString(param)); + } /** * 商户模式下 扫码模式一之生成二维码 diff --git a/mallinkService/src/main/java/com/iformall/service/pay/service/cashout/wx/WxCashOutAdapterService.java b/mallinkService/src/main/java/com/iformall/service/pay/service/cashout/wx/WxCashOutAdapterService.java index e08faf6ef..353b0daf3 100644 --- a/mallinkService/src/main/java/com/iformall/service/pay/service/cashout/wx/WxCashOutAdapterService.java +++ b/mallinkService/src/main/java/com/iformall/service/pay/service/cashout/wx/WxCashOutAdapterService.java @@ -204,30 +204,29 @@ public class WxCashOutAdapterService implements CashOutAdapterService{ @Override public CashOutAdapterResult cashOut(WxAppinfo appInfo, WxPayAccount payAccount, WxCashOut cashOut) { - if (StringUtils.isBlank(payAccount.getMerchantCertPath())) { - return new CashOutAdapterResult(false, EnumCashOutStatus.FAIL.getCode(), "零钱支付失败。商户证书为空。请联系管理员配置。", null); + if (StringUtils.isBlank(payAccount.getPrivateCertPath())) { + return new CashOutAdapterResult(false, EnumCashOutStatus.FAIL.getCode(), "零钱支付失败。证书PrivateCertPath为空。请联系管理员配置。", null); } - if (StringUtils.isBlank(payAccount.getMerchantApiKey())) { - return new CashOutAdapterResult(false, EnumCashOutStatus.FAIL.getCode(), "零钱支付失败。商户密钥为空。请联系管理员配置。", null); + if (StringUtils.isBlank(payAccount.getPrivateKeyPath())) { + return new CashOutAdapterResult(false, EnumCashOutStatus.FAIL.getCode(), "零钱支付失败。密钥PrivateKeyPath为空。请联系管理员配置。", null); } - - WxAppinfo cAppInfo = wxAppinfoService.getCAppInfo(payAccount, EnumAppPlat.WX); - if(cAppInfo == null){ - return new CashOutAdapterResult(false, EnumCashOutStatus.FAIL.getCode(), "零钱支付失败。当前商场未查询到微信C端小程序配置。", null); - } - WxPayService payService = maUtil.getWxPayService(cAppInfo,payAccount); + if (StringUtils.isBlank(payAccount.getApiV3Key())) { + return new CashOutAdapterResult(false, EnumCashOutStatus.FAIL.getCode(), "零钱支付失败。密钥ApiV3Key为空。请联系管理员配置。", null); + } + + WxPayService payService = maUtil.getWxPayService(appInfo,payAccount); if (null == payService) { return new CashOutAdapterResult(false, EnumCashOutStatus.FAIL.getCode(), "零钱支付失败。当前小程序未查询到payService。", null); } String response = null; try { - response = WxPay.merchantTranferChange(payService,generateWxCashOutPV3(payAccount, cAppInfo, cashOut)); + response = WxPay.merchantTranferChange(payService,generateWxCashOutPV3(payAccount, appInfo, cashOut)); } catch (Exception e) { log.error("零钱支付异常: " + e.getMessage(),e); return new CashOutAdapterResult(false, EnumCashOutStatus.FAIL.getCode(), "微信零钱支付接口调用异常."+e.getMessage(), null); } //log.info("微信零钱支付:" + wxCashOutP.toString() +", response: " + response.toString()); - return getReusltFromp(response,cashOut); + return generateResult(response,cashOut); // if (payAccount.getType() == EnumPayMode.MCH.getCode()) { // 普通商户模式 @@ -254,6 +253,93 @@ public class WxCashOutAdapterService implements CashOutAdapterService{ return wxCashOutPv3; } + private CashOutAdapterResult generateResult(String response,WxCashOut cashOut) { + JSONObject result = JSON.parseObject(response); + String batchId = result.getString("batch_id"); + if (!StringUtils.isBlank(batchId)) { + cashOut.setWxPayNo(batchId); + String payTime = result.getString("create_time"); + cashOut.setWxPayTime(payTime); + return new CashOutAdapterResult(true,EnumCashOutStatus.SUCCESS.getCode(),"微信零钱支付申请成功",result); + }else { + //log.error("微信零钱支付申请失败: " + response); + return new CashOutAdapterResult(false, EnumCashOutStatus.FAIL.getCode(), "微信零钱支付申请失败:微信接口未返回值", result); + } + } + + + @Override + public CashOutAdapterResult queryCashOut(WxAppinfo appInfo, WxPayAccount payAccount, WxCashOut cashOut) { + if (StringUtils.isBlank(payAccount.getPrivateCertPath())) { + return new CashOutAdapterResult(false, EnumCashOutStatus.FAIL.getCode(), "零钱支付失败。证书PrivateCertPath为空。请联系管理员配置。", null); + } + if (StringUtils.isBlank(payAccount.getPrivateKeyPath())) { + return new CashOutAdapterResult(false, EnumCashOutStatus.FAIL.getCode(), "零钱支付失败。密钥PrivateKeyPath为空。请联系管理员配置。", null); + } + if (StringUtils.isBlank(payAccount.getApiV3Key())) { + return new CashOutAdapterResult(false, EnumCashOutStatus.FAIL.getCode(), "零钱支付失败。密钥ApiV3Key为空。请联系管理员配置。", null); + } + WxPayService payService = maUtil.getWxPayService(appInfo,payAccount); + if (null == payService) { + return new CashOutAdapterResult(false, EnumCashOutStatus.FAIL.getCode(), "零钱支付失败。当前小程序未查询到payService。", null); + } + String response = null; + try { + response = WxPay.merchantTransferInfo(String.valueOf(cashOut.getId()), payService); + } catch (Exception e) { + log.error("零钱支付查询异常: " + e.getMessage(),e); + throw new MallinkException(ErrorCode.REFUND_ORDER_ERROR.getCode(), "微信零钱支付查询接口异常:"+e.getMessage()); + } + //log.info("微信零钱支付查询:"+ response.toString()); + return getReusltFromQuery(response,cashOut); + } + + private CashOutAdapterResult getReusltFromQuery(String response,WxCashOut cashOut) throws MallinkException{ + JSONObject result = JSON.parseObject(response); + JSONObject transferBatch = result.getJSONObject("transfer_batch"); + if (null != transferBatch) { + /** + * WAIT_PAY:待付款,商户员工确认付款阶段 + * ACCEPTED:已受理。批次已受理成功,若发起批量转账的30分钟后,转账批次单仍处于该状态,可能原因是商户账户余额不足等 + * PROCESSING:转账中。已开始处理批次内的转账明细单 + * FINISHED:已完成。批次内的所有转账明细单都已处理完成 + * CLOSED:已关闭。可查询具体的批次关闭原因确认 + */ + String batchStatus = transferBatch.getString("batch_status"); + if ("WAIT_PAY".equals(batchStatus)) { + throw new MallinkException(EnumCashOutStatus.FAIL.getCode(), "待商户付款:"); + }else if ("ACCEPTED".equals(batchStatus)) { + throw new MallinkException(EnumCashOutStatus.FAIL.getCode(), "已受理,待转账:"); + }else if ("PROCESSING".equals(batchStatus)) { + throw new MallinkException(EnumCashOutStatus.FAIL.getCode(), "待转账中"); + }else if ("CLOSED".equals(batchStatus)) { + /** + * MERCHANT_REVOCATION:商户主动撤销 OVERDUE_CLOSE:系统超时关闭 + */ + String close_reason = transferBatch.getString("close_reason"); + if ("MERCHANT_REVOCATION".equals(close_reason)) { + close_reason = "商户主动撤销"; + }else if ("OVERDUE_CLOSE".equals(close_reason)) { + close_reason = "系统超时关闭"; + } + return new CashOutAdapterResult(false,EnumCashOutStatus.FAIL.getCode(),"转账已关闭:"+close_reason,result); + }else if ("FINISHED".equals(batchStatus)) { + String detailId = transferBatch.getString("out_batch_no"); + cashOut.setWxPayNo(detailId); + String wxPayTime = transferBatch.getString("create_time"); + cashOut.setWxPayTime(wxPayTime); + return new CashOutAdapterResult(true,EnumCashOutStatus.SUCCESS.getCode(),"转账已完成",result); + }else { + log.error("微信零钱支付查询失败,微信返回未知状态: " + response); + throw new MallinkException(ErrorCode.SYS_PARAMETER_CAST_ERROR.getCode(), "微信零钱支付查询失败, 微信返回未知状态:"+batchStatus); + } + }else { + log.error("微信零钱支付查询失败,微信未返回值: " + response); + throw new MallinkException(ErrorCode.SYS_PARAMETER_CAST_ERROR.getCode(), "微信零钱支付查询失败,微信未返回值:"); + } + } + + // /** // * https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2 @@ -294,114 +380,114 @@ public class WxCashOutAdapterService implements CashOutAdapterService{ // // 普通商户模式 //// } // } - - private WxCashOutP generateWxCashOutP(WxPayAccount payAccount,WxAppinfo appInfo,WxCashOut cashOut) { - String noncestr = Utility.generate32UUID(); - WxCashOutP wxCashOutP = new WxCashOutP(); - wxCashOutP.setMch_appid(appInfo.getAppId()); - wxCashOutP.setMchid(payAccount.getSubMchId()); - wxCashOutP.setNonce_str(noncestr); - wxCashOutP.setAmount(cashOut.getTotalFee()); - wxCashOutP.setCheck_name("NO_CHECK"); - wxCashOutP.setDesc("客户结算"); - wxCashOutP.setOpenid(cashOut.getReciveOpenId()); - wxCashOutP.setPartner_trade_no(String.valueOf(cashOut.getId())); - return wxCashOutP; - } - - private CashOutAdapterResult getReusltFromp(String response,WxCashOut cashOut) throws MallinkException{ - Map returnMap = WxPayment.xmlToMap(response); - String result_no = returnMap.get("result_code"); - if ("SUCCESS".equals(result_no)) { - log.info("微信零钱支付申请成功: " + returnMap.toString()); - String wxPayNo = returnMap.get("payment_no"); - String payTime = returnMap.get("payment_time"); - cashOut.setWxPayNo(wxPayNo); - cashOut.setWxPayTime(payTime); - return new CashOutAdapterResult(true,EnumCashOutStatus.SUCCESS.getCode(),"微信零钱支付申请成功",returnMap); - } else { - log.error("微信零钱支付申请失败: " + response); - String errMsg = ""; - JSONObject errObj = errorRefundReqMap.getJSONObject(result_no); - if (errObj != null) { - errMsg = errObj.toJSONString(); - } else { - errMsg = returnMap.get("err_code_des"); - } - return new CashOutAdapterResult(false, EnumCashOutStatus.FAIL.getCode(), errMsg, returnMap); - } - } - - @Override - public CashOutAdapterResult queryCashOut(WxAppinfo appInfo, WxPayAccount payAccount, WxCashOut cashOut) { - if (StringUtils.isBlank(payAccount.getMerchantCertPath())) { - return new CashOutAdapterResult(false, EnumCashOutStatus.FAIL.getCode(), "零钱支付失败。商户证书为空。请联系管理员配置。", null); - } - WxCashOutQueryP wxCashOutP = generateQueryWxCashOutP(payAccount, appInfo, cashOut); - Map signMap = null; - try { - signMap = BeanUtils.toStringMap(wxCashOutP); - } catch (Exception e) { - log.error("零钱支付命令生辰: " + e.getMessage(),e); - throw new MallinkException(ErrorCode.SYS_PARAMETER_CAST_ERROR.getCode(), "零钱支付签名异常"); - } - - String signAgent = WxPayment.createSign(signMap, payAccount.getMerchantApiKey()); - signMap.put("sign", signAgent); - String response = null; - try { - response = WxPay.getTransferInfo(signMap, payAccount.getMerchantCertPath(), payAccount.getSubMchId()); - } catch (Exception e) { - log.error("零钱支付查询异常: " + e.getMessage(),e); - throw new MallinkException(ErrorCode.REFUND_ORDER_ERROR.getCode(), "微信零钱支付查询接口异常"); - } - log.info("微信零钱支付查询:" + wxCashOutP.toString() + ", response: " + response.toString()); - return getReusltFromQueryp(response,cashOut); - } - - private WxCashOutQueryP generateQueryWxCashOutP(WxPayAccount payAccount,WxAppinfo appInfo,WxCashOut cashOut) { - String noncestr = Utility.generate32UUID(); - WxCashOutQueryP wxCashOutQueryP = new WxCashOutQueryP(); - wxCashOutQueryP.setAppid(appInfo.getAppId()); - wxCashOutQueryP.setMch_id(payAccount.getSubMchId()); - wxCashOutQueryP.setNonce_str(noncestr); - wxCashOutQueryP.setPartner_trade_no(String.valueOf(cashOut.getId())); - return wxCashOutQueryP; - } - - private CashOutAdapterResult getReusltFromQueryp(String response,WxCashOut cashOut) throws MallinkException{ - Map returnMap = WxPayment.xmlToMap(response); - String result_no = returnMap.get("result_code"); - if ("SUCCESS".equals(result_no)) { - String realStatus = returnMap.get("status"); - if ("SUCCESS".equals(realStatus) || "PROCESSING".equals(realStatus)) { - String detailId = returnMap.get("detail_id"); - cashOut.setWxPayNo(detailId); - String wxPayTime = returnMap.get("transfer_time"); - cashOut.setWxPayTime(wxPayTime); - return new CashOutAdapterResult(true,EnumCashOutStatus.SUCCESS.getCode(),"微信零钱支付查询成功",returnMap); - }else if("FAILED".equals(realStatus)) { - String msg = returnMap.get("reason"); - return new CashOutAdapterResult(false,EnumCashOutStatus.FAIL.getCode(),msg,returnMap); - }else { - log.error("微信零钱支付查询失败,微信返回未知状态: " + response); - throw new MallinkException(ErrorCode.SYS_PARAMETER_CAST_ERROR.getCode(), "微信零钱支付查询失败, 微信返回未知状态:"+realStatus); - } - } else { - log.error("微信零钱支付查询失败: " + response); - String errMsg = returnMap.get("err_code_des"); - String errCode = returnMap.get("err_code"); - if ("NOT_FOUND".equals(errCode)) { - return new CashOutAdapterResult(false,EnumCashOutStatus.FAIL.getCode(),errMsg,returnMap); - } -// JSONObject errObj = errorQueryReqMap.getJSONObject(result_no); +// +// private WxCashOutP generateWxCashOutP(WxPayAccount payAccount,WxAppinfo appInfo,WxCashOut cashOut) { +// String noncestr = Utility.generate32UUID(); +// WxCashOutP wxCashOutP = new WxCashOutP(); +// wxCashOutP.setMch_appid(appInfo.getAppId()); +// wxCashOutP.setMchid(payAccount.getSubMchId()); +// wxCashOutP.setNonce_str(noncestr); +// wxCashOutP.setAmount(cashOut.getTotalFee()); +// wxCashOutP.setCheck_name("NO_CHECK"); +// wxCashOutP.setDesc("客户结算"); +// wxCashOutP.setOpenid(cashOut.getReciveOpenId()); +// wxCashOutP.setPartner_trade_no(String.valueOf(cashOut.getId())); +// return wxCashOutP; +// } +// +// private CashOutAdapterResult getReusltFromp(String response,WxCashOut cashOut) throws MallinkException{ +// Map returnMap = WxPayment.xmlToMap(response); +// String result_no = returnMap.get("result_code"); +// if ("SUCCESS".equals(result_no)) { +// log.info("微信零钱支付申请成功: " + returnMap.toString()); +// String wxPayNo = returnMap.get("payment_no"); +// String payTime = returnMap.get("payment_time"); +// cashOut.setWxPayNo(wxPayNo); +// cashOut.setWxPayTime(payTime); +// return new CashOutAdapterResult(true,EnumCashOutStatus.SUCCESS.getCode(),"微信零钱支付申请成功",returnMap); +// } else { +// log.error("微信零钱支付申请失败: " + response); +// String errMsg = ""; +// JSONObject errObj = errorRefundReqMap.getJSONObject(result_no); // if (errObj != null) { // errMsg = errObj.toJSONString(); // } else { // errMsg = returnMap.get("err_code_des"); // } - throw new MallinkException(ErrorCode.SYS_PARAMETER_CAST_ERROR.getCode(), "微信零钱支付查询失败:"+errMsg); - } - } +// return new CashOutAdapterResult(false, EnumCashOutStatus.FAIL.getCode(), errMsg, returnMap); +// } +// } +// +// @Override +// public CashOutAdapterResult queryCashOut(WxAppinfo appInfo, WxPayAccount payAccount, WxCashOut cashOut) { +// if (StringUtils.isBlank(payAccount.getMerchantCertPath())) { +// return new CashOutAdapterResult(false, EnumCashOutStatus.FAIL.getCode(), "零钱支付失败。商户证书为空。请联系管理员配置。", null); +// } +// WxCashOutQueryP wxCashOutP = generateQueryWxCashOutP(payAccount, appInfo, cashOut); +// Map signMap = null; +// try { +// signMap = BeanUtils.toStringMap(wxCashOutP); +// } catch (Exception e) { +// log.error("零钱支付命令生辰: " + e.getMessage(),e); +// throw new MallinkException(ErrorCode.SYS_PARAMETER_CAST_ERROR.getCode(), "零钱支付签名异常"); +// } +// +// String signAgent = WxPayment.createSign(signMap, payAccount.getMerchantApiKey()); +// signMap.put("sign", signAgent); +// String response = null; +// try { +// response = WxPay.getTransferInfo(signMap, payAccount.getMerchantCertPath(), payAccount.getSubMchId()); +// } catch (Exception e) { +// log.error("零钱支付查询异常: " + e.getMessage(),e); +// throw new MallinkException(ErrorCode.REFUND_ORDER_ERROR.getCode(), "微信零钱支付查询接口异常"); +// } +// log.info("微信零钱支付查询:" + wxCashOutP.toString() + ", response: " + response.toString()); +// return getReusltFromQueryp(response,cashOut); +// } +// +// private WxCashOutQueryP generateQueryWxCashOutP(WxPayAccount payAccount,WxAppinfo appInfo,WxCashOut cashOut) { +// String noncestr = Utility.generate32UUID(); +// WxCashOutQueryP wxCashOutQueryP = new WxCashOutQueryP(); +// wxCashOutQueryP.setAppid(appInfo.getAppId()); +// wxCashOutQueryP.setMch_id(payAccount.getSubMchId()); +// wxCashOutQueryP.setNonce_str(noncestr); +// wxCashOutQueryP.setPartner_trade_no(String.valueOf(cashOut.getId())); +// return wxCashOutQueryP; +// } +// +// private CashOutAdapterResult getReusltFromQueryp(String response,WxCashOut cashOut) throws MallinkException{ +// Map returnMap = WxPayment.xmlToMap(response); +// String result_no = returnMap.get("result_code"); +// if ("SUCCESS".equals(result_no)) { +// String realStatus = returnMap.get("status"); +// if ("SUCCESS".equals(realStatus) || "PROCESSING".equals(realStatus)) { +// String detailId = returnMap.get("detail_id"); +// cashOut.setWxPayNo(detailId); +// String wxPayTime = returnMap.get("transfer_time"); +// cashOut.setWxPayTime(wxPayTime); +// return new CashOutAdapterResult(true,EnumCashOutStatus.SUCCESS.getCode(),"微信零钱支付查询成功",returnMap); +// }else if("FAILED".equals(realStatus)) { +// String msg = returnMap.get("reason"); +// return new CashOutAdapterResult(false,EnumCashOutStatus.FAIL.getCode(),msg,returnMap); +// }else { +// log.error("微信零钱支付查询失败,微信返回未知状态: " + response); +// throw new MallinkException(ErrorCode.SYS_PARAMETER_CAST_ERROR.getCode(), "微信零钱支付查询失败, 微信返回未知状态:"+realStatus); +// } +// } else { +// log.error("微信零钱支付查询失败: " + response); +// String errMsg = returnMap.get("err_code_des"); +// String errCode = returnMap.get("err_code"); +// if ("NOT_FOUND".equals(errCode)) { +// return new CashOutAdapterResult(false,EnumCashOutStatus.FAIL.getCode(),errMsg,returnMap); +// } +//// JSONObject errObj = errorQueryReqMap.getJSONObject(result_no); +//// if (errObj != null) { +//// errMsg = errObj.toJSONString(); +//// } else { +//// errMsg = returnMap.get("err_code_des"); +//// } +// throw new MallinkException(ErrorCode.SYS_PARAMETER_CAST_ERROR.getCode(), "微信零钱支付查询失败:"+errMsg); +// } +// } }