weixin4j-mp:新增查询红包接口

This commit is contained in:
jinyu 2015-06-04 20:44:46 +08:00
parent daafd450a0
commit 24a16d6141
14 changed files with 490 additions and 11 deletions

View File

@ -310,3 +310,7 @@
* 2015-06-03
+ **去掉xstream依赖**
* 2015-06-04
+ **weixin4j-mp**: 新增查询红包接口

View File

@ -109,3 +109,7 @@
+ <font color="red">调整[客服接口](./src/main/java/com/foxinmy/weixin4j/mp/api/CustomApi.java)类的方法名</font>
+ <font color="red">在[二维码接口](./src/main/java/com/foxinmy/weixin4j/mp/api/QRApi.java)类新增获取二维码url方法</font>
* 2015-06-04
+ 新增查询红包接口

View File

@ -20,6 +20,7 @@ import com.foxinmy.weixin4j.mp.payment.v3.ApiResult;
import com.foxinmy.weixin4j.mp.payment.v3.MPPayment;
import com.foxinmy.weixin4j.mp.payment.v3.MPPaymentResult;
import com.foxinmy.weixin4j.mp.payment.v3.Redpacket;
import com.foxinmy.weixin4j.mp.payment.v3.RedpacketRecord;
import com.foxinmy.weixin4j.mp.payment.v3.RedpacketSendResult;
import com.foxinmy.weixin4j.mp.token.WeixinTokenCreator;
import com.foxinmy.weixin4j.mp.type.BillType;
@ -591,6 +592,36 @@ public class WeixinPayProxy {
return cashApi.sendRedpack(caFile, redpacket);
}
/**
* 查询红包记录
*
* @param caFile
* 证书文件(V3版本后缀为*.p12)
* @param outTradeNo
* 商户发放红包的商户订单号
* @return 红包记录
* @see com.foxinmy.weixin4j.mp.api.CashApi
* @see com.foxinmy.weixin4j.mp.payment.v3.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.mp.WeixinPayProxy#queryRedpack(File,String)}
*/
public RedpacketRecord queryRedpack(String outTradeNo)
throws WeixinException {
File caFile = new File(ConfigUtil.getClassPathValue("ca_file"));
return cashApi.queryRedpack(caFile, outTradeNo);
}
/**
* 企业付款 实现企业向个人付款针对部分有开发能力的商户 提供通过API完成企业付款的功能 比如目前的保险行业向客户退保给付理赔
*

View File

@ -4,6 +4,8 @@ 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;
@ -16,6 +18,7 @@ import com.foxinmy.weixin4j.mp.payment.PayUtil;
import com.foxinmy.weixin4j.mp.payment.v3.MPPayment;
import com.foxinmy.weixin4j.mp.payment.v3.MPPaymentResult;
import com.foxinmy.weixin4j.mp.payment.v3.Redpacket;
import com.foxinmy.weixin4j.mp.payment.v3.RedpacketRecord;
import com.foxinmy.weixin4j.mp.payment.v3.RedpacketSendResult;
import com.foxinmy.weixin4j.util.RandomUtil;
import com.foxinmy.weixin4j.xml.XmlStream;
@ -51,7 +54,7 @@ public class CashApi extends MpApi {
* @see com.foxinmy.weixin4j.mp.payment.v3.Redpacket
* @see com.foxinmy.weixin4j.mp.payment.v3.RedpacketSendResult
* @see <a
* href="http://pay.weixin.qq.com/wiki/doc/api/cash_coupon.php?chapter=13_5">红包接口说明</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)
@ -74,7 +77,7 @@ public class CashApi extends MpApi {
response = request.post(redpack_send_uri, param);
} catch (WeixinException e) {
throw e;
} catch (Exception e) {
} catch (IOException e) {
throw new WeixinException(e.getMessage());
} finally {
if (ca != null) {
@ -89,6 +92,55 @@ public class CashApi extends MpApi {
});
}
/**
* 查询红包记录
*
* @param caFile
* 证书文件(V3版本后缀为*.p12)
* @param outTradeNo
* 商户发放红包的商户订单号
* @return 红包记录
* @see com.foxinmy.weixin4j.mp.payment.v3.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);
String redpack_query_uri = getRequestUri("redpack_query_uri");
WeixinResponse response = null;
InputStream ca = null;
try {
ca = new FileInputStream(caFile);
SSLHttpClinet request = new SSLHttpClinet(weixinAccount.getMchId(),
ca);
response = request.post(redpack_query_uri, 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完成企业付款的功能 比如目前的保险行业向客户退保给付理赔
*
@ -124,7 +176,7 @@ public class CashApi extends MpApi {
response = request.post(mp_payment_uri, param);
} catch (WeixinException e) {
throw e;
} catch (Exception e) {
} catch (IOException e) {
throw new WeixinException(e.getMessage());
} finally {
if (ca != null) {

View File

@ -85,7 +85,7 @@ public class CouponApi extends MpApi {
response = request.post(coupon_send_uri, param);
} catch (WeixinException e) {
throw e;
} catch (Exception e) {
} catch (IOException e) {
throw new WeixinException(e.getMessage());
} finally {
if (ca != null) {

View File

@ -146,7 +146,7 @@ public class Pay3Api extends PayApi {
response = request.post(refund_uri, param);
} catch (WeixinException e) {
throw e;
} catch (Exception e) {
} catch (IOException e) {
throw new WeixinException(e.getMessage());
} finally {
if (ca != null) {

View File

@ -175,7 +175,9 @@ coupon_send_uri={mch_base_url}/mmpaymkttransfers/send_coupon
couponstock_query_uri={mch_base_url}/mmpaymkttransfers/query_coupon_stock
# \u67e5\u8be2\u4ee3\u91d1\u5238\u8be6\u7ec6\u4fe1\u606f
coupondetail_query_uri={mch_base_url}/promotion/query_coupon
# \u53d1\u653e\u73b0\u91d1\u7ea2\u5305
# \u53d1\u9001\u73b0\u91d1\u7ea2\u5305
redpack_send_uri={mch_base_url}/mmpaymkttransfers/sendredpack
# \u67e5\u8be2\u73b0\u91d1\u7ea2\u5305
redpack_query_uri={mch_base_url}/mmpaymkttransfers/gethbinfo
# \u4f01\u4e1a\u5411\u4e2a\u4eba\u4ed8\u6b3e
mp_payment_uri={mch_base_url}/mmpaymkttransfers/promotion/transfers

View File

@ -0,0 +1,299 @@
package com.foxinmy.weixin4j.mp.payment.v3;
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.mp.type.RedpacketSendType;
import com.foxinmy.weixin4j.mp.type.RedpacketStatus;
import com.foxinmy.weixin4j.mp.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;
/**
* 红包状态
*/
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;
/**
* 发送失败原因
*/
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;
/**
* 祝福语
*/
private String wishing;
/**
* 活动描述
*/
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
*/
private String openid;
/**
* 领取状态
*/
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 + "]";
}
}

