将支付API相关内容迁移到新的子模块weixin4j-pay
This commit is contained in:
parent
3af2db29d9
commit
86fc0712d0
46
weixin4j-pay/pom.xml
Normal file
46
weixin4j-pay/pom.xml
Normal file
@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>weixin4j</artifactId>
|
||||
<groupId>com.foxinmy</groupId>
|
||||
<version>1.9.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<name>weixin4j-pay</name>
|
||||
<artifactId>weixin4j-pay</artifactId>
|
||||
<url>https://github.com/foxinmy/weixin4j/tree/master/weixin4j-pay</url>
|
||||
<description>微信支付商户平台API</description>
|
||||
<developers>
|
||||
<developer>
|
||||
<id>kit-lee</id>
|
||||
<name>Kit lee</name>
|
||||
<email>ryuji.cn@gmail.com</email>
|
||||
<url>https://github.com/kit-lee</url>
|
||||
<properties>
|
||||
<contact>kit_21cn@21cn.com</contact>
|
||||
<forkRepo>https://github.com/kit-lee/weixin4j</forkRepo>
|
||||
</properties>
|
||||
</developer>
|
||||
</developers>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.foxinmy</groupId>
|
||||
<artifactId>weixin4j-base</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@ -0,0 +1,138 @@
|
||||
package com.foxinmy.weixin4j.pay.api;
|
||||
|
||||
import com.foxinmy.weixin4j.api.BaseApi;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.http.weixin.WeixinRequestExecutor;
|
||||
import com.foxinmy.weixin4j.pay.model.WeixinPayAccount;
|
||||
import com.foxinmy.weixin4j.pay.payment.mch.MerchantResult;
|
||||
import com.foxinmy.weixin4j.pay.sign.WeixinPaymentSignature;
|
||||
import com.foxinmy.weixin4j.pay.type.IdQuery;
|
||||
import com.foxinmy.weixin4j.pay.sign.WeixinSignature;
|
||||
import com.foxinmy.weixin4j.util.RandomUtil;
|
||||
import com.foxinmy.weixin4j.util.StringUtil;
|
||||
import com.foxinmy.weixin4j.util.Weixin4jConfigUtil;
|
||||
|
||||
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 java.util.ResourceBundle;
|
||||
|
||||
/**
|
||||
* 商户支付
|
||||
*
|
||||
* @className MchApi
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2016年3月26日
|
||||
* @since JDK 1.6
|
||||
* @see <a href="https://pay.weixin.qq.com/wiki/doc/api/index.html">商户支付平台</a>
|
||||
*/
|
||||
public class MchApi extends BaseApi {
|
||||
private final static ResourceBundle WEIXIN_BUNDLE;
|
||||
|
||||
private final static String PEM_CERT_PREFIX = "-----BEGIN CERTIFICATE-----";
|
||||
|
||||
static {
|
||||
WEIXIN_BUNDLE = ResourceBundle.getBundle("com/foxinmy/weixin4j/payment/weixin");
|
||||
}
|
||||
|
||||
protected final WeixinPayAccount weixinAccount;
|
||||
protected final WeixinSignature weixinSignature;
|
||||
private volatile WeixinRequestExecutor weixinSSLExecutor;
|
||||
|
||||
public MchApi(WeixinPayAccount weixinAccount) {
|
||||
this.weixinAccount = weixinAccount;
|
||||
this.weixinSignature = new WeixinPaymentSignature(weixinAccount.getPaySignKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ResourceBundle weixinBundle() {
|
||||
return WEIXIN_BUNDLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付接口请求基本数据
|
||||
*
|
||||
* @param idQuery
|
||||
* ID信息 可为空
|
||||
* @return 基础map
|
||||
*/
|
||||
protected Map<String, String> createBaseRequestMap(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 (StringUtil.isNotBlank(weixinAccount.getSubId())) {
|
||||
map.put("sub_appid", weixinAccount.getSubId());
|
||||
}
|
||||
if (StringUtil.isNotBlank(weixinAccount.getSubMchId())) {
|
||||
map.put("sub_mch_id", weixinAccount.getSubMchId());
|
||||
}
|
||||
if (idQuery != null) {
|
||||
map.put(idQuery.getType().getName(), idQuery.getId());
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信签名类
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public WeixinSignature getWeixinSignature() {
|
||||
return this.weixinSignature;
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信SSL
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected WeixinRequestExecutor getWeixinSSLExecutor() throws WeixinException {
|
||||
if (weixinSSLExecutor == null) {
|
||||
if(weixinAccount.getCertificateFile().startsWith(PEM_CERT_PREFIX)){
|
||||
// 证书是PEM格式,直接使用PEM内容生成请求执行类
|
||||
this.weixinSSLExecutor = weixinExecutor.createSSLRequestExecutor(weixinAccount.getMchId(),
|
||||
weixinAccount.getCertificateFile(), weixinAccount.getCertificateKey());
|
||||
}else {
|
||||
// 证书是p12格式,读取证书文件并生成请求执行类
|
||||
try {
|
||||
InputStream is = null;
|
||||
File certificate = new File(
|
||||
Weixin4jConfigUtil.replaceClassPathValue(weixinAccount.getCertificateFile()));
|
||||
if (!certificate.exists() || !certificate.isFile()) {
|
||||
is = Weixin4jConfigUtil.CLASSLOADER.getResourceAsStream(certificate.getName());
|
||||
} else {
|
||||
is = new FileInputStream(certificate);
|
||||
}
|
||||
if (is == null) {
|
||||
throw new WeixinException("Invalid certificate file : " + certificate.toString());
|
||||
}
|
||||
this.weixinSSLExecutor = weixinExecutor.createSSLRequestExecutor(weixinAccount.getCertificateKey(), is);
|
||||
} catch (IOException e) {
|
||||
throw new WeixinException("IO Error on createSSLRequestExecutor", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return this.weixinSSLExecutor;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置商户信息
|
||||
*
|
||||
* @param merchant
|
||||
*/
|
||||
protected <T extends MerchantResult> void declareMerchant(T merchant) {
|
||||
merchant.setAppId(weixinAccount.getId());
|
||||
merchant.setMchId(weixinAccount.getMchId());
|
||||
merchant.setDeviceInfo(weixinAccount.getDeviceInfo());
|
||||
merchant.setSubAppId(weixinAccount.getSubId());
|
||||
merchant.setSubMchId(weixinAccount.getSubMchId());
|
||||
merchant.setNonceStr(RandomUtil.generateString(16));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,775 @@
|
||||
package com.foxinmy.weixin4j.pay.api;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.TypeReference;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
|
||||
import com.foxinmy.weixin4j.http.weixin.XmlResult;
|
||||
import com.foxinmy.weixin4j.pay.model.WeixinPayAccount;
|
||||
import com.foxinmy.weixin4j.pay.payment.mch.*;
|
||||
import com.foxinmy.weixin4j.pay.type.mch.BillType;
|
||||
import com.foxinmy.weixin4j.pay.type.mch.RefundAccountType;
|
||||
import com.foxinmy.weixin4j.pay.type.*;
|
||||
import com.foxinmy.weixin4j.util.*;
|
||||
import com.foxinmy.weixin4j.xml.ListsuffixResultDeserializer;
|
||||
import com.foxinmy.weixin4j.xml.XmlStream;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 支付API
|
||||
*
|
||||
* @className PayApi
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2014年10月28日
|
||||
* @since JDK 1.6
|
||||
*/
|
||||
public class PayApi extends MchApi {
|
||||
|
||||
public PayApi(WeixinPayAccount weixinAccount) {
|
||||
super(weixinAccount);
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一下单接口</br>
|
||||
* 除被扫支付场景以外,商户系统先调用该接口在微信支付服务后台生成预支付交易单,返回正确的预支付交易回话标识后再按扫码、JSAPI
|
||||
* 、APP等不同场景生成交易串调起支付。
|
||||
*
|
||||
* @param payPackage
|
||||
* 包含订单信息的对象
|
||||
* @see MchPayPackage
|
||||
* @see PrePay
|
||||
* @see <a href=
|
||||
* "http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1">统一下单接口
|
||||
* </a>
|
||||
* @return 预支付对象
|
||||
*/
|
||||
public PrePay createPrePay(MchPayPackage payPackage) throws WeixinException {
|
||||
super.declareMerchant(payPackage);
|
||||
payPackage.setSign(weixinSignature.sign(payPackage));
|
||||
String payJsRequestXml = XmlStream.toXML(payPackage);
|
||||
WeixinResponse response = weixinExecutor.post(
|
||||
getRequestUri("order_create_uri"), payJsRequestXml);
|
||||
return response.getAsObject(new TypeReference<PrePay>() {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建支付请求对象
|
||||
*
|
||||
* @param payPackage
|
||||
* 支付详情
|
||||
* @return 支付请求对象
|
||||
* @see JSAPIPayRequest JS支付
|
||||
* @see NATIVEPayRequest 扫码支付
|
||||
* @see MICROPayRequest 刷卡支付
|
||||
* @see APPPayRequest APP支付
|
||||
* @see WAPPayRequest WAP支付
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public MchPayRequest createPayRequest(MchPayPackage payPackage)
|
||||
throws WeixinException {
|
||||
if (StringUtil.isBlank(payPackage.getTradeType())) {
|
||||
throw new WeixinException("tradeType not be empty");
|
||||
}
|
||||
String tradeType = payPackage.getTradeType().toUpperCase();
|
||||
if (TradeType.MICROPAY.name().equals(tradeType)) {
|
||||
MchPayPackage _payPackage = new MchPayPackage(payPackage.getBody(),
|
||||
payPackage.getDetail(), payPackage.getOutTradeNo(),
|
||||
DateUtil.formatFee2Yuan(payPackage.getTotalFee()), null,
|
||||
null, payPackage.getCreateIp(), null, null,
|
||||
payPackage.getAuthCode(), null, payPackage.getAttach(),
|
||||
null, null, payPackage.getGoodsTag(),
|
||||
payPackage.getLimitPay(), payPackage.getSubAppId());
|
||||
super.declareMerchant(_payPackage);
|
||||
_payPackage.setSign(weixinSignature.sign(_payPackage));
|
||||
String para = XmlStream.toXML(_payPackage);
|
||||
WeixinResponse response = weixinExecutor.post(
|
||||
getRequestUri("micropay_uri"), para);
|
||||
MICROPayRequest microPayRequest = response
|
||||
.getAsObject(new TypeReference<MICROPayRequest>() {
|
||||
});
|
||||
microPayRequest.setPaymentAccount(weixinAccount);
|
||||
return microPayRequest;
|
||||
}
|
||||
PrePay prePay = createPrePay(payPackage);
|
||||
if (TradeType.APP.name().equals(tradeType)) {
|
||||
return new APPPayRequest(prePay.getPrepayId(), weixinAccount);
|
||||
} else if (TradeType.JSAPI.name().equals(tradeType)) {
|
||||
return new JSAPIPayRequest(prePay.getPrepayId(), weixinAccount);
|
||||
} else if (TradeType.NATIVE.name().equals(tradeType)) {
|
||||
return new NATIVEPayRequest(prePay.getPrepayId(),
|
||||
prePay.getPayUrl(), weixinAccount);
|
||||
} else if (TradeType.MWEB.name().equals(tradeType)) {
|
||||
return new WAPPayRequest(prePay.getPrepayId(), prePay.getPayUrl(),
|
||||
weixinAccount);
|
||||
} else {
|
||||
throw new WeixinException("unknown tradeType:" + tradeType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建JSAPI支付请求对象
|
||||
*
|
||||
* @param openId
|
||||
* 用户ID
|
||||
* @param body
|
||||
* 订单描述
|
||||
* @param outTradeNo
|
||||
* 订单号
|
||||
* @param totalFee
|
||||
* 订单总额(元)
|
||||
* @param notifyUrl
|
||||
* 支付通知地址
|
||||
* @param createIp
|
||||
* ip地址
|
||||
* @param attach
|
||||
* 附加数据 非必填
|
||||
* @see JSAPIPayRequest
|
||||
* @return JSAPI支付对象
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public MchPayRequest createJSPayRequest(String openId, String body,
|
||||
String outTradeNo, double totalFee, String notifyUrl,
|
||||
String createIp, String attach) throws WeixinException {
|
||||
MchPayPackage payPackage = new MchPayPackage(body, outTradeNo,
|
||||
totalFee, notifyUrl, createIp, TradeType.JSAPI, openId, null,
|
||||
null, attach);
|
||||
return createPayRequest(payPackage);
|
||||
}
|
||||
|
||||
/**
|
||||
* <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 url
|
||||
* 当前访问页的URL
|
||||
* @param oauthToken
|
||||
* oauth授权时产生的token
|
||||
* @see <a href=
|
||||
* "https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_8&index=7">
|
||||
* 收货地址共享</a>
|
||||
* @return 编辑地址请求JSON串
|
||||
*/
|
||||
public String createAddressRequestJSON(String url, String oauthToken) {
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
map.put("appId", weixinAccount.getId());
|
||||
map.put("timeStamp", DateUtil.timestamp2string());
|
||||
map.put("nonceStr", RandomUtil.generateString(16));
|
||||
map.put("url", url);
|
||||
map.put("accessToken", oauthToken);
|
||||
String sign = DigestUtil.SHA1(MapUtil.toJoinString(map, false, true));
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建Native支付(扫码支付)链接【模式一】
|
||||
*
|
||||
* @param productId
|
||||
* 与订单ID等价
|
||||
* @return 支付链接
|
||||
* @see <a href=
|
||||
* "https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_1">扫码支付
|
||||
* </a>
|
||||
* @see <a href=
|
||||
* "https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_4">模式一
|
||||
* </a>
|
||||
*/
|
||||
public String createNativePayRequest(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 = weixinSignature.sign(map);
|
||||
return String.format(getRequestUri("native_pay_uri"), sign,
|
||||
weixinAccount.getId(), weixinAccount.getMchId(), productId,
|
||||
timestamp, noncestr);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建Native支付(扫码支付)回调对象【模式一】
|
||||
*
|
||||
* @param productId
|
||||
* 商品ID
|
||||
* @param body
|
||||
* 商品描述
|
||||
* @param outTradeNo
|
||||
* 商户内部唯一订单号
|
||||
* @param totalFee
|
||||
* 商品总额 单位元
|
||||
* @param notifyUrl
|
||||
* 支付回调URL
|
||||
* @param createIp
|
||||
* 订单生成的机器 IP
|
||||
* @param attach
|
||||
* 附加数据 非必填
|
||||
* @return Native回调对象
|
||||
* @see NativePayResponse
|
||||
* @see <a href=
|
||||
* "https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_1">扫码支付
|
||||
* </a>
|
||||
* @see <a href=
|
||||
* "https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_4">模式一
|
||||
* </a>
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public NativePayResponse createNativePayResponse(String productId,
|
||||
String body, String outTradeNo, double totalFee, String notifyUrl,
|
||||
String createIp, String attach) throws WeixinException {
|
||||
MchPayPackage payPackage = new MchPayPackage(body, outTradeNo,
|
||||
totalFee, notifyUrl, createIp, TradeType.NATIVE, null, null,
|
||||
productId, attach);
|
||||
PrePay prePay = createPrePay(payPackage);
|
||||
return new NativePayResponse(weixinAccount, prePay.getPrepayId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建Native支付(扫码支付)链接【模式二】
|
||||
*
|
||||
* @param productId
|
||||
* 商品ID
|
||||
* @param body
|
||||
* 商品描述
|
||||
* @param outTradeNo
|
||||
* 商户内部唯一订单号
|
||||
* @param totalFee
|
||||
* 商品总额 单位元
|
||||
* @param notifyUrl
|
||||
* 支付回调URL
|
||||
* @param createIp
|
||||
* 订单生成的机器 IP
|
||||
* @param attach
|
||||
* 附加数据 非必填
|
||||
* @return Native支付对象
|
||||
* @see NATIVEPayRequest
|
||||
* @see <a href=
|
||||
* "https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_1">扫码支付
|
||||
* </a>
|
||||
* @see <a href=
|
||||
* "https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_5">模式二
|
||||
* </a>
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public MchPayRequest createNativePayRequest(String productId, String body,
|
||||
String outTradeNo, double totalFee, String notifyUrl,
|
||||
String createIp, String attach) throws WeixinException {
|
||||
MchPayPackage payPackage = new MchPayPackage(body, outTradeNo,
|
||||
totalFee, notifyUrl, createIp, TradeType.NATIVE, null, null,
|
||||
productId, attach);
|
||||
return createPayRequest(payPackage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建APP支付请求对象
|
||||
*
|
||||
* @param body
|
||||
* 商品描述
|
||||
* @param outTradeNo
|
||||
* 商户内部唯一订单号
|
||||
* @param totalFee
|
||||
* 商品总额 单位元
|
||||
* @param notifyUrl
|
||||
* 支付回调URL
|
||||
* @param createIp
|
||||
* 订单生成的机器 IP
|
||||
* @param attach
|
||||
* 附加数据 非必填
|
||||
* @param store
|
||||
* 门店信息 非必填
|
||||
* @return APP支付对象
|
||||
* @see SceneInfoStore
|
||||
* @see APPPayRequest
|
||||
* @see <a href=
|
||||
* "https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_1">
|
||||
* APP支付</a>
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public MchPayRequest createAppPayRequest(String body, String outTradeNo,
|
||||
double totalFee, String notifyUrl, String createIp, String attach,
|
||||
SceneInfoStore store) throws WeixinException {
|
||||
MchPayPackage payPackage = new MchPayPackage(body, outTradeNo,
|
||||
totalFee, notifyUrl, createIp, TradeType.APP, null, null, null,
|
||||
attach);
|
||||
if (store != null) {
|
||||
payPackage.setSceneInfo(String.format(
|
||||
"{\"store_id\": \"%s\", \"store_name\":\"%s\"}",
|
||||
store.getId(), store.getName()));
|
||||
}
|
||||
return createPayRequest(payPackage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建WAP支付请求对象:正常流程用户支付完成后会返回至发起支付的页面,如需返回至指定页面,
|
||||
* 则可以在MWEB_URL后拼接上redirect_url参数,来指定回调页面
|
||||
*
|
||||
* @param body
|
||||
* 商品描述
|
||||
* @param outTradeNo
|
||||
* 商户内部唯一订单号
|
||||
* @param totalFee
|
||||
* 商品总额 单位元
|
||||
* @param notifyUrl
|
||||
* 支付回调URL
|
||||
* @param createIp
|
||||
* 订单生成的机器 IP
|
||||
* @param attach
|
||||
* 附加数据 非必填
|
||||
* @param app
|
||||
* 应用信息
|
||||
* @return WAP支付对象
|
||||
* @see SceneInfoApp
|
||||
* @see WAPPayRequest
|
||||
* @see <a href=
|
||||
* "https://pay.weixin.qq.com/wiki/doc/api/wap.php?chapter=15_1">WAP支付
|
||||
* </a>
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public MchPayRequest createWapPayRequest(String body, String outTradeNo,
|
||||
double totalFee, String notifyUrl, String createIp, String attach,
|
||||
SceneInfoApp app) throws WeixinException {
|
||||
MchPayPackage payPackage = new MchPayPackage(body, outTradeNo,
|
||||
totalFee, notifyUrl, createIp, TradeType.MWEB, null, null,
|
||||
null, attach);
|
||||
if (app != null) {
|
||||
payPackage.setSceneInfo(String.format("{\"h5_info\":\"%s\"}",
|
||||
app.getSceneInfo()));
|
||||
}
|
||||
return createPayRequest(payPackage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 提交被扫支付
|
||||
*
|
||||
* @param authCode
|
||||
* 扫码支付授权码 ,设备读取用户微信中的条码或者二维码信息
|
||||
* @param body
|
||||
* 商品描述
|
||||
* @param outTradeNo
|
||||
* 商户内部唯一订单号
|
||||
* @param totalFee
|
||||
* 商品总额 单位元
|
||||
* @param createIp
|
||||
* 订单生成的机器 IP
|
||||
* @param attach
|
||||
* 附加数据 非必填
|
||||
* @param store
|
||||
* 门店信息 非必填
|
||||
* @return 支付的订单信息
|
||||
* @see MICROPayRequest
|
||||
* @see Order
|
||||
* @see SceneInfoStore
|
||||
* @see <a href=
|
||||
* "http://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_10">
|
||||
* 提交被扫支付API</a>
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public MchPayRequest createMicroPayRequest(String authCode, String body,
|
||||
String outTradeNo, double totalFee, String createIp, String attach,
|
||||
SceneInfoStore store) throws WeixinException {
|
||||
MchPayPackage payPackage = new MchPayPackage(body, outTradeNo,
|
||||
totalFee, null, createIp, TradeType.MICROPAY, null, authCode,
|
||||
null, attach);
|
||||
if (store != null) {
|
||||
payPackage.setSceneInfo(String.format("{\"store_info\":\"%s\"}",
|
||||
JSON.toJSONString(store)));
|
||||
}
|
||||
return createPayRequest(payPackage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单查询
|
||||
* <p>
|
||||
* 当商户后台、网络、服务器等出现异常,商户系统最终未接收到支付通知;</br> 调用支付接口后,返回系统错误或未知交易状态情况;</br>
|
||||
* 调用被扫支付API,返回USERPAYING的状态;</br> 调用关单或撤销接口API之前,需确认支付状态;
|
||||
* </P>
|
||||
*
|
||||
* @param idQuery
|
||||
* 商户系统内部的订单号, transaction_id、out_trade_no 二 选一,如果同时存在优先级:
|
||||
* transaction_id> out_trade_no
|
||||
* @return 订单信息
|
||||
* @see 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 queryOrder(IdQuery idQuery) throws WeixinException {
|
||||
Map<String, String> map = createBaseRequestMap(idQuery);
|
||||
map.put("sign", weixinSignature.sign(map));
|
||||
String param = XmlStream.map2xml(map);
|
||||
WeixinResponse response = weixinExecutor.post(
|
||||
getRequestUri("order_query_uri"), param);
|
||||
return ListsuffixResultDeserializer.deserialize(response.getAsString(),
|
||||
Order.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 申请退款(请求需要双向证书)
|
||||
*
|
||||
* <p>
|
||||
* 当交易发生之后一段时间内,由于买家或者卖家的原因需要退款时,卖家可以通过退款接口将支付款退还给买家,微信支付将在收到退款请求并且验证成功之后,
|
||||
* 按照退款规则将支付款按原路退到买家帐号上。
|
||||
* </p>
|
||||
*
|
||||
* <ol>
|
||||
* <li>交易时间超过一年的订单无法提交退款;</li>
|
||||
* <li>
|
||||
* 微信支付退款支持单笔交易分多次退款,多次退款需要提交原支付订单的商户订单号和设置不同的退款单号。
|
||||
* 申请退款总金额不能超过订单金额。
|
||||
* <span style="color:red">一笔退款失败后重新提交,请不要更换退款单号,请使用原商户退款单号。</span>
|
||||
* </li>
|
||||
* <li>
|
||||
* 请求频率限制:150qps,即每秒钟正常的申请退款请求次数不超过150次。
|
||||
* 错误或无效请求频率限制:6qps,即每秒钟异常或错误的退款申请请求不超过6次。
|
||||
* </li>
|
||||
* <li>每个支付订单的部分退款次数不能超过50次。</li>
|
||||
* </ol>
|
||||
*
|
||||
* @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
|
||||
* 操作员帐号, 默认为商户号
|
||||
* @param refundDesc
|
||||
* 退款原因,若商户传入,会在下发给用户的退款消息中体现退款原因
|
||||
* @param refundAccountType
|
||||
* 退款资金来源,默认使用未结算资金退款:REFUND_SOURCE_UNSETTLED_FUNDS
|
||||
* @return 退款申请结果
|
||||
* @see RefundResult
|
||||
* @see <a href=
|
||||
* "http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4">
|
||||
* 申请退款API</a>
|
||||
* @since V3
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public RefundResult applyRefund(IdQuery idQuery, String outRefundNo,
|
||||
double totalFee, double refundFee, CurrencyType refundFeeType,
|
||||
String opUserId, String refundDesc,
|
||||
RefundAccountType refundAccountType) throws WeixinException {
|
||||
Map<String, String> map = createBaseRequestMap(idQuery);
|
||||
map.put("out_refund_no", outRefundNo);
|
||||
map.put("total_fee",
|
||||
Integer.toString(DateUtil.formatYuan2Fen(totalFee)));
|
||||
map.put("refund_fee",
|
||||
Integer.toString(DateUtil.formatYuan2Fen(refundFee)));
|
||||
if (StringUtil.isBlank(opUserId)) {
|
||||
opUserId = weixinAccount.getMchId();
|
||||
}
|
||||
map.put("op_user_id", opUserId);
|
||||
if (refundFeeType == null) {
|
||||
refundFeeType = CurrencyType.CNY;
|
||||
}
|
||||
if (refundAccountType == null) {
|
||||
refundAccountType = RefundAccountType.REFUND_SOURCE_UNSETTLED_FUNDS;
|
||||
}
|
||||
if (StringUtil.isNotBlank(refundDesc)) {
|
||||
map.put("refund_desc", refundDesc);
|
||||
}
|
||||
map.put("refund_fee_type", refundFeeType.name());
|
||||
map.put("refund_account", refundAccountType.name());
|
||||
map.put("sign", weixinSignature.sign(map));
|
||||
String param = XmlStream.map2xml(map);
|
||||
WeixinResponse response = getWeixinSSLExecutor().post(
|
||||
getRequestUri("refund_apply_uri"), param);
|
||||
return response.getAsObject(new TypeReference<RefundResult>() {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 退款申请(全额退款)
|
||||
*
|
||||
* @param idQuery
|
||||
* 商户系统内部的订单号, transaction_id 、 out_trade_no 二选一,如果同时存在优先级:
|
||||
* transaction_id> out_trade_no
|
||||
* @param outRefundNo
|
||||
* 商户系统内部的退款单号,商 户系统内部唯一,同一退款单号多次请求只退一笔
|
||||
* @param totalFee
|
||||
* 订单总金额,单位为元
|
||||
* @see #applyRefund(IdQuery, String, double, double, CurrencyType, String, String, RefundAccountType)
|
||||
*/
|
||||
public RefundResult applyRefund(IdQuery idQuery, String outRefundNo,
|
||||
double totalFee) throws WeixinException {
|
||||
return applyRefund(idQuery, outRefundNo, totalFee, totalFee, null,
|
||||
null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 冲正订单(需要证书)</br> 当支付返回失败,或收银系统超时需要取消交易,可以调用该接口</br> 接口逻辑:支
|
||||
* 付失败的关单,支付成功的撤销支付</br> <font color="red">7天以内的单可撤销,其他正常支付的单
|
||||
* 如需实现相同功能请调用退款接口</font></br> <font
|
||||
* color="red">调用扣款接口后请勿立即调用撤销,需要等待5秒以上。先调用查单接口,如果没有确切的返回,再调用撤销</font> </br>
|
||||
*
|
||||
* @param idQuery
|
||||
* 商户系统内部的订单号, transaction_id 、 out_trade_no 二选一,如果同时存在优先级:
|
||||
* transaction_id> out_trade_no
|
||||
* @return 撤销结果
|
||||
* @since V3
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public MerchantResult reverseOrder(IdQuery idQuery) throws WeixinException {
|
||||
Map<String, String> map = createBaseRequestMap(idQuery);
|
||||
map.put("sign", weixinSignature.sign(map));
|
||||
String param = XmlStream.map2xml(map);
|
||||
WeixinResponse response = getWeixinSSLExecutor().post(
|
||||
getRequestUri("order_reverse_uri"), param);
|
||||
return response.getAsObject(new TypeReference<MerchantResult>() {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 = createBaseRequestMap(null);
|
||||
try {
|
||||
map.put("long_url", URLEncoder.encode(url, Consts.UTF_8.name()));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
;
|
||||
}
|
||||
map.put("sign", weixinSignature.sign(map));
|
||||
String param = XmlStream.map2xml(map);
|
||||
WeixinResponse response = weixinExecutor.post(
|
||||
getRequestUri("longurl_convert_uri"), 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 MerchantResult closeOrder(String outTradeNo) throws WeixinException {
|
||||
Map<String, String> map = createBaseRequestMap(new IdQuery(outTradeNo,
|
||||
IdType.TRADENO));
|
||||
map.put("sign", weixinSignature.sign(map));
|
||||
String param = XmlStream.map2xml(map);
|
||||
WeixinResponse response = weixinExecutor.post(
|
||||
getRequestUri("order_close_uri"), param);
|
||||
return response.getAsObject(new TypeReference<MerchantResult>() {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载对账单<br>
|
||||
* 1.微信侧未成功下单的交易不会出现在对账单中。支付成功后撤销的交易会出现在对账 单中,跟原支付单订单号一致,bill_type 为
|
||||
* REVOKED;<br>
|
||||
* 2.微信在次日 9 点启动生成前一天的对账单,建议商户 9 点半后再获取;<br>
|
||||
* 3.对账单中涉及金额的字段单位为“元”。<br>
|
||||
*
|
||||
* @param billDate
|
||||
* 下载对账单的日期
|
||||
* @param billType
|
||||
* 下载对账单的类型 ALL,返回当日所有订单信息, 默认值 SUCCESS,返回当日成功支付的订单
|
||||
* REFUND,返回当日退款订单
|
||||
* @param outputStream
|
||||
* 输出流
|
||||
* @param tarType
|
||||
* 非必传参数,固定值:GZIP,返回格式为.gzip的压缩包账单。不传则默认为数据流形式。
|
||||
* @since V3
|
||||
* @see <a href=
|
||||
* "http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_6">
|
||||
* 下载对账单API</a>
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public void downloadBill(Date billDate, BillType billType,
|
||||
OutputStream outputStream, TarType tarType) 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);
|
||||
Map<String, String> map = createBaseRequestMap(null);
|
||||
map.put("bill_date", formatBillDate);
|
||||
map.put("bill_type", billType.name());
|
||||
if (tarType != null) {
|
||||
map.put("tar_type", tarType.name());
|
||||
}
|
||||
map.put("sign", weixinSignature.sign(map));
|
||||
String param = XmlStream.map2xml(map);
|
||||
WeixinResponse response = weixinExecutor.post(
|
||||
getRequestUri("downloadbill_uri"), param);
|
||||
|
||||
if (TarType.GZIP == tarType) {
|
||||
try {
|
||||
IOUtil.copy(response.getBody(), outputStream);
|
||||
} catch (IOException e) {
|
||||
;
|
||||
}
|
||||
} else {
|
||||
BufferedReader reader = null;
|
||||
BufferedWriter writer = null;
|
||||
try {
|
||||
writer = new BufferedWriter(new OutputStreamWriter(
|
||||
outputStream, Consts.UTF_8));
|
||||
reader = new BufferedReader(new InputStreamReader(
|
||||
response.getBody(), Consts.UTF_8));
|
||||
String line = null;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
writer.write(line);
|
||||
writer.newLine();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new WeixinException(e);
|
||||
} finally {
|
||||
try {
|
||||
if (reader != null) {
|
||||
reader.close();
|
||||
}
|
||||
if (writer != null) {
|
||||
writer.close();
|
||||
}
|
||||
} catch (IOException ignore) {
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 退款查询
|
||||
*
|
||||
* <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 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 queryRefund(IdQuery idQuery) throws WeixinException {
|
||||
Map<String, String> map = createBaseRequestMap(idQuery);
|
||||
map.put("sign", weixinSignature.sign(map));
|
||||
String param = XmlStream.map2xml(map);
|
||||
WeixinResponse response = weixinExecutor.post(
|
||||
getRequestUri("refund_query_uri"), 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">
|
||||
* 交易保障</a>
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public XmlResult reportInterface(String interfaceUrl, int executeTime,
|
||||
String outTradeNo, String ip, Date time, XmlResult returnXml)
|
||||
throws WeixinException {
|
||||
Map<String, String> map = createBaseRequestMap(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));
|
||||
map.put("sign", weixinSignature.sign(map));
|
||||
String param = XmlStream.map2xml(map);
|
||||
WeixinResponse response = weixinExecutor.post(
|
||||
getRequestUri("interface_report_uri"), param);
|
||||
return response.getAsXml();
|
||||
}
|
||||
|
||||
/**
|
||||
* 授权码查询OPENID接口
|
||||
*
|
||||
* @param authCode
|
||||
* 扫码支付授权码,设备读取用户微信中的条码或者二维码信息
|
||||
* @return 查询结果
|
||||
* @see OpenIdResult
|
||||
* @see <a href=
|
||||
* "https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_13&index=9">
|
||||
* 授权码查询OPENID</a>
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public OpenIdResult authCode2openId(String authCode) throws WeixinException {
|
||||
Map<String, String> map = createBaseRequestMap(null);
|
||||
map.put("auth_code", authCode);
|
||||
map.put("sign", weixinSignature.sign(map));
|
||||
String param = XmlStream.map2xml(map);
|
||||
WeixinResponse response = weixinExecutor.post(
|
||||
getRequestUri("authcode_openid_uri"), param);
|
||||
return response.getAsObject(new TypeReference<OpenIdResult>() {
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,190 @@
|
||||
package com.foxinmy.weixin4j.pay.model;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONCreator;
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.foxinmy.weixin4j.model.WeixinAccount;
|
||||
import com.foxinmy.weixin4j.util.StringUtil;
|
||||
|
||||
/**
|
||||
* 微信支付账户
|
||||
*
|
||||
* @className WeixinPayAccount
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2015年6月26日
|
||||
* @since JDK 1.6
|
||||
* @see
|
||||
*/
|
||||
public class WeixinPayAccount extends WeixinAccount {
|
||||
|
||||
private static final long serialVersionUID = -2791256176906048632L;
|
||||
/**
|
||||
* 公众号支付请求中用于加密的密钥
|
||||
*/
|
||||
private final String paySignKey;
|
||||
/**
|
||||
* 微信支付分配的商户号
|
||||
*/
|
||||
private final String mchId;
|
||||
/**
|
||||
* 加载支付证书文件的密码(默认为商户号)
|
||||
*/
|
||||
private String certificateKey;
|
||||
/**
|
||||
* 商户证书文件(默认加载classpath:ca.p12)
|
||||
*/
|
||||
private String certificateFile;
|
||||
/**
|
||||
* 微信支付分配的设备号
|
||||
*/
|
||||
private String deviceInfo;
|
||||
/**
|
||||
* 财付通商户身份的标识
|
||||
*/
|
||||
private String partnerId;
|
||||
|
||||
/**
|
||||
* 微信分配的子商户公众账号ID
|
||||
*/
|
||||
private String subId;
|
||||
/**
|
||||
* 微信支付分配的子商户号
|
||||
*/
|
||||
private String subMchId;
|
||||
|
||||
/**
|
||||
* 支付商户信息
|
||||
*
|
||||
* @param id
|
||||
* 公众号唯一的身份ID(必填)
|
||||
* @param paySignKey
|
||||
* 支付密钥字符串(必填)
|
||||
* @param mchId
|
||||
* 微信支付分配的商户号(必填)
|
||||
*/
|
||||
public WeixinPayAccount(String id, String paySignKey, String mchId) {
|
||||
this(id, paySignKey, mchId, mchId, "classpath:ca.p12");
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付商户信息
|
||||
*
|
||||
* @param id
|
||||
* 公众号唯一的身份ID(必填)
|
||||
* @param paySignKey
|
||||
* 支付密钥字符串(必填)
|
||||
* @param mchId
|
||||
* 微信支付分配的商户号(必填)
|
||||
* @param certificateKey
|
||||
* 加载支付证书文件的密码(默认为商户号)
|
||||
* @param certificateFile
|
||||
* 商户证书文件(默认加载classpath:ca.p12)
|
||||
*/
|
||||
public WeixinPayAccount(String id, String paySignKey, String mchId, String certificateKey, String certificateFile) {
|
||||
this(id, null, paySignKey, mchId, certificateKey, certificateFile, null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付商户信息
|
||||
*
|
||||
* @param id
|
||||
* 公众号唯一的身份ID(必填)
|
||||
* @param secret
|
||||
* 公众号调用接口的凭证(最好填写)
|
||||
* @param paySignKey
|
||||
* 支付密钥字符串(必填)
|
||||
* @param mchId
|
||||
* 微信支付分配的商户号(必填)
|
||||
* @param certificateKey
|
||||
* 加载支付证书文件的密码(默认为商户号)
|
||||
* @param certificateFile
|
||||
* 商户证书文件(默认加载classpath:ca.p12)
|
||||
* @param deviceInfo
|
||||
* 微信支付分配的设备号(非必填)
|
||||
* @param partnerId
|
||||
* 财付通的商户号(非必填)
|
||||
* @param subId
|
||||
* 微信分配的子商户公众账号ID(非必填)
|
||||
* @param subMchId
|
||||
* 微信支付分配的子商户号(非必填)
|
||||
*/
|
||||
@JSONCreator
|
||||
public WeixinPayAccount(@JSONField(name = "id") String id, @JSONField(name = "secret") String secret,
|
||||
@JSONField(name = "paySignKey") String paySignKey, @JSONField(name = "mchId") String mchId,
|
||||
@JSONField(name = "certificateKey") String certificateKey,
|
||||
@JSONField(name = "certificateFile") String certificateFile,
|
||||
@JSONField(name = "deviceInfo") String deviceInfo, @JSONField(name = "partnerId") String partnerId,
|
||||
@JSONField(name = "subId") String subId, @JSONField(name = "subMchId") String subMchId) {
|
||||
super(id, secret);
|
||||
this.paySignKey = paySignKey;
|
||||
this.mchId = mchId;
|
||||
this.certificateKey = certificateKey;
|
||||
this.certificateFile = certificateFile;
|
||||
this.deviceInfo = deviceInfo;
|
||||
this.partnerId = partnerId;
|
||||
this.subId = subId;
|
||||
this.subMchId = subMchId;
|
||||
}
|
||||
|
||||
public String getPaySignKey() {
|
||||
return paySignKey;
|
||||
}
|
||||
|
||||
public String getMchId() {
|
||||
return mchId;
|
||||
}
|
||||
|
||||
public String getDeviceInfo() {
|
||||
return deviceInfo;
|
||||
}
|
||||
|
||||
public String getCertificateKey() {
|
||||
return StringUtil.isBlank(certificateKey) ? mchId : certificateKey;
|
||||
}
|
||||
|
||||
public String getPartnerId() {
|
||||
return partnerId;
|
||||
}
|
||||
|
||||
public String getSubId() {
|
||||
return subId;
|
||||
}
|
||||
|
||||
public String getSubMchId() {
|
||||
return subMchId;
|
||||
}
|
||||
|
||||
public void setCertificateKey(String certificateKey) {
|
||||
this.certificateKey = certificateKey;
|
||||
}
|
||||
|
||||
public String getCertificateFile() {
|
||||
return certificateFile;
|
||||
}
|
||||
|
||||
public void setCertificateFile(String certificateFile) {
|
||||
this.certificateFile = certificateFile;
|
||||
}
|
||||
|
||||
public void setDeviceInfo(String deviceInfo) {
|
||||
this.deviceInfo = deviceInfo;
|
||||
}
|
||||
|
||||
public void setPartnerId(String partnerId) {
|
||||
this.partnerId = partnerId;
|
||||
}
|
||||
|
||||
public void setSubId(String subId) {
|
||||
this.subId = subId;
|
||||
}
|
||||
|
||||
public void setSubMchId(String subMchId) {
|
||||
this.subMchId = subMchId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "WeixinPayAccount [" + super.toString() + ", paySignKey=" + paySignKey + ", mchId=" + mchId
|
||||
+ ", certificateKey=" + certificateKey + ",certificateFile =" + certificateFile + ", deviceInfo="
|
||||
+ deviceInfo + ", partnerId=" + partnerId + ", subId=" + subId + ", subMchId=" + subMchId + "]";
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,60 @@
|
||||
package com.foxinmy.weixin4j.pay.payment;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
/**
|
||||
* JSAPI支付回调时的POST信息
|
||||
*
|
||||
* @className JsPayNotify
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2014年8月19日
|
||||
* @since JDK 1.6
|
||||
* @see
|
||||
*/
|
||||
@XmlRootElement
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class JsPayNotify extends PayBaseInfo {
|
||||
|
||||
private static final long serialVersionUID = -4659030958445259803L;
|
||||
|
||||
/**
|
||||
* 用户的openid
|
||||
*/
|
||||
@JSONField(name = "OpenId")
|
||||
@XmlElement(name = "OpenId")
|
||||
private String openId;
|
||||
/**
|
||||
* 是否关注公众号
|
||||
*/
|
||||
@JSONField(name = "IsSubscribe")
|
||||
@XmlElement(name = "IsSubscribe")
|
||||
private int isSubscribe;
|
||||
|
||||
public JsPayNotify() {
|
||||
|
||||
}
|
||||
|
||||
public String getOpenId() {
|
||||
return openId;
|
||||
}
|
||||
|
||||
public int getIsSubscribe() {
|
||||
return isSubscribe;
|
||||
}
|
||||
|
||||
@JSONField(serialize = false)
|
||||
public boolean getFormatIsSubscribe() {
|
||||
return isSubscribe == 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "openId=" + openId + ", isSubscribe=" + getFormatIsSubscribe()
|
||||
+ ", " + super.toString();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,116 @@
|
||||
package com.foxinmy.weixin4j.pay.payment;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.foxinmy.weixin4j.pay.type.SignType;
|
||||
|
||||
import javax.xml.bind.annotation.*;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 基本信息
|
||||
*
|
||||
* @className PayBaseInfo
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2014年11月5日
|
||||
* @since JDK 1.6
|
||||
* @see
|
||||
*/
|
||||
@XmlRootElement
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class PayBaseInfo implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1843024880782466990L;
|
||||
|
||||
/**
|
||||
* 公众号ID
|
||||
*/
|
||||
@JSONField(name = "appId")
|
||||
@XmlElement(name = "AppId")
|
||||
private String appId;
|
||||
/**
|
||||
* 时间戳
|
||||
*/
|
||||
@JSONField(name = "timeStamp")
|
||||
@XmlElement(name = "TimeStamp")
|
||||
private String timeStamp;
|
||||
/**
|
||||
* 随机字符串
|
||||
*/
|
||||
@JSONField(name = "nonceStr")
|
||||
@XmlElement(name = "NonceStr")
|
||||
private String nonceStr;
|
||||
/**
|
||||
* 签名结果
|
||||
*/
|
||||
@JSONField(name = "paySign")
|
||||
@XmlElement(name = "AppSignature")
|
||||
private String paySign;
|
||||
/**
|
||||
* 签名方式
|
||||
*/
|
||||
@JSONField(name = "signType")
|
||||
@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;
|
||||
}
|
||||
|
||||
@XmlTransient
|
||||
@JSONField(serialize = false)
|
||||
public SignType getFormatSignType() {
|
||||
return signType != null ? SignType.valueOf(signType.toUpperCase())
|
||||
: null;
|
||||
}
|
||||
|
||||
public void setSignType(SignType signType) {
|
||||
this.signType = signType != null ? signType.name() : 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,284 @@
|
||||
package com.foxinmy.weixin4j.pay.payment;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.foxinmy.weixin4j.pay.payment.mch.MerchantResult;
|
||||
import com.foxinmy.weixin4j.util.DateUtil;
|
||||
|
||||
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 java.util.Date;
|
||||
|
||||
/**
|
||||
* 订单信息
|
||||
*
|
||||
* @className PayPackage
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2014年12月18日
|
||||
* @since JDK 1.6
|
||||
*/
|
||||
@XmlRootElement
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class PayPackage extends MerchantResult {
|
||||
|
||||
private static final long serialVersionUID = 3450161267802545790L;
|
||||
|
||||
/**
|
||||
* 商品描述 必须
|
||||
*/
|
||||
private String body;
|
||||
/**
|
||||
* 商品详情 非必须
|
||||
*/
|
||||
private String detail;
|
||||
/**
|
||||
* 商户系统内部的订单号 ,32 个字符内 、可包含字母 ,确保 在商户系统唯一 必须
|
||||
*/
|
||||
@XmlElement(name = "out_trade_no")
|
||||
@JSONField(name = "out_trade_no")
|
||||
private String outTradeNo;
|
||||
/**
|
||||
* 订单总金额,单位为分,不能带小数点 必须
|
||||
*/
|
||||
@XmlElement(name = "total_fee")
|
||||
@JSONField(name = "total_fee")
|
||||
private int totalFee;
|
||||
/**
|
||||
* 通知地址接收微信支付成功通知 必须
|
||||
*/
|
||||
@XmlElement(name = "notify_url")
|
||||
@JSONField(name = "notify_url")
|
||||
private String notifyUrl;
|
||||
/**
|
||||
* 订单生成的机器 IP 必须
|
||||
*/
|
||||
@XmlElement(name = "spbill_create_ip")
|
||||
@JSONField(name = "spbill_create_ip")
|
||||
private String createIp;
|
||||
/**
|
||||
* 附加数据,原样返回 非必须
|
||||
*/
|
||||
private String attach;
|
||||
/**
|
||||
* 订单生成时间,格式为 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;
|
||||
|
||||
protected PayPackage() {
|
||||
// jaxb required
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单对象
|
||||
*
|
||||
* @param body
|
||||
* 订单描述 必填
|
||||
* @param detail
|
||||
* 订单详情 非必填
|
||||
* @param outTradeNo
|
||||
* 商户内部ID 必填
|
||||
* @param totalFee
|
||||
* 订单总额 必填 <font color="red">单位为元</font>
|
||||
* @param notifyUrl
|
||||
* 回调地址 必填
|
||||
* @param createIp
|
||||
* 生成订单数据的机器IP 必填
|
||||
* @param attach
|
||||
* 附加数据 非必填
|
||||
* @param timeStart
|
||||
* 订单生成时间 非必填
|
||||
* @param timeExpire
|
||||
* 订单失效时间 非必填
|
||||
* @param goodsTag
|
||||
* 订单标记 非必填
|
||||
*/
|
||||
public PayPackage(String body, String detail, String outTradeNo,
|
||||
double totalFee, String notifyUrl, String createIp, String attach,
|
||||
Date timeStart, Date timeExpire, String goodsTag) {
|
||||
this.body = body;
|
||||
this.detail = detail;
|
||||
this.outTradeNo = outTradeNo;
|
||||
this.totalFee = DateUtil.formatYuan2Fen(totalFee);
|
||||
this.notifyUrl = notifyUrl;
|
||||
this.createIp = createIp;
|
||||
this.attach = attach;
|
||||
this.timeStart = timeStart != null ? DateUtil
|
||||
.fortmat2yyyyMMddHHmmss(timeStart) : null;
|
||||
this.timeExpire = timeExpire != null ? DateUtil
|
||||
.fortmat2yyyyMMddHHmmss(timeExpire) : null;
|
||||
this.goodsTag = goodsTag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单对象
|
||||
*
|
||||
* @param body
|
||||
* 订单描述 必填
|
||||
* @param detail
|
||||
* 订单详情 非必填
|
||||
* @param outTradeNo
|
||||
* 商户内部ID 必填
|
||||
* @param totalFee
|
||||
* 订单总额 必填 <font color="red">单位为分</font>
|
||||
* @param notifyUrl
|
||||
* 回调地址 必填
|
||||
* @param createIp
|
||||
* 生成订单数据的机器IP 必填
|
||||
* @param attach
|
||||
* 附加数据 非必填
|
||||
* @param timeStart
|
||||
* 订单生成时间 非必填
|
||||
* @param timeExpire
|
||||
* 订单失效时间 非必填
|
||||
* @param goodsTag
|
||||
* 订单标记 非必填
|
||||
*/
|
||||
public PayPackage(String body, String detail, String outTradeNo,
|
||||
long totalFee, String notifyUrl, String createIp, String attach,
|
||||
Date timeStart, Date timeExpire, String goodsTag) {
|
||||
this.body = body;
|
||||
this.detail = detail;
|
||||
this.outTradeNo = outTradeNo;
|
||||
this.totalFee = Long.valueOf(totalFee).intValue();
|
||||
this.notifyUrl = notifyUrl;
|
||||
this.createIp = createIp;
|
||||
this.attach = attach;
|
||||
this.timeStart = timeStart != null ? DateUtil
|
||||
.fortmat2yyyyMMddHHmmss(timeStart) : null;
|
||||
this.timeExpire = timeExpire != null ? DateUtil
|
||||
.fortmat2yyyyMMddHHmmss(timeExpire) : null;
|
||||
this.goodsTag = goodsTag;
|
||||
}
|
||||
|
||||
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 getOutTradeNo() {
|
||||
return outTradeNo;
|
||||
}
|
||||
|
||||
public void setOutTradeNo(String outTradeNo) {
|
||||
this.outTradeNo = outTradeNo;
|
||||
}
|
||||
|
||||
public int getTotalFee() {
|
||||
return totalFee;
|
||||
}
|
||||
|
||||
/**
|
||||
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
|
||||
*
|
||||
* @return 元单位
|
||||
*/
|
||||
@JSONField(serialize = false)
|
||||
public double getFormatTotalFee() {
|
||||
return totalFee / 100d;
|
||||
}
|
||||
|
||||
/**
|
||||
* <font color="red">单位为元,自动格式化为分</font>
|
||||
*
|
||||
* @param totalFee
|
||||
* 订单总额 单位为元
|
||||
*/
|
||||
public void setTotalFee(double totalFee) {
|
||||
this.totalFee = DateUtil.formatYuan2Fen(totalFee);
|
||||
}
|
||||
|
||||
public String getNotifyUrl() {
|
||||
return notifyUrl;
|
||||
}
|
||||
|
||||
public void setNotifyUrl(String notifyUrl) {
|
||||
this.notifyUrl = notifyUrl;
|
||||
}
|
||||
|
||||
public String getCreateIp() {
|
||||
return createIp;
|
||||
}
|
||||
|
||||
public void setCreateIp(String createIp) {
|
||||
this.createIp = createIp;
|
||||
}
|
||||
|
||||
public String getAttach() {
|
||||
return attach;
|
||||
}
|
||||
|
||||
public void setAttach(String attach) {
|
||||
this.attach = attach;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "body=" + body + ", detail=" + detail + ", outTradeNo="
|
||||
+ outTradeNo + ", totalFee=" + totalFee + ", notifyUrl="
|
||||
+ notifyUrl + ", createIp=" + createIp + ", attach=" + attach
|
||||
+ ", timeStart=" + timeStart + ", timeExpire=" + timeExpire
|
||||
+ ", goodsTag=" + goodsTag;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,75 @@
|
||||
package com.foxinmy.weixin4j.pay.payment;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.foxinmy.weixin4j.util.DateUtil;
|
||||
import com.foxinmy.weixin4j.util.RandomUtil;
|
||||
|
||||
import javax.xml.bind.annotation.*;
|
||||
|
||||
@XmlRootElement
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class PayRequest extends PayBaseInfo {
|
||||
|
||||
private static final long serialVersionUID = -453746488398523883L;
|
||||
|
||||
/**
|
||||
* 订单详情扩展 订单信息组成该字符串
|
||||
*/
|
||||
@XmlElement(name = "Package")
|
||||
@JSONField(name = "package")
|
||||
private String packageInfo;
|
||||
|
||||
/**
|
||||
* 冗余字段
|
||||
*/
|
||||
@XmlTransient
|
||||
@JSONField(serialize = false)
|
||||
private String prepayId;
|
||||
/**
|
||||
* 冗余字段
|
||||
*/
|
||||
@XmlTransient
|
||||
@JSONField(serialize = false)
|
||||
private String partnerId;
|
||||
|
||||
|
||||
protected PayRequest() {
|
||||
// jaxb required
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public String getPrepayId() {
|
||||
return prepayId;
|
||||
}
|
||||
|
||||
public void setPrepayId(String prepayId) {
|
||||
this.prepayId = prepayId;
|
||||
}
|
||||
|
||||
public String getPartnerId() {
|
||||
return partnerId;
|
||||
}
|
||||
|
||||
public void setPartnerId(String partnerId) {
|
||||
this.partnerId = partnerId;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "package" + packageInfo + ", prepayId=" + prepayId
|
||||
+ super.toString();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
支付模块【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版本(商户平台)`支付**
|
||||
|
||||
|
||||
[WeixinPayProxy](WeixinPayProxy.java)
|
||||
-------------------------
|
||||
|
||||
* createPayJsRequestJson: 创建V3版本(商户平台)的JSAPI支付串
|
||||
|
||||
* createNativePayRequestURL: 创建V3版本(商户平台)的扫码支付链接
|
||||
|
||||
* createPrePay: 调用V3版本(商户平台)的统一订单接口生成预订单数据
|
||||
|
||||
* createMicroPay: 创建刷卡支付(商户平台)请求
|
||||
|
||||
* orderQuery: 订单查询接口
|
||||
|
||||
* refundOrder: 退款申请接口
|
||||
|
||||
* reverseOrder: 冲正订单接口
|
||||
|
||||
* closeOrder: 关闭订单接口
|
||||
|
||||
* downloadBill: 下载对账单接口
|
||||
|
||||
* refundQuery: 退款查询接口
|
||||
|
||||
|
||||
[Pay2Api](https://github.com/foxinmy/weixin4j/blob/master/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/Pay2Api.java)
|
||||
-------------------------
|
||||
|
||||
* createPayJsRequestJson: 创建V2版本的JSAPI支付串
|
||||
|
||||
* createNativePayRequestURL: 创建V2版本的扫码支付链接
|
||||
|
||||
* orderQuery: 订单查询接口
|
||||
|
||||
* refundOrder: 退款申请接口
|
||||
|
||||
* downloadBill: 下载对账单接口
|
||||
|
||||
* refundQuery: 退款查询接口
|
||||
@ -0,0 +1,827 @@
|
||||
package com.foxinmy.weixin4j.pay.payment;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.foxinmy.weixin4j.api.CashApi;
|
||||
import com.foxinmy.weixin4j.api.CouponApi;
|
||||
import com.foxinmy.weixin4j.api.CustomsApi;
|
||||
import com.foxinmy.weixin4j.api.PayApi;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.http.weixin.XmlResult;
|
||||
import com.foxinmy.weixin4j.model.WeixinPayAccount;
|
||||
import com.foxinmy.weixin4j.model.paging.Pageable;
|
||||
import com.foxinmy.weixin4j.pay.payment.coupon.CouponDetail;
|
||||
import com.foxinmy.weixin4j.pay.payment.coupon.CouponResult;
|
||||
import com.foxinmy.weixin4j.pay.payment.coupon.CouponStock;
|
||||
import com.foxinmy.weixin4j.pay.payment.mch.*;
|
||||
import com.foxinmy.weixin4j.sign.WeixinSignature;
|
||||
import com.foxinmy.weixin4j.type.CurrencyType;
|
||||
import com.foxinmy.weixin4j.type.CustomsCity;
|
||||
import com.foxinmy.weixin4j.type.IdQuery;
|
||||
import com.foxinmy.weixin4j.type.TarType;
|
||||
import com.foxinmy.weixin4j.type.mch.BillType;
|
||||
import com.foxinmy.weixin4j.type.mch.RefundAccountType;
|
||||
import com.foxinmy.weixin4j.util.Consts;
|
||||
import com.foxinmy.weixin4j.util.Weixin4jConfigUtil;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
/**
|
||||
* 微信支付接口实现
|
||||
*
|
||||
* @className WeixinPayProxy
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2015年1月3日
|
||||
* @since JDK 1.6
|
||||
* @see <a href="http://pay.weixin.qq.com/wiki/doc/api/index.html">商户平台支付API</a>
|
||||
*/
|
||||
public class WeixinPayProxy {
|
||||
|
||||
/**
|
||||
* 微信支付API:js支付、扫码支付等接口
|
||||
*/
|
||||
private final PayApi payApi;
|
||||
/**
|
||||
* 代金券API
|
||||
*/
|
||||
private final CouponApi couponApi;
|
||||
/**
|
||||
* 现金API
|
||||
*/
|
||||
private final CashApi cashApi;
|
||||
/**
|
||||
* 海关API
|
||||
*/
|
||||
private final CustomsApi customsApi;
|
||||
/**
|
||||
* 商户信息
|
||||
*/
|
||||
private final WeixinPayAccount weixinPayAccount;
|
||||
|
||||
/**
|
||||
* 微信支付接口实现(使用weixin4j.properties配置的account商户信息)
|
||||
*/
|
||||
public WeixinPayProxy() {
|
||||
this(JSON.parseObject(Weixin4jConfigUtil.getValue("account"),
|
||||
WeixinPayAccount.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信支付接口实现
|
||||
*
|
||||
* @param weixinPayAccount
|
||||
* 微信商户信息
|
||||
*/
|
||||
public WeixinPayProxy(WeixinPayAccount weixinPayAccount) {
|
||||
if (weixinPayAccount == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"weixinPayAccount must not be empty");
|
||||
}
|
||||
this.weixinPayAccount = weixinPayAccount;
|
||||
this.payApi = new PayApi(weixinPayAccount);
|
||||
this.couponApi = new CouponApi(weixinPayAccount);
|
||||
this.cashApi = new CashApi(weixinPayAccount);
|
||||
this.customsApi = new CustomsApi(weixinPayAccount);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取微信商户账号信息
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public WeixinPayAccount getWeixinPayAccount() {
|
||||
return weixinPayAccount;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取微信签名类
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public WeixinSignature getWeixinSignature() {
|
||||
return payApi.getWeixinSignature();
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一下单接口</br>
|
||||
* 除被扫支付场景以外,商户系统先调用该接口在微信支付服务后台生成预支付交易单,返回正确的预支付交易回话标识后再按扫码、JSAPI
|
||||
* 、APP等不同场景生成交易串调起支付。
|
||||
*
|
||||
* @param payPackage
|
||||
* 包含订单信息的对象
|
||||
* @see PayApi
|
||||
* @see MchPayPackage
|
||||
* @see PrePay
|
||||
* @see <a href=
|
||||
* "http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1">统一下单接口
|
||||
* </a>
|
||||
* @return 预支付对象
|
||||
*/
|
||||
public PrePay createPrePay(MchPayPackage payPackage) throws WeixinException {
|
||||
return payApi.createPrePay(payPackage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建支付请求对象
|
||||
*
|
||||
* @param payPackage
|
||||
* 支付详情
|
||||
* @return 支付请求对象
|
||||
* @see PayApi
|
||||
* @see JSAPIPayRequest JS支付
|
||||
* @see NATIVEPayRequest 扫码支付
|
||||
* @see MICROPayRequest 刷卡支付
|
||||
* @see APPPayRequest APP支付
|
||||
* @see WAPPayRequest WAP支付
|
||||
* @see MchPayRequest#toRequestString()
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public MchPayRequest createPayRequest(MchPayPackage payPackage)
|
||||
throws WeixinException {
|
||||
return payApi.createPayRequest(payPackage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建JSAPI支付请求对象
|
||||
*
|
||||
* @param openId
|
||||
* 用户ID
|
||||
* @param body
|
||||
* 订单描述
|
||||
* @param outTradeNo
|
||||
* 订单号
|
||||
* @param totalFee
|
||||
* 订单总额(元)
|
||||
* @param notifyUrl
|
||||
* 支付通知地址
|
||||
* @param createIp
|
||||
* ip地址
|
||||
* @param attach
|
||||
* 附加数据 非必填
|
||||
* @see PayApi
|
||||
* @see JSAPIPayRequest
|
||||
* @see MchPayRequest#toRequestString()
|
||||
* @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);
|
||||
}
|
||||
|
||||
/**
|
||||
* <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 url
|
||||
* 当前访问页的URL
|
||||
* @param oauthToken
|
||||
* oauth授权时产生的token
|
||||
* @see PayApi
|
||||
* @see <a href=
|
||||
* "https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_8&index=7">
|
||||
* 收货地址共享</a>
|
||||
* @return 编辑地址请求JSON串
|
||||
*/
|
||||
public String createAddressRequestJSON(String url, String oauthToken) {
|
||||
return payApi.createAddressRequestJSON(url, oauthToken);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建Native支付(扫码支付)链接【模式一】
|
||||
*
|
||||
* @param productId
|
||||
* 与订单ID等价
|
||||
* @return 支付链接
|
||||
* @see PayApi
|
||||
* @see <a href=
|
||||
* "https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_1">扫码支付
|
||||
* </a>
|
||||
* @see <a href=
|
||||
* "https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_4">模式一
|
||||
* </a>
|
||||
*/
|
||||
public String createNativePayRequest(String productId) {
|
||||
return payApi.createNativePayRequest(productId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建Native支付(扫码支付)回调对象【模式一】
|
||||
*
|
||||
* @param productId
|
||||
* 商品ID
|
||||
* @param body
|
||||
* 商品描述
|
||||
* @param outTradeNo
|
||||
* 商户内部唯一订单号
|
||||
* @param totalFee
|
||||
* 商品总额 单位元
|
||||
* @param notifyUrl
|
||||
* 支付回调URL
|
||||
* @param createIp
|
||||
* 订单生成的机器 IP
|
||||
* @param attach
|
||||
* 附加数据 非必填
|
||||
* @return Native回调对象
|
||||
* @see PayApi
|
||||
* @see NativePayResponse
|
||||
* @see <a href=
|
||||
* "https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_1">扫码支付
|
||||
* </a>
|
||||
* @see <a href=
|
||||
* "https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_4">模式一
|
||||
* </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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建Native支付(扫码支付)链接【模式二】
|
||||
*
|
||||
* @param productId
|
||||
* 商品ID
|
||||
* @param body
|
||||
* 商品描述
|
||||
* @param outTradeNo
|
||||
* 商户内部唯一订单号
|
||||
* @param totalFee
|
||||
* 商品总额 单位元
|
||||
* @param notifyUrl
|
||||
* 支付回调URL
|
||||
* @param createIp
|
||||
* 订单生成的机器 IP
|
||||
* @param attach
|
||||
* 附加数据 非必填
|
||||
* @return Native支付对象
|
||||
* @see PayApi
|
||||
* @see NATIVEPayRequest
|
||||
* @see MchPayRequest#toRequestString()
|
||||
* @see <a href=
|
||||
* "https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_1">扫码支付
|
||||
* </a>
|
||||
* @see <a href=
|
||||
* "https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_5">模式二
|
||||
* </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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建APP支付请求对象
|
||||
*
|
||||
* @param body
|
||||
* 商品描述
|
||||
* @param outTradeNo
|
||||
* 商户内部唯一订单号
|
||||
* @param totalFee
|
||||
* 商品总额 单位元
|
||||
* @param notifyUrl
|
||||
* 支付回调URL
|
||||
* @param createIp
|
||||
* 订单生成的机器 IP
|
||||
* @param attach
|
||||
* 附加数据 非必填
|
||||
* @param store
|
||||
* 门店信息 非必填
|
||||
* @return APP支付对象
|
||||
* @see PayApi
|
||||
* @see SceneInfoStore
|
||||
* @see APPPayRequest
|
||||
* @see MchPayRequest#toRequestString()
|
||||
* @see <a href=
|
||||
* "https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_1">
|
||||
* APP支付</a>
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public MchPayRequest createAppPayRequest(String body, String outTradeNo,
|
||||
double totalFee, String notifyUrl, String createIp, String attach,
|
||||
SceneInfoStore store) throws WeixinException {
|
||||
return payApi.createAppPayRequest(body, outTradeNo, totalFee,
|
||||
notifyUrl, createIp, attach, store);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建WAP支付请求对象
|
||||
*
|
||||
* @param body
|
||||
* 商品描述
|
||||
* @param outTradeNo
|
||||
* 商户内部唯一订单号
|
||||
* @param totalFee
|
||||
* 商品总额 单位元
|
||||
* @param notifyUrl
|
||||
* 支付回调URL
|
||||
* @param createIp
|
||||
* 订单生成的机器 IP
|
||||
* @param attach
|
||||
* 附加数据 非必填
|
||||
* @param app
|
||||
* 应用信息
|
||||
* @return WAP支付对象
|
||||
* @see PayApi
|
||||
* @see SceneInfoApp
|
||||
* @see WAPPayRequest
|
||||
* @see MchPayRequest#toRequestString()
|
||||
* @see <a href=
|
||||
* "https://pay.weixin.qq.com/wiki/doc/api/wap.php?chapter=15_1">WAP支付
|
||||
* </a>
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public MchPayRequest createWapPayRequest(String body, String outTradeNo,
|
||||
double totalFee, String notifyUrl, String createIp, String attach,
|
||||
SceneInfoApp app) throws WeixinException {
|
||||
return payApi.createWapPayRequest(body, outTradeNo, totalFee,
|
||||
notifyUrl, createIp, attach, app);
|
||||
}
|
||||
|
||||
/**
|
||||
* 提交被扫支付
|
||||
*
|
||||
* @param authCode
|
||||
* 扫码支付授权码 ,设备读取用户微信中的条码或者二维码信息
|
||||
* @param body
|
||||
* 商品描述
|
||||
* @param outTradeNo
|
||||
* 商户内部唯一订单号
|
||||
* @param totalFee
|
||||
* 商品总额 单位元
|
||||
* @param createIp
|
||||
* 订单生成的机器 IP
|
||||
* @param attach
|
||||
* 附加数据 非必填
|
||||
* @param store
|
||||
* 门店信息 非必填
|
||||
* @return 支付的订单信息
|
||||
* @see PayApi
|
||||
* @see Order
|
||||
* @see SceneInfoStore
|
||||
* @see MICROPayRequest
|
||||
* @see MchPayRequest#toRequestString()
|
||||
* @see <a href=
|
||||
* "http://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_10">
|
||||
* 提交被扫支付API</a>
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public MchPayRequest createMicroPayRequest(String authCode, String body,
|
||||
String outTradeNo, double totalFee, String createIp, String attach,
|
||||
SceneInfoStore store) throws WeixinException {
|
||||
return payApi.createMicroPayRequest(authCode, body, outTradeNo,
|
||||
totalFee, createIp, attach, store);
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单查询
|
||||
* <p>
|
||||
* 当商户后台、网络、服务器等出现异常,商户系统最终未接收到支付通知;</br> 调用支付接口后,返回系统错误或未知交易状态情况;</br>
|
||||
* 调用被扫支付API,返回USERPAYING的状态;</br> 调用关单或撤销接口API之前,需确认支付状态;
|
||||
* </P>
|
||||
*
|
||||
* @param idQuery
|
||||
* 商户系统内部的订单号, transaction_id、out_trade_no 二 选一,如果同时存在优先级:
|
||||
* transaction_id> out_trade_no
|
||||
* @since V3
|
||||
* @see Order
|
||||
* @see PayApi
|
||||
* @see <a href=
|
||||
* "http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_2">
|
||||
* 订单查询API</a>
|
||||
* @return 订单详情
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public Order queryOrder(IdQuery idQuery) throws WeixinException {
|
||||
return payApi.queryOrder(idQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 申请退款
|
||||
*
|
||||
* @see PayApi#applyRefund(IdQuery, String, double, double, CurrencyType, String, String, RefundAccountType)
|
||||
*/
|
||||
public RefundResult applyRefund(IdQuery idQuery, String outRefundNo,
|
||||
double totalFee, double refundFee, CurrencyType refundFeeType,
|
||||
String opUserId, String refundDesc,
|
||||
RefundAccountType refundAccountType) throws WeixinException {
|
||||
return payApi.applyRefund(idQuery, outRefundNo, totalFee, refundFee,
|
||||
refundFeeType, opUserId, refundDesc, refundAccountType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 申请退款
|
||||
*
|
||||
* @see PayApi#applyRefund(IdQuery, String, double)
|
||||
*/
|
||||
public RefundResult applyRefund(IdQuery idQuery, String outRefundNo,
|
||||
double totalFee) throws WeixinException {
|
||||
return payApi.applyRefund(idQuery, outRefundNo, totalFee);
|
||||
}
|
||||
|
||||
/**
|
||||
* 退款查询
|
||||
* <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 PayApi
|
||||
* @see 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 queryRefund(IdQuery idQuery) throws WeixinException {
|
||||
return payApi.queryRefund(idQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载对账单<br>
|
||||
* 1.微信侧未成功下单的交易不会出现在对账单中。支付成功后撤销的交易会出现在对账 单中,跟原支付单订单号一致,bill_type 为
|
||||
* REVOKED;<br>
|
||||
* 2.微信在次日 9 点启动生成前一天的对账单,建议商户 9 点半后再获取;<br>
|
||||
* 3.对账单中涉及金额的字段单位为“元”。<br>
|
||||
*
|
||||
* @param billDate
|
||||
* 下载对账单的日期
|
||||
* @param billType
|
||||
* 下载对账单的类型 ALL,返回当日所有订单信息, 默认值 SUCCESS,返回当日成功支付的订单
|
||||
* REFUND,返回当日退款订单
|
||||
* @para outputStream 输出流
|
||||
* @param tarType
|
||||
* 非必传参数,固定值:GZIP,返回格式为.gzip的压缩包账单。不传则默认为数据流形式。
|
||||
* @since V2 & V3
|
||||
* @see PayApi
|
||||
* @see <a href=
|
||||
* "http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_6">
|
||||
* 下载对账单API</a>
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public void downloadBill(Date billDate, BillType billType,
|
||||
OutputStream outputStream, TarType tarType) throws WeixinException {
|
||||
payApi.downloadBill(billDate, billType, outputStream, tarType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 冲正订单(需要证书)</br> 当支付返回失败,或收银系统超时需要取消交易,可以调用该接口</br> 接口逻辑:支
|
||||
* 付失败的关单,支付成功的撤销支付</br> <font color="red">7天以内的单可撤销,其他正常支付的单
|
||||
* 如需实现相同功能请调用退款接口</font></br> <font
|
||||
* color="red">调用扣款接口后请勿立即调用撤销,需要等待5秒以上。先调用查单接口,如果没有确切的返回,再调用撤销</font> </br>
|
||||
*
|
||||
* @param idQuery
|
||||
* 商户系统内部的订单号, transaction_id 、 out_trade_no 二选一,如果同时存在优先级:
|
||||
* transaction_id> out_trade_no
|
||||
* @return 撤销结果
|
||||
* @see PayApi
|
||||
* @since V3
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public MerchantResult reverseOrder(IdQuery idQuery) throws WeixinException {
|
||||
return payApi.reverseOrder(idQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭订单
|
||||
* <p>
|
||||
* 商户订单支付失败需要生成新单号重新发起支付,要对原订单号调用关单,避免重复支付;系统下单后,用户支付超时,系统退出不再受理,避免用户继续
|
||||
* ,请调用关单接口,如果关单失败,返回已完 成支付请按正常支付处理。如果出现银行掉单,调用关单成功后,微信后台会主动发起退款。
|
||||
* </p>
|
||||
*
|
||||
* @param outTradeNo
|
||||
* 商户系统内部的订单号
|
||||
* @return 执行结果
|
||||
* @see PayApi
|
||||
* @since V3
|
||||
* @throws WeixinException
|
||||
* @see <a href=
|
||||
* "http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_3">
|
||||
* 关闭订单API</a>
|
||||
*/
|
||||
public MerchantResult closeOrder(String outTradeNo) throws WeixinException {
|
||||
return payApi.closeOrder(outTradeNo);
|
||||
}
|
||||
|
||||
/**
|
||||
* native支付URL转短链接:用于扫码原生支付模式一中的二维码链接转成短链接(weixin://wxpay/s/XXXXXX),减小二维码数据量
|
||||
* ,提升扫描速度和精确度。
|
||||
*
|
||||
* @param url
|
||||
* 具有native标识的支付URL
|
||||
* @return 转换后的短链接
|
||||
* @see PayApi
|
||||
* @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 payApi.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 PayApi
|
||||
* @see <a href=
|
||||
* "http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_8">
|
||||
* 接口测试上报API</a>
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public XmlResult reportInterface(String interfaceUrl, int executeTime,
|
||||
String outTradeNo, String ip, Date time, XmlResult returnXml)
|
||||
throws WeixinException {
|
||||
return payApi.reportInterface(interfaceUrl, executeTime, outTradeNo,
|
||||
ip, time, returnXml);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发放代金券(需要证书)
|
||||
*
|
||||
* @param couponStockId
|
||||
* 代金券批次id
|
||||
* @param partnerTradeNo
|
||||
* 商户发放凭据号(格式:商户id+日期+流水号),商户侧需保持唯一性
|
||||
* @param openId
|
||||
* 用户的openid
|
||||
* @param opUserId
|
||||
* 操作员帐号, 默认为商户号 可在商户平台配置操作员对应的api权限 可为空
|
||||
* @return 发放结果
|
||||
* @see CouponApi
|
||||
* @see CouponResult
|
||||
* @see <a href=
|
||||
* "https://pay.weixin.qq.com/wiki/doc/api/tools/sp_coupon.php?chapter=12_3">
|
||||
* 发放代金券接口</a>
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public CouponResult sendCoupon(String couponStockId, String partnerTradeNo,
|
||||
String openId, String opUserId) throws WeixinException {
|
||||
return couponApi.sendCoupon(couponStockId, partnerTradeNo, openId,
|
||||
opUserId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询代金券批次
|
||||
*
|
||||
* @param couponStockId
|
||||
* 代金券批次ID
|
||||
* @return 代金券批次信息
|
||||
* @see CouponApi
|
||||
* @see CouponStock
|
||||
* @see <a href=
|
||||
* "https://pay.weixin.qq.com/wiki/doc/api/tools/sp_coupon.php?chapter=12_4">
|
||||
* 查询代金券批次信息接口</a>
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public CouponStock queryCouponStock(String couponStockId)
|
||||
throws WeixinException {
|
||||
return couponApi.queryCouponStock(couponStockId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询代金券详细
|
||||
*
|
||||
* @param openId
|
||||
* 用户ID
|
||||
* @param couponId
|
||||
* 代金券ID
|
||||
* @param stockId
|
||||
* 代金劵对应的批次号
|
||||
* @return 代金券详细信息
|
||||
* @see CouponApi
|
||||
* @see CouponDetail
|
||||
* @see <a href=
|
||||
* "https://pay.weixin.qq.com/wiki/doc/api/tools/sp_coupon.php?chapter=12_5">
|
||||
* 查询代金券详细信息接口</a>
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public CouponDetail queryCouponDetail(String openId, String couponId,
|
||||
String stockId) throws WeixinException {
|
||||
return couponApi.queryCouponDetail(openId, couponId, stockId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发放红包 企业向微信用户个人发现金红包
|
||||
*
|
||||
* @param redpacket
|
||||
* 红包信息
|
||||
* @return 发放结果
|
||||
* @see CashApi
|
||||
* @see Redpacket
|
||||
* @see RedpacketSendResult
|
||||
* @see <a href=
|
||||
* "https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_5">
|
||||
* 发放现金红包接口</a>
|
||||
* @see <a href=
|
||||
* "https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=16_5">
|
||||
* 发放裂变红包接口</a>
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public RedpacketSendResult sendRedpack(Redpacket redpacket)
|
||||
throws WeixinException {
|
||||
return cashApi.sendRedpack(redpacket);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量发放红包 企业向微信用户个人发现金红包
|
||||
*
|
||||
* @param redpacket
|
||||
* 多个红包信息
|
||||
* @return 发放结果
|
||||
* @see CashApi
|
||||
* @see #sendRedpacks(Redpacket...)
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public List<Future<RedpacketSendResult>> sendRedpacks(
|
||||
Redpacket... redpackets) {
|
||||
return cashApi.sendRedpacks(redpackets);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询红包记录
|
||||
*
|
||||
* @param outTradeNo
|
||||
* 商户发放红包的商户订单号
|
||||
* @return 红包记录
|
||||
* @see CashApi
|
||||
* @see RedpacketRecord
|
||||
* @see <a href=
|
||||
* "https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_7&index=6">
|
||||
* 查询现金红包接口</a>
|
||||
* @see <a href=
|
||||
* "https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=16_6">
|
||||
* 查询裂变红包接口</a>
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public RedpacketRecord queryRedpack(String outTradeNo)
|
||||
throws WeixinException {
|
||||
return cashApi.queryRedpack(outTradeNo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 企业付款
|
||||
*
|
||||
* @see CashApi#sendCorpPayment(CorpPayment)
|
||||
*/
|
||||
public CorpPaymentResult sendCorpPayment(CorpPayment payment)
|
||||
throws WeixinException {
|
||||
return cashApi.sendCorpPayment(payment);
|
||||
}
|
||||
|
||||
/**
|
||||
* 企业付款查询 用于商户的企业付款操作进行结果查询,返回付款操作详细结果
|
||||
*
|
||||
* @param outTradeNo
|
||||
* 商户调用企业付款API时使用的商户订单号
|
||||
* @return 付款记录
|
||||
* @see CashApi
|
||||
* @see CorpPaymentRecord
|
||||
* @see <a href=
|
||||
* "https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_3">
|
||||
* 企业付款查询接口</a>
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public CorpPaymentRecord queryCorpPayment(String outTradeNo)
|
||||
throws WeixinException {
|
||||
return cashApi.queryCorpPayment(outTradeNo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 授权码查询OPENID
|
||||
*
|
||||
* @param authCode
|
||||
* 扫码支付授权码,设备读取用户微信中的条码或者二维码信息
|
||||
* @return 查询结果
|
||||
* @see CashApi
|
||||
* @see OpenIdResult
|
||||
* @see <a href=
|
||||
* "https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_13&index=9">
|
||||
* 授权码查询OPENID</a>
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public OpenIdResult authCode2openId(String authCode) throws WeixinException {
|
||||
return payApi.authCode2openId(authCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询结算资金
|
||||
*
|
||||
* @param status
|
||||
* 是否结算
|
||||
* @param pageable
|
||||
* 分页数据
|
||||
* @param start
|
||||
* 开始日期 查询未结算记录时,该字段可不传
|
||||
* @param end
|
||||
* 结束日期 查询未结算记录时,该字段可不传
|
||||
* @return 结算金额记录
|
||||
* @throws WeixinException
|
||||
* @see CashApi
|
||||
* @see SettlementRecord
|
||||
* @see <a href=
|
||||
* "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 {
|
||||
return cashApi.querySettlement(status, pageable, start, end);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询汇率
|
||||
*
|
||||
* @param currencyType
|
||||
* 外币币种
|
||||
* @param date
|
||||
* 日期 不填则默认当天
|
||||
* @return 汇率对象
|
||||
* @throws WeixinException
|
||||
* @see CashApi
|
||||
* @see <a href=
|
||||
* "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 {
|
||||
return cashApi.queryExchageRate(currencyType, date);
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单附加信息提交
|
||||
*
|
||||
* @param customsOrder
|
||||
* 附加订单信息
|
||||
* @return 报关结果
|
||||
* @see CustomsApi
|
||||
* @see CustomsOrder
|
||||
* @see CustomsOrderResult
|
||||
* @see <a href=
|
||||
* "https://pay.weixin.qq.com/wiki/doc/api/external/declarecustom.php?chapter=18_1">
|
||||
* 附加订单信息提交接口</a>
|
||||
* @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
|
||||
* 海关
|
||||
* @return 报关记录
|
||||
* @see CustomsOrderRecord
|
||||
* @see CustomsApi
|
||||
* @see <a href=
|
||||
* "https://pay.weixin.qq.com/wiki/doc/api/external/declarecustom.php?chapter=18_1">
|
||||
* 附加订单信息查询接口</a>
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public CustomsOrderRecord queryCustomsOrder(IdQuery idQuery,
|
||||
CustomsCity customsCity) throws WeixinException {
|
||||
return customsApi.queryCustomsOrder(idQuery, customsCity);
|
||||
}
|
||||
|
||||
public final static String VERSION = Consts.VERSION;
|
||||
}
|
||||
@ -0,0 +1,74 @@
|
||||
package com.foxinmy.weixin4j.pay.payment.mch;
|
||||
|
||||
import com.foxinmy.weixin4j.pay.model.WeixinPayAccount;
|
||||
import com.foxinmy.weixin4j.pay.payment.PayRequest;
|
||||
import com.foxinmy.weixin4j.pay.type.SignType;
|
||||
import com.foxinmy.weixin4j.pay.type.TradeType;
|
||||
import com.foxinmy.weixin4j.util.DigestUtil;
|
||||
import com.foxinmy.weixin4j.util.MapUtil;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* APP支付
|
||||
*
|
||||
* @className APPPayRequest
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2015年12月25日
|
||||
* @since JDK 1.6
|
||||
* @see PrePay
|
||||
* @see PayRequest
|
||||
* @see <a href=
|
||||
* "https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_1">APP支付</a>
|
||||
*/
|
||||
public class APPPayRequest extends AbstractPayRequest {
|
||||
public APPPayRequest(String prePayId, WeixinPayAccount payAccount) {
|
||||
super(prePayId, payAccount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TradeType getPaymentType() {
|
||||
return TradeType.APP;
|
||||
}
|
||||
|
||||
/**
|
||||
* <font color="red">只做查看之用,请不要尝试作为支付请求</font>
|
||||
*/
|
||||
@Override
|
||||
public PayRequest toRequestObject() {
|
||||
PayRequest payRequest = new PayRequest(getPaymentAccount().getId(), "Sign=WXPay");
|
||||
payRequest.setPartnerId(getPaymentAccount().getMchId());
|
||||
payRequest.setPrepayId(getPrePayId());
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
map.put("appid", payRequest.getAppId());
|
||||
// 因为partnerid和prepayid在PayRequest类中是不进行序列化的
|
||||
map.put("partnerid", payRequest.getPartnerId());
|
||||
map.put("prepayid", payRequest.getPrepayId());
|
||||
map.put("package", payRequest.getPackageInfo());
|
||||
map.put("timestamp", payRequest.getTimeStamp());
|
||||
map.put("noncestr", payRequest.getNonceStr());
|
||||
String sign = DigestUtil.MD5(
|
||||
String.format("%s&key=%s", MapUtil.toJoinString(map, false, true), getPaymentAccount().getPaySignKey()))
|
||||
.toUpperCase();
|
||||
payRequest.setPaySign(sign);
|
||||
payRequest.setSignType(SignType.MD5);
|
||||
return payRequest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toRequestString() {
|
||||
PayRequest payRequest = toRequestObject();
|
||||
StringBuilder content = new StringBuilder();
|
||||
content.append("<xml>");
|
||||
content.append(String.format("<appid><![CDATA[%s]]></appid>", payRequest.getAppId()));
|
||||
content.append(String.format("<partnerid><![CDATA[%s]]></partnerid>", payRequest.getPartnerId()));
|
||||
content.append(String.format("<prepayid><![CDATA[%s]]></prepayid>", payRequest.getPrepayId()));
|
||||
content.append(String.format("<package><![CDATA[%s]]></package>", payRequest.getPackageInfo()));
|
||||
content.append(String.format("<noncestr><![CDATA[%s]]></noncestr>", payRequest.getNonceStr()));
|
||||
content.append(String.format("<timestamp><![CDATA[%s]]></timestamp>", payRequest.getTimeStamp()));
|
||||
content.append(String.format("<sign><![CDATA[%s]]></sign>", payRequest.getPaySign()));
|
||||
content.append("</xml>");
|
||||
return content.toString();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
package com.foxinmy.weixin4j.pay.payment.mch;
|
||||
|
||||
import com.foxinmy.weixin4j.pay.model.WeixinPayAccount;
|
||||
import com.foxinmy.weixin4j.pay.sign.WeixinPaymentSignature;
|
||||
import com.foxinmy.weixin4j.pay.sign.WeixinSignature;
|
||||
|
||||
public abstract class AbstractPayRequest implements MchPayRequest {
|
||||
|
||||
private final String prePayId;
|
||||
private final WeixinPayAccount paymentAccount;
|
||||
protected final WeixinSignature weixinSignature;
|
||||
|
||||
public AbstractPayRequest(String prePayId, WeixinPayAccount paymentAccount) {
|
||||
this.prePayId = prePayId;
|
||||
this.paymentAccount = paymentAccount;
|
||||
this.weixinSignature = new WeixinPaymentSignature(paymentAccount.getPaySignKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPrePayId() {
|
||||
return this.prePayId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WeixinPayAccount getPaymentAccount() {
|
||||
return this.paymentAccount;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,147 @@
|
||||
package com.foxinmy.weixin4j.pay.payment.mch;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.foxinmy.weixin4j.type.mch.CorpPaymentCheckNameType;
|
||||
import com.foxinmy.weixin4j.util.DateUtil;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
/**
|
||||
* 企业付款
|
||||
*
|
||||
* @className CorpPayment
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2015年4月1日
|
||||
* @since JDK 1.6
|
||||
* @see
|
||||
*/
|
||||
@XmlRootElement
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class CorpPayment extends MerchantResult {
|
||||
|
||||
private static final long serialVersionUID = 3734639674346425312L;
|
||||
/**
|
||||
* 商户订单号
|
||||
*/
|
||||
@XmlElement(name = "partner_trade_no")
|
||||
@JSONField(name = "partner_trade_no")
|
||||
private String outTradeNo;
|
||||
/**
|
||||
* 接收红包的用户的openid
|
||||
*/
|
||||
@JSONField(name = "openid")
|
||||
@XmlElement(name = "openid")
|
||||
private String openId;
|
||||
/**
|
||||
* 校验用户姓名选项
|
||||
*
|
||||
* @see CorpPaymentCheckNameType.type.MPPaymentCheckNameType
|
||||
*/
|
||||
@XmlElement(name = "check_name")
|
||||
@JSONField(name = "check_name")
|
||||
private CorpPaymentCheckNameType checkNameType;
|
||||
/**
|
||||
* 收款用户真实姓名。 如果check_name设置为FORCE_CHECK或OPTION_CHECK,则必填用户真实姓名 可选
|
||||
*/
|
||||
@XmlElement(name = "re_user_name")
|
||||
@JSONField(name = "re_user_name")
|
||||
private String userName;
|
||||
/**
|
||||
* 企业付款描述信息
|
||||
*/
|
||||
private String desc;
|
||||
/**
|
||||
* 付款金额 单位分
|
||||
*/
|
||||
private int amount;
|
||||
/**
|
||||
* 调用接口的机器Ip地址
|
||||
*/
|
||||
@XmlElement(name = "spbill_create_ip")
|
||||
@JSONField(name = "spbill_create_ip")
|
||||
private String clientIp;
|
||||
|
||||
protected CorpPayment() {
|
||||
// jaxb required
|
||||
}
|
||||
|
||||
/**
|
||||
* 企业付款
|
||||
*
|
||||
* @param outTradeNo
|
||||
* 商户的订单号
|
||||
* @param openId
|
||||
* 用户的openid
|
||||
* @param checkNameType
|
||||
* 校验用户姓名选项
|
||||
* @param desc
|
||||
* 描述
|
||||
* @param amount
|
||||
* 金额 单位元
|
||||
* @param clientIp
|
||||
* 调用接口IP
|
||||
*/
|
||||
public CorpPayment(String outTradeNo, String openId,
|
||||
CorpPaymentCheckNameType checkNameType, String desc, double amount,
|
||||
String clientIp) {
|
||||
this.outTradeNo = outTradeNo;
|
||||
this.openId = openId;
|
||||
this.checkNameType = checkNameType;
|
||||
this.desc = desc;
|
||||
this.amount = DateUtil.formatYuan2Fen(amount);
|
||||
this.clientIp = clientIp;
|
||||
}
|
||||
|
||||
public String getOutTradeNo() {
|
||||
return outTradeNo;
|
||||
}
|
||||
|
||||
public String getOpenId() {
|
||||
return openId;
|
||||
}
|
||||
|
||||
public CorpPaymentCheckNameType getCheckNameType() {
|
||||
return checkNameType;
|
||||
}
|
||||
|
||||
public String getUserName() {
|
||||
return userName;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
public int getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
|
||||
*
|
||||
* @return 元单位
|
||||
*/
|
||||
@JSONField(serialize = false)
|
||||
public double getFormatAmount() {
|
||||
return amount / 100d;
|
||||
}
|
||||
|
||||
public String getClientIp() {
|
||||
return clientIp;
|
||||
}
|
||||
|
||||
public void setUserName(String userName) {
|
||||
this.userName = userName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CorpPayment [outTradeNo=" + outTradeNo + ", openId=" + openId
|
||||
+ ", checkNameType=" + checkNameType + ", userName=" + userName
|
||||
+ ", desc=" + desc + ", amount=" + amount + ", clientIp="
|
||||
+ clientIp + ", " + super.toString() + "]";
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,202 @@
|
||||
package com.foxinmy.weixin4j.pay.payment.mch;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.foxinmy.weixin4j.type.mch.CorpPaymentCheckNameType;
|
||||
import com.foxinmy.weixin4j.util.DateUtil;
|
||||
|
||||
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 java.util.Date;
|
||||
|
||||
/**
|
||||
* 企业付款记录
|
||||
*
|
||||
* @className CorpPaymentRecord
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2015年6月23日
|
||||
* @since JDK 1.6
|
||||
* @see
|
||||
*/
|
||||
@XmlRootElement
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class CorpPaymentRecord extends MerchantResult {
|
||||
|
||||
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
|
||||
*/
|
||||
@JSONField(name = "openid")
|
||||
@XmlElement(name = "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 CorpPaymentCheckNameType.type.MPPaymentCheckNameType
|
||||
*/
|
||||
@XmlElement(name = "check_name")
|
||||
@JSONField(name = "check_name")
|
||||
private String checkNameType;
|
||||
/**
|
||||
* 企业付款描述信息
|
||||
*/
|
||||
@XmlElement(name = "desc")
|
||||
private String desc;
|
||||
/**
|
||||
* 实名验证结果 PASS:通过 FAILED:不通过
|
||||
*/
|
||||
@JSONField(name = "check_name_result")
|
||||
@XmlElement(name = "check_name_result")
|
||||
private String checkNameResult;
|
||||
|
||||
protected CorpPaymentRecord() {
|
||||
// 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 transferTime != null ? DateUtil
|
||||
.parse2yyyyMMddHHmmss(transferTime) : null;
|
||||
}
|
||||
|
||||
public String getCheckNameType() {
|
||||
return checkNameType;
|
||||
}
|
||||
|
||||
@JSONField(serialize = false)
|
||||
public CorpPaymentCheckNameType getFormatCheckNameType() {
|
||||
return checkNameType != null ? CorpPaymentCheckNameType
|
||||
.valueOf(checkNameType) : null;
|
||||
}
|
||||
|
||||
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 "CorpPaymentRecord [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,74 @@
|
||||
package com.foxinmy.weixin4j.pay.payment.mch;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.foxinmy.weixin4j.util.DateUtil;
|
||||
|
||||
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 java.util.Date;
|
||||
|
||||
/**
|
||||
* 企业付款结果
|
||||
*
|
||||
* @className CorpPaymentResult
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2015年4月1日
|
||||
* @since JDK 1.6
|
||||
* @see
|
||||
*/
|
||||
@XmlRootElement
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class CorpPaymentResult extends MerchantResult {
|
||||
|
||||
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 CorpPaymentResult() {
|
||||
// jaxb required
|
||||
}
|
||||
|
||||
public String getTransactionId() {
|
||||
return transactionId;
|
||||
}
|
||||
|
||||
public String getOutTradeNo() {
|
||||
return outTradeNo;
|
||||
}
|
||||
|
||||
public String getPaymentTime() {
|
||||
return paymentTime;
|
||||
}
|
||||
|
||||
@JSONField(serialize = false)
|
||||
public Date getFormatPaymentTime() {
|
||||
return paymentTime != null ? DateUtil.parseDate(paymentTime,
|
||||
"yyyy-MM-dd HH:mm:ss") : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CorpPaymentResult [transactionId=" + transactionId
|
||||
+ ", outTradeNo=" + outTradeNo + ", paymentTime=" + paymentTime
|
||||
+ ", " + super.toString() + "]";
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,217 @@
|
||||
package com.foxinmy.weixin4j.pay.payment.mch;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.foxinmy.weixin4j.type.CredentialType;
|
||||
import com.foxinmy.weixin4j.type.CurrencyType;
|
||||
import com.foxinmy.weixin4j.type.CustomsCity;
|
||||
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
|
||||
/**
|
||||
* 报关对象
|
||||
*
|
||||
* @className CustomsOrder
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2016年3月27日
|
||||
* @since JDK 1.6
|
||||
* @see
|
||||
*/
|
||||
public class CustomsOrder extends MerchantResult {
|
||||
|
||||
private static final long serialVersionUID = 799510373861612386L;
|
||||
/**
|
||||
* 微信支付订单号
|
||||
*/
|
||||
@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 = "sub_order_no")
|
||||
@JSONField(name = "sub_order_no")
|
||||
private String subOrderNo;
|
||||
/**
|
||||
* 货币类型,符合 ISO 4217 标准的三位字母代码,默认人民币:CNY
|
||||
*
|
||||
* @see com.foxinmy.weixin4j.mp.type.CurrencyType
|
||||
*/
|
||||
@XmlElement(name = "fee_type")
|
||||
@JSONField(name = "fee_type")
|
||||
private CurrencyType feeType;
|
||||
/**
|
||||
* 子订单金额,以分为单位,不能超过原订单金额,order_fee=transport_fee+product_fee(应付金额=物流费+商品价格),
|
||||
* 如有拆单则必传。
|
||||
*/
|
||||
@XmlElement(name = "order_fee")
|
||||
@JSONField(name = "order_fee")
|
||||
private String orderFee;
|
||||
/**
|
||||
* 物流费用,以分为单位,如有拆单则必传。
|
||||
*/
|
||||
@XmlElement(name = "transport_fee")
|
||||
@JSONField(name = "transport_fee")
|
||||
private String transportFee;
|
||||
/**
|
||||
* 商品费用,以分为单位,如有拆单则必传。
|
||||
*/
|
||||
@XmlElement(name = "product_fee")
|
||||
@JSONField(name = "product_fee")
|
||||
private String productFee;
|
||||
/**
|
||||
* 关税,以分为单位
|
||||
*/
|
||||
@XmlElement(name = "duty")
|
||||
@JSONField(name = "duty")
|
||||
private String dutyFee;
|
||||
/**
|
||||
* 海关
|
||||
*/
|
||||
@XmlElement(name = "customs")
|
||||
@JSONField(name = "customs")
|
||||
private CustomsCity customsCity;
|
||||
/**
|
||||
* 商户在海关登记的备案号,customsCity非NO,此参数必填
|
||||
*/
|
||||
@XmlElement(name = "mch_customs_no")
|
||||
@JSONField(name = "mch_customs_no")
|
||||
private String customsNo;
|
||||
/**
|
||||
* 证件类型:暂只支持身份证,该参数是指用户信息,商户若有用户信息,可上送,系统将以商户上传的数据为准,进行海关通关报备
|
||||
*/
|
||||
@XmlElement(name = "cert_type")
|
||||
@JSONField(name = "cert_type")
|
||||
private CredentialType credentialType;
|
||||
/**
|
||||
* 证件号码:身份证号,该参数是指用户信息,商户若有用户信息,可上送,系统将以商户上传的数据为准,进行海关通关报备;
|
||||
*/
|
||||
@XmlElement(name = "cert_id")
|
||||
@JSONField(name = "cert_id")
|
||||
private String credentialId;
|
||||
/**
|
||||
* 用户姓名,该参数是指用户信息,商户若有用户信息,可上送,系统将以商户上传的数据为准,进行海关通关报备;
|
||||
*/
|
||||
@XmlElement(name = "name")
|
||||
@JSONField(name = "name")
|
||||
private String uname;
|
||||
|
||||
public CustomsOrder(String transactionId, String outTradeNo) {
|
||||
this.transactionId = transactionId;
|
||||
this.outTradeNo = outTradeNo;
|
||||
this.customsCity = CustomsCity.NO;
|
||||
}
|
||||
|
||||
public String getSubOrderNo() {
|
||||
return subOrderNo;
|
||||
}
|
||||
|
||||
public void setSubOrderNo(String subOrderNo) {
|
||||
this.subOrderNo = subOrderNo;
|
||||
}
|
||||
|
||||
public CurrencyType getFeeType() {
|
||||
return feeType;
|
||||
}
|
||||
|
||||
public void setFeeType(CurrencyType feeType) {
|
||||
this.feeType = feeType;
|
||||
}
|
||||
|
||||
public String getOrderFee() {
|
||||
return orderFee;
|
||||
}
|
||||
|
||||
public void setOrderFee(String orderFee) {
|
||||
this.orderFee = orderFee;
|
||||
}
|
||||
|
||||
public String getTransportFee() {
|
||||
return transportFee;
|
||||
}
|
||||
|
||||
public void setTransportFee(String transportFee) {
|
||||
this.transportFee = transportFee;
|
||||
}
|
||||
|
||||
public String getProductFee() {
|
||||
return productFee;
|
||||
}
|
||||
|
||||
public void setProductFee(String productFee) {
|
||||
this.productFee = productFee;
|
||||
}
|
||||
|
||||
public String getDutyFee() {
|
||||
return dutyFee;
|
||||
}
|
||||
|
||||
public void setDutyFee(String dutyFee) {
|
||||
this.dutyFee = dutyFee;
|
||||
}
|
||||
|
||||
public CustomsCity getCustomsCity() {
|
||||
return customsCity;
|
||||
}
|
||||
|
||||
public void setCustomsCity(CustomsCity customsCity) {
|
||||
this.customsCity = customsCity;
|
||||
}
|
||||
|
||||
public String getCustomsNo() {
|
||||
return customsNo;
|
||||
}
|
||||
|
||||
public void setCustomsNo(String customsNo) {
|
||||
this.customsNo = customsNo;
|
||||
}
|
||||
|
||||
public CredentialType getCredentialType() {
|
||||
return credentialType;
|
||||
}
|
||||
|
||||
public void setCredentialType(CredentialType credentialType) {
|
||||
this.credentialType = credentialType;
|
||||
}
|
||||
|
||||
public String getCredentialId() {
|
||||
return credentialId;
|
||||
}
|
||||
|
||||
public void setCredentialId(String credentialId) {
|
||||
this.credentialId = credentialId;
|
||||
}
|
||||
|
||||
public String getUname() {
|
||||
return uname;
|
||||
}
|
||||
|
||||
public void setUname(String uname) {
|
||||
this.uname = uname;
|
||||
}
|
||||
|
||||
public String getTransactionId() {
|
||||
return transactionId;
|
||||
}
|
||||
|
||||
public String getOutTradeNo() {
|
||||
return outTradeNo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CustomsOrder [transactionId=" + transactionId + ", outTradeNo="
|
||||
+ outTradeNo + ", subOrderNo=" + subOrderNo + ", feeType="
|
||||
+ feeType + ", orderFee=" + orderFee + ", transportFee="
|
||||
+ transportFee + ", productFee=" + productFee + ", dutyFee="
|
||||
+ dutyFee + ", customsCity=" + customsCity + ", customsNo="
|
||||
+ customsNo + ", credentialType=" + credentialType
|
||||
+ ", credentialId=" + credentialId + ", uname=" + uname + ", "
|
||||
+ super.toString() + "]";
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,72 @@
|
||||
package com.foxinmy.weixin4j.pay.payment.mch;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.foxinmy.weixin4j.xml.ListsuffixResult;
|
||||
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 报关记录
|
||||
*
|
||||
* @className CustomsOrderRecord
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2016年3月27日
|
||||
* @since JDK 1.6
|
||||
* @see
|
||||
*/
|
||||
public class CustomsOrderRecord extends MerchantResult {
|
||||
|
||||
private static final long serialVersionUID = -1675090110657154049L;
|
||||
/**
|
||||
* 微信支付订单号
|
||||
*/
|
||||
@XmlElement(name = "transaction_id")
|
||||
@JSONField(name = "transaction_id")
|
||||
private String transactionId;
|
||||
/**
|
||||
* 笔数
|
||||
*/
|
||||
@XmlElement(name = "count")
|
||||
@JSONField(name = "count")
|
||||
private int orderCount;
|
||||
|
||||
/**
|
||||
* 报关详情
|
||||
*
|
||||
* @see CustomsOrderResult
|
||||
*/
|
||||
@ListsuffixResult
|
||||
private List<CustomsOrderResult> customsOrderList;
|
||||
|
||||
public String getTransactionId() {
|
||||
return transactionId;
|
||||
}
|
||||
|
||||
public void setTransactionId(String transactionId) {
|
||||
this.transactionId = transactionId;
|
||||
}
|
||||
|
||||
public int getOrderCount() {
|
||||
return orderCount;
|
||||
}
|
||||
|
||||
public void setOrderCount(int orderCount) {
|
||||
this.orderCount = orderCount;
|
||||
}
|
||||
|
||||
public List<CustomsOrderResult> getCustomsOrderList() {
|
||||
return customsOrderList;
|
||||
}
|
||||
|
||||
public void setCustomsOrderList(List<CustomsOrderResult> customsOrderList) {
|
||||
this.customsOrderList = customsOrderList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CustomsOrderRecord [transactionId=" + transactionId
|
||||
+ ", orderCount=" + orderCount + ", customsOrderList="
|
||||
+ customsOrderList + "]";
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,123 @@
|
||||
package com.foxinmy.weixin4j.pay.payment.mch;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.foxinmy.weixin4j.type.CustomsSatus;
|
||||
import com.foxinmy.weixin4j.util.DateUtil;
|
||||
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 报关结果
|
||||
*
|
||||
* @className CustomsOrderResult
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2016年3月27日
|
||||
* @since JDK 1.6
|
||||
* @see
|
||||
*/
|
||||
public class CustomsOrderResult extends MerchantResult {
|
||||
|
||||
private static final long serialVersionUID = 799510373861612386L;
|
||||
/**
|
||||
* 状态码
|
||||
*/
|
||||
private String state;
|
||||
/**
|
||||
* 微信支付订单号
|
||||
*/
|
||||
@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 = "sub_order_no")
|
||||
@JSONField(name = "sub_order_no")
|
||||
private String subOrderNo;
|
||||
/**
|
||||
* 微信子订单号
|
||||
*
|
||||
*/
|
||||
@XmlElement(name = "sub_order_id")
|
||||
@JSONField(name = "sub_order_id")
|
||||
private String subOrderId;
|
||||
/**
|
||||
* 最后更新时间
|
||||
*/
|
||||
@XmlElement(name = "modify_time")
|
||||
@JSONField(name = "modify_time")
|
||||
private String modifyTime;
|
||||
|
||||
public String getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
@JSONField(serialize = false)
|
||||
public CustomsSatus getFormatState() {
|
||||
return CustomsSatus.valueOf(state.toUpperCase());
|
||||
}
|
||||
|
||||
public void setState(String state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public String getTransactionId() {
|
||||
return transactionId;
|
||||
}
|
||||
|
||||
public void setTransactionId(String transactionId) {
|
||||
this.transactionId = transactionId;
|
||||
}
|
||||
|
||||
public String getOutTradeNo() {
|
||||
return outTradeNo;
|
||||
}
|
||||
|
||||
public void setOutTradeNo(String outTradeNo) {
|
||||
this.outTradeNo = outTradeNo;
|
||||
}
|
||||
|
||||
public String getSubOrderNo() {
|
||||
return subOrderNo;
|
||||
}
|
||||
|
||||
public void setSubOrderNo(String subOrderNo) {
|
||||
this.subOrderNo = subOrderNo;
|
||||
}
|
||||
|
||||
public String getSubOrderId() {
|
||||
return subOrderId;
|
||||
}
|
||||
|
||||
public void setSubOrderId(String subOrderId) {
|
||||
this.subOrderId = subOrderId;
|
||||
}
|
||||
|
||||
public String getModifyTime() {
|
||||
return modifyTime;
|
||||
}
|
||||
|
||||
@JSONField(serialize = false)
|
||||
public Date getFormatModifyTime() {
|
||||
return DateUtil.parse2yyyyMMddHHmmss(modifyTime);
|
||||
}
|
||||
|
||||
public void setModifyTime(String modifyTime) {
|
||||
this.modifyTime = modifyTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CustomsOrderResult [state=" + state + ", transactionId="
|
||||
+ transactionId + ", outTradeNo=" + outTradeNo
|
||||
+ ", subOrderNo=" + subOrderNo + ", subOrderId=" + subOrderId
|
||||
+ ", modifyTime=" + modifyTime + "]";
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,50 @@
|
||||
package com.foxinmy.weixin4j.pay.payment.mch;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.foxinmy.weixin4j.pay.model.WeixinPayAccount;
|
||||
import com.foxinmy.weixin4j.pay.payment.PayRequest;
|
||||
import com.foxinmy.weixin4j.pay.type.SignType;
|
||||
import com.foxinmy.weixin4j.pay.type.TradeType;
|
||||
|
||||
/**
|
||||
* 公众号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>
|
||||
*
|
||||
* @className JSAPIPayRequest
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2015年12月25日
|
||||
* @since JDK 1.6
|
||||
* @see PrePay
|
||||
* @see PayRequest
|
||||
* @see <a
|
||||
* href="https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_1">网页端调起支付API</a>
|
||||
*/
|
||||
public class JSAPIPayRequest extends AbstractPayRequest {
|
||||
|
||||
public JSAPIPayRequest(String prePayId, WeixinPayAccount payAccount) {
|
||||
super(prePayId, payAccount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TradeType getPaymentType() {
|
||||
return TradeType.JSAPI;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PayRequest toRequestObject() {
|
||||
PayRequest payRequest = new PayRequest(getPaymentAccount().getId(),
|
||||
"prepay_id=" + getPrePayId());
|
||||
payRequest.setSignType(SignType.MD5);
|
||||
payRequest.setPaySign(weixinSignature.sign(payRequest));
|
||||
return payRequest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toRequestString() {
|
||||
return JSON.toJSONString(toRequestObject());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,75 @@
|
||||
package com.foxinmy.weixin4j.pay.payment.mch;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.foxinmy.weixin4j.pay.model.WeixinPayAccount;
|
||||
import com.foxinmy.weixin4j.pay.payment.PayRequest;
|
||||
import com.foxinmy.weixin4j.type.TradeType;
|
||||
|
||||
import javax.xml.bind.annotation.XmlTransient;
|
||||
|
||||
/**
|
||||
* MICROPAY刷卡支付
|
||||
*
|
||||
* @className MICROPayRequest
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2015年12月25日
|
||||
* @since JDK 1.6
|
||||
* @see PrePay
|
||||
* @see PayRequest
|
||||
* @see <a
|
||||
* href="https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=5_1">刷卡支付</a>
|
||||
*/
|
||||
public class MICROPayRequest extends Order implements MchPayRequest {
|
||||
|
||||
private static final long serialVersionUID = 6147576305404111278L;
|
||||
|
||||
@XmlTransient
|
||||
@JSONField(serialize = false)
|
||||
private WeixinPayAccount paymentAccount;
|
||||
|
||||
protected MICROPayRequest() {
|
||||
// jaxb required
|
||||
}
|
||||
|
||||
@Override
|
||||
@JSONField(serialize = false)
|
||||
public TradeType getPaymentType() {
|
||||
return TradeType.MICROPAY;
|
||||
}
|
||||
|
||||
/**
|
||||
* <font color="red">返回null,请不要尝试作为支付请求</font>
|
||||
*/
|
||||
@Override
|
||||
@JSONField(serialize = false)
|
||||
public String toRequestString() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* <font color="red">返回null,请不要尝试作为支付请求</font>
|
||||
*/
|
||||
@JSONField(serialize = false)
|
||||
@Override
|
||||
public PayRequest toRequestObject() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* <font color="red">返回null,请不要尝试作为支付请求</font>
|
||||
*/
|
||||
@JSONField(serialize = false)
|
||||
@Override
|
||||
public String getPrePayId() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setPaymentAccount(WeixinPayAccount paymentAccount) {
|
||||
this.paymentAccount = paymentAccount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WeixinPayAccount getPaymentAccount() {
|
||||
return this.paymentAccount;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,224 @@
|
||||
package com.foxinmy.weixin4j.pay.payment.mch;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.foxinmy.weixin4j.pay.payment.PayPackage;
|
||||
import com.foxinmy.weixin4j.pay.type.CurrencyType;
|
||||
import com.foxinmy.weixin4j.pay.type.TradeType;
|
||||
|
||||
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 java.util.Date;
|
||||
|
||||
/**
|
||||
* 支付订单详情
|
||||
*
|
||||
* @className MchPayPackage
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2014年10月21日
|
||||
* @since JDK 1.6
|
||||
* @see
|
||||
*/
|
||||
@XmlRootElement
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class MchPayPackage extends PayPackage {
|
||||
|
||||
private static final long serialVersionUID = 8944928173669656177L;
|
||||
|
||||
/**
|
||||
* 交易类型JSAPI、NATIVE、APP 必须
|
||||
*/
|
||||
@XmlElement(name = "trade_type")
|
||||
@JSONField(name = "trade_type")
|
||||
private String tradeType;
|
||||
/**
|
||||
* 符合ISO 4217标准的三位字母代码,默认人民币:CNY 非必须
|
||||
*/
|
||||
@XmlElement(name = "fee_type")
|
||||
@JSONField(name = "fee_type")
|
||||
private String feeType;
|
||||
/**
|
||||
* 用户在商户 appid 下的唯一 标识, trade_type 为 JSAPI 时,此参数必传
|
||||
*/
|
||||
@XmlElement(name = "openid")
|
||||
@JSONField(name = "openid")
|
||||
private String openId;
|
||||
|
||||
/**
|
||||
* 只在 trade_type 为 NATIVE 且【模式一】 时需要填写 非必须
|
||||
*/
|
||||
@XmlElement(name = "product_id")
|
||||
@JSONField(name = "product_id")
|
||||
private String productId;
|
||||
|
||||
/**
|
||||
* 扫码支付授权码 ,设备读取用户微信中的条码或者二维码信息
|
||||
*/
|
||||
@XmlElement(name = "auth_code")
|
||||
@JSONField(name = "auth_code")
|
||||
private String authCode;
|
||||
/**
|
||||
* 指定支付方式:no_credit--指定不能使用信用卡支付
|
||||
*/
|
||||
@XmlElement(name = "limit_pay")
|
||||
@JSONField(name = "limit_pay")
|
||||
private String limitPay;
|
||||
/**
|
||||
* 服务商下的用户子标识 非必须
|
||||
*/
|
||||
@XmlElement(name = "sub_openid")
|
||||
@JSONField(name = "sub_openid")
|
||||
private String subOpenId;
|
||||
/**
|
||||
* 场景信息
|
||||
*/
|
||||
@XmlElement(name = "scene_info")
|
||||
@JSONField(name = "scene_info")
|
||||
private String sceneInfo;
|
||||
|
||||
protected MchPayPackage() {
|
||||
// jaxb required
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信支付
|
||||
*
|
||||
* @param body
|
||||
* 支付详情 必填
|
||||
* @param outTradeNo
|
||||
* 商户侧订单号 必填
|
||||
* @param totalFee
|
||||
* 支付金额(单位元) 必填
|
||||
* @param notifyUrl
|
||||
* 支付回调URL 必填
|
||||
* @param createIp
|
||||
* 发起支付的IP地址 必填
|
||||
* @param tradeType
|
||||
* 支付类型 必填
|
||||
* @param openId
|
||||
* 用户唯一标识 公众号JSAPI支付必填
|
||||
* @param authCode
|
||||
* 支付授权码 刷卡MICROPAY支付必填
|
||||
* @param productId
|
||||
* 商品ID 扫码NATIVE支付必填
|
||||
* @param attach
|
||||
* 支付时附加信息 非必填
|
||||
*/
|
||||
public MchPayPackage(String body, String outTradeNo, double totalFee,
|
||||
String notifyUrl, String createIp, TradeType tradeType,
|
||||
String openId, String authCode, String productId, String attach) {
|
||||
this(body, null, outTradeNo, totalFee, CurrencyType.CNY, notifyUrl,
|
||||
createIp, tradeType, openId, authCode, productId, attach, null,
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 完整参数
|
||||
*
|
||||
* @param body
|
||||
* 商品描述 <font color="red">必填项</font>
|
||||
* @param detial
|
||||
* 商品名称明细列表 非必填项
|
||||
* @param outTradeNo
|
||||
* 商户内部唯一订单号 <font color="red">必填项</font>
|
||||
* @param totalFee
|
||||
* 商品总额 单位元 <font color="red">必填项</font>
|
||||
* @param notifyUrl
|
||||
* 支付回调URL <font color="red">必填项</font>
|
||||
* @param createIp
|
||||
* 订单生成的机器IP <font color="red">必填项</font>
|
||||
* @param tradeType
|
||||
* 交易类型 <font color="red">必填项</font>
|
||||
* @param feeType
|
||||
* 货币类型 非必填项
|
||||
* @param openId
|
||||
* 用户ID <font color="red">tradeType=JSAPI时必填</font>
|
||||
* @param authCode
|
||||
* 刷卡支付授权码 <font color="red">tradeType=MICROPAY时必填</font>
|
||||
* @param productId
|
||||
* 产品ID <font color="red">tradeType=NATIVE时必填</font>
|
||||
* @param attach
|
||||
* 附加数据,在查询API和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据 非必填项
|
||||
* @param timeStart
|
||||
* 订单生成时间,格式为yyyyMMddHHmmss 非必填项
|
||||
* @param timeExpire
|
||||
* 订单失效时间,格式为yyyyMMddHHmmss;注意:最短失效时间间隔必须大于5分钟 非必填项
|
||||
* @param goodsTag
|
||||
* 商品标记,代金券或立减优惠功能的参数 非必填项
|
||||
* @param limitPay
|
||||
* 指定支付方式:no_credit--指定不能使用信用卡支付 非必填项
|
||||
* @param subOpenId
|
||||
* 用户在子商户appid下的唯一标识 非必填
|
||||
* openid和sub_openid可以选传其中之一,如果选择传sub_openid ,则必须传sub_appid
|
||||
*/
|
||||
public MchPayPackage(String body, String detial, String outTradeNo,
|
||||
double totalFee, CurrencyType feeType, String notifyUrl,
|
||||
String createIp, TradeType tradeType, String openId,
|
||||
String authCode, String productId, String attach, Date timeStart,
|
||||
Date timeExpire, String goodsTag, String limitPay, String subOpenId) {
|
||||
super(body, detial, outTradeNo, totalFee, notifyUrl, createIp, attach,
|
||||
timeStart, timeExpire, goodsTag);
|
||||
this.tradeType = tradeType != null ? tradeType.name() : null;
|
||||
this.feeType = feeType == null ? CurrencyType.CNY.name() : feeType
|
||||
.name();
|
||||
this.openId = openId;
|
||||
this.authCode = authCode;
|
||||
this.productId = productId;
|
||||
this.limitPay = limitPay;
|
||||
this.subOpenId = subOpenId;
|
||||
}
|
||||
|
||||
public String getTradeType() {
|
||||
return tradeType;
|
||||
}
|
||||
|
||||
public String getFeeType() {
|
||||
return feeType;
|
||||
}
|
||||
|
||||
public String getOpenId() {
|
||||
return openId;
|
||||
}
|
||||
|
||||
public String getAuthCode() {
|
||||
return authCode;
|
||||
}
|
||||
|
||||
public String getProductId() {
|
||||
return productId;
|
||||
}
|
||||
|
||||
public String getLimitPay() {
|
||||
return limitPay;
|
||||
}
|
||||
|
||||
public void setLimitPay(String limitPay) {
|
||||
this.limitPay = limitPay;
|
||||
}
|
||||
|
||||
public String getSubOpenId() {
|
||||
return subOpenId;
|
||||
}
|
||||
|
||||
public void setSubOpenId(String subOpenId) {
|
||||
this.subOpenId = subOpenId;
|
||||
}
|
||||
|
||||
public String getSceneInfo() {
|
||||
return sceneInfo;
|
||||
}
|
||||
|
||||
public void setSceneInfo(String sceneInfo) {
|
||||
this.sceneInfo = sceneInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MchPayPackage [tradeType=" + tradeType + ",feeType=" + feeType
|
||||
+ ", openId=" + openId + ", productId=" + productId
|
||||
+ ", authCode=" + authCode + ", limitPay=" + limitPay
|
||||
+ ", subOpenId=" + subOpenId + ", sceneInfo=" + sceneInfo
|
||||
+ ", " + super.toString() + "]";
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,55 @@
|
||||
package com.foxinmy.weixin4j.pay.payment.mch;
|
||||
|
||||
import com.foxinmy.weixin4j.pay.model.WeixinPayAccount;
|
||||
import com.foxinmy.weixin4j.pay.payment.PayRequest;
|
||||
import com.foxinmy.weixin4j.pay.type.TradeType;
|
||||
|
||||
/**
|
||||
* 支付请求接口
|
||||
*
|
||||
* @className MchPayRequest
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2015年12月25日
|
||||
* @since JDK 1.6
|
||||
* @see JSAPIPayRequest JS支付
|
||||
* @see NATIVEPayRequest 扫码支付
|
||||
* @see MICROPayRequest 刷卡支付
|
||||
* @see APPPayRequest APP支付
|
||||
* @see WAPPayRequest WAP支付
|
||||
*/
|
||||
public interface MchPayRequest {
|
||||
/**
|
||||
* 预支付交易ID
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getPrePayId();
|
||||
|
||||
/**
|
||||
* 支付账号
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public WeixinPayAccount getPaymentAccount();
|
||||
|
||||
/**
|
||||
* 支付类型
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public TradeType getPaymentType();
|
||||
|
||||
/**
|
||||
* 支付请求字符串
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String toRequestString();
|
||||
|
||||
/**
|
||||
* 支付请求对象
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public PayRequest toRequestObject();
|
||||
}
|
||||
@ -0,0 +1,176 @@
|
||||
package com.foxinmy.weixin4j.pay.payment.mch;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.foxinmy.weixin4j.http.weixin.XmlResult;
|
||||
import com.foxinmy.weixin4j.type.SignType;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
/**
|
||||
* 调用商户平台接口返回的公用字段
|
||||
*
|
||||
* @className MerchantResult
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2014年10月21日
|
||||
* @since JDK 1.6
|
||||
* @see
|
||||
*/
|
||||
@XmlRootElement
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class MerchantResult 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;
|
||||
/**
|
||||
* 微信分配的子商户公众账号ID 非必须
|
||||
*/
|
||||
@XmlElement(name = "sub_appid")
|
||||
@JSONField(name = "sub_appid")
|
||||
private String subAppId;
|
||||
/**
|
||||
* 微信支付分配的子商户号 非必须
|
||||
*/
|
||||
@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;
|
||||
/**
|
||||
* 签名类型 默认MD5
|
||||
*/
|
||||
@XmlElement(name = "sign_type")
|
||||
@JSONField(name = "sign_type")
|
||||
private String signType;
|
||||
/**
|
||||
* 微信支付分配的终端设备号 可能为空
|
||||
*/
|
||||
@XmlElement(name = "device_info")
|
||||
@JSONField(name = "device_info")
|
||||
private String deviceInfo;
|
||||
/**
|
||||
* 是否需要继续调用接口 Y- 需要,N-不需要
|
||||
*/
|
||||
private String recall;
|
||||
|
||||
protected MerchantResult() {
|
||||
// jaxb required
|
||||
}
|
||||
|
||||
public MerchantResult(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 getSubAppId() {
|
||||
return subAppId;
|
||||
}
|
||||
|
||||
public void setSubAppId(String subAppId) {
|
||||
this.subAppId = subAppId;
|
||||
}
|
||||
|
||||
public String getSubMchId() {
|
||||
return subMchId;
|
||||
}
|
||||
|
||||
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 getSignType() {
|
||||
return signType;
|
||||
}
|
||||
|
||||
@JSONField(serialize = false)
|
||||
public SignType getFormatSignType() {
|
||||
return signType != null ? SignType.valueOf(signType.toUpperCase())
|
||||
: null;
|
||||
}
|
||||
|
||||
public void setSignType(String signType) {
|
||||
this.signType = signType;
|
||||
}
|
||||
|
||||
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(serialize = false)
|
||||
public boolean getFormatRecall() {
|
||||
return recall != null && recall.equalsIgnoreCase("y");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "appId=" + appId + ", mchId=" + mchId + ", subAppId=" + subAppId
|
||||
+ ", subMchId=" + subMchId + ", nonceStr=" + nonceStr
|
||||
+ ", sign=" + sign + ", deviceInfo=" + deviceInfo + ", recall="
|
||||
+ getFormatRecall() + ", " + super.toString();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,126 @@
|
||||
package com.foxinmy.weixin4j.pay.payment.mch;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.foxinmy.weixin4j.type.CurrencyType;
|
||||
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
|
||||
/**
|
||||
* 商户平台交易结果
|
||||
*
|
||||
* @className MerchantTradeResult
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2016年7月21日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public class MerchantTradeResult extends MerchantResult {
|
||||
|
||||
private static final long serialVersionUID = 4205906286092873877L;
|
||||
/**
|
||||
* 微信支付订单号
|
||||
*/
|
||||
@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 Integer totalFee;
|
||||
/**
|
||||
* 应结订单金额,单位为分:应结订单金额=订单金额-非充值代金券金额,应结订单金额<=订单金额。
|
||||
*/
|
||||
@XmlElement(name = "settlement_total_fee")
|
||||
@JSONField(name = "settlement_total_fee")
|
||||
private Integer settlementTotalFee;
|
||||
/**
|
||||
* 货币类型,符合 ISO 4217 标准的三位字母代码,默认人民币:CNY
|
||||
*
|
||||
* @see com.foxinmy.weixin4j.mp.type.CurrencyType
|
||||
*/
|
||||
@XmlElement(name = "fee_type")
|
||||
@JSONField(name = "fee_type")
|
||||
private String feeType;
|
||||
/**
|
||||
* 现金支付金额
|
||||
*/
|
||||
@XmlElement(name = "cash_fee")
|
||||
@JSONField(name = "cash_fee")
|
||||
private Integer cashFee;
|
||||
|
||||
public Integer getCashFee() {
|
||||
return cashFee;
|
||||
}
|
||||
|
||||
/**
|
||||
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
|
||||
*
|
||||
* @return 元单位
|
||||
*/
|
||||
@JSONField(serialize = false)
|
||||
public double getFormatCashFee() {
|
||||
return cashFee != null ? cashFee / 100d : 0d;
|
||||
}
|
||||
|
||||
public Integer getTotalFee() {
|
||||
return totalFee;
|
||||
}
|
||||
|
||||
/**
|
||||
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
|
||||
*
|
||||
* @return 元单位
|
||||
*/
|
||||
@JSONField(serialize = false)
|
||||
public double getFormatTotalFee() {
|
||||
return totalFee != null ? totalFee / 100d : 0d;
|
||||
}
|
||||
|
||||
@JSONField(serialize = false)
|
||||
public CurrencyType getFormatFeeType() {
|
||||
return feeType != null ? CurrencyType.valueOf(feeType.toUpperCase())
|
||||
: null;
|
||||
}
|
||||
|
||||
public String getFeeType() {
|
||||
return feeType;
|
||||
}
|
||||
|
||||
public String getTransactionId() {
|
||||
return transactionId;
|
||||
}
|
||||
|
||||
public String getOutTradeNo() {
|
||||
return outTradeNo;
|
||||
}
|
||||
|
||||
public Integer getSettlementTotalFee() {
|
||||
return settlementTotalFee;
|
||||
}
|
||||
|
||||
/**
|
||||
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
|
||||
*
|
||||
* @return 元单位
|
||||
*/
|
||||
@JSONField(serialize = false)
|
||||
public double getFormatSettlementTotalFee() {
|
||||
return settlementTotalFee != null ? settlementTotalFee / 100d : 0d;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "transactionId=" + transactionId + ", outTradeNo=" + outTradeNo
|
||||
+ ", totalFee=" + totalFee + ", cashFee=" + cashFee
|
||||
+ ", feeType=" + feeType + ", settlementTotalFee="
|
||||
+ settlementTotalFee + ", " + super.toString();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,46 @@
|
||||
package com.foxinmy.weixin4j.pay.payment.mch;
|
||||
|
||||
import com.foxinmy.weixin4j.pay.model.WeixinPayAccount;
|
||||
import com.foxinmy.weixin4j.pay.payment.PayRequest;
|
||||
import com.foxinmy.weixin4j.pay.type.TradeType;
|
||||
|
||||
/**
|
||||
* NATIVE扫码支付(模式二)
|
||||
*
|
||||
* @className NATIVEPayRequest
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2015年12月25日
|
||||
* @since JDK 1.6
|
||||
* @see PrePay
|
||||
* @see PayRequest
|
||||
* @see <a
|
||||
* href="https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_1">NATIVE扫码支付(模式二)</a>
|
||||
*/
|
||||
public class NATIVEPayRequest extends AbstractPayRequest {
|
||||
|
||||
private final String codeUrl;
|
||||
|
||||
public NATIVEPayRequest(String prePayId, String codeUrl,
|
||||
WeixinPayAccount payAccount) {
|
||||
super(prePayId, payAccount);
|
||||
this.codeUrl = codeUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TradeType getPaymentType() {
|
||||
return TradeType.NATIVE;
|
||||
}
|
||||
|
||||
/**
|
||||
* <font color="red">只做查看之用,请不要尝试作为支付请求</font>
|
||||
*/
|
||||
@Override
|
||||
public PayRequest toRequestObject() {
|
||||
return new PayRequest(getPaymentAccount().getId(), "code_url=" + codeUrl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toRequestString() {
|
||||
return this.codeUrl;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
package com.foxinmy.weixin4j.pay.payment.mch;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
|
||||
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 jinyu(foxinmy@gmail.com)
|
||||
* @date 2014年10月30日
|
||||
* @since JDK 1.6
|
||||
* @see
|
||||
*/
|
||||
@XmlRootElement
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class NativePayNotify extends OpenIdResult {
|
||||
|
||||
private static final long serialVersionUID = 4515471400239795492L;
|
||||
/**
|
||||
* 用户是否关注公众账号,Y- 关注,N-未关注,仅在公众 账号类型支付有效
|
||||
*/
|
||||
@XmlElement(name = "is_subscribe")
|
||||
@JSONField(name = "is_subscribe")
|
||||
private String isSubscribe;
|
||||
/**
|
||||
* 产品ID 可视为订单ID
|
||||
*/
|
||||
@XmlElement(name = "product_id")
|
||||
@JSONField(name = "product_id")
|
||||
private String productId;
|
||||
|
||||
protected NativePayNotify() {
|
||||
// jaxb required
|
||||
}
|
||||
|
||||
public String getProductId() {
|
||||
return productId;
|
||||
}
|
||||
|
||||
public String getIsSubscribe() {
|
||||
return isSubscribe;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NativePayNotify [productId=" + productId + ", isSubscribe="
|
||||
+ isSubscribe + ", " + super.toString() + "]";
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,79 @@
|
||||
package com.foxinmy.weixin4j.pay.payment.mch;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.foxinmy.weixin4j.pay.model.WeixinPayAccount;
|
||||
import com.foxinmy.weixin4j.pay.sign.WeixinPaymentSignature;
|
||||
import com.foxinmy.weixin4j.util.Consts;
|
||||
import com.foxinmy.weixin4j.util.RandomUtil;
|
||||
|
||||
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支付时的回调响应
|
||||
*
|
||||
* @className NativePayResponse
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2014年10月28日
|
||||
* @since JDK 1.6
|
||||
* @see
|
||||
*/
|
||||
@XmlRootElement
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class NativePayResponse extends MerchantResult {
|
||||
|
||||
private static final long serialVersionUID = 6119895998783333012L;
|
||||
|
||||
@XmlElement(name = "prepay_id")
|
||||
@JSONField(name = "prepay_id")
|
||||
private String prepayId;
|
||||
|
||||
protected NativePayResponse() {
|
||||
// jaxb required
|
||||
}
|
||||
|
||||
/**
|
||||
* 作为return_code 为 FAIL 的时候返回
|
||||
*
|
||||
* @param returnMsg
|
||||
* 失败消息
|
||||
* @param resultMsg
|
||||
* 结果消息
|
||||
*/
|
||||
public NativePayResponse(String returnMsg, String resultMsg) {
|
||||
super(Consts.FAIL, returnMsg);
|
||||
super.setErrCodeDes(resultMsg);
|
||||
super.setResultCode(Consts.FAIL);
|
||||
}
|
||||
|
||||
/**
|
||||
* 作为return_code 为 SUCCESS 的时候返回
|
||||
*
|
||||
* @param weixinAccount
|
||||
* 商户信息
|
||||
* @param prepayId
|
||||
* 调用统一下单接口生成的预支付ID
|
||||
*/
|
||||
public NativePayResponse(WeixinPayAccount weixinAccount, String prepayId) {
|
||||
super(Consts.SUCCESS, "OK");
|
||||
this.setResultCode(Consts.SUCCESS);
|
||||
this.setMchId(weixinAccount.getMchId());
|
||||
this.setAppId(weixinAccount.getId());
|
||||
this.setNonceStr(RandomUtil.generateString(16));
|
||||
this.prepayId = prepayId;
|
||||
this.setSign(new WeixinPaymentSignature(weixinAccount.getPaySignKey())
|
||||
.sign(this));
|
||||
}
|
||||
|
||||
public String getPrepayId() {
|
||||
return prepayId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NativePayResponse [prepayId=" + prepayId + ", "
|
||||
+ super.toString() + "]";
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,52 @@
|
||||
package com.foxinmy.weixin4j.pay.payment.mch;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
/**
|
||||
* authcode2openid
|
||||
*
|
||||
* @className OpenIdResult
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2015年7月23日
|
||||
* @since JDK 1.6
|
||||
* @see
|
||||
*/
|
||||
@XmlRootElement
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class OpenIdResult extends MerchantResult {
|
||||
|
||||
private static final long serialVersionUID = 902743989722741814L;
|
||||
|
||||
/**
|
||||
* 用户在商户appid下的唯一标识
|
||||
*/
|
||||
@XmlElement(name = "openid")
|
||||
@JSONField(name = "openid")
|
||||
private String openId;
|
||||
|
||||
/**
|
||||
* 用户在商户appid下的唯一标识
|
||||
*/
|
||||
@XmlElement(name = "sub_openid")
|
||||
@JSONField(name = "sub_openid")
|
||||
private String subOpenId;
|
||||
|
||||
public String getOpenId() {
|
||||
return openId;
|
||||
}
|
||||
|
||||
public String getSubOpenId() {
|
||||
return subOpenId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "OpenIdResult [openId=" + openId + ", subOpenId=" + subOpenId
|
||||
+ ", " + super.toString() + "]";
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,247 @@
|
||||
package com.foxinmy.weixin4j.pay.payment.mch;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.foxinmy.weixin4j.pay.payment.coupon.OrderCouponInfo;
|
||||
import com.foxinmy.weixin4j.type.BankType;
|
||||
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.xml.ListsuffixResult;
|
||||
|
||||
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 java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 订单信息
|
||||
*
|
||||
* @className Order
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2014年11月2日
|
||||
* @since JDK 1.6
|
||||
* @see
|
||||
*/
|
||||
@XmlRootElement
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class Order extends MerchantTradeResult {
|
||||
|
||||
private static final long serialVersionUID = 5636828325595317079L;
|
||||
/**
|
||||
* 交易状态
|
||||
*
|
||||
* @see TradeState
|
||||
*/
|
||||
@XmlElement(name = "trade_state")
|
||||
@JSONField(name = "trade_state")
|
||||
private String 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 TradeType
|
||||
*/
|
||||
@XmlElement(name = "trade_type")
|
||||
@JSONField(name = "trade_type")
|
||||
private String tradeType;
|
||||
/**
|
||||
* 银行类型
|
||||
*/
|
||||
@XmlElement(name = "bank_type")
|
||||
@JSONField(name = "bank_type")
|
||||
private String bankType;
|
||||
|
||||
/**
|
||||
* 现金支付货币类型,符合 ISO 4217 标准的三位字母代码,默认人民币:CNY
|
||||
*
|
||||
* @see com.foxinmy.weixin4j.mp.type.CurrencyType
|
||||
*/
|
||||
@XmlElement(name = "cash_fee_type")
|
||||
@JSONField(name = "cash_fee_type")
|
||||
private String cashFeeType;
|
||||
/**
|
||||
* 代金券金额:“代金券”金额<=订单金额,订单金额-“代金券”金额=现金支付金额
|
||||
*/
|
||||
@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<OrderCouponInfo> couponList;
|
||||
/**
|
||||
* 商家数据包
|
||||
*/
|
||||
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;
|
||||
|
||||
/**
|
||||
* 用户在子商户下的openid
|
||||
*/
|
||||
@XmlElement(name = "sub_openid")
|
||||
@JSONField(name = "sub_openid")
|
||||
private String subOpenId;
|
||||
/**
|
||||
* 是否关注子公众账号,Y- 关注,N-未关注,仅在公众 账号类型支付有效
|
||||
*/
|
||||
@XmlElement(name = "sub_is_subscribe")
|
||||
@JSONField(name = "sub_is_subscribe")
|
||||
private String subIsSubscribe;
|
||||
|
||||
protected Order() {
|
||||
// jaxb required
|
||||
}
|
||||
|
||||
@JSONField(serialize = false)
|
||||
public TradeState getFormatTradeState() {
|
||||
return tradeState != null ? TradeState
|
||||
.valueOf(tradeState.toUpperCase()) : null;
|
||||
}
|
||||
|
||||
public String getOpenId() {
|
||||
return openId;
|
||||
}
|
||||
|
||||
public String getIsSubscribe() {
|
||||
return isSubscribe;
|
||||
}
|
||||
|
||||
@JSONField(serialize = false)
|
||||
public boolean getFormatIsSubscribe() {
|
||||
return isSubscribe != null && isSubscribe.equalsIgnoreCase("y");
|
||||
}
|
||||
|
||||
@JSONField(serialize = false)
|
||||
public TradeType getFormatTradeType() {
|
||||
return tradeType != null ? TradeType.valueOf(tradeType.toUpperCase())
|
||||
: null;
|
||||
}
|
||||
|
||||
public String getBankType() {
|
||||
return bankType;
|
||||
}
|
||||
|
||||
@JSONField(serialize = false)
|
||||
public BankType getFormatBankType() {
|
||||
return bankType != null ? BankType.valueOf(bankType.toUpperCase())
|
||||
: null;
|
||||
}
|
||||
|
||||
public Integer getCouponFee() {
|
||||
return couponFee;
|
||||
}
|
||||
|
||||
/**
|
||||
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
|
||||
*
|
||||
* @return 元单位
|
||||
*/
|
||||
@JSONField(serialize = false)
|
||||
public double getFormatCouponFee() {
|
||||
return couponFee != null ? couponFee / 100d : 0d;
|
||||
}
|
||||
|
||||
public Integer getCouponCount() {
|
||||
return couponCount;
|
||||
}
|
||||
|
||||
public String getTradeState() {
|
||||
return tradeState;
|
||||
}
|
||||
|
||||
public String getTradeType() {
|
||||
return tradeType;
|
||||
}
|
||||
|
||||
public String getAttach() {
|
||||
return attach;
|
||||
}
|
||||
|
||||
public String getTimeEnd() {
|
||||
return timeEnd;
|
||||
}
|
||||
|
||||
@JSONField(serialize = false)
|
||||
public Date getFormatTimeEnd() {
|
||||
return timeEnd != null ? DateUtil.parse2yyyyMMddHHmmss(timeEnd) : null;
|
||||
}
|
||||
|
||||
public String getTradeStateDesc() {
|
||||
return tradeStateDesc;
|
||||
}
|
||||
|
||||
public List<OrderCouponInfo> getCouponList() {
|
||||
return couponList;
|
||||
}
|
||||
|
||||
public void setCouponList(List<OrderCouponInfo> couponList) {
|
||||
this.couponList = couponList;
|
||||
}
|
||||
|
||||
public String getSubOpenId() {
|
||||
return subOpenId;
|
||||
}
|
||||
|
||||
public String getSubIsSubscribe() {
|
||||
return subIsSubscribe;
|
||||
}
|
||||
|
||||
@JSONField(serialize = false)
|
||||
public boolean getFormatSubIsSubscribe() {
|
||||
return subIsSubscribe != null && subIsSubscribe.equalsIgnoreCase("y");
|
||||
}
|
||||
|
||||
public String getCashFeeType() {
|
||||
return cashFeeType;
|
||||
}
|
||||
|
||||
@JSONField(serialize = false)
|
||||
public CurrencyType getFormatCashFeeType() {
|
||||
return cashFeeType != null ? CurrencyType.valueOf(cashFeeType
|
||||
.toUpperCase()) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Order [tradeState=" + tradeState + ", openId=" + openId
|
||||
+ ", isSubscribe=" + isSubscribe + ", tradeType=" + tradeType
|
||||
+ ", bankType=" + bankType + ", cashFeeType=" + cashFeeType
|
||||
+ ", couponFee=" + couponFee + ", couponCount=" + couponCount
|
||||
+ ", couponList=" + couponList + ", attach=" + attach
|
||||
+ ", timeEnd=" + timeEnd + ", tradeStateDesc=" + tradeStateDesc
|
||||
+ ", subOpenId=" + subOpenId + ", subIsSubscribe="
|
||||
+ subIsSubscribe + ", " + super.toString() + "]";
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,79 @@
|
||||
package com.foxinmy.weixin4j.pay.payment.mch;
|
||||
|
||||
import com.foxinmy.weixin4j.type.TradeType;
|
||||
|
||||
import javax.xml.bind.annotation.*;
|
||||
|
||||
/**
|
||||
* V3预订单信息
|
||||
*
|
||||
* @className PrePay
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2014年10月21日
|
||||
* @since JDK 1.6
|
||||
* @see
|
||||
*/
|
||||
@XmlRootElement
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class PrePay extends MerchantResult {
|
||||
|
||||
private static final long serialVersionUID = -8430005768959715444L;
|
||||
|
||||
/**
|
||||
* 调用接口提交的交易类型,取值如下:JSAPI,NATIVE,APP,
|
||||
*
|
||||
* @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 或者 MWEB 是有 返回</br> NATVIE支付:可直接生成二维码展示出来进行扫码支付可能为空</br>
|
||||
* MWEB支付:可直接作为跳转支付的URL
|
||||
*/
|
||||
@XmlElements({ @XmlElement(name = "code_url"),
|
||||
@XmlElement(name = "mweb_url") })
|
||||
private String payUrl;
|
||||
|
||||
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 getPayUrl() {
|
||||
return payUrl;
|
||||
}
|
||||
|
||||
public void setPayUrl(String payUrl) {
|
||||
this.payUrl = payUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PrePay [tradeType=" + tradeType + ", prepayId=" + prepayId
|
||||
+ ", payUrl=" + payUrl + ", " + super.toString() + "]";
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,269 @@
|
||||
package com.foxinmy.weixin4j.pay.payment.mch;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.foxinmy.weixin4j.type.mch.RedpacketSceneType;
|
||||
import com.foxinmy.weixin4j.util.DateUtil;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
/**
|
||||
* 红包
|
||||
*
|
||||
* @className Redpacket
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2015年3月28日
|
||||
* @since JDK 1.6
|
||||
* @see <a
|
||||
* href="https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_1">普通红包</a>
|
||||
* @see <a
|
||||
* href="https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=16_1">裂变红包</a>
|
||||
*/
|
||||
@XmlRootElement
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class Redpacket extends MerchantResult {
|
||||
|
||||
private static final long serialVersionUID = -7021352305575714281L;
|
||||
|
||||
/**
|
||||
* 商户订单号(每个订单号必须唯一) 组成: 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 = "send_name")
|
||||
@JSONField(name = "send_name")
|
||||
private String sendName;
|
||||
/**
|
||||
* 付款金额,单位分
|
||||
*/
|
||||
@XmlElement(name = "total_amount")
|
||||
@JSONField(name = "total_amount")
|
||||
private int totalAmount;
|
||||
/**
|
||||
* 红包发放总人数
|
||||
*/
|
||||
@XmlElement(name = "total_num")
|
||||
@JSONField(name = "total_num")
|
||||
private int totalNum;
|
||||
/**
|
||||
* 红包金额设置方式(裂变红包) ALL_RAND—全部随机,商户指定总金额和红包发放总人数,由微信支付随机计算出各红包金额
|
||||
*/
|
||||
@XmlElement(name = "amt_type")
|
||||
@JSONField(name = "amt_type")
|
||||
private String amtType;
|
||||
/**
|
||||
* 红包祝福语
|
||||
*/
|
||||
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;
|
||||
|
||||
/**
|
||||
* 服务商模式下触达用户时的appid(可填服务商自己的appid或子商户的appid),服务商模式下必填,
|
||||
* 服务商模式下填入的子商户appid必须在微信支付商户平台中先录入,否则会校验不过。 非必须
|
||||
*/
|
||||
@XmlElement(name = "msgappid")
|
||||
@JSONField(name = "msgappid")
|
||||
private String msgAppId;
|
||||
/**
|
||||
* 扣钱方mchid,常规模式下无效,服务商模式下选填,服务商模式下不填默认扣子商户的钱.非必须
|
||||
*/
|
||||
@XmlElement(name = "consume_mch_id")
|
||||
@JSONField(name = "consume_mch_id")
|
||||
private String consumeMchId;
|
||||
/**
|
||||
* 发放红包使用场景,红包金额大于200时必传
|
||||
*/
|
||||
@XmlElement(name = "scene_id")
|
||||
@JSONField(name = "scene_id")
|
||||
private RedpacketSceneType sceneType;
|
||||
/**
|
||||
* 活动信息
|
||||
*/
|
||||
@XmlElement(name = "risk_info")
|
||||
@JSONField(name = "risk_info")
|
||||
private String risk;
|
||||
|
||||
protected Redpacket() {
|
||||
// jaxb required
|
||||
}
|
||||
|
||||
/**
|
||||
* 红包
|
||||
*
|
||||
* @param outTradeNo
|
||||
* 商户侧一天内不可重复的订单号 接口根据商户订单号支持重入 如出现超时可再调用 必填
|
||||
* @param openId
|
||||
* 接受收红包的用户的openid 必填
|
||||
* @param sendName
|
||||
* 红包发送者名称 必填
|
||||
* @param totalAmount
|
||||
* 付款金额 <font color="red">单位为元,自动格式化为分</font> 必填
|
||||
* @param totalNum
|
||||
* 红包发放总人数 大于1视为裂变红包 必填
|
||||
* @param wishing
|
||||
* 红包祝福语 必填
|
||||
* @param clientIp
|
||||
* Ip地址 必填
|
||||
* @param actName
|
||||
* 活动名称 必填
|
||||
* @param remark
|
||||
* 备注 必填
|
||||
*/
|
||||
public Redpacket(String outTradeNo, String openId, String sendName,
|
||||
double totalAmount, int totalNum, String wishing, String clientIp,
|
||||
String actName, String remark) {
|
||||
this.outTradeNo = outTradeNo;
|
||||
this.openId = openId;
|
||||
this.sendName = sendName;
|
||||
this.totalAmount = DateUtil.formatYuan2Fen(totalAmount);
|
||||
this.totalNum = totalNum;
|
||||
this.wishing = wishing;
|
||||
this.clientIp = clientIp;
|
||||
this.actName = actName;
|
||||
this.remark = remark;
|
||||
this.amtType = totalNum > 1 ? "ALL_RAND" : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量发送时可能需要
|
||||
*
|
||||
* @param outTradeNo
|
||||
* 订单号
|
||||
* @param openId
|
||||
* 用户ID
|
||||
* @return 红包实体
|
||||
*/
|
||||
public Redpacket copy(String outTradeNo, String openId) {
|
||||
Redpacket readpacket = new Redpacket(outTradeNo, openId, sendName,
|
||||
totalAmount, totalNum, wishing, clientIp, actName, remark);
|
||||
readpacket.setMsgAppId(msgAppId);
|
||||
readpacket.setConsumeMchId(consumeMchId);
|
||||
readpacket.setSceneType(sceneType);
|
||||
readpacket.setRisk(risk);
|
||||
return readpacket;
|
||||
}
|
||||
|
||||
public String getOutTradeNo() {
|
||||
return outTradeNo;
|
||||
}
|
||||
|
||||
public String getOpenId() {
|
||||
return openId;
|
||||
}
|
||||
|
||||
public String getSendName() {
|
||||
return sendName;
|
||||
}
|
||||
|
||||
public int getTotalAmount() {
|
||||
return totalAmount;
|
||||
}
|
||||
|
||||
/**
|
||||
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
|
||||
*
|
||||
* @return 元单位
|
||||
*/
|
||||
@JSONField(serialize = false)
|
||||
public double getFormatTotalAmount() {
|
||||
return totalAmount / 100d;
|
||||
}
|
||||
|
||||
public int getTotalNum() {
|
||||
return totalNum;
|
||||
}
|
||||
|
||||
public String getWishing() {
|
||||
return wishing;
|
||||
}
|
||||
|
||||
public String getAmtType() {
|
||||
return amtType;
|
||||
}
|
||||
|
||||
public String getClientIp() {
|
||||
return clientIp;
|
||||
}
|
||||
|
||||
public String getActName() {
|
||||
return actName;
|
||||
}
|
||||
|
||||
public String getRemark() {
|
||||
return remark;
|
||||
}
|
||||
|
||||
public String getMsgAppId() {
|
||||
return msgAppId;
|
||||
}
|
||||
|
||||
public void setMsgAppId(String msgAppId) {
|
||||
this.msgAppId = msgAppId;
|
||||
}
|
||||
|
||||
public String getConsumeMchId() {
|
||||
return consumeMchId;
|
||||
}
|
||||
|
||||
public void setConsumeMchId(String consumeMchId) {
|
||||
this.consumeMchId = consumeMchId;
|
||||
}
|
||||
|
||||
public RedpacketSceneType getSceneType() {
|
||||
return sceneType;
|
||||
}
|
||||
|
||||
public void setSceneType(RedpacketSceneType sceneType) {
|
||||
this.sceneType = sceneType;
|
||||
}
|
||||
|
||||
public String getRisk() {
|
||||
return risk;
|
||||
}
|
||||
|
||||
public void setRisk(String risk) {
|
||||
this.risk = risk;
|
||||
}
|
||||
|
||||
public void setRisk(RedpacketRisk risk) {
|
||||
this.risk = risk.toContent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Redpacket [outTradeNo=" + outTradeNo + ", openId=" + openId
|
||||
+ ", sendName=" + sendName + ", totalAmount=" + totalAmount
|
||||
+ ", totalNum=" + totalNum + ", amtType=" + amtType
|
||||
+ ", wishing=" + wishing + ", clientIp=" + clientIp
|
||||
+ ", actName=" + actName + ", remark=" + remark + ", msgAppId="
|
||||
+ msgAppId + ", consumeMchId=" + consumeMchId + ", sceneType="
|
||||
+ sceneType + ", risk=" + risk + ", " + super.toString() + "]";
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,315 @@
|
||||
package com.foxinmy.weixin4j.pay.payment.mch;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.foxinmy.weixin4j.http.weixin.XmlResult;
|
||||
import com.foxinmy.weixin4j.type.mch.RedpacketSendType;
|
||||
import com.foxinmy.weixin4j.type.mch.RedpacketStatus;
|
||||
import com.foxinmy.weixin4j.type.mch.RedpacketType;
|
||||
import com.foxinmy.weixin4j.util.DateUtil;
|
||||
|
||||
import javax.xml.bind.annotation.*;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 红包记录
|
||||
*
|
||||
* @className RedpacketRecord
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2015年6月4日
|
||||
* @since JDK 1.6
|
||||
* @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 String status;
|
||||
/**
|
||||
* 发放类型
|
||||
*/
|
||||
@XmlElement(name = "send_type")
|
||||
@JSONField(name = "send_type")
|
||||
private String sendType;
|
||||
/**
|
||||
* 红包类型
|
||||
*/
|
||||
@XmlElement(name = "hb_type")
|
||||
@JSONField(name = "hb_type")
|
||||
private String hbType;
|
||||
/**
|
||||
* 红包个数
|
||||
*/
|
||||
@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;
|
||||
}
|
||||
|
||||
@JSONField(serialize = false)
|
||||
public RedpacketStatus getFormatStatus() {
|
||||
return status != null ? RedpacketStatus.valueOf(status.toUpperCase())
|
||||
: null;
|
||||
}
|
||||
|
||||
@JSONField(serialize = false)
|
||||
public RedpacketSendType getFormatSendType() {
|
||||
return sendType != null ? RedpacketSendType.valueOf(sendType) : null;
|
||||
}
|
||||
|
||||
@JSONField(serialize = false)
|
||||
public RedpacketType getFomatHbType() {
|
||||
return hbType != null ? RedpacketType.valueOf(hbType) : null;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public String getSendType() {
|
||||
return sendType;
|
||||
}
|
||||
|
||||
public String getHbType() {
|
||||
return hbType;
|
||||
}
|
||||
|
||||
public int getTotalNum() {
|
||||
return totalNum;
|
||||
}
|
||||
|
||||
public int getTotalAmount() {
|
||||
return totalAmount;
|
||||
}
|
||||
|
||||
/**
|
||||
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
|
||||
*
|
||||
* @return 元单位
|
||||
*/
|
||||
@JSONField(serialize = false)
|
||||
public double getFormatTotalAmount() {
|
||||
return totalAmount / 100d;
|
||||
}
|
||||
|
||||
public String getReason() {
|
||||
return reason;
|
||||
}
|
||||
|
||||
public String getSendTime() {
|
||||
return sendTime;
|
||||
}
|
||||
|
||||
@JSONField(serialize = false)
|
||||
public Date getFormatSendTime() {
|
||||
return sendTime != null ? DateUtil.parse2yyyyMMddHHmmss(sendTime)
|
||||
: null;
|
||||
}
|
||||
|
||||
public String getRefundTime() {
|
||||
return refundTime;
|
||||
}
|
||||
|
||||
@JSONField(serialize = false)
|
||||
public Date getFormatRefundTime() {
|
||||
return refundTime != null ? DateUtil.parse2yyyyMMddHHmmss(refundTime)
|
||||
: null;
|
||||
}
|
||||
|
||||
public Integer getRefundAmount() {
|
||||
return refundAmount;
|
||||
}
|
||||
|
||||
/**
|
||||
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
|
||||
*
|
||||
* @return 元单位
|
||||
*/
|
||||
@JSONField(serialize = false)
|
||||
public double getFormatRefundAmount() {
|
||||
return refundAmount != null ? refundAmount.intValue() / 100d : 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 implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 领取红包的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)
|
||||
public double getFormatAmount() {
|
||||
return amount / 100d;
|
||||
}
|
||||
|
||||
@JSONField(serialize = false)
|
||||
public Date getFormatReceiveTime() {
|
||||
return receiveTime != null ? DateUtil
|
||||
.parse2yyyyMMddHHmmss(receiveTime) : null;
|
||||
}
|
||||
|
||||
@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 + ", hbType=" + hbType
|
||||
+ ", totalNum=" + totalNum + ", totalAmount="
|
||||
+ getFormatTotalAmount() + ", reason=" + reason + ", sendTime="
|
||||
+ sendTime + ", refundTime=" + refundTime + ", refundAmount="
|
||||
+ getFormatRefundAmount() + ", wishing=" + wishing
|
||||
+ ", remark=" + remark + ", actName=" + actName
|
||||
+ ", receivers=" + receivers + "]";
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,85 @@
|
||||
package com.foxinmy.weixin4j.pay.payment.mch;
|
||||
|
||||
import com.foxinmy.weixin4j.util.Consts;
|
||||
import com.foxinmy.weixin4j.util.DateUtil;
|
||||
import com.foxinmy.weixin4j.util.MapUtil;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 发送红包的活动信息
|
||||
*
|
||||
* @className RedpacketRisk
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2017年1月4日
|
||||
* @since JDK 1.6
|
||||
* @see
|
||||
*/
|
||||
public class RedpacketRisk {
|
||||
private Map<String, String> risk;
|
||||
|
||||
public RedpacketRisk() {
|
||||
this.risk = new HashMap<String, String>();
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户操作的时间戳
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public RedpacketRisk postTimestamp() {
|
||||
risk.put("posttime", DateUtil.timestamp2string());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 业务系统账号的手机号,国家代码-手机号。不需要+号
|
||||
*
|
||||
* @param mobile
|
||||
* @return
|
||||
*/
|
||||
public RedpacketRisk mobile(String mobile) {
|
||||
risk.put("mobile", mobile);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户操作的客户端版本
|
||||
*
|
||||
* @param clientVersion
|
||||
* @return
|
||||
*/
|
||||
public RedpacketRisk clientVersion(String clientVersion) {
|
||||
risk.put("clientversion", clientVersion);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* mac 地址或者设备唯一标识
|
||||
*
|
||||
* @param deviceid
|
||||
* @return
|
||||
*/
|
||||
public RedpacketRisk deviceid(String deviceid) {
|
||||
risk.put("deviceid", deviceid);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Map<String, String> getRisk() {
|
||||
return risk;
|
||||
}
|
||||
|
||||
public String toContent() {
|
||||
if (risk.isEmpty())
|
||||
return null;
|
||||
try {
|
||||
return URLEncoder.encode(MapUtil.toJoinString(risk, false, false),
|
||||
Consts.UTF_8.name());
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,102 @@
|
||||
package com.foxinmy.weixin4j.pay.payment.mch;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.foxinmy.weixin4j.util.DateUtil;
|
||||
|
||||
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 java.util.Date;
|
||||
|
||||
/**
|
||||
* 发送红包结果
|
||||
*
|
||||
* @className RedpacketSendResult
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2015年4月1日
|
||||
* @since JDK 1.6
|
||||
* @see
|
||||
*/
|
||||
@XmlRootElement
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class RedpacketSendResult extends MerchantResult {
|
||||
|
||||
private static final long serialVersionUID = 5611847899634131711L;
|
||||
/**
|
||||
* 商户订单号(每个订单号必须唯一) 组成: 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;
|
||||
/**
|
||||
* 发放成功时间
|
||||
*/
|
||||
@XmlElement(name = "send_time")
|
||||
@JSONField(name = "send_time")
|
||||
private String sendTime;
|
||||
/**
|
||||
* 微信单号
|
||||
*/
|
||||
@XmlElement(name = "send_listid")
|
||||
@JSONField(name = "send_listid")
|
||||
private String sendListid;
|
||||
|
||||
protected RedpacketSendResult() {
|
||||
// jaxb required
|
||||
}
|
||||
|
||||
public String getOutTradeNo() {
|
||||
return outTradeNo;
|
||||
}
|
||||
|
||||
public String getOpenId() {
|
||||
return openId;
|
||||
}
|
||||
|
||||
public int getTotalAmount() {
|
||||
return totalAmount;
|
||||
}
|
||||
|
||||
/**
|
||||
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
|
||||
*
|
||||
* @return 元单位
|
||||
*/
|
||||
@JSONField(serialize = false)
|
||||
public double getFormatTotalAmount() {
|
||||
return totalAmount / 100d;
|
||||
}
|
||||
|
||||
public String getSendTime() {
|
||||
return sendTime;
|
||||
}
|
||||
|
||||
@JSONField(serialize = false)
|
||||
public Date getFormatSendTime() {
|
||||
return DateUtil.parse2yyyyMMddHHmmss(sendTime);
|
||||
}
|
||||
|
||||
public String getSendListid() {
|
||||
return sendListid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RedpacketSendResult [outTradeNo=" + outTradeNo + ", openId="
|
||||
+ openId + ", totalAmount=" + totalAmount + ", "
|
||||
+ super.toString() + "]";
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,218 @@
|
||||
package com.foxinmy.weixin4j.pay.payment.mch;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.foxinmy.weixin4j.pay.payment.coupon.RefundCouponInfo;
|
||||
import com.foxinmy.weixin4j.type.mch.CouponType;
|
||||
import com.foxinmy.weixin4j.type.mch.RefundChannel;
|
||||
import com.foxinmy.weixin4j.type.mch.RefundStatus;
|
||||
import com.foxinmy.weixin4j.util.DateUtil;
|
||||
import com.foxinmy.weixin4j.xml.ListsuffixResult;
|
||||
|
||||
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 java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 退款详细
|
||||
*
|
||||
* @className RefundDetail
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2016年7月21日
|
||||
* @since JDK 1.6
|
||||
*/
|
||||
@XmlRootElement
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class RefundDetail implements Serializable {
|
||||
private static final long serialVersionUID = 1402738803019986864L;
|
||||
|
||||
protected RefundDetail() {
|
||||
// jaxb required
|
||||
}
|
||||
|
||||
/**
|
||||
* 商户退款单号
|
||||
*/
|
||||
@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;
|
||||
/**
|
||||
* 退款状态
|
||||
*/
|
||||
@XmlElement(name = "refund_status")
|
||||
@JSONField(name = "refund_status")
|
||||
private String refundStatus;
|
||||
/**
|
||||
* 退款金额:退款金额=申请退款金额-非充值代金券退款金额,退款金额<=申请退款金额
|
||||
*/
|
||||
@XmlElement(name = "settlement_refund_fee")
|
||||
@JSONField(name = "settlement_refund_fee")
|
||||
private Integer settlementRefundFee;
|
||||
/**
|
||||
* 代金券退款金额:代金券退款金额<=退款金额,退款金额-代金券或立减优惠退款金额为现金,
|
||||
*/
|
||||
@XmlElement(name = "coupon_refund_fee")
|
||||
@JSONField(name = "coupon_refund_fee")
|
||||
private Integer couponRefundFee;
|
||||
/**
|
||||
* 代金券或立减优惠使用数量
|
||||
*/
|
||||
@XmlElement(name = "coupon_refund_count")
|
||||
@JSONField(name = "coupon_refund_count")
|
||||
private Integer couponRefundCount;
|
||||
/**
|
||||
* 代金券类型
|
||||
*
|
||||
* @see CouponType
|
||||
*/
|
||||
@XmlElement(name = "coupon_type")
|
||||
@JSONField(name = "coupon_type")
|
||||
private String couponType;
|
||||
/**
|
||||
* 退款入账账户:取当前退款单的退款入账方 1)退回银行卡: {银行名称}{卡类型}{卡尾号} 2)退回支付用户零钱: 支付用户零钱
|
||||
*/
|
||||
@XmlElement(name = "refund_recv_accout")
|
||||
@JSONField(name = "refund_recv_accout")
|
||||
private String refundRecvAccout;
|
||||
/**
|
||||
* 退款成功时间,当退款状态为退款成功时有返回
|
||||
*/
|
||||
@XmlElement(name = "refund_success_time")
|
||||
@JSONField(name = "refund_success_time")
|
||||
private String refundSuccessTime;
|
||||
/**
|
||||
* 退款代金券信息
|
||||
*
|
||||
* @see RefundCouponInfo
|
||||
*/
|
||||
@ListsuffixResult
|
||||
private List<RefundCouponInfo> couponList;
|
||||
|
||||
public String getOutRefundNo() {
|
||||
return outRefundNo;
|
||||
}
|
||||
|
||||
public String getRefundId() {
|
||||
return refundId;
|
||||
}
|
||||
|
||||
public String getRefundChannel() {
|
||||
return refundChannel;
|
||||
}
|
||||
|
||||
@JSONField(serialize = false)
|
||||
public RefundChannel getFormatRefundChannel() {
|
||||
return refundChannel != null ? RefundChannel.valueOf(refundChannel
|
||||
.toUpperCase()) : null;
|
||||
}
|
||||
|
||||
public int getRefundFee() {
|
||||
return refundFee;
|
||||
}
|
||||
|
||||
public String getRefundStatus() {
|
||||
return refundStatus;
|
||||
}
|
||||
|
||||
@JSONField(serialize = false)
|
||||
public RefundStatus getFormatRefundStatus() {
|
||||
return refundStatus != null ? RefundStatus.valueOf(refundStatus
|
||||
.toUpperCase()) : null;
|
||||
}
|
||||
|
||||
public List<RefundCouponInfo> getCouponList() {
|
||||
return couponList;
|
||||
}
|
||||
|
||||
public void setCouponList(List<RefundCouponInfo> couponList) {
|
||||
this.couponList = couponList;
|
||||
}
|
||||
|
||||
public Integer getSettlementRefundFee() {
|
||||
return settlementRefundFee;
|
||||
}
|
||||
|
||||
/**
|
||||
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
|
||||
*
|
||||
* @return 元单位
|
||||
*/
|
||||
@JSONField(serialize = false)
|
||||
public double getFormatSettlementRefundFee() {
|
||||
return settlementRefundFee != null ? settlementRefundFee / 100d : 0d;
|
||||
}
|
||||
|
||||
public Integer getCouponRefundFee() {
|
||||
return couponRefundFee;
|
||||
}
|
||||
|
||||
/**
|
||||
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
|
||||
*
|
||||
* @return 元单位
|
||||
*/
|
||||
@JSONField(serialize = false)
|
||||
public double getFormatCouponRefundFee() {
|
||||
return couponRefundFee != null ? couponRefundFee / 100d : 0d;
|
||||
}
|
||||
|
||||
public Integer getCouponRefundCount() {
|
||||
return couponRefundCount;
|
||||
}
|
||||
|
||||
public String getCouponType() {
|
||||
return couponType;
|
||||
}
|
||||
|
||||
@JSONField(serialize = false)
|
||||
public CouponType getFormatCouponType() {
|
||||
return couponType != null ? CouponType
|
||||
.valueOf(couponType.toUpperCase()) : null;
|
||||
}
|
||||
|
||||
public String getRefundRecvAccout() {
|
||||
return refundRecvAccout;
|
||||
}
|
||||
|
||||
public String getRefundSuccessTime() {
|
||||
return refundSuccessTime;
|
||||
}
|
||||
|
||||
@JSONField(serialize = false)
|
||||
public Date getFormatRefundSuccessTime() {
|
||||
return refundSuccessTime != null ? DateUtil.parse2yyyyMMddHHmmss(refundSuccessTime) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RefundDetail [outRefundNo=" + outRefundNo + ", refundId="
|
||||
+ refundId + ", refundChannel=" + refundChannel
|
||||
+ ", refundFee=" + refundFee + ", refundStatus=" + refundStatus
|
||||
+ ", settlementRefundFee=" + settlementRefundFee
|
||||
+ ", couponRefundFee=" + couponRefundFee
|
||||
+ ", couponRefundCount=" + couponRefundCount + ", couponType="
|
||||
+ couponType + ", refundRecvAccout=" + refundRecvAccout
|
||||
+ ", couponList=" + couponList + "]";
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,81 @@
|
||||
package com.foxinmy.weixin4j.pay.payment.mch;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.foxinmy.weixin4j.xml.ListsuffixResult;
|
||||
|
||||
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 java.util.List;
|
||||
|
||||
/**
|
||||
* 退款记录
|
||||
*
|
||||
* @className RefundRecord
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2014年11月1日
|
||||
* @since JDK 1.6
|
||||
*/
|
||||
@XmlRootElement
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class RefundRecord extends MerchantTradeResult {
|
||||
|
||||
private static final long serialVersionUID = -2971132874939642721L;
|
||||
/**
|
||||
* 退款笔数
|
||||
*/
|
||||
@XmlElement(name = "refund_count")
|
||||
@JSONField(name = "refund_count")
|
||||
private int refundCount;
|
||||
/**
|
||||
* 退款总金额,单位为分,可以做部分退款
|
||||
*/
|
||||
@XmlElement(name = "refund_fee")
|
||||
@JSONField(name = "refund_fee")
|
||||
private int refundFee;
|
||||
/**
|
||||
* 退款详情
|
||||
*
|
||||
* @see RefundDetail
|
||||
*/
|
||||
@ListsuffixResult({ ".*(_\\d)$" })
|
||||
private List<RefundDetail> refundList;
|
||||
|
||||
protected RefundRecord() {
|
||||
// jaxb required
|
||||
}
|
||||
|
||||
public int getRefundCount() {
|
||||
return refundCount;
|
||||
}
|
||||
|
||||
public int getRefundFee() {
|
||||
return refundFee;
|
||||
}
|
||||
|
||||
/**
|
||||
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
|
||||
*
|
||||
* @return 元单位
|
||||
*/
|
||||
@JSONField(serialize = false)
|
||||
public double getFormatRefundFee() {
|
||||
return refundFee / 100d;
|
||||
}
|
||||
|
||||
public List<RefundDetail> getRefundList() {
|
||||
return refundList;
|
||||
}
|
||||
|
||||
public void setRefundList(List<RefundDetail> refundList) {
|
||||
this.refundList = refundList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RefundRecord [refundCount=" + refundCount + ", refundFee="
|
||||
+ refundFee + ", refundList=" + refundList + ", "
|
||||
+ super.toString() + "]";
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,128 @@
|
||||
package com.foxinmy.weixin4j.pay.payment.mch;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.foxinmy.weixin4j.type.mch.RefundChannel;
|
||||
import com.foxinmy.weixin4j.xml.ListsuffixResult;
|
||||
|
||||
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 java.util.List;
|
||||
|
||||
/**
|
||||
* 退款申请结果
|
||||
*
|
||||
* @className RefundResult
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2014年11月6日
|
||||
* @since JDK 1.6
|
||||
* @see
|
||||
*/
|
||||
@XmlRootElement
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class RefundResult extends MerchantTradeResult {
|
||||
|
||||
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;
|
||||
/**
|
||||
* 现金退款金额
|
||||
*/
|
||||
@XmlElement(name = "cash_refund_fee")
|
||||
@JSONField(name = "cash_refund_fee")
|
||||
private Integer cashRefundFee;
|
||||
/**
|
||||
* 退款详情
|
||||
*
|
||||
* @see RefundDetail
|
||||
*/
|
||||
@ListsuffixResult({ ".*(_\\d)$" })
|
||||
private List<RefundDetail> refundList;
|
||||
|
||||
protected RefundResult() {
|
||||
// jaxb required
|
||||
}
|
||||
|
||||
public String getOutRefundNo() {
|
||||
return outRefundNo;
|
||||
}
|
||||
|
||||
public String getRefundId() {
|
||||
return refundId;
|
||||
}
|
||||
|
||||
public String getRefundChannel() {
|
||||
return refundChannel;
|
||||
}
|
||||
|
||||
@JSONField(serialize = false)
|
||||
public RefundChannel getFormatRefundChannel() {
|
||||
return refundChannel != null ? RefundChannel.valueOf(refundChannel
|
||||
.toUpperCase()) : null;
|
||||
}
|
||||
|
||||
public int getRefundFee() {
|
||||
return refundFee;
|
||||
}
|
||||
|
||||
/**
|
||||
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
|
||||
*
|
||||
* @return 元单位
|
||||
*/
|
||||
@JSONField(serialize = false)
|
||||
public double getFormatRefundFee() {
|
||||
return refundFee / 100d;
|
||||
}
|
||||
|
||||
public Integer getCashRefundFee() {
|
||||
return cashRefundFee;
|
||||
}
|
||||
|
||||
/**
|
||||
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
|
||||
*
|
||||
* @return 元单位
|
||||
*/
|
||||
@JSONField(serialize = false)
|
||||
public double getFormatCashRefundFee() {
|
||||
return cashRefundFee != null ? cashRefundFee.intValue() / 100d : 0d;
|
||||
}
|
||||
|
||||
public List<RefundDetail> getRefundList() {
|
||||
return refundList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RefundResult [" + super.toString() + ", outRefundNo="
|
||||
+ outRefundNo + ", refundId=" + refundId + ", refundChannel="
|
||||
+ refundChannel + ", refundFee=" + refundFee
|
||||
+ ", cashRefundFee=" + cashRefundFee + ", refundList="
|
||||
+ refundList + "]";
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,99 @@
|
||||
package com.foxinmy.weixin4j.pay.payment.mch;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
@XmlRootElement
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class SceneInfoApp {
|
||||
/**
|
||||
* 终端类型
|
||||
*/
|
||||
private String type;
|
||||
/**
|
||||
* 应用名称
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 应用路径
|
||||
*/
|
||||
private String path;
|
||||
private String sceneInfo;
|
||||
|
||||
private SceneInfoApp(String type, String name, String path) {
|
||||
this.type = type;
|
||||
this.name = name;
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public String getSceneInfo() {
|
||||
return sceneInfo;
|
||||
}
|
||||
|
||||
public void setSceneInfo(String sceneInfo) {
|
||||
this.sceneInfo = sceneInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* IOS应用
|
||||
*
|
||||
* @param appName 应用名
|
||||
* @param bundleId 模块ID
|
||||
* @return
|
||||
*/
|
||||
public static SceneInfoApp createIOSAPP(String appName, String bundleId) {
|
||||
SceneInfoApp app = new SceneInfoApp("IOS", appName, bundleId);
|
||||
String sceneInfo = String
|
||||
.format("{\"type\": \"%s\",\"app_name\": \"%s\",\"bundle_id\": \"%s\"}",
|
||||
app.getType(), app.getName(), app.getPath());
|
||||
app.setSceneInfo(sceneInfo);
|
||||
return app;
|
||||
}
|
||||
|
||||
/**
|
||||
* Android应用
|
||||
*
|
||||
* @param appName 应用名
|
||||
* @param packageName 包名
|
||||
* @return
|
||||
*/
|
||||
public static SceneInfoApp createAndroidAPP(String appName, String packageName) {
|
||||
SceneInfoApp app = new SceneInfoApp("Android", appName, packageName);
|
||||
String sceneInfo = String
|
||||
.format("{\"type\": \"%s\",\"app_name\": \"%s\",\"package_name\": \"%s\"}",
|
||||
app.getType(), app.getName(), app.getPath());
|
||||
app.setSceneInfo(sceneInfo);
|
||||
return app;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wap应用
|
||||
*
|
||||
* @param name
|
||||
* 网站名
|
||||
* @param url
|
||||
* 网站URL地址
|
||||
* @return
|
||||
*/
|
||||
public static SceneInfoApp createWapAPP(String name, String url) {
|
||||
SceneInfoApp app = new SceneInfoApp("Wap", name, url);
|
||||
String sceneInfo = String.format(
|
||||
"{\"type\": \"%s\",\"wap_name\": \"%s\",\"wap_url\": \"%s\"}",
|
||||
app.getType(), app.getName(), app.getPath());
|
||||
app.setSceneInfo(sceneInfo);
|
||||
return app;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,75 @@
|
||||
package com.foxinmy.weixin4j.pay.payment.mch;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
@XmlRootElement
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class SceneInfoStore {
|
||||
/**
|
||||
* SZTX001 门店唯一标识
|
||||
*/
|
||||
private String id;
|
||||
/**
|
||||
* 腾讯大厦腾大餐厅 门店名称
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 门店所在地行政区划码,详细见《最新县及县以上行政区划代码》
|
||||
*/
|
||||
@XmlElement(name = "area_code")
|
||||
@JSONField(name = "area_code")
|
||||
private String areaCode;
|
||||
/**
|
||||
* 科技园中一路腾讯大厦 门店详细地址
|
||||
*/
|
||||
private String address;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getAreaCode() {
|
||||
return areaCode;
|
||||
}
|
||||
|
||||
public void setAreaCode(String areaCode) {
|
||||
this.areaCode = areaCode;
|
||||
}
|
||||
|
||||
public String getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public void setAddress(String address) {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public SceneInfoStore(String id, String name) {
|
||||
super();
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SceneInfoStore [id=" + id + ", name=" + name + ", areaCode="
|
||||
+ areaCode + ", address=" + address + "]";
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,272 @@
|
||||
package com.foxinmy.weixin4j.pay.payment.mch;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.foxinmy.weixin4j.type.CurrencyType;
|
||||
import com.foxinmy.weixin4j.util.DateUtil;
|
||||
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 结算资金
|
||||
*
|
||||
* @className Settlement
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2016年3月26日
|
||||
* @since JDK 1.6
|
||||
* @see
|
||||
*/
|
||||
public class SettlementRecord extends MerchantResult {
|
||||
|
||||
private static final long serialVersionUID = 7952659545609519979L;
|
||||
|
||||
/**
|
||||
* 付款批次号
|
||||
*/
|
||||
@XmlElement(name = "fbatchno")
|
||||
@JSONField(name = "fbatchno")
|
||||
private String batchNo;
|
||||
/**
|
||||
* 结算日期
|
||||
*/
|
||||
@XmlElement(name = "date_settlement")
|
||||
@JSONField(name = "date_settlement")
|
||||
private String settleDate;
|
||||
/**
|
||||
* 交易开始日期
|
||||
*/
|
||||
@XmlElement(name = "date_start")
|
||||
@JSONField(name = "date_start")
|
||||
private String startDate;
|
||||
/**
|
||||
* 交易结束日期
|
||||
*/
|
||||
@XmlElement(name = "date_end")
|
||||
@JSONField(name = "date_end")
|
||||
private String endDate;
|
||||
/**
|
||||
* 划账金额:外币标价,外币最小单位
|
||||
*/
|
||||
@XmlElement(name = "transaction_id")
|
||||
@JSONField(name = "transaction_id")
|
||||
private int settleFee;
|
||||
/**
|
||||
* 未划账金额:外币标价,外币最小单位
|
||||
*/
|
||||
@XmlElement(name = "unsettlement_fee")
|
||||
@JSONField(name = "unsettlement_fee")
|
||||
private int unSettleFee;
|
||||
/**
|
||||
* 结算币种
|
||||
*/
|
||||
@XmlElement(name = "settlementfee_type")
|
||||
@JSONField(name = "settlementfee_type")
|
||||
private String settleFeeType;
|
||||
/**
|
||||
* 支付金额:外币标价,外币最小单位
|
||||
*/
|
||||
@XmlElement(name = "pay_fee")
|
||||
@JSONField(name = "pay_fee")
|
||||
private int payFee;
|
||||
/**
|
||||
* 退款金额:外币标价,外币最小单位
|
||||
*/
|
||||
@XmlElement(name = "refund_fee")
|
||||
@JSONField(name = "refund_fee")
|
||||
private int refundFee;
|
||||
/**
|
||||
* 支付净额:外币标价,外币最小单位
|
||||
*/
|
||||
@XmlElement(name = "pay_net_fee")
|
||||
@JSONField(name = "pay_net_fee")
|
||||
private int payNetFee;
|
||||
/**
|
||||
* 手续费金额:外币标价,外币最小单位
|
||||
*/
|
||||
@XmlElement(name = "poundage_fee")
|
||||
@JSONField(name = "poundage_fee")
|
||||
private int poundageFee;
|
||||
|
||||
protected SettlementRecord() {
|
||||
// jaxb required
|
||||
}
|
||||
|
||||
public String getBatchNo() {
|
||||
return batchNo;
|
||||
}
|
||||
|
||||
public void setBatchNo(String batchNo) {
|
||||
this.batchNo = batchNo;
|
||||
}
|
||||
|
||||
public String getSettleDate() {
|
||||
return settleDate;
|
||||
}
|
||||
|
||||
@JSONField(serialize = false)
|
||||
public Date getFormatSettleDate() {
|
||||
return DateUtil.parse2yyyyMMddHHmmss(settleDate);
|
||||
}
|
||||
|
||||
public void setSettleDate(String settleDate) {
|
||||
this.settleDate = settleDate;
|
||||
}
|
||||
|
||||
public String getStartDate() {
|
||||
return startDate;
|
||||
}
|
||||
|
||||
@JSONField(serialize = false)
|
||||
public Date getFormatStartDate() {
|
||||
return DateUtil.parse2yyyyMMddHHmmss(startDate);
|
||||
}
|
||||
|
||||
public void setStartDate(String startDate) {
|
||||
this.startDate = startDate;
|
||||
}
|
||||
|
||||
public String getEndDate() {
|
||||
return endDate;
|
||||
}
|
||||
|
||||
@JSONField(serialize = false)
|
||||
public Date getFormatEndDate() {
|
||||
return DateUtil.parse2yyyyMMddHHmmss(settleDate);
|
||||
}
|
||||
|
||||
public void setEndDate(String endDate) {
|
||||
this.endDate = endDate;
|
||||
}
|
||||
|
||||
public int getSettleFee() {
|
||||
return settleFee;
|
||||
}
|
||||
|
||||
/**
|
||||
* <font color="red">最小单位除100得到的值</font>
|
||||
*
|
||||
* @return /100
|
||||
*/
|
||||
@JSONField(serialize = false)
|
||||
public double getFormatSettleFee() {
|
||||
return settleFee / 100d;
|
||||
}
|
||||
|
||||
public void setSettleFee(int settleFee) {
|
||||
this.settleFee = settleFee;
|
||||
}
|
||||
|
||||
public int getUnSettleFee() {
|
||||
return unSettleFee;
|
||||
}
|
||||
|
||||
/**
|
||||
* <font color="red">最小单位除100得到的值</font>
|
||||
*
|
||||
* @return /100
|
||||
*/
|
||||
@JSONField(serialize = false)
|
||||
public double getFormatUnSettleFee() {
|
||||
return unSettleFee / 100d;
|
||||
}
|
||||
|
||||
public void setUnSettleFee(int unSettleFee) {
|
||||
this.unSettleFee = unSettleFee;
|
||||
}
|
||||
|
||||
public String getSettleFeeType() {
|
||||
return settleFeeType;
|
||||
}
|
||||
|
||||
@JSONField(serialize = false)
|
||||
public CurrencyType getFormatSettleFeeType() {
|
||||
return CurrencyType.valueOf(settleFeeType.toUpperCase());
|
||||
}
|
||||
|
||||
public void setSettleFeeType(String settleFeeType) {
|
||||
this.settleFeeType = settleFeeType;
|
||||
}
|
||||
|
||||
public int getPayFee() {
|
||||
return payFee;
|
||||
}
|
||||
|
||||
/**
|
||||
* <font color="red">最小单位除100得到的值</font>
|
||||
*
|
||||
* @return /100
|
||||
*/
|
||||
@JSONField(serialize = false)
|
||||
public double getFormatPayFee() {
|
||||
return payFee / 100d;
|
||||
}
|
||||
|
||||
public void setPayFee(int payFee) {
|
||||
this.payFee = payFee;
|
||||
}
|
||||
|
||||
public int getRefundFee() {
|
||||
return refundFee;
|
||||
}
|
||||
|
||||
/**
|
||||
* <font color="red">最小单位除100得到的值</font>
|
||||
*
|
||||
* @return /100
|
||||
*/
|
||||
@JSONField(serialize = false)
|
||||
public double getFormatRefundFee() {
|
||||
return refundFee / 100d;
|
||||
}
|
||||
|
||||
public void setRefundFee(int refundFee) {
|
||||
this.refundFee = refundFee;
|
||||
}
|
||||
|
||||
public int getPayNetFee() {
|
||||
return payNetFee;
|
||||
}
|
||||
|
||||
public void setPayNetFee(int payNetFee) {
|
||||
this.payNetFee = payNetFee;
|
||||
}
|
||||
|
||||
/**
|
||||
* <font color="red">最小单位除100得到的值</font>
|
||||
*
|
||||
* @return /100
|
||||
*/
|
||||
@JSONField(serialize = false)
|
||||
public double getFormatPayNetFee() {
|
||||
return payNetFee / 100d;
|
||||
}
|
||||
|
||||
public int getPoundageFee() {
|
||||
return poundageFee;
|
||||
}
|
||||
|
||||
/**
|
||||
* <font color="red">最小单位除100得到的值</font>
|
||||
*
|
||||
* @return /100
|
||||
*/
|
||||
@JSONField(serialize = false)
|
||||
public double getFormatPoundageFee() {
|
||||
return poundageFee / 100d;
|
||||
}
|
||||
|
||||
public void setPoundageFee(int poundageFee) {
|
||||
this.poundageFee = poundageFee;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SettlementRecord [batchNo=" + batchNo + ", settleDate="
|
||||
+ settleDate + ", startDate=" + startDate + ", endDate="
|
||||
+ endDate + ", settleFee=" + settleFee + ", unSettleFee="
|
||||
+ unSettleFee + ", settleFeeType=" + settleFeeType
|
||||
+ ", payFee=" + payFee + ", refundFee=" + refundFee
|
||||
+ ", payNetFee=" + payNetFee + ", poundageFee=" + poundageFee
|
||||
+ ", " + super.toString() + "]";
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
package com.foxinmy.weixin4j.pay.payment.mch;
|
||||
|
||||
import com.foxinmy.weixin4j.pay.model.WeixinPayAccount;
|
||||
import com.foxinmy.weixin4j.pay.payment.PayRequest;
|
||||
import com.foxinmy.weixin4j.pay.type.TradeType;
|
||||
|
||||
/**
|
||||
* WAP支付
|
||||
*
|
||||
* @className WAPPayRequest
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2015年12月25日
|
||||
* @since JDK 1.6
|
||||
* @see PrePay
|
||||
* @see PayRequest
|
||||
* @see <a
|
||||
* href="https://pay.weixin.qq.com/wiki/doc/api/wap.php?chapter=15_1">WAP支付</a>
|
||||
*/
|
||||
public class WAPPayRequest extends AbstractPayRequest {
|
||||
/**
|
||||
* 微信支付URL
|
||||
*/
|
||||
private final String payUrl;
|
||||
|
||||
public WAPPayRequest(String prePayId, String payUrl,
|
||||
WeixinPayAccount payAccount) {
|
||||
super(prePayId, payAccount);
|
||||
this.payUrl = payUrl;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public TradeType getPaymentType() {
|
||||
return TradeType.MWEB;
|
||||
}
|
||||
|
||||
/**
|
||||
* <font color="red">只做查看之用,请不要尝试作为支付请求</font>
|
||||
*/
|
||||
@Override
|
||||
public PayRequest toRequestObject() {
|
||||
PayRequest payRequest = new PayRequest(getPaymentAccount().getId(),
|
||||
getPaymentType().name());
|
||||
payRequest.setPrepayId(getPrePayId());
|
||||
return payRequest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toRequestString() {
|
||||
// PayRequest payRequest = toRequestObject();
|
||||
// String original = MapUtil.toJoinString(payRequest, true, true);
|
||||
// String sign = DigestUtil.MD5(
|
||||
// String.format("%s&key=%s", original, getPaymentAccount()
|
||||
// .getPaySignKey())).toUpperCase();
|
||||
// return String.format("weixin://wap/pay?%s",
|
||||
// URLEncodingUtil.encoding(
|
||||
// String.format("%s&sign=%s", original, sign),
|
||||
// Consts.UTF_8, true));
|
||||
return this.payUrl;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,45 @@
|
||||
package com.foxinmy.weixin4j.pay.sign;
|
||||
|
||||
import com.foxinmy.weixin4j.util.MapUtil;
|
||||
|
||||
/**
|
||||
* 微信签名
|
||||
*
|
||||
* @className AbstractWeixinSignature
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2016年3月26日
|
||||
* @since JDK 1.6
|
||||
* @see
|
||||
*/
|
||||
public abstract class AbstractWeixinSignature implements WeixinSignature {
|
||||
/**
|
||||
* 是否编码
|
||||
*
|
||||
* @return 默认false不进行编码
|
||||
*/
|
||||
@Override
|
||||
public boolean encoder() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否转换小写
|
||||
*
|
||||
* @return 默认false不转换小写
|
||||
*/
|
||||
@Override
|
||||
public boolean lowerCase() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼接字符串
|
||||
*
|
||||
* @param obj
|
||||
* @return
|
||||
*/
|
||||
protected StringBuilder join(Object obj) {
|
||||
return new StringBuilder(MapUtil.toJoinString(obj, encoder(),
|
||||
lowerCase()));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
package com.foxinmy.weixin4j.pay.sign;
|
||||
|
||||
import com.foxinmy.weixin4j.pay.type.SignType;
|
||||
import com.foxinmy.weixin4j.util.DigestUtil;
|
||||
|
||||
/**
|
||||
* 微信支付签名实现
|
||||
*
|
||||
* @className WeixinPaymentSignature
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2016年3月26日
|
||||
* @since JDK 1.6
|
||||
* @see <a
|
||||
* href="https://pay.weixin.qq.com/wiki/doc/api/external/jsapi.php?chapter=4_3">支付签名说明</a>
|
||||
*/
|
||||
public class WeixinPaymentSignature extends AbstractWeixinSignature {
|
||||
/**
|
||||
* 支付密钥
|
||||
*/
|
||||
private final String paySignKey;
|
||||
|
||||
public WeixinPaymentSignature(String paySignKey) {
|
||||
this.paySignKey = paySignKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignType getSignType() {
|
||||
return SignType.MD5;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String sign(Object obj) {
|
||||
StringBuilder sb = join(obj).append("&key=").append(paySignKey);
|
||||
return DigestUtil.MD5(sb.toString()).toUpperCase();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
package com.foxinmy.weixin4j.pay.sign;
|
||||
|
||||
import com.foxinmy.weixin4j.pay.type.SignType;
|
||||
|
||||
/**
|
||||
* 微信签名
|
||||
*
|
||||
* @className WeixinSignature
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2016年3月26日
|
||||
* @since JDK 1.6
|
||||
* @see
|
||||
*/
|
||||
public interface WeixinSignature {
|
||||
/**
|
||||
* 是否编码
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean encoder();
|
||||
|
||||
/**
|
||||
* 是否转换小写
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean lowerCase();
|
||||
|
||||
/**
|
||||
* 签名类型
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public SignType getSignType();
|
||||
|
||||
/**
|
||||
* 签名
|
||||
*
|
||||
* @param obj
|
||||
* @return
|
||||
*/
|
||||
public String sign(Object obj);
|
||||
}
|
||||
@ -0,0 +1,260 @@
|
||||
package com.foxinmy.weixin4j.pay.type;
|
||||
|
||||
|
||||
/**
|
||||
* 银行类型
|
||||
*
|
||||
* @className BankType
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2015年8月19日
|
||||
* @since JDK 1.6
|
||||
* @see
|
||||
*/
|
||||
public enum BankType {
|
||||
/**
|
||||
* 工商银行(借记卡)
|
||||
*/
|
||||
ICBC_DEBIT("工商银行(借记卡)"),
|
||||
/**
|
||||
* 工商银行(信用卡)
|
||||
*/
|
||||
ICBC_CREDIT("工商银行(信用卡)"),
|
||||
/**
|
||||
* 农业银行(借记卡)
|
||||
*/
|
||||
ABC_DEBIT("农业银行(借记卡)"),
|
||||
/**
|
||||
* 农业银行 (信用卡)
|
||||
*/
|
||||
ABC_CREDIT("农业银行 (信用卡)"),
|
||||
/**
|
||||
* 邮政储蓄(借记卡)
|
||||
*/
|
||||
PSBC_DEBIT("邮政储蓄(借记卡)"),
|
||||
/**
|
||||
* 邮政储蓄 (信用卡)
|
||||
*/
|
||||
PSBC_CREDIT("邮政储蓄 (信用卡)"),
|
||||
/**
|
||||
* 建设银行(借记卡)
|
||||
*/
|
||||
CCB_DEBIT("建设银行(借记卡)"),
|
||||
/**
|
||||
* 建设银行 (信用卡)
|
||||
*/
|
||||
CCB_CREDIT("建设银行 (信用卡)"),
|
||||
/**
|
||||
* 招商银行(借记卡)
|
||||
*/
|
||||
CMB_DEBIT("招商银行(借记卡)"),
|
||||
/**
|
||||
* 招商银行(信用卡)
|
||||
*/
|
||||
CMB_CREDIT("招商银行(信用卡)"),
|
||||
/**
|
||||
* 交通银行(借记卡)
|
||||
*/
|
||||
COMM_DEBIT("交通银行(借记卡)"),
|
||||
/**
|
||||
* 中国银行(信用卡)
|
||||
*/
|
||||
BOC_CREDIT("中国银行(信用卡)"),
|
||||
/**
|
||||
* 浦发银行(借记卡)
|
||||
*/
|
||||
SPDB_DEBIT("浦发银行(借记卡)"),
|
||||
/**
|
||||
* 浦发银行 (信用卡)
|
||||
*/
|
||||
SPDB_CREDIT("浦发银行 (信用卡)"),
|
||||
/**
|
||||
* 广发银行(借记卡)
|
||||
*/
|
||||
GDB_DEBIT("广发银行(借记卡)"),
|
||||
/**
|
||||
* 广发银行(信用卡)
|
||||
*/
|
||||
GDB_CREDIT("广发银行(信用卡)"),
|
||||
/**
|
||||
* 民生银行(借记卡)
|
||||
*/
|
||||
CMBC_DEBIT("民生银行(借记卡)"),
|
||||
/**
|
||||
* 民生银行(信用卡)
|
||||
*/
|
||||
CMBC_CREDIT("民生银行(信用卡)"),
|
||||
/**
|
||||
* 平安银行(借记卡)
|
||||
*/
|
||||
PAB_DEBIT("平安银行(借记卡)"),
|
||||
/**
|
||||
* 平安银行(信用卡)
|
||||
*/
|
||||
PAB_CREDIT("平安银行(信用卡)"),
|
||||
/**
|
||||
* 光大银行(借记卡)
|
||||
*/
|
||||
CEB_DEBIT("光大银行(借记卡)"),
|
||||
/**
|
||||
* 光大银行(信用卡)
|
||||
*/
|
||||
CEB_CREDIT("光大银行(信用卡)"),
|
||||
/**
|
||||
* 兴业银行 (借记卡)
|
||||
*/
|
||||
CIB_DEBIT("兴业银行 (借记卡)"),
|
||||
/**
|
||||
* 兴业银行(信用卡)
|
||||
*/
|
||||
CIB_CREDIT("兴业银行(信用卡)"),
|
||||
/**
|
||||
* 中信银行(借记卡)
|
||||
*/
|
||||
CITIC_DEBIT("中信银行(借记卡)"),
|
||||
/**
|
||||
* 中信银行(信用卡)
|
||||
*/
|
||||
CITIC_CREDIT("中信银行(信用卡)"),
|
||||
/**
|
||||
* 深发银行(信用卡)
|
||||
*/
|
||||
SDB_CREDIT("深发银行(信用卡)"),
|
||||
/**
|
||||
* 上海银行(借记卡)
|
||||
*/
|
||||
BOSH_DEBIT("上海银行(借记卡)"),
|
||||
/**
|
||||
* 上海银行 (信用卡)
|
||||
*/
|
||||
BOSH_CREDIT("上海银行 (信用卡)"),
|
||||
/**
|
||||
* 华润银行(借记卡)
|
||||
*/
|
||||
CRB_DEBIT("华润银行(借记卡)"),
|
||||
/**
|
||||
* 杭州银行(借记卡)
|
||||
*/
|
||||
HZB_DEBIT("杭州银行(借记卡)"),
|
||||
/**
|
||||
* 杭州银行(信用卡)
|
||||
*/
|
||||
HZB_CREDIT("杭州银行(信用卡)"),
|
||||
/**
|
||||
* 包商银行(借记卡)
|
||||
*/
|
||||
BSB_DEBIT("包商银行(借记卡)"),
|
||||
/**
|
||||
* 包商银行 (信用卡)
|
||||
*/
|
||||
BSB_CREDIT("包商银行 (信用卡)"),
|
||||
/**
|
||||
* 重庆银行(借记卡)
|
||||
*/
|
||||
CQB_DEBIT("重庆银行(借记卡)"),
|
||||
/**
|
||||
* 顺德农商行 (借记卡)
|
||||
*/
|
||||
SDEB_DEBIT("顺德农商行 (借记卡)"),
|
||||
/**
|
||||
* 深圳农商银行(借记卡)
|
||||
*/
|
||||
SZRCB_DEBIT("深圳农商银行(借记卡)"),
|
||||
/**
|
||||
* 哈尔滨银行(借记卡)
|
||||
*/
|
||||
HRBB_DEBIT("哈尔滨银行(借记卡)"),
|
||||
/**
|
||||
* 成都银行(借记卡)
|
||||
*/
|
||||
BOCD_DEBIT("成都银行(借记卡)"),
|
||||
/**
|
||||
* 南粤银行 (借记卡)
|
||||
*/
|
||||
GDNYB_DEBIT("南粤银行 (借记卡)"),
|
||||
/**
|
||||
* 南粤银行 (信用卡)
|
||||
*/
|
||||
GDNYB_CREDIT("南粤银行 (信用卡)"),
|
||||
/**
|
||||
* 广州银行(信用卡)
|
||||
*/
|
||||
GZCB_CREDIT("广州银行(信用卡)"),
|
||||
/**
|
||||
* 江苏银行(借记卡)
|
||||
*/
|
||||
JSB_DEBIT("江苏银行(借记卡)"),
|
||||
/**
|
||||
* 江苏银行(信用卡)
|
||||
*/
|
||||
JSB_CREDIT("江苏银行(信用卡)"),
|
||||
/**
|
||||
* 宁波银行(借记卡)
|
||||
*/
|
||||
NBCB_DEBIT("宁波银行(借记卡)"),
|
||||
/**
|
||||
* 宁波银行(信用卡)
|
||||
*/
|
||||
NBCB_CREDIT("宁波银行(信用卡)"),
|
||||
/**
|
||||
* 南京银行(借记卡)
|
||||
*/
|
||||
NJCB_DEBIT("南京银行(借记卡)"),
|
||||
/**
|
||||
* 青岛银行(借记卡)
|
||||
*/
|
||||
QDCCB_DEBIT("青岛银行(借记卡)"),
|
||||
/**
|
||||
* 浙江泰隆银行(借记卡)
|
||||
*/
|
||||
ZJTLCB_DEBIT("浙江泰隆银行(借记卡)"),
|
||||
/**
|
||||
* 西安银行(借记卡)
|
||||
*/
|
||||
XAB_DEBIT("西安银行(借记卡)"),
|
||||
/**
|
||||
* 常熟农商银行 (借记卡)
|
||||
*/
|
||||
CSRCB_DEBIT("常熟农商银行 (借记卡)"),
|
||||
/**
|
||||
* 齐鲁银行(借记卡)
|
||||
*/
|
||||
QLB_DEBIT("齐鲁银行(借记卡)"),
|
||||
/**
|
||||
* 龙江银行(借记卡)
|
||||
*/
|
||||
LJB_DEBIT("龙江银行(借记卡)"),
|
||||
/**
|
||||
* 华夏银行(借记卡)
|
||||
*/
|
||||
HXB_DEBIT("华夏银行(借记卡)"),
|
||||
/**
|
||||
* 测试银行借记卡快捷支付 (借记卡)
|
||||
*/
|
||||
CS_DEBIT("测试银行借记卡快捷支付 (借记卡)"),
|
||||
/**
|
||||
* AE (信用卡)
|
||||
*/
|
||||
AE_CREDIT("AE (信用卡)"),
|
||||
/**
|
||||
* JCB (信用卡)
|
||||
*/
|
||||
JCB_CREDIT("JCB (信用卡)"),
|
||||
/**
|
||||
* MASTERCARD (信用卡)
|
||||
*/
|
||||
MASTERCARD_CREDIT("MASTERCARD (信用卡)"),
|
||||
/**
|
||||
* VISA (信用卡)
|
||||
*/
|
||||
VISA_CREDIT("VISA (信用卡)");
|
||||
|
||||
private String desc;
|
||||
|
||||
BankType(String desc) {
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
package com.foxinmy.weixin4j.pay.type;
|
||||
|
||||
/**
|
||||
* 证件类型
|
||||
*
|
||||
* @className CredentialType
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2016年3月27日
|
||||
* @since JDK 1.6
|
||||
* @see
|
||||
*/
|
||||
public enum CredentialType {
|
||||
IDCARD("身份证");
|
||||
CredentialType(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
private String name;
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
package com.foxinmy.weixin4j.pay.type;
|
||||
|
||||
/**
|
||||
* 币种
|
||||
*
|
||||
* @className CurrencyType
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2014年11月2日
|
||||
* @since JDK 1.6
|
||||
* @see
|
||||
*/
|
||||
public enum CurrencyType {
|
||||
CNY("人民币"), HKD("港元"), TWD("台币"), EUR("欧元"), USD("美元"), GBP("英镑"), JPY("日元"), CAD(
|
||||
"加拿大元"), AUD("澳大利亚元"), NZD("新西兰元"), KRW("韩元"), THB("泰铢");
|
||||
|
||||
private String desc;
|
||||
|
||||
CurrencyType(String desc) {
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
package com.foxinmy.weixin4j.pay.type;
|
||||
|
||||
/**
|
||||
* 海关
|
||||
*
|
||||
* @className CustomsCity
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2016年3月27日
|
||||
* @since JDK 1.6
|
||||
* @see
|
||||
*/
|
||||
public enum CustomsCity {
|
||||
NO("无需上报海关"), GUANGZHOU("广州"), HANGZHOU("杭州"), NINGBO("宁波"), ZHENGZHOU_BS(
|
||||
"郑州(保税物流中心)"), CHONGQING("重庆"), XIAN("西安"), SHANGHAI("上海"), ZHENGZHOU_ZH(
|
||||
"郑州(综保区)");
|
||||
|
||||
private String name;
|
||||
|
||||
CustomsCity(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
package com.foxinmy.weixin4j.pay.type;
|
||||
|
||||
/**
|
||||
* 报关状态
|
||||
*
|
||||
* @className CustomsSatus
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2016年3月27日
|
||||
* @since JDK 1.6
|
||||
* @see
|
||||
*/
|
||||
public enum CustomsSatus {
|
||||
UNDECLARED("未申报"), SUBMITTED("申报已提交"), PROCESSING("申报中"), SUCCESS("申报成功"), FAIL(
|
||||
"申报失败"), EXCEPT("海关接口异常");
|
||||
private String sate;
|
||||
|
||||
CustomsSatus(String sate) {
|
||||
this.sate = sate;
|
||||
}
|
||||
|
||||
public String getSate() {
|
||||
return this.sate;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,45 @@
|
||||
package com.foxinmy.weixin4j.pay.type;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* ID查询
|
||||
*
|
||||
* @className IdQuery
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2014年11月1日
|
||||
* @since JDK 1.6
|
||||
* @see
|
||||
*/
|
||||
public class IdQuery implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -5273675987521807370L;
|
||||
/**
|
||||
* id值
|
||||
*/
|
||||
private String id;
|
||||
/**
|
||||
* id类型
|
||||
*
|
||||
* @see IdType
|
||||
*/
|
||||
private IdType type;
|
||||
|
||||
public IdQuery(String id, IdType idType) {
|
||||
this.id = id;
|
||||
this.type = idType;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public IdType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s=%s", type.getName(), id);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,46 @@
|
||||
package com.foxinmy.weixin4j.pay.type;
|
||||
|
||||
/**
|
||||
* ID类型
|
||||
*
|
||||
* @className IdType
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2014年11月1日
|
||||
* @since JDK 1.6
|
||||
* @see
|
||||
*/
|
||||
public enum IdType {
|
||||
/**
|
||||
* 微信退款单号
|
||||
*/
|
||||
REFUNDID("refund_id"),
|
||||
/**
|
||||
* 微信订单号
|
||||
*/
|
||||
TRANSACTIONID("transaction_id"),
|
||||
/**
|
||||
* 商户订单号
|
||||
*/
|
||||
TRADENO("out_trade_no"),
|
||||
/**
|
||||
* 商户退款号
|
||||
*/
|
||||
REFUNDNO("out_refund_no"),
|
||||
/**
|
||||
* 商户子订单号
|
||||
*/
|
||||
SUBORDERNO("sub_order_no"),
|
||||
/**
|
||||
* 微信子订单号
|
||||
*/
|
||||
SUBORDERID("sub_order_id");
|
||||
private String name;
|
||||
|
||||
IdType(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
package com.foxinmy.weixin4j.pay.type;
|
||||
|
||||
/**
|
||||
* 签名类型
|
||||
*
|
||||
* @className SignType
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2014年11月5日
|
||||
* @since JDK 1.6
|
||||
* @see
|
||||
*/
|
||||
public enum SignType {
|
||||
SHA1, MD5, HMAC$SHA256
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
package com.foxinmy.weixin4j.pay.type;
|
||||
|
||||
/**
|
||||
* 压缩类型
|
||||
*
|
||||
* @className TarType
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2016年12月21日
|
||||
* @since JDK 1.6
|
||||
* @see
|
||||
*/
|
||||
public enum TarType {
|
||||
GZIP
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
package com.foxinmy.weixin4j.pay.type;
|
||||
|
||||
/**
|
||||
* 微信支付类型
|
||||
*
|
||||
* @className TradeType
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2014年10月21日
|
||||
* @since JDK 1.6
|
||||
* @see
|
||||
*/
|
||||
public enum TradeType {
|
||||
/**
|
||||
* JS支付
|
||||
*/
|
||||
JSAPI,
|
||||
/**
|
||||
* 刷卡支付
|
||||
*/
|
||||
MICROPAY,
|
||||
/**
|
||||
* 扫码支付
|
||||
*/
|
||||
NATIVE,
|
||||
/**
|
||||
* APP支付
|
||||
*/
|
||||
APP,
|
||||
/**
|
||||
* WAP支付
|
||||
*/
|
||||
MWEB;
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
package com.foxinmy.weixin4j.pay.type.mch;
|
||||
|
||||
/**
|
||||
* 对账单类型
|
||||
*
|
||||
* @className BillType
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2014年10月31日
|
||||
* @since JDK 1.6
|
||||
* @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,25 @@
|
||||
package com.foxinmy.weixin4j.pay.type.mch;
|
||||
|
||||
/**
|
||||
* 企业付款检查收款人姓名的策略
|
||||
*
|
||||
* @className CorpPaymentCheckNameType
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2015年4月1日
|
||||
* @since JDK 1.6
|
||||
* @see
|
||||
*/
|
||||
public enum CorpPaymentCheckNameType {
|
||||
/**
|
||||
* 不校验真实姓名
|
||||
*/
|
||||
NO_CHECK,
|
||||
/**
|
||||
* 强校验真实姓名(未实名认证的用户会校验失败,无法转账)
|
||||
*/
|
||||
FORCE_CHECK,
|
||||
/**
|
||||
* 针对已实名认证的用户才校验真实姓名(未实名认证用户不校验,可以转账成功)
|
||||
*/
|
||||
OPTION_CHECK;
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
package com.foxinmy.weixin4j.pay.type.mch;
|
||||
|
||||
/**
|
||||
* 代金券状态
|
||||
*
|
||||
* @className CouponStatus
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2015年3月27日
|
||||
* @since JDK 1.6
|
||||
* @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.pay.type.mch;
|
||||
|
||||
/**
|
||||
* 代金券批次状态
|
||||
*
|
||||
* @className CouponStockStatus
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2015年3月27日
|
||||
* @since JDK 1.6
|
||||
* @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.pay.type.mch;
|
||||
|
||||
/**
|
||||
* 代金券批次类型
|
||||
*
|
||||
* @className CouponStockType
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2015年3月27日
|
||||
* @since JDK 1.6
|
||||
* @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,43 @@
|
||||
package com.foxinmy.weixin4j.pay.type.mch;
|
||||
|
||||
/**
|
||||
* 代金券类型
|
||||
*
|
||||
* @className CouponType
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2015年3月27日
|
||||
* @since JDK 1.6
|
||||
* @see
|
||||
*/
|
||||
public enum CouponType {
|
||||
/**
|
||||
* 使用无门槛
|
||||
*/
|
||||
NO_THRESHOLD(1),
|
||||
/**
|
||||
* 使用有门槛
|
||||
*/
|
||||
HAS_THRESHOLD(2),
|
||||
/**
|
||||
* 门槛叠加
|
||||
*/
|
||||
THRESHOLD_PLUS(3),
|
||||
|
||||
/**
|
||||
* 充值代金券
|
||||
*/
|
||||
CASH(-1),
|
||||
/**
|
||||
* 非充值代金券
|
||||
*/
|
||||
NO_CASH(-2);
|
||||
private int val;
|
||||
|
||||
CouponType(int val) {
|
||||
this.val = val;
|
||||
}
|
||||
|
||||
public int getVal() {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
package com.foxinmy.weixin4j.pay.type.mch;
|
||||
|
||||
/**
|
||||
* 发放红包使用场景
|
||||
*
|
||||
* @className RedpacketSceneType
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2017年1月4日
|
||||
* @since JDK 1.6
|
||||
*/
|
||||
public enum RedpacketSceneType {
|
||||
/**
|
||||
* 商品促销
|
||||
*/
|
||||
PRODUCT_1,
|
||||
/**
|
||||
* 抽奖
|
||||
*/
|
||||
PRODUCT_2,
|
||||
/**
|
||||
* 虚拟物品兑奖
|
||||
*/
|
||||
PRODUCT_3,
|
||||
/**
|
||||
* 企业内部福利
|
||||
*/
|
||||
PRODUCT_4,
|
||||
/**
|
||||
* 渠道分润
|
||||
*/
|
||||
PRODUCT_5,
|
||||
/**
|
||||
* 保险回馈
|
||||
*/
|
||||
PRODUCT_6,
|
||||
/**
|
||||
* 彩票派奖
|
||||
*/
|
||||
PRODUCT_7,
|
||||
/**
|
||||
* 税务刮奖
|
||||
*/
|
||||
PRODUCT_8
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
package com.foxinmy.weixin4j.pay.type.mch;
|
||||
|
||||
/**
|
||||
* 红包发放类型
|
||||
*
|
||||
* @className RedpacketSendType
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2015年6月4日
|
||||
* @since JDK 1.6
|
||||
* @see
|
||||
*/
|
||||
public enum RedpacketSendType {
|
||||
/**
|
||||
* 通过API接口发放
|
||||
*/
|
||||
API,
|
||||
/**
|
||||
* 通过上传文件方式发放
|
||||
*/
|
||||
UPLOAD,
|
||||
/**
|
||||
* 通过活动方式发放
|
||||
*/
|
||||
ACTIVITY;
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
package com.foxinmy.weixin4j.pay.type.mch;
|
||||
|
||||
/**
|
||||
* 红包状态
|
||||
* @className RedpacketStatus
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2015年6月4日
|
||||
* @since JDK 1.6
|
||||
* @see
|
||||
*/
|
||||
public enum RedpacketStatus {
|
||||
/**
|
||||
* 发放中
|
||||
*/
|
||||
SENDING,
|
||||
/**
|
||||
* 已发放待领取
|
||||
*/
|
||||
SENT,
|
||||
/**
|
||||
* 发放失败
|
||||
*/
|
||||
FAILED,
|
||||
/**
|
||||
* 已领取
|
||||
*/
|
||||
RECEIVED,
|
||||
/**
|
||||
* 已退款
|
||||
*/
|
||||
REFUND;
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
package com.foxinmy.weixin4j.pay.type.mch;
|
||||
|
||||
/**
|
||||
* 红包类型
|
||||
*
|
||||
* @className RedpacketType
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2015年6月4日
|
||||
* @since JDK 1.6
|
||||
* @see
|
||||
*/
|
||||
public enum RedpacketType {
|
||||
/**
|
||||
* 裂变红包
|
||||
*/
|
||||
GROUP,
|
||||
/**
|
||||
* 普通红包
|
||||
*/
|
||||
NORMAL;
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
package com.foxinmy.weixin4j.pay.type.mch;
|
||||
|
||||
/**
|
||||
* 退款资金来源
|
||||
* @className RefundAccountType
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2016年12月12日
|
||||
*/
|
||||
public enum RefundAccountType {
|
||||
/**
|
||||
* ---未结算资金退款(默认使用未结算资金退款)
|
||||
*/
|
||||
REFUND_SOURCE_UNSETTLED_FUNDS,
|
||||
/**
|
||||
* ---可用余额退款
|
||||
*/
|
||||
REFUND_SOURCE_RECHARGE_FUNDS
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
package com.foxinmy.weixin4j.pay.type.mch;
|
||||
|
||||
/**
|
||||
* 退款渠道
|
||||
*
|
||||
* @className RefundChannel
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2014年11月6日
|
||||
* @since JDK 1.6
|
||||
* @see
|
||||
*/
|
||||
public enum RefundChannel {
|
||||
/**
|
||||
* 原路退款
|
||||
*/
|
||||
ORIGINAL,
|
||||
/**
|
||||
* 退回到余额
|
||||
*/
|
||||
BALANCE,
|
||||
/**
|
||||
* 财付通
|
||||
*/
|
||||
TENPAY,
|
||||
/**
|
||||
* 银行
|
||||
*/
|
||||
BANK,
|
||||
/**
|
||||
* 原账户异常退到其他余额账户
|
||||
*/
|
||||
OTHER_BALANCE,
|
||||
/**
|
||||
* 原银行卡异常退到其他银行卡
|
||||
*/
|
||||
OTHER_BANKCARD
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
package com.foxinmy.weixin4j.pay.type.mch;
|
||||
|
||||
/**
|
||||
* 退款状态
|
||||
*
|
||||
* @className RefundStatus
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2014年11月2日
|
||||
* @since JDK 1.6
|
||||
* @see
|
||||
*/
|
||||
public enum RefundStatus {
|
||||
/**
|
||||
* 退款成功
|
||||
*/
|
||||
SUCCESS,
|
||||
/**
|
||||
* 退款失败
|
||||
*/
|
||||
FAIL,
|
||||
/**
|
||||
* 退款处理中
|
||||
*/
|
||||
PROCESSING,
|
||||
/**
|
||||
* 未确定,需要商户 原退款单号重新发起
|
||||
*/
|
||||
NOTSURE,
|
||||
/**
|
||||
* 转入代发,退款到银行发现用户的卡作废或者冻结了,导致原路退款银行卡失败,资金回流到商户的现金帐号,需要商户人工干预,通过线下或者财付通转
|
||||
* 账的方式进行退款。
|
||||
*/
|
||||
CHANGE;
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
package com.foxinmy.weixin4j.pay.type.mch;
|
||||
|
||||
/**
|
||||
* 退款类型
|
||||
*
|
||||
* @className RefundType
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2014年12月31日
|
||||
* @since JDK 1.6
|
||||
* @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;
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user