将微信支付模块移到base工程

This commit is contained in:
jinyu
2015-06-26 22:35:12 +08:00
parent 663cba9677
commit 5ee2755a16
85 changed files with 1161 additions and 1488 deletions
@@ -3,9 +3,12 @@ package com.foxinmy.weixin4j.api;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.alibaba.fastjson.JSON;
import com.foxinmy.weixin4j.http.weixin.WeixinHttpClient;
import com.foxinmy.weixin4j.model.WeixinAccount;
import com.foxinmy.weixin4j.token.FileTokenStorager;
import com.foxinmy.weixin4j.token.TokenStorager;
import com.foxinmy.weixin4j.util.ConfigUtil;
/**
* API基础
@@ -38,8 +41,19 @@ public abstract class BaseApi {
return sb.toString();
}
/**
* 默认使用weixin4j.properties文件中的公众号信息
*/
public final static WeixinAccount DEFAULT_WEIXIN_ACCOUNT;
/**
* 默认token使用File的方式存储
*/
public final static TokenStorager DEFAULT_TOKEN_STORAGER = new FileTokenStorager();
public final static TokenStorager DEFAULT_TOKEN_STORAGER;
static {
DEFAULT_WEIXIN_ACCOUNT = JSON.parseObject(
ConfigUtil.getValue("account"), WeixinAccount.class);
DEFAULT_TOKEN_STORAGER = new FileTokenStorager();
}
}
@@ -0,0 +1,243 @@
package com.foxinmy.weixin4j.api;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.weixin.SSLHttpClinet;
import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
import com.foxinmy.weixin4j.model.WeixinPayAccount;
import com.foxinmy.weixin4j.payment.PayURLConsts;
import com.foxinmy.weixin4j.payment.PayUtil;
import com.foxinmy.weixin4j.payment.mch.MPPayment;
import com.foxinmy.weixin4j.payment.mch.MPPaymentRecord;
import com.foxinmy.weixin4j.payment.mch.MPPaymentResult;
import com.foxinmy.weixin4j.payment.mch.Redpacket;
import com.foxinmy.weixin4j.payment.mch.RedpacketRecord;
import com.foxinmy.weixin4j.payment.mch.RedpacketSendResult;
import com.foxinmy.weixin4j.util.RandomUtil;
import com.foxinmy.weixin4j.xml.XmlStream;
/**
* 现金API
*
* @className CashApi
* @author jy
* @date 2015年3月28日
* @since JDK 1.7
* @see <a
* href="http://pay.weixin.qq.com/wiki/doc/api/cash_coupon.php?chapter=13_1">现金红包</a>
* @see <a
* href="http://pay.weixin.qq.com/wiki/doc/api/mch_pay.php?chapter=14_1">企业付款</a>
*/
public class CashApi {
private final WeixinPayAccount weixinAccount;
public CashApi(WeixinPayAccount weixinAccount) {
this.weixinAccount = weixinAccount;
}
/**
* 发放红包 企业向微信用户个人发现金红包
*
* @param caFile
* 证书文件(V3版本后缀为*.p12)
* @param redpacket
* 红包信息
* @return 发放结果
* @see com.foxinmy.weixin4j.payment.mch.Redpacket
* @see com.foxinmy.weixin4j.payment.mch.RedpacketSendResult
* @see <a
* href="http://pay.weixin.qq.com/wiki/doc/api/cash_coupon.php?chapter=13_5">发放红包接口说明</a>
* @throws WeixinException
*/
public RedpacketSendResult sendRedpack(File caFile, Redpacket redpacket)
throws WeixinException {
JSONObject obj = (JSONObject) JSON.toJSON(redpacket);
obj.put("nonce_str", RandomUtil.generateString(16));
obj.put("mch_id", weixinAccount.getMchId());
obj.put("sub_mch_id", weixinAccount.getSubMchId());
obj.put("wxappid", weixinAccount.getId());
String sign = PayUtil.paysignMd5(obj, weixinAccount.getPaySignKey());
obj.put("sign", sign);
String param = XmlStream.map2xml(obj);
WeixinResponse response = null;
InputStream ca = null;
try {
ca = new FileInputStream(caFile);
SSLHttpClinet request = new SSLHttpClinet(weixinAccount.getMchId(),
ca);
response = request.post(PayURLConsts.MCH_REDPACKSEND_URL, param);
} catch (WeixinException e) {
throw e;
} catch (IOException e) {
throw new WeixinException(e.getMessage());
} finally {
if (ca != null) {
try {
ca.close();
} catch (IOException e) {
;
}
}
}
return response.getAsObject(new TypeReference<RedpacketSendResult>() {
});
}
/**
* 查询红包记录
*
* @param caFile
* 证书文件(V3版本后缀为*.p12)
* @param outTradeNo
* 商户发放红包的商户订单号
* @return 红包记录
* @see com.foxinmy.weixin4j.payment.mch.RedpacketRecord
* @see <a
* href="http://pay.weixin.qq.com/wiki/doc/api/cash_coupon.php?chapter=13_6">查询红包接口说明</a>
* @throws WeixinException
*/
public RedpacketRecord queryRedpack(File caFile, String outTradeNo)
throws WeixinException {
Map<String, String> para = new HashMap<String, String>();
para.put("nonce_str", RandomUtil.generateString(16));
para.put("mch_id", weixinAccount.getMchId());
para.put("bill_type", "MCHT");
para.put("appid", weixinAccount.getId());
para.put("mch_billno", outTradeNo);
String sign = PayUtil.paysignMd5(para, weixinAccount.getPaySignKey());
para.put("sign", sign);
String param = XmlStream.map2xml(para);
WeixinResponse response = null;
InputStream ca = null;
try {
ca = new FileInputStream(caFile);
SSLHttpClinet request = new SSLHttpClinet(weixinAccount.getMchId(),
ca);
response = request.post(PayURLConsts.MCH_REDPACKQUERY_URL, param);
} catch (WeixinException e) {
throw e;
} catch (IOException e) {
throw new WeixinException(e.getMessage());
} finally {
if (ca != null) {
try {
ca.close();
} catch (IOException e) {
;
}
}
}
return response.getAsObject(new TypeReference<RedpacketRecord>() {
});
}
/**
* 企业付款 实现企业向个人付款,针对部分有开发能力的商户, 提供通过API完成企业付款的功能。 比如目前的保险行业向客户退保、给付、理赔。
*
* @param caFile
* 证书文件(V3版本后缀为*.p12)
* @param mpPayment
* 付款信息
* @return 付款结果
* @see com.foxinmy.weixin4j.payment.mch.MPPayment
* @see com.foxinmy.weixin4j.payment.mch.MPPaymentResult
* @see <a
* href="http://pay.weixin.qq.com/wiki/doc/api/mch_pay.php?chapter=14_1">企业付款</a>
* @throws WeixinException
*/
public MPPaymentResult mpPayment(File caFile, MPPayment mpPayment)
throws WeixinException {
JSONObject obj = (JSONObject) JSON.toJSON(mpPayment);
obj.put("nonce_str", RandomUtil.generateString(16));
obj.put("mchid", weixinAccount.getMchId());
obj.put("sub_mch_id", weixinAccount.getSubMchId());
obj.put("mch_appid", weixinAccount.getId());
obj.put("device_info", weixinAccount.getDeviceInfo());
String sign = PayUtil.paysignMd5(obj, weixinAccount.getPaySignKey());
obj.put("sign", sign);
String param = XmlStream.map2xml(obj);
WeixinResponse response = null;
InputStream ca = null;
try {
ca = new FileInputStream(caFile);
SSLHttpClinet request = new SSLHttpClinet(weixinAccount.getMchId(),
ca);
response = request.post(PayURLConsts.MCH_ENPAYMENT_URL, param);
} catch (WeixinException e) {
throw e;
} catch (IOException e) {
throw new WeixinException(e.getMessage());
} finally {
if (ca != null) {
try {
ca.close();
} catch (IOException e) {
;
}
}
}
String text = response.getAsString()
.replaceFirst("<mch_appid>", "<appid>")
.replaceFirst("</mch_appid>", "</appid>")
.replaceFirst("<mchid>", "<mch_id>")
.replaceFirst("</mchid>", "</mch_id>");
return XmlStream.fromXML(text, MPPaymentResult.class);
}
/**
* 企业付款查询 用于商户的企业付款操作进行结果查询,返回付款操作详细结果
*
* @param caFile
* 证书文件(V3版本后缀为*.p12)
* @param outTradeNo
* 商户调用企业付款API时使用的商户订单号
* @return 付款记录
* @see com.foxinmy.weixin4j.payment.mch.MPPaymentRecord
* @see <a
* href="http://pay.weixin.qq.com/wiki/doc/api/mch_pay.php?chapter=14_3">企业付款查询</a>
* @throws WeixinException
*/
public MPPaymentRecord mpPaymentQuery(File caFile, String outTradeNo)
throws WeixinException {
JSONObject obj = new JSONObject();
obj.put("nonce_str", RandomUtil.generateString(16));
obj.put("mch_id", weixinAccount.getMchId());
obj.put("appid", weixinAccount.getId());
obj.put("partner_trade_no", outTradeNo);
String sign = PayUtil.paysignMd5(obj, weixinAccount.getPaySignKey());
obj.put("sign", sign);
String param = XmlStream.map2xml(obj);
WeixinResponse response = null;
InputStream ca = null;
try {
ca = new FileInputStream(caFile);
SSLHttpClinet request = new SSLHttpClinet(weixinAccount.getMchId(),
ca);
response = request.post(PayURLConsts.MCH_ENPAYQUERY_URL, param);
} catch (WeixinException e) {
throw e;
} catch (IOException e) {
throw new WeixinException(e.getMessage());
} finally {
if (ca != null) {
try {
ca.close();
} catch (IOException e) {
;
}
}
}
return response.getAsObject(new TypeReference<MPPaymentRecord>() {
});
}
}
@@ -0,0 +1,173 @@
package com.foxinmy.weixin4j.api;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import com.alibaba.fastjson.TypeReference;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.weixin.SSLHttpClinet;
import com.foxinmy.weixin4j.http.weixin.WeixinHttpClient;
import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
import com.foxinmy.weixin4j.model.WeixinPayAccount;
import com.foxinmy.weixin4j.payment.PayURLConsts;
import com.foxinmy.weixin4j.payment.PayUtil;
import com.foxinmy.weixin4j.payment.coupon.CouponDetail;
import com.foxinmy.weixin4j.payment.coupon.CouponResult;
import com.foxinmy.weixin4j.payment.coupon.CouponStock;
import com.foxinmy.weixin4j.util.RandomUtil;
import com.foxinmy.weixin4j.util.StringUtil;
import com.foxinmy.weixin4j.xml.XmlStream;
/**
* 代金券API
*
* @className CouponApi
* @author jy
* @date 2015年3月25日
* @since JDK 1.7
* @see <a href="http://pay.weixin.qq.com/wiki/doc/api/sp_coupon.php">代金券文档</a>
*/
public class CouponApi {
private final WeixinHttpClient weixinClient;
private final WeixinPayAccount weixinAccount;
public CouponApi(WeixinPayAccount weixinAccount) {
this.weixinAccount = weixinAccount;
this.weixinClient = new WeixinHttpClient();
}
/**
* 发放代金券(需要证书)
*
* @param caFile
* 证书文件(后缀为*.p12)
* @param couponStockId
* 代金券批次id
* @param partnerTradeNo
* 商户发放凭据号(格式:商户id+日期+流水号),商户侧需保持唯一性
* @param openId
* 用户的openid
* @param opUserId
* 操作员帐号, 默认为商户号 可在商户平台配置操作员对应的api权限 可为空
* @return 发放结果
* @see com.foxinmy.weixin4j.payment.coupon.CouponResult
* @see <a
* href="http://pay.weixin.qq.com/wiki/doc/api/sp_coupon.php?chapter=12_3">发放代金券接口</a>
* @throws WeixinException
*/
public CouponResult sendCoupon(File caFile, String couponStockId,
String partnerTradeNo, String openId, String opUserId)
throws WeixinException {
Map<String, String> map = baseMap();
map.put("coupon_stock_id", couponStockId);
map.put("partner_trade_no", partnerTradeNo);
map.put("openid", openId);
// openid记录数(目前支持num=1
map.put("openid_count", "1");
// 操作员帐号, 默认为商户号 可在商户平台配置操作员对应的api权限
if (StringUtil.isBlank(opUserId)) {
opUserId = weixinAccount.getMchId();
}
map.put("op_user_id", opUserId);
map.put("version", "1.0");
map.put("type", "XML");
String sign = PayUtil.paysignMd5(map, weixinAccount.getPaySignKey());
map.put("sign", sign);
String param = XmlStream.map2xml(map);
WeixinResponse response = null;
InputStream ca = null;
try {
ca = new FileInputStream(caFile);
SSLHttpClinet request = new SSLHttpClinet(weixinAccount.getMchId(),
ca);
response = request.post(PayURLConsts.MCH_COUPONSEND_URL, param);
} catch (WeixinException e) {
throw e;
} catch (IOException e) {
throw new WeixinException(e.getMessage());
} finally {
if (ca != null) {
try {
ca.close();
} catch (IOException e) {
;
}
}
}
return response.getAsObject(new TypeReference<CouponResult>() {
});
}
/**
* 查询代金券批次
*
* @param couponStockId
* 代金券批次ID
* @return 代金券批次信息
* @see com.foxinmy.weixin4j.payment.coupon.CouponStock
* @see <a
* href="http://pay.weixin.qq.com/wiki/doc/api/sp_coupon.php?chapter=12_4">查询代金券批次信息</a>
* @throws WeixinException
*/
public CouponStock queryCouponStock(String couponStockId)
throws WeixinException {
Map<String, String> map = baseMap();
map.put("coupon_stock_id", couponStockId);
String sign = PayUtil.paysignMd5(map, weixinAccount.getPaySignKey());
map.put("sign", sign);
String param = XmlStream.map2xml(map);
WeixinResponse response = weixinClient.post(
PayURLConsts.MCH_COUPONSTOCKQUERY_URL, param);
return response.getAsObject(new TypeReference<CouponStock>() {
});
}
/**
* 查询代金券详细
*
* @param couponId
* 代金券ID
* @return 代金券详细信息
* @see com.foxinmy.weixin4j.payment.coupon.CouponDetail
* @see <a
* href="http://pay.weixin.qq.com/wiki/doc/api/sp_coupon.php?chapter=12_5">查询代金券详细信息</a>
* @throws WeixinException
*/
public CouponDetail queryCouponDetail(String couponId)
throws WeixinException {
Map<String, String> map = baseMap();
map.put("coupon_id", couponId);
String sign = PayUtil.paysignMd5(map, weixinAccount.getPaySignKey());
map.put("sign", sign);
String param = XmlStream.map2xml(map);
WeixinResponse response = weixinClient.post(
PayURLConsts.MCH_COUPONDETAILQUERY_URL, param);
return response.getAsObject(new TypeReference<CouponDetail>() {
});
}
/**
* 接口请求基本数据
*
* @return
*/
private Map<String, String> baseMap() {
Map<String, String> map = new HashMap<String, String>();
map.put("appid", weixinAccount.getId());
map.put("mch_id", weixinAccount.getMchId());
map.put("nonce_str", RandomUtil.generateString(16));
if (StringUtil.isNotBlank(weixinAccount.getDeviceInfo())) {
map.put("device_info", weixinAccount.getDeviceInfo());
}
if (StringUtil.isNotBlank(weixinAccount.getSubMchId())) {
map.put("sub_mch_id", weixinAccount.getSubMchId());
}
return map;
}
}
@@ -0,0 +1,464 @@
package com.foxinmy.weixin4j.api;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.weixin.SSLHttpClinet;
import com.foxinmy.weixin4j.http.weixin.WeixinHttpClient;
import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
import com.foxinmy.weixin4j.http.weixin.XmlResult;
import com.foxinmy.weixin4j.model.Consts;
import com.foxinmy.weixin4j.model.WeixinPayAccount;
import com.foxinmy.weixin4j.payment.PayURLConsts;
import com.foxinmy.weixin4j.payment.PayUtil;
import com.foxinmy.weixin4j.payment.mch.ApiResult;
import com.foxinmy.weixin4j.payment.mch.Order;
import com.foxinmy.weixin4j.payment.mch.RefundRecord;
import com.foxinmy.weixin4j.payment.mch.RefundResult;
import com.foxinmy.weixin4j.type.BillType;
import com.foxinmy.weixin4j.type.CurrencyType;
import com.foxinmy.weixin4j.type.IdQuery;
import com.foxinmy.weixin4j.type.IdType;
import com.foxinmy.weixin4j.util.ConfigUtil;
import com.foxinmy.weixin4j.util.DateUtil;
import com.foxinmy.weixin4j.util.RandomUtil;
import com.foxinmy.weixin4j.util.StringUtil;
import com.foxinmy.weixin4j.xml.ListsuffixResultDeserializer;
import com.foxinmy.weixin4j.xml.XmlStream;
/**
* (商户平台版)支付API
*
* @className Pay3Api
* @author jy
* @date 2014年10月28日
* @since JDK 1.7
* @see <a href="http://pay.weixin.qq.com/wiki/doc/api/index.html">商户平台API</a>
*/
public class Pay3Api {
private final WeixinHttpClient weixinClient;
private final WeixinPayAccount weixinAccount;
public Pay3Api(WeixinPayAccount weixinAccount) {
this.weixinAccount = weixinAccount;
this.weixinClient = new WeixinHttpClient();
}
/**
* 订单查询
* <p>
* 当商户后台、网络、服务器等出现异常,商户系统最终未接收到支付通知;</br> 调用支付接口后,返回系统错误或未知交易状态情况;</br>
* 调用被扫支付API,返回USERPAYING的状态;</br> 调用关单或撤销接口API之前,需确认支付状态;
* </P>
*
* @param idQuery
* 商户系统内部的订单号, transaction_id、out_trade_no 二 选一,如果同时存在优先级:
* transaction_id> out_trade_no
* @return 订单信息
* @see com.foxinmy.weixin4j.payment.mch.Order
* @see <a
* href="http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_2">订单查询API</a>
* @since V3
* @throws WeixinException
*/
public Order orderQuery(IdQuery idQuery) throws WeixinException {
Map<String, String> map = baseMap(idQuery);
String sign = PayUtil.paysignMd5(map, weixinAccount.getPaySignKey());
map.put("sign", sign);
String param = XmlStream.map2xml(map);
WeixinResponse response = weixinClient.post(
PayURLConsts.MCH_ORDERQUERY_URL, param);
return ListsuffixResultDeserializer.deserialize(response.getAsString(),
Order.class);
}
/**
* 申请退款(请求需要双向证书)
* <p>
* 当交易发生之后一段时间内,由于买家或者卖家的原因需要退款时,卖家可以通过退款接口将支付款退还给买家,微信支付将在收到退款请求并且验证成功之后,
* 按照退款规则将支付款按原路退到买家帐号上。
* </p>
* <p style="color:red">
* 1.交易时间超过半年的订单无法提交退款;
* 2.微信支付退款支持单笔交易分多次退款,多次退款需要提交原支付订单的商户订单号和设置不同的退款单号。一笔退款失败后重新提交
* ,要采用原来的退款单号。总退款金额不能超过用户实际支付金额。
* </p>
*
* @param caFile
* 证书文件(V3版本后缀为*.p12)
* @param idQuery
* 商户系统内部的订单号, transaction_id 、 out_trade_no 二选一,如果同时存在优先级:
* transaction_id> out_trade_no
* @param outRefundNo
* 商户系统内部的退款单号,商 户系统内部唯一,同一退款单号多次请求只退一笔
* @param totalFee
* 订单总金额,单位为元
* @param refundFee
* 退款总金额,单位为元,可以做部分退款
* @param opUserId
* 操作员帐号, 默认为商户号
*
* @return 退款申请结果
* @see com.foxinmy.weixin4j.payment.mch.RefundResult
* @see <a
* href="http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4">申请退款API</a>
* @since V3
* @throws WeixinException
*/
protected RefundResult refundApply(File caFile, IdQuery idQuery,
String outRefundNo, double totalFee, double refundFee,
String opUserId, Map<String, String> mopara) throws WeixinException {
WeixinResponse response = null;
InputStream ca = null;
try {
ca = new FileInputStream(caFile);
Map<String, String> map = baseMap(idQuery);
map.put("out_refund_no", outRefundNo);
map.put("total_fee", DateUtil.formaFee2Fen(totalFee));
map.put("refund_fee", DateUtil.formaFee2Fen(refundFee));
if (StringUtil.isBlank(opUserId)) {
opUserId = weixinAccount.getMchId();
}
map.put("op_user_id", opUserId);
if (mopara != null && !mopara.isEmpty()) {
map.putAll(mopara);
}
String sign = PayUtil
.paysignMd5(map, weixinAccount.getPaySignKey());
map.put("sign", sign);
String param = XmlStream.map2xml(map);
SSLHttpClinet request = new SSLHttpClinet(weixinAccount.getMchId(),
ca);
response = request.post(PayURLConsts.MCH_REFUNDAPPLY_URL, param);
} catch (WeixinException e) {
throw e;
} catch (IOException e) {
throw new WeixinException(e.getMessage());
} finally {
if (ca != null) {
try {
ca.close();
} catch (IOException e) {
;
}
}
}
return response.getAsObject(new TypeReference<RefundResult>() {
});
}
/**
* 退款申请
*
* @param caFile
* 证书文件(V3版本后缀为*.p12)
* @param idQuery
* 商户系统内部的订单号, transaction_id 、 out_trade_no 二选一,如果同时存在优先级:
* transaction_id> out_trade_no
* @param outRefundNo
* 商户系统内部的退款单号,商 户系统内部唯一,同一退款单号多次请求只退一笔
* @param totalFee
* 订单总金额,单位为元
* @param refundFee
* 退款总金额,单位为元,可以做部分退款
* @param refundFeeType
* 货币类型,符合ISO 4217标准的三位字母代码,默认人民币:CNY
* @param opUserId
* 操作员帐号, 默认为商户号
* @see {@link com.foxinmy.weixin4j.api.Pay3Api#refundApply(File, IdQuery, String, double, double, String, Map)}
*/
public RefundResult refundApply(File caFile, IdQuery idQuery,
String outRefundNo, double totalFee, double refundFee,
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 refundApply(caFile, idQuery, outRefundNo, totalFee, refundFee,
opUserId, mopara);
}
/**
* 冲正订单(需要证书)</br> 当支付返回失败,或收银系统超时需要取消交易,可以调用该接口</br> 接口逻辑:支
* 付失败的关单,支付成功的撤销支付</br> <font color="red">7天以内的单可撤销,其他正常支付的单
* 如需实现相同功能请调用退款接口</font></br> <font
* color="red">调用扣款接口后请勿立即调用撤销,需要等待5秒以上。先调用查单接口,如果没有确切的返回,再调用撤销</font></br>
*
* @param caFile
* 证书文件(V3版本后缀为*.p12)
* @param idQuery
* 商户系统内部的订单号, transaction_id 、 out_trade_no 二选一,如果同时存在优先级:
* transaction_id> out_trade_no
* @return 撤销结果
* @since V3
* @throws WeixinException
*/
public ApiResult reverseOrder(File caFile, IdQuery idQuery)
throws WeixinException {
InputStream ca = null;
try {
ca = new FileInputStream(caFile);
SSLHttpClinet request = new SSLHttpClinet(weixinAccount.getMchId(),
ca);
Map<String, String> map = baseMap(idQuery);
String sign = PayUtil
.paysignMd5(map, weixinAccount.getPaySignKey());
map.put("sign", sign);
String param = XmlStream.map2xml(map);
WeixinResponse response = request.post(
PayURLConsts.MCH_ORDERREVERSE_URL, param);
return response.getAsObject(new TypeReference<ApiResult>() {
});
} catch (IOException e) {
throw new WeixinException(e.getMessage());
} finally {
if (ca != null) {
try {
ca.close();
} catch (IOException e) {
;
}
}
}
}
/**
* native支付URL转短链接:用于扫码原生支付模式一中的二维码链接转成短链接(weixin://wxpay/s/XXXXXX),减小二维码数据量
* ,提升扫描速度和精确度。
*
* @param url
* 具有native标识的支付URL
* @return 转换后的短链接
* @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 {
Map<String, String> map = baseMap(null);
try {
map.put("long_url", URLEncoder.encode(url, Consts.UTF_8.name()));
} catch (UnsupportedEncodingException ignore) {
;
}
String sign = PayUtil.paysignMd5(map, weixinAccount.getPaySignKey());
map.put("sign", sign);
String param = XmlStream.map2xml(map);
WeixinResponse response = weixinClient.post(
PayURLConsts.MCH_SHORTURL_URL, param);
map = XmlStream.xml2map(response.getAsString());
return map.get("short_url");
}
/**
* 关闭订单
* <p>
* 商户订单支付失败需要生成新单号重新发起支付,要对原订单号调用关单,避免重复支付;系统下单后,用户支付超时,系统退出不再受理,避免用户继续
* ,请调用关单接口,如果关单失败,返回已完 成支付请按正常支付处理。如果出现银行掉单,调用关单成功后,微信后台会主动发起退款。
* </p>
*
* @param outTradeNo
* 商户系统内部的订单号
* @return 处理结果
* @since V3
* @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 {
Map<String, String> map = baseMap(new IdQuery(outTradeNo,
IdType.TRADENO));
String sign = PayUtil.paysignMd5(map, weixinAccount.getPaySignKey());
map.put("sign", sign);
String param = XmlStream.map2xml(map);
WeixinResponse response = weixinClient.post(
PayURLConsts.MCH_CLOSEORDER_URL, param);
return response.getAsObject(new TypeReference<ApiResult>() {
});
}
/**
* 下载对账单<br>
* 1.微信侧未成功下单的交易不会出现在对账单中。支付成功后撤销的交易会出现在对账 单中,跟原支付单订单号一致,bill_type 为
* REVOKED;<br>
* 2.微信在次日 9 点启动生成前一天的对账单,建议商户 9 点半后再获取;<br>
* 3.对账单中涉及金额的字段单位为“元”。<br>
*
* @param billDate
* 下载对账单的日期
* @param billType
* 下载对账单的类型 ALL,返回当日所有订单信息, 默认值 SUCCESS,返回当日成功支付的订单
* REFUND,返回当日退款订单
* @return excel表格
* @since V3
* @see <a
* href="http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_6">下载对账单API</a>
* @throws WeixinException
*/
public File downloadbill(Date billDate, BillType billType)
throws WeixinException {
if (billDate == null) {
Calendar now = Calendar.getInstance();
now.add(Calendar.DAY_OF_MONTH, -1);
billDate = now.getTime();
}
if (billType == null) {
billType = BillType.ALL;
}
String formatBillDate = DateUtil.fortmat2yyyyMMdd(billDate);
String bill_path = ConfigUtil.getValue("bill_path");
String fileName = String.format("%s_%s_%s.txt", formatBillDate,
billType.name().toLowerCase(), weixinAccount.getId());
File file = new File(String.format("%s/%s", bill_path, fileName));
if (file.exists()) {
return file;
}
Map<String, String> map = baseMap(null);
map.put("bill_date", formatBillDate);
map.put("bill_type", billType.name());
String sign = PayUtil.paysignMd5(map, weixinAccount.getPaySignKey());
map.put("sign", sign);
String param = XmlStream.map2xml(map);
WeixinResponse response = weixinClient.post(
PayURLConsts.MCH_DOWNLOADBILL_URL, param);
BufferedReader reader = null;
BufferedWriter writer = null;
FileWriter fw = null;
try {
fw = new FileWriter(file);
writer = new BufferedWriter(fw);
reader = new BufferedReader(new InputStreamReader(
new ByteArrayInputStream(response.getContent()),
com.foxinmy.weixin4j.model.Consts.GBK));
String line = null;
while ((line = reader.readLine()) != null) {
writer.write(line);
writer.newLine();
}
} catch (IOException e) {
throw new WeixinException(e.getMessage());
} finally {
try {
if (reader != null) {
reader.close();
}
if (writer != null) {
writer.close();
fw.close();
}
} catch (IOException ignore) {
;
}
}
return file;
}
/**
* 退款查询
*
* <p>
* 提交退款申请后,通过调用该接口查询退款状态。退款有一定延时,用零钱支付的退款20分钟内到账,银行卡支付的退款3个工作日后重新查询退款状态。
* </p>
*
* @param idQuery
* 单号 refund_id、out_refund_no、 out_trade_no 、 transaction_id
* 四个参数必填一个,优先级为:
* refund_id>out_refund_no>transaction_id>out_trade_no
* @return 退款记录
* @see com.foxinmy.weixin4j.payment.mch.RefundRecord
* @see com.foxinmy.weixin4j.payment.mch.RefundDetail
* @see <a
* href="http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_5">退款查询API</a>
* @since V3
* @throws WeixinException
*/
public RefundRecord refundQuery(IdQuery idQuery) throws WeixinException {
Map<String, String> map = baseMap(idQuery);
String sign = PayUtil.paysignMd5(map, weixinAccount.getPaySignKey());
map.put("sign", sign);
String param = XmlStream.map2xml(map);
WeixinResponse response = weixinClient.post(
PayURLConsts.MCH_REFUNDQUERY_URL, param);
return ListsuffixResultDeserializer.deserialize(response.getAsString(),
RefundRecord.class);
}
/**
* 接口上报
*
* @param interfaceUrl
* 上报对应的接口的完整 URL, 类似: https://api.mch.weixin.q
* q.com/pay/unifiedorder
* @param executeTime
* 接口耗时情况,单位为毫秒
* @param outTradeNo
* 商户系统内部的订单号,商 户可以在上报时提供相关商户订单号方便微信支付更好 的提高服务质量。
* @param ip
* 发起接口调用时的机器 IP
* @param time
* 商户调用该接口时商户自己 系统的时间
* @param returnXml
* 调用接口返回的基本数据
* @return 处理结果
* @throws WeixinException
* @see <a
* href="http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_8">接口测试上报API</a>
*/
@SuppressWarnings("unchecked")
public XmlResult interfaceReport(String interfaceUrl, int executeTime,
String outTradeNo, String ip, Date time, XmlResult returnXml)
throws WeixinException {
Map<String, String> map = baseMap(null);
map.put("interface_url", interfaceUrl);
map.put("execute_time_", Integer.toString(executeTime));
map.put("out_trade_no", outTradeNo);
map.put("user_ip", ip);
map.put("time", DateUtil.fortmat2yyyyMMddHHmmss(time));
map.putAll((Map<String, String>) JSON.toJSON(returnXml));
String sign = PayUtil.paysignMd5(map, weixinAccount.getPaySignKey());
map.put("sign", sign);
String param = XmlStream.map2xml(map);
WeixinResponse response = weixinClient.post(
PayURLConsts.MCH_PAYREPORT_URL, param);
return response.getAsXmlResult();
}
/**
* V3接口请求基本数据
*
* @return
*/
private Map<String, String> baseMap(IdQuery idQuery) {
Map<String, String> map = new HashMap<String, String>();
map.put("appid", weixinAccount.getId());
map.put("mch_id", weixinAccount.getMchId());
map.put("nonce_str", RandomUtil.generateString(16));
if (StringUtil.isNotBlank(weixinAccount.getDeviceInfo())) {
map.put("device_info", weixinAccount.getDeviceInfo());
}
if (idQuery != null) {
map.put(idQuery.getType().getName(), idQuery.getId());
}
return map;
}
}
@@ -1,15 +1,15 @@
package com.foxinmy.weixin4j.page;
package com.foxinmy.weixin4j.model;
import java.io.Serializable;
import com.foxinmy.weixin4j.page.Sort.Direction;
import com.foxinmy.weixin4j.model.Sort.Direction;
/**
* @className Pageable
* @author jy
* @date 2014年12月27日
* @since JDK 1.7
* @see com.foxinmy.weixin4j.page.springframework.data.domain.Pageable
* @see com.foxinmy.weixin4j.model.springframework.data.domain.Pageable
*/
public class Pageable implements Serializable {
@@ -1,4 +1,4 @@
package com.foxinmy.weixin4j.page;
package com.foxinmy.weixin4j.model;
import java.io.Serializable;
import java.util.Iterator;
@@ -1,4 +1,4 @@
package com.foxinmy.weixin4j.page;
package com.foxinmy.weixin4j.model;
import java.io.Serializable;
import java.util.ArrayList;
@@ -29,6 +29,7 @@ public class WeixinAccount implements Serializable {
private String encodingAesKey;
public WeixinAccount() {
}
public WeixinAccount(String id, String secret) {
@@ -0,0 +1,134 @@
package com.foxinmy.weixin4j.model;
import com.alibaba.fastjson.annotation.JSONCreator;
import com.alibaba.fastjson.annotation.JSONField;
import com.foxinmy.weixin4j.util.StringUtil;
/**
* 微信支付账户
*
* @className WeixinPayAccount
* @author jy
* @date 2015年6月26日
* @since JDK 1.7
* @see
*/
public class WeixinPayAccount extends WeixinAccount {
private static final long serialVersionUID = -2791256176906048632L;
/**
* 公众号支付请求中用于加密的密钥 Key,可验证商户唯一身份,PaySignKey 对应于支付场景中的 appKey 值
*/
private String paySignKey;
/**
* 财付通商户身份的标识
*/
private String partnerId;
/**
* 财付通商户权限密钥Key
*/
private String partnerKey;
/**
* 微信支付分配的商户号(商户平台版)
*/
private String mchId;
/**
* 微信支付分配的子商户号,受理模式下必填(商户平台版)
*/
private String subMchId;
/**
* 微信支付分配的设备号(商户平台版)
*/
private String deviceInfo;
/**
* 微信支付版本号(如果无则按照mchId来做判断)
*/
private int version;
/**
* 商户平台版本(V3)字段
*
* @param appId
* 公众号唯一的身份ID
* @param appSecret
* 调用接口的凭证
* @param paySignKey
* 支付密钥字符串
* @param mchId
* 微信支付分配的商户号
*/
@JSONCreator
public WeixinPayAccount(@JSONField(name = "appId") String appId,
@JSONField(name = "appSecret") String appSecret,
@JSONField(name = "paySignKey") String paySignKey,
@JSONField(name = "mchId") String mchId) {
super(appId, appSecret);
this.paySignKey = paySignKey;
this.mchId = mchId;
}
/**
* V2版本字段
*
* @param appId
* 公众号唯一的身份ID
* @param appSecret
* 调用接口的凭证
* @param paySignKey
* 支付密钥字符串
* @param partnerId
* 财付通账号的ID
* @param partnerKey
* 财付通账号的key
*/
@JSONCreator
public WeixinPayAccount(@JSONField(name = "appId") String appId,
@JSONField(name = "appSecret") String appSecret,
@JSONField(name = "paySignKey") String paySignKey,
@JSONField(name = "partnerId") String partnerId,
@JSONField(name = "partnerKey") String partnerKey) {
super(appId, appSecret);
this.paySignKey = paySignKey;
this.partnerId = partnerId;
this.partnerKey = partnerKey;
}
public String getPaySignKey() {
return paySignKey;
}
public String getPartnerId() {
return partnerId;
}
public String getPartnerKey() {
return partnerKey;
}
public String getMchId() {
return mchId;
}
public String getSubMchId() {
return subMchId;
}
public String getDeviceInfo() {
return deviceInfo;
}
public int getVersion() {
if (version == 0) {
return StringUtil.isNotBlank(mchId) ? 3 : 2;
}
return version;
}
@Override
public String toString() {
return "WeixinPayAccount [paySignKey=" + paySignKey + ", partnerId="
+ partnerId + ", partnerKey=" + partnerKey + ", mchId=" + mchId
+ ", subMchId=" + subMchId + ", deviceInfo=" + deviceInfo
+ ", version=" + version + "]";
}
}
@@ -0,0 +1,66 @@
package com.foxinmy.weixin4j.payment;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import com.alibaba.fastjson.annotation.JSONField;
/**
* JSAPI支付回调时的POST信息
*
* @className JsPayNotify
* @author jy
* @date 2014年8月19日
* @since JDK 1.7
* @see
*/
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class JsPayNotify extends PayBaseInfo {
private static final long serialVersionUID = -4659030958445259803L;
/**
* 用户的openid
*/
@XmlElement(name = "OpenId")
private String openid;
/**
* 是否关注公众号
*/
@XmlElement(name = "IsSubscribe")
private int issubscribe;
public JsPayNotify() {
}
public String getOpenid() {
return openid;
}
public void setOpenid(String openid) {
this.openid = openid;
}
public int getIssubscribe() {
return issubscribe;
}
public void setIssubscribe(int issubscribe) {
this.issubscribe = issubscribe;
}
@JSONField(serialize = false, deserialize = false)
public boolean getFormatIssubscribe() {
return issubscribe == 1;
}
@Override
public String toString() {
return "openid=" + openid + ", issubscribe=" + getFormatIssubscribe()
+ ", " + super.toString();
}
}
@@ -0,0 +1,126 @@
package com.foxinmy.weixin4j.payment;
import java.util.Date;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import com.alibaba.fastjson.annotation.JSONField;
import com.foxinmy.weixin4j.model.WeixinPayAccount;
import com.foxinmy.weixin4j.util.RandomUtil;
/**
* 刷卡支付
*
* @className MicroPayPackage
* @author jy
* @date 2014年11月17日
* @since JDK 1.7
* @see
*/
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class MicroPayPackage extends PayPackage {
private static final long serialVersionUID = 8944928173669656177L;
/**
* 微信分配的公众账号 必须
*/
private String appid;
/**
* 微信支付分配的商户号 必须
*/
@XmlElement(name = "mch_id")
@JSONField(name = "mch_id")
private String mchId;
/**
* 微信支付分配的终端设备号 非必须
*/
@XmlElement(name = "device_info")
@JSONField(name = "device_info")
private String deviceInfo;
/**
* 随机字符串,不长于 32 位 必须
*/
@XmlElement(name = "nonce_str")
@JSONField(name = "nonce_str")
private String nonceStr;
/**
* 签名 <font color="red">调用者不必关注</font>
*/
private String sign;
/**
* 扫码支付授权码 ,设备读取用户微信中的条码或者二维码信息
*/
@XmlElement(name = "auth_code")
@JSONField(name = "auth_code")
private String authCode;
protected MicroPayPackage(){
// jaxb required
}
public MicroPayPackage(WeixinPayAccount weixinAccount, String body,
String attach, String outTradeNo, double totalFee,
String spbillCreateIp, String authCode) {
this(weixinAccount.getId(), weixinAccount.getMchId(), weixinAccount
.getDeviceInfo(), RandomUtil.generateString(16), body, attach,
outTradeNo, totalFee, spbillCreateIp, null, null, null,
authCode);
}
public MicroPayPackage(String appid, String mchId, String deviceInfo,
String nonceStr, String body, String attach, String outTradeNo,
double totalFee, String spbillCreateIp, Date timeStart,
Date timeExpire, String goodsTag, String authCode) {
super(body, attach, outTradeNo, totalFee, spbillCreateIp, timeStart,
timeExpire, goodsTag, null);
this.appid = appid;
this.mchId = mchId;
this.deviceInfo = deviceInfo;
this.nonceStr = nonceStr;
this.authCode = authCode;
}
public String getAppid() {
return appid;
}
public String getMchId() {
return mchId;
}
public String getDeviceInfo() {
return deviceInfo;
}
public String getNonceStr() {
return nonceStr;
}
public String getSign() {
return sign;
}
public void setSign(String sign) {
this.sign = sign;
}
public String getAuthCode() {
return authCode;
}
public void setAuthCode(String authCode) {
this.authCode = authCode;
}
@Override
public String toString() {
return "MicroPayPackage [appid=" + appid + ", mchId=" + mchId
+ ", deviceInfo=" + deviceInfo + ", nonceStr=" + nonceStr
+ ", sign=" + sign + ", authCode=" + authCode + ", "
+ super.toString() + "]";
}
}
@@ -0,0 +1,117 @@
package com.foxinmy.weixin4j.payment;
import java.io.Serializable;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import com.alibaba.fastjson.annotation.JSONField;
import com.foxinmy.weixin4j.type.SignType;
/**
* 基本信息
*
* @className PayBaseInfo
* @author jy
* @date 2014年11月5日
* @since JDK 1.7
* @see
*/
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class PayBaseInfo implements Serializable {
private static final long serialVersionUID = 1843024880782466990L;
/**
* 公众号ID
*/
@XmlElement(name = "AppId")
private String appId;
/**
* 时间戳
*/
@XmlElement(name = "TimeStamp")
private String timeStamp;
/**
* 随机字符串
*/
@XmlElement(name = "NonceStr")
private String nonceStr;
/**
* 签名结果
*/
@XmlElement(name = "AppSignature")
private String paySign;
/**
* 签名方式
*/
@XmlElement(name = "SignMethod")
private String signType;
public String getAppId() {
return appId;
}
public void setAppId(String appId) {
this.appId = appId;
}
public String getTimeStamp() {
return timeStamp;
}
public void setTimeStamp(String timeStamp) {
this.timeStamp = timeStamp;
}
public String getNonceStr() {
return nonceStr;
}
public void setNonceStr(String nonceStr) {
this.nonceStr = nonceStr;
}
public String getPaySign() {
return paySign;
}
public void setPaySign(String paySign) {
this.paySign = paySign;
}
public String getSignType() {
return signType;
}
@JSONField(serialize = false, deserialize = false)
public SignType getFormatSignType() {
return SignType.valueOf(signType.toUpperCase());
}
public void setSignType(SignType signType) {
if (signType != null) {
this.signType = signType.name();
} else {
this.signType = null;
}
}
public PayBaseInfo() {
}
public PayBaseInfo(String appId, String timestamp, String noncestr) {
this.appId = appId;
this.timeStamp = timestamp;
this.nonceStr = noncestr;
}
@Override
public String toString() {
return "appId=" + appId + ", timeStamp=" + timeStamp + ", nonceStr="
+ nonceStr + ", paySign=" + paySign + ", signType=" + signType;
}
}
@@ -0,0 +1,232 @@
package com.foxinmy.weixin4j.payment;
import java.io.Serializable;
import java.util.Date;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import com.alibaba.fastjson.annotation.JSONField;
import com.foxinmy.weixin4j.util.DateUtil;
/**
* 订单信息
*
* @className PayPackage
* @author jy
* @date 2014年12月18日
* @since JDK 1.7
* @see
*/
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class PayPackage implements Serializable {
private static final long serialVersionUID = 3450161267802545790L;
/**
* 商品描述 必须
*/
private String body;
/**
* 商品详情 非必须
*/
private String detail;
/**
* 附加数据,原样返回 非必须
*/
private String attach;
/**
* 商户系统内部的订单号 ,32 个字符内 、可包含字母 ,确保 在商户系统唯一 必须
*/
@XmlElement(name = "out_trade_no")
@JSONField(name = "out_trade_no")
private String outTradeNo;
/**
* 订单总金额,单位为分,不能带小数点 必须
*/
@XmlElement(name = "total_fee")
@JSONField(name = "total_fee")
private String totalFee;
/**
* 订单生成的机器 IP 必须
*/
@XmlElement(name = "spbill_create_ip")
@JSONField(name = "spbill_create_ip")
private String spbillCreateIp;
/**
* 订单生成时间,格式为 yyyyMMddHHmmss,如 2009 年 12月25日9点10分10秒表示为 20091225091010。时区 为
* GMT+8 beijing。该时间取 自商户服务器 非必须
*/
@XmlElement(name = "time_start")
@JSONField(name = "time_start")
private String timeStart;
/**
* 订单失效时间,格为 yyyyMMddHHmmss,如 2009 年 12月27日9点10分10秒表示为 20091227091010。时区 为
* GMT+8 beijing。该时间取 自商户服务商品标记 非必须
*/
@XmlElement(name = "time_expire")
@JSONField(name = "time_expire")
private String timeExpire;
/**
* 商品标记,该字段不能随便填,不使用请填空 非必须
*/
@XmlElement(name = "goods_tag")
@JSONField(name = "goods_tag")
private String goodsTag;
/**
* 通知地址接收微信支付成功通知 必须
*/
@XmlElement(name = "notify_url")
@JSONField(name = "notify_url")
private String notifyUrl;
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public String getDetail() {
return detail;
}
public void setDetail(String detail) {
this.detail = detail;
}
public String getAttach() {
return attach;
}
public void setAttach(String attach) {
this.attach = attach;
}
public String getOutTradeNo() {
return outTradeNo;
}
public void setOutTradeNo(String outTradeNo) {
this.outTradeNo = outTradeNo;
}
public String getTotalFee() {
return totalFee;
}
/**
* <font color="red">单位为元,自动格式化为分</font>
*
* @param totalFee
* 订单总额 单位为元
*/
public void setTotalFee(double totalFee) {
this.totalFee = DateUtil.formaFee2Fen(totalFee);
}
public String getSpbillCreateIp() {
return spbillCreateIp;
}
public void setSpbillCreateIp(String spbillCreateIp) {
this.spbillCreateIp = spbillCreateIp;
}
public String getTimeStart() {
return timeStart;
}
public void setTimeStart(String timeStart) {
this.timeStart = timeStart;
}
public void setTimeExpire(String timeExpire) {
this.timeExpire = timeExpire;
}
public void setTimeStart(Date timeStart) {
this.timeStart = timeStart != null ? DateUtil
.fortmat2yyyyMMddHHmmss(timeStart) : null;
}
public String getTimeExpire() {
return timeExpire;
}
public void setTimeExpire(Date timeExpire) {
this.timeExpire = timeExpire != null ? DateUtil
.fortmat2yyyyMMddHHmmss(timeExpire) : null;
}
public String getGoodsTag() {
return goodsTag;
}
public void setGoodsTag(String goodsTag) {
this.goodsTag = goodsTag;
}
public String getNotifyUrl() {
return notifyUrl;
}
public void setNotifyUrl(String notifyUrl) {
this.notifyUrl = notifyUrl;
}
protected PayPackage(){
// jaxb required
}
/**
* 订单对象
*
* @param body
* 订单描述
* @param attach
* 附加数据
* @param outTradeNo
* 商户内部ID
* @param totalFee
* 订单总额 <font color="red">单位为元</font>
* @param spbillCreateIp
* 生成订单数据的机器IP
* @param timeStart
* 订单生成时间
* @param timeExpire
* 订单失效时间
* @param goodsTag
* 订单标记
* @param notifyUrl
* 回调地址
*/
public PayPackage(String body, String attach, String outTradeNo,
double totalFee, String spbillCreateIp, Date timeStart,
Date timeExpire, String goodsTag, String notifyUrl) {
this.body = body;
this.attach = attach;
this.outTradeNo = outTradeNo;
this.totalFee = DateUtil.formaFee2Fen(totalFee);
this.spbillCreateIp = spbillCreateIp;
this.timeStart = timeStart != null ? DateUtil
.fortmat2yyyyMMddHHmmss(timeStart) : null;
this.timeExpire = timeExpire != null ? DateUtil
.fortmat2yyyyMMddHHmmss(timeExpire) : null;
this.goodsTag = goodsTag;
this.notifyUrl = notifyUrl;
}
@Override
public String toString() {
return "PayPackage [body=" + body + ", detail=" + detail + ", attach="
+ attach + ", outTradeNo=" + outTradeNo + ", totalFee="
+ totalFee + ", spbillCreateIp=" + spbillCreateIp
+ ", timeStart=" + timeStart + ", timeExpire=" + timeExpire
+ ", goodsTag=" + goodsTag + ", notifyUrl=" + notifyUrl + "]";
}
}
@@ -0,0 +1,46 @@
package com.foxinmy.weixin4j.payment;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import com.alibaba.fastjson.annotation.JSONField;
import com.foxinmy.weixin4j.util.DateUtil;
import com.foxinmy.weixin4j.util.RandomUtil;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class PayRequest extends PayBaseInfo {
private static final long serialVersionUID = -453746488398523883L;
/**
* 订单详情扩展 订单信息组成该字符串
*/
@XmlElement(name = "Package")
@JSONField(name = "package")
private String packageInfo;
public PayRequest() {
super(null, DateUtil.timestamp2string(), RandomUtil.generateString(16));
}
public PayRequest(String appId, String packageInfo) {
super(appId, DateUtil.timestamp2string(), RandomUtil.generateString(16));
this.packageInfo = packageInfo;
}
public String getPackageInfo() {
return packageInfo;
}
public void setPackageInfo(String packageInfo) {
this.packageInfo = packageInfo;
}
@Override
public String toString() {
return "package" + packageInfo + ", " + super.toString();
}
}
@@ -0,0 +1,105 @@
package com.foxinmy.weixin4j.payment;
/**
* 支付URL常量类
*
* @className PayURLConsts
* @author jy
* @date 2014年12月3日
* @since JDK 1.7
* @see
*/
public final class PayURLConsts {
private static final String MCH_BASE_URL = "https://api.mch.weixin.qq.com";
/**
* 商户平台下统一订单生成的url
*/
public static final String MCH_UNIFIEDORDER_URL = MCH_BASE_URL
+ "/pay/unifiedorder";
/**
* 订单查询(商户平台)
*/
public static final String MCH_ORDERQUERY_URL = MCH_BASE_URL
+ "/pay/orderquery";
/**
* 关闭订单(商户平台)
*/
public static final String MCH_CLOSEORDER_URL = MCH_BASE_URL
+ "/pay/closeorder";
/**
* 对账单下载(商户平台)
*/
public static final String MCH_DOWNLOADBILL_URL = MCH_BASE_URL
+ "/pay/downloadbill";
/**
* 退款查询(商户平台)
*/
public static final String MCH_REFUNDQUERY_URL = MCH_BASE_URL
+ "/pay/refundquery";
/**
* 退款申请(商户平台)
*/
public static final String MCH_REFUNDAPPLY_URL = MCH_BASE_URL
+ "/secapi/pay/refund";
/**
* 冲正撤销(商户平台)
*/
public static final String MCH_ORDERREVERSE_URL = MCH_BASE_URL
+ "/secapi/pay/reverse";
/**
* 被扫支付&刷卡支付(商户平台)
*/
public static final String MCH_MICROPAY_URL = MCH_BASE_URL
+ "/pay/micropay";
/**
* 接口上报(商户平台)
*/
public static final String MCH_PAYREPORT_URL = MCH_BASE_URL
+ "/payitil/report";
/**
* 发送现金红包(商户平台)
*/
public static final String MCH_REDPACKSEND_URL = MCH_BASE_URL
+ "/mmpaymkttransfers/sendredpack";
/**
* 查询现金红包(商户平台)
*/
public static final String MCH_REDPACKQUERY_URL = MCH_BASE_URL
+ "/mmpaymkttransfers/gethbinfo";
/**
* 企业向个人付款(商户平台)
*/
public static final String MCH_ENPAYMENT_URL = MCH_BASE_URL
+ "/mmpaymkttransfers/promotion/transfers";
/**
* 企业付款查询(商户平台)
*/
public static final String MCH_ENPAYQUERY_URL = MCH_BASE_URL
+ "/mmpaymkttransfers/gettransferinfo";
/**
* 发放代金券(商户平台)
*/
public static final String MCH_COUPONSEND_URL = MCH_BASE_URL
+ "/mmpaymkttransfers/send_coupon";
/**
* 查询代金券批次信息(商户平台)
*/
public static final String MCH_COUPONSTOCKQUERY_URL = MCH_BASE_URL
+ "/mmpaymkttransfers/query_coupon_stock";
/**
* 查询代金券详细信息(商户平台)
*/
public static final String MCH_COUPONDETAILQUERY_URL = MCH_BASE_URL
+ "/promotion/query_coupon";
/**
* 长链接转换(商户平台)
*/
public static final String MCH_SHORTURL_URL = MCH_BASE_URL
+ "/tools/shorturl";
/**
* 商户平台下native支付的url
*/
public static final String MCH_NATIVE_URL = "weixin://wxpay/bizpayurl?sign=%s&appid=%s&mch_id=%s&product_id=%s&time_stamp=%s&nonce_str=%s";
}
@@ -0,0 +1,290 @@
package com.foxinmy.weixin4j.payment;
import java.util.HashMap;
import java.util.Map;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.foxinmy.weixin4j.exception.PayException;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.weixin.WeixinHttpClient;
import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
import com.foxinmy.weixin4j.model.Consts;
import com.foxinmy.weixin4j.model.WeixinPayAccount;
import com.foxinmy.weixin4j.payment.mch.MchPayPackage;
import com.foxinmy.weixin4j.payment.mch.MchPayRequest;
import com.foxinmy.weixin4j.payment.mch.Order;
import com.foxinmy.weixin4j.payment.mch.PrePay;
import com.foxinmy.weixin4j.type.SignType;
import com.foxinmy.weixin4j.type.TradeType;
import com.foxinmy.weixin4j.util.ConfigUtil;
import com.foxinmy.weixin4j.util.DateUtil;
import com.foxinmy.weixin4j.util.DigestUtil;
import com.foxinmy.weixin4j.util.MapUtil;
import com.foxinmy.weixin4j.util.RandomUtil;
import com.foxinmy.weixin4j.util.StringUtil;
import com.foxinmy.weixin4j.xml.XmlStream;
/**
* 支付工具类(JSAPI,NATIVE,MicroPay)
*
* @className PayUtil
* @author jy
* @date 2014年10月28日
* @since JDK 1.7
* @see
*/
public class PayUtil {
/**
* md5签名(一般用于V3.x支付接口)
*
* @param obj
* 签名对象
* @param paySignKey
* 支付API的密钥
* @return
*/
public static String paysignMd5(Object obj, String paySignKey) {
StringBuilder sb = new StringBuilder();
// a--->string1
sb.append(MapUtil.toJoinString(obj, false, false, null));
// b--->
// 在 string1 最后拼接上 key=paternerKey 得到 stringSignTemp 字符串,并 对
// stringSignTemp 进行 md5 运算
// 再将得到的 字符串所有字符转换为大写 ,得到 sign 值 signValue。
sb.append("&key=").append(paySignKey);
return DigestUtil.MD5(sb.toString()).toUpperCase();
}
/**
* 生成V3.x版本JSAPI支付字符串
*
* @param openId
* 用户ID
* @param body
* 订单描述
* @param orderNo
* 订单号
* @param orderFee
* 订单总额 按实际金额传入即可(元) 构造函数会转换为分
* @param notifyUrl
* 支付通知地址
* @param ip
* ip地址
* @param weixinAccount
* 商户信息
* @return 支付json串
* @throws PayException
*/
public static String createPayJsRequestJson(String openId, String body,
String orderNo, double orderFee, String notifyUrl, String ip,
WeixinPayAccount weixinAccount) throws PayException {
MchPayPackage payPackage = new MchPayPackage(weixinAccount, openId,
body, orderNo, orderFee, ip, TradeType.JSAPI);
payPackage.setNotifyUrl(notifyUrl);
return createPayJsRequestJson(payPackage, weixinAccount);
}
/**
* 生成V3.x版本JSAPI支付字符串
*
* @param payPackage
* 订单信息
* @param weixinAccount
* 商户信息
* @return 支付json串
* @throws PayException
*/
public static String createPayJsRequestJson(MchPayPackage payPackage,
WeixinPayAccount weixinAccount) throws PayException {
String paySignKey = weixinAccount.getPaySignKey();
payPackage.setSign(paysignMd5(payPackage, paySignKey));
PrePay prePay = createPrePay(payPackage, paySignKey);
MchPayRequest jsPayRequest = new MchPayRequest(prePay);
jsPayRequest.setSignType(SignType.MD5);
jsPayRequest.setPaySign(paysignMd5(jsPayRequest, paySignKey));
return JSON.toJSONString(jsPayRequest);
}
/**
* 统一下单接口</br>
* 除被扫支付场景以外,商户系统先调用该接口在微信支付服务后台生成预支付交易单,返回正确的预支付交易回话标识后再按扫码、JSAPI
* 、APP等不同场景生成交易串调起支付。
*
* @param payPackage
* 包含订单信息的对象
* @param paySignKey
* <font color="red">如果sign为空 则拿paysignkey进行签名</font>
* @see com.foxinmy.weixin4j.payment.mch.MchPayPackage
* @see com.foxinmy.weixin4j.payment.mch.PrePay
* @see <a
* href="http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1">统一下单接口</a>
* @return 预支付对象
*/
private final static WeixinHttpClient httpClient = new WeixinHttpClient();
public static PrePay createPrePay(MchPayPackage payPackage,
String paySignKey) throws PayException {
if (StringUtil.isBlank(payPackage.getSign())) {
payPackage.setSign(paysignMd5(payPackage, paySignKey));
}
String payJsRequestXml = XmlStream.toXML(payPackage);
try {
WeixinResponse response = httpClient.post(
PayURLConsts.MCH_UNIFIEDORDER_URL, payJsRequestXml);
PrePay prePay = response.getAsObject(new TypeReference<PrePay>() {
});
if (!prePay.getReturnCode().equalsIgnoreCase(Consts.SUCCESS)) {
throw new PayException(prePay.getReturnMsg(),
prePay.getReturnCode());
}
if (!prePay.getResultCode().equalsIgnoreCase(Consts.SUCCESS)) {
throw new PayException(prePay.getResultCode(),
prePay.getErrCodeDes());
}
return prePay;
} catch (WeixinException e) {
throw new PayException(e.getErrorCode(), e.getErrorMsg());
}
}
/**
* <p>
* 生成编辑地址请求
* </p>
*
* err_msg edit_address:ok获取编辑收货地址成功</br> edit_address:fail获取编辑收货地址失败</br>
* userName 收货人姓名</br> telNumber 收货人电话</br> addressPostalCode 邮编</br>
* proviceFirstStageName 国标收货地址第一级地址</br> addressCitySecondStageName
* 国标收货地址第二级地址</br> addressCountiesThirdStageName 国标收货地址第三级地址</br>
* addressDetailInfo 详细收货地址信息</br> nationalCode 收货地址国家码</br>
*
* @param appId
* 公众号的ID
* @param url
* 当前访问页的URL
* @param accessToken
* snsapi_base授权时产生的token
* @return
*/
public static String createAddressRequestJson(String appId, String url,
String accessToken) {
Map<String, String> map = new HashMap<String, String>();
map.put("appId", appId);
map.put("timeStamp", DateUtil.timestamp2string());
map.put("nonceStr", RandomUtil.generateString(16));
map.put("url", url);
map.put("accessToken", accessToken);
String sign = DigestUtil.SHA1(MapUtil.toJoinString(map, false, true,
null));
map.remove("url");
map.remove("accessToken");
map.put("scope", "jsapi_address");
map.put("signType", SignType.SHA1.name().toLowerCase());
map.put("addrSign", sign);
return JSON.toJSONString(map);
}
/**
* 创建V3.x NativePay支付(扫码支付)链接
*
* @param weixinAccount
* 支付配置信息
* @param productId
* 与订单ID等价
* @return 支付链接
* @see <a href="http://pay.weixin.qq.com/wiki/doc/api/native.php">扫码支付</a>
*/
public static String createNativePayRequestURL(
WeixinPayAccount weixinAccount, String productId) {
Map<String, String> map = new HashMap<String, String>();
String timestamp = DateUtil.timestamp2string();
String noncestr = RandomUtil.generateString(16);
map.put("appid", weixinAccount.getId());
map.put("mch_id", weixinAccount.getMchId());
map.put("time_stamp", timestamp);
map.put("nonce_str", noncestr);
map.put("product_id", productId);
String sign = paysignMd5(map, weixinAccount.getPaySignKey());
return String.format(PayURLConsts.MCH_NATIVE_URL, sign,
weixinAccount.getId(), weixinAccount.getMchId(), productId,
timestamp, noncestr);
}
/**
* 提交被扫支付
*
* @param authCode
* 扫码支付授权码 ,设备读取用户微信中的条码或者二维码信息
* @param body
* 商品描述
* @param attach
* 附加数据
* @param orderNo
* 商户内部唯一订单号
* @param orderFee
* 商品总额 单位元
* @param ip
* 订单生成的机器 IP
* @param weixinAccount
* 商户信息
* @return 支付的订单信息
* @see {@link com.foxinmy.weixin4j.payment.PayUtil#createMicroPay(MicroPayPackage, WeixinPayAccount)}
* @throws WeixinException
*/
public static Order createMicroPay(String authCode, String body,
String attach, String orderNo, double orderFee, String ip,
WeixinPayAccount weixinAccount) throws WeixinException {
MicroPayPackage payPackage = new MicroPayPackage(weixinAccount, body,
attach, orderNo, orderFee, ip, authCode);
return createMicroPay(payPackage, weixinAccount);
}
/**
* 提交被扫支付:收银员使用扫码设备读取微信用户刷卡授权码以后,二维码或条码信息传送至商户收银台,由商户收银台或者商户后台调用该接口发起支付.
*
* @param payPackage
* 订单信息
* @param weixinAccount
* 商户信息
* @return 支付的订单信息
* @throws WeixinException
* @see com.foxinmy.weixin4j.payment.mch.Order
* @see <a
* href="http://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_10">提交被扫支付API</a>
*/
public static Order createMicroPay(MicroPayPackage payPackage,
WeixinPayAccount weixinAccount) throws WeixinException {
String sign = paysignMd5(payPackage, weixinAccount.getPaySignKey());
payPackage.setSign(sign);
String para = XmlStream.toXML(payPackage);
WeixinResponse response = httpClient.post(
PayURLConsts.MCH_MICROPAY_URL, para);
return response
.getAsObject(new TypeReference<com.foxinmy.weixin4j.payment.mch.Order>() {
});
}
private static String JSAPI() throws PayException {
WeixinPayAccount weixinAccount = JSON.parseObject(
ConfigUtil.getValue("account"), WeixinPayAccount.class);
return createPayJsRequestJson("oyFLst1bqtuTcxK-ojF8hOGtLQao", "支付测试",
"JSAPI01", 0.01d, "http://127.0.0.1/jsapi/notify", "127.0.0.0",
weixinAccount);
}
private static String NATIVE() {
WeixinPayAccount weixinAccount = JSON.parseObject(
ConfigUtil.getValue("account"), WeixinPayAccount.class);
return createNativePayRequestURL(weixinAccount, "P1");
}
public static void main(String[] args) throws PayException {
// V3版本下的JS支付
System.out.println(JSAPI());
// V3版本下的原生支付
System.out.println(NATIVE());
}
}
@@ -0,0 +1,48 @@
支付模块【JSAPI】【NATIVE】【MICROPAY】
微信公众平台[V2版本支付](https://mp.weixin.qq.com/paymch/readtemplate?t=mp/business/course2_tmpl&lang=zh_CN)文档
微信公众平台[V3版本支付](https://mp.weixin.qq.com/paymch/readtemplate?t=mp/business/course3_tmpl&lang=zh_CN)文档
**在`2014年10月9号`之前申请并审核通过的支付接口应该属于`V2版本`支付,而之后申请的接口则为`V3版本(商户平台)`支付**
[PayUtil](./PayUtil.java)
-------------------------
* createPayJsRequestJson: 创建V3版本(商户平台)的JSAPI支付串
* createNativePayRequestURL: 创建V3版本(商户平台)的扫码支付链接
* createPrePay: 调用V3版本(商户平台)的统一订单接口生成预订单数据
* createMicroPay: 创建刷卡支付(商户平台)请求
* createAddressRequestJson: 生成编辑收货地址请求串
[Pay3Api](../api/Pay3Api.java)
-------------------------
* orderQuery: 订单查询接口
* refundOrder: 退款申请接口
* reverseOrder: 冲正订单接口
* closeOrder: 关闭订单接口
* downloadbill: 下载对账单接口
* refundQuery: 退款查询接口
[Pay2Api](../api/Pay2Api.java)
-------------------------
* orderQuery: 订单查询接口
* refundOrder: 退款申请接口
* downloadbill: 下载对账单接口
* refundQuery: 退款查询接口
@@ -0,0 +1,492 @@
package com.foxinmy.weixin4j.payment;
import java.io.File;
import java.util.Date;
import com.alibaba.fastjson.JSON;
import com.foxinmy.weixin4j.api.CashApi;
import com.foxinmy.weixin4j.api.CouponApi;
import com.foxinmy.weixin4j.api.Pay3Api;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.weixin.XmlResult;
import com.foxinmy.weixin4j.model.WeixinPayAccount;
import com.foxinmy.weixin4j.payment.coupon.CouponDetail;
import com.foxinmy.weixin4j.payment.coupon.CouponResult;
import com.foxinmy.weixin4j.payment.coupon.CouponStock;
import com.foxinmy.weixin4j.payment.mch.ApiResult;
import com.foxinmy.weixin4j.payment.mch.MPPayment;
import com.foxinmy.weixin4j.payment.mch.MPPaymentRecord;
import com.foxinmy.weixin4j.payment.mch.MPPaymentResult;
import com.foxinmy.weixin4j.payment.mch.Order;
import com.foxinmy.weixin4j.payment.mch.Redpacket;
import com.foxinmy.weixin4j.payment.mch.RedpacketRecord;
import com.foxinmy.weixin4j.payment.mch.RedpacketSendResult;
import com.foxinmy.weixin4j.payment.mch.RefundRecord;
import com.foxinmy.weixin4j.type.BillType;
import com.foxinmy.weixin4j.type.CurrencyType;
import com.foxinmy.weixin4j.type.IdQuery;
import com.foxinmy.weixin4j.util.ConfigUtil;
/**
* 微信支付接口实现
*
* @className WeixinPayProxy
* @author jy
* @date 2015年1月3日
* @since JDK 1.7
* @see com.foxinmy.weixin4j.api.Pay2Api
* @see com.foxinmy.weixin4j.api.Pay3Api
* @see <a href="http://pay.weixin.qq.com/wiki/doc/api/index.html">商户平台支付API</a>
*/
public class WeixinPayProxy {
private final Pay3Api pay3Api;
private final CouponApi couponApi;
private final CashApi cashApi;
private final File DEFAULT_CA_FILE;
/**
* 使用weixin4j.properties配置的账号信息
*/
public WeixinPayProxy() {
this(JSON.parseObject(ConfigUtil.getValue("account"),
WeixinPayAccount.class));
}
/**
*
* @param weixinAccount
* 支付相关的公众号账号信息
*
*/
public WeixinPayProxy(WeixinPayAccount weixinAccount) {
this.pay3Api = new Pay3Api(weixinAccount);
this.couponApi = new CouponApi(weixinAccount);
this.cashApi = new CashApi(weixinAccount);
this.DEFAULT_CA_FILE = new File(ConfigUtil.getClassPathValue("ca_file"));
}
/**
* 订单查询
* <p>
* 当商户后台、网络、服务器等出现异常,商户系统最终未接收到支付通知;</br> 调用支付接口后,返回系统错误或未知交易状态情况;</br>
* 调用被扫支付API,返回USERPAYING的状态;</br> 调用关单或撤销接口API之前,需确认支付状态;
* </P>
*
* @param idQuery
* 商户系统内部的订单号, transaction_id、out_trade_no 二 选一,如果同时存在优先级:
* transaction_id> out_trade_no
* @since V3
* @see com.foxinmy.weixin4j.payment.mch.Order
* @see com.foxinmy.weixin4j.api.PayApi
* @see com.foxinmy.weixin4j.api.Pay3Api
* @see <a
* href="http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_2">订单查询API</a>
* @return 订单详情
* @throws WeixinException
*/
public Order orderQuery(IdQuery idQuery) throws WeixinException {
return pay3Api.orderQuery(idQuery);
}
/**
* 申请退款(请求需要双向证书)</br>
* <p>
* 当交易发生之后一段时间内,由于买家或者卖家的原因需要退款时,卖家可以通过退款接口将支付款退还给买家,微信支付将在收到退款请求并且验证成功之后,
* 按照退款规则将支付款按原路退到买家帐号上。
* </p>
* <p style="color:red">
* 1.交易时间超过半年的订单无法提交退款;
* 2.微信支付退款支持单笔交易分多次退款,多次退款需要提交原支付订单的商户订单号和设置不同的退款单号。一笔退款失败后重新提交
* ,要采用原来的退款单号。总退款金额不能超过用户实际支付金额。
* </p>
*
* @param caFile
* 证书文件(后缀为*.p12)
* @param idQuery
* 商户系统内部的订单号, transaction_id 、 out_trade_no 二选一,如果同时存在优先级:
* transaction_id> out_trade_no
* @param outRefundNo
* 商户系统内部的退款单号,商 户系统内部唯一,同一退款单号多次请求只退一笔
* @param totalFee
* 订单总金额,单位为元
* @param refundFee
* 退款总金额,单位为元,可以做部分退款
* @param refundFeeType
* 货币类型,符合ISO 4217标准的三位字母代码,默认人民币:CNY
* @param opUserId
* 操作员帐号, 默认为商户号
*
* @return 退款申请结果
* @see com.foxinmy.weixin4j.payment.mch.RefundResult
* @see com.foxinmy.weixin4j.api.PayApi
* @see com.foxinmy.weixin4j.api.Pay3Api
* @see <a
* href="http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4">申请退款API</a>
* @since V3
* @throws WeixinException
*/
public com.foxinmy.weixin4j.payment.mch.RefundResult refundApply(
File caFile, IdQuery idQuery, String outRefundNo, double totalFee,
double refundFee, CurrencyType refundFeeType, String opUserId)
throws WeixinException {
return pay3Api.refundApply(caFile, idQuery, outRefundNo, totalFee,
refundFee, refundFeeType, opUserId);
}
/**
* 退款申请采用properties中配置的ca文件
*
* @see {@link com.foxinmy.weixin4j.payment.WeixinPayProxy#refundV3(File, IdQuery, String, double, double,CurrencyType, String)}
*/
public com.foxinmy.weixin4j.payment.mch.RefundResult refundApply(
IdQuery idQuery, String outRefundNo, double totalFee,
double refundFee, String opUserId) throws WeixinException {
return pay3Api.refundApply(DEFAULT_CA_FILE, idQuery, outRefundNo,
totalFee, refundFee, CurrencyType.CNY, opUserId);
}
/**
* 退款查询
* <p>
* 提交退款申请后,通过调用该接口查询退款状态。退款有一定延时,用零钱支付的退款20分钟内到账,银行卡支付的退款3个工作日后重新查询退款状态。
* </p>
*
* @param idQuery
* 单号 refund_id、out_refund_no、 out_trade_no 、 transaction_id
* 四个参数必填一个,优先级为:
* refund_id>out_refund_no>transaction_id>out_trade_no
* @return 退款记录
* @see com.foxinmy.weixin4j.api.PayApi
* @see com.foxinmy.weixin4j.api.Pay3Api
* @see com.foxinmy.weixin4j.payment.mch.RefundRecord
* @see <a
* href="http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_5">退款查询API</a>
* @since V3
* @throws WeixinException
*/
public RefundRecord refundQueryV3(IdQuery idQuery) throws WeixinException {
return pay3Api.refundQuery(idQuery);
}
/**
* 下载对账单<br>
* 1.微信侧未成功下单的交易不会出现在对账单中。支付成功后撤销的交易会出现在对账 单中,跟原支付单订单号一致,bill_type 为
* REVOKED;<br>
* 2.微信在次日 9 点启动生成前一天的对账单,建议商户 9 点半后再获取;<br>
* 3.对账单中涉及金额的字段单位为“元”。<br>
*
* @param billDate
* 下载对账单的日期
* @param billType
* 下载对账单的类型 ALL,返回当日所有订单信息, 默认值 SUCCESS,返回当日成功支付的订单
* REFUND,返回当日退款订单
* @return excel表格
* @since V2 & V3
* @see com.foxinmy.weixin4j.api.PayApi
* @see <a
* href="http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_6">下载对账单API</a>
* @throws WeixinException
*/
public File downloadbill(Date billDate, BillType billType)
throws WeixinException {
return pay3Api.downloadbill(billDate, billType);
}
/**
* 冲正订单(需要证书)</br> 当支付返回失败,或收银系统超时需要取消交易,可以调用该接口</br> 接口逻辑:支
* 付失败的关单,支付成功的撤销支付</br> <font color="red">7天以内的单可撤销,其他正常支付的单
* 如需实现相同功能请调用退款接口</font></br> <font
* color="red">调用扣款接口后请勿立即调用撤销,需要等待5秒以上。先调用查单接口,如果没有确切的返回,再调用撤销</font></br>
*
* @param ca
* 证书文件(V2版本后缀为*.pfx,V3版本后缀为*.p12)
* @param idQuery
* 商户系统内部的订单号, transaction_id 、 out_trade_no 二选一,如果同时存在优先级:
* transaction_id> out_trade_no
* @return 撤销结果
* @see com.foxinmy.weixin4j.api.PayApi
* @see com.foxinmy.weixin4j.api.Pay2Api
* @see com.foxinmy.weixin4j.api.Pay3Api
* @since V3
* @throws WeixinException
*/
public ApiResult reverseOrder(File caFile, IdQuery idQuery)
throws WeixinException {
return pay3Api.reverseOrder(caFile, idQuery);
}
/**
* 冲正撤销:默认采用properties中配置的ca文件
*
* @param idQuery
* transaction_id、out_trade_no 二选一
* @return 撤销结果
* @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#reverse(File, IdQuery)}
* @throws WeixinException
*/
public ApiResult reverseOrder(IdQuery idQuery) throws WeixinException {
return pay3Api.reverseOrder(DEFAULT_CA_FILE, idQuery);
}
/**
* 关闭订单
* <p>
* 商户订单支付失败需要生成新单号重新发起支付,要对原订单号调用关单,避免重复支付;系统下单后,用户支付超时,系统退出不再受理,避免用户继续
* ,请调用关单接口,如果关单失败,返回已完 成支付请按正常支付处理。如果出现银行掉单,调用关单成功后,微信后台会主动发起退款。
* </p>
*
* @param outTradeNo
* 商户系统内部的订单号
* @return 执行结果
* @see com.foxinmy.weixin4j.api.PayApi
* @see com.foxinmy.weixin4j.api.Pay3Api
* @since V3
* @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 {
return pay3Api.closeOrder(outTradeNo);
}
/**
* native支付URL转短链接:用于扫码原生支付模式一中的二维码链接转成短链接(weixin://wxpay/s/XXXXXX),减小二维码数据量
* ,提升扫描速度和精确度。
*
* @param url
* 具有native标识的支付URL
* @return 转换后的短链接
* @see com.foxinmy.weixin4j.api.PayApi
* @see com.foxinmy.weixin4j.api.Pay2Api
* @see com.foxinmy.weixin4j.api.Pay3Api
* @see <a
* href="http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_9">转换短链接API</a>
* @since V3
* @throws WeixinException
*/
public String getPayShorturl(String url) throws WeixinException {
return pay3Api.getShorturl(url);
}
/**
* 接口上报
*
* @param interfaceUrl
* 上报对应的接口的完整 URL, 类似: https://api.mch.weixin.q
* q.com/pay/unifiedorder
* @param executeTime
* 接口耗时情况,单位为毫秒
* @param outTradeNo
* 商户系统内部的订单号,商 户可以在上报时提供相关商户订单号方便微信支付更好 的提高服务质量。
* @param ip
* 发起接口调用时的机器 IP
* @param time
* 商户调用该接口时商户自己 系统的时间
* @param returnXml
* 调用接口返回的基本数据
* @return 处理结果
* @see com.foxinmy.weixin4j.api.PayApi
* @see com.foxinmy.weixin4j.api.Pay3Api
* @see <a
* href="http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_8">接口测试上报API</a>
* @throws WeixinException
*/
public XmlResult interfaceReport(String interfaceUrl, int executeTime,
String outTradeNo, String ip, Date time, XmlResult returnXml)
throws WeixinException {
return pay3Api.interfaceReport(interfaceUrl, executeTime, outTradeNo,
ip, time, returnXml);
}
/**
* 发放代金券(需要证书)
*
* @param caFile
* 证书文件(后缀为*.p12)
* @param couponStockId
* 代金券批次id
* @param partnerTradeNo
* 商户发放凭据号(格式:商户id+日期+流水号),商户侧需保持唯一性
* @param openId
* 用户的openid
* @param opUserId
* 操作员帐号, 默认为商户号 可在商户平台配置操作员对应的api权限 可为空
* @return 发放结果
* @see com.foxinmy.weixin4j.api.CouponApi
* @see com.foxinmy.weixin4j.payment.coupon.CouponResult
* @see <a
* href="http://pay.weixin.qq.com/wiki/doc/api/sp_coupon.php?chapter=12_3">发放代金券接口</a>
* @throws WeixinException
*/
public CouponResult sendCoupon(File caFile, String couponStockId,
String partnerTradeNo, String openId, String opUserId)
throws WeixinException {
return couponApi.sendCoupon(caFile, couponStockId, partnerTradeNo,
openId, opUserId);
}
/**
* 发放代金券采用properties中配置的ca文件
*
* @see {@link com.foxinmy.weixin4j.payment.WeixinPayProxy#sendCoupon(File, String, String, String, String)}
*/
public CouponResult sendCoupon(String couponStockId, String partnerTradeNo,
String openId) throws WeixinException {
return couponApi.sendCoupon(DEFAULT_CA_FILE, couponStockId,
partnerTradeNo, openId, null);
}
/**
* 查询代金券批次
*
* @param couponStockId
* 代金券批次ID
* @return 代金券批次信息
* @see com.foxinmy.weixin4j.api.CouponApi
* @see com.foxinmy.weixin4j.payment.coupon.CouponStock
* @see <a
* href="http://pay.weixin.qq.com/wiki/doc/api/sp_coupon.php?chapter=12_4">查询代金券信息</a>
* @throws WeixinException
*/
public CouponStock queryCouponStock(String couponStockId)
throws WeixinException {
return couponApi.queryCouponStock(couponStockId);
}
/**
* 查询代金券详细
*
* @param couponId
* 代金券ID
* @return 代金券详细信息
* @see com.foxinmy.weixin4j.api.CouponApi
* @see com.foxinmy.weixin4j.payment.coupon.CouponDetail
* @see <a
* href="http://pay.weixin.qq.com/wiki/doc/api/sp_coupon.php?chapter=12_5">查询代金券详细信息</a>
* @throws WeixinException
*/
public CouponDetail queryCouponDetail(String couponId)
throws WeixinException {
return couponApi.queryCouponDetail(couponId);
}
/**
* 发放红包 企业向微信用户个人发现金红包
*
* @param caFile
* 证书文件(V3版本后缀为*.p12)
* @param redpacket
* 红包信息
* @return 发放结果
* @see com.foxinmy.weixin4j.api.CashApi
* @see com.foxinmy.weixin4j.payment.mch.Redpacket
* @see com.foxinmy.weixin4j.payment.mch.RedpacketSendResult
* @see <a
* href="http://pay.weixin.qq.com/wiki/doc/api/cash_coupon.php?chapter=13_5">红包接口说明</a>
* @throws WeixinException
*/
public RedpacketSendResult sendRedpack(File caFile, Redpacket redpacket)
throws WeixinException {
return cashApi.sendRedpack(caFile, redpacket);
}
/**
* 发放红包采用properties中配置的ca文件
*
* @see {@link com.foxinmy.weixin4j.payment.WeixinPayProxy#sendRedpack(File, Redpacket)}
*/
public RedpacketSendResult sendRedpack(Redpacket redpacket)
throws WeixinException {
return cashApi.sendRedpack(DEFAULT_CA_FILE, redpacket);
}
/**
* 查询红包记录
*
* @param caFile
* 证书文件(V3版本后缀为*.p12)
* @param outTradeNo
* 商户发放红包的商户订单号
* @return 红包记录
* @see com.foxinmy.weixin4j.api.CashApi
* @see com.foxinmy.weixin4j.payment.mch.RedpacketRecord
* @see <a
* href="http://pay.weixin.qq.com/wiki/doc/api/cash_coupon.php?chapter=13_6">查询红包接口说明</a>
* @throws WeixinException
*/
public RedpacketRecord queryRedpack(File caFile, String outTradeNo)
throws WeixinException {
return cashApi.queryRedpack(caFile, outTradeNo);
}
/**
* 查询红包采用properties中配置的ca文件
*
* @see {@link com.foxinmy.weixin4j.payment.WeixinPayProxy#queryRedpack(File,String)}
*/
public RedpacketRecord queryRedpack(String outTradeNo)
throws WeixinException {
return cashApi.queryRedpack(DEFAULT_CA_FILE, outTradeNo);
}
/**
* 企业付款 实现企业向个人付款,针对部分有开发能力的商户, 提供通过API完成企业付款的功能。 比如目前的保险行业向客户退保、给付、理赔。
*
* @param caFile
* 证书文件(V3版本后缀为*.p12)
* @param mpPayment
* 付款信息
* @return 付款结果
* @see com.foxinmy.weixin4j.api.CashApi
* @see com.foxinmy.weixin4j.payment.mch.MPPayment
* @see com.foxinmy.weixin4j.payment.mch.MPPaymentResult
* @see <a
* href="http://pay.weixin.qq.com/wiki/doc/api/mch_pay.php?chapter=14_1">企业付款</a>
* @throws WeixinException
*/
public MPPaymentResult mpPayment(File caFile, MPPayment mpPayment)
throws WeixinException {
return cashApi.mpPayment(caFile, mpPayment);
}
/**
* 企业付款采用properties中配置的ca文件
*
* @see {@link com.foxinmy.weixin4j.payment.WeixinPayProxy#mpPayment(File, MPPayment)}
*/
public MPPaymentResult mpPayment(MPPayment mpPayment)
throws WeixinException {
return cashApi.mpPayment(DEFAULT_CA_FILE, mpPayment);
}
/**
* 企业付款查询 用于商户的企业付款操作进行结果查询,返回付款操作详细结果
*
* @param caFile
* 证书文件(V3版本后缀为*.p12)
* @param outTradeNo
* 商户调用企业付款API时使用的商户订单号
* @return 付款记录
* @see com.foxinmy.weixin4j.api.CashApi
* @see com.foxinmy.weixin4j.payment.mch.MPPaymentRecord
* @see <a
* href="http://pay.weixin.qq.com/wiki/doc/api/mch_pay.php?chapter=14_3">企业付款查询</a>
* @throws WeixinException
*/
public MPPaymentRecord mpPaymentQuery(File caFile, String outTradeNo)
throws WeixinException {
return cashApi.mpPaymentQuery(caFile, outTradeNo);
}
/**
* 企业付款查询采用properties中配置的ca文件
*
* @see {@link com.foxinmy.weixin4j.payment.WeixinPayProxy#mpPaymentQuery(File, String)}
*/
public MPPaymentRecord mpPaymentQuery(String outTradeNo)
throws WeixinException {
return cashApi.mpPaymentQuery(DEFAULT_CA_FILE, outTradeNo);
}
}
@@ -0,0 +1,380 @@
package com.foxinmy.weixin4j.payment.coupon;
import java.util.Date;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import com.alibaba.fastjson.annotation.JSONField;
import com.foxinmy.weixin4j.payment.mch.ApiResult;
import com.foxinmy.weixin4j.type.CouponStatus;
import com.foxinmy.weixin4j.type.CouponStockType;
import com.foxinmy.weixin4j.type.CouponType;
import com.foxinmy.weixin4j.util.DateUtil;
import com.foxinmy.weixin4j.util.StringUtil;
/**
* 代金券详细
*
* @className CouponDetail
* @author jy
* @date 2015年3月27日
* @since JDK 1.7
* @see
*/
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class CouponDetail extends ApiResult {
private static final long serialVersionUID = -311265355895457070L;
/**
* 代金券批次Id
*/
@XmlElement(name = "coupon_stock_id")
@JSONField(name = "coupon_stock_id")
private String couponStockId;
/**
* 批次类型;1-批量型,2-触发型
*/
@XmlElement(name = "coupon_stock_type")
@JSONField(name = "coupon_stock_type")
private int couponStockType;
/**
* 代金券id
*/
@XmlElement(name = "coupon_id")
@JSONField(name = "coupon_id")
private String couponId;
/**
* 代金券面值,单位是分
*/
@XmlElement(name = "coupon_value")
@JSONField(name = "coupon_value")
private int couponValue;
/**
* 代金券使用最低限额,单位是分
*/
@XmlElement(name = "coupon_mininum")
@JSONField(name = "coupon_mininum")
private int couponMininum;
/**
* 代金券名称
*/
@XmlElement(name = "coupon_name")
@JSONField(name = "coupon_name")
private String couponName;
/**
* 代金券状态:2-已激活,4-已锁定,8-已实扣
*/
@XmlElement(name = "coupon_state")
@JSONField(name = "coupon_state")
private int couponStatus;
/**
* 代金券类型:1-代金券无门槛,2-代金券有门槛互斥,3-代金券有门槛叠加,
*/
@XmlElement(name = "coupon_type")
@JSONField(name = "coupon_type")
private int couponType;
/**
* 代金券描述
*/
@XmlElement(name = "coupon_desc")
@JSONField(name = "coupon_desc")
private String couponDesc;
/**
* 代金券实际使用金额
*/
@XmlElement(name = "coupon_use_value")
@JSONField(name = "coupon_use_value")
private int couponUseValue;
/**
* 代金券剩余金额:部分使用情况下,可能会存在券剩余金额
*/
@XmlElement(name = "coupon_remain_value")
@JSONField(name = "coupon_remain_value")
private int couponRemainValue;
/**
* 生效开始时间:格式为yyyyMMddhhmmss,如2009年12月27日9点10分10秒表示为20091227091010。
*/
@XmlElement(name = "begin_time")
@JSONField(name = "begin_time")
private String beginTime;
/**
* 生效结束时间:格式为yyyyMMddhhmmss,如2009年12月27日9点10分10秒表示为20091227091010。
*/
@XmlElement(name = "end_time")
@JSONField(name = "end_time")
private String endTime;
/**
* 发放时间:格式为yyyyMMddhhmmss,如2009年12月27日9点10分10秒表示为20091227091010。
*/
@XmlElement(name = "send_time")
@JSONField(name = "send_time")
private String sendTime;
/**
* 使用时间:格式为yyyyMMddhhmmss,如2009年12月27日9点10分10秒表示为20091227091010。
*/
@XmlElement(name = "use_time")
@JSONField(name = "use_time")
private String useTime;
/**
* 使用单号:代金券使用后,关联的大单收单单号
*/
@XmlElement(name = "trade_no")
@JSONField(name = "trade_no")
private String tradeNo;
/**
* 消耗方商户id:代金券使用后,消耗方商户id
*/
@XmlElement(name = "consumer_mch_id")
@JSONField(name = "consumer_mch_id")
private String consumerMchId;
/**
* 消耗方商户名称:代金券使用后,消耗方商户名称
*/
@XmlElement(name = "consumer_mch_name")
@JSONField(name = "consumer_mch_name")
private String consumerMchName;
/**
* 消耗方商户appid:代金券使用后,消耗方商户appid
*/
@XmlElement(name = "consumer_mch_appid")
@JSONField(name = "consumer_mch_appid")
private String consumerMchAppid;
/**
* 发放来源:代金券发放来源
*/
@XmlElement(name = "send_source")
@JSONField(name = "send_source")
private String sendSource;
/**
* 是否允许部分使用:该代金券是否允许部分使用标识:1-表示支持部分使用
*/
@XmlElement(name = "is_partial_use")
@JSONField(name = "is_partial_use")
private int isPartialUse;
public CouponDetail(){
}
public String getCouponStockId() {
return couponStockId;
}
public int getCouponStockType() {
return couponStockType;
}
@JSONField(deserialize = false, serialize = false)
public CouponStockType getFormatCouponStockType() {
for (CouponStockType couponStockType : CouponStockType.values()) {
if (couponStockType.getVal() == this.couponStockType) {
return couponStockType;
}
}
return null;
}
public String getCouponId() {
return couponId;
}
public int getCouponValue() {
return couponValue;
}
/**
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
*
* @return 元单位
*/
@JSONField(deserialize = false, serialize = false)
public double getFormatCouponValue() {
return couponValue / 100d;
}
public int getCouponMininum() {
return couponMininum;
}
/**
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
*
* @return 元单位
*/
@JSONField(deserialize = false, serialize = false)
public double getFormatCouponMininum() {
return couponMininum / 100d;
}
public String getCouponName() {
return couponName;
}
public int getCouponStatus() {
return couponStatus;
}
@JSONField(deserialize = false, serialize = false)
public CouponStatus getFormatCouponStatus() {
for (CouponStatus couponStatus : CouponStatus.values()) {
if (couponStatus.getVal() == this.couponStatus) {
return couponStatus;
}
}
return null;
}
public int getCouponType() {
return couponType;
}
@JSONField(deserialize = false, serialize = false)
public CouponType getFormatCouponType() {
for (CouponType couponType : CouponType.values()) {
if (couponType.getVal() == this.couponType) {
return couponType;
}
}
return null;
}
public String getCouponDesc() {
return couponDesc;
}
public int getCouponUseValue() {
return couponUseValue;
}
/**
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
*
* @return 元单位
*/
@JSONField(deserialize = false, serialize = false)
public double getFormatCouponUseValue() {
return couponUseValue / 100d;
}
public int getCouponRemainValue() {
return couponRemainValue;
}
/**
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
*
* @return 元单位
*/
@JSONField(deserialize = false, serialize = false)
public double getFormatCouponRemainValue() {
return couponRemainValue / 100d;
}
public String getBeginTime() {
return beginTime;
}
@JSONField(deserialize = false, serialize = false)
public Date getFormatBeginTime() {
return DateUtil.parse2yyyyMMddHHmmss(beginTime);
}
public String getEndTime() {
return endTime;
}
@JSONField(deserialize = false, serialize = false)
public Date getFormatEndTime() {
return DateUtil.parse2yyyyMMddHHmmss(endTime);
}
public String getSendTime() {
return sendTime;
}
@JSONField(deserialize = false, serialize = false)
public Date getFormatSendTime() {
return DateUtil.parse2yyyyMMddHHmmss(sendTime);
}
public String getUseTime() {
return useTime;
}
@JSONField(deserialize = false, serialize = false)
public Date getFormatUseTime() {
return StringUtil.isNotBlank(useTime) ? DateUtil
.parse2yyyyMMddHHmmss(useTime) : null;
}
public String getTradeNo() {
return tradeNo;
}
public String getConsumerMchId() {
return consumerMchId;
}
public String getConsumerMchName() {
return consumerMchName;
}
public String getConsumerMchAppid() {
return consumerMchAppid;
}
public String getSendSource() {
return sendSource;
}
public int getIsPartialUse() {
return isPartialUse;
}
@JSONField(deserialize = false, serialize = false)
public boolean getFormatIsPartialUse() {
return isPartialUse == 1;
}
@Override
public String toString() {
return "CouponDetail [couponStockId=" + couponStockId
+ ", couponStockType=" + getFormatCouponStockType()
+ ", couponId=" + couponId + ", couponValue="
+ getFormatCouponValue() + ", couponMininum="
+ getFormatCouponMininum() + ", couponName=" + couponName
+ ", couponStatus=" + getCouponStatus() + ", couponType="
+ getFormatCouponType() + ", couponDesc=" + couponDesc
+ ", couponUseValue=" + getFormatCouponUseValue()
+ ", couponRemainValue=" + getFormatCouponRemainValue()
+ ", beginTime=" + getFormatBeginTime() + ", endTime="
+ getFormatEndTime() + ", sendTime=" + getFormatSendTime()
+ ", useTime=" + getFormatUseTime() + ", tradeNo=" + tradeNo
+ ", consumerMchId=" + consumerMchId + ", consumerMchName="
+ consumerMchName + ", consumerMchAppid=" + consumerMchAppid
+ ", sendSource=" + sendSource + ", isPartialUse="
+ getFormatIsPartialUse() + ", " + super.toString()
+ "]";
}
}
@@ -0,0 +1,81 @@
package com.foxinmy.weixin4j.payment.coupon;
import java.io.Serializable;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import com.alibaba.fastjson.annotation.JSONField;
/**
* 代金券信息(订单,退款中体现)
*
* @className CouponInfo
* @author jy
* @date 2015年3月24日
* @since JDK 1.7
* @see
*/
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class CouponInfo implements Serializable {
private static final long serialVersionUID = -8744999305258786901L;
/**
* 代金券或立减优惠批次ID
*/
@XmlElement(name = "coupon_batch_id")
@JSONField(name = "coupon_batch_id")
private String couponBatchId;
/**
* 代金券或立减优惠ID
*/
@XmlElement(name = "coupon_id")
@JSONField(name = "coupon_id")
private String couponId;
/**
* 单个代金券或立减优惠支付金额
*/
@XmlElement(name = "coupon_fee")
@JSONField(name = "coupon_fee")
private Integer couponFee;
public CouponInfo(){
}
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;
}
}
@@ -0,0 +1,126 @@
package com.foxinmy.weixin4j.payment.coupon;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import com.alibaba.fastjson.annotation.JSONField;
import com.foxinmy.weixin4j.payment.mch.ApiResult;
/**
* 代金券发放结果
*
* @className CouponResult
* @author jy
* @date 2015年3月25日
* @since JDK 1.7
* @see
*/
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class CouponResult extends ApiResult {
private static final long serialVersionUID = -1996967923720149124L;
/**
* 代金券批次id
*/
@XmlElement(name = "coupon_stock_id")
@JSONField(name = "coupon_stock_id")
private String couponStockId;
/**
* 返回记录数
*/
@XmlElement(name = "resp_count")
@JSONField(name = "resp_count")
private int responseCount;
/**
* 成功记录数
*/
@XmlElement(name = "success_count")
@JSONField(name = "success_count")
private int successCount;
/**
* 失败记录数
*/
@XmlElement(name = "failed_count")
@JSONField(name = "failed_count")
private int failedCount;
/**
* 用户在商户appid下的唯一标识
*/
@XmlElement(name = "openid")
@JSONField(name = "openid")
private String openId;
/**
* 返回码 SUCCESS或者FAILED
*/
@XmlElement(name = "ret_code")
@JSONField(name = "ret_code")
private String retCode;
/**
* 代金券id
*/
@XmlElement(name = "coupon_id")
@JSONField(name = "coupon_id")
private String couponId;
/**
* 失败描述信息,例如:“用户已达领用上限”
*/
@XmlElement(name = "ret_msg")
@JSONField(name = "ret_msg")
private String retMsg;
public CouponResult(){
}
public String getCouponStockId() {
return couponStockId;
}
public int getResponseCount() {
return responseCount;
}
public int getSuccessCount() {
return successCount;
}
public int getFailedCount() {
return failedCount;
}
public String getOpenId() {
return openId;
}
public String getRetCode() {
return retCode;
}
public String getCouponId() {
return couponId;
}
public String getRetMsg() {
return retMsg;
}
@Override
public String toString() {
return "CouponResult [couponStockId=" + couponStockId
+ ", responseCount=" + responseCount + ", successCount="
+ successCount + ", failedCount=" + failedCount + ", openId="
+ openId + ", retCode=" + retCode + ", couponId=" + couponId
+ ", retMsg=" + retMsg + "]";
}
}
@@ -0,0 +1,306 @@
package com.foxinmy.weixin4j.payment.coupon;
import java.util.Date;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import com.alibaba.fastjson.annotation.JSONField;
import com.foxinmy.weixin4j.payment.mch.ApiResult;
import com.foxinmy.weixin4j.type.CouponStockStatus;
import com.foxinmy.weixin4j.type.CouponType;
import com.foxinmy.weixin4j.util.DateUtil;
/**
* 代金券信息
*
* @className CouponStock
* @author jy
* @date 2015年3月27日
* @since JDK 1.7
* @see
*/
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class CouponStock extends ApiResult {
private static final long serialVersionUID = -8627202879200080499L;
/**
* 代金券批次ID
*/
@XmlElement(name = "coupon_stock_id")
@JSONField(name = "coupon_stock_id")
private String couponStockId;
/**
* 代金券名称
*/
@XmlElement(name = "coupon_name")
@JSONField(name = "coupon_name")
private String couponName;
/**
* 代金券面额
*/
@XmlElement(name = "coupon_value")
@JSONField(name = "coupon_value")
private int couponValue;
/**
* 代金券使用最低限额
*/
@XmlElement(name = "coupon_mininumn")
@JSONField(name = "coupon_mininumn")
private Integer couponMininumn;
/**
* 代金券类型:1-代金券无门槛,2-代金券有门槛互斥,3-代金券有门槛叠加
*/
@XmlElement(name = "coupon_type")
@JSONField(name = "coupon_type")
private int couponType;
/**
* 批次状态: 1-未激活;2-审批中;4-已激活;8-已作废;16-中止发放;
*/
@XmlElement(name = "coupon_stock_status")
@JSONField(name = "coupon_stock_status")
private int couponStockStatus;
/**
* 代金券数量
*/
@XmlElement(name = "coupon_total")
@JSONField(name = "coupon_total")
private int couponTotal;
/**
* 代金券每个人最多能领取的数量, 如果为0,则表示没有限制
*/
@XmlElement(name = "max_quota")
@JSONField(name = "max_quota")
private Integer maxQuota;
/**
* 代金券锁定数量
*/
@XmlElement(name = "locked_num")
@JSONField(name = "locked_num")
private Integer lockedNum;
/**
* 代金券已使用数量
*/
@XmlElement(name = "used_num")
@JSONField(name = "used_num")
private Integer usedNum;
/**
* 代金券已经发送的数量
*/
@XmlElement(name = "is_send_num")
@JSONField(name = "is_send_num")
private Integer sendNum;
/**
* 生效开始时间 格式为yyyyMMddhhmmss,如2009年12月27日9点10分10秒表示为20091227091010。
*/
@XmlElement(name = "begin_time")
@JSONField(name = "begin_time")
private String beginTime;
/**
* 生效结束时间 格式为yyyyMMddhhmmss,如2009年12月27日9点10分10秒表示为20091227091010。
*/
@XmlElement(name = "end_time")
@JSONField(name = "end_time")
private String endTime;
/**
* 创建时间 格式为yyyyMMddhhmmss,如2009年12月27日9点10分10秒表示为20091227091010。
*/
@XmlElement(name = "create_time")
@JSONField(name = "create_time")
private String createTime;
/**
* 代金券预算额度
*/
@XmlElement(name = "coupon_budget")
@JSONField(name = "coupon_budget")
private Integer couponBudget;
public CouponStock(){
}
public String getCouponStockId() {
return couponStockId;
}
public String getCouponName() {
return couponName;
}
public int getCouponValue() {
return couponValue;
}
/**
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
*
* @return 元单位
*/
@JSONField(deserialize = false, serialize = false)
public double getFormatCouponValue() {
return couponValue / 100d;
}
public Integer getCouponMininumn() {
return couponMininumn;
}
/**
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
*
* @return 元单位
*/
@JSONField(deserialize = false, serialize = false)
public double getFormatCouponMininumn() {
return couponMininumn != null ? couponMininumn.intValue() / 100d : 0d;
}
public int getCouponType() {
return couponType;
}
@JSONField(deserialize = false, serialize = false)
public CouponType getFormatCouponType() {
for (CouponType couponType : CouponType.values()) {
if (couponType.getVal() == this.couponType) {
return couponType;
}
}
return null;
}
public int getCouponStockStatus() {
return couponStockStatus;
}
@JSONField(deserialize = false, serialize = false)
public CouponStockStatus getFormatCouponStockStatus() {
for (CouponStockStatus couponStockStatus : CouponStockStatus.values()) {
if (couponStockStatus.getVal() == this.couponStockStatus) {
return couponStockStatus;
}
}
return null;
}
public int getCouponTotal() {
return couponTotal;
}
public Integer getMaxQuota() {
return maxQuota;
}
/**
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
*
* @return 元单位
*/
@JSONField(deserialize = false, serialize = false)
public double getFormatMaxQuota() {
return maxQuota != null ? maxQuota.intValue() / 100d : 0d;
}
public Integer getLockedNum() {
return lockedNum;
}
/**
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
*
* @return 元单位
*/
@JSONField(deserialize = false, serialize = false)
public double getFormatLockedNum() {
return lockedNum != null ? lockedNum.intValue() / 100d : 0d;
}
public Integer getUsedNum() {
return usedNum;
}
/**
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
*
* @return 元单位
*/
@JSONField(deserialize = false, serialize = false)
public double getFormatUsedNum() {
return usedNum != null ? usedNum.intValue() / 100d : 0d;
}
public Integer getSendNum() {
return sendNum;
}
/**
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
*
* @return 元单位
*/
@JSONField(deserialize = false, serialize = false)
public double getFormatSendNum() {
return sendNum != null ? sendNum.intValue() / 100d : 0d;
}
public String getBeginTime() {
return beginTime;
}
@JSONField(deserialize = false, serialize = false)
public Date getFormatBeginTime() {
return DateUtil.parse2yyyyMMddHHmmss(beginTime);
}
public String getEndTime() {
return endTime;
}
@JSONField(deserialize = false, serialize = false)
public Date getFormatEndTime() {
return DateUtil.parse2yyyyMMddHHmmss(endTime);
}
public String getCreateTime() {
return createTime;
}
@JSONField(deserialize = false, serialize = false)
public Date getFormatCreateTime() {
return DateUtil.parse2yyyyMMddHHmmss(createTime);
}
public Integer getCouponBudget() {
return couponBudget;
}
/**
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
*
* @return 元单位
*/
@JSONField(deserialize = false, serialize = false)
public double getFormatCouponBudget() {
return couponBudget != null ? couponBudget.intValue() / 100d : 0d;
}
@Override
public String toString() {
return "CouponDetail [couponStockId=" + couponStockId + ", couponName="
+ couponName + ", couponValue=" + getFormatCouponValue()
+ ", couponMininumn=" + getFormatCouponMininumn()
+ ", couponType=" + getFormatCouponType()
+ ", couponStockStatus=" + getFormatCouponStockStatus()
+ ", couponTotal=" + couponTotal + ", maxQuota="
+ getFormatMaxQuota() + ", lockedNum=" + getFormatLockedNum()
+ ", usedNum=" + getFormatUsedNum() + ", sendNum="
+ getFormatSendNum() + ", beginTime=" + beginTime
+ ", endTime=" + endTime + ", createTime=" + createTime
+ ", couponBudget=" + getFormatCouponBudget() + ", "
+ super.toString() + "]";
}
}
@@ -0,0 +1,142 @@
package com.foxinmy.weixin4j.payment.mch;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import com.alibaba.fastjson.annotation.JSONField;
import com.foxinmy.weixin4j.http.weixin.XmlResult;
import com.foxinmy.weixin4j.util.StringUtil;
/**
* 调用V3.x接口返回的公用字段
*
* @className ApiResult
* @author jy
* @date 2014年10月21日
* @since JDK 1.7
* @see
*/
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class ApiResult extends XmlResult {
private static final long serialVersionUID = -8430005768959715444L;
/**
* 微信分配的公众账号 ID商户号 非空
*/
@XmlElement(name = "appid")
@JSONField(name = "appid")
private String appId;
/**
* 微信支付分配的商户号 非空
*/
@XmlElement(name = "mch_id")
@JSONField(name = "mch_id")
private String mchId;
/**
* 代理模式下分配的商户号 可能为空
*/
@XmlElement(name = "sub_mch_id")
@JSONField(name = "sub_mch_id")
private String subMchId;
/**
* 随机字符串 非空
*/
@XmlElement(name = "nonce_str")
@JSONField(name = "nonce_str")
private String nonceStr;
/**
* 签名 <font color="red">调用者无需关心</font>
*/
private String sign;
/**
* 微信支付分配的终端设备号 可能为空
*/
@XmlElement(name = "device_info")
@JSONField(name = "device_info")
private String deviceInfo;
/**
* 是否需要继续调用接口 Y- 需要,N-不需要
*/
private String recall;
protected ApiResult() {
}
public ApiResult(String returnCode, String returnMsg) {
super(returnCode, returnMsg);
}
public String getAppId() {
return appId;
}
public void setAppId(String appId) {
this.appId = appId;
}
public String getMchId() {
return mchId;
}
public void setMchId(String mchId) {
this.mchId = mchId;
}
public String getSubMchId() {
return StringUtil.isNotBlank(subMchId) ? subMchId : null;
}
public void setSubMchId(String subMchId) {
this.subMchId = subMchId;
}
public String getNonceStr() {
return nonceStr;
}
public void setNonceStr(String nonceStr) {
this.nonceStr = nonceStr;
}
public String getSign() {
return sign;
}
public void setSign(String sign) {
this.sign = sign;
}
public String getDeviceInfo() {
return deviceInfo;
}
public void setDeviceInfo(String deviceInfo) {
this.deviceInfo = deviceInfo;
}
public String getRecall() {
return recall;
}
public void setRecall(String recall) {
this.recall = recall;
}
@JSONField(deserialize = false, serialize = false)
public boolean getFormatRecall() {
return recall != null && recall.equalsIgnoreCase("y");
}
@Override
public String toString() {
return "appId=" + appId + ", mchId=" + mchId + ", subMchId=" + subMchId
+ ", nonceStr=" + nonceStr + ", sign=" + sign + ", deviceInfo="
+ deviceInfo + ", recall=" + getFormatRecall() + ", "
+ super.toString();
}
}
@@ -0,0 +1,130 @@
package com.foxinmy.weixin4j.payment.mch;
import java.io.Serializable;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import com.alibaba.fastjson.annotation.JSONField;
import com.foxinmy.weixin4j.type.MPPaymentCheckNameType;
import com.foxinmy.weixin4j.util.DateUtil;
/**
* 企业付款
*
* @className MPPayment
* @author jy
* @date 2015年4月1日
* @since JDK 1.7
* @see
*/
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class MPPayment implements Serializable {
private static final long serialVersionUID = 3734639674346425312L;
/**
* 商户订单号
*/
@XmlElement(name = "partner_trade_no")
@JSONField(name = "partner_trade_no")
private String outTradeNo;
/**
* 接收红包的用户的openid
*/
private String openid;
/**
* 校验用户姓名选项
*
* @see com.foxinmy.weixin4j.mp.type.MPPaymentCheckNameType
*/
@XmlElement(name = "check_name")
@JSONField(name = "check_name")
private MPPaymentCheckNameType checkNameType;
/**
* 收款用户真实姓名。 如果check_name设置为FORCE_CHECK或OPTION_CHECK,则必填用户真实姓名 可选
*/
@XmlElement(name = "re_user_name")
@JSONField(name = "re_user_name")
private String userName;
/**
* 企业付款描述信息
*/
private String desc;
/**
* 付款金额
*/
private String amount;
/**
* 调用接口的机器Ip地址
*/
@XmlElement(name = "spbill_create_ip")
@JSONField(name = "spbill_create_ip")
private String clientIp;
protected MPPayment() {
// jaxb required
}
/**
* 企业付款
* @param outTradeNo 商户的订单号
* @param openid 用户的openid
* @param checkNameType 校验用户姓名选项
* @param desc 描述
* @param amount 金额
* @param clientIp 调用接口IP
*/
public MPPayment(String outTradeNo, String openid,
MPPaymentCheckNameType checkNameType, String desc, double amount,
String clientIp) {
this.outTradeNo = outTradeNo;
this.openid = openid;
this.checkNameType = checkNameType;
this.desc = desc;
this.amount = DateUtil.formaFee2Fen(amount);
this.clientIp = clientIp;
}
public String getOutTradeNo() {
return outTradeNo;
}
public String getOpenid() {
return openid;
}
public MPPaymentCheckNameType getCheckNameType() {
return checkNameType;
}
public String getUserName() {
return userName;
}
public String getDesc() {
return desc;
}
public String getAmount() {
return amount;
}
public String getClientIp() {
return clientIp;
}
public void setUserName(String userName) {
this.userName = userName;
}
@Override
public String toString() {
return "MPPayment [outTradeNo=" + outTradeNo + ", openid=" + openid
+ ", checkNameType=" + checkNameType + ", userName=" + userName
+ ", desc=" + desc + ", amount=" + amount + ", clientIp="
+ clientIp + "]";
}
}
@@ -0,0 +1,193 @@
package com.foxinmy.weixin4j.payment.mch;
import java.util.Date;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import com.alibaba.fastjson.annotation.JSONField;
import com.foxinmy.weixin4j.type.MPPaymentCheckNameType;
import com.foxinmy.weixin4j.util.DateUtil;
/**
* 企业付款记录
*
* @className MPPaymentRecord
* @author jy
* @date 2015年6月23日
* @since JDK 1.7
* @see
*/
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class MPPaymentRecord extends ApiResult {
private static final long serialVersionUID = -1926873539419750498L;
/**
* 微信订单订单号
*/
@JSONField(name = "detail_id")
@XmlElement(name = "detail_id")
private String transactionId;
/**
* 商户订单号
*/
@JSONField(name = "partner_trade_no")
@XmlElement(name = "partner_trade_no")
private String outTradeNo;
/**
* 交易状态 SUCCESS:转账成功 FAILED:转账失败
*/
@JSONField(name = "status")
@XmlElement(name = "status")
private String transactionStatus;
/**
* 如果失败则应该有原因
*/
@JSONField(name = "reason")
@XmlElement(name = "reason")
private String failureReason;
/**
* 收款用户openid
*/
private String openid;
/**
* 收款用户姓名
*/
@JSONField(name = "transfer_name")
@XmlElement(name = "transfer_name")
private String transferName;
/**
* 付款金额(单位为分)
*/
@JSONField(name = "payment_amount")
@XmlElement(name = "payment_amount")
private int paymentAmount;
/**
* 转账时间
*/
@JSONField(name = "transfer_time")
@XmlElement(name = "transfer_time")
private String transferTime;
/**
* 校验用户姓名选项
*
* @see com.foxinmy.weixin4j.mp.type.MPPaymentCheckNameType
*/
@XmlElement(name = "check_name")
@JSONField(name = "check_name")
private MPPaymentCheckNameType checkNameType;
/**
* 企业付款描述信息
*/
private String desc;
/**
* 实名验证结果 PASS:通过 FAILED:不通过
*/
@JSONField(name = "check_name_result")
@XmlElement(name = "check_name_result")
private String checkNameResult;
protected MPPaymentRecord() {
// jaxb required
}
public String getTransactionId() {
return transactionId;
}
public String getOutTradeNo() {
return outTradeNo;
}
public String getTransactionStatus() {
return transactionStatus;
}
/**
* 格式化交易状态
*
* @return
*/
@JSONField(serialize = false)
public boolean getFormatTransactionStatus() {
return "success".equalsIgnoreCase(transactionStatus);
}
public String getFailureReason() {
return failureReason;
}
public String getOpenid() {
return openid;
}
public String getTransferName() {
return transferName;
}
public int getPaymentAmount() {
return paymentAmount;
}
/**
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
*
* @return 元单位
*/
@JSONField(serialize = false)
public double getFormatPaymentAmount() {
return paymentAmount / 100d;
}
public String getTransferTime() {
return transferTime;
}
/**
* 格式化转账时间
*
* @return
*/
@JSONField(serialize = false)
public Date getFormatTransferTime() {
return DateUtil.parse2yyyyMMddHHmmss(transferTime);
}
public MPPaymentCheckNameType getCheckNameType() {
return checkNameType;
}
public String getDesc() {
return desc;
}
public String getCheckNameResult() {
return checkNameResult;
}
/**
* 格式化交易状态
*
* @return
*/
@JSONField(serialize = false)
public boolean getFormatCheckNameResult() {
return "pass".equalsIgnoreCase(checkNameResult);
}
@Override
public String toString() {
return "MPPaymentRecord [transactionId=" + transactionId
+ ", outTradeNo=" + outTradeNo + ", transactionStatus="
+ getFormatTransactionStatus() + ", failureReason="
+ failureReason + ", openid=" + openid + ", transferName="
+ transferName + ", paymentAmount=" + getFormatPaymentAmount()
+ ", transferTime=" + transferTime + ", checkNameType="
+ checkNameType + ", desc=" + desc + ", checkNameResult="
+ getFormatCheckNameResult() + ", " + super.toString() + "]";
}
}
@@ -0,0 +1,66 @@
package com.foxinmy.weixin4j.payment.mch;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import com.alibaba.fastjson.annotation.JSONField;
/**
* 企业付款结果
*
* @className MPPaymentResult
* @author jy
* @date 2015年4月1日
* @since JDK 1.7
* @see
*/
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class MPPaymentResult extends ApiResult {
private static final long serialVersionUID = 1110472826089211646L;
/**
* 微信订单订单号
*/
@JSONField(name = "payment_no")
@XmlElement(name = "payment_no")
private String transactionId;
/**
* 商户订单号
*/
@JSONField(name = "partner_trade_no")
@XmlElement(name = "partner_trade_no")
private String outTradeNo;
/**
* 支付时间
*/
@JSONField(name = "payment_time")
@XmlElement(name = "payment_time")
private String paymentTime;
protected MPPaymentResult() {
// jaxb required
}
public String getTransactionId() {
return transactionId;
}
public String getOutTradeNo() {
return outTradeNo;
}
public String getPaymentTime() {
return paymentTime;
}
@Override
public String toString() {
return "MPPaymentResult [transactionId=" + transactionId
+ ", outTradeNo=" + outTradeNo + ", paymentTime=" + paymentTime
+ "]";
}
}
@@ -0,0 +1,158 @@
package com.foxinmy.weixin4j.payment.mch;
import java.util.Date;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import com.alibaba.fastjson.annotation.JSONField;
import com.foxinmy.weixin4j.model.WeixinPayAccount;
import com.foxinmy.weixin4j.payment.PayPackage;
import com.foxinmy.weixin4j.type.TradeType;
import com.foxinmy.weixin4j.util.RandomUtil;
/**
* 支付的订单详情
*
* @className MchPayPackage
* @author jy
* @date 2014年10月21日
* @since JDK 1.7
* @see
*/
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class MchPayPackage extends PayPackage {
private static final long serialVersionUID = 8944928173669656177L;
/**
* 微信分配的公众账号 必须
*/
private String appid;
/**
* 微信支付分配的商户号 必须
*/
@XmlElement(name = "mch_id")
@JSONField(name = "mch_id")
private String mchId;
/**
* 微信支付分配的终端设备号 非必须
*/
@XmlElement(name = "device_info")
@JSONField(name = "device_info")
private String deviceInfo;
/**
* 随机字符串,不长于 32 位 必须
*/
@XmlElement(name = "nonce_str")
@JSONField(name = "nonce_str")
private String nonceStr;
/**
* 签名 <font color="red">调用者无需关心</font>
*/
private String sign;
/**
* 交易类型JSAPI、NATIVE、APP 必须
*/
@XmlElement(name = "trade_type")
@JSONField(name = "trade_type")
private String tradeType;
/**
* 用户在商户 appid 下的唯一 标识, trade_type 为 JSAPI 时,此参数必传
*/
private String openid;
/**
* 只在 trade_type 为 NATIVE 时需要填写 非必须
*/
@XmlElement(name = "product_id")
@JSONField(name = "product_id")
private String productId;
protected MchPayPackage() {
// jaxb required
}
public MchPayPackage(WeixinPayAccount weixinAccount, String openId,
String body, String outTradeNo, double totalFee,
String spbillCreateIp, TradeType tradeType) {
this(weixinAccount, openId, body, null, outTradeNo, totalFee, null,
spbillCreateIp, tradeType);
}
public MchPayPackage(WeixinPayAccount weixinAccount, String openId,
String body, String attach, String outTradeNo, double totalFee,
String notifyUrl, String spbillCreateIp, TradeType tradeType) {
this(weixinAccount.getId(), weixinAccount.getMchId(), weixinAccount
.getDeviceInfo(), RandomUtil.generateString(16), body, attach,
outTradeNo, totalFee, spbillCreateIp, null, null, null,
notifyUrl, tradeType, openId, null);
}
public MchPayPackage(String appid, String mchId, String deviceInfo,
String nonceStr, String body, String attach, String outTradeNo,
double totalFee, String spbillCreateIp, Date timeStart,
Date timeExpire, String goodsTag, String notifyUrl,
TradeType tradeType, String openid, String productId) {
super(body, attach, outTradeNo, totalFee, spbillCreateIp, timeStart,
timeExpire, goodsTag, notifyUrl);
this.appid = appid;
this.mchId = mchId;
this.deviceInfo = deviceInfo;
this.nonceStr = nonceStr;
this.tradeType = tradeType.name();
this.openid = openid;
this.productId = productId;
}
public String getAppid() {
return appid;
}
public String getMchId() {
return mchId;
}
public String getDeviceInfo() {
return deviceInfo;
}
public String getNonceStr() {
return nonceStr;
}
public String getSign() {
return sign;
}
public void setSign(String sign) {
this.sign = sign;
}
public String getTradeType() {
return tradeType;
}
public String getOpenid() {
return openid;
}
public String getProductId() {
return productId;
}
public void setProductId(String productId) {
this.productId = productId;
}
@Override
public String toString() {
return "MchPayPackage [appid=" + appid + ", mchId=" + mchId
+ ", deviceInfo=" + deviceInfo + ", nonceStr=" + nonceStr
+ ", sign=" + sign + ", tradeType=" + tradeType + ", openid="
+ openid + ", productId=" + productId + ", " + super.toString()
+ "]";
}
}
@@ -0,0 +1,46 @@
package com.foxinmy.weixin4j.payment.mch;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import com.foxinmy.weixin4j.exception.PayException;
import com.foxinmy.weixin4j.payment.PayRequest;
/**
* JS支付:get_brand_wcpay_request</br>
* <p>
* get_brand_wcpay_request:ok 支付成功<br>
* get_brand_wcpay_request:cancel 支付过程中用户取消<br>
* get_brand_wcpay_request:fail 支付失败
* </p>
* <p>
* NATIVE支付:PayRequest.TradeType=NATIVE
* </p>
*
* @className PayRequest
* @author jy
* @date 2014年8月17日
* @since JDK 1.7
* @see com.foxinmy.weixin4j.payment.mch.PrePay
*/
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class MchPayRequest extends PayRequest {
private static final long serialVersionUID = -5972173459255255197L;
protected MchPayRequest() {
// jaxb required
}
public MchPayRequest(PrePay prePay) throws PayException {
this.setAppId(prePay.getAppId());
this.setPackageInfo("prepay_id=" + prePay.getPrepayId());
}
@Override
public String toString() {
return "MchPayRequest [" + super.toString() + "]";
}
}
@@ -0,0 +1,42 @@
package com.foxinmy.weixin4j.payment.mch;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
/**
* Native支付回调时POST的信息
*
* @className PayNativeNotify
* @author jy
* @date 2014年10月30日
* @since JDK 1.7
* @see
*/
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class NativePayNotify extends ApiResult {
private static final long serialVersionUID = 4515471400239795492L;
/**
* 产品ID 可视为订单ID
*/
@XmlElement(name = "product_id")
private String productId;
protected NativePayNotify() {
// jaxb required
}
public String getProductId() {
return productId;
}
@Override
public String toString() {
return "NativePayNotify [productId=" + productId + ", "
+ super.toString() + "]";
}
}
@@ -0,0 +1,87 @@
package com.foxinmy.weixin4j.payment.mch;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import com.alibaba.fastjson.annotation.JSONField;
import com.foxinmy.weixin4j.exception.PayException;
import com.foxinmy.weixin4j.model.Consts;
import com.foxinmy.weixin4j.payment.PayUtil;
import com.foxinmy.weixin4j.util.RandomUtil;
/**
* Native支付时的回调响应
*
* @className NativePayResponseV3
* @author jy
* @date 2014年10月28日
* @since JDK 1.7
* @see
*/
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class NativePayResponse extends ApiResult {
private static final long serialVersionUID = 6119895998783333012L;
@XmlTransient
@JSONField(serialize = false)
private PrePay prePay;
private String prepay_id;
protected NativePayResponse() {
// jaxb required
}
/**
* 一般作为校验失败时返回
*
* @param returnMsg
* 失败消息
* @param resultMsg
* 结果消息
* @throws PayException
*/
public NativePayResponse(String returnMsg, String resultMsg) {
super.setReturnMsg(returnMsg);
super.setReturnCode(Consts.FAIL);
super.setErrCodeDes(resultMsg);
super.setResultCode(Consts.FAIL);
}
/**
* 作为return_code 为 SUCCESS 的时候返回
*
* @param payPackage
* 订单信息
* @throws PayException
*/
public NativePayResponse(MchPayPackage payPackage, String paysignKey)
throws PayException {
super.setReturnCode(Consts.SUCCESS);
this.setResultCode(Consts.SUCCESS);
this.setMchId(payPackage.getMchId());
this.setAppId(payPackage.getAppid());
this.setNonceStr(RandomUtil.generateString(16));
this.prePay = PayUtil.createPrePay(payPackage, paysignKey);
this.prepay_id = prePay.getPrepayId();
}
public String getPrepay_id() {
return prepay_id;
}
public void setPrepay_id(String prepay_id) {
this.prepay_id = prepay_id;
}
@Override
public String toString() {
return "NativePayResponseV3 [prePay=" + prePay + ", prepay_id="
+ prepay_id + ", " + super.toString() + "]";
}
}
@@ -0,0 +1,268 @@
package com.foxinmy.weixin4j.payment.mch;
import java.util.Date;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import com.alibaba.fastjson.annotation.JSONField;
import com.foxinmy.weixin4j.payment.coupon.CouponInfo;
import com.foxinmy.weixin4j.type.CurrencyType;
import com.foxinmy.weixin4j.type.TradeState;
import com.foxinmy.weixin4j.type.TradeType;
import com.foxinmy.weixin4j.util.DateUtil;
import com.foxinmy.weixin4j.util.StringUtil;
import com.foxinmy.weixin4j.xml.ListsuffixResult;
/**
* V3订单信息
*
* @className Order
* @author jy
* @date 2014年11月2日
* @since JDK 1.7
* @see
*/
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Order extends ApiResult {
private static final long serialVersionUID = 5636828325595317079L;
/**
* 交易状态
*
* @see com.foxinmy.weixin4j.mp.type.TradeState
*/
@XmlElement(name = "trade_state")
@JSONField(name = "trade_state")
private TradeState tradeState;
/**
* 用户的openid
*/
@XmlElement(name = "openid")
@JSONField(name = "openid")
private String openId;
/**
* 用户是否关注公众账号,Y- 关注,N-未关注,仅在公众 账号类型支付有效
*/
@XmlElement(name = "is_subscribe")
@JSONField(name = "is_subscribe")
private String isSubscribe;
/**
* 交易类型
*
* @see com.foxinmy.weixin4j.mp.type.TradeType
*/
@XmlElement(name = "trade_type")
@JSONField(name = "trade_type")
private TradeType tradeType;
/**
* 银行类型
*/
@XmlElement(name = "bank_type")
@JSONField(name = "bank_type")
private String bankType;
/**
* 订单总金额,单位为分
*/
@XmlElement(name = "total_fee")
@JSONField(name = "total_fee")
private int totalFee;
/**
* 现金券支付金额<=订单总金 额,订单总金额-现金券金额 为现金支付金额
*/
@XmlElement(name = "coupon_fee")
@JSONField(name = "coupon_fee")
private Integer couponFee;
/**
* 代金券或立减优惠使用数量
*/
@XmlElement(name = "coupon_count")
@JSONField(name = "coupon_count")
private Integer couponCount;
/**
* 代金券信息 验证签名有点麻烦
*/
@ListsuffixResult
private List<CouponInfo> couponList;
/**
* 现金支付金额
*/
@XmlElement(name = "cash_fee")
@JSONField(name = "cash_fee")
private int cashFee;
/**
* 货币类型,符合 ISO 4217 标准的三位字母代码,默认人民币:CNY
*
* @see com.foxinmy.weixin4j.mp.type.CurrencyType
*/
@XmlElement(name = "fee_type")
@JSONField(name = "fee_type")
private CurrencyType feeType;
/**
* 微信支付订单号
*/
@XmlElement(name = "transaction_id")
@JSONField(name = "transaction_id")
private String transactionId;
/**
* 商户订单号
*/
@XmlElement(name = "out_trade_no")
@JSONField(name = "out_trade_no")
private String outTradeNo;
/**
* 商家数据包
*/
private String attach;
/**
* 支付完成时间,格式为 yyyyMMddhhmmss
*/
@XmlElement(name = "time_end")
@JSONField(name = "time_end")
private String timeEnd;
/**
* 交易状态描述
*/
@XmlElement(name = "trade_state_desc")
@JSONField(name = "trade_state_desc")
private String tradeStateDesc;
protected Order() {
// jaxb required
}
public TradeState getTradeState() {
return tradeState;
}
public String getOpenId() {
return openId;
}
public String getIsSubscribe() {
return isSubscribe;
}
@JSONField(serialize = false, deserialize = false)
public boolean getFormatIsSubscribe() {
return isSubscribe != null && isSubscribe.equalsIgnoreCase("y");
}
public TradeType getTradeType() {
return tradeType;
}
public String getBankType() {
return bankType;
}
public int getTotalFee() {
return totalFee;
}
/**
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
*
* @return 元单位
*/
@JSONField(serialize = false, deserialize = false)
public double getFormatTotalFee() {
return totalFee / 100d;
}
public Integer getCouponFee() {
return couponFee;
}
/**
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
*
* @return 元单位
*/
@JSONField(serialize = false, deserialize = false)
public double getFormatCouponFee() {
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() {
return cashFee;
}
/**
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
*
* @return 元单位
*/
@JSONField(serialize = false, deserialize = false)
public double getFormatCashFee() {
return cashFee / 100d;
}
public CurrencyType getFeeType() {
return feeType;
}
public String getTransactionId() {
return transactionId;
}
public String getOutTradeNo() {
return outTradeNo;
}
public String getAttach() {
return attach;
}
public String getTimeEnd() {
return timeEnd;
}
@JSONField(serialize = false, deserialize = false)
public Date getFormatTimeEnd() {
if (StringUtil.isNotBlank(timeEnd)) {
return DateUtil.parse2yyyyMMddHHmmss(timeEnd);
}
return null;
}
public String getTradeStateDesc() {
return tradeStateDesc;
}
public List<CouponInfo> getCouponList() {
return couponList;
}
public void setCouponList(List<CouponInfo> couponList) {
this.couponList = couponList;
}
@Override
public String toString() {
return "Order [tradeState=" + tradeState + ", openId=" + openId
+ ", isSubscribe=" + getFormatIsSubscribe() + ", tradeType="
+ tradeType + ", bankType=" + bankType + ", feeType=" + feeType
+ ", transactionId=" + transactionId + ", outTradeNo="
+ outTradeNo + ", attach=" + attach + ", timeEnd=" + timeEnd
+ ", totalFee=" + getFormatTotalFee() + ", couponFee="
+ getFormatCouponFee() + ", couponCount="
+ getFormatCouponCount() + ", couponList=" + couponList
+ ", cashFee=" + getFormatCashFee() + ", timeEnd="
+ getFormatTimeEnd() + ", tradeStateDesc=" + tradeStateDesc
+ ", " + super.toString() + "]";
}
}
@@ -0,0 +1,80 @@
package com.foxinmy.weixin4j.payment.mch;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import com.foxinmy.weixin4j.type.TradeType;
/**
* V3预订单信息
*
* @className PrePay
* @author jy
* @date 2014年10月21日
* @since JDK 1.7
* @see
*/
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class PrePay extends ApiResult {
private static final long serialVersionUID = -8430005768959715444L;
/**
* 调用接口提交的交易类型,取值如下:JSAPI,NATIVEAPP
*
* @see com.foxinmy.weixin4j.mp.type.TradeType
*/
@XmlElement(name = "trade_type")
private TradeType tradeType;
/**
* 微信生成的预支付回话标识,用于后续接口调用中使用,该值有效期为2小时
*/
@XmlElement(name = "prepay_id")
private String prepayId;
/**
* trade_type 为 NATIVE 是有 返回,此参数可直接生成二 维码展示出来进行扫码支付 可能为空
*/
@XmlElement(name = "code_url")
private String codeUrl;
protected PrePay() {
// jaxb required
}
public PrePay(String returnCode, String returnMsg) {
super(returnCode, returnMsg);
}
public TradeType getTradeType() {
return tradeType;
}
public void setTradeType(TradeType tradeType) {
this.tradeType = tradeType;
}
public String getPrepayId() {
return prepayId;
}
public void setPrepayId(String prepayId) {
this.prepayId = prepayId;
}
public String getCodeUrl() {
return codeUrl;
}
public void setCodeUrl(String codeUrl) {
this.codeUrl = codeUrl;
}
@Override
public String toString() {
return "PrePay [tradeType=" + tradeType + ", prepayId=" + prepayId
+ ", codeUrl=" + codeUrl + ", " + super.toString() + "]";
}
}
@@ -0,0 +1,279 @@
package com.foxinmy.weixin4j.payment.mch;
import java.io.Serializable;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import com.alibaba.fastjson.annotation.JSONField;
import com.foxinmy.weixin4j.util.DateUtil;
/**
* 红包
*
* @className Redpacket
* @author jy
* @date 2015年3月28日
* @since JDK 1.7
* @see <a
* href="http://pay.weixin.qq.com/wiki/doc/api/cash_coupon.php?chapter=13_1">红包简介</a>
*/
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Redpacket implements Serializable {
private static final long serialVersionUID = -7021352305575714281L;
/**
* 商户订单号(每个订单号必须唯一) 组成: mch_id+yyyymmdd+10位一天内不能重复的数字。
*/
@XmlElement(name = "mch_billno")
@JSONField(name = "mch_billno")
private String outTradeNo;
/**
* 提供方名称 必填
*/
@XmlElement(name = "nick_name")
@JSONField(name = "nick_name")
private String nickName;
/**
* 红包发送者名称 必填
*/
@XmlElement(name = "send_name")
@JSONField(name = "send_name")
private String sendName;
/**
* 接收红包的用户的openid
*/
@XmlElement(name = "re_openid")
@JSONField(name = "re_openid")
private String openid;
/**
* 付款金额,单位分
*/
@XmlElement(name = "total_amount")
@JSONField(name = "total_amount")
private String totalAmount;
/**
* 最小红包金额,单位分
*/
@XmlElement(name = "min_value")
@JSONField(name = "min_value")
private String minValue;
/**
* 最大红包金额,单位分( 最小金额等于最大金额: min_value=max_value =total_amount
*/
@XmlElement(name = "max_value")
@JSONField(name = "max_value")
private String maxValue;
/**
* 红包发放总人数
*/
@XmlElement(name = "total_num")
@JSONField(name = "total_num")
private int totalNum;
/**
* 红包祝福语
*/
private String wishing;
/**
* ip地址
*/
@XmlElement(name = "client_ip")
@JSONField(name = "client_ip")
private String clientIp;
/**
* 活动名称
*/
@XmlElement(name = "act_name")
@JSONField(name = "act_name")
private String actName;
/**
* 备注
*/
private String remark;
/**
* 商户logo的url 非必填
*/
@XmlElement(name = "logo_imgurl")
@JSONField(name = "logo_imgurl")
private String logoUrl;
/**
* 分享文案 非必填
*/
@XmlElement(name = "share_content")
@JSONField(name = "share_content")
private String shareContent;
/**
* 分享链接 非必填
*/
@XmlElement(name = "share_url")
@JSONField(name = "share_url")
private String shareUrl;
/**
* 分享的图片 非必填
*/
@XmlElement(name = "share_imgurl")
@JSONField(name = "share_imgurl")
private String shareImageUrl;
protected Redpacket() {
// jaxb required
}
/**
* 红包
*
* @param outTradeNo
* 商户侧一天内不可重复的订单号 接口根据商户订单号支持重入 如出现超时可再调用
* @param nickName
* 提供方名称
* @param sendName
* 红包发送者名称
* @param openid
* 接受收红包的用户的openid
* @param totalAmount
* 付款金额 <font color="red">单位为元,自动格式化为分</font>
*/
public Redpacket(String outTradeNo, String nickName, String sendName,
String openid, double totalAmount) {
this.outTradeNo = outTradeNo;
this.nickName = nickName;
this.sendName = sendName;
this.openid = openid;
this.totalAmount = DateUtil.formaFee2Fen(totalAmount);
}
public String getOutTradeNo() {
return outTradeNo;
}
public String getNickName() {
return nickName;
}
public String getSendName() {
return sendName;
}
public String getOpenid() {
return openid;
}
public String getTotalAmount() {
return totalAmount;
}
public String getMinValue() {
return minValue;
}
/**
* <font color="red">单位为元,自动格式化为分</font>
*
* @param minValue
* 最小红包 单位为元
*/
public void setMinValue(double minValue) {
this.minValue = DateUtil.formaFee2Fen(minValue);
}
public String getMaxValue() {
return maxValue;
}
/**
* <font color="red">单位为元,自动格式化为分</font>
*
* @param minValue
* 最大红包 单位为元
*/
public void setMaxValue(double maxValue) {
this.maxValue = DateUtil.formaFee2Fen(maxValue);
}
public int getTotalNum() {
return totalNum;
}
public void setTotalNum(int totalNum) {
this.totalNum = totalNum;
}
public String getWishing() {
return wishing;
}
public void setWishing(String wishing) {
this.wishing = wishing;
}
public String getClientIp() {
return clientIp;
}
public void setClientIp(String clientIp) {
this.clientIp = clientIp;
}
public String getActName() {
return actName;
}
public void setActName(String actName) {
this.actName = actName;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
public String getLogoUrl() {
return logoUrl;
}
public void setLogoUrl(String logoUrl) {
this.logoUrl = logoUrl;
}
public String getShareContent() {
return shareContent;
}
public void setShareContent(String shareContent) {
this.shareContent = shareContent;
}
public String getShareUrl() {
return shareUrl;
}
public void setShareUrl(String shareUrl) {
this.shareUrl = shareUrl;
}
public String getShareImageUrl() {
return shareImageUrl;
}
public void setShareImageUrl(String shareImageUrl) {
this.shareImageUrl = shareImageUrl;
}
@Override
public String toString() {
return "Redpacket [ nickName=" + nickName + ", sendName=" + sendName
+ ", openid=" + openid + ", totalAmount=" + totalAmount
+ ", minValue=" + minValue + ", maxValue=" + maxValue
+ ", totalNum=" + totalNum + ", wishing=" + wishing
+ ", clientIp=" + clientIp + ", actName=" + actName
+ ", remark=" + remark + ", logoUrl=" + logoUrl
+ ", shareContent=" + shareContent + ", shareUrl=" + shareUrl
+ ", shareImageUrl=" + shareImageUrl + "]";
}
}
@@ -0,0 +1,305 @@
package com.foxinmy.weixin4j.payment.mch;
import java.util.Date;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
import com.alibaba.fastjson.annotation.JSONField;
import com.foxinmy.weixin4j.http.weixin.XmlResult;
import com.foxinmy.weixin4j.type.RedpacketSendType;
import com.foxinmy.weixin4j.type.RedpacketStatus;
import com.foxinmy.weixin4j.type.RedpacketType;
import com.foxinmy.weixin4j.util.DateUtil;
import com.foxinmy.weixin4j.util.StringUtil;
/**
* 红包记录
*
* @className RedpacketRecord
* @author jy
* @date 2015年6月4日
* @since JDK 1.7
* @see
*/
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class RedpacketRecord extends XmlResult {
private static final long serialVersionUID = 929959747323918458L;
/**
* 商户订单号(每个订单号必须唯一) 组成: mch_id+yyyymmdd+10位一天内不能重复的数字。
*/
@XmlElement(name = "mch_billno")
@JSONField(name = "mch_billno")
private String outTradeNo;
/**
* 微信支付分配的商户号
*/
@XmlElement(name = "mch_id")
@JSONField(name = "mch_id")
private String mchId;
/**
* 红包单号
*/
@XmlElement(name = "detail_id")
@JSONField(name = "detail_id")
private String repacketId;
/**
* 红包状态
*/
@XmlElement(name = "status")
private RedpacketStatus status;
/**
* 发放类型
*/
@XmlElement(name = "send_type")
@JSONField(name = "send_type")
private RedpacketSendType sendType;
/**
* 红包类型
*/
@XmlElement(name = "hb_type")
@JSONField(name = "hb_type")
private RedpacketType type;
/**
* 红包个数
*/
@XmlElement(name = "total_num")
@JSONField(name = "total_num")
private int totalNum;
/**
* 红包总金额(单位分)
*/
@XmlElement(name = "total_amount")
@JSONField(name = "total_amount")
private int totalAmount;
/**
* 发送失败原因
*/
@XmlElement(name = "reason")
private String reason;
/**
* 发放时间
*/
@XmlElement(name = "send_time")
@JSONField(name = "send_time")
private String sendTime;
/**
* 红包退款时间
*/
@XmlElement(name = "refund_time")
@JSONField(name = "refund_time")
private String refundTime;
/**
* 红包退款金额
*/
@XmlElement(name = "refund_amount")
@JSONField(name = "refund_amount")
private Integer refundAmount;
/**
* 祝福语
*/
@XmlElement(name = "wishing")
private String wishing;
/**
* 活动描述
*/
@XmlElement(name = "remark")
private String remark;
/**
* 活动名称
*/
@XmlElement(name = "act_name")
@JSONField(name = "act_name")
private String actName;
/**
* 裂变红包领取列表
*/
@XmlElement(name = "hbinfo")
@XmlElementWrapper(name = "hblist")
@JSONField(name = "hblist")
private List<RedpacketReceiver> receivers;
public String getOutTradeNo() {
return outTradeNo;
}
public String getMchId() {
return mchId;
}
public String getRepacketId() {
return repacketId;
}
public RedpacketStatus getStatus() {
return status;
}
public RedpacketSendType getSendType() {
return sendType;
}
public RedpacketType getType() {
return type;
}
public int getTotalNum() {
return totalNum;
}
public int getTotalAmount() {
return totalAmount;
}
/**
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
*
* @return 元单位
*/
@JSONField(serialize = false, deserialize = false)
public double getFormatTotalAmount() {
return totalAmount / 100d;
}
public String getReason() {
return reason;
}
public String getSendTime() {
return sendTime;
}
@JSONField(serialize = false, deserialize = false)
public Date getFormatSendTime() {
return DateUtil.parse2yyyyMMddHHmmss(sendTime);
}
public String getRefundTime() {
return refundTime;
}
@JSONField(serialize = false, deserialize = false)
public Date getFormatRefundTime() {
if (StringUtil.isNotBlank(refundTime)) {
return DateUtil.parse2yyyyMMddHHmmss(refundTime);
}
return null;
}
public Integer getRefundAmount() {
return refundAmount;
}
/**
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
*
* @return 元单位
*/
@JSONField(serialize = false, deserialize = false)
public double getFormatRefundAmount() {
if (refundAmount != null) {
return refundAmount.intValue() / 100d;
}
return 0d;
}
public String getWishing() {
return wishing;
}
public String getRemark() {
return remark;
}
public String getActName() {
return actName;
}
public List<RedpacketReceiver> getReceivers() {
return receivers;
}
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public static class RedpacketReceiver {
/**
* 领取红包的Openid
*/
@XmlElement(name = "openid")
private String openid;
/**
* 领取状态
*/
@XmlElement(name = "status")
private RedpacketStatus status;
/**
* 领取金额
*/
private int amount;
/**
* 领取时间
*/
@XmlElement(name = "rcv_time")
@JSONField(name = "rcv_time")
private String receiveTime;
public String getOpenid() {
return openid;
}
public RedpacketStatus getStatus() {
return status;
}
public int getAmount() {
return amount;
}
public String getReceiveTime() {
return receiveTime;
}
/**
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
*
* @return 元单位
*/
@JSONField(serialize = false, deserialize = false)
public double getFormatAmount() {
return amount / 100d;
}
@JSONField(serialize = false, deserialize = false)
public Date getFormatReceiveTime() {
return DateUtil.parse2yyyyMMddHHmmss(receiveTime);
}
@Override
public String toString() {
return "RedpacketReceiver [openid=" + openid + ", status=" + status
+ ", amount=" + getFormatAmount() + ", receiveTime="
+ receiveTime + "]";
}
}
@Override
public String toString() {
return "RedpacketRecord [outTradeNo=" + outTradeNo + ", mchId=" + mchId
+ ", repacketId=" + repacketId + ", status=" + status
+ ", sendType=" + sendType + ", type=" + type + ", totalNum="
+ totalNum + ", totalAmount=" + getFormatTotalAmount()
+ ", reason=" + reason + ", sendTime=" + sendTime
+ ", refundTime=" + refundTime + ", refundAmount="
+ getFormatRefundAmount() + ", wishing=" + wishing
+ ", remark=" + remark + ", actName=" + actName
+ ", receivers=" + receivers + "]";
}
}
@@ -0,0 +1,97 @@
package com.foxinmy.weixin4j.payment.mch;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import com.alibaba.fastjson.annotation.JSONField;
import com.foxinmy.weixin4j.http.weixin.XmlResult;
/**
* 发送红包结果
*
* @className RedpacketSendResult
* @author jy
* @date 2015年4月1日
* @since JDK 1.7
* @see
*/
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class RedpacketSendResult extends XmlResult {
private static final long serialVersionUID = 5611847899634131711L;
/**
* 微信分配的公众账号
*/
@XmlElement(name = "wxappid")
@JSONField(name = "wxappid")
private String appid;
/**
* 微信支付分配的商户号
*/
@XmlElement(name = "mch_id")
@JSONField(name = "mch_id")
private String mchId;
/**
* 商户订单号(每个订单号必须唯一) 组成: mch_id+yyyymmdd+10位一天内不能重复的数字。
*/
@XmlElement(name = "mch_billno")
@JSONField(name = "mch_billno")
private String outTradeNo;
/**
* 接收红包的用户的openid
*/
@XmlElement(name = "re_openid")
@JSONField(name = "re_openid")
private String openid;
/**
* 付款金额 单位为分
*/
@XmlElement(name = "total_amount")
@JSONField(name = "total_amount")
private int totalAmount;
protected RedpacketSendResult() {
// jaxb required
}
public String getAppid() {
return appid;
}
public String getMchId() {
return mchId;
}
public String getOutTradeNo() {
return outTradeNo;
}
public String getOpenid() {
return openid;
}
public int getTotalAmount() {
return totalAmount;
}
/**
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
*
* @return 元单位
*/
@JSONField(serialize = false, deserialize = false)
public double getFormatTotalAmount() {
return totalAmount / 100d;
}
@Override
public String toString() {
return "RedpacketSendResult [appid=" + appid + ", mchId=" + mchId
+ ", outTradeNo=" + outTradeNo + ", openid=" + openid
+ ", totalAmount=" + totalAmount + ", " + super.toString()
+ "]";
}
}
@@ -0,0 +1,288 @@
package com.foxinmy.weixin4j.payment.mch;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import com.alibaba.fastjson.annotation.JSONField;
import com.foxinmy.weixin4j.payment.coupon.CouponInfo;
import com.foxinmy.weixin4j.type.CurrencyType;
import com.foxinmy.weixin4j.type.RefundChannel;
import com.foxinmy.weixin4j.type.RefundStatus;
import com.foxinmy.weixin4j.util.StringUtil;
import com.foxinmy.weixin4j.xml.ListsuffixResult;
/**
* V3退款详细
*
* @className RefundDetail
* @author jy
* @date 2014年11月6日
* @since JDK 1.7
* @see
*/
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class RefundDetail extends ApiResult {
private static final long serialVersionUID = -3687863914168618620L;
/**
* 商户退款单号
*/
@XmlElement(name = "out_refund_no")
@JSONField(name = "out_refund_no")
private String outRefundNo;
/**
* 微信退款单号
*/
@XmlElement(name = "refund_id")
@JSONField(name = "refund_id")
private String refundId;
/**
* 退款渠道:ORIGINAL—原路退款,默认 BALANCE—退回到余额
*/
@XmlElement(name = "refund_channel")
@JSONField(name = "refund_channel")
private String refundChannel;
/**
* 退款总金额,单位为分,可以做部分退款
*/
@XmlElement(name = "refund_fee")
@JSONField(name = "refund_fee")
private int refundFee;
/**
* 退款货币种类
*
* @see com.foxinmy.weixin4j.mp.type.CurrencyType
*/
@XmlElement(name = "refund_fee_type")
@JSONField(name = "refund_fee_type")
private CurrencyType refundFeeType;
/**
* 订单总金额
*/
@XmlElement(name = "total_fee")
@JSONField(name = "total_fee")
private int totalFee;
/**
* 订单金额货币种类
*
* @see com.foxinmy.weixin4j.mp.type.CurrencyType
*/
@XmlElement(name = "fee_type")
@JSONField(name = "fee_type")
private CurrencyType feeType;
/**
* 现金支付金额
*/
@XmlElement(name = "cash_fee")
@JSONField(name = "cash_fee")
private int cashFee;
/**
* 现金支付货币种类
*
* @see com.foxinmy.weixin4j.mp.type.CurrencyType
*/
@XmlElement(name = "cash_fee_type")
@JSONField(name = "cash_fee_type")
private CurrencyType cashFeeType;
/**
* 现金退款金额
*/
@XmlElement(name = "cash_refund_fee")
@JSONField(name = "cash_refund_fee")
private Integer cashRefundFee;
/**
* 现金退款货币类型
*
* @see com.foxinmy.weixin4j.mp.type.CurrencyType
*/
@XmlElement(name = "cash_refund_fee_type")
@JSONField(name = "cash_refund_fee_type")
private CurrencyType cashRefundFeeType;
/**
* 退款状态
*/
@XmlElement(name = "refund_status")
@JSONField(name = "refund_status")
private String refundStatus;
/**
* 现金券退款金额<=退款金额,退款金额-现金券退款金额为现金
*/
@XmlElement(name = "coupon_refund_fee")
@JSONField(name = "coupon_refund_fee")
private Integer couponRefundFee;
/**
* 代金券或立减优惠使用数量 <font
* color="red">微信支付文档上写的coupon_count,而实际测试拿到的是coupon_refund_count,做个记号。
* </font>
*/
@XmlElement(name = "coupon_refund_count")
@JSONField(name = "coupon_refund_count")
private Integer couponRefundCount;
/**
* 代金券信息
*
* @see com.foxinmy.weixin4j.payment.coupon.CouponInfo
*/
@ListsuffixResult
private List<CouponInfo> couponList;
protected RefundDetail() {
// jaxb required
}
public String getOutRefundNo() {
return outRefundNo;
}
public String getRefundId() {
return refundId;
}
public String getRefundChannel() {
return refundChannel;
}
@JSONField(deserialize = false, serialize = false)
public RefundChannel getFormatRefundChannel() {
if (StringUtil.isNotBlank(refundChannel)) {
return RefundChannel.valueOf(refundChannel.toUpperCase());
}
return null;
}
public int getRefundFee() {
return refundFee;
}
public CurrencyType getFeeType() {
return feeType;
}
/**
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
*
* @return 元单位
*/
@JSONField(deserialize = false, serialize = false)
public double getFormatRefundFee() {
return refundFee / 100d;
}
public String getRefundStatus() {
return refundStatus;
}
@JSONField(deserialize = false, serialize = false)
public RefundStatus getFormatRefundStatus() {
if (StringUtil.isNotBlank(refundStatus)) {
return RefundStatus.valueOf(refundStatus);
}
return null;
}
public Integer getCouponRefundFee() {
return couponRefundFee;
}
/**
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
*
* @return 元单位
*/
@JSONField(deserialize = false, serialize = false)
public double getFormatCouponRefundFee() {
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
public String toString() {
return "RefundDetail [outRefundNo=" + outRefundNo + ", refundId="
+ refundId + ", refundChannel=" + refundChannel
+ ", refundFee=" + getFormatRefundFee() + ", refundFeeType="
+ refundFeeType + ", totalFee=" + getFormatTotalFee()
+ ", feeType=" + feeType + ", cashFee=" + getFormatCashFee()
+ ", cashFeeType=" + cashFeeType + ", cashRefundFee="
+ getFormatCashRefundFee() + ", cashRefundFeeType="
+ cashRefundFeeType + ", refundStatus=" + refundStatus
+ ", couponRefundFee=" + getFormatCouponRefundFee()
+ ", couponCount=" + getCouponRefundCount() + ", couponList="
+ couponList + ", " + super.toString() + "]";
}
}
@@ -0,0 +1,192 @@
package com.foxinmy.weixin4j.payment.mch;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import com.alibaba.fastjson.annotation.JSONField;
import com.foxinmy.weixin4j.type.CurrencyType;
import com.foxinmy.weixin4j.xml.ListsuffixResult;
/**
* V3退款记录
*
* @className RefundRecord
* @author jy
* @date 2014年11月1日
* @since JDK 1.7
*/
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class RefundRecord extends ApiResult {
private static final long serialVersionUID = -2971132874939642721L;
/**
* 微信订单号
*/
@XmlElement(name = "transaction_id")
@JSONField(name = "transaction_id")
private String transactionId;
/**
* 商户订单号
*/
@XmlElement(name = "out_trade_no")
@JSONField(name = "out_trade_no")
private String outTradeNo;
/**
* 订单总金额
*/
@XmlElement(name = "total_fee")
@JSONField(name = "total_fee")
private int totalFee;
/**
* 订单金额货币种类
*
* @see com.foxinmy.weixin4j.mp.type.CurrencyType
*/
@XmlElement(name = "fee_type")
@JSONField(name = "fee_type")
private CurrencyType feeType;
/**
* 现金支付金额
*/
@XmlElement(name = "cash_fee")
@JSONField(name = "cash_fee")
private int cashFee;
/**
* 现金支付金额货币种类
*
* @see com.foxinmy.weixin4j.mp.type.CurrencyType
*/
@XmlElement(name = "cash_fee_type")
@JSONField(name = "cash_fee_type")
private CurrencyType cashFeeType;
/**
* 退款总金额
*/
@XmlElement(name = "refund_fee")
@JSONField(name = "refund_fee")
private int refundFee;
/**
* 代金券或立减优惠退款金额=订单金额-现金退款金额,注意:满立减金额不会退回
*/
@XmlElement(name = "coupon_refund_fee")
@JSONField(name = "coupon_refund_fee")
private Integer couponRefundFee;
/**
* 退款笔数
*/
@XmlElement(name = "refund_count")
@JSONField(name = "refund_count")
private int refundCount;
/**
* 退款详情
*
* @see com.foxinmy.weixin4j.payment.mch.RefundDetail
*/
@ListsuffixResult({ "^out_refund_no(_\\d)$", "^refund_.*(_\\d)$" })
private List<RefundDetail> refundList;
protected RefundRecord() {
// jaxb required
}
public String getTransactionId() {
return transactionId;
}
public String getOutTradeNo() {
return outTradeNo;
}
/**
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
*
* @return 元单位
*/
@JSONField(serialize = false, deserialize = false)
public double getFormatCashFee() {
return cashFee / 100d;
}
public int getCashFee() {
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 getRefundCount() {
return refundCount;
}
public List<RefundDetail> getRefundList() {
return refundList;
}
public void setRefundList(List<RefundDetail> refundList) {
this.refundList = refundList;
}
public int getRefundFee() {
return refundFee;
}
/**
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
*
* @return 元单位
*/
@JSONField(serialize = false, deserialize = false)
public double getFormatRefundFee() {
return refundFee / 100d;
}
@Override
public String toString() {
return "RefundRecord [transactionId=" + transactionId + ", outTradeNo="
+ outTradeNo + ", totalFee=" + getFormatTotalFee()
+ ", feeType=" + feeType + ", cashFee=" + getFormatCashFee()
+ ", cashFeeType=" + cashFeeType + ", refundFee="
+ getFormatRefundFee() + ", couponRefundFee="
+ getFormatCouponRefundFee() + ", refundCount=" + refundCount
+ ", refundList=" + refundList + ", " + super.toString() + "]";
}
}
@@ -0,0 +1,55 @@
package com.foxinmy.weixin4j.payment.mch;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import com.alibaba.fastjson.annotation.JSONField;
/**
* V3退款申请结果
*
* @className RefundResult
* @author jy
* @date 2014年11月6日
* @since JDK 1.7
* @see
*/
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class RefundResult extends RefundDetail {
private static final long serialVersionUID = -3687863914168618620L;
/**
* 微信订单号
*/
@XmlElement(name = "transaction_id")
@JSONField(name = "transaction_id")
private String transactionId;
/**
* 商户系统内部的订单号
*/
@XmlElement(name = "out_trade_no")
@JSONField(name = "out_trade_no")
private String outTradeNo;
protected RefundResult() {
// jaxb required
}
public String getTransactionId() {
return transactionId;
}
public String getOutTradeNo() {
return outTradeNo;
}
@Override
public String toString() {
return "RefundResult [transactionId=" + transactionId + ", outTradeNo="
+ outTradeNo + ", " + super.toString() + "]";
}
}
@@ -0,0 +1,34 @@
package com.foxinmy.weixin4j.type;
/**
* 对账单类型
*
* @className BillType
* @author jy
* @date 2014年10月31日
* @since JDK 1.7
* @see
*/
public enum BillType {
/**
* 全部
*/
ALL(0),
/**
* 成功订单
*/
SUCCESS(1),
/**
* 退款订单
*/
REFUND(2);
private int val;
BillType(int val) {
this.val = val;
}
public int getVal() {
return val;
}
}
@@ -0,0 +1,34 @@
package com.foxinmy.weixin4j.type;
/**
* 代金券状态
*
* @className CouponStatus
* @author jy
* @date 2015年3月27日
* @since JDK 1.7
* @see
*/
public enum CouponStatus {
/**
* 已激活
*/
ACTIVATED(2),
/**
* 已锁定
*/
LOCKED(4),
/**
* 已实扣
*/
USED(8);
private int val;
CouponStatus(int val) {
this.val = val;
}
public int getVal() {
return val;
}
}
@@ -0,0 +1,42 @@
package com.foxinmy.weixin4j.type;
/**
* 代金券批次状态
*
* @className CouponStockStatus
* @author jy
* @date 2015年3月27日
* @since JDK 1.7
* @see
*/
public enum CouponStockStatus {
/**
* 未激活
*/
INACTIVE(1),
/**
* 审批中
*/
APPROVAL_PROCESS(2),
/**
* 已激活
*/
ACTIVATED(4),
/**
* 已作废
*/
SUPERSEDED(8),
/**
* 中止发放
*/
SUSPEND(16);
private int val;
CouponStockStatus(int val) {
this.val = val;
}
public int getVal() {
return val;
}
}
@@ -0,0 +1,30 @@
package com.foxinmy.weixin4j.type;
/**
* 代金券批次类型
*
* @className CouponStockType
* @author jy
* @date 2015年3月27日
* @since JDK 1.7
* @see
*/
public enum CouponStockType {
/**
* 批量型
*/
BATCH(1),
/**
* 触发型
*/
TRIGGER(2);
private int val;
CouponStockType(int val) {
this.val = val;
}
public int getVal() {
return val;
}
}
@@ -0,0 +1,34 @@
package com.foxinmy.weixin4j.type;
/**
* 代金券类型
*
* @className CouponType
* @author jy
* @date 2015年3月27日
* @since JDK 1.7
* @see
*/
public enum CouponType {
/**
* 使用无门槛
*/
NO_THRESHOLD(1),
/**
* 使用有门槛
*/
HAS_THRESHOLD(2),
/**
* 门槛叠加
*/
THRESHOLD_PLUS(3);
private int val;
CouponType(int val) {
this.val = val;
}
public int getVal() {
return val;
}
}
@@ -0,0 +1,23 @@
package com.foxinmy.weixin4j.type;
/**
* 币种
*
* @className CurrencyType
* @author jy
* @date 2014年11月2日
* @since JDK 1.7
* @see
*/
public enum CurrencyType {
CNY("人民币"), HKD("港元"), TWD("台币"), EUR("欧元"), USD("美元"), GBP("英镑"), JPY("日元");
private String desc;
CurrencyType(String desc) {
this.desc = desc;
}
public String getDesc() {
return desc;
}
}
@@ -0,0 +1,53 @@
package com.foxinmy.weixin4j.type;
import java.io.Serializable;
/**
* ID查询
*
* @className IdQuery
* @author jy
* @date 2014年11月1日
* @since JDK 1.7
* @see
*/
public class IdQuery implements Serializable {
private static final long serialVersionUID = -5273675987521807370L;
/**
* id值
*/
private String id;
/**
* id类型
*
* @see com.foxinmy.weixin4j.mp.type.IdType
*/
private IdType type;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public IdType getType() {
return type;
}
public void setType(IdType type) {
this.type = type;
}
public IdQuery(String id, IdType idType) {
this.id = id;
this.type = idType;
}
@Override
public String toString() {
return String.format("%s=%s", type.getName(), id);
}
}
@@ -0,0 +1,38 @@
package com.foxinmy.weixin4j.type;
/**
* ID类型
*
* @className IdType
* @author jy
* @date 2014年11月1日
* @since JDK 1.7
* @see
*/
public enum IdType {
/**
* 微信退款单号
*/
REFUNDID("refund_id"),
/**
* 微信订单号
*/
TRANSACTIONID("transaction_id"),
/**
* 商户订单号
*/
TRADENO("out_trade_no"),
/**
* 商户退款号
*/
REFUNDNO("out_refund_no");
private String name;
IdType(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
@@ -0,0 +1,25 @@
package com.foxinmy.weixin4j.type;
/**
* 企业付款检查收款人姓名的策略
*
* @className MPPaymentCheckType
* @author jy
* @date 2015年4月1日
* @since JDK 1.7
* @see
*/
public enum MPPaymentCheckNameType {
/**
* 不校验真实姓名
*/
NO_CHECK,
/**
* 强校验真实姓名(未实名认证的用户会校验失败,无法转账)
*/
FORCE_CHECK,
/**
* 针对已实名认证的用户才校验真实姓名(未实名认证用户不校验,可以转账成功)
*/
OPTION_CHECK;
}
@@ -0,0 +1,25 @@
package com.foxinmy.weixin4j.type;
/**
* 二维码类型
*
* @className QRType
* @author jy
* @date 2014年11月4日
* @since JDK 1.7
* @see
*/
public enum QRType {
/**
* 临时二维码
*/
QR_SCENE,
/**
* 永久二维码(场景值为数字范围在1-100000之间)
*/
QR_LIMIT_SCENE,
/**
* 永久二维码(场景值为字符串长度在1-64之间)
*/
QR_LIMIT_STR_SCENE;
}
@@ -0,0 +1,25 @@
package com.foxinmy.weixin4j.type;
/**
* 红包发放类型
*
* @className RedpacketSendType
* @author jy
* @date 2015年6月4日
* @since JDK 1.7
* @see
*/
public enum RedpacketSendType {
/**
* 通过API接口发放
*/
API,
/**
* 通过上传文件方式发放
*/
UPLOAD,
/**
* 通过活动方式发放
*/
ACTIVITY;
}
@@ -0,0 +1,32 @@
package com.foxinmy.weixin4j.type;
/**
* 红包状态
* @className RedpacketStatus
* @author jy
* @date 2015年6月4日
* @since JDK 1.7
* @see
*/
public enum RedpacketStatus {
/**
* 发放中
*/
SENDING,
/**
* 已发放待领取
*/
SENT,
/**
* 发放失败
*/
FAILED,
/**
* 已领取
*/
RECEIVED,
/**
* 已退款
*/
REFUND;
}
@@ -0,0 +1,21 @@
package com.foxinmy.weixin4j.type;
/**
* 红包类型
*
* @className RedpacketType
* @author jy
* @date 2015年6月4日
* @since JDK 1.7
* @see
*/
public enum RedpacketType {
/**
* 裂变红包
*/
GROUP,
/**
* 普通红包
*/
NORMAL;
}
@@ -0,0 +1,29 @@
package com.foxinmy.weixin4j.type;
/**
* 退款渠道
*
* @className RefundChannel
* @author jy
* @date 2014年11月6日
* @since JDK 1.7
* @see
*/
public enum RefundChannel {
/**
* 原路退款
*/
ORIGINAL,
/**
* 退回到余额
*/
BALANCE,
/**
* 财付通
*/
TENPAY,
/**
* 银行
*/
BANK;
}
@@ -0,0 +1,34 @@
package com.foxinmy.weixin4j.type;
/**
* 退款状态
*
* @className RefundStatus
* @author jy
* @date 2014年11月2日
* @since JDK 1.7
* @see
*/
public enum RefundStatus {
/**
* 退款成功
*/
SUCCESS,
/**
* 退款失败
*/
FAIL,
/**
* 退款处理中
*/
PROCESSING,
/**
* 未确定,需要商户 原退款单号重新发起
*/
NOTSURE,
/**
* 转入代发,退款到银行发现用户的卡作废或者冻结了,导致原路退款银行卡失败,资金回流到商户的现金帐号,需要商户人工干预,通过线下或者财付通转
* 账的方式进行退款。
*/
CHANGE;
}
@@ -0,0 +1,35 @@
package com.foxinmy.weixin4j.type;
/**
* 退款类型
*
* @className RefundType
* @author jy
* @date 2014年12月31日
* @since JDK 1.7
* @see
*/
public enum RefundType {
/**
* 1:商户号余额退款;
*/
BALANCE(1),
/**
* 2:现金帐号 退款;
*/
CASH(2),
/**
* 3:优先商户号退款,若商户号余额不足, 再做现金帐号退款。 使用 2 或 3 时,需联系财 付通开通此功能
*/
BOTH(3);
private int val;
RefundType(int val) {
this.val = val;
}
public int getVal() {
return val;
}
}
@@ -0,0 +1,13 @@
package com.foxinmy.weixin4j.type;
/**
* 签名类型
* @className SignType
* @author jy
* @date 2014年11月5日
* @since JDK 1.7
* @see
*/
public enum SignType {
SHA1,MD5
}
@@ -0,0 +1,45 @@
package com.foxinmy.weixin4j.type;
/**
* 交易状态
*
* @className TradeState
* @author jy
* @date 2014年11月2日
* @since JDK 1.7
* @see
*/
public enum TradeState {
/**
* 支付成功
*/
SUCCESS,
/**
* 转入退款
*/
REFUND,
/**
* 未支付
*/
NOTPAY,
/**
* 已关闭
*/
CLOSED,
/**
* 已撤销
*/
REVOKED,
/**
* 用户支付中
*/
USERPAYING,
/**
* 未支付(输入密码或 确认支付超时)
*/
NOPAY,
/**
* 支付失败(其他 原因,如银行返回失败)
*/
PAYERROR;
}
@@ -0,0 +1,29 @@
package com.foxinmy.weixin4j.type;
/**
* 微信支付类型
*
* @className TradeType
* @author jy
* @date 2014年10月21日
* @since JDK 1.7
* @see
*/
public enum TradeType {
/**
* H5页面上的JSAPI支付
*/
JSAPI,
/**
* 刷卡支付
*/
MICROPAY,
/**
* 扫描支付
*/
NATIVE,
/**
* APP支付
*/
APP;
}