diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/PartnerTransactionsCloseRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/PartnerTransactionsCloseRequest.java new file mode 100644 index 0000000000..a98d0c69e7 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/PartnerTransactionsCloseRequest.java @@ -0,0 +1,61 @@ +package com.github.binarywang.wxpay.bean.ecommerce; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * 关闭普通订单请求 + * @author: f00lish + * @date: 2020/12/09 + */ +@Data +@NoArgsConstructor +public class PartnerTransactionsCloseRequest implements Serializable { + + private static final long serialVersionUID = -7602636370950088329L; + + /** + *
+ * 字段名:服务商户号 + * 变量名:sp_mchid + * 是否必填:是 + * 类型:string(32) + * 描述: + * 服务商户号,由微信支付生成并下发 + * 示例值:1230000109 + *+ */ + @SerializedName(value = "sp_mchid") + private String spMchid; + + /** + *
+ * 字段名:二级商户号 + * 变量名:sub_mchid + * 是否必填:是 + * 类型:string(32) + * 描述: + * 二级商户的商户号,有微信支付生成并下发。 + * 示例值:1900000109 + *+ */ + @SerializedName(value = "sub_mchid") + private String subMchid; + + /** + *
+ * 字段名:商户订单号 + * 变量名:out_trade_no + * 是否必填:是 + * 类型:string(32) + * 描述: + * 商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一,详见【商户订单号】。 + * 特殊规则:最小字符长度为6 + * 示例值:1217752501201407033233368018 + *+ */ + private transient String outTradeNo; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/EcommerceService.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/EcommerceService.java index 91c58e7ac3..cdca944626 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/EcommerceService.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/EcommerceService.java @@ -166,6 +166,17 @@ public interface EcommerceService { */ PartnerTransactionsResult queryPartnerTransactions(PartnerTransactionsQueryRequest request) throws WxPayException; + /** + *
+ * 关闭普通订单API + * 文档地址: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/e_transactions/chapter3_6.shtml + *+ * + * @param request 关闭普通订单请求 + * @throws WxPayException the wx pay exception + */ + void closePartnerTransactions(PartnerTransactionsCloseRequest request) throws WxPayException; + /** *
* 服务商账户实时余额 diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/EcommerceServiceImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/EcommerceServiceImpl.java index 58a02d8ff8..4feaaab01f 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/EcommerceServiceImpl.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/EcommerceServiceImpl.java @@ -149,6 +149,12 @@ public PartnerTransactionsResult queryPartnerTransactions(PartnerTransactionsQue return GSON.fromJson(response, PartnerTransactionsResult.class); } + @Override + public void closePartnerTransactions(PartnerTransactionsCloseRequest request) throws WxPayException { + String url = String.format("%s/v3/pay/partner/transactions/out-trade-no/%s/close", this.payService.getPayBaseUrl(), request.getOutTradeNo()); + String response = this.payService.postV3(url, GSON.toJson(request)); + } + @Override public FundBalanceResult spNowBalance(SpAccountTypeEnum accountType) throws WxPayException { String url = String.format("%s/v3/merchant/fund/balance/%s", this.payService.getPayBaseUrl(), accountType); diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceApacheHttpImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceApacheHttpImpl.java index 6b9adf289c..523c9b2470 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceApacheHttpImpl.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceApacheHttpImpl.java @@ -2,6 +2,7 @@ import com.github.binarywang.wxpay.bean.WxPayApiData; import com.github.binarywang.wxpay.exception.WxPayException; +import com.google.gson.JsonElement; import com.google.gson.JsonObject; import me.chanjar.weixin.common.util.json.GsonParser; import org.apache.commons.lang3.StringUtils; @@ -99,18 +100,24 @@ public String postV3(String url, String requestStr) throws WxPayException { try (CloseableHttpResponse response = httpClient.execute(httpPost)) { //v3已经改为通过状态码判断200 204 成功 int statusCode = response.getStatusLine().getStatusCode(); - String responseString = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); + //post方法有可能会没有返回值的情况 + String responseString; + if (response.getEntity() == null) { + responseString = null; + }else { + responseString = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); + } if (HttpStatus.SC_OK == statusCode || HttpStatus.SC_NO_CONTENT == statusCode) { this.log.info("\n【请求地址】:{}\n【请求数据】:{}\n【响应数据】:{}", url, requestStr, responseString); return responseString; } else { //有错误提示信息返回 JsonObject jsonObject = GsonParser.parse(responseString); - throw new WxPayException(jsonObject.get("message").getAsString()); + throw convertException(jsonObject); } } catch (Exception e) { this.log.error("\n【请求地址】:{}\n【请求数据】:{}\n【异常信息】:{}", url, requestStr, e.getMessage()); - throw new WxPayException(e.getMessage(), e); + throw (e instanceof WxPayException) ? (WxPayException)e : new WxPayException(e.getMessage(), e); } finally { httpPost.releaseConnection(); } @@ -141,12 +148,12 @@ public String postV3WithWechatpaySerial(String url, String requestStr) throws Wx } else { //有错误提示信息返回 JsonObject jsonObject = GsonParser.parse(responseString); - throw new WxPayException(jsonObject.get("message").getAsString()); + throw convertException(jsonObject); } } catch (Exception e) { this.log.error("\n【请求地址】:{}\n【请求数据】:{}\n【异常信息】:{}", url, requestStr, e.getMessage()); e.printStackTrace(); - throw new WxPayException(e.getMessage(), e); + throw (e instanceof WxPayException) ? (WxPayException)e : new WxPayException(e.getMessage(), e); } finally { httpPost.releaseConnection(); } @@ -165,18 +172,24 @@ public String postV3(String url, HttpPost httpPost) throws WxPayException { try (CloseableHttpResponse response = httpClient.execute(httpPost)) { //v3已经改为通过状态码判断200 204 成功 int statusCode = response.getStatusLine().getStatusCode(); - String responseString = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); + //post方法有可能会没有返回值的情况 + String responseString; + if (response.getEntity() == null) { + responseString = null; + }else { + responseString = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); + } if (HttpStatus.SC_OK == statusCode || HttpStatus.SC_NO_CONTENT == statusCode) { this.log.info("\n【请求地址】:{}\n【响应数据】:{}", url, responseString); return responseString; } else { //有错误提示信息返回 JsonObject jsonObject = GsonParser.parse(responseString); - throw new WxPayException(jsonObject.get("message").getAsString()); + throw convertException(jsonObject); } } catch (Exception e) { this.log.error("\n【请求地址】:{}\n【异常信息】:{}", url, e.getMessage()); - throw new WxPayException(e.getMessage(), e); + throw (e instanceof WxPayException) ? (WxPayException)e : new WxPayException(e.getMessage(), e); } finally { httpPost.releaseConnection(); } @@ -198,11 +211,11 @@ public String getV3(URI url) throws WxPayException { } else { //有错误提示信息返回 JsonObject jsonObject = GsonParser.parse(responseString); - throw new WxPayException(jsonObject.get("message").getAsString()); + throw convertException(jsonObject); } } catch (Exception e) { this.log.error("\n【请求地址】:{}\n【异常信息】:{}", url, e.getMessage()); - throw new WxPayException(e.getMessage(), e); + throw (e instanceof WxPayException) ? (WxPayException)e : new WxPayException(e.getMessage(), e); } finally { httpGet.releaseConnection(); } @@ -223,11 +236,11 @@ public InputStream downloadV3(URI url) throws WxPayException { //有错误提示信息返回 String responseString = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); JsonObject jsonObject = GsonParser.parse(responseString); - throw new WxPayException(jsonObject.get("message").getAsString()); + throw convertException(jsonObject); } } catch (Exception e) { this.log.error("\n【请求地址】:{}\n【异常信息】:{}", url, e.getMessage()); - throw new WxPayException(e.getMessage(), e); + throw (e instanceof WxPayException) ? (WxPayException)e : new WxPayException(e.getMessage(), e); } finally { httpGet.releaseConnection(); } @@ -291,4 +304,16 @@ private void initSSLContext(HttpClientBuilder httpClientBuilder) throws WxPayExc httpClientBuilder.setSSLSocketFactory(connectionSocketFactory); } + + private WxPayException convertException(JsonObject jsonObject) { + //todo 这里考虑使用新的适用于V3的异常 + JsonElement codeElement = jsonObject.get("code"); + String code = codeElement == null ? null : codeElement.getAsString(); + String message = jsonObject.get("message").getAsString(); + WxPayException wxPayException = new WxPayException(message); + wxPayException.setErrCode(code); + wxPayException.setErrCodeDes(message); + return wxPayException; + } + }