This commit is contained in:
jinyu 2016-05-24 10:23:53 +08:00
parent 816a4ec0ef
commit 866b37c54b
13 changed files with 292 additions and 226 deletions

View File

@ -27,7 +27,7 @@ import com.foxinmy.weixin4j.xml.XmlStream;
/**
* 现金API
*
*
* @className CashApi
* @author jinyu(foxinmy@gmail.com)
* @date 2015年3月28日
@ -47,7 +47,7 @@ public class CashApi extends MchApi {
/**
* 发放红包 企业向微信用户个人发现金红包
*
*
* @param certificate
* 后缀为*.p12的证书文件
* @param redpacket
@ -63,7 +63,8 @@ public class CashApi extends MchApi {
* 发放裂变红包接口</a>
* @throws WeixinException
*/
public RedpacketSendResult sendRedpack(InputStream certificate, Redpacket redpacket) throws WeixinException {
public RedpacketSendResult sendRedpack(InputStream certificate,
Redpacket redpacket) throws WeixinException {
redpacket.declareWeixinPayAccount(weixinAccount);
JSONObject obj = (JSONObject) JSON.toJSON(redpacket);
obj.put("wxappid", obj.remove("appid"));
@ -71,8 +72,9 @@ public class CashApi extends MchApi {
String param = XmlStream.map2xml(obj);
WeixinResponse response = null;
try {
response = createSSLRequestExecutor(certificate).post(redpacket.getTotalNum() > 1
? getRequestUri("groupredpack_send_uri") : getRequestUri("redpack_send_uri"), param);
response = createSSLRequestExecutor(certificate)
.post(redpacket.getTotalNum() > 1 ? getRequestUri("groupredpack_send_uri")
: getRequestUri("redpack_send_uri"), param);
} finally {
if (certificate != null) {
try {
@ -82,14 +84,15 @@ public class CashApi extends MchApi {
}
}
}
String text = response.getAsString().replaceFirst("<wxappid>", "<appid>").replaceFirst("</wxappid>",
"</appid>");
String text = response.getAsString()
.replaceFirst("<wxappid>", "<appid>")
.replaceFirst("</wxappid>", "</appid>");
return XmlStream.fromXML(text, RedpacketSendResult.class);
}
/**
* 查询红包记录
*
*
* @param certificate
* 后缀为*.p12的证书文件
* @param outTradeNo
@ -104,7 +107,8 @@ public class CashApi extends MchApi {
* 查询裂变红包接口</a>
* @throws WeixinException
*/
public RedpacketRecord queryRedpack(InputStream certificate, String outTradeNo) throws WeixinException {
public RedpacketRecord queryRedpack(InputStream certificate,
String outTradeNo) throws WeixinException {
Map<String, String> para = createBaseRequestMap(null);
para.put("bill_type", "MCHT");
para.put("mch_billno", outTradeNo);
@ -112,7 +116,8 @@ public class CashApi extends MchApi {
String param = XmlStream.map2xml(para);
WeixinResponse response = null;
try {
response = createSSLRequestExecutor(certificate).post(getRequestUri("redpack_query_uri"), param);
response = createSSLRequestExecutor(certificate).post(
getRequestUri("redpack_query_uri"), param);
} finally {
if (certificate != null) {
try {
@ -128,7 +133,16 @@ public class CashApi extends MchApi {
/**
* 企业付款 实现企业向个人付款针对部分有开发能力的商户 提供通过API完成企业付款的功能 比如目前的保险行业向客户退保给付理赔
*
* <p>
* 接口调用规则
* <p>
* <li>给同一个实名用户付款单笔单日限额2W/2W
* <li>给同一个非实名用户付款单笔单日限额2000/2000
* <li>一个商户同一日付款总额限额100W
* <li>单笔最小金额默认为1元
* <li>每个用户每天最多可付款10次可以在商户平台--API安全进行设置
* <li>给同一个用户付款时间间隔不得低于15秒
*
* @param certificate
* 后缀为*.p12的证书文件
* @param payment
@ -141,7 +155,8 @@ public class CashApi extends MchApi {
* 企业付款接口</a>
* @throws WeixinException
*/
public CorpPaymentResult sendCorpPayment(InputStream certificate, CorpPayment payment) throws WeixinException {
public CorpPaymentResult sendCorpPayment(InputStream certificate,
CorpPayment payment) throws WeixinException {
payment.declareWeixinPayAccount(weixinAccount);
JSONObject obj = (JSONObject) JSON.toJSON(payment);
obj.put("mchid", obj.remove("mch_id"));
@ -150,7 +165,8 @@ public class CashApi extends MchApi {
String param = XmlStream.map2xml(obj);
WeixinResponse response = null;
try {
response = createSSLRequestExecutor(certificate).post(getRequestUri("corppayment_send_uri"), param);
response = createSSLRequestExecutor(certificate).post(
getRequestUri("corppayment_send_uri"), param);
} finally {
if (certificate != null) {
try {
@ -160,15 +176,17 @@ public class CashApi extends MchApi {
}
}
}
String text = response.getAsString().replaceFirst("<mch_appid>", "<appid>")
.replaceFirst("</mch_appid>", "</appid>").replaceFirst("<mchid>", "<mch_id>")
String text = response.getAsString()
.replaceFirst("<mch_appid>", "<appid>")
.replaceFirst("</mch_appid>", "</appid>")
.replaceFirst("<mchid>", "<mch_id>")
.replaceFirst("</mchid>", "</mch_id>");
return XmlStream.fromXML(text, CorpPaymentResult.class);
}
/**
* 企业付款查询 用于商户的企业付款操作进行结果查询返回付款操作详细结果
*
*
* @param certificate
* 后缀为*.p12的证书文件
* @param outTradeNo
@ -180,7 +198,8 @@ public class CashApi extends MchApi {
* 企业付款查询接口</a>
* @throws WeixinException
*/
public CorpPaymentRecord queryCorpPayment(InputStream certificate, String outTradeNo) throws WeixinException {
public CorpPaymentRecord queryCorpPayment(InputStream certificate,
String outTradeNo) throws WeixinException {
JSONObject obj = new JSONObject();
obj.put("nonce_str", RandomUtil.generateString(16));
obj.put("mch_id", weixinAccount.getMchId());
@ -190,7 +209,8 @@ public class CashApi extends MchApi {
String param = XmlStream.map2xml(obj);
WeixinResponse response = null;
try {
response = createSSLRequestExecutor(certificate).post(getRequestUri("corppayment_query_uri"), param);
response = createSSLRequestExecutor(certificate).post(
getRequestUri("corppayment_query_uri"), param);
} finally {
if (certificate != null) {
try {
@ -206,7 +226,7 @@ public class CashApi extends MchApi {
/**
* 查询结算资金
*
*
* @param status
* 是否结算
* @param pageable
@ -222,8 +242,8 @@ public class CashApi extends MchApi {
* "https://pay.weixin.qq.com/wiki/doc/api/external/micropay.php?chapter=9_14&index=7">
* 查询结算资金接口</a>
*/
public SettlementRecord querySettlement(boolean status, Pageable pageable, Date start, Date end)
throws WeixinException {
public SettlementRecord querySettlement(boolean status, Pageable pageable,
Date start, Date end) throws WeixinException {
JSONObject obj = new JSONObject();
obj.put("nonce_str", RandomUtil.generateString(16));
obj.put("mch_id", weixinAccount.getMchId());
@ -239,14 +259,15 @@ public class CashApi extends MchApi {
}
obj.put("sign", weixinSignature.sign(obj));
String param = XmlStream.map2xml(obj);
WeixinResponse response = weixinExecutor.post(getRequestUri("settlement_query_uri"), param);
WeixinResponse response = weixinExecutor.post(
getRequestUri("settlement_query_uri"), param);
return response.getAsObject(new TypeReference<SettlementRecord>() {
});
}
/**
* 查询汇率
*
*
* @param currencyType
* 外币币种
* @param date
@ -257,7 +278,8 @@ public class CashApi extends MchApi {
* "https://pay.weixin.qq.com/wiki/doc/api/external/micropay.php?chapter=9_15&index=8">
* 查询汇率接口</a>
*/
public double queryExchageRate(CurrencyType currencyType, Date date) throws WeixinException {
public double queryExchageRate(CurrencyType currencyType, Date date)
throws WeixinException {
if (date == null) {
date = new Date();
}
@ -269,8 +291,10 @@ public class CashApi extends MchApi {
obj.put("date", DateUtil.fortmat2yyyyMMdd(date));
obj.put("sign", weixinSignature.sign(obj));
String param = XmlStream.map2xml(obj);
WeixinResponse response = weixinExecutor.post(getRequestUri("exchagerate_query_uri"), param);
BigDecimal rate = new BigDecimal(XmlStream.xml2map(response.getAsString()).get("rate"));
WeixinResponse response = weixinExecutor.post(
getRequestUri("exchagerate_query_uri"), param);
BigDecimal rate = new BigDecimal(XmlStream.xml2map(
response.getAsString()).get("rate"));
return rate.divide(new BigDecimal(100000000d)).doubleValue();
}
}

View File

@ -16,11 +16,11 @@ import com.foxinmy.weixin4j.xml.XmlStream;
/**
* 报关接口
*
*
* @className CustomsApi
* @author jinyu(foxinmy@gmail.com)
* @date 2016年3月67日
* @since JDK 1.7
* @since JDK 1.6
* @see
*/
public class CustomsApi extends MchApi {
@ -31,7 +31,7 @@ public class CustomsApi extends MchApi {
/**
* 订单附加信息提交
*
*
* @param customsOrder
* 附加订单信息
* @return 报关结果
@ -56,7 +56,7 @@ public class CustomsApi extends MchApi {
/**
* 订单附加信息查询
*
*
* @param idQuery
* out_trade_no,transaction_id,sub_order_no,sub_order_id四选一
* @param customsCity

View File

@ -37,12 +37,13 @@ import com.foxinmy.weixin4j.http.HttpParams;
import com.foxinmy.weixin4j.http.HttpRequest;
import com.foxinmy.weixin4j.http.HttpResponse;
import com.foxinmy.weixin4j.http.entity.HttpEntity;
import com.foxinmy.weixin4j.model.Consts;
import com.foxinmy.weixin4j.util.SettableFuture;
import com.foxinmy.weixin4j.util.StringUtil;
/**
* Netty 4.x
*
*
* @className Netty4HttpClient
* @author jinyu(foxinmy@gmail.com)
* @date 2015年8月30日
@ -183,11 +184,11 @@ public class Netty4HttpClient extends AbstractHttpClient {
if (!headers.containsKey(HttpHeaders.USER_AGENT)) {
headers.set(HttpHeaders.USER_AGENT, "netty/httpclient");
}
for (Entry<String, List<String>> header : headers
.entrySet()) {
for (Entry<String, List<String>> header : headers.entrySet()) {
uriRequest.headers().set(header.getKey(), header.getValue());
}
uriRequest.headers().set(HttpHeaders.ACCEPT_CHARSET, "utf-8");
uriRequest.headers().set(HttpHeaders.ACCEPT_CHARSET,
Consts.UTF_8.displayName());
uriRequest.headers().set(HttpHeaders.CONNECTION,
io.netty.handler.codec.http.HttpHeaders.Values.CLOSE);
return uriRequest;

View File

@ -12,8 +12,8 @@ import com.foxinmy.weixin4j.http.HttpStatus;
import com.foxinmy.weixin4j.http.HttpVersion;
/**
* Netty Respone::Requires Netty 4.x or higher
*
* Netty Response::Requires Netty 4.x or higher
*
* @className Netty4HttpResponse
* @author jinyu(foxinmy@gmail.com)
* @date 2015年8月30日

View File

@ -19,7 +19,6 @@ import com.foxinmy.weixin4j.type.ButtonType;
* @author jinyu(foxinmy@gmail.com)
* @date 2014年4月5日
* @since JDK 1.6
* @see com.foxinmy.weixin4j.type.ButtonType
*/
public class Button implements Serializable {
@ -37,18 +36,13 @@ public class Button implements Serializable {
*/
private ButtonType type;
/**
* 菜单KEY值,根据type的类型而定,用于消息接口推送,不超过128字节.
* <p>
* 官网上设置的自定义菜单</br> Text:保存文字到value Imgvoice保存mediaID到value
* Video保存视频下载链接到value</br> News保存图文消息到news_info View保存链接到url</br>
* <p>
* 使用API设置的自定义菜单</br>
* clickscancode_pushscancode_waitmsgpic_sysphotopic_photo_or_album
* </br>
* pic_weixinlocation_select保存为keyview保存为url;media_idview_limited
* 保存为media_id
* </p>
* </p>
* 菜单KEY值,根据type的类型而定</p> 通过公众平台设置的自定义菜单</br> <li>text:保存文字 <li>
* imgvoice保存媒体ID <li>video保存视频URL <li>
* news保存图文消息:List#com.foxinmy.weixin4j.tuple.MpArticle# <li>view保存链接URL
* <p>使用API设置的自定义菜单</p> <li>
* clickscancode_pushscancode_waitmsgpic_sysphotopic_photo_or_album
* pic_weixinlocation_select保存key <li>view保存链接URL; <li>
* media_idview_limited保存媒体ID
*/
private Serializable content;
/**

View File

@ -45,7 +45,7 @@ import com.foxinmy.weixin4j.util.Weixin4jSettings;
/**
* 微信支付接口实现
*
*
* @className WeixinPayProxy
* @author jinyu(foxinmy@gmail.com)
* @date 2015年1月3日
@ -98,7 +98,7 @@ public class WeixinPayProxy {
/**
* 获取微信商户支付信息
*
*
* @return
*/
public WeixinPayAccount getPayAccount() {
@ -109,7 +109,7 @@ public class WeixinPayProxy {
* 统一下单接口</br>
* 除被扫支付场景以外商户系统先调用该接口在微信支付服务后台生成预支付交易单返回正确的预支付交易回话标识后再按扫码JSAPI
* APP等不同场景生成交易串调起支付
*
*
* @param payPackage
* 包含订单信息的对象
* @see com.foxinmy.weixin4j.api.PayApi
@ -126,7 +126,7 @@ public class WeixinPayProxy {
/**
* 创建支付请求对象
*
*
* @param payPackage
* 支付详情
* @return 支付请求对象
@ -138,13 +138,14 @@ public class WeixinPayProxy {
* @see com.foxinmy.weixin4j.payment.mch.WAPPayRequest WAP支付
* @throws WeixinException
*/
public MchPayRequest createPayRequest(MchPayPackage payPackage) throws WeixinException {
public MchPayRequest createPayRequest(MchPayPackage payPackage)
throws WeixinException {
return payApi.createPayRequest(payPackage);
}
/**
* 创建支付请求对象完整参数
*
*
* @param body
* 商品描述 <font color="red">必填项</font>
* @param detail
@ -184,17 +185,20 @@ public class WeixinPayProxy {
* @see com.foxinmy.weixin4j.payment.mch.WAPPayRequest WAP支付
* @throws WeixinException
*/
public MchPayRequest createPayRequest(String body, String detail, String outTradeNo, double totalFee,
String notifyUrl, String createIp, TradeType tradeType, String openId, String productId, String attach,
Date timeStart, Date timeExpire, String goodsTag, String limitPay, String subOpenId)
public MchPayRequest createPayRequest(String body, String detail,
String outTradeNo, double totalFee, String notifyUrl,
String createIp, TradeType tradeType, String openId,
String productId, String attach, Date timeStart, Date timeExpire,
String goodsTag, String limitPay, String subOpenId)
throws WeixinException {
return payApi.createPayRequest(body, detail, outTradeNo, totalFee, notifyUrl, createIp, tradeType, openId,
productId, attach, timeStart, timeExpire, goodsTag, limitPay, subOpenId);
return payApi.createPayRequest(body, detail, outTradeNo, totalFee,
notifyUrl, createIp, tradeType, openId, productId, attach,
timeStart, timeExpire, goodsTag, limitPay, subOpenId);
}
/**
* 创建JSAPI支付请求对象
*
*
* @param openId
* 用户ID
* @param body
@ -214,27 +218,24 @@ public class WeixinPayProxy {
* @return JSAPI支付对象
* @throws WeixinException
*/
public MchPayRequest createJSPayRequest(String openId, String body, String outTradeNo, double totalFee,
String notifyUrl, String createIp, String attach) throws WeixinException {
return payApi.createJSPayRequest(openId, body, outTradeNo, totalFee, notifyUrl, createIp, attach);
public MchPayRequest createJSPayRequest(String openId, String body,
String outTradeNo, double totalFee, String notifyUrl,
String createIp, String attach) throws WeixinException {
return payApi.createJSPayRequest(openId, body, outTradeNo, totalFee,
notifyUrl, createIp, attach);
}
/**
* <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>
*
*
* 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 url
* 当前访问页的URL
* @param oauthToken
@ -251,7 +252,7 @@ public class WeixinPayProxy {
/**
* 创建Native支付(扫码支付)链接模式一
*
*
* @param productId
* 与订单ID等价
* @return 支付链接
@ -269,7 +270,7 @@ public class WeixinPayProxy {
/**
* 创建Native支付(扫码支付)回调对象模式一
*
*
* @param productId
* 商品ID
* @param body
@ -295,14 +296,16 @@ public class WeixinPayProxy {
* </a>
* @throws WeixinException
*/
public NativePayResponse createNativePayResponse(String productId, String body, String outTradeNo, double totalFee,
String notifyUrl, String createIp, String attach) throws WeixinException {
return payApi.createNativePayResponse(productId, body, outTradeNo, totalFee, notifyUrl, createIp, attach);
public NativePayResponse createNativePayResponse(String productId,
String body, String outTradeNo, double totalFee, String notifyUrl,
String createIp, String attach) throws WeixinException {
return payApi.createNativePayResponse(productId, body, outTradeNo,
totalFee, notifyUrl, createIp, attach);
}
/**
* 创建Native支付(扫码支付)链接模式二
*
*
* @param productId
* 商品ID
* @param body
@ -328,14 +331,16 @@ public class WeixinPayProxy {
* </a>
* @throws WeixinException
*/
public MchPayRequest createNativePayRequest(String productId, String body, String outTradeNo, double totalFee,
String notifyUrl, String createIp, String attach) throws WeixinException {
return payApi.createNativePayRequest(productId, body, outTradeNo, totalFee, notifyUrl, createIp, attach);
public MchPayRequest createNativePayRequest(String productId, String body,
String outTradeNo, double totalFee, String notifyUrl,
String createIp, String attach) throws WeixinException {
return payApi.createNativePayRequest(productId, body, outTradeNo,
totalFee, notifyUrl, createIp, attach);
}
/**
* 创建APP支付请求对象
*
*
* @param body
* 商品描述
* @param outTradeNo
@ -356,14 +361,16 @@ public class WeixinPayProxy {
* APP支付</a>
* @throws WeixinException
*/
public MchPayRequest createAppPayRequest(String body, String outTradeNo, double totalFee, String notifyUrl,
String createIp, String attach) throws WeixinException {
return payApi.createAppPayRequest(body, outTradeNo, totalFee, notifyUrl, createIp, attach);
public MchPayRequest createAppPayRequest(String body, String outTradeNo,
double totalFee, String notifyUrl, String createIp, String attach)
throws WeixinException {
return payApi.createAppPayRequest(body, outTradeNo, totalFee,
notifyUrl, createIp, attach);
}
/**
* 创建WAP支付请求对象
*
*
* @param body
* 商品描述
* @param outTradeNo
@ -384,14 +391,16 @@ public class WeixinPayProxy {
* </a>
* @throws WeixinException
*/
public MchPayRequest createWAPPayRequest(String body, String outTradeNo, double totalFee, String notifyUrl,
String createIp, String attach) throws WeixinException {
return payApi.createWAPPayRequest(body, outTradeNo, totalFee, notifyUrl, createIp, attach);
public MchPayRequest createWAPPayRequest(String body, String outTradeNo,
double totalFee, String notifyUrl, String createIp, String attach)
throws WeixinException {
return payApi.createWAPPayRequest(body, outTradeNo, totalFee,
notifyUrl, createIp, attach);
}
/**
* 提交被扫支付
*
*
* @param authCode
* 扫码支付授权码 ,设备读取用户微信中的条码或者二维码信息
* @param body
@ -413,20 +422,20 @@ public class WeixinPayProxy {
* 提交被扫支付API</a>
* @throws WeixinException
*/
public MchPayRequest createMICROPayRequest(String authCode, String body, String outTradeNo, double totalFee,
String createIp, String attach) throws WeixinException {
return payApi.createMICROPayRequest(authCode, body, outTradeNo, totalFee, createIp, attach);
public MchPayRequest createMICROPayRequest(String authCode, String body,
String outTradeNo, double totalFee, String createIp, String attach)
throws WeixinException {
return payApi.createMICROPayRequest(authCode, body, outTradeNo,
totalFee, createIp, attach);
}
/**
* 订单查询
* <p>
* 当商户后台网络服务器等出现异常商户系统最终未接收到支付通知</br>
* 调用支付接口后返回系统错误或未知交易状态情况</br>
* 调用被扫支付API返回USERPAYING的状态</br>
* 调用关单或撤销接口API之前需确认支付状态
* 当商户后台网络服务器等出现异常商户系统最终未接收到支付通知</br> 调用支付接口后返回系统错误或未知交易状态情况</br>
* 调用被扫支付API返回USERPAYING的状态</br> 调用关单或撤销接口API之前需确认支付状态
* </P>
*
*
* @param idQuery
* 商户系统内部的订单号, transaction_idout_trade_no 选一,如果同时存在优先级:
* transaction_id> out_trade_no
@ -454,7 +463,7 @@ public class WeixinPayProxy {
* 2.微信支付退款支持单笔交易分多次退款多次退款需要提交原支付订单的商户订单号和设置不同的退款单号一笔退款失败后重新提交
* 要采用原来的退款单号总退款金额不能超过用户实际支付金额
* </p>
*
*
* @param certificate
* 后缀为*.p12的证书文件
* @param idQuery
@ -470,7 +479,7 @@ public class WeixinPayProxy {
* 货币类型符合ISO 4217标准的三位字母代码默认人民币CNY
* @param opUserId
* 操作员帐号, 默认为商户号
*
*
* @return 退款申请结果
* @see com.foxinmy.weixin4j.payment.mch.RefundResult
* @see com.foxinmy.weixin4j.api.PayApi
@ -480,21 +489,25 @@ public class WeixinPayProxy {
* @since V3
* @throws WeixinException
*/
public RefundResult applyRefund(InputStream certificate, IdQuery idQuery, String outRefundNo, double totalFee,
double refundFee, CurrencyType refundFeeType, String opUserId) throws WeixinException {
return payApi.applyRefund(certificate, idQuery, outRefundNo, totalFee, refundFee, refundFeeType, opUserId);
public RefundResult applyRefund(InputStream certificate, IdQuery idQuery,
String outRefundNo, double totalFee, double refundFee,
CurrencyType refundFeeType, String opUserId) throws WeixinException {
return payApi.applyRefund(certificate, idQuery, outRefundNo, totalFee,
refundFee, refundFeeType, opUserId);
}
/**
* 退款申请(全额退款)
*
*
* @throws IOException
*
*
* @see {@link #applyRefund(InputStream, IdQuery, String, double, double, String,CurrencyType)}
*/
public RefundResult applyRefund(IdQuery idQuery, String outRefundNo, double totalFee)
throws WeixinException, IOException {
return payApi.applyRefund(new FileInputStream(settings.getCertificateFile0()), idQuery, outRefundNo, totalFee);
public RefundResult applyRefund(IdQuery idQuery, String outRefundNo,
double totalFee) throws WeixinException, IOException {
return payApi.applyRefund(
new FileInputStream(settings.getCertificateFile0()), idQuery,
outRefundNo, totalFee);
}
/**
@ -502,7 +515,7 @@ public class WeixinPayProxy {
* <p>
* 提交退款申请后通过调用该接口查询退款状态退款有一定延时用零钱支付的退款20分钟内到账银行卡支付的退款3个工作日后重新查询退款状态
* </p>
*
*
* @param idQuery
* 单号 refund_idout_refund_no out_trade_no transaction_id
* 四个参数必填一个,优先级为:
@ -526,7 +539,7 @@ public class WeixinPayProxy {
* REVOKED;<br>
* 2.微信在次日 9 点启动生成前一天的对账单,建议商户 9 点半后再获取;<br>
* 3.对账单中涉及金额的字段单位为<br>
*
*
* @param billDate
* 下载对账单的日期
* @param billType
@ -540,18 +553,17 @@ public class WeixinPayProxy {
* 下载对账单API</a>
* @throws WeixinException
*/
public File downloadBill(Date billDate, BillType billType) throws WeixinException {
public File downloadBill(Date billDate, BillType billType)
throws WeixinException {
return payApi.downloadBill(billDate, billType, settings.getTmpdir0());
}
/**
* 冲正订单(需要证书)</br>
* 当支付返回失败,或收银系统超时需要取消交易,可以调用该接口</br>
* 接口逻辑: 付失败的关单,支付成功的撤销支付</br>
* <font color="red">7天以内的单可撤销,其他正常支付的单 如需实现相同功能请调用退款接口</font></br>
* <font color="red">调用扣款接口后请勿立即调用撤销,需要等待5秒以上先调用查单接口,如果没有确切的返回,再调用撤销</font>
* </br>
*
* 冲正订单(需要证书)</br> 当支付返回失败,或收银系统超时需要取消交易,可以调用该接口</br> 接口逻辑:
* 付失败的关单,支付成功的撤销支付</br> <font color="red">7天以内的单可撤销,其他正常支付的单
* 如需实现相同功能请调用退款接口</font></br> <font
* color="red">调用扣款接口后请勿立即调用撤销,需要等待5秒以上先调用查单接口,如果没有确切的返回,再调用撤销</font> </br>
*
* @param certificate
* 证书文件(V2版本后缀为*.pfx,V3版本后缀为*.p12)
* @param idQuery
@ -562,13 +574,14 @@ public class WeixinPayProxy {
* @since V3
* @throws WeixinException
*/
public MerchantResult reverseOrder(InputStream certificate, IdQuery idQuery) throws WeixinException {
public MerchantResult reverseOrder(InputStream certificate, IdQuery idQuery)
throws WeixinException {
return payApi.reverseOrder(certificate, idQuery);
}
/**
* 冲正撤销
*
*
* @param idQuery
* transaction_idout_trade_no 二选一
* @return 撤销结果
@ -576,8 +589,10 @@ public class WeixinPayProxy {
* @throws WeixinException
* @throws IOException
*/
public MerchantResult reverseOrder(IdQuery idQuery) throws WeixinException, IOException {
return payApi.reverseOrder(new FileInputStream(settings.getCertificateFile0()), idQuery);
public MerchantResult reverseOrder(IdQuery idQuery) throws WeixinException,
IOException {
return payApi.reverseOrder(
new FileInputStream(settings.getCertificateFile0()), idQuery);
}
/**
@ -586,7 +601,7 @@ public class WeixinPayProxy {
* 商户订单支付失败需要生成新单号重新发起支付要对原订单号调用关单避免重复支付系统下单后用户支付超时系统退出不再受理避免用户继续
* 请调用关单接口,如果关单失败,返回已完 成支付请按正常支付处理如果出现银行掉单,调用关单成功后,微信后台会主动发起退款
* </p>
*
*
* @param outTradeNo
* 商户系统内部的订单号
* @return 执行结果
@ -604,7 +619,7 @@ public class WeixinPayProxy {
/**
* native支付URL转短链接:用于扫码原生支付模式一中的二维码链接转成短链接(weixin://wxpay/s/XXXXXX)减小二维码数据量
* 提升扫描速度和精确度
*
*
* @param url
* 具有native标识的支付URL
* @return 转换后的短链接
@ -621,7 +636,7 @@ public class WeixinPayProxy {
/**
* 接口上报
*
*
* @param interfaceUrl
* 上报对应的接口的完整 URL, 类似: https://api.mch.weixin.q
* q.com/pay/unifiedorder
@ -642,14 +657,16 @@ public class WeixinPayProxy {
* 接口测试上报API</a>
* @throws WeixinException
*/
public XmlResult interfaceReport(String interfaceUrl, int executeTime, String outTradeNo, String ip, Date time,
XmlResult returnXml) throws WeixinException {
return payApi.interfaceReport(interfaceUrl, executeTime, outTradeNo, ip, time, returnXml);
public XmlResult interfaceReport(String interfaceUrl, int executeTime,
String outTradeNo, String ip, Date time, XmlResult returnXml)
throws WeixinException {
return payApi.interfaceReport(interfaceUrl, executeTime, outTradeNo,
ip, time, returnXml);
}
/**
* 发放代金券(需要证书)
*
*
* @param certificate
* 后缀为*.p12的证书文件
* @param couponStockId
@ -668,25 +685,28 @@ public class WeixinPayProxy {
* 发放代金券接口</a>
* @throws WeixinException
*/
public CouponResult sendCoupon(InputStream certificate, String couponStockId, String partnerTradeNo, String openId,
public CouponResult sendCoupon(InputStream certificate,
String couponStockId, String partnerTradeNo, String openId,
String opUserId) throws WeixinException {
return couponApi.sendCoupon(certificate, couponStockId, partnerTradeNo, openId, opUserId);
return couponApi.sendCoupon(certificate, couponStockId, partnerTradeNo,
openId, opUserId);
}
/**
* 发放代金券
*
*
* @see {@link com.foxinmy.weixin4j.payment.WeixinPayProxy#sendCoupon(InputStream, String, String, String, String)}
*/
public CouponResult sendCoupon(String couponStockId, String partnerTradeNo, String openId)
throws WeixinException, IOException {
return couponApi.sendCoupon(new FileInputStream(settings.getCertificateFile0()), couponStockId, partnerTradeNo,
openId, null);
public CouponResult sendCoupon(String couponStockId, String partnerTradeNo,
String openId) throws WeixinException, IOException {
return couponApi.sendCoupon(
new FileInputStream(settings.getCertificateFile0()),
couponStockId, partnerTradeNo, openId, null);
}
/**
* 查询代金券批次
*
*
* @param couponStockId
* 代金券批次ID
* @return 代金券批次信息
@ -697,13 +717,14 @@ public class WeixinPayProxy {
* 查询代金券批次信息接口</a>
* @throws WeixinException
*/
public CouponStock queryCouponStock(String couponStockId) throws WeixinException {
public CouponStock queryCouponStock(String couponStockId)
throws WeixinException {
return couponApi.queryCouponStock(couponStockId);
}
/**
* 查询代金券详细
*
*
* @param couponId
* 代金券ID
* @return 代金券详细信息
@ -714,13 +735,14 @@ public class WeixinPayProxy {
* 查询代金券详细信息接口</a>
* @throws WeixinException
*/
public CouponDetail queryCouponDetail(String couponId) throws WeixinException {
public CouponDetail queryCouponDetail(String couponId)
throws WeixinException {
return couponApi.queryCouponDetail(couponId);
}
/**
* 发放红包 企业向微信用户个人发现金红包
*
*
* @param certificate
* 后缀为*.p12的证书文件
* @param redpacket
@ -737,22 +759,25 @@ public class WeixinPayProxy {
* 发放裂变红包接口</a>
* @throws WeixinException
*/
public RedpacketSendResult sendRedpack(InputStream certificate, Redpacket redpacket) throws WeixinException {
public RedpacketSendResult sendRedpack(InputStream certificate,
Redpacket redpacket) throws WeixinException {
return cashApi.sendRedpack(certificate, redpacket);
}
/**
* 发放红包
*
*
* @see {@link #sendRedpack(InputStream, Redpacket)}
*/
public RedpacketSendResult sendRedpack(Redpacket redpacket) throws WeixinException, IOException {
return cashApi.sendRedpack(new FileInputStream(settings.getCertificateFile0()), redpacket);
public RedpacketSendResult sendRedpack(Redpacket redpacket)
throws WeixinException, IOException {
return cashApi.sendRedpack(
new FileInputStream(settings.getCertificateFile0()), redpacket);
}
/**
* 查询红包记录
*
*
* @param certificate
* 后缀为*.p12的证书文件
* @param outTradeNo
@ -768,22 +793,36 @@ public class WeixinPayProxy {
* 查询裂变红包接口</a>
* @throws WeixinException
*/
public RedpacketRecord queryRedpack(InputStream certificate, String outTradeNo) throws WeixinException {
public RedpacketRecord queryRedpack(InputStream certificate,
String outTradeNo) throws WeixinException {
return cashApi.queryRedpack(certificate, outTradeNo);
}
/**
* 查询红包
*
*
* @see {@link #queryRedpack(InputStream,String)}
*/
public RedpacketRecord queryRedpack(String outTradeNo) throws WeixinException, IOException {
return cashApi.queryRedpack(new FileInputStream(settings.getCertificateFile0()), outTradeNo);
public RedpacketRecord queryRedpack(String outTradeNo)
throws WeixinException, IOException {
return cashApi
.queryRedpack(
new FileInputStream(settings.getCertificateFile0()),
outTradeNo);
}
/**
* 企业付款 实现企业向个人付款针对部分有开发能力的商户 提供通过API完成企业付款的功能 比如目前的保险行业向客户退保给付理赔
*
* <p>
* 接口调用规则
* <p>
* <li>给同一个实名用户付款单笔单日限额2W/2W
* <li>给同一个非实名用户付款单笔单日限额2000/2000
* <li>一个商户同一日付款总额限额100W
* <li>单笔最小金额默认为1元
* <li>每个用户每天最多可付款10次可以在商户平台--API安全进行设置
* <li>给同一个用户付款时间间隔不得低于15秒
*
* @param certificate
* 后缀为*.p12的证书文件
* @param payment
@ -797,22 +836,25 @@ public class WeixinPayProxy {
* 企业付款接口</a>
* @throws WeixinException
*/
public CorpPaymentResult sendCorpPayment(InputStream certificate, CorpPayment payment) throws WeixinException {
public CorpPaymentResult sendCorpPayment(InputStream certificate,
CorpPayment payment) throws WeixinException {
return cashApi.sendCorpPayment(certificate, payment);
}
/**
* 企业付款
*
*
* @see {@link #sendCorpPayment(InputStream, CorpPayment)}
*/
public CorpPaymentResult sendCorpPayment(CorpPayment payment) throws WeixinException, IOException {
return cashApi.sendCorpPayment(new FileInputStream(settings.getCertificateFile0()), payment);
public CorpPaymentResult sendCorpPayment(CorpPayment payment)
throws WeixinException, IOException {
return cashApi.sendCorpPayment(
new FileInputStream(settings.getCertificateFile0()), payment);
}
/**
* 企业付款查询 用于商户的企业付款操作进行结果查询返回付款操作详细结果
*
*
* @param certificate
* 后缀为*.p12的证书文件
* @param outTradeNo
@ -825,22 +867,27 @@ public class WeixinPayProxy {
* 企业付款查询接口</a>
* @throws WeixinException
*/
public CorpPaymentRecord queryCorpPayment(InputStream certificate, String outTradeNo) throws WeixinException {
public CorpPaymentRecord queryCorpPayment(InputStream certificate,
String outTradeNo) throws WeixinException {
return cashApi.queryCorpPayment(certificate, outTradeNo);
}
/**
* 企业付款查询
*
*
* @see {@link #CorpPaymentRecord(InputStream, String)}
*/
public CorpPaymentRecord queryCorpPayment(String outTradeNo) throws WeixinException, IOException {
return cashApi.queryCorpPayment(new FileInputStream(settings.getCertificateFile0()), outTradeNo);
public CorpPaymentRecord queryCorpPayment(String outTradeNo)
throws WeixinException, IOException {
return cashApi
.queryCorpPayment(
new FileInputStream(settings.getCertificateFile0()),
outTradeNo);
}
/**
* 授权码查询OPENID
*
*
* @param authCode
* 扫码支付授权码设备读取用户微信中的条码或者二维码信息
* @return 查询结果
@ -857,7 +904,7 @@ public class WeixinPayProxy {
/**
* 查询结算资金
*
*
* @param status
* 是否结算
* @param pageable
@ -874,14 +921,14 @@ public class WeixinPayProxy {
* "https://pay.weixin.qq.com/wiki/doc/api/external/micropay.php?chapter=9_14&index=7">
* 查询结算资金接口</a>
*/
public SettlementRecord querySettlement(boolean status, Pageable pageable, Date start, Date end)
throws WeixinException {
public SettlementRecord querySettlement(boolean status, Pageable pageable,
Date start, Date end) throws WeixinException {
return cashApi.querySettlement(status, pageable, start, end);
}
/**
* 查询汇率
*
*
* @param currencyType
* 外币币种
* @param date
@ -893,13 +940,14 @@ public class WeixinPayProxy {
* "https://pay.weixin.qq.com/wiki/doc/api/external/micropay.php?chapter=9_15&index=8">
* 查询汇率接口</a>
*/
public double queryExchageRate(CurrencyType currencyType, Date date) throws WeixinException {
public double queryExchageRate(CurrencyType currencyType, Date date)
throws WeixinException {
return cashApi.queryExchageRate(currencyType, date);
}
/**
* 订单附加信息提交
*
*
* @param customsOrder
* 附加订单信息
* @return 报关结果
@ -911,13 +959,14 @@ public class WeixinPayProxy {
* 附加订单信息提交接口</a>
* @throws WeixinException
*/
public CustomsOrderResult declareCustomsOrder(CustomsOrder customsOrder) throws WeixinException {
public CustomsOrderResult declareCustomsOrder(CustomsOrder customsOrder)
throws WeixinException {
return customsApi.declareCustomsOrder(customsOrder);
}
/**
* 订单附加信息查询
*
*
* @param idQuery
* out_trade_no,transaction_id,sub_order_no,sub_order_id四选一
* @param customsCity
@ -930,7 +979,8 @@ public class WeixinPayProxy {
* 附加订单信息查询接口</a>
* @throws WeixinException
*/
public CustomsOrderRecord queryCustomsOrder(IdQuery idQuery, CustomsCity customsCity) throws WeixinException {
public CustomsOrderRecord queryCustomsOrder(IdQuery idQuery,
CustomsCity customsCity) throws WeixinException {
return customsApi.queryCustomsOrder(idQuery, customsCity);
}

View File

@ -9,7 +9,7 @@ import com.alibaba.fastjson.annotation.JSONField;
/**
* 企业付款结果
*
*
* @className CorpPaymentResult
* @author jinyu(foxinmy@gmail.com)
* @date 2015年4月1日
@ -44,7 +44,7 @@ public class CorpPaymentResult extends MerchantResult {
protected CorpPaymentResult() {
// jaxb required
}
public String getTransactionId() {
return transactionId;
}
@ -61,6 +61,6 @@ public class CorpPaymentResult extends MerchantResult {
public String toString() {
return "CorpPaymentResult [transactionId=" + transactionId
+ ", outTradeNo=" + outTradeNo + ", paymentTime=" + paymentTime
+ "]";
+ ", " + super.toString() + "]";
}
}

View File

@ -7,7 +7,7 @@ import com.alibaba.fastjson.annotation.JSONField;
/**
* 群发消息图文(消息内容存储在微信后台)
*
*
* @author jinyu(foxinmy@gmail.com)
* @date 2014年4月26日
* @since JDK 1.6

View File

@ -6,7 +6,7 @@ package com.foxinmy.weixin4j.type;
* 旧版本微信用户点击后将没有回应
* 开发者也不能正常接收到事件推送media_id和view_limited是专门给第三方平台旗下未微信认证具体而言是资质认证未通过的订阅号准备的事件类型
* 它们是没有事件推送的能力相对受限其他类型的公众号不必使用</font>
*
*
* @className ButtonType
* @author jinyu(foxinmy@gmail.com)
* @date 2014年9月30日
@ -62,5 +62,9 @@ public enum ButtonType {
* 跳转图文消息URL:用户点击view_limited类型按钮后微信客户端将打开开发者在按钮中填写的永久素材id对应的图文消息URL
* 永久素材类型只支持图文消息 请注意永久素材id必须是在素材管理/新增永久素材接口上传后获得的合法id
*/
view_limited;
view_limited,
/**
* 以下类型请勿使用,在公众平台设置的按钮类型,如果尝试使用API方式创建菜单则会出错
*/
popups,text,img,voice,video,news;
}

View File

@ -19,10 +19,11 @@ import com.foxinmy.weixin4j.mp.model.SemQuery;
import com.foxinmy.weixin4j.mp.model.SemResult;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.tuple.MpArticle;
import com.foxinmy.weixin4j.type.ButtonType;
/**
* 辅助相关API
*
*
* @className HelperApi
* @author jinyu(foxinmy@gmail.com)
* @date 2014年9月26日
@ -39,7 +40,7 @@ public class HelperApi extends MpApi {
/**
* 长链接转短链接
*
*
* @param url
* 待转换的链接
* @return 短链接
@ -62,7 +63,7 @@ public class HelperApi extends MpApi {
/**
* 语义理解
*
*
* @param semQuery
* 语义理解协议
* @return 语义理解结果
@ -84,7 +85,7 @@ public class HelperApi extends MpApi {
/**
* 获取微信服务器IP地址
*
*
* @return IP地址
* @see <a
* href="https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140187&token=&lang=zh_CN">获取IP地址</a>
@ -93,8 +94,8 @@ public class HelperApi extends MpApi {
public List<String> getWechatServerIp() throws WeixinException {
String getcallbackip_uri = getRequestUri("getcallbackip_uri");
Token token = tokenHolder.getToken();
WeixinResponse response = weixinExecutor.post(String.format(getcallbackip_uri,
token.getAccessToken()));
WeixinResponse response = weixinExecutor.post(String.format(
getcallbackip_uri, token.getAccessToken()));
return JSON.parseArray(response.getAsJson().getString("ip_list"),
String.class);
}
@ -102,7 +103,7 @@ public class HelperApi extends MpApi {
/**
* 获取公众号当前使用的自定义菜单的配置如果公众号是通过API调用设置的菜单则返回菜单的开发配置
* 而如果公众号是在公众平台官网通过网站功能发布菜单则本接口返回运营者设置的菜单配置
*
*
* @return 菜单集合
* @see {@link MenuApi#getMenu()}
* @see <a
@ -115,10 +116,9 @@ public class HelperApi extends MpApi {
public MenuSetting getMenuSetting() throws WeixinException {
String menu_get_selfmenu_uri = getRequestUri("menu_get_selfmenu_uri");
Token token = tokenHolder.getToken();
WeixinResponse response = weixinExecutor.get(String.format(menu_get_selfmenu_uri,
token.getAccessToken()));
WeixinResponse response = weixinExecutor.get(String.format(
menu_get_selfmenu_uri, token.getAccessToken()));
JSONObject result = response.getAsJson();
JSONArray buttons = result.getJSONObject("selfmenu_info").getJSONArray(
"button");
List<Button> buttonList = new ArrayList<Button>(buttons.size());
@ -128,6 +128,7 @@ public class HelperApi extends MpApi {
if (buttonObj.containsKey("sub_button")) {
JSONPath.set(buttonObj, "$.sub_button", buttonObj
.getJSONObject("sub_button").getJSONArray("list"));
buttonObj.put("type", ButtonType.popups);
}
buttonList.add(JSON.parseObject(buttonObj.toJSONString(),
Button.class, ButtonExtraProcessor.global));
@ -147,9 +148,15 @@ public class HelperApi extends MpApi {
if (key.equals("news_info")) {
JSONArray news = ((JSONObject) value).getJSONArray("list");
List<MpArticle> newsList = new ArrayList<MpArticle>(news.size());
JSONObject article = null;
for (int i = 0; i < news.size(); i++) {
newsList.add(JSON.parseObject(news.getString(i),
MpArticle.class, ArticleExtraProcessor.global));
article = news.getJSONObject(i);
article.put("showCoverPic", article.remove("show_cover"));
article.put("coverUrl", article.remove("cover_url"));
article.put("contentUrl", article.remove("content_url"));
article.put("sourceUrl", article.remove("source_url"));
newsList.add(JSON.parseObject(article.toJSONString(),
MpArticle.class));
}
JSONPath.set(object, "$.content", newsList);
} else {
@ -158,28 +165,9 @@ public class HelperApi extends MpApi {
}
};
private static final class ArticleExtraProcessor implements ExtraProcessor {
private static final ArticleExtraProcessor global = new ArticleExtraProcessor();
private ArticleExtraProcessor() {
}
@Override
public void processExtra(Object object, String key, Object value) {
MpArticle mpArticle = (MpArticle) object;
if (key.equals("show_cover")) {
mpArticle.setShowCoverPic(value.equals("1"));
}
if (key.equals("source_url")) {
mpArticle.setSourceUrl(value.toString());
}
}
}
/**
* 获取公众号当前使用的自动回复规则包括关注后自动回复消息自动回复60分钟内触发一次关键词自动回复
*
*
* @see com.foxinmy.weixin4j.mp.model.AutoReplySetting
* @see <a
* href="https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1433751299&token=&lang=zh_CN">获取自动回复规则</a>

View File

@ -9,7 +9,16 @@ import org.junit.Test;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.mp.api.HelperApi;
public class HelpTest extends TokenTest {
/**
* 辅助API测试
*
* @className HelperTest
* @author jinyu(foxinmy@gmail.com)
* @date 2016年5月24日
* @since JDK 1.6
* @see
*/
public class HelperTest extends TokenTest {
private HelperApi helperApi;
@Before

View File

@ -17,7 +17,7 @@ import com.foxinmy.weixin4j.util.ServerToolkits;
/**
* 微信回复编码类
*
*
* @className WeixinResponseEncoder
* @author jinyu(foxinmy@gmail.com)
* @date 2014年11月13日

View File

@ -17,7 +17,7 @@ import com.foxinmy.weixin4j.startup.WeixinServerBootstrap;
/**
* HTTP工具类
*
*
* @className HttpUtil
* @author jinyu(foxinmy@gmail.com)
* @date 2014年11月15日
@ -31,15 +31,11 @@ public class HttpUtil {
/**
* 创建有内容的HttpResponse响应
*
*
* @param content
* 响应内容
* @param status
* 响应状态
* @param contentType
* 响应类型
* @param request
* 请求对象
* @return HttpResponse
*/
public static HttpResponse createHttpResponse(String content,
@ -58,12 +54,12 @@ public class HttpUtil {
}
public static void resolveHeaders(FullHttpResponse httpResponse) {
/*if (HttpHeaders.isKeepAlive(httpRequest)) {
httpResponse.headers().set(CONNECTION, Values.KEEP_ALIVE);
}
if (HttpHeaders.isTransferEncodingChunked(httpRequest)) {
httpResponse.headers().set(TRANSFER_ENCODING, Values.CHUNKED);
}*/
/*
* if (HttpHeaders.isKeepAlive(httpRequest)) {
* httpResponse.headers().set(CONNECTION, Values.KEEP_ALIVE); } if
* (HttpHeaders.isTransferEncodingChunked(httpRequest)) {
* httpResponse.headers().set(TRANSFER_ENCODING, Values.CHUNKED); }
*/
httpResponse.headers().set(DATE, new Date());
httpResponse.headers().set(SERVER, SERVER);
httpResponse.headers()