新增退款接口
This commit is contained in:
parent
f489667109
commit
26d04798c5
@ -48,10 +48,14 @@ weixin4j
|
||||
|
||||
+ 优化了代码
|
||||
|
||||
* 2014-11-06
|
||||
|
||||
+ **weixin-base**: 删除`WeixinConfig`类只保留`WeixinAccount`类
|
||||
|
||||
+ **weixin-mp**: 新增`退款接口`
|
||||
|
||||
接下来
|
||||
------
|
||||
* 公众号退款接口
|
||||
|
||||
* 公众号智能接口
|
||||
|
||||
* 微信消息加密
|
||||
|
||||
@ -17,4 +17,8 @@ weixin4j-base
|
||||
|
||||
+ `TokenApi`重命名为`TokenHolder`
|
||||
|
||||
+ 新增`WeixinConfig`等类
|
||||
+ 新增`WeixinConfig`等类
|
||||
|
||||
* 2014-11-06
|
||||
|
||||
+ 删除`WeixinConfig`类只保留`WeixinAccount`类
|
||||
@ -47,7 +47,7 @@ import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
*/
|
||||
public class HttpRequest {
|
||||
private final String SUCCESS = "success";
|
||||
private AbstractHttpClient client;
|
||||
protected AbstractHttpClient client;
|
||||
|
||||
public HttpRequest() {
|
||||
this(150, 100, 10000, 10000);
|
||||
@ -155,17 +155,17 @@ public class HttpRequest {
|
||||
HttpResponse httpResponse = client.execute(request);
|
||||
StatusLine statusLine = httpResponse.getStatusLine();
|
||||
HttpEntity httpEntity = httpResponse.getEntity();
|
||||
|
||||
int status = statusLine.getStatusCode();
|
||||
if (status != HttpStatus.SC_OK) {
|
||||
throw new WeixinException(status + "", "request fail");
|
||||
throw new WeixinException(Integer.toString(status),
|
||||
"request fail");
|
||||
}
|
||||
// 301或者302
|
||||
if (status == HttpStatus.SC_MOVED_PERMANENTLY
|
||||
|| status == HttpStatus.SC_MOVED_TEMPORARILY) {
|
||||
throw new WeixinException(status + "", String.format(
|
||||
"the page was redirected to %s",
|
||||
httpResponse.getFirstHeader("location")));
|
||||
throw new WeixinException(Integer.toString(status),
|
||||
String.format("the page was redirected to %s",
|
||||
httpResponse.getFirstHeader("location")));
|
||||
}
|
||||
byte[] data = EntityUtils.toByteArray(httpEntity);
|
||||
response = new Response();
|
||||
@ -186,8 +186,8 @@ public class HttpRequest {
|
||||
JsonResult jsonResult = response.getAsJsonResult();
|
||||
response.setJsonResult(true);
|
||||
if (jsonResult.getCode() != 0) {
|
||||
throw new WeixinException(jsonResult.getCode() + "",
|
||||
jsonResult.getDesc());
|
||||
throw new WeixinException(Integer.toString(jsonResult
|
||||
.getCode()), jsonResult.getDesc());
|
||||
}
|
||||
return response;
|
||||
} catch (JSONException e) {
|
||||
@ -205,7 +205,7 @@ public class HttpRequest {
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new WeixinException(e.getMessage());
|
||||
throw new WeixinException("-1", e.getMessage());
|
||||
} finally {
|
||||
request.releaseConnection();
|
||||
}
|
||||
|
||||
@ -0,0 +1,48 @@
|
||||
package com.foxinmy.weixin4j.http;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.KeyStore;
|
||||
|
||||
import org.apache.http.conn.scheme.Scheme;
|
||||
import org.apache.http.conn.ssl.SSLSocketFactory;
|
||||
|
||||
/**
|
||||
* ssl请求
|
||||
*
|
||||
* @className SSLHttpRequest
|
||||
* @author jy
|
||||
* @date 2014年11月6日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public class SSLHttpRequest extends HttpRequest {
|
||||
|
||||
public SSLHttpRequest(String password, File file) throws IOException {
|
||||
this(password, new FileInputStream(file));
|
||||
}
|
||||
|
||||
public SSLHttpRequest(String password, InputStream inputStream) {
|
||||
super();
|
||||
try {
|
||||
KeyStore trustStore = KeyStore.getInstance("PKCS12");
|
||||
trustStore.load(inputStream, password.toCharArray());
|
||||
SSLSocketFactory socketFactory = new SSLSocketFactory(trustStore,
|
||||
password);
|
||||
client.getConnectionManager().getSchemeRegistry()
|
||||
.register(new Scheme("https", 443, socketFactory));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
if (inputStream != null) {
|
||||
inputStream.close();
|
||||
}
|
||||
} catch (Exception ignore) {
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -24,7 +24,6 @@ public class Token implements Serializable {
|
||||
private String accessToken;
|
||||
@JSONField(name = "expires_in")
|
||||
private int expiresIn;
|
||||
private String openid;
|
||||
private long time;
|
||||
|
||||
public String getAccessToken() {
|
||||
@ -43,14 +42,6 @@ public class Token implements Serializable {
|
||||
this.expiresIn = expiresIn;
|
||||
}
|
||||
|
||||
public String getOpenid() {
|
||||
return openid;
|
||||
}
|
||||
|
||||
public void setOpenid(String openid) {
|
||||
this.openid = openid;
|
||||
}
|
||||
|
||||
public long getTime() {
|
||||
return time;
|
||||
}
|
||||
@ -69,6 +60,7 @@ public class Token implements Serializable {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Token [accessToken=" + accessToken + ", expiresIn=" + expiresIn + ", openid=" + openid + ", time=" + time + "]";
|
||||
return "Token [accessToken=" + accessToken + ", expiresIn=" + expiresIn
|
||||
+ ", time=" + time + "]";
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
package com.foxinmy.weixin4j.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 微信账户信息
|
||||
*
|
||||
@ -9,9 +11,16 @@ package com.foxinmy.weixin4j.model;
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public class WeixinAccount extends WeixinConfig {
|
||||
public class WeixinAccount implements Serializable {
|
||||
private static final long serialVersionUID = 3689999353867189585L;
|
||||
|
||||
private String token;
|
||||
// 支付场景下为用户的openid 其余情况可能是公众号的原始ID
|
||||
private String openId;
|
||||
// 公众号身份的唯一标识
|
||||
private String appId;
|
||||
// 公众平台接口 API 的权限获取所需密钥 Key
|
||||
private String appSecret;
|
||||
// 公众号支付请求中用于加密的密钥 Key,可验证商户唯一身份,PaySignKey 对应于支付场景中的 appKey 值
|
||||
private String paySignKey;
|
||||
// 财付通商户身份的标识
|
||||
@ -30,6 +39,38 @@ public class WeixinAccount extends WeixinConfig {
|
||||
// 是否是订阅号
|
||||
private boolean isSubscribe;
|
||||
|
||||
public String getToken() {
|
||||
return token;
|
||||
}
|
||||
|
||||
public void setToken(String token) {
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
public String getOpenId() {
|
||||
return openId;
|
||||
}
|
||||
|
||||
public void setOpenId(String openId) {
|
||||
this.openId = openId;
|
||||
}
|
||||
|
||||
public String getAppId() {
|
||||
return appId;
|
||||
}
|
||||
|
||||
public void setAppId(String appId) {
|
||||
this.appId = appId;
|
||||
}
|
||||
|
||||
public String getAppSecret() {
|
||||
return appSecret;
|
||||
}
|
||||
|
||||
public void setAppSecret(String appSecret) {
|
||||
this.appSecret = appSecret;
|
||||
}
|
||||
|
||||
public String getPaySignKey() {
|
||||
return paySignKey;
|
||||
}
|
||||
@ -98,19 +139,51 @@ public class WeixinAccount extends WeixinConfig {
|
||||
|
||||
}
|
||||
|
||||
public WeixinAccount(String appId, String appSecret) {
|
||||
this.appId = appId;
|
||||
this.appSecret = appSecret;
|
||||
}
|
||||
|
||||
/**
|
||||
* V3版本字段
|
||||
*
|
||||
* @param appId
|
||||
* @param appSecret
|
||||
* @param paySignKey
|
||||
* @param mchId
|
||||
*/
|
||||
public WeixinAccount(String appId, String appSecret, String paySignKey,
|
||||
String mchId) {
|
||||
super(appId, appSecret);
|
||||
this(appId, appSecret);
|
||||
this.paySignKey = paySignKey;
|
||||
this.mchId = mchId;
|
||||
}
|
||||
|
||||
/**
|
||||
* V2版本字段
|
||||
*
|
||||
* @param appId
|
||||
* @param appSecret
|
||||
* @param paySignKey
|
||||
* @param partnerId
|
||||
* @param partnerKey
|
||||
*/
|
||||
public WeixinAccount(String appId, String appSecret, String paySignKey,
|
||||
String partnerId, String partnerKey) {
|
||||
super(appId, appSecret);
|
||||
this(appId, appSecret);
|
||||
this.paySignKey = paySignKey;
|
||||
this.partnerId = partnerId;
|
||||
this.partnerKey = partnerKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "WeixinAccount [token=" + token + ", openId=" + openId
|
||||
+ ", appId=" + appId + ", appSecret=" + appSecret
|
||||
+ ", paySignKey=" + paySignKey + ", partnerId=" + partnerId
|
||||
+ ", partnerKey=" + partnerKey + ", mchId=" + mchId
|
||||
+ ", deviceInfo=" + deviceInfo + ", isAlive=" + isAlive
|
||||
+ ", isService=" + isService + ", isSubscribe=" + isSubscribe
|
||||
+ "]";
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,64 +0,0 @@
|
||||
package com.foxinmy.weixin4j.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class WeixinConfig implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -3454743453282851243L;
|
||||
|
||||
private String token;
|
||||
// 支付场景下为用户的openid 其余情况可能是公众号的原始ID
|
||||
private String openId;
|
||||
// 公众号身份的唯一标识
|
||||
private String appId;
|
||||
// 除了支付请求需要用到 paySignKey,公众平台接口 API 的权限获取所需密 钥 Key
|
||||
private String appSecret;
|
||||
|
||||
public String getToken() {
|
||||
return token;
|
||||
}
|
||||
|
||||
public void setToken(String token) {
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
public String getOpenId() {
|
||||
return openId;
|
||||
}
|
||||
|
||||
public void setOpenId(String openId) {
|
||||
this.openId = openId;
|
||||
}
|
||||
|
||||
public String getAppId() {
|
||||
return appId;
|
||||
}
|
||||
|
||||
public void setAppId(String appId) {
|
||||
this.appId = appId;
|
||||
}
|
||||
|
||||
public String getAppSecret() {
|
||||
return appSecret;
|
||||
}
|
||||
|
||||
public void setAppSecret(String appSecret) {
|
||||
this.appSecret = appSecret;
|
||||
}
|
||||
|
||||
public WeixinConfig() {
|
||||
|
||||
}
|
||||
|
||||
public WeixinConfig(String appId, String appSecret) {
|
||||
this.appId = appId;
|
||||
this.appSecret = appSecret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "WeixinConfig [token=" + token + ", openId=" + openId
|
||||
+ ", appId=" + appId + ", appSecret=" + appSecret + "]";
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
package com.foxinmy.weixin4j.token;
|
||||
|
||||
import com.foxinmy.weixin4j.http.HttpRequest;
|
||||
import com.foxinmy.weixin4j.model.WeixinConfig;
|
||||
import com.foxinmy.weixin4j.model.WeixinAccount;
|
||||
import com.foxinmy.weixin4j.util.ConfigUtil;
|
||||
|
||||
/**
|
||||
@ -16,17 +16,17 @@ import com.foxinmy.weixin4j.util.ConfigUtil;
|
||||
public abstract class AbstractTokenHolder implements TokenHolder {
|
||||
protected final String tokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";
|
||||
protected final HttpRequest request = new HttpRequest();
|
||||
private final WeixinConfig weixinConfig;
|
||||
private final WeixinAccount weixinAccount;
|
||||
|
||||
public AbstractTokenHolder() {
|
||||
this.weixinConfig = ConfigUtil.getWeixinConfig();
|
||||
this.weixinAccount = ConfigUtil.getWeixinAccount();
|
||||
}
|
||||
|
||||
public AbstractTokenHolder(String appid, String appsecret) {
|
||||
this.weixinConfig = new WeixinConfig(appid, appsecret);
|
||||
public AbstractTokenHolder(WeixinAccount weixinAccount) {
|
||||
this.weixinAccount = weixinAccount;
|
||||
}
|
||||
|
||||
public WeixinConfig getConfig() {
|
||||
return this.weixinConfig;
|
||||
public WeixinAccount getAccount() {
|
||||
return weixinAccount;
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,6 +12,7 @@ import com.alibaba.fastjson.TypeReference;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.http.Response;
|
||||
import com.foxinmy.weixin4j.model.Token;
|
||||
import com.foxinmy.weixin4j.model.WeixinAccount;
|
||||
import com.foxinmy.weixin4j.util.ConfigUtil;
|
||||
import com.foxinmy.weixin4j.xml.XStream;
|
||||
|
||||
@ -32,8 +33,12 @@ public class FileTokenHolder extends AbstractTokenHolder {
|
||||
super();
|
||||
}
|
||||
|
||||
public FileTokenHolder(WeixinAccount weixinAccount) {
|
||||
super(weixinAccount);
|
||||
}
|
||||
|
||||
public FileTokenHolder(String appid, String appsecret) {
|
||||
super(appid, appsecret);
|
||||
this(new WeixinAccount(appid, appsecret));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -50,8 +55,8 @@ public class FileTokenHolder extends AbstractTokenHolder {
|
||||
*/
|
||||
@Override
|
||||
public Token getToken() throws WeixinException {
|
||||
String appid = getConfig().getAppId();
|
||||
String appsecret = getConfig().getAppSecret();
|
||||
String appid = getAccount().getAppId();
|
||||
String appsecret = getAccount().getAppSecret();
|
||||
if (StringUtils.isBlank(appid) || StringUtils.isBlank(appsecret)) {
|
||||
throw new IllegalArgumentException(
|
||||
"appid or appsecret not be null!");
|
||||
@ -65,7 +70,6 @@ public class FileTokenHolder extends AbstractTokenHolder {
|
||||
if (token_file.exists()) {
|
||||
token = XStream.get(new FileInputStream(token_file),
|
||||
Token.class);
|
||||
|
||||
long expise_time = token.getTime()
|
||||
+ (token.getExpiresIn() * 1000) - 3;
|
||||
if (expise_time > now_time) {
|
||||
@ -79,7 +83,6 @@ public class FileTokenHolder extends AbstractTokenHolder {
|
||||
token = response.getAsObject(new TypeReference<Token>() {
|
||||
});
|
||||
token.setTime(now_time);
|
||||
token.setOpenid(appid);
|
||||
XStream.to(token, new FileOutputStream(token_file));
|
||||
} catch (IOException e) {
|
||||
throw new WeixinException("-1", "IO ERROR");
|
||||
|
||||
@ -10,6 +10,7 @@ import redis.clients.jedis.exceptions.JedisException;
|
||||
import com.alibaba.fastjson.TypeReference;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.model.Token;
|
||||
import com.foxinmy.weixin4j.model.WeixinAccount;
|
||||
|
||||
/**
|
||||
* 基于redis保存的Token获取类
|
||||
@ -26,17 +27,7 @@ public class RedisTokenHolder extends AbstractTokenHolder {
|
||||
|
||||
private JedisPool jedisPool;
|
||||
|
||||
public RedisTokenHolder() {
|
||||
super();
|
||||
}
|
||||
|
||||
public RedisTokenHolder(String appid, String appsecret) {
|
||||
this(appid, appsecret, "localhost", 6379);
|
||||
}
|
||||
|
||||
public RedisTokenHolder(String appid, String appsecret, String host,
|
||||
int port) {
|
||||
super(appid, appsecret);
|
||||
private void createPool(String host, int port) {
|
||||
JedisPoolConfig poolConfig = new JedisPoolConfig();
|
||||
poolConfig.setMaxTotal(50);
|
||||
poolConfig.setMaxIdle(5);
|
||||
@ -46,10 +37,33 @@ public class RedisTokenHolder extends AbstractTokenHolder {
|
||||
this.jedisPool = new JedisPool(poolConfig, host, port);
|
||||
}
|
||||
|
||||
public RedisTokenHolder() {
|
||||
this("localhost", 6379);
|
||||
}
|
||||
|
||||
public RedisTokenHolder(String host, int port) {
|
||||
super();
|
||||
createPool(host, port);
|
||||
}
|
||||
|
||||
public RedisTokenHolder(WeixinAccount weixinAccount) {
|
||||
this(weixinAccount, "localhost", 6379);
|
||||
}
|
||||
|
||||
public RedisTokenHolder(String appId, String appSecret, String host,
|
||||
int port) {
|
||||
this(new WeixinAccount(appId, appSecret), host, port);
|
||||
}
|
||||
|
||||
public RedisTokenHolder(WeixinAccount weixinAccount, String host, int port) {
|
||||
super(weixinAccount);
|
||||
createPool(host, port);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Token getToken() throws WeixinException {
|
||||
String appid = getConfig().getAppId();
|
||||
String appsecret = getConfig().getAppSecret();
|
||||
String appid = getAccount().getAppId();
|
||||
String appsecret = getAccount().getAppSecret();
|
||||
if (StringUtils.isBlank(appid) || StringUtils.isBlank(appsecret)) {
|
||||
throw new IllegalArgumentException(
|
||||
"appid or appsecret not be null!");
|
||||
@ -68,13 +82,12 @@ public class RedisTokenHolder extends AbstractTokenHolder {
|
||||
});
|
||||
jedis.setex(key, token.getExpiresIn() - 3,
|
||||
token.getAccessToken());
|
||||
token.setTime(System.currentTimeMillis());
|
||||
} else {
|
||||
token = new Token();
|
||||
token.setAccessToken(accessToken);
|
||||
token.setExpiresIn(jedis.ttl(key).intValue());
|
||||
}
|
||||
token.setTime(System.currentTimeMillis());
|
||||
token.setOpenid(appid);
|
||||
} catch (JedisException e) {
|
||||
jedisPool.returnBrokenResource(jedis);
|
||||
} finally {
|
||||
@ -82,4 +95,4 @@ public class RedisTokenHolder extends AbstractTokenHolder {
|
||||
}
|
||||
return token;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2,7 +2,7 @@ package com.foxinmy.weixin4j.token;
|
||||
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.model.Token;
|
||||
import com.foxinmy.weixin4j.model.WeixinConfig;
|
||||
import com.foxinmy.weixin4j.model.WeixinAccount;
|
||||
|
||||
/**
|
||||
* 获取Token接口
|
||||
@ -17,7 +17,7 @@ import com.foxinmy.weixin4j.model.WeixinConfig;
|
||||
* @see com.foxinmy.weixin4j.token.RedisTokenHolder
|
||||
*/
|
||||
public interface TokenHolder {
|
||||
public WeixinConfig getConfig();
|
||||
public WeixinAccount getAccount();
|
||||
|
||||
public Token getToken() throws WeixinException;
|
||||
}
|
||||
|
||||
@ -6,7 +6,6 @@ import java.util.Set;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.foxinmy.weixin4j.model.WeixinAccount;
|
||||
import com.foxinmy.weixin4j.model.WeixinConfig;
|
||||
|
||||
/**
|
||||
* 商户配置工具类
|
||||
@ -38,9 +37,4 @@ public class ConfigUtil {
|
||||
String text = getValue("account");
|
||||
return JSON.parseObject(text, WeixinAccount.class);
|
||||
}
|
||||
|
||||
public static WeixinConfig getWeixinConfig() {
|
||||
String text = getValue("account");
|
||||
return JSON.parseObject(text, WeixinConfig.class);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package com.foxinmy.weixin4j.util;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
@ -25,7 +26,16 @@ public class DateUtil {
|
||||
return new SimpleDateFormat(yyyyMMddHHmmss).format(date);
|
||||
}
|
||||
|
||||
public static String format2fee(double fee) {
|
||||
public static Date parse2yyyyMMddHHmmss(String date) {
|
||||
try {
|
||||
return new SimpleDateFormat(yyyyMMddHHmmss).parse(date);
|
||||
} catch (ParseException e) {
|
||||
;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String formaFee2Fen(double fee) {
|
||||
return new DecimalFormat("#").format(fee * 100);
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,7 +28,7 @@ weixin4j-mp
|
||||
|
||||
* **weixin4j-mp-server**
|
||||
|
||||
`netty服务器 & 消息分发`
|
||||
`netty服务器` & `消息分发`
|
||||
|
||||
更新LOG
|
||||
-------
|
||||
@ -48,4 +48,8 @@ weixin4j-mp
|
||||
|
||||
+ `weixin-mp`分离为`weixin-mp-api`和`weixin-mp-server`两个工程
|
||||
|
||||
+ **weixin-mp**: 加入`支付`模块
|
||||
+ **weixin-mp**: 新增`支付`模块
|
||||
|
||||
* 2014-11-06
|
||||
|
||||
+ **weixin-mp**: 新增`退款接口`
|
||||
@ -41,7 +41,7 @@ weixin.properties说明
|
||||
| media_path | 调用媒体接口时保存媒体文件的物理路径 |
|
||||
| bill_path | 调用支付(`V3`)下载对账单接口保存excel文件的物理路径 |
|
||||
|
||||
示例(properties中换行用右斜杆\)
|
||||
示例(properties中换行用右斜杆\\)
|
||||
|
||||
> account={"appId":"appId","appSecret":"appSecret",
|
||||
> "token":"开放者的token 非必须","openId":"公众号的openid 非必须",
|
||||
@ -84,4 +84,8 @@ weixin.properties说明
|
||||
|
||||
+ 分离为`weixin-mp-api`和`weixin-mp-server`两个工程
|
||||
|
||||
+ 加入`支付模块`
|
||||
+ 新增`支付模块`
|
||||
|
||||
* 2014-11-06
|
||||
|
||||
+ 新增`退款申请`接口
|
||||
@ -2,6 +2,7 @@ package com.foxinmy.weixin4j.mp;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@ -25,18 +26,18 @@ import com.foxinmy.weixin4j.mp.model.CustomRecord;
|
||||
import com.foxinmy.weixin4j.mp.model.Following;
|
||||
import com.foxinmy.weixin4j.mp.model.Group;
|
||||
import com.foxinmy.weixin4j.mp.model.MpArticle;
|
||||
import com.foxinmy.weixin4j.mp.model.OauthToken;
|
||||
import com.foxinmy.weixin4j.mp.model.QRParameter;
|
||||
import com.foxinmy.weixin4j.mp.model.User;
|
||||
import com.foxinmy.weixin4j.mp.model.OauthToken;
|
||||
import com.foxinmy.weixin4j.mp.msg.model.Article;
|
||||
import com.foxinmy.weixin4j.mp.msg.model.BaseMsg;
|
||||
import com.foxinmy.weixin4j.mp.msg.notify.BaseNotify;
|
||||
import com.foxinmy.weixin4j.mp.payment.v2.Order;
|
||||
import com.foxinmy.weixin4j.mp.payment.v3.Refund;
|
||||
import com.foxinmy.weixin4j.mp.payment.v3.RefundResult;
|
||||
import com.foxinmy.weixin4j.mp.response.TemplateMessage;
|
||||
import com.foxinmy.weixin4j.mp.type.BillType;
|
||||
import com.foxinmy.weixin4j.mp.type.IdQuery;
|
||||
import com.foxinmy.weixin4j.mp.type.IdType;
|
||||
import com.foxinmy.weixin4j.token.FileTokenHolder;
|
||||
import com.foxinmy.weixin4j.token.TokenHolder;
|
||||
import com.foxinmy.weixin4j.type.MediaType;
|
||||
@ -396,8 +397,7 @@ public class WeixinProxy {
|
||||
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E9%AB%98%E7%BA%A7%E7%BE%A4%E5%8F%91%E6%8E%A5%E5%8F%A3#.E5.88.A0.E9.99.A4.E7.BE.A4.E5.8F.91">删除群发</a>
|
||||
* @see com.foxinmy.weixin4j.mp.api.MassApi
|
||||
* @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#massByGroup(JSONObject, String)}
|
||||
* @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#massByOpenIds(JSONObject, String...)
|
||||
|
||||
* @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#massByOpenIds(JSONObject, String...)
|
||||
*/
|
||||
public JsonResult deleteMassNews(String msgid) throws WeixinException {
|
||||
return massApi.deleteMassNews(msgid);
|
||||
@ -720,8 +720,6 @@ public class WeixinProxy {
|
||||
/**
|
||||
* 发货通知
|
||||
*
|
||||
* @param weixinAccount
|
||||
* 商户信息
|
||||
* @param openId
|
||||
* 用户ID
|
||||
* @param transid
|
||||
@ -736,28 +734,25 @@ public class WeixinProxy {
|
||||
* @throws WeixinException
|
||||
* @see com.foxinmy.weixin4j.mp.api.PayApi
|
||||
*/
|
||||
public JsonResult deliverNotify(WeixinAccount weixinAccount, String openId,
|
||||
String transid, String orderNo, boolean status, String statusMsg)
|
||||
public JsonResult deliverNotify(String openId, String transid,
|
||||
String outTradeNo, boolean status, String statusMsg)
|
||||
throws WeixinException {
|
||||
return payApi.deliverNotify(weixinAccount, openId, transid, orderNo,
|
||||
status, statusMsg);
|
||||
return payApi.deliverNotify(openId, transid, outTradeNo, status,
|
||||
statusMsg);
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单查询
|
||||
*
|
||||
* @param weixinAccount
|
||||
* 商户信息
|
||||
* @param orderNo
|
||||
* @param outTradeNo
|
||||
* 订单号
|
||||
* @return 订单信息
|
||||
* @throws WeixinException
|
||||
* @see com.foxinmy.weixin4j.mp.api.PayApi
|
||||
*/
|
||||
public Order orderQueryV2(WeixinAccount weixinAccount, String orderNo)
|
||||
public Order orderQueryV2(WeixinAccount weixinAccount, String outTradeNo)
|
||||
throws WeixinException {
|
||||
return payApi.orderQueryV2(weixinAccount, new IdQuery(orderNo,
|
||||
IdType.ORDERNO));
|
||||
return payApi.orderQueryV2(outTradeNo);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -779,18 +774,15 @@ public class WeixinProxy {
|
||||
/**
|
||||
* V3订单查询
|
||||
*
|
||||
* @param weixinAccount
|
||||
* 商户信息
|
||||
* @param idQuery
|
||||
* 商户系统内部的订单号, transaction_id、out_trade_no 二 选一,如果同时存在优先级:
|
||||
* transaction_id> out_trade_no
|
||||
* @see com.foxinmy.weixin4j.mp.api.PayApi
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public com.foxinmy.weixin4j.mp.payment.v3.Order orderQueryV3(
|
||||
WeixinAccount weixinAccount, IdQuery idQuery)
|
||||
public com.foxinmy.weixin4j.mp.payment.v3.Order orderQueryV3(IdQuery idQuery)
|
||||
throws WeixinException {
|
||||
return payApi.orderQueryV3(weixinAccount, idQuery);
|
||||
return payApi.orderQueryV3(idQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -800,8 +792,6 @@ public class WeixinProxy {
|
||||
* 2.微信在次日 9 点启动生成前一天的对账单,建议商户 9 点半后再获取;<br>
|
||||
* 3.对账单中涉及金额的字段单位为“元”。<br>
|
||||
*
|
||||
* @param weixinAccount
|
||||
* 商户配置
|
||||
* @param billDate
|
||||
* 下载对账单的日期
|
||||
* @param billType
|
||||
@ -812,16 +802,60 @@ public class WeixinProxy {
|
||||
* @throws WeixinException
|
||||
* @throws IOException
|
||||
*/
|
||||
public File downloadbill(WeixinAccount weixinAccount, Date billDate,
|
||||
BillType billType) throws WeixinException, IOException {
|
||||
return payApi.downloadbill(weixinAccount, billDate, billType);
|
||||
public File downloadbill(Date billDate, BillType billType)
|
||||
throws WeixinException, IOException {
|
||||
return payApi.downloadbill(billDate, billType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 申请退款(请求需要双向证书)<br/>
|
||||
* <p style="color:red">
|
||||
* 交易时间超过 1 年的订单无法提交退款; <br/>
|
||||
* 支持部分退款,部分退需要设置相同的订单号和不同的 out_refund_no。一笔退款失 败后重新提交,要采用原来的
|
||||
* out_refund_no。总退款金额不能超过用户实际支付金额。<br/>
|
||||
* </p>
|
||||
*
|
||||
* @param ca
|
||||
* 证书文件
|
||||
* @param idQuery
|
||||
* ) 商户系统内部的订单号, transaction_id 、 out_trade_no 二选一,如果同时存在优先级:
|
||||
* transaction_id> out_trade_no
|
||||
* @param outRefundNo
|
||||
* 商户系统内部的退款单号,商 户系统内部唯一,同一退款单号多次请求只退一笔
|
||||
* @param totalFee
|
||||
* 订单总金额,单位为元
|
||||
* @param refundFee
|
||||
* 退款总金额,单位为元,可以做部分退款
|
||||
* @param opUserId
|
||||
* 操作员帐号, 默认为商户号
|
||||
* @see com.foxinmy.weixin4j.mp.api.PayApi
|
||||
* @throws WeixinException
|
||||
* @throws IOException
|
||||
* @return 退款结果
|
||||
*/
|
||||
public RefundResult refund(InputStream ca, IdQuery idQuery,
|
||||
String outRefundNo, double totalFee, double refundFee,
|
||||
String opUserId) throws WeixinException, IOException {
|
||||
return payApi.refund(idQuery, outRefundNo, totalFee, refundFee,
|
||||
opUserId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用properties中配置的ca文件
|
||||
*
|
||||
* @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#refund(InputStream, IdQuery, String, double, double, String)}
|
||||
*/
|
||||
public RefundResult refund(IdQuery idQuery, String outRefundNo,
|
||||
double totalFee, double refundFee, String opUserId)
|
||||
throws WeixinException, IOException {
|
||||
return payApi.refund(idQuery, outRefundNo, totalFee, refundFee,
|
||||
opUserId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 退款查询<br/>
|
||||
* 退款有一定延时,用零钱支付的退款20分钟内到账,银行卡支付的退款 3 个工作日后重新查询退款状态
|
||||
*
|
||||
* @param weixinAccount
|
||||
* @param idQuery
|
||||
* 单号 refund_id、out_refund_no、 out_trade_no 、 transaction_id
|
||||
* 四个参数必填一个,优先级为:
|
||||
@ -830,9 +864,8 @@ public class WeixinProxy {
|
||||
* @return 退款记录
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public Refund refundQuery(WeixinAccount weixinAccount, IdQuery idQuery)
|
||||
throws WeixinException {
|
||||
return payApi.refundQuery(weixinAccount, idQuery);
|
||||
public Refund refundQuery(IdQuery idQuery) throws WeixinException {
|
||||
return payApi.refundQuery(idQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -840,33 +873,26 @@ public class WeixinProxy {
|
||||
* 当订单支付失败,调用关单接口后用新订单号重新发起支付,如果关单失败,返回已完
|
||||
* 成支付请按正常支付处理。如果出现银行掉单,调用关单成功后,微信后台会主动发起退款。
|
||||
*
|
||||
* @param weixinAccount
|
||||
* 商户信息
|
||||
* @param order
|
||||
* @param outTradeNo
|
||||
* 商户系统内部的订单号
|
||||
* @return 执行结果
|
||||
* @see com.foxinmy.weixin4j.mp.api.PayApi
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public XmlResult closeOrder(WeixinAccount weixinAccount, String orderNo)
|
||||
throws WeixinException {
|
||||
return payApi.orderQueryV3(weixinAccount, new IdQuery(orderNo,
|
||||
IdType.ORDERNO));
|
||||
public XmlResult closeOrder(String outTradeNo) throws WeixinException {
|
||||
return payApi.closeOrder(outTradeNo);
|
||||
}
|
||||
|
||||
/**
|
||||
* native支付URL转短链接
|
||||
*
|
||||
* @param weixinAccount
|
||||
* 商户信息
|
||||
* @param url
|
||||
* 具有native标识的支付URL
|
||||
* @return 转换后的短链接
|
||||
* @see com.foxinmy.weixin4j.mp.api.PayApi
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public String getPayShorturl(WeixinAccount weixinAccount, String url)
|
||||
throws WeixinException {
|
||||
return payApi.getShorturl(weixinAccount, url);
|
||||
public String getPayShorturl(String url) throws WeixinException {
|
||||
return payApi.getShorturl(url);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,8 +2,10 @@ package com.foxinmy.weixin4j.mp.api;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.StringReader;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
@ -16,6 +18,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
@ -25,6 +28,7 @@ import com.alibaba.fastjson.parser.Feature;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.http.JsonResult;
|
||||
import com.foxinmy.weixin4j.http.Response;
|
||||
import com.foxinmy.weixin4j.http.SSLHttpRequest;
|
||||
import com.foxinmy.weixin4j.http.XmlResult;
|
||||
import com.foxinmy.weixin4j.model.Token;
|
||||
import com.foxinmy.weixin4j.model.WeixinAccount;
|
||||
@ -32,8 +36,10 @@ import com.foxinmy.weixin4j.mp.payment.PayUtil;
|
||||
import com.foxinmy.weixin4j.mp.payment.v2.Order;
|
||||
import com.foxinmy.weixin4j.mp.payment.v3.Refund;
|
||||
import com.foxinmy.weixin4j.mp.payment.v3.RefundConverter;
|
||||
import com.foxinmy.weixin4j.mp.payment.v3.RefundResult;
|
||||
import com.foxinmy.weixin4j.mp.type.BillType;
|
||||
import com.foxinmy.weixin4j.mp.type.IdQuery;
|
||||
import com.foxinmy.weixin4j.mp.type.IdType;
|
||||
import com.foxinmy.weixin4j.mp.util.ExcelUtil;
|
||||
import com.foxinmy.weixin4j.token.TokenHolder;
|
||||
import com.foxinmy.weixin4j.util.ConfigUtil;
|
||||
@ -60,24 +66,23 @@ public class PayApi extends BaseApi {
|
||||
/**
|
||||
* 发货通知
|
||||
*
|
||||
* @param weixinAccount
|
||||
* 商户信息
|
||||
* @param openId
|
||||
* 用户ID
|
||||
* @param transid
|
||||
* 交易单号
|
||||
* @param orderNo
|
||||
* @param outTradeNo
|
||||
* 订单号
|
||||
* @param status
|
||||
* 成功|失败
|
||||
* @param statusMsg
|
||||
* status为失败时携带的信息
|
||||
* @return
|
||||
* @return 发货处理结果
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public JsonResult deliverNotify(WeixinAccount weixinAccount, String openId,
|
||||
String transid, String orderNo, boolean status, String statusMsg)
|
||||
public JsonResult deliverNotify(String openId, String transid,
|
||||
String outTradeNo, boolean status, String statusMsg)
|
||||
throws WeixinException {
|
||||
WeixinAccount weixinAccount = tokenHolder.getAccount();
|
||||
String delivernotify_uri = getRequestUri("delivernotify_uri");
|
||||
Token token = tokenHolder.getToken();
|
||||
|
||||
@ -87,7 +92,7 @@ public class PayApi extends BaseApi {
|
||||
// 用户购买的openId
|
||||
param.put("openid", openId);
|
||||
param.put("transid", transid);
|
||||
param.put("out_trade_no", orderNo);
|
||||
param.put("out_trade_no", outTradeNo);
|
||||
param.put("deliver_timestamp", System.currentTimeMillis() / 1000 + "");
|
||||
param.put("deliver_status", status ? "1" : "0");
|
||||
param.put("deliver_msg", statusMsg);
|
||||
@ -105,20 +110,17 @@ public class PayApi extends BaseApi {
|
||||
/**
|
||||
* 订单查询
|
||||
*
|
||||
* @param weixinAccount
|
||||
* 商户信息
|
||||
* @param orderNo
|
||||
* 订单号
|
||||
* @return
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public Order orderQueryV2(WeixinAccount weixinAccount, IdQuery idQuery)
|
||||
throws WeixinException {
|
||||
public Order orderQueryV2(String orderNo) throws WeixinException {
|
||||
WeixinAccount weixinAccount = tokenHolder.getAccount();
|
||||
String orderquery_uri = getRequestUri("orderquery_uri");
|
||||
Token token = tokenHolder.getToken();
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(idQuery.getType().getName()).append(idQuery.getId());
|
||||
sb.append("out_trade_no=").append(orderNo);
|
||||
sb.append("&partner=").append(weixinAccount.getPartnerId());
|
||||
String part = sb.toString();
|
||||
sb.append("&key=").append(weixinAccount.getPartnerKey());
|
||||
@ -149,6 +151,10 @@ public class PayApi extends BaseApi {
|
||||
String order_info = response.getAsJson().getString("order_info");
|
||||
Order order = JSON.parseObject(order_info, Order.class,
|
||||
Feature.IgnoreNotMatch);
|
||||
if (order.getRetCode() != 0) {
|
||||
throw new WeixinException(Integer.toString(order.getRetCode()),
|
||||
order.getRetMsg());
|
||||
}
|
||||
order.setMapData(JSON.parseObject(order_info,
|
||||
new TypeReference<Map<String, String>>() {
|
||||
}));
|
||||
@ -177,21 +183,15 @@ public class PayApi extends BaseApi {
|
||||
/**
|
||||
* V3订单查询
|
||||
*
|
||||
* @param weixinAccount
|
||||
* 商户信息
|
||||
* @param idQuery
|
||||
* 商户系统内部的订单号, transaction_id、out_trade_no 二 选一,如果同时存在优先级:
|
||||
* transaction_id> out_trade_no
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public com.foxinmy.weixin4j.mp.payment.v3.Order orderQueryV3(
|
||||
WeixinAccount weixinAccount, IdQuery idQuery)
|
||||
public com.foxinmy.weixin4j.mp.payment.v3.Order orderQueryV3(IdQuery idQuery)
|
||||
throws WeixinException {
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
map.put("appid", weixinAccount.getAppId());
|
||||
map.put("mch_id", weixinAccount.getMchId());
|
||||
map.put("nonce_str", RandomUtil.generateString(16));
|
||||
map.put(idQuery.getType().getName(), idQuery.getId());
|
||||
WeixinAccount weixinAccount = tokenHolder.getAccount();
|
||||
Map<String, String> map = baseMap2V3(idQuery);
|
||||
String sign = PayUtil.paysignMd5(map, weixinAccount.getPaySignKey());
|
||||
map.put("sign", sign);
|
||||
String param = map2xml(map);
|
||||
@ -202,6 +202,67 @@ public class PayApi extends BaseApi {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 申请退款(请求需要双向证书)<br/>
|
||||
* <p style="color:red">
|
||||
* 交易时间超过 1 年的订单无法提交退款; <br/>
|
||||
* 支持部分退款,部分退需要设置相同的订单号和不同的 out_refund_no。一笔退款失 败后重新提交,要采用原来的
|
||||
* out_refund_no。总退款金额不能超过用户实际支付金额。<br/>
|
||||
* </p>
|
||||
*
|
||||
* @param ca
|
||||
* 证书文件
|
||||
* @param idQuery
|
||||
* ) 商户系统内部的订单号, transaction_id 、 out_trade_no 二选一,如果同时存在优先级:
|
||||
* transaction_id> out_trade_no
|
||||
* @param outRefundNo
|
||||
* 商户系统内部的退款单号,商 户系统内部唯一,同一退款单号多次请求只退一笔
|
||||
* @param totalFee
|
||||
* 订单总金额,单位为元
|
||||
* @param refundFee
|
||||
* 退款总金额,单位为元,可以做部分退款
|
||||
* @param opUserId
|
||||
* 操作员帐号, 默认为商户号
|
||||
* @throws WeixinException
|
||||
* @throws IOException
|
||||
* @return 退款结果
|
||||
*/
|
||||
public RefundResult refund(InputStream ca, IdQuery idQuery,
|
||||
String outRefundNo, double totalFee, double refundFee,
|
||||
String opUserId) throws WeixinException, IOException {
|
||||
WeixinAccount weixinAccount = tokenHolder.getAccount();
|
||||
Map<String, String> map = baseMap2V3(idQuery);
|
||||
map.put("out_refund_no", outRefundNo);
|
||||
map.put("total_fee", DateUtil.formaFee2Fen(totalFee));
|
||||
map.put("refund_fee", DateUtil.formaFee2Fen(refundFee));
|
||||
if (StringUtils.isBlank(opUserId)) {
|
||||
opUserId = weixinAccount.getMchId();
|
||||
}
|
||||
map.put("op_user_id", opUserId);
|
||||
String sign = PayUtil.paysignMd5(map, weixinAccount.getPaySignKey());
|
||||
map.put("sign", sign);
|
||||
String param = map2xml(map);
|
||||
String refund_uri = getRequestUri("refund_uri");
|
||||
SSLHttpRequest request = new SSLHttpRequest(weixinAccount.getMchId(),
|
||||
ca);
|
||||
Response response = request.post(refund_uri, param);
|
||||
return response.getAsObject(new TypeReference<RefundResult>() {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用properties中配置的ca文件
|
||||
*
|
||||
* @see {@link com.foxinmy.weixin4j.mp.api.PayApi#refund(InputStream, IdQuery, String, double, double, String)}
|
||||
*/
|
||||
public RefundResult refund(IdQuery idQuery, String outRefundNo,
|
||||
double totalFee, double refundFee, String opUserId)
|
||||
throws WeixinException, IOException {
|
||||
File caFile = new File(ConfigUtil.getValue("ca_file"));
|
||||
return refund(new FileInputStream(caFile), idQuery, outRefundNo,
|
||||
totalFee, refundFee, opUserId);
|
||||
}
|
||||
|
||||
/**
|
||||
* native支付URL转短链接
|
||||
*
|
||||
@ -212,13 +273,10 @@ public class PayApi extends BaseApi {
|
||||
* @return 转换后的短链接
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public String getShorturl(WeixinAccount weixinAccount, String url)
|
||||
throws WeixinException {
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
map.put("appid", weixinAccount.getAppId());
|
||||
map.put("mch_id", weixinAccount.getMchId());
|
||||
public String getShorturl(String url) throws WeixinException {
|
||||
WeixinAccount weixinAccount = tokenHolder.getAccount();
|
||||
Map<String, String> map = baseMap2V3(null);
|
||||
map.put("long_url", url);
|
||||
map.put("nonce_str", RandomUtil.generateString(16));
|
||||
String sign = PayUtil.paysignMd5(map, weixinAccount.getPaySignKey());
|
||||
map.put("sign", sign);
|
||||
try {
|
||||
@ -238,20 +296,15 @@ public class PayApi extends BaseApi {
|
||||
* 当订单支付失败,调用关单接口后用新订单号重新发起支付,如果关单失败,返回已完
|
||||
* 成支付请按正常支付处理。如果出现银行掉单,调用关单成功后,微信后台会主动发起退款。
|
||||
*
|
||||
* @param weixinAccount
|
||||
* 商户信息
|
||||
* @param idQuery
|
||||
* @param outTradeNo
|
||||
* 商户系统内部的订单号
|
||||
* @return
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public XmlResult closeOrder(WeixinAccount weixinAccount, IdQuery idQuery)
|
||||
throws WeixinException {
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
map.put("appid", weixinAccount.getAppId());
|
||||
map.put("mch_id", weixinAccount.getMchId());
|
||||
map.put("nonce_str", RandomUtil.generateString(16));
|
||||
map.put(idQuery.getType().getName(), idQuery.getId());
|
||||
public XmlResult closeOrder(String outTradeNo) throws WeixinException {
|
||||
WeixinAccount weixinAccount = tokenHolder.getAccount();
|
||||
Map<String, String> map = baseMap2V3(new IdQuery(outTradeNo,
|
||||
IdType.TRADENO));
|
||||
String sign = PayUtil.paysignMd5(map, weixinAccount.getPaySignKey());
|
||||
map.put("sign", sign);
|
||||
String param = map2xml(map);
|
||||
@ -267,8 +320,6 @@ public class PayApi extends BaseApi {
|
||||
* 2.微信在次日 9 点启动生成前一天的对账单,建议商户 9 点半后再获取;<br>
|
||||
* 3.对账单中涉及金额的字段单位为“元”。<br>
|
||||
*
|
||||
* @param weixinAccount
|
||||
* 商户配置
|
||||
* @param billDate
|
||||
* 下载对账单的日期
|
||||
* @param billType
|
||||
@ -278,9 +329,9 @@ public class PayApi extends BaseApi {
|
||||
* @throws WeixinException
|
||||
* @throws IOException
|
||||
*/
|
||||
public File downloadbill(WeixinAccount weixinAccount, Date billDate,
|
||||
BillType billType) throws WeixinException, IOException {
|
||||
|
||||
public File downloadbill(Date billDate, BillType billType)
|
||||
throws WeixinException, IOException {
|
||||
WeixinAccount weixinAccount = tokenHolder.getAccount();
|
||||
if (billDate == null) {
|
||||
Calendar now = Calendar.getInstance();
|
||||
now.add(Calendar.DAY_OF_MONTH, -10);
|
||||
@ -297,11 +348,7 @@ public class PayApi extends BaseApi {
|
||||
if (file.exists()) {
|
||||
return file;
|
||||
}
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
map.put("appid", weixinAccount.getAppId());
|
||||
map.put("mch_id", weixinAccount.getMchId());
|
||||
map.put("nonce_str", RandomUtil.generateString(16));
|
||||
map.put("device_info", weixinAccount.getDeviceInfo());
|
||||
Map<String, String> map = baseMap2V3(null);
|
||||
map.put("bill_date", _billDate);
|
||||
map.put("bill_type", billType.name());
|
||||
String sign = PayUtil.paysignMd5(map, weixinAccount.getPaySignKey());
|
||||
@ -334,7 +381,6 @@ public class PayApi extends BaseApi {
|
||||
* 退款查询<br/>
|
||||
* 退款有一定延时,用零钱支付的退款20分钟内到账,银行卡支付的退款 3 个工作日后重新查询退款状态
|
||||
*
|
||||
* @param weixinAccount 商户信息
|
||||
* @param idQuery
|
||||
* 单号 refund_id、out_refund_no、 out_trade_no 、 transaction_id
|
||||
* 四个参数必填一个,优先级为:
|
||||
@ -342,14 +388,9 @@ public class PayApi extends BaseApi {
|
||||
* @return 退款记录
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public Refund refundQuery(WeixinAccount weixinAccount, IdQuery idQuery)
|
||||
throws WeixinException {
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
map.put("appid", weixinAccount.getAppId());
|
||||
map.put("mch_id", weixinAccount.getMchId());
|
||||
map.put("nonce_str", RandomUtil.generateString(16));
|
||||
map.put("device_info", weixinAccount.getDeviceInfo());
|
||||
map.put(idQuery.getType().getName(), idQuery.getId());
|
||||
public Refund refundQuery(IdQuery idQuery) throws WeixinException {
|
||||
WeixinAccount weixinAccount = tokenHolder.getAccount();
|
||||
Map<String, String> map = baseMap2V3(idQuery);
|
||||
String sign = PayUtil.paysignMd5(map, weixinAccount.getPaySignKey());
|
||||
map.put("sign", sign);
|
||||
String param = map2xml(map);
|
||||
@ -357,4 +398,24 @@ public class PayApi extends BaseApi {
|
||||
Response response = request.post(refundquery_uri, param);
|
||||
return new RefundConverter().fromXML(response.getAsString());
|
||||
}
|
||||
|
||||
/**
|
||||
* V3接口请求基本数据
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private Map<String, String> baseMap2V3(IdQuery idQuery) {
|
||||
WeixinAccount weixinAccount = tokenHolder.getAccount();
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
map.put("appid", weixinAccount.getAppId());
|
||||
map.put("mch_id", weixinAccount.getMchId());
|
||||
map.put("nonce_str", RandomUtil.generateString(16));
|
||||
if (StringUtils.isNotBlank(weixinAccount.getDeviceInfo())) {
|
||||
map.put("device_info", weixinAccount.getDeviceInfo());
|
||||
}
|
||||
if (idQuery != null) {
|
||||
map.put(idQuery.getType().getName(), idQuery.getId());
|
||||
}
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,7 +10,7 @@ import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.http.JsonResult;
|
||||
import com.foxinmy.weixin4j.http.Response;
|
||||
import com.foxinmy.weixin4j.model.Token;
|
||||
import com.foxinmy.weixin4j.model.WeixinConfig;
|
||||
import com.foxinmy.weixin4j.model.WeixinAccount;
|
||||
import com.foxinmy.weixin4j.mp.model.Following;
|
||||
import com.foxinmy.weixin4j.mp.model.OauthToken;
|
||||
import com.foxinmy.weixin4j.mp.model.User;
|
||||
@ -45,10 +45,10 @@ public class UserApi extends BaseApi {
|
||||
* @see com.foxinmy.weixin4j.mp.model.OauthToken
|
||||
*/
|
||||
public OauthToken getOauthToken(String code) throws WeixinException {
|
||||
WeixinAccount weixinAccount = tokenHolder.getAccount();
|
||||
String user_token_uri = getRequestUri("sns_user_token_uri");
|
||||
WeixinConfig weixinConfig = tokenHolder.getConfig();
|
||||
Response response = request.get(String.format(user_token_uri,
|
||||
weixinConfig.getAppId(), weixinConfig.getAppSecret(), code));
|
||||
weixinAccount.getAppId(), weixinAccount.getAppSecret(), code));
|
||||
|
||||
return response.getAsObject(new TypeReference<OauthToken>() {
|
||||
});
|
||||
|
||||
@ -17,11 +17,21 @@ public class OauthToken extends Token {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String openid;
|
||||
|
||||
@JSONField(name = "refresh_token")
|
||||
private String refreshToken;
|
||||
|
||||
private String scope;
|
||||
|
||||
public String getOpenid() {
|
||||
return openid;
|
||||
}
|
||||
|
||||
public void setOpenid(String openid) {
|
||||
this.openid = openid;
|
||||
}
|
||||
|
||||
public String getRefreshToken() {
|
||||
return refreshToken;
|
||||
}
|
||||
@ -40,6 +50,9 @@ public class OauthToken extends Token {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "UserToken [refreshToken=" + refreshToken + ", scope=" + scope + ", getAccessToken()=" + getAccessToken() + ", getExpiresIn()=" + getExpiresIn() + ", getOpenid()=" + getOpenid() + ", getTime()=" + getTime() + "]";
|
||||
return "OauthToken [openid=" + openid + ", refreshToken="
|
||||
+ refreshToken + ", scope=" + scope + ", getAccessToken()="
|
||||
+ getAccessToken() + ", getExpiresIn()=" + getExpiresIn()
|
||||
+ ", getTime()=" + getTime() + "]";
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,6 +20,8 @@ public class ApiResult extends XmlResult {
|
||||
private String appId;// 微信分配的公众账号 ID商户号 非空
|
||||
@XStreamAlias("mch_id")
|
||||
private String mchId;// 微信支付分配的商户号 非空
|
||||
@XStreamAlias("sub_mch_id")
|
||||
private String subMchId; // 未知 可能为空
|
||||
@XStreamAlias("nonce_str")
|
||||
private String nonceStr;// 随机字符串 非空
|
||||
private String sign;// 签名 非空
|
||||
@ -50,6 +52,14 @@ public class ApiResult extends XmlResult {
|
||||
this.mchId = mchId;
|
||||
}
|
||||
|
||||
public String getSubMchId() {
|
||||
return subMchId;
|
||||
}
|
||||
|
||||
public void setSubMchId(String subMchId) {
|
||||
this.subMchId = subMchId;
|
||||
}
|
||||
|
||||
public String getNonceStr() {
|
||||
return nonceStr;
|
||||
}
|
||||
@ -76,8 +86,11 @@ public class ApiResult extends XmlResult {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ApiResult [appId=" + appId + ", mchId=" + mchId + ", nonceStr="
|
||||
+ nonceStr + ", sign=" + sign + ", deviceInfo=" + deviceInfo
|
||||
+ "]";
|
||||
return "ApiResult [appId=" + appId + ", mchId=" + mchId + ", subMchId="
|
||||
+ subMchId + ", nonceStr=" + nonceStr + ", sign=" + sign
|
||||
+ ", deviceInfo=" + deviceInfo + ", getReturnCode()="
|
||||
+ getReturnCode() + ", getReturnMsg()=" + getReturnMsg()
|
||||
+ ", getResultCode()=" + getResultCode() + ", getErrCode()="
|
||||
+ getErrCode() + ", getErrCodeDes()=" + getErrCodeDes() + "]";
|
||||
}
|
||||
}
|
||||
|
||||
@ -52,7 +52,7 @@ public class PayPackage implements Serializable {
|
||||
}
|
||||
|
||||
public void setTotal_fee(double total_fee) {
|
||||
this.total_fee = DateUtil.format2fee(total_fee);
|
||||
this.total_fee = DateUtil.formaFee2Fen(total_fee);
|
||||
}
|
||||
|
||||
public String getSpbill_create_ip() {
|
||||
@ -78,7 +78,6 @@ public class PayPackage implements Serializable {
|
||||
public void setTime_start(Date time_start) {
|
||||
this.time_start = time_start != null ? DateUtil
|
||||
.fortmat2yyyyMMddHHmmss(time_start) : null;
|
||||
;
|
||||
}
|
||||
|
||||
public String getTime_expire() {
|
||||
@ -88,7 +87,6 @@ public class PayPackage implements Serializable {
|
||||
public void setTime_expire(Date time_expire) {
|
||||
this.time_expire = time_expire != null ? DateUtil
|
||||
.fortmat2yyyyMMddHHmmss(time_expire) : null;
|
||||
;
|
||||
}
|
||||
|
||||
public String getGoods_tag() {
|
||||
@ -116,7 +114,7 @@ public class PayPackage implements Serializable {
|
||||
this.body = body;
|
||||
this.attach = attach;
|
||||
this.out_trade_no = out_trade_no;
|
||||
this.total_fee = DateUtil.format2fee(total_fee);
|
||||
this.total_fee = DateUtil.formaFee2Fen(total_fee);
|
||||
this.spbill_create_ip = spbill_create_ip;
|
||||
this.time_start = time_start != null ? DateUtil
|
||||
.fortmat2yyyyMMddHHmmss(time_start) : null;
|
||||
|
||||
@ -1,8 +1,11 @@
|
||||
package com.foxinmy.weixin4j.mp.payment.v2;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.foxinmy.weixin4j.http.JsonResult;
|
||||
import com.foxinmy.weixin4j.util.DateUtil;
|
||||
|
||||
/**
|
||||
* 订单信息
|
||||
@ -18,84 +21,104 @@ public class Order extends JsonResult {
|
||||
private static final long serialVersionUID = 4543552984506609920L;
|
||||
|
||||
// 是查询结果状态码,0 表明成功,其他表明错误;
|
||||
private String ret_code;
|
||||
@JSONField(name = "ret_code")
|
||||
private int retCode;
|
||||
// 是查询结果出错信息;
|
||||
private String ret_msg;
|
||||
@JSONField(name = "ret_msg")
|
||||
private String retMsg;
|
||||
// 是返回信息中的编码方式;
|
||||
private String input_charset;
|
||||
@JSONField(name = "input_charset")
|
||||
private String inputCharset;
|
||||
// 是订单状态,0 为成功,其他为失败;
|
||||
private String trade_state;
|
||||
@JSONField(name = "trade_state")
|
||||
private int tradeState;
|
||||
// 是交易模式,1 为即时到帐,其他保留;
|
||||
private String trade_mode;
|
||||
@JSONField(name = "trade_mode")
|
||||
private int tradeMode;
|
||||
// 是财付通商户号,即前文的 partnerid;
|
||||
private String partner;
|
||||
// 是银行类型;
|
||||
private String bank_type;
|
||||
@JSONField(name = "bank_type")
|
||||
private String bankType;
|
||||
// 是银行订单号;
|
||||
private String bank_billno;
|
||||
@JSONField(name = "bank_billno")
|
||||
private String bankBillno;
|
||||
// 是总金额,单位为分;
|
||||
private String total_fee;
|
||||
@JSONField(name = "total_fee")
|
||||
private int totalFee;
|
||||
// 是币种,1 为人民币;
|
||||
private String fee_type;
|
||||
@JSONField(name = "fee_type")
|
||||
private String feeType;
|
||||
// 是财付通订单号;
|
||||
private String transaction_id;
|
||||
@JSONField(name = "transaction_id")
|
||||
private String transactionId;
|
||||
// 是第三方订单号;
|
||||
private String out_trade_no;
|
||||
@JSONField(name = "out_trade_no")
|
||||
private String outTradeNo;
|
||||
// 表明是否分账,false 为无分账,true 为有分账;
|
||||
private boolean is_split;
|
||||
@JSONField(name = "is_split")
|
||||
private boolean isSplit;
|
||||
// 表明是否退款,false 为无退款,ture 为退款;
|
||||
private boolean is_refund;
|
||||
@JSONField(name = "is_refund")
|
||||
private boolean isRefund;
|
||||
// attach 是商户数据包,即生成订单package 时商户填入的 attach;
|
||||
private String attach;
|
||||
// 支付完成时间;
|
||||
private String time_end;
|
||||
@JSONField(name = "time_end")
|
||||
private String timeEnd;
|
||||
// 物流费用,单位为分;
|
||||
private String transport_fee;
|
||||
@JSONField(name = "transport_fee")
|
||||
private int transportFee;
|
||||
// 物品费用,单位为分;
|
||||
private String product_fee;
|
||||
@JSONField(name = "product_fee")
|
||||
private int productFee;
|
||||
// 折扣价格,单位为分;
|
||||
private String discount;
|
||||
private int discount;
|
||||
// 换算成人民币之后的总金额,单位为分,一般看 total_fee 即可。
|
||||
private String rmb_total_fee;
|
||||
@JSONField(name = "rmb_total_fee")
|
||||
private int rmbTotalFee;
|
||||
|
||||
public String getRet_code() {
|
||||
return ret_code;
|
||||
@JSONField(serialize = false)
|
||||
private Map<String, String> mapData;
|
||||
|
||||
public int getRetCode() {
|
||||
return retCode;
|
||||
}
|
||||
|
||||
public void setRet_code(String ret_code) {
|
||||
this.ret_code = ret_code;
|
||||
public void setRetCode(int retCode) {
|
||||
this.retCode = retCode;
|
||||
}
|
||||
|
||||
public String getRet_msg() {
|
||||
return ret_msg;
|
||||
public String getRetMsg() {
|
||||
return retMsg;
|
||||
}
|
||||
|
||||
public void setRet_msg(String ret_msg) {
|
||||
this.ret_msg = ret_msg;
|
||||
public void setRetMsg(String retMsg) {
|
||||
this.retMsg = retMsg;
|
||||
}
|
||||
|
||||
public String getInput_charset() {
|
||||
return input_charset;
|
||||
public String getInputCharset() {
|
||||
return inputCharset;
|
||||
}
|
||||
|
||||
public void setInput_charset(String input_charset) {
|
||||
this.input_charset = input_charset;
|
||||
public void setInputCharset(String inputCharset) {
|
||||
this.inputCharset = inputCharset;
|
||||
}
|
||||
|
||||
public String getTrade_state() {
|
||||
return trade_state;
|
||||
public int getTradeState() {
|
||||
return tradeState;
|
||||
}
|
||||
|
||||
public void setTrade_state(String trade_state) {
|
||||
this.trade_state = trade_state;
|
||||
public void setTradeState(int tradeState) {
|
||||
this.tradeState = tradeState;
|
||||
}
|
||||
|
||||
public String getTrade_mode() {
|
||||
return trade_mode;
|
||||
public int getTradeMode() {
|
||||
return tradeMode;
|
||||
}
|
||||
|
||||
public void setTrade_mode(String trade_mode) {
|
||||
this.trade_mode = trade_mode;
|
||||
public void setTradeMode(int tradeMode) {
|
||||
this.tradeMode = tradeMode;
|
||||
}
|
||||
|
||||
public String getPartner() {
|
||||
@ -106,68 +129,73 @@ public class Order extends JsonResult {
|
||||
this.partner = partner;
|
||||
}
|
||||
|
||||
public String getBank_type() {
|
||||
return bank_type;
|
||||
public String getBankType() {
|
||||
return bankType;
|
||||
}
|
||||
|
||||
public void setBank_type(String bank_type) {
|
||||
this.bank_type = bank_type;
|
||||
public void setBankType(String bankType) {
|
||||
this.bankType = bankType;
|
||||
}
|
||||
|
||||
public String getBank_billno() {
|
||||
return bank_billno;
|
||||
public String getBankBillno() {
|
||||
return bankBillno;
|
||||
}
|
||||
|
||||
public void setBank_billno(String bank_billno) {
|
||||
this.bank_billno = bank_billno;
|
||||
public void setBankBillno(String bankBillno) {
|
||||
this.bankBillno = bankBillno;
|
||||
}
|
||||
|
||||
public String getTotal_fee() {
|
||||
return total_fee;
|
||||
/**
|
||||
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
|
||||
*
|
||||
* @return 元单位
|
||||
*/
|
||||
public double getTotalFee() {
|
||||
return totalFee / 100d;
|
||||
}
|
||||
|
||||
public void setTotal_fee(String total_fee) {
|
||||
this.total_fee = total_fee;
|
||||
public void setTotalFee(int totalFee) {
|
||||
this.totalFee = totalFee;
|
||||
}
|
||||
|
||||
public String getFee_type() {
|
||||
return fee_type;
|
||||
public String getFeeType() {
|
||||
return feeType;
|
||||
}
|
||||
|
||||
public void setFee_type(String fee_type) {
|
||||
this.fee_type = fee_type;
|
||||
public void setFeeType(String feeType) {
|
||||
this.feeType = feeType;
|
||||
}
|
||||
|
||||
public String getTransaction_id() {
|
||||
return transaction_id;
|
||||
public String getTransactionId() {
|
||||
return transactionId;
|
||||
}
|
||||
|
||||
public void setTransaction_id(String transaction_id) {
|
||||
this.transaction_id = transaction_id;
|
||||
public void setTransactionId(String transactionId) {
|
||||
this.transactionId = transactionId;
|
||||
}
|
||||
|
||||
public String getOut_trade_no() {
|
||||
return out_trade_no;
|
||||
public String getOutTradeNo() {
|
||||
return outTradeNo;
|
||||
}
|
||||
|
||||
public void setOut_trade_no(String out_trade_no) {
|
||||
this.out_trade_no = out_trade_no;
|
||||
public void setOutTradeNo(String outTradeNo) {
|
||||
this.outTradeNo = outTradeNo;
|
||||
}
|
||||
|
||||
public boolean isIs_split() {
|
||||
return is_split;
|
||||
public boolean isSplit() {
|
||||
return isSplit;
|
||||
}
|
||||
|
||||
public void setIs_split(boolean is_split) {
|
||||
this.is_split = is_split;
|
||||
public void setSplit(boolean isSplit) {
|
||||
this.isSplit = isSplit;
|
||||
}
|
||||
|
||||
public boolean isIs_refund() {
|
||||
return is_refund;
|
||||
public boolean isRefund() {
|
||||
return isRefund;
|
||||
}
|
||||
|
||||
public void setIs_refund(boolean is_refund) {
|
||||
this.is_refund = is_refund;
|
||||
public void setRefund(boolean isRefund) {
|
||||
this.isRefund = isRefund;
|
||||
}
|
||||
|
||||
public String getAttach() {
|
||||
@ -178,48 +206,66 @@ public class Order extends JsonResult {
|
||||
this.attach = attach;
|
||||
}
|
||||
|
||||
public String getTime_end() {
|
||||
return time_end;
|
||||
public Date getTimeEnd() {
|
||||
return DateUtil.parse2yyyyMMddHHmmss(timeEnd);
|
||||
}
|
||||
|
||||
public void setTime_end(String time_end) {
|
||||
this.time_end = time_end;
|
||||
public void setTimeEnd(String timeEnd) {
|
||||
this.timeEnd = timeEnd;
|
||||
}
|
||||
|
||||
public String getTransport_fee() {
|
||||
return transport_fee;
|
||||
/**
|
||||
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
|
||||
*
|
||||
* @return 元单位
|
||||
*/
|
||||
public double getTransportFee() {
|
||||
return transportFee / 100d;
|
||||
}
|
||||
|
||||
public void setTransport_fee(String transport_fee) {
|
||||
this.transport_fee = transport_fee;
|
||||
public void setTransportFee(int transportFee) {
|
||||
this.transportFee = transportFee;
|
||||
}
|
||||
|
||||
public String getProduct_fee() {
|
||||
return product_fee;
|
||||
/**
|
||||
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
|
||||
*
|
||||
* @return 元单位
|
||||
*/
|
||||
public double getProductFee() {
|
||||
return productFee / 100d;
|
||||
}
|
||||
|
||||
public void setProduct_fee(String product_fee) {
|
||||
this.product_fee = product_fee;
|
||||
public void setProductFee(int productFee) {
|
||||
this.productFee = productFee;
|
||||
}
|
||||
|
||||
public String getDiscount() {
|
||||
return discount;
|
||||
/**
|
||||
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
|
||||
*
|
||||
* @return 元单位
|
||||
*/
|
||||
public double getDiscount() {
|
||||
return discount / 100d;
|
||||
}
|
||||
|
||||
public void setDiscount(String discount) {
|
||||
public void setDiscount(int discount) {
|
||||
this.discount = discount;
|
||||
}
|
||||
|
||||
public String getRmb_total_fee() {
|
||||
return rmb_total_fee;
|
||||
/**
|
||||
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
|
||||
*
|
||||
* @return 元单位
|
||||
*/
|
||||
public double getRmbTotalFee() {
|
||||
return rmbTotalFee / 100d;
|
||||
}
|
||||
|
||||
public void setRmb_total_fee(String rmb_total_fee) {
|
||||
this.rmb_total_fee = rmb_total_fee;
|
||||
public void setRmbTotalFee(int rmbTotalFee) {
|
||||
this.rmbTotalFee = rmbTotalFee;
|
||||
}
|
||||
|
||||
private Map<String, String> mapData;
|
||||
|
||||
public Map<String, String> getMapData() {
|
||||
return mapData;
|
||||
}
|
||||
@ -230,16 +276,16 @@ public class Order extends JsonResult {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Order [ret_code=" + ret_code + ", ret_msg=" + ret_msg
|
||||
+ ", input_charset=" + input_charset + ", trade_state="
|
||||
+ trade_state + ", trade_mode=" + trade_mode + ", partner="
|
||||
+ partner + ", bank_type=" + bank_type + ", bank_billno="
|
||||
+ bank_billno + ", total_fee=" + total_fee + ", fee_type="
|
||||
+ fee_type + ", transaction_id=" + transaction_id
|
||||
+ ", out_trade_no=" + out_trade_no + ", is_split=" + is_split
|
||||
+ ", is_refund=" + is_refund + ", attach=" + attach
|
||||
+ ", time_end=" + time_end + ", transport_fee=" + transport_fee
|
||||
+ ", product_fee=" + product_fee + ", discount=" + discount
|
||||
+ ", rmb_total_fee=" + rmb_total_fee + "]";
|
||||
return "Order [retCode=" + retCode + ", retMsg=" + retMsg
|
||||
+ ", inputCharset=" + inputCharset + ", tradeState="
|
||||
+ tradeState + ", tradeMode=" + tradeMode + ", partner="
|
||||
+ partner + ", bankType=" + bankType + ", bankBillno="
|
||||
+ bankBillno + ", totalFee=" + totalFee + ", feeType="
|
||||
+ feeType + ", transactionId=" + transactionId
|
||||
+ ", outTradeNo=" + outTradeNo + ", isSplit=" + isSplit
|
||||
+ ", isRefund=" + isRefund + ", attach=" + attach
|
||||
+ ", timeEnd=" + timeEnd + ", transportFee=" + transportFee
|
||||
+ ", productFee=" + productFee + ", discount=" + discount
|
||||
+ ", rmbTotalFee=" + rmbTotalFee + ", mapData=" + mapData + "]";
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,66 +38,34 @@ public class PayFeedback extends PayBaseInfo {
|
||||
return feedbackId;
|
||||
}
|
||||
|
||||
public void setFeedbackId(String feedbackId) {
|
||||
this.feedbackId = feedbackId;
|
||||
}
|
||||
|
||||
public String getOpenId() {
|
||||
return openId;
|
||||
}
|
||||
|
||||
public void setOpenId(String openId) {
|
||||
this.openId = openId;
|
||||
}
|
||||
|
||||
public String getTransId() {
|
||||
return transId;
|
||||
}
|
||||
|
||||
public void setTransId(String transId) {
|
||||
this.transId = transId;
|
||||
}
|
||||
|
||||
public String getReason() {
|
||||
return reason;
|
||||
}
|
||||
|
||||
public void setReason(String reason) {
|
||||
this.reason = reason;
|
||||
}
|
||||
|
||||
public String getSolution() {
|
||||
return solution;
|
||||
}
|
||||
|
||||
public void setSolution(String solution) {
|
||||
this.solution = solution;
|
||||
}
|
||||
|
||||
public String getExtInfo() {
|
||||
return extInfo;
|
||||
}
|
||||
|
||||
public void setExtInfo(String extInfo) {
|
||||
this.extInfo = extInfo;
|
||||
}
|
||||
|
||||
public String getPicInfo() {
|
||||
return picInfo;
|
||||
}
|
||||
|
||||
public void setPicInfo(String picInfo) {
|
||||
this.picInfo = picInfo;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PayFeedback [feedbackId=" + feedbackId + ", openId=" + openId
|
||||
|
||||
@ -72,7 +72,7 @@ public class PayPackageV2 extends PayPackage {
|
||||
}
|
||||
|
||||
public void setTransport_fee(double transport_fee) {
|
||||
this.transport_fee = DateUtil.format2fee(transport_fee);
|
||||
this.transport_fee = DateUtil.formaFee2Fen(transport_fee);
|
||||
}
|
||||
|
||||
public String getProduct_fee() {
|
||||
@ -80,7 +80,7 @@ public class PayPackageV2 extends PayPackage {
|
||||
}
|
||||
|
||||
public void setProduct_fee(double product_fee) {
|
||||
this.product_fee = DateUtil.format2fee(product_fee);
|
||||
this.product_fee = DateUtil.formaFee2Fen(product_fee);
|
||||
}
|
||||
|
||||
public String getInput_charset() {
|
||||
@ -125,8 +125,8 @@ public class PayPackageV2 extends PayPackage {
|
||||
this.fee_type = "1";
|
||||
this.input_charset = "UTF-8";
|
||||
this.transport_fee = transport_fee > 0d ? DateUtil
|
||||
.format2fee(transport_fee) : null;
|
||||
this.product_fee = product_fee > 0 ? DateUtil.format2fee(product_fee)
|
||||
.formaFee2Fen(transport_fee) : null;
|
||||
this.product_fee = product_fee > 0 ? DateUtil.formaFee2Fen(product_fee)
|
||||
: null;
|
||||
}
|
||||
|
||||
|
||||
@ -21,26 +21,14 @@ public class PayWarn extends PayBaseInfo {
|
||||
return errortype;
|
||||
}
|
||||
|
||||
public void setErrortype(String errortype) {
|
||||
this.errortype = errortype;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getAlarmcontent() {
|
||||
return alarmcontent;
|
||||
}
|
||||
|
||||
public void setAlarmcontent(String alarmcontent) {
|
||||
this.alarmcontent = alarmcontent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PayWarn [errortype=" + errortype + ", description="
|
||||
|
||||
@ -1,9 +1,12 @@
|
||||
package com.foxinmy.weixin4j.mp.payment.v3;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import com.foxinmy.weixin4j.mp.payment.ApiResult;
|
||||
import com.foxinmy.weixin4j.mp.type.CurrencyType;
|
||||
import com.foxinmy.weixin4j.mp.type.TradeState;
|
||||
import com.foxinmy.weixin4j.mp.type.TradeType;
|
||||
import com.foxinmy.weixin4j.util.DateUtil;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
@ -51,7 +54,6 @@ public class Order extends ApiResult {
|
||||
@XStreamAlias("out_rade_no")
|
||||
private String outTradeNo;
|
||||
// 商家数据包
|
||||
@XStreamAlias("attach")
|
||||
private String attach;
|
||||
// 支付完成时间,格式为 yyyyMMddhhmmss
|
||||
@XStreamAlias("time_end")
|
||||
@ -61,96 +63,58 @@ public class Order extends ApiResult {
|
||||
return tradeState;
|
||||
}
|
||||
|
||||
public void setTradeState(TradeState tradeState) {
|
||||
this.tradeState = tradeState;
|
||||
}
|
||||
|
||||
public String getOpenId() {
|
||||
return openId;
|
||||
}
|
||||
|
||||
public void setOpenId(String openId) {
|
||||
this.openId = openId;
|
||||
}
|
||||
|
||||
public String getIsSubscribe() {
|
||||
return isSubscribe;
|
||||
}
|
||||
|
||||
public void setIsSubscribe(String isSubscribe) {
|
||||
this.isSubscribe = isSubscribe;
|
||||
}
|
||||
|
||||
public TradeType getTradeType() {
|
||||
return tradeType;
|
||||
}
|
||||
|
||||
public void setTradeType(TradeType tradeType) {
|
||||
this.tradeType = tradeType;
|
||||
}
|
||||
|
||||
public String getBankType() {
|
||||
return bankType;
|
||||
}
|
||||
|
||||
public void setBankType(String bankType) {
|
||||
this.bankType = bankType;
|
||||
/**
|
||||
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
|
||||
*
|
||||
* @return 元单位
|
||||
*/
|
||||
public double getTotalFee() {
|
||||
return totalFee / 100d;
|
||||
}
|
||||
|
||||
public int getTotalFee() {
|
||||
return totalFee;
|
||||
}
|
||||
|
||||
public void setTotalFee(int totalFee) {
|
||||
this.totalFee = totalFee;
|
||||
}
|
||||
|
||||
public int getCouponFee() {
|
||||
return couponFee;
|
||||
}
|
||||
|
||||
public void setCouponFee(int couponFee) {
|
||||
this.couponFee = couponFee;
|
||||
/**
|
||||
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
|
||||
*
|
||||
* @return 元单位
|
||||
*/
|
||||
public double getCouponFee() {
|
||||
return couponFee / 100d;
|
||||
}
|
||||
|
||||
public CurrencyType getFeeType() {
|
||||
return feeType;
|
||||
}
|
||||
|
||||
public void setFeeType(CurrencyType feeType) {
|
||||
this.feeType = feeType;
|
||||
}
|
||||
|
||||
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 getAttach() {
|
||||
return attach;
|
||||
}
|
||||
|
||||
public void setAttach(String attach) {
|
||||
this.attach = attach;
|
||||
}
|
||||
|
||||
public String getTimeEnd() {
|
||||
return timeEnd;
|
||||
}
|
||||
|
||||
public void setTimeEnd(String timeEnd) {
|
||||
this.timeEnd = timeEnd;
|
||||
public Date getTimeEnd() {
|
||||
return DateUtil.parse2yyyyMMddHHmmss(timeEnd);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -33,34 +33,18 @@ public class Refund extends ApiResult {
|
||||
return transactionId;
|
||||
}
|
||||
|
||||
public void setTransactionId(String transactionId) {
|
||||
this.transactionId = transactionId;
|
||||
}
|
||||
|
||||
public String getOrderNo() {
|
||||
return orderNo;
|
||||
}
|
||||
|
||||
public void setOrderNo(String orderNo) {
|
||||
this.orderNo = orderNo;
|
||||
}
|
||||
|
||||
public String getSubMchId() {
|
||||
return subMchId;
|
||||
}
|
||||
|
||||
public void setSubMchId(String subMchId) {
|
||||
this.subMchId = subMchId;
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public void setCount(int count) {
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
public List<RefundDetail> getDetails() {
|
||||
return details;
|
||||
}
|
||||
@ -71,15 +55,14 @@ public class Refund extends ApiResult {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Refund [transactionId=" + transactionId + ", subMchId="
|
||||
+ subMchId + ", orderNo=" + orderNo + ", count=" + count
|
||||
return "Refund [transactionId=" + transactionId + ", orderNo="
|
||||
+ orderNo + ", subMchId=" + subMchId + ", count=" + count
|
||||
+ ", details=" + details + ", getAppId()=" + getAppId()
|
||||
+ ", getMchId()=" + getMchId() + ", getNonceStr()="
|
||||
+ getNonceStr() + ", getSign()=" + getSign()
|
||||
+ ", getDeviceInfo()=" + getDeviceInfo() + ", toString()="
|
||||
+ super.toString() + ", getReturnCode()=" + getReturnCode()
|
||||
+ ", getReturnMsg()=" + getReturnMsg() + ", getResultCode()="
|
||||
+ getResultCode() + ", getErrCode()=" + getErrCode()
|
||||
+ ", getErrCodeDes()=" + getErrCodeDes() + "]";
|
||||
+ ", getDeviceInfo()=" + getDeviceInfo() + ", getReturnCode()="
|
||||
+ getReturnCode() + ", getReturnMsg()=" + getReturnMsg()
|
||||
+ ", getResultCode()=" + getResultCode() + ", getErrCode()="
|
||||
+ getErrCode() + ", getErrCodeDes()=" + getErrCodeDes() + "]";
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,6 +2,9 @@ package com.foxinmy.weixin4j.mp.payment.v3;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.foxinmy.weixin4j.mp.type.RefundChannel;
|
||||
import com.foxinmy.weixin4j.mp.type.RefundStatus;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
@ -35,50 +38,37 @@ public class RefundDetail implements Serializable {
|
||||
return outRefundNo;
|
||||
}
|
||||
|
||||
public void setOutRefundNo(String outRefundNo) {
|
||||
this.outRefundNo = outRefundNo;
|
||||
}
|
||||
|
||||
public String getRefundId() {
|
||||
return refundId;
|
||||
}
|
||||
|
||||
public void setRefundId(String refundId) {
|
||||
this.refundId = refundId;
|
||||
}
|
||||
|
||||
public String getRefundChannel() {
|
||||
return refundChannel;
|
||||
return StringUtils.isBlank(refundChannel) ? RefundChannel.BALANCE
|
||||
.name() : refundChannel;
|
||||
}
|
||||
|
||||
public void setRefundChannel(String refundChannel) {
|
||||
this.refundChannel = refundChannel;
|
||||
/**
|
||||
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
|
||||
*
|
||||
* @return 元单位
|
||||
*/
|
||||
public double getRefundFee() {
|
||||
return refundFee / 100d;
|
||||
}
|
||||
|
||||
public int getRefundFee() {
|
||||
return refundFee;
|
||||
}
|
||||
|
||||
public void setRefundFee(int refundFee) {
|
||||
this.refundFee = refundFee;
|
||||
}
|
||||
|
||||
public int getCouponRefundFee() {
|
||||
return couponRefundFee;
|
||||
}
|
||||
|
||||
public void setCouponRefundFee(int couponRefundFee) {
|
||||
this.couponRefundFee = couponRefundFee;
|
||||
/**
|
||||
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
|
||||
*
|
||||
* @return 元单位
|
||||
*/
|
||||
public double getCouponRefundFee() {
|
||||
return couponRefundFee / 100d;
|
||||
}
|
||||
|
||||
public RefundStatus getRefundStatus() {
|
||||
return refundStatus;
|
||||
}
|
||||
|
||||
public void setRefundStatus(RefundStatus refundStatus) {
|
||||
this.refundStatus = refundStatus;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RefundDetail [outRefundNo=" + outRefundNo + ", refundId="
|
||||
|
||||
@ -0,0 +1,98 @@
|
||||
package com.foxinmy.weixin4j.mp.payment.v3;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.foxinmy.weixin4j.mp.payment.ApiResult;
|
||||
import com.foxinmy.weixin4j.mp.type.RefundChannel;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 退款申请结果
|
||||
*
|
||||
* @className RefundResult
|
||||
* @author jy
|
||||
* @date 2014年11月6日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
@XStreamAlias("xml")
|
||||
public class RefundResult extends ApiResult {
|
||||
|
||||
private static final long serialVersionUID = -3687863914168618620L;
|
||||
|
||||
// 微信订单号
|
||||
@XStreamAlias("transaction_id")
|
||||
private String transactionId;
|
||||
// 商户系统内部的订单号
|
||||
@XStreamAlias("out_trade_no")
|
||||
private String outTradeNo;
|
||||
// 商户退款单号
|
||||
@XStreamAlias("out_refund_no")
|
||||
private String outRefundNo;
|
||||
// 微信退款单号
|
||||
@XStreamAlias("refund_id")
|
||||
private String refundId;
|
||||
// 退款渠道 ORIGINAL—原路退款,默认 BALANCE—退回到余额
|
||||
@XStreamAlias("refund_channel")
|
||||
private String refundChannel;
|
||||
// 退款总金额,单位为元,可以做部分退款
|
||||
@XStreamAlias("refund_fee")
|
||||
private int refundFee;
|
||||
// 现金券退款金额<=退款金 额,退款金额-现金券退款金 额为现金
|
||||
@XStreamAlias("coupon_refund_fee")
|
||||
private int couponRefundFee;
|
||||
|
||||
public String getTransactionId() {
|
||||
return transactionId;
|
||||
}
|
||||
|
||||
public String getOutTradeNo() {
|
||||
return outTradeNo;
|
||||
}
|
||||
|
||||
public String getOutRefundNo() {
|
||||
return outRefundNo;
|
||||
}
|
||||
|
||||
public String getRefundId() {
|
||||
return refundId;
|
||||
}
|
||||
|
||||
public String getRefundChannel() {
|
||||
return StringUtils.isBlank(refundChannel) ? RefundChannel.BALANCE
|
||||
.name() : refundChannel;
|
||||
}
|
||||
|
||||
/**
|
||||
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
|
||||
*
|
||||
* @return 元单位
|
||||
*/
|
||||
public double getRefundFee() {
|
||||
return refundFee / 100d;
|
||||
}
|
||||
|
||||
/**
|
||||
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
|
||||
*
|
||||
* @return 元单位
|
||||
*/
|
||||
public double getCouponRefundFee() {
|
||||
return couponRefundFee / 100d;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RefundResult [transactionId=" + transactionId + ", outTradeNo="
|
||||
+ outTradeNo + ", outRefundNo=" + outRefundNo + ", refundId="
|
||||
+ refundId + ", refundChannel=" + refundChannel
|
||||
+ ", refundFee=" + refundFee + ", couponRefundFee="
|
||||
+ couponRefundFee + ", getAppId()=" + getAppId()
|
||||
+ ", getMchId()=" + getMchId() + ", getNonceStr()="
|
||||
+ getNonceStr() + ", getSign()=" + getSign()
|
||||
+ ", getDeviceInfo()=" + getDeviceInfo() + ", getReturnCode()="
|
||||
+ getReturnCode() + ", getReturnMsg()=" + getReturnMsg()
|
||||
+ ", getResultCode()=" + getResultCode() + ", getErrCode()="
|
||||
+ getErrCode() + ", getErrCodeDes()=" + getErrCodeDes() + "]";
|
||||
}
|
||||
}
|
||||
@ -12,7 +12,7 @@ package com.foxinmy.weixin4j.mp.type;
|
||||
public enum IdType {
|
||||
REFUNDID("refund_id"), // 微信退款单号
|
||||
TRANSACTIONID("transaction_id"), // 微信订单号
|
||||
ORDERNO("out_trade_no"), // 商户订单号
|
||||
TRADENO("out_trade_no"), // 商户订单号
|
||||
REFUNDNO("out_refund_no"); // 商户退款号
|
||||
private String name;
|
||||
|
||||
|
||||
@ -0,0 +1,15 @@
|
||||
package com.foxinmy.weixin4j.mp.type;
|
||||
|
||||
/**
|
||||
* 退款渠道
|
||||
*
|
||||
* @className RefundChannel
|
||||
* @author jy
|
||||
* @date 2014年11月6日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public enum RefundChannel {
|
||||
ORIGINAL, // 原路退款
|
||||
BALANCE;// 退回到余额
|
||||
}
|
||||
@ -36,11 +36,11 @@ public class MessagePush {
|
||||
|
||||
int status = statusLine.getStatusCode();
|
||||
if (status != HttpStatus.SC_OK) {
|
||||
throw new WeixinException(status + "", "request fail");
|
||||
throw new WeixinException(Integer.toString(status), "request fail");
|
||||
}
|
||||
if (status == HttpStatus.SC_MOVED_PERMANENTLY
|
||||
|| status == HttpStatus.SC_MOVED_TEMPORARILY) {
|
||||
throw new WeixinException(status + "", "uri moved");
|
||||
throw new WeixinException(Integer.toString(status), "uri moved");
|
||||
}
|
||||
return EntityUtils.toString(httpResponse.getEntity(),
|
||||
StandardCharsets.UTF_8);
|
||||
|
||||
@ -23,7 +23,7 @@ weixin4j-mp-server
|
||||
| media_path | 调用媒体接口时保存媒体文件的物理路径 |
|
||||
| bill_path | 调用支付(`V3`)下载对账单接口保存excel文件的物理路径 |
|
||||
|
||||
示例(properties中换行用右斜杆\)
|
||||
示例(properties中换行用右斜杆\\)
|
||||
|
||||
> account={"appId":"appId","appSecret":"appSecret",
|
||||
> "token":"开放者的token 非必须","openId":"公众号的openid 非必须",
|
||||
|
||||
@ -12,4 +12,6 @@ qr_path=/tmp/weixin/qr
|
||||
# \u5a92\u4f53\u6587\u4ef6\u4fdd\u5b58\u8def\u5f84
|
||||
media_path=/tmp/weixin/media
|
||||
# \u5bf9\u8d26\u5355\u4fdd\u5b58\u8def\u5f84
|
||||
bill_path=/tmp/weixin/bill
|
||||
bill_path=/tmp/weixin/bill
|
||||
# ca\u8bc1\u4e66\u5b58\u653e\u7684\u5b8c\u6574\u8def\u5f84
|
||||
ca_file=/tmp/weixin/xxxxx.p12
|
||||
Loading…
x
Reference in New Issue
Block a user