@@ -2,6 +2,7 @@ package me.chanjar.weixin.mp.api; | |||||
import me.chanjar.weixin.common.exception.WxErrorException; | import me.chanjar.weixin.common.exception.WxErrorException; | ||||
import me.chanjar.weixin.mp.bean.pay.WxPayJsSDKCallback; | import me.chanjar.weixin.mp.bean.pay.WxPayJsSDKCallback; | ||||
import me.chanjar.weixin.mp.bean.pay.result.WxPayOrderCloseResult; | |||||
import me.chanjar.weixin.mp.bean.pay.request.WxEntPayRequest; | import me.chanjar.weixin.mp.bean.pay.request.WxEntPayRequest; | ||||
import me.chanjar.weixin.mp.bean.pay.request.WxPayRefundRequest; | import me.chanjar.weixin.mp.bean.pay.request.WxPayRefundRequest; | ||||
import me.chanjar.weixin.mp.bean.pay.request.WxPaySendRedpackRequest; | import me.chanjar.weixin.mp.bean.pay.request.WxPaySendRedpackRequest; | ||||
@@ -35,6 +36,22 @@ public interface WxMpPayService { | |||||
*/ | */ | ||||
WxPayOrderQueryResult queryOrder(String transactionId, String outTradeNo) throws WxErrorException; | WxPayOrderQueryResult queryOrder(String transactionId, String outTradeNo) throws WxErrorException; | ||||
/** | |||||
* <pre> | |||||
* 关闭订单 | |||||
* 应用场景 | |||||
* 以下情况需要调用关单接口: | |||||
* 1. 商户订单支付失败需要生成新单号重新发起支付,要对原订单号调用关单,避免重复支付; | |||||
* 2. 系统下单后,用户支付超时,系统退出不再受理,避免用户继续,请调用关单接口。 | |||||
* 注意:订单生成后不能马上调用关单接口,最短调用时间间隔为5分钟。 | |||||
* 接口地址:https://api.mch.weixin.qq.com/pay/closeorder | |||||
* 是否需要证书: 不需要。 | |||||
* </pre> | |||||
* @param outTradeNo 商户系统内部的订单号,当没提供transaction_id时需要传这个。 | |||||
* @throws WxErrorException | |||||
*/ | |||||
WxPayOrderCloseResult closeOrder(String outTradeNo) throws WxErrorException; | |||||
/** | /** | ||||
* 统一下单(详见http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1) | * 统一下单(详见http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1) | ||||
* 在发起微信支付前,需要调用统一下单接口,获取"预支付交易会话标识" | * 在发起微信支付前,需要调用统一下单接口,获取"预支付交易会话标识" | ||||
@@ -8,6 +8,7 @@ import me.chanjar.weixin.common.util.xml.XStreamInitializer; | |||||
import me.chanjar.weixin.mp.api.WxMpPayService; | import me.chanjar.weixin.mp.api.WxMpPayService; | ||||
import me.chanjar.weixin.mp.api.WxMpService; | import me.chanjar.weixin.mp.api.WxMpService; | ||||
import me.chanjar.weixin.mp.bean.pay.WxPayJsSDKCallback; | import me.chanjar.weixin.mp.bean.pay.WxPayJsSDKCallback; | ||||
import me.chanjar.weixin.mp.bean.pay.result.WxPayOrderCloseResult; | |||||
import me.chanjar.weixin.mp.bean.pay.request.*; | import me.chanjar.weixin.mp.bean.pay.request.*; | ||||
import me.chanjar.weixin.mp.bean.pay.result.*; | import me.chanjar.weixin.mp.bean.pay.result.*; | ||||
import org.apache.commons.codec.digest.DigestUtils; | import org.apache.commons.codec.digest.DigestUtils; | ||||
@@ -210,6 +211,39 @@ public class WxMpPayServiceImpl implements WxMpPayService { | |||||
return result; | return result; | ||||
} | } | ||||
@Override | |||||
public WxPayOrderCloseResult closeOrder(String outTradeNo) throws WxErrorException { | |||||
if (StringUtils.isBlank(outTradeNo)) { | |||||
throw new IllegalArgumentException("out_trade_no 不能为空"); | |||||
} | |||||
XStream xstream = XStreamInitializer.getInstance(); | |||||
xstream.processAnnotations(WxPayOrderCloseRequest.class); | |||||
xstream.processAnnotations(WxPayOrderCloseResult.class); | |||||
WxPayOrderCloseRequest request = new WxPayOrderCloseRequest(); | |||||
request.setOutTradeNo(StringUtils.trimToNull(outTradeNo)); | |||||
request.setAppid(this.wxMpService.getWxMpConfigStorage().getAppId()); | |||||
request.setMchId(this.wxMpService.getWxMpConfigStorage().getPartnerId()); | |||||
request.setNonceStr(System.currentTimeMillis() + ""); | |||||
String sign = this.createSign(BeanUtils.xmlBean2Map(request), | |||||
this.wxMpService.getWxMpConfigStorage().getPartnerKey()); | |||||
request.setSign(sign); | |||||
String url = PAY_BASE_URL + "/pay/closeorder"; | |||||
String responseContent = this.wxMpService.post(url, xstream.toXML(request)); | |||||
WxPayOrderCloseResult result = (WxPayOrderCloseResult) xstream.fromXML(responseContent); | |||||
if ("FAIL".equals(result.getResultCode())) { | |||||
throw new WxErrorException(WxError.newBuilder() | |||||
.setErrorMsg(result.getErrCode() + ":" + result.getErrCodeDes()) | |||||
.build()); | |||||
} | |||||
return result; | |||||
} | |||||
@Override | @Override | ||||
public WxPayUnifiedOrderResult unifiedOrder(WxPayUnifiedOrderRequest request) | public WxPayUnifiedOrderResult unifiedOrder(WxPayUnifiedOrderRequest request) | ||||
throws WxErrorException { | throws WxErrorException { | ||||
@@ -0,0 +1,36 @@ | |||||
package me.chanjar.weixin.mp.bean.pay.request; | |||||
import com.thoughtworks.xstream.annotations.XStreamAlias; | |||||
/** | |||||
* <pre> | |||||
* 关闭订单请求对象类 | |||||
* Created by Binary Wang on 2016-10-27. | |||||
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a> | |||||
* </pre> | |||||
*/ | |||||
@XStreamAlias("xml") | |||||
public class WxPayOrderCloseRequest extends WxPayBaseRequest{ | |||||
/** | |||||
* <pre> | |||||
* 商户订单号 | |||||
* out_trade_no | |||||
* 二选一 | |||||
* String(32) | |||||
* 20150806125346 | |||||
* 商户系统内部的订单号,当没提供transaction_id时需要传这个。 | |||||
* </pre> | |||||
*/ | |||||
@XStreamAlias("out_trade_no") | |||||
private String outTradeNo; | |||||
public String getOutTradeNo() { | |||||
return this.outTradeNo; | |||||
} | |||||
public void setOutTradeNo(String outTradeNo) { | |||||
this.outTradeNo = outTradeNo; | |||||
} | |||||
} |
@@ -0,0 +1,28 @@ | |||||
package me.chanjar.weixin.mp.bean.pay.result; | |||||
import com.thoughtworks.xstream.annotations.XStreamAlias; | |||||
/** | |||||
* <pre> | |||||
* 关闭订单结果对象类 | |||||
* Created by Binary Wang on 2016-10-27. | |||||
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a> | |||||
* </pre> | |||||
*/ | |||||
@XStreamAlias("xml") | |||||
public class WxPayOrderCloseResult extends WxPayBaseResult { | |||||
/** | |||||
* 业务结果描述 | |||||
*/ | |||||
@XStreamAlias("result_msg") | |||||
private String resultMsg; | |||||
public String getResultMsg() { | |||||
return this.resultMsg; | |||||
} | |||||
public void setResultMsg(String resultMsg) { | |||||
this.resultMsg = resultMsg; | |||||
} | |||||
} |
@@ -87,6 +87,15 @@ public class WxMpPayServiceImplTest { | |||||
System.err.println(this.wxService.getPayService().queryOrder(null, "11111")); | System.err.println(this.wxService.getPayService().queryOrder(null, "11111")); | ||||
} | } | ||||
/** | |||||
* Test method for {@link me.chanjar.weixin.mp.api.impl.WxMpPayServiceImpl#closeOrder(String)} . | |||||
* @throws WxErrorException | |||||
*/ | |||||
@Test | |||||
public final void testCloseOrder() throws WxErrorException { | |||||
System.err.println(this.wxService.getPayService().closeOrder("11212121")); | |||||
} | |||||
/** | /** | ||||
* Test method for {@link me.chanjar.weixin.mp.api.impl.WxMpPayServiceImpl#entPay(WxEntPayRequest, File)}. | * Test method for {@link me.chanjar.weixin.mp.api.impl.WxMpPayServiceImpl#entPay(WxEntPayRequest, File)}. | ||||
* @throws WxErrorException | * @throws WxErrorException | ||||