mirror of
https://gitee.com/binary/weixin-java-tools.git
synced 2025-04-05 17:38:05 +08:00
🆕 #1529 微信支付退款增加支持单品退款和对应查询的接口
This commit is contained in:
parent
58b261753d
commit
92c0fd698b
@ -89,9 +89,8 @@ public class WxPayRefundQueryRequest extends BaseWxPayRequest {
|
||||
&& StringUtils.isBlank(outRefundNo) && StringUtils.isBlank(refundId)) ||
|
||||
(StringUtils.isNotBlank(transactionId) && StringUtils.isNotBlank(outTradeNo)
|
||||
&& StringUtils.isNotBlank(outRefundNo) && StringUtils.isNotBlank(refundId))) {
|
||||
throw new WxPayException("transaction_id,out_trade_no,out_refund_no,refund_id 必须四选一");
|
||||
throw new WxPayException("transactionId,outRefundNo,transactionId,refundId 必须四选一");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -4,8 +4,11 @@ import com.github.binarywang.wxpay.config.WxPayConfig;
|
||||
import com.github.binarywang.wxpay.constant.WxPayConstants.RefundAccountSource;
|
||||
import com.github.binarywang.wxpay.exception.WxPayException;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
import com.thoughtworks.xstream.annotations.XStreamConverter;
|
||||
import lombok.*;
|
||||
import lombok.experimental.Accessors;
|
||||
import me.chanjar.weixin.common.annotation.Required;
|
||||
import me.chanjar.weixin.common.util.xml.XStreamCDataConverter;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
@ -26,7 +29,10 @@ import java.util.Map;
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@XStreamAlias("xml")
|
||||
@Accessors(chain = true)
|
||||
public class WxPayRefundRequest extends BaseWxPayRequest {
|
||||
private static final long serialVersionUID = 522565152886671848L;
|
||||
|
||||
private static final String[] REFUND_ACCOUNT = new String[]{
|
||||
RefundAccountSource.RECHARGE_FUNDS, RefundAccountSource.UNSETTLED_FUNDS};
|
||||
|
||||
@ -127,7 +133,6 @@ public class WxPayRefundRequest extends BaseWxPayRequest {
|
||||
* 描述:操作员帐号, 默认为商户号
|
||||
* </pre>
|
||||
*/
|
||||
//@Required
|
||||
@XStreamAlias("op_user_id")
|
||||
private String opUserId;
|
||||
/**
|
||||
@ -172,6 +177,54 @@ public class WxPayRefundRequest extends BaseWxPayRequest {
|
||||
@XStreamAlias("notify_url")
|
||||
private String notifyUrl;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 字段名:商品详情
|
||||
* 变量名:detail
|
||||
* 类型:否
|
||||
* 示例值:String(6000)
|
||||
* 退款包含的商品列表信息detail字段列表说明:
|
||||
*
|
||||
* 字段名 变量名 必填 类型 示例值 描述
|
||||
* 商品列表 goods_detail 是 String 示例见下文 商品信息,使用Json数组格式提交
|
||||
* 商品列表goods_detail字段列表说明:
|
||||
*
|
||||
* 字段名 变量名 必填 类型 示例值 描述
|
||||
* 商品编码 goods_id 是 String(32) 商品编码 由半角的大小写字母、数字、中划线、下划线中的一种或几种组成
|
||||
* 微信侧商品编码 wxpay_goods_id 否 String(32) 1001 微信支付定义的统一商品编号(没有可不传)
|
||||
* 商品名称 goods_name 否 String(256) iPhone6s 16G 商品的实际名称
|
||||
* 商品退款金额 refund_amount 是 int 528800 商品退款金额
|
||||
* 商品退货数量 refund_quantity 是 int 1 单品的退款数量
|
||||
* 商品单价 price 是 int 528800 单位为:分。如果商户有优惠,需传输商户优惠后的单价(例如:用户对一笔100元的订单使用了商场发的优惠券100-50,则活动商品的单价应为原单价-50)
|
||||
* detail字段值举例如下:
|
||||
*
|
||||
* {
|
||||
* "goods_detail": [
|
||||
* {
|
||||
* "goods_id": "商品编码",
|
||||
* "wxpay_goods_id": "1001",
|
||||
* "goods_name": "iPhone6s 16G",
|
||||
* "refund_amount": 528800,
|
||||
* "refund_quantity": 1,
|
||||
* "price": 528800
|
||||
* },
|
||||
* {
|
||||
* "goods_id": "商品编码",
|
||||
* "wxpay_goods_id": "1001",
|
||||
* "goods_name": "iPhone6s 16G",
|
||||
* "refund_amount": 528800,
|
||||
* "refund_quantity": 1,
|
||||
* "price": 608800
|
||||
* }
|
||||
* ]
|
||||
* }
|
||||
* 描述:退款包含的商品列表信息,全额退款可不传,必须按照规范上传,JSON格式
|
||||
* </pre>
|
||||
*/
|
||||
@XStreamAlias("detail")
|
||||
@XStreamConverter(value = XStreamCDataConverter.class)
|
||||
private String detail;
|
||||
|
||||
@Override
|
||||
public void checkAndSign(WxPayConfig config) throws WxPayException {
|
||||
if (StringUtils.isBlank(this.getOpUserId())) {
|
||||
|
@ -0,0 +1,117 @@
|
||||
package com.github.binarywang.wxpay.bean.result;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 营销详情 .
|
||||
*
|
||||
* @author <a href="https://github.com/binarywang">Binary Wang</a>
|
||||
* @date 2020-06-07
|
||||
*/
|
||||
@Data
|
||||
public class WxPayRefundPromotionDetail implements Serializable {
|
||||
private static final long serialVersionUID = 2197712244944584263L;
|
||||
|
||||
/**
|
||||
* 字段名:券ID
|
||||
* 变量名:promotion_id
|
||||
* 是否必填:是
|
||||
* 类型:String(32)
|
||||
* 示例例:109519
|
||||
* 描述:券或者立减优惠id
|
||||
*/
|
||||
@SerializedName("promotion_id")
|
||||
private String promotionId;
|
||||
/**
|
||||
* 字段名:优惠范围
|
||||
* 变量名:scope
|
||||
* 是否必填:是
|
||||
* 类型:String(32)
|
||||
* 示例例:SINGLE
|
||||
* 描述:GLOBAL- 全场代金券,SINGLE- 单品优惠
|
||||
*/
|
||||
@SerializedName("scope")
|
||||
private String scope;
|
||||
/**
|
||||
* 字段名:优惠类型
|
||||
* 变量名:type
|
||||
* 是否必填:是
|
||||
* 类型:String(32)
|
||||
* 示例例:DISCOUNT
|
||||
* 描述:COUPON- 代金券,需要走结算资金的充值型代金券,(境外商户券币种与支付币种一致),DISCOUNT- 优惠券,不走结算资金的免充值型优惠券,(境外商户券币种与标价币种一致
|
||||
*/
|
||||
@SerializedName("type")
|
||||
private String type;
|
||||
/**
|
||||
* 字段名:代金券退款金额
|
||||
* 变量名:refund_amount
|
||||
* 是否必填:是
|
||||
* 类型:Int
|
||||
* 示例例:100
|
||||
* 描述:代金券退款金额<=退款金额,退款金额-代金券或立减优惠退款金额为现金,说明详见代金券或立减优惠
|
||||
*/
|
||||
@SerializedName("refund_amount")
|
||||
private Integer refundAmount;
|
||||
/**
|
||||
* 字段名:商品列表
|
||||
* 变量名:goods_detail
|
||||
* 是否必填:否
|
||||
* 类型:String
|
||||
* 示例例:见下文
|
||||
* 描述:商品信息,使用Json格式
|
||||
*/
|
||||
@SerializedName("goods_detail")
|
||||
private List<GoodDetail> goodsDetails;
|
||||
|
||||
@Data
|
||||
public static class GoodDetail {
|
||||
/**
|
||||
* 字段名:商品编码
|
||||
* 变量名:goods_id
|
||||
* 是否必填:是
|
||||
* 类型:String(32)
|
||||
* 示例值:商品编码
|
||||
* 描述:由半角的大小写字母、数字、中划线、下划线中的一种或几种组成
|
||||
*/
|
||||
@SerializedName("goods_id")
|
||||
private String goodsId;
|
||||
|
||||
/**
|
||||
* 字段名:优惠退款金额
|
||||
* 变量名:refund_amount
|
||||
* 是否必填:是
|
||||
* 类型:int
|
||||
* 示例值:528800
|
||||
* 描述:优惠退款金额
|
||||
*/
|
||||
@SerializedName("refund_amount")
|
||||
private Integer refundAmount;
|
||||
|
||||
/**
|
||||
* 字段名:商品退货数量
|
||||
* 变量名:refund_quantity
|
||||
* 是否必填:是
|
||||
* 类型:int
|
||||
* 示例值:1
|
||||
* 描述:单品的退货数量
|
||||
*/
|
||||
@SerializedName("refund_quantity")
|
||||
private Integer refundQuantity;
|
||||
|
||||
/**
|
||||
* 字段名:商品单价
|
||||
* 变量名:price
|
||||
* 是否必填:是
|
||||
* 类型:int
|
||||
* 示例值:528800
|
||||
* 描述:单位为:分。如果商户有优惠,需传输商户优惠后的单价(例如:用户对一笔100元的订单使用了商场发的优惠券100-50,则活动商品的单价应为原单价-50)
|
||||
*/
|
||||
@SerializedName("price")
|
||||
private Integer price;
|
||||
|
||||
}
|
||||
}
|
@ -3,12 +3,17 @@ package com.github.binarywang.wxpay.bean.result;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.w3c.dom.Document;
|
||||
|
||||
/**
|
||||
@ -130,6 +135,34 @@ public class WxPayRefundQueryResult extends BaseWxPayResult {
|
||||
|
||||
private List<RefundRecord> refundRecords;
|
||||
|
||||
/**
|
||||
* 营销详情.
|
||||
*/
|
||||
@XStreamAlias("promotion_detail")
|
||||
private String promotionDetailString;
|
||||
|
||||
private List<WxPayRefundPromotionDetail> promotionDetails;
|
||||
|
||||
/**
|
||||
* 组装生成营销详情信息.
|
||||
*/
|
||||
public void composePromotionDetails() {
|
||||
if (StringUtils.isEmpty(this.promotionDetailString)) {
|
||||
return;
|
||||
}
|
||||
|
||||
JsonElement tmpJsonElement = new JsonParser().parse(this.promotionDetailString);
|
||||
|
||||
final List<WxPayRefundPromotionDetail> promotionDetail = WxGsonBuilder.create()
|
||||
.fromJson(tmpJsonElement.getAsJsonObject().get("promotion_detail"),
|
||||
new TypeToken<List<WxPayRefundPromotionDetail>>() {
|
||||
}.getType()
|
||||
);
|
||||
|
||||
this.setPromotionDetails(promotionDetail);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 组装生成退款记录属性的内容.
|
||||
*/
|
||||
|
@ -1,15 +1,20 @@
|
||||
package com.github.binarywang.wxpay.bean.result;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.w3c.dom.Document;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 微信支付-申请退款返回结果.
|
||||
@ -115,8 +120,35 @@ public class WxPayRefundResult extends BaseWxPayResult implements Serializable {
|
||||
@XStreamAlias("coupon_refund_fee")
|
||||
private Integer couponRefundFee;
|
||||
|
||||
/**
|
||||
* 营销详情.
|
||||
*/
|
||||
@XStreamAlias("promotion_detail")
|
||||
private String promotionDetailString;
|
||||
|
||||
private List<WxPayRefundPromotionDetail> promotionDetails;
|
||||
|
||||
private List<WxPayRefundCouponInfo> refundCoupons;
|
||||
|
||||
/**
|
||||
* 组装生成营销详情信息.
|
||||
*/
|
||||
public void composePromotionDetails() {
|
||||
if (StringUtils.isEmpty(this.promotionDetailString)) {
|
||||
return;
|
||||
}
|
||||
|
||||
JsonElement tmpJsonElement = new JsonParser().parse(this.promotionDetailString);
|
||||
|
||||
final List<WxPayRefundPromotionDetail> promotionDetail = WxGsonBuilder.create()
|
||||
.fromJson(tmpJsonElement.getAsJsonObject().get("promotion_detail"),
|
||||
new TypeToken<List<WxPayRefundPromotionDetail>>() {
|
||||
}.getType()
|
||||
);
|
||||
|
||||
this.setPromotionDetails(promotionDetail);
|
||||
}
|
||||
|
||||
/**
|
||||
* 组装生成退款代金券信息.
|
||||
*/
|
||||
|
@ -256,6 +256,33 @@ public interface WxPayService {
|
||||
*/
|
||||
WxPayRefundResult refund(WxPayRefundRequest request) throws WxPayException;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 申请退款API(支持单品).
|
||||
* 详见 https://pay.weixin.qq.com/wiki/doc/api/danpin.php?chapter=9_103&index=3
|
||||
*
|
||||
* 应用场景
|
||||
* 当交易发生之后一段时间内,由于买家或者卖家的原因需要退款时,卖家可以通过退款接口将支付款退还给买家,微信支付将在收到退款请求并且验证成功之后,按照退款规则将支付款按原路退到买家帐号上。
|
||||
*
|
||||
* 注意:
|
||||
* 1、交易时间超过一年的订单无法提交退款;
|
||||
* 2、微信支付退款支持单笔交易分多次退款,多次退款需要提交原支付订单的商户订单号和设置不同的退款单号。申请退款总金额不能超过订单金额。 一笔退款失败后重新提交,请不要更换退款单号,请使用原商户退款单号。
|
||||
* 3、请求频率限制:150qps,即每秒钟正常的申请退款请求次数不超过150次
|
||||
* 错误或无效请求频率限制:6qps,即每秒钟异常或错误的退款申请请求不超过6次
|
||||
* 4、每个支付订单的部分退款次数不能超过50次
|
||||
* 5、本接口支持单品优惠订单全额退款和单品优惠订单部分退款,推荐使用本接口,如果使用不支持单品优惠部分退款的历史接口,请看https://pay.weixin.qq.com/wiki/doc/api/jsapi_sl.php?chapter=9_4
|
||||
*
|
||||
* 接口地址
|
||||
* https://api.mch.weixin.qq.com/secapi/pay/refundv2
|
||||
* https://api2.mch.weixin.qq.com/secapi/pay/refundv2(备用域名)见跨城冗灾方案
|
||||
* </pre>
|
||||
*
|
||||
* @param request 请求对象
|
||||
* @return 退款操作结果 wx pay refund result
|
||||
* @throws WxPayException the wx pay exception
|
||||
*/
|
||||
WxPayRefundResult refundV2(WxPayRefundRequest request) throws WxPayException;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 微信支付-查询退款.
|
||||
@ -293,6 +320,29 @@ public interface WxPayService {
|
||||
*/
|
||||
WxPayRefundQueryResult refundQuery(WxPayRefundQueryRequest request) throws WxPayException;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 微信支付-查询退款API(支持单品).
|
||||
* 应用场景
|
||||
* 提交退款申请后,通过调用该接口查询退款状态。退款有一定延时,用零钱支付的退款20分钟内到账,银行卡支付的退款3个工作日后重新查询退款状态。
|
||||
* 注意:
|
||||
* 1、本接口支持查询单品优惠相关退款信息,且仅支持按微信退款单号或商户退款单号查询,若继续调用老查询退款接口,
|
||||
* 请见https://pay.weixin.qq.com/wiki/doc/api/jsapi_sl.php?chapter=9_5
|
||||
* 2、请求频率限制:300qps,即每秒钟正常的退款查询请求次数不超过300次
|
||||
* 3、错误或无效请求频率限制:6qps,即每秒钟异常或错误的退款查询请求不超过6次
|
||||
*
|
||||
* 接口地址
|
||||
* https://api.mch.weixin.qq.com/pay/refundqueryv2
|
||||
* https://api2.mch.weixin.qq.com/pay/refundqueryv2(备用域名)见跨城冗灾方案
|
||||
* 详见 https://pay.weixin.qq.com/wiki/doc/api/danpin.php?chapter=9_104&index=4
|
||||
* </pre>
|
||||
*
|
||||
* @param request 微信退款单号
|
||||
* @return 退款信息 wx pay refund query result
|
||||
* @throws WxPayException the wx pay exception
|
||||
*/
|
||||
WxPayRefundQueryResult refundQueryV2(WxPayRefundQueryRequest request) throws WxPayException;
|
||||
|
||||
/**
|
||||
* 解析支付结果通知.
|
||||
* 详见https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7
|
||||
|
@ -128,6 +128,22 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxPayRefundResult refundV2(WxPayRefundRequest request) throws WxPayException {
|
||||
request.checkAndSign(this.getConfig());
|
||||
|
||||
String url = this.getPayBaseUrl() + "/secapi/pay/refundv2";
|
||||
if (this.getConfig().isUseSandboxEnv()) {
|
||||
url = this.getConfig().getPayBaseUrl() + "/sandboxnew/pay/refundv2";
|
||||
}
|
||||
|
||||
String responseContent = this.post(url, request.toXML(), true);
|
||||
WxPayRefundResult result = BaseWxPayResult.fromXML(responseContent, WxPayRefundResult.class);
|
||||
result.composePromotionDetails();
|
||||
result.checkResult(this, request.getSignType(), true);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxPayRefundQueryResult refundQuery(String transactionId, String outTradeNo, String outRefundNo, String refundId)
|
||||
throws WxPayException {
|
||||
@ -152,6 +168,18 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxPayRefundQueryResult refundQueryV2(WxPayRefundQueryRequest request) throws WxPayException {
|
||||
request.checkAndSign(this.getConfig());
|
||||
|
||||
String url = this.getPayBaseUrl() + "/pay/refundqueryv2";
|
||||
String responseContent = this.post(url, request.toXML(), false);
|
||||
WxPayRefundQueryResult result = BaseWxPayResult.fromXML(responseContent, WxPayRefundQueryResult.class);
|
||||
result.composePromotionDetails();
|
||||
result.checkResult(this, request.getSignType(), true);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxPayOrderNotifyResult parseOrderNotifyResult(String xmlData) throws WxPayException {
|
||||
return this.parseOrderNotifyResult(xmlData, null);
|
||||
|
@ -0,0 +1,47 @@
|
||||
package com.github.binarywang.wxpay.bean.request;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author <a href="https://github.com/binarywang">Binary Wang</a>
|
||||
* @date 2020-06-07
|
||||
*/
|
||||
public class WxPayRefundRequestTest {
|
||||
|
||||
@Test
|
||||
public void testToXML() {
|
||||
WxPayRefundRequest refundRequest = new WxPayRefundRequest();
|
||||
refundRequest.setAppid("wx2421b1c4370ec43b");
|
||||
refundRequest.setMchId("10000100");
|
||||
refundRequest.setNonceStr("6cefdb308e1e2e8aabd48cf79e546a02");
|
||||
refundRequest.setNotifyUrl("https://weixin.qq.com/");
|
||||
refundRequest.setOutRefundNo("1415701182");
|
||||
refundRequest.setOutTradeNo("1415757673");
|
||||
refundRequest.setRefundFee(1);
|
||||
refundRequest.setTotalFee(1);
|
||||
refundRequest.setTransactionId("");
|
||||
refundRequest.setDetail("{\"goods_detail\":[{\"goods_id\":\"商品编码\",\"wxpay_goods_id\":\"1001\",\"goods_name\":\"iPhone6s\n" +
|
||||
"16G\",\"refund_amount\":528800,\"refund_quantity\":1,\"price\":528800},{\"goods_id\":\"商品编码\",\"wxpay_goods_id\":\"1001\",\"goods_name\":\"iPhone6s\n" +
|
||||
"16G\",\"refund_amount\"\":528800,\"refund_quantity\":1,\"price\":608800}]}");
|
||||
refundRequest.setSign("FE56DD4AA85C0EECA82C35595A69E153");
|
||||
|
||||
assertThat(refundRequest.toXML())
|
||||
.isEqualTo("<xml>\n" +
|
||||
" <appid>wx2421b1c4370ec43b</appid>\n" +
|
||||
" <mch_id>10000100</mch_id>\n" +
|
||||
" <nonce_str>6cefdb308e1e2e8aabd48cf79e546a02</nonce_str>\n" +
|
||||
" <sign>FE56DD4AA85C0EECA82C35595A69E153</sign>\n" +
|
||||
" <transaction_id></transaction_id>\n" +
|
||||
" <out_trade_no>1415757673</out_trade_no>\n" +
|
||||
" <out_refund_no>1415701182</out_refund_no>\n" +
|
||||
" <total_fee>1</total_fee>\n" +
|
||||
" <refund_fee>1</refund_fee>\n" +
|
||||
" <notify_url>https://weixin.qq.com/</notify_url>\n" +
|
||||
" <detail><![CDATA[{\"goods_detail\":[{\"goods_id\":\"商品编码\",\"wxpay_goods_id\":\"1001\",\"goods_name\":\"iPhone6s\n" +
|
||||
"16G\",\"refund_amount\":528800,\"refund_quantity\":1,\"price\":528800},{\"goods_id\":\"商品编码\",\"wxpay_goods_id\":\"1001\",\"goods_name\":\"iPhone6s\n" +
|
||||
"16G\",\"refund_amount\"\":528800,\"refund_quantity\":1,\"price\":608800}]}]]></detail>\n" +
|
||||
"</xml>");
|
||||
}
|
||||
}
|
@ -13,7 +13,6 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* @author <a href="https://github.com/binarywang">Binary Wang</a>
|
||||
*/
|
||||
public class WxPayRefundResultTest {
|
||||
|
||||
@Test
|
||||
public void testFromXML() {
|
||||
/*
|
||||
@ -49,6 +48,49 @@ public class WxPayRefundResultTest {
|
||||
assertThat(result.getRefundCoupons().get(0).getCouponRefundFee()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFromXML_danpin() {
|
||||
//样例来自:https://pay.weixin.qq.com/wiki/doc/api/danpin.php?chapter=9_103&index=3
|
||||
String xmlString = "<xml>\n" +
|
||||
"<return_code><![CDATA[SUCCESS]]></return_code>\n" +
|
||||
"<return_msg><![CDATA[OK]]></return_msg>\n" +
|
||||
"<appid><![CDATA[wx2421b1c4370ec43b]]></appid>\n" +
|
||||
"<mch_id><![CDATA[10000100]]></mch_id>\n" +
|
||||
"<nonce_str><![CDATA[NfsMFbUFpdbEhPXP]]></nonce_str>\n" +
|
||||
"<sign><![CDATA[B7274EB9F8925EB93100DD2085FA56C0]]></sign>\n" +
|
||||
"<result_code><![CDATA[SUCCESS]]></result_code>\n" +
|
||||
"<transaction_id><![CDATA[1008450740201411110005820873]]></transaction_id>\n" +
|
||||
"<out_trade_no><![CDATA[1415757673]]></out_trade_no>\n" +
|
||||
"<out_refund_no><![CDATA[1415701182]]></out_refund_no>\n" +
|
||||
"<refund_id><![CDATA[2008450740201411110000174436]]></refund_id>\n" +
|
||||
"<refund_channel><![CDATA[]]></refund_channel>\n" +
|
||||
"<total_fee>1</total_fee >\n" +
|
||||
"<refund_fee>1</refund_fee>\n" +
|
||||
"<cash_fee>1</cash_fee >\n" +
|
||||
"<cash_refund_fee>1</cash_refund_fee>\n" +
|
||||
"<promotion_detail>{\"promotion_detail\":[{\"promotion_id\":\"109519\",\"scope\":\"SINGLE\",\"type\":\"DISCOUNT\",\"refund_amount\":5,\"goods_detail\":[{\"goods_id\":\"a_goods1\",\"refund_quantity\":7,\"price\":1,\"refund_amount\":4},{\"goods_id\":\"a_goods2\",\"refund_quantity\":1,\"price\":2,\"refund_amount\":1}]}]}</promotion_detail>\n" +
|
||||
"</xml>";
|
||||
|
||||
WxPayRefundResult result = BaseWxPayResult.fromXML(xmlString, WxPayRefundResult.class);
|
||||
result.composePromotionDetails();
|
||||
assertThat(result.getPromotionDetails()).isNotEmpty();
|
||||
assertThat(result.getPromotionDetails().get(0).getPromotionId()).isEqualTo("109519");
|
||||
assertThat(result.getPromotionDetails().get(0).getRefundAmount()).isEqualTo(5);
|
||||
assertThat(result.getPromotionDetails().get(0).getScope()).isEqualTo("SINGLE");
|
||||
assertThat(result.getPromotionDetails().get(0).getType()).isEqualTo("DISCOUNT");
|
||||
|
||||
assertThat(result.getPromotionDetails().get(0).getGoodsDetails()).isNotEmpty();
|
||||
assertThat(result.getPromotionDetails().get(0).getGoodsDetails().get(0).getGoodsId()).isEqualTo("a_goods1");
|
||||
assertThat(result.getPromotionDetails().get(0).getGoodsDetails().get(0).getRefundQuantity()).isEqualTo(7);
|
||||
assertThat(result.getPromotionDetails().get(0).getGoodsDetails().get(0).getRefundAmount()).isEqualTo(4);
|
||||
assertThat(result.getPromotionDetails().get(0).getGoodsDetails().get(0).getPrice()).isEqualTo(1);
|
||||
|
||||
assertThat(result.getPromotionDetails().get(0).getGoodsDetails().get(1).getGoodsId()).isEqualTo("a_goods2");
|
||||
assertThat(result.getPromotionDetails().get(0).getGoodsDetails().get(1).getRefundQuantity()).isEqualTo(1);
|
||||
assertThat(result.getPromotionDetails().get(0).getGoodsDetails().get(1).getRefundAmount()).isEqualTo(1);
|
||||
assertThat(result.getPromotionDetails().get(0).getGoodsDetails().get(1).getPrice()).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFromXMLFastMode() {
|
||||
/*
|
||||
|
@ -315,6 +315,18 @@ public class BaseWxPayServiceImplTest {
|
||||
log.info(result.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRefundV2() throws WxPayException {
|
||||
WxPayRefundResult result = this.payService.refundV2(
|
||||
WxPayRefundRequest.newBuilder()
|
||||
.outRefundNo("aaa")
|
||||
.outTradeNo("1111")
|
||||
.totalFee(1222)
|
||||
.refundFee(111)
|
||||
.build());
|
||||
log.info(result.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link WxPayService#refundQuery(String, String, String, String)} .
|
||||
*
|
||||
@ -341,6 +353,11 @@ public class BaseWxPayServiceImplTest {
|
||||
log.info(result.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRefundQueryV2() throws WxPayException {
|
||||
this.payService.refundQueryV2(WxPayRefundQueryRequest.newBuilder().outRefundNo("1").build());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test parse refund notify result.
|
||||
*
|
||||
@ -686,4 +703,5 @@ public class BaseWxPayServiceImplTest {
|
||||
assertThat(result).isNotNull();
|
||||
System.out.println(result);
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user