根据《微信商户平台文档》修缮Pay3Api类 & mp-server新增客服创建、关闭、转接会话的事件
This commit is contained in:
parent
a40ff51cd6
commit
e4e05e5370
@ -193,4 +193,10 @@
|
|||||||
+ **weixin-mp**: 新增素材管理多个接口
|
+ **weixin-mp**: 新增素材管理多个接口
|
||||||
|
|
||||||
+ **weixin-mp**: 新增多客服会话管理多个接口
|
+ **weixin-mp**: 新增多客服会话管理多个接口
|
||||||
|
|
||||||
|
* 2015-03-25
|
||||||
|
|
||||||
|
+ **weixin-mp**: 根据《微信商户平台文档》修缮[Pay3Api](./weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/api/Pay3Api.java)类
|
||||||
|
|
||||||
|
+ **weixin-mp**: 新增客服创建、关闭、转接会话事件
|
||||||
|
|
||||||
@ -10,7 +10,7 @@ weixin4j
|
|||||||
|
|
||||||
`公众平台API封装`
|
`公众平台API封装`
|
||||||
|
|
||||||
`微信支付(公众号)`
|
`微信支付(刷卡/扫码/公众号)`
|
||||||
|
|
||||||
`netty服务器&消息分发`
|
`netty服务器&消息分发`
|
||||||
|
|
||||||
@ -71,6 +71,8 @@ netty的代码没有放到maven中心仓库,也没什么意义,因为最终需
|
|||||||
|
|
||||||
接下来
|
接下来
|
||||||
------
|
------
|
||||||
|
* 代金券 & 红包接口
|
||||||
|
|
||||||
* 公众号服务应用
|
* 公众号服务应用
|
||||||
|
|
||||||
* 企业号第三方应用
|
* 企业号第三方应用
|
||||||
|
|||||||
@ -188,4 +188,10 @@ weixin4j-mp
|
|||||||
|
|
||||||
+ **weixin-mp-api**: 新增素材管理多个接口
|
+ **weixin-mp-api**: 新增素材管理多个接口
|
||||||
|
|
||||||
+ **weixin-mp-api**: 新增多客服会话管理多个接口
|
+ **weixin-mp-api**: 新增多客服会话管理多个接口
|
||||||
|
|
||||||
|
* 2015-03-25
|
||||||
|
|
||||||
|
+ **weixin-mp-api**: 根据《微信商户平台文档》修缮[Pay3Api](./weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/api/Pay3Api.java)类
|
||||||
|
|
||||||
|
+ **weixin-mp-server**: 新增客服创建、关闭、转接会话事件
|
||||||
@ -167,4 +167,8 @@ weixin.properties说明
|
|||||||
|
|
||||||
+ 新增素材管理多个接口
|
+ 新增素材管理多个接口
|
||||||
|
|
||||||
+ 新增多客服会话管理多个接口
|
+ 新增多客服会话管理多个接口
|
||||||
|
|
||||||
|
* 2015-03-25
|
||||||
|
|
||||||
|
+ 根据《微信商户平台文档》修缮[Pay3Api](./weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/api/Pay3Api.java)类
|
||||||
@ -12,6 +12,7 @@ import com.foxinmy.weixin4j.mp.api.Pay3Api;
|
|||||||
import com.foxinmy.weixin4j.mp.api.PayApi;
|
import com.foxinmy.weixin4j.mp.api.PayApi;
|
||||||
import com.foxinmy.weixin4j.mp.payment.v3.ApiResult;
|
import com.foxinmy.weixin4j.mp.payment.v3.ApiResult;
|
||||||
import com.foxinmy.weixin4j.mp.type.BillType;
|
import com.foxinmy.weixin4j.mp.type.BillType;
|
||||||
|
import com.foxinmy.weixin4j.mp.type.CurrencyType;
|
||||||
import com.foxinmy.weixin4j.mp.type.IdQuery;
|
import com.foxinmy.weixin4j.mp.type.IdQuery;
|
||||||
import com.foxinmy.weixin4j.mp.type.IdType;
|
import com.foxinmy.weixin4j.mp.type.IdType;
|
||||||
import com.foxinmy.weixin4j.mp.type.RefundType;
|
import com.foxinmy.weixin4j.mp.type.RefundType;
|
||||||
@ -30,6 +31,7 @@ import com.foxinmy.weixin4j.util.ConfigUtil;
|
|||||||
* @since JDK 1.7
|
* @since JDK 1.7
|
||||||
* @see com.foxinmy.weixin4j.mp.api.Pay2Api
|
* @see com.foxinmy.weixin4j.mp.api.Pay2Api
|
||||||
* @see com.foxinmy.weixin4j.mp.api.Pay3Api
|
* @see com.foxinmy.weixin4j.mp.api.Pay3Api
|
||||||
|
* @see <a href="http://pay.weixin.qq.com/wiki/doc/api/index.html">商户平台支付API</a>
|
||||||
*/
|
*/
|
||||||
public class WeixinPayProxy {
|
public class WeixinPayProxy {
|
||||||
private final PayApi payApi;
|
private final PayApi payApi;
|
||||||
@ -122,6 +124,10 @@ public class WeixinPayProxy {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* V3订单查询
|
* V3订单查询
|
||||||
|
* <p>
|
||||||
|
* 当商户后台、网络、服务器等出现异常,商户系统最终未接收到支付通知;</br> 调用支付接口后,返回系统错误或未知交易状态情况;</br>
|
||||||
|
* 调用被扫支付API,返回USERPAYING的状态;</br> 调用关单或撤销接口API之前,需确认支付状态;
|
||||||
|
* </P>
|
||||||
*
|
*
|
||||||
* @param idQuery
|
* @param idQuery
|
||||||
* 商户系统内部的订单号, transaction_id、out_trade_no 二 选一,如果同时存在优先级:
|
* 商户系统内部的订单号, transaction_id、out_trade_no 二 选一,如果同时存在优先级:
|
||||||
@ -130,6 +136,8 @@ public class WeixinPayProxy {
|
|||||||
* @see com.foxinmy.weixin4j.mp.payment.v3.Order
|
* @see com.foxinmy.weixin4j.mp.payment.v3.Order
|
||||||
* @see com.foxinmy.weixin4j.mp.api.PayApi
|
* @see com.foxinmy.weixin4j.mp.api.PayApi
|
||||||
* @see com.foxinmy.weixin4j.mp.api.Pay3Api
|
* @see com.foxinmy.weixin4j.mp.api.Pay3Api
|
||||||
|
* @see <a
|
||||||
|
* href="http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_2">订单查询API</a>
|
||||||
* @return 订单详情
|
* @return 订单详情
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
*/
|
*/
|
||||||
@ -253,9 +261,14 @@ public class WeixinPayProxy {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* V3申请退款(请求需要双向证书)</br>
|
* V3申请退款(请求需要双向证书)</br>
|
||||||
|
* <p>
|
||||||
|
* 当交易发生之后一段时间内,由于买家或者卖家的原因需要退款时,卖家可以通过退款接口将支付款退还给买家,微信支付将在收到退款请求并且验证成功之后,
|
||||||
|
* 按照退款规则将支付款按原路退到买家帐号上。
|
||||||
|
* </p>
|
||||||
* <p style="color:red">
|
* <p style="color:red">
|
||||||
* 交易时间超过 1 年的订单无法提交退款; </br> 支持部分退款,部分退需要设置相同的订单号和不同的 out_refund_no。一笔退款失
|
* 1.交易时间超过半年的订单无法提交退款;
|
||||||
* 败后重新提交,要采用原来的 out_refund_no。总退款金额不能超过用户实际支付金额。</br>
|
* 2.微信支付退款支持单笔交易分多次退款,多次退款需要提交原支付订单的商户订单号和设置不同的退款单号。一笔退款失败后重新提交
|
||||||
|
* ,要采用原来的退款单号。总退款金额不能超过用户实际支付金额。
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param caFile
|
* @param caFile
|
||||||
@ -269,6 +282,8 @@ public class WeixinPayProxy {
|
|||||||
* 订单总金额,单位为元
|
* 订单总金额,单位为元
|
||||||
* @param refundFee
|
* @param refundFee
|
||||||
* 退款总金额,单位为元,可以做部分退款
|
* 退款总金额,单位为元,可以做部分退款
|
||||||
|
* @param refundFeeType
|
||||||
|
* 货币类型,符合ISO 4217标准的三位字母代码,默认人民币:CNY
|
||||||
* @param opUserId
|
* @param opUserId
|
||||||
* 操作员帐号, 默认为商户号
|
* 操作员帐号, 默认为商户号
|
||||||
*
|
*
|
||||||
@ -276,31 +291,37 @@ public class WeixinPayProxy {
|
|||||||
* @see com.foxinmy.weixin4j.mp.payment.v3.RefundResult
|
* @see com.foxinmy.weixin4j.mp.payment.v3.RefundResult
|
||||||
* @see com.foxinmy.weixin4j.mp.api.PayApi
|
* @see com.foxinmy.weixin4j.mp.api.PayApi
|
||||||
* @see com.foxinmy.weixin4j.mp.api.Pay3Api
|
* @see com.foxinmy.weixin4j.mp.api.Pay3Api
|
||||||
* @since V3
|
* @see <a
|
||||||
|
* href="http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4">申请退款API</a>
|
||||||
|
* @since V3 TODO
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
*/
|
*/
|
||||||
public com.foxinmy.weixin4j.mp.payment.v3.RefundResult refundV3(
|
public com.foxinmy.weixin4j.mp.payment.v3.RefundResult refundV3(
|
||||||
File caFile, IdQuery idQuery, String outRefundNo, double totalFee,
|
File caFile, IdQuery idQuery, String outRefundNo, double totalFee,
|
||||||
double refundFee, String opUserId) throws WeixinException {
|
double refundFee, CurrencyType refundFeeType, String opUserId)
|
||||||
|
throws WeixinException {
|
||||||
return pay3Api.refund(caFile, idQuery, outRefundNo, totalFee,
|
return pay3Api.refund(caFile, idQuery, outRefundNo, totalFee,
|
||||||
refundFee, opUserId);
|
refundFee, refundFeeType, opUserId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* V3退款申请采用properties中配置的ca文件
|
* V3退款申请采用properties中配置的ca文件
|
||||||
*
|
*
|
||||||
* @see {@link com.foxinmy.weixin4j.mp.WeixinPayProxy#refundV3(File, IdQuery, String, double, double, String)}
|
* @see {@link com.foxinmy.weixin4j.mp.WeixinPayProxy#refundV3(File, IdQuery, String, double, double,CurrencyType, String)}
|
||||||
*/
|
*/
|
||||||
public com.foxinmy.weixin4j.mp.payment.v3.RefundResult refundV3(
|
public com.foxinmy.weixin4j.mp.payment.v3.RefundResult refundV3(
|
||||||
IdQuery idQuery, String outRefundNo, double totalFee,
|
IdQuery idQuery, String outRefundNo, double totalFee,
|
||||||
double refundFee, String opUserId) throws WeixinException {
|
double refundFee, String opUserId) throws WeixinException {
|
||||||
File caFile = new File(ConfigUtil.getClassPathValue("ca_file"));
|
File caFile = new File(ConfigUtil.getClassPathValue("ca_file"));
|
||||||
return pay3Api.refund(caFile, idQuery, outRefundNo, totalFee,
|
return pay3Api.refund(caFile, idQuery, outRefundNo, totalFee,
|
||||||
refundFee, opUserId);
|
refundFee, CurrencyType.CNY, opUserId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* V3退款查询</br> 退款有一定延时,用零钱支付的退款20分钟内到账,银行卡支付的退款 3 个工作日后重新查询退款状态
|
* V3退款查询
|
||||||
|
* <p>
|
||||||
|
* 提交退款申请后,通过调用该接口查询退款状态。退款有一定延时,用零钱支付的退款20分钟内到账,银行卡支付的退款3个工作日后重新查询退款状态。
|
||||||
|
* </p>
|
||||||
*
|
*
|
||||||
* @param idQuery
|
* @param idQuery
|
||||||
* 单号 refund_id、out_refund_no、 out_trade_no 、 transaction_id
|
* 单号 refund_id、out_refund_no、 out_trade_no 、 transaction_id
|
||||||
@ -310,6 +331,8 @@ public class WeixinPayProxy {
|
|||||||
* @see com.foxinmy.weixin4j.mp.api.PayApi
|
* @see com.foxinmy.weixin4j.mp.api.PayApi
|
||||||
* @see com.foxinmy.weixin4j.mp.api.Pay3Api
|
* @see com.foxinmy.weixin4j.mp.api.Pay3Api
|
||||||
* @see com.foxinmy.weixin4j.mp.payment.v3.RefundRecord
|
* @see com.foxinmy.weixin4j.mp.payment.v3.RefundRecord
|
||||||
|
* @see <a
|
||||||
|
* href="http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_5">退款查询API</a>
|
||||||
* @since V3
|
* @since V3
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
*/
|
*/
|
||||||
@ -333,6 +356,8 @@ public class WeixinPayProxy {
|
|||||||
* @return excel表格
|
* @return excel表格
|
||||||
* @since V2 & V3
|
* @since V2 & V3
|
||||||
* @see com.foxinmy.weixin4j.mp.api.PayApi
|
* @see com.foxinmy.weixin4j.mp.api.PayApi
|
||||||
|
* @see <a
|
||||||
|
* href="http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_6">下载对账单API</a>
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
*/
|
*/
|
||||||
public File downloadbill(Date billDate, BillType billType)
|
public File downloadbill(Date billDate, BillType billType)
|
||||||
@ -378,8 +403,11 @@ public class WeixinPayProxy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 关闭订单</br> 当订单支付失败,调用关单接口后用新订单号重新发起支付,如果关单失败,返回已完
|
* 关闭订单
|
||||||
* 成支付请按正常支付处理。如果出现银行掉单,调用关单成功后,微信后台会主动发起退款。
|
* <p>
|
||||||
|
* 商户订单支付失败需要生成新单号重新发起支付,要对原订单号调用关单,避免重复支付;系统下单后,用户支付超时,系统退出不再受理,避免用户继续
|
||||||
|
* ,请调用关单接口,如果关单失败,返回已完 成支付请按正常支付处理。如果出现银行掉单,调用关单成功后,微信后台会主动发起退款。
|
||||||
|
* </p>
|
||||||
*
|
*
|
||||||
* @param outTradeNo
|
* @param outTradeNo
|
||||||
* 商户系统内部的订单号
|
* 商户系统内部的订单号
|
||||||
@ -388,13 +416,16 @@ public class WeixinPayProxy {
|
|||||||
* @see com.foxinmy.weixin4j.mp.api.Pay3Api
|
* @see com.foxinmy.weixin4j.mp.api.Pay3Api
|
||||||
* @since V3
|
* @since V3
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
|
* @see <a
|
||||||
|
* href="http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_3">关闭订单API</a>
|
||||||
*/
|
*/
|
||||||
public ApiResult closeOrder(String outTradeNo) throws WeixinException {
|
public ApiResult closeOrder(String outTradeNo) throws WeixinException {
|
||||||
return payApi.closeOrder(outTradeNo);
|
return payApi.closeOrder(outTradeNo);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* native支付URL转短链接
|
* native支付URL转短链接:用于扫码原生支付模式一中的二维码链接转成短链接(weixin://wxpay/s/XXXXXX),减小二维码数据量
|
||||||
|
* ,提升扫描速度和精确度。
|
||||||
*
|
*
|
||||||
* @param url
|
* @param url
|
||||||
* 具有native标识的支付URL
|
* 具有native标识的支付URL
|
||||||
@ -402,6 +433,8 @@ public class WeixinPayProxy {
|
|||||||
* @see com.foxinmy.weixin4j.mp.api.PayApi
|
* @see com.foxinmy.weixin4j.mp.api.PayApi
|
||||||
* @see com.foxinmy.weixin4j.mp.api.Pay2Api
|
* @see com.foxinmy.weixin4j.mp.api.Pay2Api
|
||||||
* @see com.foxinmy.weixin4j.mp.api.Pay3Api
|
* @see com.foxinmy.weixin4j.mp.api.Pay3Api
|
||||||
|
* @see <a
|
||||||
|
* href="http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_9">转换短链接API</a>
|
||||||
* @since V2 & V3
|
* @since V2 & V3
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
*/
|
*/
|
||||||
@ -428,6 +461,8 @@ public class WeixinPayProxy {
|
|||||||
* @return 处理结果
|
* @return 处理结果
|
||||||
* @see com.foxinmy.weixin4j.mp.api.PayApi
|
* @see com.foxinmy.weixin4j.mp.api.PayApi
|
||||||
* @see com.foxinmy.weixin4j.mp.api.Pay3Api
|
* @see com.foxinmy.weixin4j.mp.api.Pay3Api
|
||||||
|
* @see <a
|
||||||
|
* href="http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_8">接口测试上报API</a>
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
*/
|
*/
|
||||||
public XmlResult interfaceReport(String interfaceUrl, int executeTime,
|
public XmlResult interfaceReport(String interfaceUrl, int executeTime,
|
||||||
|
|||||||
@ -39,7 +39,7 @@ import com.foxinmy.weixin4j.http.SSLHttpRequest;
|
|||||||
import com.foxinmy.weixin4j.model.Token;
|
import com.foxinmy.weixin4j.model.Token;
|
||||||
import com.foxinmy.weixin4j.model.WeixinMpAccount;
|
import com.foxinmy.weixin4j.model.WeixinMpAccount;
|
||||||
import com.foxinmy.weixin4j.mp.payment.PayUtil;
|
import com.foxinmy.weixin4j.mp.payment.PayUtil;
|
||||||
import com.foxinmy.weixin4j.mp.payment.RefundConverter;
|
import com.foxinmy.weixin4j.mp.payment.conver.RefundConverter;
|
||||||
import com.foxinmy.weixin4j.mp.payment.v2.Order;
|
import com.foxinmy.weixin4j.mp.payment.v2.Order;
|
||||||
import com.foxinmy.weixin4j.mp.payment.v2.RefundRecord;
|
import com.foxinmy.weixin4j.mp.payment.v2.RefundRecord;
|
||||||
import com.foxinmy.weixin4j.mp.payment.v2.RefundResult;
|
import com.foxinmy.weixin4j.mp.payment.v2.RefundResult;
|
||||||
|
|||||||
@ -30,12 +30,14 @@ import com.foxinmy.weixin4j.http.SSLHttpRequest;
|
|||||||
import com.foxinmy.weixin4j.http.XmlResult;
|
import com.foxinmy.weixin4j.http.XmlResult;
|
||||||
import com.foxinmy.weixin4j.model.WeixinMpAccount;
|
import com.foxinmy.weixin4j.model.WeixinMpAccount;
|
||||||
import com.foxinmy.weixin4j.mp.payment.PayUtil;
|
import com.foxinmy.weixin4j.mp.payment.PayUtil;
|
||||||
import com.foxinmy.weixin4j.mp.payment.RefundConverter;
|
import com.foxinmy.weixin4j.mp.payment.conver.CouponConverter;
|
||||||
|
import com.foxinmy.weixin4j.mp.payment.conver.RefundConverter;
|
||||||
import com.foxinmy.weixin4j.mp.payment.v3.ApiResult;
|
import com.foxinmy.weixin4j.mp.payment.v3.ApiResult;
|
||||||
import com.foxinmy.weixin4j.mp.payment.v3.Order;
|
import com.foxinmy.weixin4j.mp.payment.v3.Order;
|
||||||
import com.foxinmy.weixin4j.mp.payment.v3.RefundRecord;
|
import com.foxinmy.weixin4j.mp.payment.v3.RefundRecord;
|
||||||
import com.foxinmy.weixin4j.mp.payment.v3.RefundResult;
|
import com.foxinmy.weixin4j.mp.payment.v3.RefundResult;
|
||||||
import com.foxinmy.weixin4j.mp.type.BillType;
|
import com.foxinmy.weixin4j.mp.type.BillType;
|
||||||
|
import com.foxinmy.weixin4j.mp.type.CurrencyType;
|
||||||
import com.foxinmy.weixin4j.mp.type.IdQuery;
|
import com.foxinmy.weixin4j.mp.type.IdQuery;
|
||||||
import com.foxinmy.weixin4j.mp.type.IdType;
|
import com.foxinmy.weixin4j.mp.type.IdType;
|
||||||
import com.foxinmy.weixin4j.mp.util.ExcelUtil;
|
import com.foxinmy.weixin4j.mp.util.ExcelUtil;
|
||||||
@ -51,7 +53,7 @@ import com.foxinmy.weixin4j.util.RandomUtil;
|
|||||||
* @author jy
|
* @author jy
|
||||||
* @date 2014年10月28日
|
* @date 2014年10月28日
|
||||||
* @since JDK 1.7
|
* @since JDK 1.7
|
||||||
* @see
|
* @see <a href="http://pay.weixin.qq.com/wiki/doc/api/jsapi.php">公众号支付API</a>
|
||||||
*/
|
*/
|
||||||
public class Pay3Api extends PayApi {
|
public class Pay3Api extends PayApi {
|
||||||
|
|
||||||
@ -61,12 +63,18 @@ public class Pay3Api extends PayApi {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 订单查询
|
* 订单查询
|
||||||
|
* <p>
|
||||||
|
* 当商户后台、网络、服务器等出现异常,商户系统最终未接收到支付通知;</br> 调用支付接口后,返回系统错误或未知交易状态情况;</br>
|
||||||
|
* 调用被扫支付API,返回USERPAYING的状态;</br> 调用关单或撤销接口API之前,需确认支付状态;
|
||||||
|
* </P>
|
||||||
*
|
*
|
||||||
* @param idQuery
|
* @param idQuery
|
||||||
* 商户系统内部的订单号, transaction_id、out_trade_no 二 选一,如果同时存在优先级:
|
* 商户系统内部的订单号, transaction_id、out_trade_no 二 选一,如果同时存在优先级:
|
||||||
* transaction_id> out_trade_no
|
* transaction_id> out_trade_no
|
||||||
* @return 订单信息
|
* @return 订单信息
|
||||||
* @see com.foxinmy.weixin4j.mp.payment.v3.Order
|
* @see com.foxinmy.weixin4j.mp.payment.v3.Order
|
||||||
|
* @see <a
|
||||||
|
* href="http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_2">订单查询API</a>
|
||||||
* @since V3
|
* @since V3
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
*/
|
*/
|
||||||
@ -77,15 +85,19 @@ public class Pay3Api extends PayApi {
|
|||||||
String param = map2xml(map);
|
String param = map2xml(map);
|
||||||
String orderquery_uri = getRequestUri("orderquery_v3_uri");
|
String orderquery_uri = getRequestUri("orderquery_v3_uri");
|
||||||
Response response = request.post(orderquery_uri, param);
|
Response response = request.post(orderquery_uri, param);
|
||||||
return response.getAsObject(new TypeReference<Order>() {
|
return CouponConverter.fromXML(response.getAsString(), Order.class);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 申请退款(请求需要双向证书)</br>
|
* 申请退款(请求需要双向证书)
|
||||||
|
* <p>
|
||||||
|
* 当交易发生之后一段时间内,由于买家或者卖家的原因需要退款时,卖家可以通过退款接口将支付款退还给买家,微信支付将在收到退款请求并且验证成功之后,
|
||||||
|
* 按照退款规则将支付款按原路退到买家帐号上。
|
||||||
|
* </p>
|
||||||
* <p style="color:red">
|
* <p style="color:red">
|
||||||
* 交易时间超过 1 年的订单无法提交退款; </br> 支持部分退款,部分退需要设置相同的订单号和不同的 out_refund_no。一笔退款失
|
* 1.交易时间超过半年的订单无法提交退款;
|
||||||
* 败后重新提交,要采用原来的 out_refund_no。总退款金额不能超过用户实际支付金额。</br>
|
* 2.微信支付退款支持单笔交易分多次退款,多次退款需要提交原支付订单的商户订单号和设置不同的退款单号。一笔退款失败后重新提交
|
||||||
|
* ,要采用原来的退款单号。总退款金额不能超过用户实际支付金额。
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param caFile
|
* @param caFile
|
||||||
@ -104,6 +116,8 @@ public class Pay3Api extends PayApi {
|
|||||||
*
|
*
|
||||||
* @return 退款申请结果
|
* @return 退款申请结果
|
||||||
* @see com.foxinmy.weixin4j.mp.payment.v3.RefundResult
|
* @see com.foxinmy.weixin4j.mp.payment.v3.RefundResult
|
||||||
|
* @see <a
|
||||||
|
* href="http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4">申请退款API</a>
|
||||||
* @since V3
|
* @since V3
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
*/
|
*/
|
||||||
@ -147,15 +161,15 @@ public class Pay3Api extends PayApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return response.getAsObject(new TypeReference<RefundResult>() {
|
return CouponConverter.fromXML(response.getAsString(),
|
||||||
});
|
RefundResult.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 退款申请
|
* 退款申请
|
||||||
*
|
*
|
||||||
* @param caFile
|
* @param caFile
|
||||||
* 证书文件(V2版本后缀为*.pfx)
|
* 证书文件(V3版本后缀为*.p12)
|
||||||
* @param idQuery
|
* @param idQuery
|
||||||
* 商户系统内部的订单号, transaction_id 、 out_trade_no 二选一,如果同时存在优先级:
|
* 商户系统内部的订单号, transaction_id 、 out_trade_no 二选一,如果同时存在优先级:
|
||||||
* transaction_id> out_trade_no
|
* transaction_id> out_trade_no
|
||||||
@ -165,15 +179,22 @@ public class Pay3Api extends PayApi {
|
|||||||
* 订单总金额,单位为元
|
* 订单总金额,单位为元
|
||||||
* @param refundFee
|
* @param refundFee
|
||||||
* 退款总金额,单位为元,可以做部分退款
|
* 退款总金额,单位为元,可以做部分退款
|
||||||
|
* @param refundFeeType
|
||||||
|
* 货币类型,符合ISO 4217标准的三位字母代码,默认人民币:CNY
|
||||||
* @param opUserId
|
* @param opUserId
|
||||||
* 操作员帐号, 默认为商户号
|
* 操作员帐号, 默认为商户号
|
||||||
* @see {@link com.foxinmy.weixin4j.mp.api.Pay3Api#refund(File, IdQuery, String, double, double, String, Map)}
|
* @see {@link com.foxinmy.weixin4j.mp.api.Pay3Api#refund(File, IdQuery, String, double, double, String, Map)}
|
||||||
*/
|
*/
|
||||||
public RefundResult refund(File caFile, IdQuery idQuery,
|
public RefundResult refund(File caFile, IdQuery idQuery,
|
||||||
String outRefundNo, double totalFee, double refundFee,
|
String outRefundNo, double totalFee, double refundFee,
|
||||||
String opUserId) throws WeixinException {
|
CurrencyType refundFeeType, String opUserId) throws WeixinException {
|
||||||
|
Map<String, String> mopara = new HashMap<String, String>();
|
||||||
|
if (refundFeeType == null) {
|
||||||
|
refundFeeType = CurrencyType.CNY;
|
||||||
|
}
|
||||||
|
mopara.put("refund_fee_type", refundFeeType.name());
|
||||||
return refund(caFile, idQuery, outRefundNo, totalFee, refundFee,
|
return refund(caFile, idQuery, outRefundNo, totalFee, refundFee,
|
||||||
opUserId, null);
|
opUserId, mopara);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -221,12 +242,15 @@ public class Pay3Api extends PayApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* native支付URL转短链接
|
* native支付URL转短链接:用于扫码原生支付模式一中的二维码链接转成短链接(weixin://wxpay/s/XXXXXX),减小二维码数据量
|
||||||
|
* ,提升扫描速度和精确度。
|
||||||
*
|
*
|
||||||
* @param url
|
* @param url
|
||||||
* 具有native标识的支付URL
|
* 具有native标识的支付URL
|
||||||
* @return 转换后的短链接
|
* @return 转换后的短链接
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
|
* @see <a
|
||||||
|
* href="http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_9">转换短链接API</a>
|
||||||
*/
|
*/
|
||||||
public String getShorturl(String url) throws WeixinException {
|
public String getShorturl(String url) throws WeixinException {
|
||||||
Map<String, String> map = baseMap(null);
|
Map<String, String> map = baseMap(null);
|
||||||
@ -245,14 +269,19 @@ public class Pay3Api extends PayApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 关闭订单</br> 当订单支付失败,调用关单接口后用新订单号重新发起支付,如果关单失败,返回已完
|
* 关闭订单
|
||||||
* 成支付请按正常支付处理。如果出现银行掉单,调用关单成功后,微信后台会主动发起退款。
|
* <p>
|
||||||
|
* 商户订单支付失败需要生成新单号重新发起支付,要对原订单号调用关单,避免重复支付;系统下单后,用户支付超时,系统退出不再受理,避免用户继续
|
||||||
|
* ,请调用关单接口,如果关单失败,返回已完 成支付请按正常支付处理。如果出现银行掉单,调用关单成功后,微信后台会主动发起退款。
|
||||||
|
* </p>
|
||||||
*
|
*
|
||||||
* @param outTradeNo
|
* @param outTradeNo
|
||||||
* 商户系统内部的订单号
|
* 商户系统内部的订单号
|
||||||
* @return 处理结果
|
* @return 处理结果
|
||||||
* @since V3
|
* @since V3
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
|
* @see <a
|
||||||
|
* href="http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_3">关闭订单API</a>
|
||||||
*/
|
*/
|
||||||
public ApiResult closeOrder(String outTradeNo) throws WeixinException {
|
public ApiResult closeOrder(String outTradeNo) throws WeixinException {
|
||||||
Map<String, String> map = baseMap(new IdQuery(outTradeNo,
|
Map<String, String> map = baseMap(new IdQuery(outTradeNo,
|
||||||
@ -280,6 +309,8 @@ public class Pay3Api extends PayApi {
|
|||||||
* REFUND,返回当日退款订单
|
* REFUND,返回当日退款订单
|
||||||
* @return excel表格
|
* @return excel表格
|
||||||
* @since V3
|
* @since V3
|
||||||
|
* @see <a
|
||||||
|
* href="http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_6">下载对账单API</a>
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
*/
|
*/
|
||||||
public File downloadbill(Date billDate, BillType billType)
|
public File downloadbill(Date billDate, BillType billType)
|
||||||
@ -349,7 +380,11 @@ public class Pay3Api extends PayApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 退款查询</br> 退款有一定延时,用零钱支付的退款20分钟内到账,银行卡支付的退款 3 个工作日后重新查询退款状态
|
* 退款查询
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 提交退款申请后,通过调用该接口查询退款状态。退款有一定延时,用零钱支付的退款20分钟内到账,银行卡支付的退款3个工作日后重新查询退款状态。
|
||||||
|
* </p>
|
||||||
*
|
*
|
||||||
* @param idQuery
|
* @param idQuery
|
||||||
* 单号 refund_id、out_refund_no、 out_trade_no 、 transaction_id
|
* 单号 refund_id、out_refund_no、 out_trade_no 、 transaction_id
|
||||||
@ -358,6 +393,8 @@ public class Pay3Api extends PayApi {
|
|||||||
* @return 退款记录
|
* @return 退款记录
|
||||||
* @see com.foxinmy.weixin4j.mp.payment.v3.RefundRecord
|
* @see com.foxinmy.weixin4j.mp.payment.v3.RefundRecord
|
||||||
* @see com.foxinmy.weixin4j.mp.payment.v3.RefundDetail
|
* @see com.foxinmy.weixin4j.mp.payment.v3.RefundDetail
|
||||||
|
* @see <a
|
||||||
|
* href="http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_5">退款查询API</a>
|
||||||
* @since V3
|
* @since V3
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
*/
|
*/
|
||||||
@ -390,6 +427,8 @@ public class Pay3Api extends PayApi {
|
|||||||
* 调用接口返回的基本数据
|
* 调用接口返回的基本数据
|
||||||
* @return 处理结果
|
* @return 处理结果
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
|
* @see <a
|
||||||
|
* href="http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_8">接口测试上报API</a>
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public XmlResult interfaceReport(String interfaceUrl, int executeTime,
|
public XmlResult interfaceReport(String interfaceUrl, int executeTime,
|
||||||
|
|||||||
@ -21,6 +21,7 @@ public class PayPackage implements Serializable {
|
|||||||
private static final long serialVersionUID = 3450161267802545790L;
|
private static final long serialVersionUID = 3450161267802545790L;
|
||||||
|
|
||||||
private String body; // 商品描述 必须
|
private String body; // 商品描述 必须
|
||||||
|
private String detail; // 商品详情 非必须
|
||||||
private String attach; // 附加数据,原样返回 非必须
|
private String attach; // 附加数据,原样返回 非必须
|
||||||
@XStreamAlias("out_trade_no")
|
@XStreamAlias("out_trade_no")
|
||||||
@JSONField(name = "out_trade_no")
|
@JSONField(name = "out_trade_no")
|
||||||
@ -56,6 +57,14 @@ public class PayPackage implements Serializable {
|
|||||||
this.body = body;
|
this.body = body;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getDetail() {
|
||||||
|
return detail;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDetail(String detail) {
|
||||||
|
this.detail = detail;
|
||||||
|
}
|
||||||
|
|
||||||
public String getAttach() {
|
public String getAttach() {
|
||||||
return attach;
|
return attach;
|
||||||
}
|
}
|
||||||
@ -151,10 +160,10 @@ public class PayPackage implements Serializable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "PayPackage [body=" + body + ", attach=" + attach
|
return "PayPackage [body=" + body + ", detail=" + detail + ", attach="
|
||||||
+ ", outTradeNo=" + outTradeNo + ", totalFee=" + totalFee
|
+ attach + ", outTradeNo=" + outTradeNo + ", totalFee="
|
||||||
+ ", spbillCreateIp=" + spbillCreateIp + ", timeStart="
|
+ totalFee + ", spbillCreateIp=" + spbillCreateIp
|
||||||
+ timeStart + ", timeExpire=" + timeExpire + ", goodsTag="
|
+ ", timeStart=" + timeStart + ", timeExpire=" + timeExpire
|
||||||
+ goodsTag + ", notifyUrl=" + notifyUrl + "]";
|
+ ", goodsTag=" + goodsTag + ", notifyUrl=" + notifyUrl + "]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -208,7 +208,9 @@ public class PayUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建预支付对象</br>
|
* 统一下单接口</br>
|
||||||
|
* 除被扫支付场景以外,商户系统先调用该接口在微信支付服务后台生成预支付交易单,返回正确的预支付交易回话标识后再按扫码、JSAPI
|
||||||
|
* 、APP等不同场景生成交易串调起支付。
|
||||||
*
|
*
|
||||||
* @param payPackage
|
* @param payPackage
|
||||||
* 包含订单信息的对象
|
* 包含订单信息的对象
|
||||||
@ -216,6 +218,8 @@ public class PayUtil {
|
|||||||
* <font color="red">如果sign为空 则拿paysignkey进行签名</font>
|
* <font color="red">如果sign为空 则拿paysignkey进行签名</font>
|
||||||
* @see com.foxinmy.weixin4j.mp.payment.v3.PayPackageV3
|
* @see com.foxinmy.weixin4j.mp.payment.v3.PayPackageV3
|
||||||
* @see com.foxinmy.weixin4j.mp.payment.v3.PrePay
|
* @see com.foxinmy.weixin4j.mp.payment.v3.PrePay
|
||||||
|
* @see <a
|
||||||
|
* href="http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1">统一下单接口</a>
|
||||||
* @return 预支付对象
|
* @return 预支付对象
|
||||||
*/
|
*/
|
||||||
public static PrePay createPrePay(PayPackageV3 payPackage, String paySignKey)
|
public static PrePay createPrePay(PayPackageV3 payPackage, String paySignKey)
|
||||||
@ -306,13 +310,14 @@ public class PayUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建V3.x NativePay支付链接
|
* 创建V3.x NativePay支付(扫码支付)链接
|
||||||
*
|
*
|
||||||
* @param weixinAccount
|
* @param weixinAccount
|
||||||
* 支付配置信息
|
* 支付配置信息
|
||||||
* @param productId
|
* @param productId
|
||||||
* 与订单ID等价
|
* 与订单ID等价
|
||||||
* @return
|
* @return
|
||||||
|
* @see <a href="http://pay.weixin.qq.com/wiki/doc/api/native.php">扫码支付</a>
|
||||||
*/
|
*/
|
||||||
public static String createNativePayRequestURLV3(
|
public static String createNativePayRequestURLV3(
|
||||||
WeixinMpAccount weixinAccount, String productId) {
|
WeixinMpAccount weixinAccount, String productId) {
|
||||||
@ -330,7 +335,7 @@ public class PayUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NATIVE回调时的响应
|
* 创建V2.x NATIVE回调时的响应字符串
|
||||||
*
|
*
|
||||||
* @param weixinAccount
|
* @param weixinAccount
|
||||||
* 商户信息
|
* 商户信息
|
||||||
@ -360,7 +365,7 @@ public class PayUtil {
|
|||||||
* 提交被扫支付
|
* 提交被扫支付
|
||||||
*
|
*
|
||||||
* @param authCode
|
* @param authCode
|
||||||
* 扫码支付授权码 ,设备读取用 户微信中的条码或者二维码 信息
|
* 扫码支付授权码 ,设备读取用户微信中的条码或者二维码信息
|
||||||
* @param body
|
* @param body
|
||||||
* 商品描述
|
* 商品描述
|
||||||
* @param attach
|
* @param attach
|
||||||
@ -373,7 +378,7 @@ public class PayUtil {
|
|||||||
* 订单生成的机器 IP
|
* 订单生成的机器 IP
|
||||||
* @param weixinAccount
|
* @param weixinAccount
|
||||||
* 商户信息
|
* 商户信息
|
||||||
* @return 返回数据
|
* @return 支付的订单信息
|
||||||
* @see {@link com.foxinmy.weixin4j.mp.payment.PayUtil#createMicroPay(MicroPayPackage, WeixinMpAccount)}
|
* @see {@link com.foxinmy.weixin4j.mp.payment.PayUtil#createMicroPay(MicroPayPackage, WeixinMpAccount)}
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
*/
|
*/
|
||||||
@ -387,14 +392,17 @@ public class PayUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 提交被扫支付
|
* 提交被扫支付:收银员使用扫码设备读取微信用户刷卡授权码以后,二维码或条码信息传送至商户收银台,由商户收银台或者商户后台调用该接口发起支付.
|
||||||
*
|
*
|
||||||
* @param payPackage
|
* @param payPackage
|
||||||
* 订单信息
|
* 订单信息
|
||||||
* @param weixinAccount
|
* @param weixinAccount
|
||||||
* 商户信息
|
* 商户信息
|
||||||
* @return 返回数据
|
* @return 支付的订单信息
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
|
* @see com.foxinmy.weixin4j.mp.payment.v3.Order
|
||||||
|
* @see <a
|
||||||
|
* href="http://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_10">提交被扫支付API</a>
|
||||||
*/
|
*/
|
||||||
public static com.foxinmy.weixin4j.mp.payment.v3.Order createMicroPay(
|
public static com.foxinmy.weixin4j.mp.payment.v3.Order createMicroPay(
|
||||||
MicroPayPackage payPackage, WeixinMpAccount weixinAccount)
|
MicroPayPackage payPackage, WeixinMpAccount weixinAccount)
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
package com.foxinmy.weixin4j.mp.payment;
|
package com.foxinmy.weixin4j.mp.payment.conver;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -9,6 +9,9 @@ import java.util.Map.Entry;
|
|||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import com.foxinmy.weixin4j.mp.payment.coupon.CouponInfo;
|
||||||
|
import com.foxinmy.weixin4j.mp.payment.v3.Order;
|
||||||
|
import com.foxinmy.weixin4j.mp.payment.v3.RefundResult;
|
||||||
import com.foxinmy.weixin4j.xml.XmlStream;
|
import com.foxinmy.weixin4j.xml.XmlStream;
|
||||||
import com.thoughtworks.xstream.converters.Converter;
|
import com.thoughtworks.xstream.converters.Converter;
|
||||||
import com.thoughtworks.xstream.converters.MarshallingContext;
|
import com.thoughtworks.xstream.converters.MarshallingContext;
|
||||||
@ -20,45 +23,41 @@ import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
|
|||||||
import com.thoughtworks.xstream.mapper.Mapper;
|
import com.thoughtworks.xstream.mapper.Mapper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 退款查询接口调用结果转换类
|
* V3订单详情转换类
|
||||||
*
|
*
|
||||||
* @className RefundConverter
|
* @className OrderConverter
|
||||||
* @author jy
|
* @author jy
|
||||||
* @date 2014年11月2日
|
* @date 2015年3月24日
|
||||||
* @since JDK 1.7
|
* @since JDK 1.7
|
||||||
* @see com.foxinmy.weixin4j.mp.payment.v2.RefundRecord
|
* @see
|
||||||
* @see com.foxinmy.weixin4j.mp.payment.v2.RefundDetail
|
|
||||||
* @see com.foxinmy.weixin4j.mp.payment.v3.RefundRecord
|
|
||||||
* @see com.foxinmy.weixin4j.mp.payment.v3.RefundDetail
|
|
||||||
*/
|
*/
|
||||||
public class RefundConverter {
|
public class CouponConverter {
|
||||||
|
|
||||||
private final static XmlStream xStream = XmlStream.get();
|
private final static XmlStream xStream = XmlStream.get();
|
||||||
private final static Mapper mapper;
|
private final static Mapper mapper;
|
||||||
private final static ReflectionProvider reflectionProvider;
|
private final static ReflectionProvider reflectionProvider;
|
||||||
private final static Pattern pattern = Pattern.compile("(_\\d)$");
|
private final static Pattern pattern = Pattern.compile("(_\\d)$");
|
||||||
|
private static Class<CouponInfo> COUPON_CLASS = CouponInfo.class;
|
||||||
private static Class<?> clazz;
|
private static Class<?> clazz;
|
||||||
private final static Class<com.foxinmy.weixin4j.mp.payment.v2.RefundRecord> REFUNDRECORD2 = com.foxinmy.weixin4j.mp.payment.v2.RefundRecord.class;
|
|
||||||
private final static Class<com.foxinmy.weixin4j.mp.payment.v3.RefundRecord> REFUNDRECORD3 = com.foxinmy.weixin4j.mp.payment.v3.RefundRecord.class;
|
|
||||||
|
|
||||||
static {
|
static {
|
||||||
xStream.processAnnotations(new Class[] { REFUNDRECORD2, REFUNDRECORD3,
|
xStream.processAnnotations(new Class[] { COUPON_CLASS });
|
||||||
com.foxinmy.weixin4j.mp.payment.v2.RefundDetail.class,
|
|
||||||
com.foxinmy.weixin4j.mp.payment.v3.RefundDetail.class });
|
|
||||||
xStream.aliasField("refund_state", com.foxinmy.weixin4j.mp.payment.v2.RefundDetail.class, "refundStatus");
|
|
||||||
xStream.registerConverter(new $());
|
xStream.registerConverter(new $());
|
||||||
mapper = xStream.getMapper();
|
mapper = xStream.getMapper();
|
||||||
reflectionProvider = xStream.getReflectionProvider();
|
reflectionProvider = xStream.getReflectionProvider();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> T fromXML(String xml, Class<T> clazz) {
|
public static <T> T fromXML(String xml, Class<T> clazz) {
|
||||||
RefundConverter.clazz = clazz;
|
CouponConverter.clazz = clazz;
|
||||||
|
xStream.processAnnotations(clazz);
|
||||||
return xStream.fromXML(xml, clazz);
|
return xStream.fromXML(xml, clazz);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class $ implements Converter {
|
private static class $ implements Converter {
|
||||||
@Override
|
@Override
|
||||||
public boolean canConvert(@SuppressWarnings("rawtypes") Class clazz) {
|
public boolean canConvert(@SuppressWarnings("rawtypes") Class clazz) {
|
||||||
return clazz.equals(REFUNDRECORD2) || clazz.equals(REFUNDRECORD3);
|
return clazz.equals(Order.class)
|
||||||
|
|| clazz.equals(RefundResult.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -71,9 +70,9 @@ public class RefundConverter {
|
|||||||
@Override
|
@Override
|
||||||
public Object unmarshal(HierarchicalStreamReader reader,
|
public Object unmarshal(HierarchicalStreamReader reader,
|
||||||
UnmarshallingContext context) {
|
UnmarshallingContext context) {
|
||||||
Object refund = null;
|
Object object = null;
|
||||||
try {
|
try {
|
||||||
refund = clazz.newInstance();
|
object = clazz.newInstance();
|
||||||
} catch (InstantiationException e) {
|
} catch (InstantiationException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} catch (IllegalAccessException e) {
|
} catch (IllegalAccessException e) {
|
||||||
@ -88,9 +87,9 @@ public class RefundConverter {
|
|||||||
Field field = reflectionProvider.getFieldOrNull(clazz,
|
Field field = reflectionProvider.getFieldOrNull(clazz,
|
||||||
fieldName);
|
fieldName);
|
||||||
if (field != null) {
|
if (field != null) {
|
||||||
Object value = context.convertAnother(refund,
|
Object value = context.convertAnother(object,
|
||||||
field.getType());
|
field.getType());
|
||||||
reflectionProvider.writeField(refund, fieldName, value,
|
reflectionProvider.writeField(object, fieldName, value,
|
||||||
field.getDeclaringClass());
|
field.getDeclaringClass());
|
||||||
} else if ((matcher = pattern.matcher(nodeName)).find()) {
|
} else if ((matcher = pattern.matcher(nodeName)).find()) {
|
||||||
String key = matcher.group();
|
String key = matcher.group();
|
||||||
@ -103,27 +102,34 @@ public class RefundConverter {
|
|||||||
}
|
}
|
||||||
reader.moveUp();
|
reader.moveUp();
|
||||||
}
|
}
|
||||||
StringBuilder detailXml = new StringBuilder();
|
if (!outMap.isEmpty()) {
|
||||||
detailXml.append("<list>");
|
StringBuilder couponXml = new StringBuilder();
|
||||||
String detailCanonicalName = clazz.getCanonicalName().replaceFirst(
|
couponXml.append("<list>");
|
||||||
"RefundRecord", "RefundDetail");
|
for (Iterator<Entry<String, Map<String, String>>> outIt = outMap
|
||||||
for (Iterator<Entry<String, Map<String, String>>> outIt = outMap
|
.entrySet().iterator(); outIt.hasNext();) {
|
||||||
.entrySet().iterator(); outIt.hasNext();) {
|
couponXml.append("<")
|
||||||
detailXml.append("<").append(detailCanonicalName).append(">");
|
.append(COUPON_CLASS.getCanonicalName())
|
||||||
for (Iterator<Entry<String, String>> innerIt = outIt.next()
|
.append(">");
|
||||||
.getValue().entrySet().iterator(); innerIt.hasNext();) {
|
for (Iterator<Entry<String, String>> innerIt = outIt.next()
|
||||||
Entry<String, String> entry = innerIt.next();
|
.getValue().entrySet().iterator(); innerIt
|
||||||
detailXml.append("<").append(entry.getKey()).append(">");
|
.hasNext();) {
|
||||||
detailXml.append(entry.getValue());
|
Entry<String, String> entry = innerIt.next();
|
||||||
detailXml.append("</").append(entry.getKey()).append(">");
|
couponXml.append("<").append(entry.getKey())
|
||||||
|
.append(">");
|
||||||
|
couponXml.append(entry.getValue());
|
||||||
|
couponXml.append("</").append(entry.getKey())
|
||||||
|
.append(">");
|
||||||
|
}
|
||||||
|
couponXml.append("</")
|
||||||
|
.append(COUPON_CLASS.getCanonicalName())
|
||||||
|
.append(">");
|
||||||
}
|
}
|
||||||
detailXml.append("</").append(detailCanonicalName).append(">");
|
couponXml.append("</list>");
|
||||||
|
reflectionProvider.writeField(object, "couponList",
|
||||||
|
xStream.fromXML(couponXml.toString(), List.class),
|
||||||
|
List.class.getDeclaringClass());
|
||||||
}
|
}
|
||||||
detailXml.append("</list>");
|
return object;
|
||||||
reflectionProvider.writeField(refund, "details",
|
|
||||||
xStream.fromXML(detailXml.toString(), List.class),
|
|
||||||
List.class.getDeclaringClass());
|
|
||||||
return refund;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -0,0 +1,190 @@
|
|||||||
|
package com.foxinmy.weixin4j.mp.payment.conver;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import com.foxinmy.weixin4j.mp.payment.coupon.CouponInfo;
|
||||||
|
import com.foxinmy.weixin4j.xml.XmlStream;
|
||||||
|
import com.thoughtworks.xstream.converters.Converter;
|
||||||
|
import com.thoughtworks.xstream.converters.MarshallingContext;
|
||||||
|
import com.thoughtworks.xstream.converters.UnmarshallingContext;
|
||||||
|
import com.thoughtworks.xstream.converters.reflection.ReflectionConverter;
|
||||||
|
import com.thoughtworks.xstream.converters.reflection.ReflectionProvider;
|
||||||
|
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
|
||||||
|
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
|
||||||
|
import com.thoughtworks.xstream.mapper.Mapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 退款查询接口调用结果转换类
|
||||||
|
*
|
||||||
|
* @className RefundConverter
|
||||||
|
* @author jy
|
||||||
|
* @date 2014年11月2日
|
||||||
|
* @since JDK 1.7
|
||||||
|
* @see com.foxinmy.weixin4j.mp.payment.v2.RefundRecord
|
||||||
|
* @see com.foxinmy.weixin4j.mp.payment.v2.RefundDetail
|
||||||
|
* @see com.foxinmy.weixin4j.mp.payment.v3.RefundRecord
|
||||||
|
* @see com.foxinmy.weixin4j.mp.payment.v3.RefundDetail
|
||||||
|
*/
|
||||||
|
public class RefundConverter {
|
||||||
|
private final static XmlStream xStream = XmlStream.get();
|
||||||
|
private final static Mapper mapper;
|
||||||
|
private final static ReflectionProvider reflectionProvider;
|
||||||
|
private final static Pattern REFUND_PATTERN = Pattern.compile("_\\d{1,}$");
|
||||||
|
private final static Pattern COUPON_PATTERN = Pattern
|
||||||
|
.compile("_\\d{1,}_\\d{1,}$");
|
||||||
|
private static Class<?> clazz;
|
||||||
|
private final static Class<CouponInfo> COUPON_CLASS = CouponInfo.class;
|
||||||
|
private final static Class<com.foxinmy.weixin4j.mp.payment.v2.RefundRecord> REFUNDRECORD2 = com.foxinmy.weixin4j.mp.payment.v2.RefundRecord.class;
|
||||||
|
private final static Class<com.foxinmy.weixin4j.mp.payment.v3.RefundRecord> REFUNDRECORD3 = com.foxinmy.weixin4j.mp.payment.v3.RefundRecord.class;
|
||||||
|
|
||||||
|
static {
|
||||||
|
xStream.processAnnotations(new Class[] { REFUNDRECORD2, REFUNDRECORD3 });
|
||||||
|
xStream.aliasField("refund_state",
|
||||||
|
com.foxinmy.weixin4j.mp.payment.v2.RefundDetail.class,
|
||||||
|
"refundStatus");
|
||||||
|
xStream.registerConverter(new $());
|
||||||
|
mapper = xStream.getMapper();
|
||||||
|
reflectionProvider = xStream.getReflectionProvider();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> T fromXML(String xml, Class<T> clazz) {
|
||||||
|
RefundConverter.clazz = clazz;
|
||||||
|
xStream.processAnnotations(clazz);
|
||||||
|
return xStream.fromXML(xml, clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class $ implements Converter {
|
||||||
|
@Override
|
||||||
|
public boolean canConvert(@SuppressWarnings("rawtypes") Class clazz) {
|
||||||
|
return clazz.equals(REFUNDRECORD2) || clazz.equals(REFUNDRECORD3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void marshal(Object source, HierarchicalStreamWriter writer,
|
||||||
|
MarshallingContext context) {
|
||||||
|
new ReflectionConverter(mapper, reflectionProvider).marshal(source,
|
||||||
|
writer, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object unmarshal(HierarchicalStreamReader reader,
|
||||||
|
UnmarshallingContext context) {
|
||||||
|
Object refund = null;
|
||||||
|
try {
|
||||||
|
refund = clazz.newInstance();
|
||||||
|
} catch (InstantiationException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
Matcher matcher = null;
|
||||||
|
Map<String, Map<String, String>> refundMap = new HashMap<String, Map<String, String>>();
|
||||||
|
Map<String, Map<String, String>> couponMap = new HashMap<String, Map<String, String>>();
|
||||||
|
while (reader.hasMoreChildren()) {
|
||||||
|
reader.moveDown();
|
||||||
|
String nodeName = reader.getNodeName();
|
||||||
|
String fieldName = mapper.realMember(clazz, nodeName);
|
||||||
|
Field field = reflectionProvider.getFieldOrNull(clazz,
|
||||||
|
fieldName);
|
||||||
|
if (field != null) {
|
||||||
|
Object value = context.convertAnother(refund,
|
||||||
|
field.getType());
|
||||||
|
reflectionProvider.writeField(refund, fieldName, value,
|
||||||
|
field.getDeclaringClass());
|
||||||
|
} else if ((matcher = REFUND_PATTERN.matcher(nodeName)).find()) {
|
||||||
|
String key = matcher.group();
|
||||||
|
Map<String, String> innerMap = null;
|
||||||
|
if ((matcher = COUPON_PATTERN.matcher(nodeName)).find()) {
|
||||||
|
key = matcher.group();
|
||||||
|
if ((innerMap = couponMap.get(key)) == null) {
|
||||||
|
innerMap = new HashMap<String, String>();
|
||||||
|
couponMap.put(key, innerMap);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ((innerMap = refundMap
|
||||||
|
.get(String.format("%s_", key))) == null) {
|
||||||
|
innerMap = new HashMap<String, String>();
|
||||||
|
refundMap.put(String.format("%s_", key), innerMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
innerMap.put(nodeName.replaceFirst(key, ""),
|
||||||
|
reader.getValue());
|
||||||
|
}
|
||||||
|
reader.moveUp();
|
||||||
|
}
|
||||||
|
if (!refundMap.isEmpty()) {
|
||||||
|
StringBuilder detailXml = new StringBuilder();
|
||||||
|
detailXml.append("<list>");
|
||||||
|
String detailCanonicalName = clazz.getCanonicalName()
|
||||||
|
.replaceFirst("RefundRecord", "RefundDetail");
|
||||||
|
for (Iterator<Entry<String, Map<String, String>>> refundIT = refundMap
|
||||||
|
.entrySet().iterator(); refundIT.hasNext();) {
|
||||||
|
detailXml.append("<").append(detailCanonicalName)
|
||||||
|
.append(">");
|
||||||
|
Entry<String, Map<String, String>> refundEntry = refundIT
|
||||||
|
.next();
|
||||||
|
for (Iterator<Entry<String, String>> innerIt = refundEntry
|
||||||
|
.getValue().entrySet().iterator(); innerIt
|
||||||
|
.hasNext();) {
|
||||||
|
Entry<String, String> entry = innerIt.next();
|
||||||
|
detailXml.append("<").append(entry.getKey())
|
||||||
|
.append(">");
|
||||||
|
detailXml.append(entry.getValue());
|
||||||
|
detailXml.append("</").append(entry.getKey())
|
||||||
|
.append(">");
|
||||||
|
}
|
||||||
|
if (!couponMap.isEmpty()) {
|
||||||
|
detailXml.append("<couponList class=\"")
|
||||||
|
.append(ArrayList.class.getCanonicalName())
|
||||||
|
.append("\">");
|
||||||
|
Iterator<Entry<String, Map<String, String>>> couponIT = couponMap
|
||||||
|
.entrySet().iterator();
|
||||||
|
while (couponIT.hasNext()) {
|
||||||
|
Entry<String, Map<String, String>> couponEntry = couponIT
|
||||||
|
.next();
|
||||||
|
if (couponEntry.getKey().startsWith(
|
||||||
|
refundEntry.getKey())) {
|
||||||
|
detailXml
|
||||||
|
.append("<")
|
||||||
|
.append(COUPON_CLASS.getCanonicalName())
|
||||||
|
.append(">");
|
||||||
|
for (Iterator<Entry<String, String>> innerIt = couponEntry
|
||||||
|
.getValue().entrySet().iterator(); innerIt
|
||||||
|
.hasNext();) {
|
||||||
|
Entry<String, String> entry = innerIt
|
||||||
|
.next();
|
||||||
|
detailXml.append("<")
|
||||||
|
.append(entry.getKey()).append(">");
|
||||||
|
detailXml.append(entry.getValue());
|
||||||
|
detailXml.append("</")
|
||||||
|
.append(entry.getKey()).append(">");
|
||||||
|
}
|
||||||
|
detailXml
|
||||||
|
.append("</")
|
||||||
|
.append(COUPON_CLASS.getCanonicalName())
|
||||||
|
.append(">");
|
||||||
|
couponIT.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
detailXml.append("</couponList>");
|
||||||
|
}
|
||||||
|
detailXml.append("</").append(detailCanonicalName)
|
||||||
|
.append(">");
|
||||||
|
}
|
||||||
|
detailXml.append("</list>");
|
||||||
|
reflectionProvider.writeField(refund, "details",
|
||||||
|
xStream.fromXML(detailXml.toString(), List.class),
|
||||||
|
List.class.getDeclaringClass());
|
||||||
|
}
|
||||||
|
return refund;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,65 @@
|
|||||||
|
package com.foxinmy.weixin4j.mp.payment.coupon;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.annotation.JSONField;
|
||||||
|
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 代金券信息
|
||||||
|
*
|
||||||
|
* @className CouponBase
|
||||||
|
* @author jy
|
||||||
|
* @date 2015年3月24日
|
||||||
|
* @since JDK 1.7
|
||||||
|
* @see
|
||||||
|
*/
|
||||||
|
public class CouponInfo implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -8744999305258786901L;
|
||||||
|
|
||||||
|
// 代金券或立减优惠批次ID
|
||||||
|
@XStreamAlias("coupon_batch_id")
|
||||||
|
@JSONField(name = "coupon_batch_id")
|
||||||
|
private String couponBatchId;
|
||||||
|
// 代金券或立减优惠ID
|
||||||
|
@XStreamAlias("coupon_id")
|
||||||
|
@JSONField(name = "coupon_id")
|
||||||
|
private String couponId;
|
||||||
|
// 单个代金券或立减优惠支付金额
|
||||||
|
@XStreamAlias("coupon_fee")
|
||||||
|
@JSONField(name = "coupon_fee")
|
||||||
|
private Integer couponFee;
|
||||||
|
|
||||||
|
public String getCouponBatchId() {
|
||||||
|
return couponBatchId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCouponId() {
|
||||||
|
return couponId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getCouponFee() {
|
||||||
|
return couponFee;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
|
||||||
|
*
|
||||||
|
* @return 元单位
|
||||||
|
*/
|
||||||
|
@JSONField(serialize = false, deserialize = false)
|
||||||
|
public double getFormatCouponFee() {
|
||||||
|
return couponFee / 100d;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCouponId(String couponId) {
|
||||||
|
this.couponId = couponId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "couponBatchId=" + couponBatchId + ", couponId=" + couponId
|
||||||
|
+ ", couponFee=" + couponFee;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -110,6 +110,6 @@ public class ApiResult extends XmlResult {
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
return "appId=" + appId + ", mchId=" + mchId + ", subMchId=" + subMchId
|
return "appId=" + appId + ", mchId=" + mchId + ", subMchId=" + subMchId
|
||||||
+ ", nonceStr=" + nonceStr + ", sign=" + sign + ", deviceInfo="
|
+ ", nonceStr=" + nonceStr + ", sign=" + sign + ", deviceInfo="
|
||||||
+ deviceInfo + ", recall=" + recall + ", " + super.toString();
|
+ deviceInfo + ", recall=" + getFormatRecall() + ", " + super.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,15 +1,16 @@
|
|||||||
package com.foxinmy.weixin4j.mp.payment.v3;
|
package com.foxinmy.weixin4j.mp.payment.v3;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.annotation.JSONField;
|
import com.alibaba.fastjson.annotation.JSONField;
|
||||||
|
import com.foxinmy.weixin4j.mp.payment.coupon.CouponInfo;
|
||||||
import com.foxinmy.weixin4j.mp.type.CurrencyType;
|
import com.foxinmy.weixin4j.mp.type.CurrencyType;
|
||||||
import com.foxinmy.weixin4j.mp.type.TradeState;
|
import com.foxinmy.weixin4j.mp.type.TradeState;
|
||||||
import com.foxinmy.weixin4j.mp.type.TradeType;
|
import com.foxinmy.weixin4j.mp.type.TradeType;
|
||||||
import com.foxinmy.weixin4j.util.DateUtil;
|
import com.foxinmy.weixin4j.util.DateUtil;
|
||||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||||
|
import com.thoughtworks.xstream.annotations.XStreamOmitField;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* V3订单信息
|
* V3订单信息
|
||||||
@ -54,6 +55,14 @@ public class Order extends ApiResult {
|
|||||||
@XStreamAlias("coupon_fee")
|
@XStreamAlias("coupon_fee")
|
||||||
@JSONField(name = "coupon_fee")
|
@JSONField(name = "coupon_fee")
|
||||||
private Integer couponFee;
|
private Integer couponFee;
|
||||||
|
// 代金券或立减优惠使用数量
|
||||||
|
@XStreamAlias("coupon_count")
|
||||||
|
@JSONField(name = "coupon_count")
|
||||||
|
private Integer couponCount;
|
||||||
|
// 代金券信息
|
||||||
|
@XStreamOmitField
|
||||||
|
@JSONField(serialize = false)
|
||||||
|
private List<CouponInfo> couponList;
|
||||||
@XStreamAlias("cash_fee")
|
@XStreamAlias("cash_fee")
|
||||||
@JSONField(name = "cash_fee")
|
@JSONField(name = "cash_fee")
|
||||||
private int cashFee;
|
private int cashFee;
|
||||||
@ -75,6 +84,10 @@ public class Order extends ApiResult {
|
|||||||
@XStreamAlias("time_end")
|
@XStreamAlias("time_end")
|
||||||
@JSONField(name = "time_end")
|
@JSONField(name = "time_end")
|
||||||
private String timeEnd;
|
private String timeEnd;
|
||||||
|
// 交易状态描述
|
||||||
|
@XStreamAlias("trade_state_desc")
|
||||||
|
@JSONField(name = "trade_state_desc")
|
||||||
|
private String tradeStateDesc;
|
||||||
|
|
||||||
public TradeState getTradeState() {
|
public TradeState getTradeState() {
|
||||||
return tradeState;
|
return tradeState;
|
||||||
@ -88,6 +101,11 @@ public class Order extends ApiResult {
|
|||||||
return isSubscribe;
|
return isSubscribe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JSONField(serialize = false, deserialize = false)
|
||||||
|
public boolean getFormatIsSubscribe() {
|
||||||
|
return isSubscribe != null && isSubscribe.equalsIgnoreCase("y");
|
||||||
|
}
|
||||||
|
|
||||||
public TradeType getTradeType() {
|
public TradeType getTradeType() {
|
||||||
return tradeType;
|
return tradeType;
|
||||||
}
|
}
|
||||||
@ -124,6 +142,15 @@ public class Order extends ApiResult {
|
|||||||
return couponFee != null ? couponFee / 100d : 0d;
|
return couponFee != null ? couponFee / 100d : 0d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Integer getCouponCount() {
|
||||||
|
return couponCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
@JSONField(serialize = false, deserialize = false)
|
||||||
|
public int getFormatCouponCount() {
|
||||||
|
return couponCount != null ? couponCount.intValue() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
public int getCashFee() {
|
public int getCashFee() {
|
||||||
return cashFee;
|
return cashFee;
|
||||||
}
|
}
|
||||||
@ -151,7 +178,7 @@ public class Order extends ApiResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getAttach() {
|
public String getAttach() {
|
||||||
return StringUtils.isBlank(attach) ? null : attach;
|
return attach;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getTimeEnd() {
|
public String getTimeEnd() {
|
||||||
@ -163,18 +190,30 @@ public class Order extends ApiResult {
|
|||||||
return DateUtil.parse2yyyyMMddHHmmss(timeEnd);
|
return DateUtil.parse2yyyyMMddHHmmss(timeEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getTradeStateDesc() {
|
||||||
|
return tradeStateDesc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<CouponInfo> getCouponList() {
|
||||||
|
return couponList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCouponList(List<CouponInfo> couponList) {
|
||||||
|
this.couponList = couponList;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Order [tradeState=" + tradeState + ", openId=" + openId
|
return "Order [tradeState=" + tradeState + ", openId=" + openId
|
||||||
+ ", isSubscribe=" + isSubscribe + ", tradeType=" + tradeType
|
+ ", isSubscribe=" + getFormatIsSubscribe() + ", tradeType="
|
||||||
+ ", bankType=" + bankType + ", totalFee=" + totalFee
|
+ tradeType + ", bankType=" + bankType + ", feeType=" + feeType
|
||||||
+ ", couponFee=" + couponFee + ", cashFee=" + cashFee
|
+ ", transactionId=" + transactionId + ", outTradeNo="
|
||||||
+ ", feeType=" + feeType + ", transactionId=" + transactionId
|
+ outTradeNo + ", attach=" + attach + ", timeEnd=" + timeEnd
|
||||||
+ ", outTradeNo=" + outTradeNo + ", attach=" + attach
|
+ ", totalFee=" + getFormatTotalFee() + ", couponFee="
|
||||||
+ ", timeEnd=" + timeEnd + ", getFormatTotalFee()="
|
+ getFormatCouponFee() + ", couponCount="
|
||||||
+ getFormatTotalFee() + ", getFormatCouponFee()="
|
+ getFormatCouponCount() + ", couponList=" + couponList
|
||||||
+ getFormatCouponFee() + ", getFormatCashFee()="
|
+ ", cashFee=" + getFormatCashFee() + ", timeEnd="
|
||||||
+ getFormatCashFee() + ", getFormatTimeEnd()="
|
+ getFormatTimeEnd() + ", tradeStateDesc=" + tradeStateDesc
|
||||||
+ getFormatTimeEnd() + ", " + super.toString() + "]";
|
+ ", " + super.toString() + "]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,12 +18,20 @@ public class PrePay extends ApiResult {
|
|||||||
private static final long serialVersionUID = -8430005768959715444L;
|
private static final long serialVersionUID = -8430005768959715444L;
|
||||||
|
|
||||||
@XStreamAlias("trade_type")
|
@XStreamAlias("trade_type")
|
||||||
private TradeType tradeType;// 交易类型JSAPI、NATIVE、APP 非空
|
/**
|
||||||
|
* 调用接口提交的交易类型,取值如下:JSAPI,NATIVE,APP,
|
||||||
|
*/
|
||||||
|
private TradeType tradeType;
|
||||||
@XStreamAlias("prepay_id")
|
@XStreamAlias("prepay_id")
|
||||||
private String prepayId;// 微信生成的预支付 ID,用于后续接口调用中使用二维码链接 非空
|
/**
|
||||||
|
* 微信生成的预支付回话标识,用于后续接口调用中使用,该值有效期为2小时
|
||||||
|
*/
|
||||||
|
private String prepayId;
|
||||||
@XStreamAlias("code_url")
|
@XStreamAlias("code_url")
|
||||||
private String codeUrl;// trade_type 为 NATIVE 是有 返回,此参数可直接生成二 维码展示出来进行扫码支付
|
/**
|
||||||
// 可能为空
|
* trade_type 为 NATIVE 是有 返回,此参数可直接生成二 维码展示出来进行扫码支付 可能为空
|
||||||
|
*/
|
||||||
|
private String codeUrl;
|
||||||
|
|
||||||
public PrePay() {
|
public PrePay() {
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,12 @@
|
|||||||
package com.foxinmy.weixin4j.mp.payment.v3;
|
package com.foxinmy.weixin4j.mp.payment.v3;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import com.alibaba.fastjson.annotation.JSONField;
|
import com.alibaba.fastjson.annotation.JSONField;
|
||||||
|
import com.foxinmy.weixin4j.mp.payment.coupon.CouponInfo;
|
||||||
|
import com.foxinmy.weixin4j.mp.type.CurrencyType;
|
||||||
import com.foxinmy.weixin4j.mp.type.RefundChannel;
|
import com.foxinmy.weixin4j.mp.type.RefundChannel;
|
||||||
import com.foxinmy.weixin4j.mp.type.RefundStatus;
|
import com.foxinmy.weixin4j.mp.type.RefundStatus;
|
||||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||||
@ -32,12 +36,43 @@ public class RefundDetail extends ApiResult {
|
|||||||
@XStreamAlias("refund_fee")
|
@XStreamAlias("refund_fee")
|
||||||
@JSONField(name = "refund_fee")
|
@JSONField(name = "refund_fee")
|
||||||
private int refundFee; // 退款总金额,单位为分,可以做部分退款
|
private int refundFee; // 退款总金额,单位为分,可以做部分退款
|
||||||
|
@XStreamAlias("refund_fee_type")
|
||||||
|
@JSONField(name = "refund_fee_type")
|
||||||
|
private CurrencyType refundFeeType; // 退款货币种类
|
||||||
|
@XStreamAlias("total_fee")
|
||||||
|
@JSONField(name = "total_fee")
|
||||||
|
private int totalFee; // 订单总金额
|
||||||
|
@XStreamAlias("fee_type")
|
||||||
|
@JSONField(name = "fee_type")
|
||||||
|
private CurrencyType feeType; // 订单金额货币种类
|
||||||
|
@XStreamAlias("cash_fee")
|
||||||
|
@JSONField(name = "cash_fee")
|
||||||
|
private int cashFee; // 现金支付金额
|
||||||
|
@XStreamAlias("cash_fee_type")
|
||||||
|
@JSONField(name = "cash_fee_type")
|
||||||
|
private CurrencyType cashFeeType; // 现金支付货币种类
|
||||||
|
@XStreamAlias("cash_refund_fee")
|
||||||
|
@JSONField(name = "cash_refund_fee")
|
||||||
|
private Integer cashRefundFee; // 现金退款金额
|
||||||
|
@XStreamAlias("cash_refund_fee_type")
|
||||||
|
@JSONField(name = "cash_refund_fee_type")
|
||||||
|
private CurrencyType cashRefundFeeType; // 现金退款货币类型
|
||||||
@XStreamAlias("refund_status")
|
@XStreamAlias("refund_status")
|
||||||
@JSONField(name = "refund_status")
|
@JSONField(name = "refund_status")
|
||||||
private String refundStatus; // 退款状态
|
private String refundStatus; // 退款状态
|
||||||
@XStreamAlias("coupon_refund_fee")
|
@XStreamAlias("coupon_refund_fee")
|
||||||
@JSONField(name = "coupon_refund_fee")
|
@JSONField(name = "coupon_refund_fee")
|
||||||
private int couponRefundFee; // 现金券退款金额<=退款金额,退款金额-现金券退款金额为现金
|
private Integer couponRefundFee; // 现金券退款金额<=退款金额,退款金额-现金券退款金额为现金
|
||||||
|
/**
|
||||||
|
* <font
|
||||||
|
* color="red">微信支付文档上写的coupon_count,而实际测试拿到的是coupon_refund_count,做个记号。
|
||||||
|
* </font>
|
||||||
|
*/
|
||||||
|
@XStreamAlias("coupon_refund_count")
|
||||||
|
@JSONField(name = "coupon_refund_count")
|
||||||
|
private Integer couponRefundCount; // 代金券或立减优惠使用数量
|
||||||
|
@JSONField(serialize = false)
|
||||||
|
private List<CouponInfo> couponList; // 代金券信息
|
||||||
|
|
||||||
public String getOutRefundNo() {
|
public String getOutRefundNo() {
|
||||||
return outRefundNo;
|
return outRefundNo;
|
||||||
@ -63,6 +98,10 @@ public class RefundDetail extends ApiResult {
|
|||||||
return refundFee;
|
return refundFee;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CurrencyType getFeeType() {
|
||||||
|
return feeType;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
|
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
|
||||||
*
|
*
|
||||||
@ -85,7 +124,7 @@ public class RefundDetail extends ApiResult {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getCouponRefundFee() {
|
public Integer getCouponRefundFee() {
|
||||||
return couponRefundFee;
|
return couponRefundFee;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,17 +135,92 @@ public class RefundDetail extends ApiResult {
|
|||||||
*/
|
*/
|
||||||
@JSONField(deserialize = false, serialize = false)
|
@JSONField(deserialize = false, serialize = false)
|
||||||
public double getFormatCouponRefundFee() {
|
public double getFormatCouponRefundFee() {
|
||||||
return couponRefundFee / 100d;
|
return couponRefundFee != null ? couponRefundFee.intValue() / 100d : 0d;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CurrencyType getRefundFeeType() {
|
||||||
|
return refundFeeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTotalFee() {
|
||||||
|
return totalFee;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
|
||||||
|
*
|
||||||
|
* @return 元单位
|
||||||
|
*/
|
||||||
|
@JSONField(deserialize = false, serialize = false)
|
||||||
|
public double getFormatTotalFee() {
|
||||||
|
return totalFee / 100d;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCashFee() {
|
||||||
|
return cashFee;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
|
||||||
|
*
|
||||||
|
* @return 元单位
|
||||||
|
*/
|
||||||
|
@JSONField(deserialize = false, serialize = false)
|
||||||
|
public double getFormatCashFee() {
|
||||||
|
return cashFee / 100d;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CurrencyType getCashFeeType() {
|
||||||
|
return cashFeeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getCashRefundFee() {
|
||||||
|
return cashRefundFee;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
|
||||||
|
*
|
||||||
|
* @return 元单位
|
||||||
|
*/
|
||||||
|
@JSONField(deserialize = false, serialize = false)
|
||||||
|
public double getFormatCashRefundFee() {
|
||||||
|
return cashRefundFee != null ? cashRefundFee.intValue() / 100d : 0d;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CurrencyType getCashRefundFeeType() {
|
||||||
|
return cashRefundFeeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getCouponRefundCount() {
|
||||||
|
return couponRefundCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
@JSONField(deserialize = false, serialize = false)
|
||||||
|
public int getFormatCouponRefundCount() {
|
||||||
|
return couponRefundCount != null ? couponRefundCount.intValue() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<CouponInfo> getCouponList() {
|
||||||
|
return couponList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCouponList(List<CouponInfo> couponList) {
|
||||||
|
this.couponList = couponList;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "RefundDetail [outRefundNo=" + outRefundNo + ", refundId="
|
return "RefundDetail [outRefundNo=" + outRefundNo + ", refundId="
|
||||||
+ refundId + ", refundChannel=" + refundChannel
|
+ refundId + ", refundChannel=" + refundChannel
|
||||||
+ ", refundFee=" + refundFee + ", refundStatus=" + refundStatus
|
+ ", refundFee=" + getFormatRefundFee() + ", refundFeeType="
|
||||||
+ ", couponRefundFee=" + couponRefundFee
|
+ refundFeeType + ", totalFee=" + getFormatTotalFee()
|
||||||
+ ", getFormatRefundChannel()=" + getFormatRefundChannel()
|
+ ", feeType=" + feeType + ", cashFee=" + getFormatCashFee()
|
||||||
+ ", getFormatRefundStatus()=" + getFormatRefundStatus()
|
+ ", cashFeeType=" + cashFeeType + ", cashRefundFee="
|
||||||
+ ", getFormatCouponRefundFee()=" + getFormatCouponRefundFee();
|
+ getFormatCashRefundFee() + ", cashRefundFeeType="
|
||||||
|
+ cashRefundFeeType + ", refundStatus=" + refundStatus
|
||||||
|
+ ", couponRefundFee=" + getFormatCouponRefundFee()
|
||||||
|
+ ", couponCount=" + getCouponRefundCount() + ", couponList="
|
||||||
|
+ couponList + ", " + super.toString() + "]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,7 @@ package com.foxinmy.weixin4j.mp.payment.v3;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.alibaba.fastjson.annotation.JSONField;
|
import com.alibaba.fastjson.annotation.JSONField;
|
||||||
|
import com.foxinmy.weixin4j.mp.type.CurrencyType;
|
||||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||||
import com.thoughtworks.xstream.annotations.XStreamOmitField;
|
import com.thoughtworks.xstream.annotations.XStreamOmitField;
|
||||||
|
|
||||||
@ -26,9 +27,24 @@ public class RefundRecord extends ApiResult {
|
|||||||
@XStreamAlias("out_trade_no")
|
@XStreamAlias("out_trade_no")
|
||||||
@JSONField(name = "out_trade_no")
|
@JSONField(name = "out_trade_no")
|
||||||
private String outTradeNo;// 商户订单号
|
private String outTradeNo;// 商户订单号
|
||||||
|
@XStreamAlias("total_fee")
|
||||||
|
@JSONField(name = "total_fee")
|
||||||
|
private int totalFee; // 订单总金额
|
||||||
|
@XStreamAlias("fee_type")
|
||||||
|
@JSONField(name = "fee_type")
|
||||||
|
private CurrencyType feeType; // 订单金额货币种类
|
||||||
@XStreamAlias("cash_fee")
|
@XStreamAlias("cash_fee")
|
||||||
@JSONField(name = "cash_fee")
|
@JSONField(name = "cash_fee")
|
||||||
private int cashFee;
|
private int cashFee; // 现金支付金额
|
||||||
|
@XStreamAlias("cash_fee_type")
|
||||||
|
@JSONField(name = "cash_fee_type")
|
||||||
|
private CurrencyType cashFeeType; // 现金支付金额货币种类
|
||||||
|
@XStreamAlias("refund_fee")
|
||||||
|
@JSONField(name = "refund_fee")
|
||||||
|
private int refundFee; // 退款总金额
|
||||||
|
@XStreamAlias("coupon_refund_fee")
|
||||||
|
@JSONField(name = "coupon_refund_fee")
|
||||||
|
private Integer couponRefundFee; // 代金券或立减优惠退款金额=订单金额-现金退款金额,注意:满立减金额不会退回
|
||||||
@XStreamAlias("refund_count")
|
@XStreamAlias("refund_count")
|
||||||
@JSONField(name = "refund_count")
|
@JSONField(name = "refund_count")
|
||||||
private int count;// 退款笔数
|
private int count;// 退款笔数
|
||||||
@ -58,6 +74,42 @@ public class RefundRecord extends ApiResult {
|
|||||||
return cashFee;
|
return cashFee;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CurrencyType getFeeType() {
|
||||||
|
return feeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CurrencyType getCashFeeType() {
|
||||||
|
return cashFeeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
|
||||||
|
*
|
||||||
|
* @return 元单位
|
||||||
|
*/
|
||||||
|
@JSONField(serialize = false, deserialize = false)
|
||||||
|
public double getFormatCouponRefundFee() {
|
||||||
|
return couponRefundFee != null ? couponRefundFee.intValue() / 100d : 0d;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getCouponRefundFee() {
|
||||||
|
return couponRefundFee;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
|
||||||
|
*
|
||||||
|
* @return 元单位
|
||||||
|
*/
|
||||||
|
@JSONField(serialize = false, deserialize = false)
|
||||||
|
public double getFormatTotalFee() {
|
||||||
|
return totalFee / 100d;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTotalFee() {
|
||||||
|
return totalFee;
|
||||||
|
}
|
||||||
|
|
||||||
public int getCount() {
|
public int getCount() {
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
@ -70,10 +122,28 @@ public class RefundRecord extends ApiResult {
|
|||||||
this.details = details;
|
this.details = details;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getRefundFee() {
|
||||||
|
return refundFee;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
|
||||||
|
*
|
||||||
|
* @return 元单位
|
||||||
|
*/
|
||||||
|
@JSONField(serialize = false, deserialize = false)
|
||||||
|
public double getFormatRefundFee() {
|
||||||
|
return refundFee / 100d;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "RefundRecord [transactionId=" + transactionId + ", outTradeNo="
|
return "RefundRecord [transactionId=" + transactionId + ", outTradeNo="
|
||||||
+ outTradeNo + ", cashFee=" + cashFee + ", count=" + count
|
+ outTradeNo + ", totalFee=" + getFormatTotalFee()
|
||||||
|
+ ", feeType=" + feeType + ", cashFee=" + getFormatCashFee()
|
||||||
|
+ ", cashFeeType=" + cashFeeType + ", refundFee="
|
||||||
|
+ getFormatRefundFee() + ", couponRefundFee="
|
||||||
|
+ getFormatCouponRefundFee() + ", count=" + count
|
||||||
+ ", details=" + details + ", " + super.toString() + "]";
|
+ ", details=" + details + ", " + super.toString() + "]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,151 +25,160 @@ import com.foxinmy.weixin4j.token.WeixinTokenCreator;
|
|||||||
import com.foxinmy.weixin4j.type.AccountType;
|
import com.foxinmy.weixin4j.type.AccountType;
|
||||||
|
|
||||||
public class PayTest {
|
public class PayTest {
|
||||||
private final static WeixinPayProxy PAY2;
|
private final static WeixinPayProxy PAY2;
|
||||||
private final static WeixinPayProxy PAY3;
|
private final static WeixinPayProxy PAY3;
|
||||||
private final static WeixinMpAccount ACCOUNT2;
|
private final static WeixinMpAccount ACCOUNT2;
|
||||||
private final static WeixinMpAccount ACCOUNT3;
|
private final static WeixinMpAccount ACCOUNT3;
|
||||||
static {
|
static {
|
||||||
ACCOUNT2 = new WeixinMpAccount(
|
ACCOUNT2 = new WeixinMpAccount(
|
||||||
"wxba294f2c6f330361",
|
"请填入v2版本的appid",
|
||||||
"8e33f5371a1afea1f7bce88088cb4bba",
|
"请填入v2版本的appsecret",
|
||||||
"gADrKITv3qYWu9JEg1NS0WPaU5yFgTwS9WfPueskfPpt3OZGpnUN1uBom36G2tP701vi2pPRJLZF9dEDFj9pqxidPn10Y91Lj8kK37Svz6S4MfeAHo9svFZmHkIKScGb",
|
"请填入v2版本的paysignkey",
|
||||||
"1221928801", "8d1b26231827a965ef54fe6a3a151551");
|
"请填入v2版本的partnerId", "请填入v2版本的partnerKey");
|
||||||
PAY2 = new WeixinPayProxy(ACCOUNT2, new FileTokenHolder(
|
PAY2 = new WeixinPayProxy(ACCOUNT2, new FileTokenHolder(
|
||||||
new WeixinTokenCreator(ACCOUNT2.getId(), ACCOUNT2.getSecret(),
|
new WeixinTokenCreator(ACCOUNT2.getId(), ACCOUNT2.getSecret(),
|
||||||
AccountType.MP)));
|
AccountType.MP)));
|
||||||
ACCOUNT3 = new WeixinMpAccount("wx0d1d598c0c03c999",
|
ACCOUNT3 = new WeixinMpAccount("请填入v3版本的appid",
|
||||||
"2513ac683f1beabdb6b98d9ddd9e5755",
|
"请填入v3版本的appSecret",
|
||||||
"GATFzDwbQdbbci3QEQxX2rUBvwTrsMiZ", "10020674");
|
"请填入v3版本的paysignkey", "请填入v3版本的mchid");
|
||||||
PAY3 = new WeixinPayProxy(ACCOUNT3, new FileTokenHolder(
|
PAY3 = new WeixinPayProxy(ACCOUNT3, new FileTokenHolder(
|
||||||
new WeixinTokenCreator(ACCOUNT3.getId(), ACCOUNT3.getSecret(),
|
new WeixinTokenCreator(ACCOUNT3.getId(), ACCOUNT3.getSecret(),
|
||||||
AccountType.MP)));
|
AccountType.MP)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void orderQueryV2() throws WeixinException {
|
public void orderQueryV2() throws WeixinException {
|
||||||
System.err.println(PAY2.orderQueryV2("D14110500021"));
|
System.err.println(PAY2.orderQueryV2("D14110500021"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void refundV2() throws WeixinException {
|
public void refundV2() throws WeixinException {
|
||||||
File caFile = new File(
|
File caFile = new File(
|
||||||
"/Users/jy/workspace/feican/canyi-weixin-parent/canyi-weixin-service/src/main/resources/1221928801.pfx");
|
"签名文件,如12333.pfx");
|
||||||
IdQuery idQuery = new IdQuery("D15020300005", IdType.TRADENO);
|
IdQuery idQuery = new IdQuery("D15020300005", IdType.TRADENO);
|
||||||
System.err.println(PAY2.refundV2(caFile, idQuery, "1422925555037", 16d, 16d,
|
System.err.println(PAY2.refundV2(caFile, idQuery, "1422925555037", 16d,
|
||||||
"1221928801", "111111", null, null, null));
|
16d, "1221928801", "111111", null, null, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void refundQueryV2() throws WeixinException {
|
public void refundQueryV2() throws WeixinException {
|
||||||
System.err.println(PAY2.refundQueryV2(new IdQuery("D14123000004",
|
System.err.println(PAY2.refundQueryV2(new IdQuery("D14123000004",
|
||||||
IdType.TRADENO)));
|
IdType.TRADENO)));
|
||||||
refundQueryV3();
|
refundQueryV3();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void downbillV2() throws WeixinException {
|
public void downbillV2() throws WeixinException {
|
||||||
Calendar c = Calendar.getInstance();
|
Calendar c = Calendar.getInstance();
|
||||||
c.set(Calendar.YEAR, 2014);
|
c.set(Calendar.YEAR, 2014);
|
||||||
c.set(Calendar.MONTH, 11);
|
c.set(Calendar.MONTH, 11);
|
||||||
c.set(Calendar.DAY_OF_MONTH, 22);
|
c.set(Calendar.DAY_OF_MONTH, 22);
|
||||||
File file = PAY2.downloadbill(c.getTime(), null);
|
File file = PAY2.downloadbill(c.getTime(), null);
|
||||||
System.err.println(file);
|
System.err.println(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void orderQueryV3() throws WeixinException {
|
public void orderQueryV3() throws WeixinException {
|
||||||
Order order = PAY3.orderQueryV3(new IdQuery("T0002", IdType.TRADENO));
|
Order order = PAY3.orderQueryV3(new IdQuery("T0002", IdType.TRADENO));
|
||||||
System.err.println(order);
|
System.err.println(order);
|
||||||
String sign = order.getSign();
|
String sign = order.getSign();
|
||||||
order.setSign(null);
|
order.setSign(null);
|
||||||
String valiSign = PayUtil.paysignMd5(order, ACCOUNT3.getPaySignKey());
|
String valiSign = PayUtil.paysignMd5(order, ACCOUNT3.getPaySignKey());
|
||||||
System.err
|
System.err
|
||||||
.println(String.format("sign=%s,valiSign=%s", sign, valiSign));
|
.println(String.format("sign=%s,valiSign=%s", sign, valiSign));
|
||||||
Assert.assertEquals(valiSign, sign);
|
Assert.assertEquals(valiSign, sign);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void refundQueryV3() throws WeixinException {
|
public void refundQueryV3() throws WeixinException {
|
||||||
System.err.println(PAY3.refundQueryV3(new IdQuery("T00015",
|
com.foxinmy.weixin4j.mp.payment.v3.RefundRecord record = PAY3.refundQueryV3(new IdQuery("TT_1427183696238",
|
||||||
IdType.TRADENO)));
|
IdType.TRADENO));
|
||||||
}
|
System.err.println(record);
|
||||||
|
// 这里的验证签名需要把details循环拼接
|
||||||
|
String sign = record.getSign();
|
||||||
|
record.setSign(null);
|
||||||
|
String valiSign = PayUtil.paysignMd5(record, ACCOUNT3.getPaySignKey());
|
||||||
|
System.err
|
||||||
|
.println(String.format("sign=%s,valiSign=%s", sign, valiSign));
|
||||||
|
Assert.assertEquals(valiSign, sign);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void downbillV3() throws WeixinException {
|
public void downbillV3() throws WeixinException {
|
||||||
Calendar c = Calendar.getInstance();
|
Calendar c = Calendar.getInstance();
|
||||||
System.err.println(c.getTime());
|
System.err.println(c.getTime());
|
||||||
c.set(Calendar.YEAR, 2014);
|
c.set(Calendar.YEAR, 2015);
|
||||||
c.set(Calendar.MONTH, 9);
|
c.set(Calendar.MONTH, 2);
|
||||||
c.set(Calendar.DAY_OF_MONTH, 22);
|
c.set(Calendar.DAY_OF_MONTH, 24);
|
||||||
System.err.println(c.getTime());
|
System.err.println(c.getTime());
|
||||||
File file = PAY3.downloadbill(c.getTime(), null);
|
File file = PAY3.downloadbill(c.getTime(), null);
|
||||||
System.err.println(file);
|
System.err.println(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void refundV3() throws WeixinException {
|
public void refundV3() throws WeixinException {
|
||||||
File caFile = new File(
|
File caFile = new File(
|
||||||
"/Users/jy/workspace/feican/canyi-weixin-parent/canyi-weixin-service/src/main/resources/10020674.p12");
|
"签名文件如123.p12");
|
||||||
IdQuery idQuery = new IdQuery("T00015", IdType.TRADENO);
|
IdQuery idQuery = new IdQuery("TT_1427183696238", IdType.TRADENO);
|
||||||
com.foxinmy.weixin4j.mp.payment.v3.RefundResult result = PAY3.refundV3(
|
com.foxinmy.weixin4j.mp.payment.v3.RefundResult result = PAY3.refundV3(
|
||||||
caFile, idQuery, "R0002", 1d, 1d, "10020674");
|
caFile, idQuery, "TT_R" + System.currentTimeMillis(), 0.01d, 0.01d,
|
||||||
System.err.println(result);
|
null, "10020674");
|
||||||
String sign = result.getSign();
|
System.err.println(result);
|
||||||
result.setSign(null);
|
String sign = result.getSign();
|
||||||
String valiSign = PayUtil.paysignMd5(result, ACCOUNT3.getPaySignKey());
|
result.setSign(null);
|
||||||
System.err
|
String valiSign = PayUtil.paysignMd5(result, ACCOUNT3.getPaySignKey());
|
||||||
.println(String.format("sign=%s,valiSign=%s", sign, valiSign));
|
System.err
|
||||||
Assert.assertEquals(valiSign, sign);
|
.println(String.format("sign=%s,valiSign=%s", sign, valiSign));
|
||||||
}
|
Assert.assertEquals(valiSign, sign);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void nativeV3() throws WeixinException {
|
public void nativeV3() throws WeixinException {
|
||||||
PayPackageV3 payPackageV3 = new PayPackageV3(ACCOUNT3,
|
PayPackageV3 payPackageV3 = new PayPackageV3(ACCOUNT3,
|
||||||
"oyFLst1bqtuTcxK-ojF8hOGtLQao", "native测试", "T0001", 0.1d,
|
"oyFLst1bqtuTcxK-ojF8hOGtLQao", "native测试", "T0001", 0.1d,
|
||||||
"127.0.0.1", TradeType.NATIVE);
|
"127.0.0.1", TradeType.NATIVE);
|
||||||
payPackageV3.setProductId("0001");
|
payPackageV3.setProductId("0001");
|
||||||
payPackageV3.setNotifyUrl("xxxx");
|
payPackageV3.setNotifyUrl("xxxx");
|
||||||
PrePay prePay = null;
|
PrePay prePay = null;
|
||||||
try {
|
try {
|
||||||
prePay = PayUtil.createPrePay(payPackageV3,
|
prePay = PayUtil.createPrePay(payPackageV3,
|
||||||
ACCOUNT3.getPaySignKey());
|
ACCOUNT3.getPaySignKey());
|
||||||
} catch (PayException e) {
|
} catch (PayException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
System.err.println(prePay);
|
System.err.println(prePay);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void closeOrder() throws WeixinException {
|
public void closeOrder() throws WeixinException {
|
||||||
ApiResult result = PAY3.closeOrder("D111");
|
ApiResult result = PAY3.closeOrder("D111");
|
||||||
System.err.println(result);
|
System.err.println(result);
|
||||||
String sign = result.getSign();
|
String sign = result.getSign();
|
||||||
result.setSign(null);
|
result.setSign(null);
|
||||||
String valiSign = PayUtil.paysignMd5(result, ACCOUNT3.getPaySignKey());
|
String valiSign = PayUtil.paysignMd5(result, ACCOUNT3.getPaySignKey());
|
||||||
System.err
|
System.err
|
||||||
.println(String.format("sign=%s,valiSign=%s", sign, valiSign));
|
.println(String.format("sign=%s,valiSign=%s", sign, valiSign));
|
||||||
Assert.assertEquals(valiSign, sign);
|
Assert.assertEquals(valiSign, sign);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shortUrl() throws WeixinException {
|
public void shortUrl() throws WeixinException {
|
||||||
String url = "weixin://wxpay/bizpayurl?xxxxxx";
|
String url = "weixin://wxpay/bizpayurl?xxxxxx";
|
||||||
String shortUrl = PAY3.getPayShorturl(url);
|
String shortUrl = PAY3.getPayShorturl(url);
|
||||||
System.err.println(shortUrl);
|
System.err.println(shortUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void interfaceReport() throws WeixinException {
|
public void interfaceReport() throws WeixinException {
|
||||||
String interfaceUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder";
|
String interfaceUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder";
|
||||||
int executeTime = 2500;
|
int executeTime = 2500;
|
||||||
String outTradeNo = null;
|
String outTradeNo = null;
|
||||||
String ip = "127.0.0.1";
|
String ip = "127.0.0.1";
|
||||||
Date time = new Date();
|
Date time = new Date();
|
||||||
XmlResult returnXml = new XmlResult("SUCCESS", "");
|
XmlResult returnXml = new XmlResult("SUCCESS", "");
|
||||||
returnXml.setResultCode("SUCCESS");
|
returnXml.setResultCode("SUCCESS");
|
||||||
returnXml = PAY3.interfaceReport(interfaceUrl, executeTime, outTradeNo,
|
returnXml = PAY3.interfaceReport(interfaceUrl, executeTime, outTradeNo,
|
||||||
ip, time, returnXml);
|
ip, time, returnXml);
|
||||||
System.err.println(returnXml);
|
System.err.println(returnXml);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -67,4 +67,8 @@ weixin4j-mp-server
|
|||||||
|
|
||||||
* 2014-11-23
|
* 2014-11-23
|
||||||
|
|
||||||
+ `WeixinServerBootstrap`重命名为`WeixinMpServerBootstrap`
|
+ `WeixinServerBootstrap`重命名为`WeixinMpServerBootstrap`
|
||||||
|
|
||||||
|
* 2015-03-25
|
||||||
|
|
||||||
|
+ 新增客服创建、关闭、转接会话事件
|
||||||
@ -5,6 +5,8 @@ import java.util.HashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.dom4j.DocumentException;
|
||||||
|
import org.dom4j.io.SAXReader;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@ -16,6 +18,7 @@ import com.foxinmy.weixin4j.model.WeixinMpAccount;
|
|||||||
import com.foxinmy.weixin4j.mp.payment.JsPayNotify;
|
import com.foxinmy.weixin4j.mp.payment.JsPayNotify;
|
||||||
import com.foxinmy.weixin4j.mp.payment.PayPackage;
|
import com.foxinmy.weixin4j.mp.payment.PayPackage;
|
||||||
import com.foxinmy.weixin4j.mp.payment.PayUtil;
|
import com.foxinmy.weixin4j.mp.payment.PayUtil;
|
||||||
|
import com.foxinmy.weixin4j.mp.payment.conver.CouponConverter;
|
||||||
import com.foxinmy.weixin4j.mp.payment.v2.NativePayNotifyV2;
|
import com.foxinmy.weixin4j.mp.payment.v2.NativePayNotifyV2;
|
||||||
import com.foxinmy.weixin4j.mp.payment.v2.NativePayResponseV2;
|
import com.foxinmy.weixin4j.mp.payment.v2.NativePayResponseV2;
|
||||||
import com.foxinmy.weixin4j.mp.payment.v2.PayFeedback;
|
import com.foxinmy.weixin4j.mp.payment.v2.PayFeedback;
|
||||||
@ -149,16 +152,22 @@ public class PayAction {
|
|||||||
* <return_code>SUCCESS/FAIL</return_code><br>
|
* <return_code>SUCCESS/FAIL</return_code><br>
|
||||||
* <return_msg>如非空,为错误 原因签名失败参数格式校验错误</return_msg><br>
|
* <return_msg>如非空,为错误 原因签名失败参数格式校验错误</return_msg><br>
|
||||||
* </xml>
|
* </xml>
|
||||||
|
* @throws DocumentException
|
||||||
|
* @see <a
|
||||||
|
* href="http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7">支付结果通知</a>
|
||||||
*/
|
*/
|
||||||
public String jsNotifyV3(InputStream inputStream) {
|
public String jsNotifyV3(InputStream inputStream) throws DocumentException {
|
||||||
com.foxinmy.weixin4j.mp.payment.v3.Order order = XmlStream.get(
|
SAXReader sax = new SAXReader();
|
||||||
inputStream, com.foxinmy.weixin4j.mp.payment.v3.Order.class);
|
String orderXml = sax.read(inputStream).asXML();
|
||||||
|
com.foxinmy.weixin4j.mp.payment.v3.Order order = CouponConverter
|
||||||
|
.fromXML(orderXml, com.foxinmy.weixin4j.mp.payment.v3.Order.class);
|
||||||
log.info("jsapi_notify_order_info:", order);
|
log.info("jsapi_notify_order_info:", order);
|
||||||
String sign = order.getSign();
|
String sign = order.getSign();
|
||||||
order.setSign(null);
|
order.setSign(null);
|
||||||
WeixinMpAccount weixinAccount = ConfigUtil.getWeixinMpAccount();
|
WeixinMpAccount weixinAccount = ConfigUtil.getWeixinMpAccount();
|
||||||
String valid_sign = PayUtil.paysignMd5(order,
|
String valid_sign = PayUtil.paysignMd5(order,
|
||||||
weixinAccount.getPaySignKey());
|
weixinAccount.getPaySignKey());
|
||||||
|
// 如果订单中存在代金券的情况并不适用
|
||||||
log.info("微信签名----->sign={},vaild_sign={}", sign, valid_sign);
|
log.info("微信签名----->sign={},vaild_sign={}", sign, valid_sign);
|
||||||
if (!sign.equals(valid_sign)) {
|
if (!sign.equals(valid_sign)) {
|
||||||
return XmlStream.to(new XmlResult(Consts.FAIL, "签名错误"));
|
return XmlStream.to(new XmlResult(Consts.FAIL, "签名错误"));
|
||||||
|
|||||||
@ -0,0 +1,21 @@
|
|||||||
|
package com.foxinmy.weixin4j.mp.action.event;
|
||||||
|
|
||||||
|
import com.foxinmy.weixin4j.action.DebugAction;
|
||||||
|
import com.foxinmy.weixin4j.action.mapping.ActionAnnotation;
|
||||||
|
import com.foxinmy.weixin4j.msg.event.KfCloseEventMessage;
|
||||||
|
import com.foxinmy.weixin4j.type.EventType;
|
||||||
|
import com.foxinmy.weixin4j.type.MessageType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客服关闭会话消息
|
||||||
|
*
|
||||||
|
* @className KfCloseAction
|
||||||
|
* @author jy
|
||||||
|
* @date 2015年3月25日
|
||||||
|
* @since JDK 1.7
|
||||||
|
* @see com.foxinmy.weixin4j.msg.event.KfCloseEventMessage
|
||||||
|
*/
|
||||||
|
@ActionAnnotation(msgType = MessageType.event, eventType = { EventType.kf_close_session })
|
||||||
|
public class KfCloseAction extends DebugAction<KfCloseEventMessage> {
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
package com.foxinmy.weixin4j.mp.action.event;
|
||||||
|
|
||||||
|
import com.foxinmy.weixin4j.action.DebugAction;
|
||||||
|
import com.foxinmy.weixin4j.action.mapping.ActionAnnotation;
|
||||||
|
import com.foxinmy.weixin4j.msg.event.KfCreateEventMessage;
|
||||||
|
import com.foxinmy.weixin4j.type.EventType;
|
||||||
|
import com.foxinmy.weixin4j.type.MessageType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客服接入会话消息
|
||||||
|
*
|
||||||
|
* @className KfCreateAction
|
||||||
|
* @author jy
|
||||||
|
* @date 2015年3月25日
|
||||||
|
* @since JDK 1.7
|
||||||
|
* @see com.foxinmy.weixin4j.msg.event.KfCreateEventMessage
|
||||||
|
*/
|
||||||
|
@ActionAnnotation(msgType = MessageType.event, eventType = { EventType.kf_create_session })
|
||||||
|
public class KfCreateAction extends DebugAction<KfCreateEventMessage> {
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
package com.foxinmy.weixin4j.mp.action.event;
|
||||||
|
|
||||||
|
import com.foxinmy.weixin4j.action.DebugAction;
|
||||||
|
import com.foxinmy.weixin4j.action.mapping.ActionAnnotation;
|
||||||
|
import com.foxinmy.weixin4j.msg.event.KfSwitchEventMessage;
|
||||||
|
import com.foxinmy.weixin4j.type.EventType;
|
||||||
|
import com.foxinmy.weixin4j.type.MessageType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客服转接会话消息
|
||||||
|
*
|
||||||
|
* @className KfSwitchAction
|
||||||
|
* @author jy
|
||||||
|
* @date 2015年3月25日
|
||||||
|
* @since JDK 1.7
|
||||||
|
* @see com.foxinmy.weixin4j.msg.event.KfSwitchEventMessage
|
||||||
|
*/
|
||||||
|
@ActionAnnotation(msgType = MessageType.event, eventType = { EventType.kf_switch_session })
|
||||||
|
public class KfSwitchAction extends DebugAction<KfSwitchEventMessage> {
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user