View File

@ -0,0 +1,25 @@
package com.foxinmy.weixin4j.mp.type;
/**
* 红包发放类型
*
* @className RedpacketSendType
* @author jy
* @date 2015年6月4日
* @since JDK 1.7
* @see
*/
public enum RedpacketSendType {
/**
* 通过API接口发放
*/
API,
/**
* 通过上传文件方式发放
*/
UPLOAD,
/**
* 通过活动方式发放
*/
ACTIVITY;
}

View File

@ -0,0 +1,32 @@
package com.foxinmy.weixin4j.mp.type;
/**
* 红包状态
* @className RedpacketStatus
* @author jy
* @date 2015年6月4日
* @since JDK 1.7
* @see
*/
public enum RedpacketStatus {
/**
* 发放中
*/
SENDING,
/**
* 已发放待领取
*/
SENT,
/**
* 发放失败
*/
FAILED,
/**
* 已领取
*/
RECEIVED,
/**
* 已退款
*/
REFUND;
}

View File

@ -0,0 +1,21 @@
package com.foxinmy.weixin4j.mp.type;
/**
* 红包类型
*
* @className RedpacketType
* @author jy
* @date 2015年6月4日
* @since JDK 1.7
* @see
*/
public enum RedpacketType {
/**
* 裂变红包
*/
GROUP,
/**
* 普通红包
*/
NORMAL;
}

View File

@ -6,6 +6,7 @@ import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.mp.payment.v3.MPPayment;
import com.foxinmy.weixin4j.mp.payment.v3.MPPaymentResult;
import com.foxinmy.weixin4j.mp.payment.v3.Redpacket;
import com.foxinmy.weixin4j.mp.payment.v3.RedpacketRecord;
import com.foxinmy.weixin4j.mp.payment.v3.RedpacketSendResult;
import com.foxinmy.weixin4j.mp.type.MPPaymentCheckNameType;
@ -35,6 +36,13 @@ public class CashTest extends CouponTest {
System.err.println(result);
}
@Test
public void queryRedpacket() throws WeixinException {
String outTradeNo = "HB001";
RedpacketRecord record = WEIXINPAY.queryRedpack(caFile, outTradeNo);
System.err.println(record);
}
@Test
public void mpPayment() throws WeixinException {
MPPayment payment = new MPPayment("MP001",

View File

@ -32,7 +32,7 @@ public class CouponTest {
static {
ACCOUNT = new WeixinMpAccount("appid",
"appsecret",
"paysing", "mchid");
"paysign", "mchid");
WEIXINPAY = new WeixinPayProxy(ACCOUNT, new FileTokenHolder(
new WeixinTokenCreator(ACCOUNT.getId(), ACCOUNT.getSecret())));
}

View File

@ -95,13 +95,14 @@ public class XmlstreamTest {
}
System.err.println(ListsuffixResultConverter
.containRefundDetailConvert(sb.toString(), com.foxinmy.weixin4j.mp.payment.v3.RefundRecord.class));
.containRefundDetailConvert(sb.toString(),
com.foxinmy.weixin4j.mp.payment.v3.RefundRecord.class));
}
public static void main(String[] args) throws Exception {
// map2xml();
// xml2map();
xml2order();
// xml2order();
// xml2refundRecordV2();
// xml2refundRecordV3();
// object2xmlWithoutRootElement();