新增V2版本"退款申请","退款查询","对账单下载"三个接口以及语义理解接口鸡肋实现
This commit is contained in:
parent
1371d1d5c7
commit
ff436b6f03
@ -32,7 +32,7 @@ weixin4j
|
||||
|
||||
* 2014-10-31
|
||||
|
||||
+ **weixin4j-mp**: `weixin.properties`切分为API调用地址/公众号信息两部分
|
||||
+ **weixin4j-mp**: `weixin.properties`切分为API调用地址和公众号信息两部分
|
||||
|
||||
+ **weixin4j-base**: `TokenApi`重命名为`TokenHolder`
|
||||
|
||||
@ -54,6 +54,12 @@ weixin4j
|
||||
|
||||
+ **weixin-mp**: 新增`退款接口`
|
||||
|
||||
* 2014-11-08
|
||||
|
||||
+ **weixin-mp**: 新增V2版本`退款申请`、`退款查询`、`对账单下载`三个接口
|
||||
|
||||
+ **weixin-mp**: 新增一个简单的`语义理解`接口
|
||||
|
||||
接下来
|
||||
------
|
||||
* 公众号智能接口
|
||||
|
||||
@ -103,5 +103,10 @@
|
||||
<artifactId>commons-codec</artifactId>
|
||||
<version>${commons.codec.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jsoup</groupId>
|
||||
<artifactId>jsoup</artifactId>
|
||||
<version>${jsoup.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
@ -22,6 +22,7 @@ public class WeixinException extends Exception {
|
||||
}
|
||||
|
||||
public WeixinException(String errorMsg) {
|
||||
this.errorCode = "";
|
||||
this.errorMsg = errorMsg;
|
||||
}
|
||||
|
||||
|
||||
@ -3,10 +3,11 @@ package com.foxinmy.weixin4j.http;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.http.Consts;
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.HttpEntity;
|
||||
@ -32,9 +33,13 @@ import org.apache.http.impl.conn.PoolingClientConnectionManager;
|
||||
import org.apache.http.params.CoreConnectionPNames;
|
||||
import org.apache.http.params.CoreProtocolPNames;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Document;
|
||||
|
||||
import com.alibaba.fastjson.JSONException;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.util.MapUtil;
|
||||
import com.thoughtworks.xstream.mapper.CannotResolveClassException;
|
||||
|
||||
/**
|
||||
* 调用微信相关接口的HttpRequest,对于其他请求可能并不试用
|
||||
@ -46,7 +51,7 @@ import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
* @see
|
||||
*/
|
||||
public class HttpRequest {
|
||||
private final String SUCCESS = "success";
|
||||
|
||||
protected AbstractHttpClient client;
|
||||
|
||||
public HttpRequest() {
|
||||
@ -84,6 +89,14 @@ public class HttpRequest {
|
||||
return get(url, (Parameter[]) null);
|
||||
}
|
||||
|
||||
public Response get(String url, Map<String, String> para)
|
||||
throws WeixinException {
|
||||
return get(
|
||||
String.format("%s?%s", url,
|
||||
MapUtil.toJoinString(para, false, false, null)),
|
||||
(Parameter[]) null);
|
||||
}
|
||||
|
||||
public Response get(String url, Parameter... parameters)
|
||||
throws WeixinException {
|
||||
StringBuilder sb = new StringBuilder(url);
|
||||
@ -106,11 +119,13 @@ public class HttpRequest {
|
||||
public Response post(String url, Parameter... parameters)
|
||||
throws WeixinException {
|
||||
HttpPost method = new HttpPost(url);
|
||||
if (parameters != null && parameters.length > 0) {
|
||||
List<NameValuePair> params = new ArrayList<NameValuePair>();
|
||||
for (Parameter parameter : parameters) {
|
||||
params.add(parameter.toPostPara());
|
||||
}
|
||||
method.setEntity(new UrlEncodedFormEntity(params, Consts.UTF_8));
|
||||
}
|
||||
return doRequest(method);
|
||||
}
|
||||
|
||||
@ -167,42 +182,39 @@ public class HttpRequest {
|
||||
String.format("the page was redirected to %s",
|
||||
httpResponse.getFirstHeader("location")));
|
||||
}
|
||||
|
||||
byte[] data = EntityUtils.toByteArray(httpEntity);
|
||||
response = new Response();
|
||||
response.setBody(data);
|
||||
response.setStatusCode(status);
|
||||
response.setStatusText(statusLine.getReasonPhrase());
|
||||
response.setStream(new ByteArrayInputStream(data));
|
||||
response.setText(new String(data, Consts.UTF_8));
|
||||
|
||||
EntityUtils.consume(httpEntity);
|
||||
Header contentType = httpResponse
|
||||
.getFirstHeader(HttpHeaders.CONTENT_TYPE);
|
||||
// error with html
|
||||
if (contentType.getValue().contains(
|
||||
ContentType.APPLICATION_JSON.getMimeType())
|
||||
|| contentType.getValue().contains(
|
||||
ContentType.TEXT_HTML.getMimeType())) {
|
||||
response.setText(new String(data, "gbk"));
|
||||
Document doc = Jsoup.parse(response.getAsString());
|
||||
throw new WeixinException(doc.body().text());
|
||||
} else if (contentType.getValue().contains(
|
||||
ContentType.APPLICATION_JSON.getMimeType())) {
|
||||
checkJson(response);
|
||||
} else if (contentType.getValue().contains(
|
||||
ContentType.TEXT_XML.getMimeType())) {
|
||||
checkXml(response);
|
||||
} else if (contentType.getValue().contains(
|
||||
ContentType.TEXT_PLAIN.getMimeType())) {
|
||||
response.setText(new String(data, StandardCharsets.UTF_8));
|
||||
try {
|
||||
JsonResult jsonResult = response.getAsJsonResult();
|
||||
response.setJsonResult(true);
|
||||
if (jsonResult.getCode() != 0) {
|
||||
throw new WeixinException(Integer.toString(jsonResult
|
||||
.getCode()), jsonResult.getDesc());
|
||||
}
|
||||
checkJson(response);
|
||||
return response;
|
||||
} catch (JSONException e) {
|
||||
;
|
||||
}
|
||||
XmlResult xmlResult = response.getAsXmlResult();
|
||||
response.setXmlResult(true);
|
||||
if (!xmlResult.getReturnCode().equalsIgnoreCase(SUCCESS)) {
|
||||
throw new WeixinException(xmlResult.getReturnCode(),
|
||||
xmlResult.getReturnMsg());
|
||||
}
|
||||
if (!xmlResult.getResultCode().equalsIgnoreCase(SUCCESS)) {
|
||||
throw new WeixinException(xmlResult.getErrCode(),
|
||||
xmlResult.getErrCodeDes());
|
||||
}
|
||||
checkXml(response);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new WeixinException("-1", e.getMessage());
|
||||
@ -211,4 +223,48 @@ public class HttpRequest {
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
private void checkJson(Response response) throws WeixinException {
|
||||
response.setJsonResult(true);
|
||||
JsonResult jsonResult = response.getAsJsonResult();
|
||||
if (jsonResult.getCode() != 0) {
|
||||
if (StringUtils.isBlank(jsonResult.getDesc())) {
|
||||
jsonResult = response.getTextError(jsonResult.getCode());
|
||||
}
|
||||
throw new WeixinException(Integer.toString(jsonResult.getCode()),
|
||||
jsonResult.getDesc());
|
||||
}
|
||||
}
|
||||
|
||||
private void checkXml(Response response) throws WeixinException {
|
||||
response.setXmlResult(true);
|
||||
XmlResult xmlResult = null;
|
||||
try {
|
||||
xmlResult = response.getAsXmlResult();
|
||||
} catch (CannotResolveClassException ex) {
|
||||
// <?xml><root><data..../data></root>
|
||||
String newXml = response.getAsString()
|
||||
.replaceFirst("<root>", "<xml>")
|
||||
.replaceFirst("<retcode>", "<return_code>")
|
||||
.replaceFirst("</retcode>", "</return_code>")
|
||||
.replaceFirst("<retmsg>", "<return_msg>")
|
||||
.replaceFirst("</retmsg>", "</return_msg>")
|
||||
.replaceFirst("</root>", "</xml>");
|
||||
response.setText(newXml);
|
||||
xmlResult = response.getAsXmlResult();
|
||||
}
|
||||
if (xmlResult.getReturnCode().equals("0")) {
|
||||
return;
|
||||
}
|
||||
if (!xmlResult.getReturnCode().equalsIgnoreCase(
|
||||
com.foxinmy.weixin4j.model.Consts.SUCCESS)) {
|
||||
throw new WeixinException(xmlResult.getReturnCode(),
|
||||
xmlResult.getReturnMsg());
|
||||
}
|
||||
if (!xmlResult.getResultCode().equalsIgnoreCase(
|
||||
com.foxinmy.weixin4j.model.Consts.SUCCESS)) {
|
||||
throw new WeixinException(xmlResult.getErrCode(),
|
||||
xmlResult.getErrCodeDes());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,15 +2,13 @@ package com.foxinmy.weixin4j.http;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.apache.http.Consts;
|
||||
import org.apache.http.NameValuePair;
|
||||
import org.apache.http.message.BasicNameValuePair;
|
||||
|
||||
public class Parameter {
|
||||
|
||||
private final static String CHARSET = StandardCharsets.UTF_8.name();
|
||||
|
||||
private String name;
|
||||
private String value;
|
||||
|
||||
@ -41,7 +39,8 @@ public class Parameter {
|
||||
|
||||
public String toGetPara() {
|
||||
try {
|
||||
return String.format("&%s=%s", name, URLEncoder.encode(value, CHARSET));
|
||||
return String.format("&%s=%s", name,
|
||||
URLEncoder.encode(value, Consts.UTF_8.name()));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
return String.format("&%s=%s", name, value);
|
||||
}
|
||||
@ -49,7 +48,8 @@ public class Parameter {
|
||||
|
||||
public NameValuePair toPostPara() {
|
||||
try {
|
||||
return new BasicNameValuePair(name, URLEncoder.encode(value, CHARSET));
|
||||
return new BasicNameValuePair(name, URLEncoder.encode(value,
|
||||
Consts.UTF_8.name()));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
return new BasicNameValuePair(name, value);
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ package com.foxinmy.weixin4j.http;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.dom4j.Document;
|
||||
import org.dom4j.DocumentException;
|
||||
import org.dom4j.Node;
|
||||
@ -73,18 +74,41 @@ public class Response {
|
||||
* @return
|
||||
* @throws DocumentException
|
||||
*/
|
||||
public JsonResult getTextError() throws DocumentException {
|
||||
JsonResult result = getAsJsonResult();
|
||||
if (result.getCode() != 0) {
|
||||
public JsonResult getTextError(int code) {
|
||||
JsonResult result = new JsonResult();
|
||||
result.setCode(code);
|
||||
SAXReader reader = new SAXReader();
|
||||
Document doc = reader.read(Response.class
|
||||
.getResourceAsStream("error.xml"));
|
||||
Node node = doc.getRootElement().selectSingleNode(
|
||||
String.format("error/code[text()='%d']", result.getCode()));
|
||||
if (node != null) {
|
||||
result.setText(node.getParent().selectSingleNode("text")
|
||||
.getStringValue());
|
||||
Document doc = null;
|
||||
try {
|
||||
doc = reader.read(Response.class.getResourceAsStream("error.xml"));
|
||||
} catch (DocumentException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
Node node = doc.getRootElement().selectSingleNode(
|
||||
String.format("error/code[text()=%d]", code));
|
||||
if (node != null) {
|
||||
node = node.getParent();
|
||||
String desc = null;
|
||||
Node _node = node.selectSingleNode("desc");
|
||||
if (_node != null) {
|
||||
desc = _node.getStringValue();
|
||||
}
|
||||
String text = null;
|
||||
_node = node.selectSingleNode("text");
|
||||
if (_node != null) {
|
||||
text = _node.getStringValue();
|
||||
}
|
||||
if (StringUtils.isBlank(desc) && StringUtils.isNotBlank(text)) {
|
||||
desc = text;
|
||||
}
|
||||
if (StringUtils.isBlank(text) && StringUtils.isNotBlank(desc)) {
|
||||
text = desc;
|
||||
}
|
||||
result.setDesc(desc);
|
||||
result.setText(text);
|
||||
} else {
|
||||
result.setDesc("unknown error");
|
||||
result.setText("未知错误");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -6,7 +6,10 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.KeyStore;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
|
||||
import org.apache.http.conn.scheme.Scheme;
|
||||
import org.apache.http.conn.scheme.SchemeSocketFactory;
|
||||
import org.apache.http.conn.ssl.SSLSocketFactory;
|
||||
|
||||
/**
|
||||
@ -27,7 +30,8 @@ public class SSLHttpRequest extends HttpRequest {
|
||||
public SSLHttpRequest(String password, InputStream inputStream) {
|
||||
super();
|
||||
try {
|
||||
KeyStore trustStore = KeyStore.getInstance("PKCS12");
|
||||
KeyStore trustStore = KeyStore
|
||||
.getInstance(com.foxinmy.weixin4j.model.Consts.PKCS12);
|
||||
trustStore.load(inputStream, password.toCharArray());
|
||||
SSLSocketFactory socketFactory = new SSLSocketFactory(trustStore,
|
||||
password);
|
||||
@ -45,4 +49,11 @@ public class SSLHttpRequest extends HttpRequest {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public SSLHttpRequest(SSLContext sslContext) {
|
||||
super();
|
||||
SchemeSocketFactory socketFactory = new SSLSocketFactory(sslContext);
|
||||
client.getConnectionManager().getSchemeRegistry()
|
||||
.register(new Scheme("https", 443, socketFactory));
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ package com.foxinmy.weixin4j.http;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.foxinmy.weixin4j.model.Consts;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
@ -16,8 +17,6 @@ import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
public class XmlResult implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -6185313616955051150L;
|
||||
public static final String SUCCESS = "SUCCESS";
|
||||
public static final String FAIL = "FAIL";
|
||||
|
||||
@XStreamAlias("return_code")
|
||||
private String returnCode;// 此字段是通信标识,非交易 标识,交易是否成功需要查 看 result_code 来判断 非空
|
||||
@ -71,15 +70,15 @@ public class XmlResult implements Serializable {
|
||||
}
|
||||
|
||||
public XmlResult() {
|
||||
this(SUCCESS.toLowerCase(), "");
|
||||
this(Consts.SUCCESS.toLowerCase(), "");
|
||||
}
|
||||
|
||||
public XmlResult(String returnCode, String returnMsg) {
|
||||
this.returnCode = returnCode;
|
||||
this.returnMsg = returnMsg;
|
||||
if (returnCode.equalsIgnoreCase(SUCCESS)) {
|
||||
this.resultCode = SUCCESS.toLowerCase();
|
||||
this.errCode = SUCCESS.toLowerCase();
|
||||
if (returnCode.equalsIgnoreCase(Consts.SUCCESS)) {
|
||||
this.resultCode = Consts.SUCCESS.toLowerCase();
|
||||
this.errCode = Consts.SUCCESS.toLowerCase();
|
||||
this.errCodeDes = "";
|
||||
}
|
||||
}
|
||||
|
||||
@ -362,6 +362,83 @@
|
||||
<desc>api unauthorized</desc>
|
||||
<text>接口未授权</text>
|
||||
</error>
|
||||
<!-- 语义理解API错误 -->
|
||||
<error>
|
||||
<code>7000000</code>
|
||||
<text>请求正常,无语义结果</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>7000001</code>
|
||||
<text>缺失请求参数</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>7000002</code>
|
||||
<text>signature 参数无效</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>7000003</code>
|
||||
<text>地理位置相关配置 1 无效</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>7000004</code>
|
||||
<text>地理位置相关配置 2 无效</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>7000005</code>
|
||||
<text>请求地理位置信息失败</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>7000006</code>
|
||||
<text>地理位置结果解析失败</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>7000007</code>
|
||||
<text>内部初始化失败</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>7000008</code>
|
||||
<text>非法 appid(获取密钥失败)</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>7000009</code>
|
||||
<text>请求语义服务失败</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>7000010</code>
|
||||
<text>非法 post 请求</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>7000011</code>
|
||||
<text>post 请求 json 字段无效</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>7000030</code>
|
||||
<text>查询 query 太短</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>7000031</code>
|
||||
<text>查询 query 太长</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>7000032</code>
|
||||
<text>城市、经纬度信息缺失</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>7000033</code>
|
||||
<text>query 请求语义处理失败</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>7000034</code>
|
||||
<text>获取天气信息失败</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>7000035</code>
|
||||
<text>获取股票信息失败</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>7000036</code>
|
||||
<text>utf8 编码转换失败</text>
|
||||
</error>
|
||||
<!-- 微信支付API错误 -->
|
||||
<error>
|
||||
<code>SYSTEMERROR</code>
|
||||
|
||||
@ -0,0 +1,11 @@
|
||||
package com.foxinmy.weixin4j.model;
|
||||
|
||||
public final class Consts {
|
||||
public static final String SUCCESS = "SUCCESS";
|
||||
public static final String FAIL = "FAIL";
|
||||
public static final String SunX509 = "SunX509";
|
||||
public static final String JKS = "JKS";
|
||||
public static final String PKCS12 = "PKCS12";
|
||||
public static final String TLS = "TLS";
|
||||
public static final String X509 = "X.509";
|
||||
}
|
||||
@ -2,6 +2,8 @@ package com.foxinmy.weixin4j.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
/**
|
||||
* 微信账户信息
|
||||
*
|
||||
@ -31,6 +33,8 @@ public class WeixinAccount implements Serializable {
|
||||
private String mchId;
|
||||
// 微信支付分配的设备号
|
||||
private String deviceInfo;
|
||||
// 微信支付版本号(如果无则按照mchId来做判断)
|
||||
private int version;
|
||||
|
||||
// 是否已经认证
|
||||
private boolean isAlive;
|
||||
@ -135,6 +139,17 @@ public class WeixinAccount implements Serializable {
|
||||
this.isSubscribe = isSubscribe;
|
||||
}
|
||||
|
||||
public int getVersion() {
|
||||
if (version == 0) {
|
||||
return StringUtils.isNotBlank(mchId) ? 3 : 2;
|
||||
}
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(int version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public WeixinAccount() {
|
||||
|
||||
}
|
||||
|
||||
@ -19,7 +19,6 @@ public class ScanEventMessage extends EventMessage {
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = 8078674062833071562L;
|
||||
private static final String PARA_PREFIX = "qrscene_";
|
||||
|
||||
@XStreamAlias("EventKey")
|
||||
private String eventKey; // 事件KEY值,是一个32位无符号整数,即创建二维码时的二维码scene_id
|
||||
@ -35,7 +34,7 @@ public class ScanEventMessage extends EventMessage {
|
||||
}
|
||||
|
||||
public String getParameter() {
|
||||
return eventKey.replace(PARA_PREFIX, "");
|
||||
return eventKey.replace("qrscene_", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -16,12 +16,15 @@ import java.util.Date;
|
||||
*/
|
||||
public class DateUtil {
|
||||
private static final String yyyyMMdd = "yyyyMMdd";
|
||||
private static final String yyyy_MM_dd = "yyyy-MM-dd";
|
||||
private static final String yyyyMMddHHmmss = "yyyyMMddHHmmss";
|
||||
|
||||
public static String fortmat2yyyyMMdd(Date date) {
|
||||
return new SimpleDateFormat(yyyyMMdd).format(date);
|
||||
}
|
||||
|
||||
public static String fortmat2yyyy_MM_dd(Date date) {
|
||||
return new SimpleDateFormat(yyyy_MM_dd).format(date);
|
||||
}
|
||||
public static String fortmat2yyyyMMddHHmmss(Date date) {
|
||||
return new SimpleDateFormat(yyyyMMddHHmmss).format(date);
|
||||
}
|
||||
|
||||
@ -2,19 +2,19 @@ package com.foxinmy.weixin4j.util;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Comparator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import org.apache.http.Consts;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.fastjson.TypeReference;
|
||||
|
||||
/**
|
||||
* 签名工具类
|
||||
*
|
||||
* @className MapUtil
|
||||
* @author jy
|
||||
* @date 2014年10月31日
|
||||
@ -22,10 +22,8 @@ import com.alibaba.fastjson.TypeReference;
|
||||
* @see
|
||||
*/
|
||||
public class MapUtil {
|
||||
private final static Charset charset = StandardCharsets.UTF_8;
|
||||
|
||||
public static String toJoinString(Object object, boolean encoder,
|
||||
boolean lowerCase, JSONObject extra) {
|
||||
boolean lowerCase, Map<String, String> extra) {
|
||||
String text = JSON.toJSONString(object);
|
||||
Map<String, String> map = new TreeMap<String, String>(
|
||||
new Comparator<String>() {
|
||||
@ -34,14 +32,18 @@ public class MapUtil {
|
||||
return o1.compareTo(o2);
|
||||
}
|
||||
});
|
||||
|
||||
map.putAll(JSON.parseObject(text,
|
||||
new TypeReference<Map<String, String>>() {
|
||||
}));
|
||||
if (extra != null && !extra.isEmpty()) {
|
||||
for (String key : extra.keySet()) {
|
||||
map.put(key, extra.getString(key));
|
||||
map.putAll(extra);
|
||||
}
|
||||
return toJoinString(map, encoder, lowerCase);
|
||||
}
|
||||
|
||||
public static String toJoinString(Map<String, String> map, boolean encoder,
|
||||
boolean lowerCase) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
Set<Map.Entry<String, String>> set = map.entrySet();
|
||||
try {
|
||||
@ -50,14 +52,14 @@ public class MapUtil {
|
||||
sb.append(entry.getKey().toLowerCase())
|
||||
.append("=")
|
||||
.append(URLEncoder.encode(entry.getValue(),
|
||||
charset.name())).append("&");
|
||||
Consts.UTF_8.name())).append("&");
|
||||
}
|
||||
} else if (encoder) {
|
||||
for (Map.Entry<String, String> entry : set) {
|
||||
sb.append(entry.getKey())
|
||||
.append("=")
|
||||
.append(URLEncoder.encode(entry.getValue(),
|
||||
charset.name())).append("&");
|
||||
Consts.UTF_8.name())).append("&");
|
||||
}
|
||||
} else if (lowerCase) {
|
||||
for (Map.Entry<String, String> entry : set) {
|
||||
|
||||
@ -52,4 +52,10 @@ weixin4j-mp
|
||||
|
||||
* 2014-11-06
|
||||
|
||||
+ **weixin-mp**: 新增`退款接口`
|
||||
+ **weixin-mp-api**: 新增`退款接口`
|
||||
|
||||
* 2014-11-08
|
||||
|
||||
+ **weixin-mp-api**: 新增V2版本`退款申请`、`退款查询`、`对账单下载`三个接口
|
||||
|
||||
+ **weixin-mp-api**: 新增一个简单的`语义理解`接口
|
||||
@ -93,3 +93,9 @@ weixin.properties说明
|
||||
* 2014-11-06
|
||||
|
||||
+ 新增`退款申请`接口
|
||||
|
||||
* 2014-11-08
|
||||
|
||||
+ 新增V2版本`退款申请`、`退款查询`、`对账单下载`三个接口
|
||||
|
||||
+ 新增一个简单的`语义理解`接口
|
||||
@ -14,21 +14,8 @@
|
||||
<description>微信公众号API</description>
|
||||
<build>
|
||||
<finalName>weixin4j-mp-api</finalName>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<excludes>
|
||||
<exclude>*.*</exclude>
|
||||
</excludes>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jsoup</groupId>
|
||||
<artifactId>jsoup</artifactId>
|
||||
<version>${jsoup.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>jaxen</groupId>
|
||||
<artifactId>jaxen</artifactId>
|
||||
|
||||
@ -32,9 +32,9 @@ import com.foxinmy.weixin4j.mp.model.User;
|
||||
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.Refund;
|
||||
import com.foxinmy.weixin4j.mp.payment.RefundResult;
|
||||
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;
|
||||
@ -740,15 +740,16 @@ public class WeixinProxy {
|
||||
* 用户ID
|
||||
* @param transid
|
||||
* 交易单号
|
||||
* @param orderNo
|
||||
* @param outTradeNo
|
||||
* 订单号
|
||||
* @param status
|
||||
* 成功|失败
|
||||
* @param statusMsg
|
||||
* status为失败时携带的信息
|
||||
* @return 调用结果
|
||||
* @throws WeixinException
|
||||
* @return 发货处理结果
|
||||
* @since V2 & V3
|
||||
* @see com.foxinmy.weixin4j.mp.api.PayApi
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public JsonResult deliverNotify(String openId, String transid,
|
||||
String outTradeNo, boolean status, String statusMsg)
|
||||
@ -780,6 +781,7 @@ public class WeixinProxy {
|
||||
* 维权单号
|
||||
* @return 调用结果
|
||||
* @see com.foxinmy.weixin4j.mp.api.PayApi
|
||||
* @since V2 & V3
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public JsonResult updateFeedback(String openId, String feedbackId)
|
||||
@ -814,6 +816,7 @@ public class WeixinProxy {
|
||||
* 下载对账单的类型 ALL,返回当日所有订单信息, 默认值 SUCCESS,返回当日成功支付的订单
|
||||
* REFUND,返回当日退款订单
|
||||
* @return excel表格
|
||||
* @since V2 & V3
|
||||
* @see com.foxinmy.weixin4j.mp.api.PayApi
|
||||
* @throws WeixinException
|
||||
* @throws IOException
|
||||
@ -824,7 +827,7 @@ public class WeixinProxy {
|
||||
}
|
||||
|
||||
/**
|
||||
* 申请退款(请求需要双向证书)<br/>
|
||||
* 申请退款(V3请求需要双向证书)<br/>
|
||||
* <p style="color:red">
|
||||
* 交易时间超过 1 年的订单无法提交退款; <br/>
|
||||
* 支持部分退款,部分退需要设置相同的订单号和不同的 out_refund_no。一笔退款失 败后重新提交,要采用原来的
|
||||
@ -832,7 +835,7 @@ public class WeixinProxy {
|
||||
* </p>
|
||||
*
|
||||
* @param ca
|
||||
* 证书文件
|
||||
* 证书文件<font color="red">V2版本时无需传入</font>
|
||||
* @param idQuery
|
||||
* ) 商户系统内部的订单号, transaction_id 、 out_trade_no 二选一,如果同时存在优先级:
|
||||
* transaction_id> out_trade_no
|
||||
@ -844,28 +847,36 @@ public class WeixinProxy {
|
||||
* 退款总金额,单位为元,可以做部分退款
|
||||
* @param opUserId
|
||||
* 操作员帐号, 默认为商户号
|
||||
* @param opUserPasswd
|
||||
* <font color="red">V3版本留空,V2版本需传入值</font>
|
||||
*
|
||||
* @return 退款申请结果
|
||||
* @see com.foxinmy.weixin4j.mp.api.PayApi
|
||||
* @see com.foxinmy.weixin4j.mp.payment.RefundResult
|
||||
* @since V2 & V3
|
||||
* @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);
|
||||
String opUserId, String opUserPasswd) throws WeixinException,
|
||||
IOException {
|
||||
return payApi.refund(ca, idQuery, outRefundNo, totalFee, refundFee,
|
||||
opUserId, opUserPasswd);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用properties中配置的ca文件
|
||||
* 不同的退款接口选择<br/>
|
||||
* V3支付则采用properties中配置的ca文件<br/>
|
||||
* V2支付则需要传入opUserPasswd参数<br/>
|
||||
*
|
||||
* @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#refund(InputStream, IdQuery, String, double, double, String)}
|
||||
* @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#refund(InputStream, IdQuery, String, double, double, String,String)}
|
||||
*/
|
||||
public RefundResult refund(IdQuery idQuery, String outRefundNo,
|
||||
double totalFee, double refundFee, String opUserId)
|
||||
throws WeixinException, IOException {
|
||||
double totalFee, double refundFee, String opUserId,
|
||||
String opUserPasswd) throws WeixinException, IOException {
|
||||
return payApi.refund(idQuery, outRefundNo, totalFee, refundFee,
|
||||
opUserId);
|
||||
opUserId, opUserPasswd);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -876,8 +887,10 @@ public class WeixinProxy {
|
||||
* 单号 refund_id、out_refund_no、 out_trade_no 、 transaction_id
|
||||
* 四个参数必填一个,优先级为:
|
||||
* refund_id>out_refund_no>transaction_id>out_trade_no
|
||||
* @see com.foxinmy.weixin4j.mp.api.PayApi
|
||||
* @return 退款记录
|
||||
* @see com.foxinmy.weixin4j.mp.api.PayApi
|
||||
* @see com.foxinmy.weixin4j.mp.payment.Refund
|
||||
* @since V2 & V3
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public Refund refundQuery(IdQuery idQuery) throws WeixinException {
|
||||
@ -893,6 +906,7 @@ public class WeixinProxy {
|
||||
* 商户系统内部的订单号
|
||||
* @return 执行结果
|
||||
* @see com.foxinmy.weixin4j.mp.api.PayApi
|
||||
* @since V3
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public XmlResult closeOrder(String outTradeNo) throws WeixinException {
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
package com.foxinmy.weixin4j.mp.api;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.regex.Matcher;
|
||||
@ -24,7 +22,6 @@ import com.thoughtworks.xstream.mapper.DefaultMapper;
|
||||
public class BaseApi {
|
||||
protected final HttpRequest request = new HttpRequest();
|
||||
protected final static XStream mapXstream = XStream.get();
|
||||
protected final Charset utf8 = StandardCharsets.UTF_8;
|
||||
private final static ResourceBundle weixinBundle;
|
||||
static {
|
||||
weixinBundle = ResourceBundle
|
||||
|
||||
@ -1,9 +1,13 @@
|
||||
package com.foxinmy.weixin4j.mp.api;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
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.mp.model.SemQuery;
|
||||
import com.foxinmy.weixin4j.mp.model.SemResult;
|
||||
import com.foxinmy.weixin4j.token.TokenHolder;
|
||||
|
||||
/**
|
||||
@ -44,4 +48,28 @@ public class HelperApi extends BaseApi {
|
||||
|
||||
return response.getAsJson().getString("short_url");
|
||||
}
|
||||
|
||||
/**
|
||||
* 语义理解
|
||||
*
|
||||
* @param semQuery
|
||||
* 语义理解协议
|
||||
* @return 语义理解结果
|
||||
* @see com.foxinmy.weixin4j.mp.model.SemQuery
|
||||
* @see com.foxinmy.weixin4j.mp.model.SemResult
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E8%AF%AD%E4%B9%89%E7%90%86%E8%A7%A3">语义理解</a>
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public SemResult semantic(SemQuery semQuery) throws WeixinException {
|
||||
WeixinAccount weixinAccount = tokenHolder.getAccount();
|
||||
String semantic_uri = getRequestUri("semantic_uri");
|
||||
Token token = tokenHolder.getToken();
|
||||
semQuery.appid(weixinAccount.getAppId());
|
||||
Response response = request.post(
|
||||
String.format(semantic_uri, token.getAccessToken()),
|
||||
semQuery.toJson());
|
||||
return response.getAsObject(new TypeReference<SemResult>() {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,19 +6,29 @@ import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.StringReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.Charset;
|
||||
import java.security.KeyStore;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.net.ssl.KeyManagerFactory;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.http.Consts;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
@ -33,10 +43,10 @@ import com.foxinmy.weixin4j.http.XmlResult;
|
||||
import com.foxinmy.weixin4j.model.Token;
|
||||
import com.foxinmy.weixin4j.model.WeixinAccount;
|
||||
import com.foxinmy.weixin4j.mp.payment.PayUtil;
|
||||
import com.foxinmy.weixin4j.mp.payment.Refund;
|
||||
import com.foxinmy.weixin4j.mp.payment.RefundConverter;
|
||||
import com.foxinmy.weixin4j.mp.payment.RefundResult;
|
||||
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;
|
||||
@ -77,6 +87,7 @@ public class PayApi extends BaseApi {
|
||||
* @param statusMsg
|
||||
* status为失败时携带的信息
|
||||
* @return 发货处理结果
|
||||
* @since V2 & V3
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public JsonResult deliverNotify(String openId, String transid,
|
||||
@ -96,8 +107,7 @@ public class PayApi extends BaseApi {
|
||||
param.put("deliver_timestamp", System.currentTimeMillis() / 1000 + "");
|
||||
param.put("deliver_status", status ? "1" : "0");
|
||||
param.put("deliver_msg", statusMsg);
|
||||
param.put("app_signature", DigestUtils.sha1Hex(MapUtil.toJoinString(
|
||||
param, false, true, null)));
|
||||
param.put("app_signature", PayUtil.paysignSha(param, null));
|
||||
param.put("sign_method", "sha1");
|
||||
|
||||
Response response = request.post(
|
||||
@ -135,10 +145,9 @@ public class PayApi extends BaseApi {
|
||||
obj.put("appkey", weixinAccount.getPaySignKey());
|
||||
obj.put("package", sb.toString());
|
||||
obj.put("timestamp", timestamp);
|
||||
String signature = DigestUtils.sha1Hex(MapUtil.toJoinString(obj, false,
|
||||
true, null));
|
||||
String signature = PayUtil.paysignSha(obj, null);
|
||||
|
||||
obj = new JSONObject();
|
||||
obj.clear();
|
||||
obj.put("appid", weixinAccount.getAppId());
|
||||
obj.put("package", sb.toString());
|
||||
obj.put("timestamp", timestamp);
|
||||
@ -170,6 +179,7 @@ public class PayApi extends BaseApi {
|
||||
* @param feedbackId
|
||||
* 维权单号
|
||||
* @return 维权处理结果
|
||||
* @since V2 & V3
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public JsonResult updateFeedback(String openId, String feedbackId)
|
||||
@ -226,16 +236,113 @@ public class PayApi extends BaseApi {
|
||||
* 退款总金额,单位为元,可以做部分退款
|
||||
* @param opUserId
|
||||
* 操作员帐号, 默认为商户号
|
||||
* @param opUserPasswd
|
||||
* <font color="red">V3版本留空,V2版本需传入值</font>
|
||||
*
|
||||
* @return 退款申请结果
|
||||
* @see com.foxinmy.weixin4j.mp.payment.v3.RefundResult
|
||||
* @see com.foxinmy.weixin4j.mp.payment.RefundResult
|
||||
* @since V2 & V3
|
||||
* @throws WeixinException
|
||||
* @throws IOException
|
||||
*/
|
||||
public RefundResult refund(InputStream ca, IdQuery idQuery,
|
||||
String outRefundNo, double totalFee, double refundFee,
|
||||
String opUserId) throws WeixinException, IOException {
|
||||
String opUserId, String opUserPasswd) throws WeixinException,
|
||||
IOException {
|
||||
WeixinAccount weixinAccount = tokenHolder.getAccount();
|
||||
|
||||
int version = weixinAccount.getVersion();
|
||||
String refund_uri = getRequestUri(String.format("refund_v%d_uri",
|
||||
version));
|
||||
Response response = null;
|
||||
if (version == 2) {
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
map.put("input_charset", Consts.UTF_8.name());
|
||||
// 版本号
|
||||
// 填写为 1.0 时,操作员密码为明文
|
||||
// 填写为 1.1 时,操作员密码为 MD5(密码)值
|
||||
map.put("service_version", "1.1");
|
||||
map.put("partner", weixinAccount.getPartnerId());
|
||||
map.put("out_refund_no", outRefundNo);
|
||||
map.put("total_fee", DateUtil.formaFee2Fen(totalFee));
|
||||
map.put("refund_fee", DateUtil.formaFee2Fen(refundFee));
|
||||
map.put(idQuery.getType().getName(), idQuery.getId());
|
||||
if (StringUtils.isBlank(opUserId)) {
|
||||
opUserId = weixinAccount.getPartnerId();
|
||||
}
|
||||
map.put("op_user_id", opUserId);
|
||||
map.put("op_user_passwd", DigestUtils.md5Hex(opUserPasswd));
|
||||
// 以下几个字段可能用不到 记录下来
|
||||
// [接收人帐号]
|
||||
// recv_user_id
|
||||
// 转账退款接收退款的财付通帐号。
|
||||
// 一般无需填写,只有退银行失败,资金转入商 户号现金账号时(即状态为转入代发,查询返 回的 refund_status 是 7 或
|
||||
// 11),填写原退款 单号并填写此字段,资金才会退到指定财付通 账号。其他情况此字段忽略
|
||||
// ---------------------------------------------------------------------------------
|
||||
// [接收人姓名]
|
||||
// reccv_user_name
|
||||
// 转账退款接收退款的姓名(需与接收退款的财 付通帐号绑定的姓名一致)
|
||||
// ---------------------------------------------------------------------------------
|
||||
// [通过商户订单号退款]
|
||||
// use_spbill_no_flag
|
||||
// 若通过接口 (https://www.tenpay.com/cgi-bin/v1.0/pay _gate.cgi)
|
||||
// 支付的商户订单号来退款,则取值 为 1;而通过本文档支付接口的,则无需传值。
|
||||
// ---------------------------------------------------------------------------------
|
||||
// [退款类型]
|
||||
// refund_type
|
||||
// 为空或者填 1:商户号余额退款;2:现金帐号 退款;3:优先商户号退款,若商户号余额不足, 再做现金帐号退款。使用 2 或 3
|
||||
// 时,需联系财 付通开通此功能。
|
||||
String sign = PayUtil
|
||||
.paysignMd5(map, weixinAccount.getPartnerKey());
|
||||
map.put("sign", sign.toLowerCase());
|
||||
|
||||
SSLContext ctx = null;
|
||||
try {
|
||||
File file = new File(ConfigUtil.getValue("ca_file"));
|
||||
|
||||
String jksPwd = "";
|
||||
File jksFile = new File(String.format("%s/tenpay_cacert.jks",
|
||||
file.getParent()));
|
||||
KeyStore ks = null;
|
||||
// create jks ca
|
||||
if (!jksFile.exists()) {
|
||||
CertificateFactory cf = CertificateFactory
|
||||
.getInstance(com.foxinmy.weixin4j.model.Consts.X509);
|
||||
java.security.cert.Certificate cert = cf
|
||||
.generateCertificate(PayUtil.class
|
||||
.getResourceAsStream("cacert.pem"));
|
||||
ks = KeyStore
|
||||
.getInstance(com.foxinmy.weixin4j.model.Consts.JKS);
|
||||
ks.load(null, null);
|
||||
ks.setCertificateEntry("tenpay", cert);
|
||||
ks.store(new FileOutputStream(jksFile),
|
||||
jksPwd.toCharArray());
|
||||
}
|
||||
// load jks ca
|
||||
TrustManagerFactory tmf = TrustManagerFactory
|
||||
.getInstance(com.foxinmy.weixin4j.model.Consts.SunX509);
|
||||
ks = KeyStore
|
||||
.getInstance(com.foxinmy.weixin4j.model.Consts.JKS);
|
||||
ks.load(new FileInputStream(jksFile), jksPwd.toCharArray());
|
||||
tmf.init(ks);
|
||||
// load pfx ca
|
||||
KeyManagerFactory kmf = KeyManagerFactory
|
||||
.getInstance(com.foxinmy.weixin4j.model.Consts.SunX509);
|
||||
ks = KeyStore
|
||||
.getInstance(com.foxinmy.weixin4j.model.Consts.PKCS12);
|
||||
ks.load(ca, weixinAccount.getPartnerId().toCharArray());
|
||||
kmf.init(ks, weixinAccount.getPartnerId().toCharArray());
|
||||
|
||||
ctx = SSLContext
|
||||
.getInstance(com.foxinmy.weixin4j.model.Consts.TLS);
|
||||
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(),
|
||||
new SecureRandom());
|
||||
} catch (Exception e) {
|
||||
throw new WeixinException(e.getMessage());
|
||||
}
|
||||
SSLHttpRequest request = new SSLHttpRequest(ctx);
|
||||
response = request.get(refund_uri, map);
|
||||
} else if (version == 3) {
|
||||
Map<String, String> map = baseMap2V3(idQuery);
|
||||
map.put("out_refund_no", outRefundNo);
|
||||
map.put("total_fee", DateUtil.formaFee2Fen(totalFee));
|
||||
@ -244,28 +351,31 @@ public class PayApi extends BaseApi {
|
||||
opUserId = weixinAccount.getMchId();
|
||||
}
|
||||
map.put("op_user_id", opUserId);
|
||||
String sign = PayUtil.paysignMd5(map, weixinAccount.getPaySignKey());
|
||||
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);
|
||||
SSLHttpRequest request = new SSLHttpRequest(
|
||||
weixinAccount.getMchId(), ca);
|
||||
response = request.post(refund_uri, param);
|
||||
}
|
||||
return response.getAsObject(new TypeReference<RefundResult>() {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用properties中配置的ca文件
|
||||
* 不同的退款接口选择<br/>
|
||||
* 默认采用properties中配置的ca文件<br/>
|
||||
* V2支付则需要传入opUserPasswd参数<br/>
|
||||
*
|
||||
* @see {@link com.foxinmy.weixin4j.mp.api.PayApi#refund(InputStream, IdQuery, String, double, double, String)}
|
||||
* @see {@link com.foxinmy.weixin4j.mp.api.PayApi#refund(InputStream, IdQuery, String, double, double, String, 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);
|
||||
double totalFee, double refundFee, String opUserId,
|
||||
String opUserPasswd) throws WeixinException, IOException {
|
||||
File ca = new File(ConfigUtil.getValue("ca_file"));
|
||||
return refund(new FileInputStream(ca), idQuery, outRefundNo, totalFee,
|
||||
refundFee, opUserId, opUserPasswd);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -283,8 +393,8 @@ public class PayApi extends BaseApi {
|
||||
String sign = PayUtil.paysignMd5(map, weixinAccount.getPaySignKey());
|
||||
map.put("sign", sign);
|
||||
try {
|
||||
map.put("long_url", URLEncoder.encode(url, utf8.name()));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
map.put("long_url", URLEncoder.encode(url, Consts.UTF_8.name()));
|
||||
} catch (UnsupportedEncodingException ignore) {
|
||||
;
|
||||
}
|
||||
String param = map2xml(map);
|
||||
@ -302,6 +412,7 @@ public class PayApi extends BaseApi {
|
||||
* @param outTradeNo
|
||||
* 商户系统内部的订单号
|
||||
* @return 处理结果
|
||||
* @since V3
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public XmlResult closeOrder(String outTradeNo) throws WeixinException {
|
||||
@ -329,6 +440,7 @@ public class PayApi extends BaseApi {
|
||||
* 下载对账单的类型 ALL,返回当日所有订单信息, 默认值 SUCCESS,返回当日成功支付的订单
|
||||
* REFUND,返回当日退款订单
|
||||
* @return excel表格
|
||||
* @since V2 & V3
|
||||
* @throws WeixinException
|
||||
* @throws IOException
|
||||
*/
|
||||
@ -337,7 +449,7 @@ public class PayApi extends BaseApi {
|
||||
WeixinAccount weixinAccount = tokenHolder.getAccount();
|
||||
if (billDate == null) {
|
||||
Calendar now = Calendar.getInstance();
|
||||
now.add(Calendar.DAY_OF_MONTH, -10);
|
||||
now.add(Calendar.DAY_OF_MONTH, -1);
|
||||
billDate = now.getTime();
|
||||
}
|
||||
if (billType == null) {
|
||||
@ -351,17 +463,37 @@ public class PayApi extends BaseApi {
|
||||
if (file.exists()) {
|
||||
return file;
|
||||
}
|
||||
int version = weixinAccount.getVersion();
|
||||
String downloadbill_uri = getRequestUri(String.format(
|
||||
"downloadbill_v%d_uri", version));
|
||||
Response response = null;
|
||||
Charset charset = Consts.UTF_8;
|
||||
if (version == 2) {
|
||||
Map<String, String> map = new LinkedHashMap<String, String>();
|
||||
map.put("spid", weixinAccount.getPartnerId());
|
||||
map.put("trans_time", DateUtil.fortmat2yyyy_MM_dd(billDate));
|
||||
map.put("stamp", Long.toString(System.currentTimeMillis() / 100));
|
||||
map.put("cft_signtype", "0");
|
||||
map.put("mchtype", Integer.toString(billType.getVal()));
|
||||
map.put("key", weixinAccount.getPartnerKey());
|
||||
String sign = DigestUtils.md5Hex(MapUtil.toJoinString(map, false,
|
||||
false));
|
||||
map.put("sign", sign.toLowerCase());
|
||||
response = request.get(downloadbill_uri, map);
|
||||
charset = Charset.forName("GBK");
|
||||
} else if (version == 3) {
|
||||
Map<String, String> map = baseMap2V3(null);
|
||||
map.put("bill_date", _billDate);
|
||||
map.put("bill_type", billType.name());
|
||||
String sign = PayUtil.paysignMd5(map, weixinAccount.getPaySignKey());
|
||||
String sign = PayUtil
|
||||
.paysignMd5(map, weixinAccount.getPaySignKey());
|
||||
map.put("sign", sign);
|
||||
String param = map2xml(map);
|
||||
String downloadbill_uri = getRequestUri("downloadbill_uri");
|
||||
Response response = request.post(downloadbill_uri, param);
|
||||
response = request.post(downloadbill_uri, param);
|
||||
}
|
||||
|
||||
BufferedReader reader = new BufferedReader(new StringReader(
|
||||
response.getAsString()));
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(
|
||||
response.getStream(), charset));
|
||||
String line = null;
|
||||
List<String[]> bills = new LinkedList<String[]>();
|
||||
while ((line = reader.readLine()) != null) {
|
||||
@ -389,17 +521,33 @@ public class PayApi extends BaseApi {
|
||||
* 四个参数必填一个,优先级为:
|
||||
* refund_id>out_refund_no>transaction_id>out_trade_no
|
||||
* @return 退款记录
|
||||
* @see com.foxinmy.weixin4j.mp.payment.v3.Refund
|
||||
* @see com.foxinmy.weixin4j.mp.payment.Refund
|
||||
* @since V2 & V3
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public Refund refundQuery(IdQuery idQuery) throws WeixinException {
|
||||
WeixinAccount weixinAccount = tokenHolder.getAccount();
|
||||
int version = weixinAccount.getVersion();
|
||||
String refundquery_uri = getRequestUri(String.format(
|
||||
"refundquery_v%d_uri", version));
|
||||
Response response = null;
|
||||
if (version == 2) {
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
map.put("input_charset", Consts.UTF_8.name());
|
||||
map.put("partner", weixinAccount.getPartnerId());
|
||||
map.put(idQuery.getType().getName(), idQuery.getId());
|
||||
String sign = PayUtil
|
||||
.paysignMd5(map, weixinAccount.getPartnerKey());
|
||||
map.put("sign", sign.toLowerCase());
|
||||
response = request.get(refundquery_uri, map);
|
||||
} else if (version == 3) {
|
||||
Map<String, String> map = baseMap2V3(idQuery);
|
||||
String sign = PayUtil.paysignMd5(map, weixinAccount.getPaySignKey());
|
||||
String sign = PayUtil
|
||||
.paysignMd5(map, weixinAccount.getPaySignKey());
|
||||
map.put("sign", sign);
|
||||
String param = map2xml(map);
|
||||
String refundquery_uri = getRequestUri("refundquery_uri");
|
||||
Response response = request.post(refundquery_uri, param);
|
||||
response = request.post(refundquery_uri, param);
|
||||
}
|
||||
return new RefundConverter().fromXML(response.getAsString());
|
||||
}
|
||||
|
||||
|
||||
@ -5,10 +5,15 @@
|
||||
# http://mp.weixin.qq.com/wiki/index.php?title=%E6%8E%A5%E5%8F%A3%E9%A2%91%E7%8E%87%E9%99%90%E5%88%B6%E8%AF%B4%E6%98%8E
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
api_base_url=https://api.weixin.qq.com/cgi-bin
|
||||
api_base_url=https://api.weixin.qq.com
|
||||
api_cgi_url={api_base_url}/cgi-bin
|
||||
mp_base_url=https://mp.weixin.qq.com/cgi-bin
|
||||
file_base_url=http://file.api.weixin.qq.com/cgi-bin
|
||||
mch_base_url=https://api.mch.weixin.qq.com
|
||||
tenpay_base_url=http://mch.tenpay.com
|
||||
tenpay_ssl_base_url=https://mch.tenpay.com
|
||||
tenpay_gw_base_url=https://gw.tenpay.com
|
||||
|
||||
|
||||
# \u7f51\u9875\u6388\u6743\u83b7\u53d6\u7528\u6237\u4fe1\u606f
|
||||
user_auth_uri=https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=%s#wechat_redirect
|
||||
@ -16,68 +21,78 @@ sns_user_token_uri=https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&se
|
||||
sns_user_info_uri=https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=zh_CN
|
||||
|
||||
# \u76f4\u63a5\u83b7\u53d6\u7528\u6237\u4fe1\u606f
|
||||
api_user_info_uri={api_base_url}/user/info?access_token=%s&openid=%s&lang=zh_CN
|
||||
api_user_info_uri={api_cgi_url}/user/info?access_token=%s&openid=%s&lang=zh_CN
|
||||
# \u83b7\u53d6token
|
||||
api_token_uri={api_base_url}/token?grant_type=client_credential&appid=%s&secret=%s
|
||||
api_token_uri={api_cgi_url}/token?grant_type=client_credential&appid=%s&secret=%s
|
||||
# \u83b7\u53d6\u4e8c\u7ef4\u7801
|
||||
qr_ticket_uri={api_base_url}/qrcode/create?access_token=%s
|
||||
qr_ticket_uri={api_cgi_url}/qrcode/create?access_token=%s
|
||||
qr_image_uri={mp_base_url}/showqrcode?ticket=%s
|
||||
# \u4e0a\u4f20\u5a92\u4f53\u6587\u4ef6
|
||||
file_upload_uri={file_base_url}/media/upload?access_token=%s&type=%s
|
||||
# \u4e0b\u8f7d\u5a92\u4f53\u6587\u4ef6
|
||||
file_download_uri={file_base_url}/media/get?access_token=%s&media_id=%s
|
||||
# \u53d1\u9001\u5ba2\u670d\u6d88\u606f
|
||||
custom_notify_uri={api_base_url}/message/custom/send?access_token=%s
|
||||
custom_notify_uri={api_cgi_url}/message/custom/send?access_token=%s
|
||||
# \u521b\u5efa\u5206\u7ec4
|
||||
group_create_uri={api_base_url}/groups/create?access_token=%s
|
||||
group_create_uri={api_cgi_url}/groups/create?access_token=%s
|
||||
# \u67e5\u8be2\u5206\u7ec4
|
||||
group_get_uri={api_base_url}/groups/get?access_token=%s
|
||||
group_get_uri={api_cgi_url}/groups/get?access_token=%s
|
||||
# \u67e5\u8be2\u7528\u6237\u6240\u5728\u5206\u7ec4
|
||||
group_getid_uri={api_base_url}/groups/getid?access_token=%s
|
||||
group_getid_uri={api_cgi_url}/groups/getid?access_token=%s
|
||||
# \u4fee\u6539\u5206\u7ec4\u540d
|
||||
group_modify_uri={api_base_url}/groups/update?access_token=%s
|
||||
group_modify_uri={api_cgi_url}/groups/update?access_token=%s
|
||||
# \u79fb\u52a8\u7528\u6237\u5206\u7ec4
|
||||
group_move_uri={api_base_url}/groups/members/update?access_token=%s
|
||||
group_move_uri={api_cgi_url}/groups/members/update?access_token=%s
|
||||
# \u83b7\u53d6\u5173\u6ce8\u7740
|
||||
following_uri={api_base_url}/user/get?access_token=%s&next_openid=%s
|
||||
following_uri={api_cgi_url}/user/get?access_token=%s&next_openid=%s
|
||||
# \u81ea\u5b9a\u4e49\u83dc\u5355
|
||||
menu_create_uri={api_base_url}/menu/create?access_token=%s
|
||||
menu_create_uri={api_cgi_url}/menu/create?access_token=%s
|
||||
# \u67e5\u8be2\u83dc\u5355
|
||||
menu_get_uri={api_base_url}/menu/get?access_token=%s
|
||||
menu_get_uri={api_cgi_url}/menu/get?access_token=%s
|
||||
# \u5220\u9664\u83dc\u5355
|
||||
menu_delete_uri={api_base_url}/menu/delete?access_token=%s
|
||||
menu_delete_uri={api_cgi_url}/menu/delete?access_token=%s
|
||||
# \u4e0a\u4f20\u56fe\u6587
|
||||
article_upload_uri={api_base_url}/media/uploadnews?access_token=%s
|
||||
article_upload_uri={api_cgi_url}/media/uploadnews?access_token=%s
|
||||
# \u4e0a\u4f20\u89c6\u9891
|
||||
video_upload_uri={file_base_url}/media/uploadvideo?access_token=%s
|
||||
# \u5206\u7ec4\u7fa4\u53d1
|
||||
mass_group_uri={api_base_url}/message/mass/sendall?access_token=%s
|
||||
mass_group_uri={api_cgi_url}/message/mass/sendall?access_token=%s
|
||||
# openId\u7fa4\u53d1
|
||||
mass_openid_uri={api_base_url}/message/mass/send?access_token=%s
|
||||
mass_openid_uri={api_cgi_url}/message/mass/send?access_token=%s
|
||||
# \u5220\u9664\u7fa4\u53d1
|
||||
mass_delete_uri={api_base_url}/message/mass/delete?access_token=%s
|
||||
mass_delete_uri={api_cgi_url}/message/mass/delete?access_token=%s
|
||||
# \u5ba2\u670d\u804a\u5929\u8bb0\u5f55
|
||||
custom_record_uri={api_base_url}/customservice/getrecord?access_token=%s
|
||||
custom_record_uri={api_cgi_url}/customservice/getrecord?access_token=%s
|
||||
# \u957f\u94fe\u63a5\u8f6c\u77ed\u94fe\u63a5
|
||||
shorturl_uri={api_base_url}/shorturl?access_token=%s
|
||||
shorturl_uri={api_cgi_url}/shorturl?access_token=%s
|
||||
p_shorturl_uri={mch_base_url}/tools/shorturl
|
||||
# \u8bbe\u7f6e\u5907\u6ce8\u540d
|
||||
updateremark_uri={api_base_url}/user/info/updateremark?access_token=%s
|
||||
updateremark_uri={api_cgi_url}/user/info/updateremark?access_token=%s
|
||||
# \u6a21\u677f\u6d88\u606f
|
||||
template_send_uri={api_base_url}/message/template/send?access_token=%s
|
||||
template_send_uri={api_cgi_url}/message/template/send?access_token=%s
|
||||
# \u8bed\u4e49\u7406\u89e3
|
||||
semantic_uri={api_base_url}/semantic/semproxy/search?access_token=%s
|
||||
|
||||
# \u8ba2\u5355\u67e5\u8be2
|
||||
orderquery_uri=https://api.weixin.qq.com/pay/orderquery?access_token=%s
|
||||
orderquery_uri={api_base_url}/pay/orderquery?access_token=%s
|
||||
# \u53d1\u8d27\u901a\u77e5
|
||||
delivernotify_uri=https://api.weixin.qq.com/pay/delivernotify?access_token=%s
|
||||
delivernotify_uri={api_base_url}/pay/delivernotify?access_token=%s
|
||||
# \u7ef4\u6743\u5904\u7406
|
||||
payfeedback_update_uri=https://api.weixin.qq.com/payfeedback/update?access_token=%s&openid=%s&feedbackid=%s
|
||||
payfeedback_update_uri={api_base_url}/payfeedback/update?access_token=%s&openid=%s&feedbackid=%s
|
||||
# \u5bf9\u8d26\u5355\u4e0b\u8f7d
|
||||
downloadbill_v2_uri={tenpay_base_url}/cgi-bin/mchdown_real_new.cgi
|
||||
# \u9000\u6b3e\u67e5\u8be2
|
||||
refundquery_v2_uri={tenpay_gw_base_url}/gateway/normalrefundquery.xml
|
||||
# \u9000\u6b3e\u7533\u8bf7
|
||||
refund_v2_uri={tenpay_ssl_base_url}/refundapi/gateway/refund.xml
|
||||
|
||||
# \u8ba2\u5355\u67e5\u8be2
|
||||
orderquery_v3_uri={mch_base_url}/pay/orderquery
|
||||
# \u5173\u95ed\u8ba2\u5355
|
||||
closeorder_uri={mch_base_url}/pay/closeorder
|
||||
# \u5bf9\u8d26\u5355\u4e0b\u8f7d
|
||||
downloadbill_uri={mch_base_url}/pay/downloadbill
|
||||
downloadbill_v3_uri={mch_base_url}/pay/downloadbill
|
||||
# \u9000\u6b3e\u67e5\u8be2
|
||||
refundquery_uri={mch_base_url}/pay/refundquery
|
||||
refundquery_v3_uri={mch_base_url}/pay/refundquery
|
||||
# \u9000\u6b3e\u7533\u8bf7
|
||||
refund_uri={mch_base_url}/secapi/pay/refund
|
||||
refund_v3_uri={mch_base_url}/secapi/pay/refund
|
||||
|
||||
@ -38,10 +38,10 @@ public class Button implements Serializable {
|
||||
public Button(String name, String value, ButtonType buttonType) {
|
||||
this.name = name;
|
||||
this.type = buttonType;
|
||||
if (buttonType == ButtonType.click) {
|
||||
this.key = value;
|
||||
} else if (buttonType == ButtonType.view) {
|
||||
if (buttonType == ButtonType.view) {
|
||||
this.url = value;
|
||||
} else {
|
||||
this.key = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,88 @@
|
||||
package com.foxinmy.weixin4j.mp.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.foxinmy.weixin4j.mp.type.SemCategory;
|
||||
|
||||
/**
|
||||
* 语义理解参数
|
||||
*
|
||||
* @className SemQuery
|
||||
* @author jy
|
||||
* @date 2014年11月7日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public class SemQuery implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 679548284525912436L;
|
||||
private JSONObject jsonObj;
|
||||
|
||||
// 输入文本串
|
||||
public SemQuery(String query) {
|
||||
jsonObj = new JSONObject();
|
||||
jsonObj.put("query", query);
|
||||
}
|
||||
|
||||
// 城市名称,与经纬度二选一传入
|
||||
public SemQuery city(String city) {
|
||||
jsonObj.put("city", city);
|
||||
return this;
|
||||
}
|
||||
|
||||
// 需要使用的服务类别,多个用,隔开,不能为空
|
||||
public SemQuery category(SemCategory... categorys) {
|
||||
String category = "";
|
||||
if (categorys.length == 1) {
|
||||
category = categorys[0].name();
|
||||
} else {
|
||||
for (int i = 0; i < categorys.length - 1; i++) {
|
||||
category += categorys[i].name() + ",";
|
||||
}
|
||||
category += categorys[categorys.length - 1].name();
|
||||
}
|
||||
jsonObj.put("category", category);
|
||||
return this;
|
||||
}
|
||||
|
||||
// App id,开发者的唯一标识,用于区分开放者, 如果为空,则没法使用上下文理解功能。
|
||||
public SemQuery appid(String appid) {
|
||||
jsonObj.put("appid", appid);
|
||||
return this;
|
||||
}
|
||||
|
||||
// 用户唯一 id(并非开发者 id),用于区分该开发者下不同用户,如果为空,则没法使用上下文理解功能。appid 和 uid
|
||||
// 同时存在的情况下,才可以使用上下文理解功能。
|
||||
public SemQuery uid(String uid) {
|
||||
jsonObj.put("uid", uid);
|
||||
return this;
|
||||
}
|
||||
|
||||
// 区域名称,在城市存在的情况下可省;与经纬度 二选一传入
|
||||
public SemQuery region(String region) {
|
||||
jsonObj.put("region", region);
|
||||
return this;
|
||||
}
|
||||
|
||||
// 纬度经度;与城市二选一传入
|
||||
public SemQuery location(float latitude, float longitude) {
|
||||
jsonObj.put("latitude", latitude);
|
||||
jsonObj.put("longitude", longitude);
|
||||
return this;
|
||||
}
|
||||
|
||||
// 输入文本串
|
||||
public static SemQuery build(String query) {
|
||||
return new SemQuery(query);
|
||||
}
|
||||
|
||||
public String toJson() {
|
||||
return jsonObj.toJSONString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SemQuery " + jsonObj;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,88 @@
|
||||
package com.foxinmy.weixin4j.mp.model;
|
||||
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.foxinmy.weixin4j.http.JsonResult;
|
||||
|
||||
/**
|
||||
* 语义理解结果
|
||||
*
|
||||
* @className SemResult
|
||||
* @author jy
|
||||
* @date 2014年11月7日
|
||||
* @since JDK 1.7
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E8%AF%AD%E4%B9%89%E7%90%86%E8%A7%A3">语义理解</a>
|
||||
*/
|
||||
public class SemResult extends JsonResult {
|
||||
|
||||
private static final long serialVersionUID = 9051214458161068387L;
|
||||
// 用户的输入字符串
|
||||
private String query;
|
||||
// 服务的全局类型id,详见协议文档中垂直服务协议定义
|
||||
private String type;
|
||||
// 语义理解后的结构化标识,各服务不同
|
||||
private JSONObject semantic;
|
||||
// 部分类别的结果
|
||||
private JSONArray result;
|
||||
// 部分类别的结果html5展示,目前不支持
|
||||
private String answer;
|
||||
// 特殊回复说明
|
||||
private String text;
|
||||
|
||||
public String getQuery() {
|
||||
return query;
|
||||
}
|
||||
|
||||
public void setQuery(String query) {
|
||||
this.query = query;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public JSONObject getSemantic() {
|
||||
return semantic;
|
||||
}
|
||||
|
||||
public void setSemantic(JSONObject semantic) {
|
||||
this.semantic = semantic;
|
||||
}
|
||||
|
||||
public JSONArray getResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
public void setResult(JSONArray result) {
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
public String getAnswer() {
|
||||
return answer;
|
||||
}
|
||||
|
||||
public void setAnswer(String answer) {
|
||||
this.answer = answer;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SemResult [query=" + query + ", type=" + type + ", semantic="
|
||||
+ semantic + ", result=" + result + ", answer=" + answer
|
||||
+ ", text=" + text + ", getCode()=" + getCode()
|
||||
+ ", getDesc()=" + getDesc() + "]";
|
||||
}
|
||||
}
|
||||
@ -11,6 +11,7 @@ import org.slf4j.LoggerFactory;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.foxinmy.weixin4j.exception.PayException;
|
||||
import com.foxinmy.weixin4j.http.XmlResult;
|
||||
import com.foxinmy.weixin4j.model.Consts;
|
||||
import com.foxinmy.weixin4j.model.WeixinAccount;
|
||||
import com.foxinmy.weixin4j.mp.payment.v2.NativePayNotifyV2;
|
||||
import com.foxinmy.weixin4j.mp.payment.v2.NativePayResponseV2;
|
||||
@ -163,7 +164,7 @@ public class PayAction {
|
||||
weixinAccount.getPaySignKey());
|
||||
log.info("微信签名----->sign={},vaild_sign={}", sign, valid_sign);
|
||||
if (!sign.equals(valid_sign)) {
|
||||
return XStream.to(new XmlResult(XmlResult.FAIL, "签名错误"));
|
||||
return XStream.to(new XmlResult(Consts.FAIL, "签名错误"));
|
||||
}
|
||||
return XStream.to(new XmlResult());
|
||||
}
|
||||
|
||||
@ -122,9 +122,9 @@ public class PayUtil {
|
||||
* @return
|
||||
*/
|
||||
public static String paysignSha(Object obj, String paySignKey) {
|
||||
JSONObject extra = null;
|
||||
Map<String, String> extra = null;
|
||||
if (StringUtils.isNotBlank(paySignKey)) {
|
||||
extra = new JSONObject();
|
||||
extra = new HashMap<String, String>();
|
||||
extra.put("appKey", paySignKey);
|
||||
}
|
||||
return DigestUtils.sha1Hex(MapUtil
|
||||
@ -255,7 +255,7 @@ public class PayUtil {
|
||||
Map<String, String> param = new HashMap<String, String>();
|
||||
param.put("appId", appId);
|
||||
param.put("url", url);
|
||||
param.put("timeStamp", System.currentTimeMillis() / 1000 + "");
|
||||
param.put("timeStamp", Long.toString(System.currentTimeMillis() / 1000));
|
||||
param.put("nonceStr", RandomUtil.generateString(16));
|
||||
param.put("accessToken", accessToken);
|
||||
String sign = paysignSha(param, null);
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
package com.foxinmy.weixin4j.mp.payment.v3;
|
||||
package com.foxinmy.weixin4j.mp.payment;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.foxinmy.weixin4j.mp.payment.ApiResult;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
@ -12,7 +11,7 @@ import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
* @author jy
|
||||
* @date 2014年11月1日
|
||||
* @since JDK 1.7
|
||||
* @see com.foxinmy.weixin4j.mp.payment.v3.RefundDetail
|
||||
* @see com.foxinmy.weixin4j.mp.payment.RefundDetail
|
||||
*/
|
||||
@XStreamAlias("xml")
|
||||
public class Refund extends ApiResult {
|
||||
@ -27,6 +26,7 @@ public class Refund extends ApiResult {
|
||||
private String subMchId; //
|
||||
@XStreamAlias("refund_count")
|
||||
private int count;// 退款笔数
|
||||
private String partner; // 商户号V2
|
||||
private List<RefundDetail> details;
|
||||
|
||||
public String getTransactionId() {
|
||||
@ -45,6 +45,10 @@ public class Refund extends ApiResult {
|
||||
return count;
|
||||
}
|
||||
|
||||
public String getPartner() {
|
||||
return partner;
|
||||
}
|
||||
|
||||
public List<RefundDetail> getDetails() {
|
||||
return details;
|
||||
}
|
||||
@ -57,12 +61,13 @@ public class Refund extends ApiResult {
|
||||
public String toString() {
|
||||
return "Refund [transactionId=" + transactionId + ", orderNo="
|
||||
+ orderNo + ", subMchId=" + subMchId + ", count=" + count
|
||||
+ ", details=" + details + ", getAppId()=" + getAppId()
|
||||
+ ", getMchId()=" + getMchId() + ", getNonceStr()="
|
||||
+ getNonceStr() + ", getSign()=" + getSign()
|
||||
+ ", getDeviceInfo()=" + getDeviceInfo() + ", getReturnCode()="
|
||||
+ getReturnCode() + ", getReturnMsg()=" + getReturnMsg()
|
||||
+ ", getResultCode()=" + getResultCode() + ", getErrCode()="
|
||||
+ getErrCode() + ", getErrCodeDes()=" + getErrCodeDes() + "]";
|
||||
+ ", partner=" + partner + ", details=" + details
|
||||
+ ", getAppId()=" + getAppId() + ", getMchId()=" + getMchId()
|
||||
+ ", getNonceStr()=" + getNonceStr() + ", getSign()="
|
||||
+ getSign() + ", getDeviceInfo()=" + getDeviceInfo()
|
||||
+ ", getReturnCode()=" + getReturnCode() + ", getReturnMsg()="
|
||||
+ getReturnMsg() + ", getResultCode()=" + getResultCode()
|
||||
+ ", getErrCode()=" + getErrCode() + ", getErrCodeDes()="
|
||||
+ getErrCodeDes() + "]";
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
package com.foxinmy.weixin4j.mp.payment.v3;
|
||||
package com.foxinmy.weixin4j.mp.payment;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.HashMap;
|
||||
@ -26,8 +26,8 @@ import com.thoughtworks.xstream.mapper.Mapper;
|
||||
* @author jy
|
||||
* @date 2014年11月2日
|
||||
* @since JDK 1.7
|
||||
* @see com.foxinmy.weixin4j.mp.payment.v3.Refund
|
||||
* @see com.foxinmy.weixin4j.mp.payment.v3.RefundDetail
|
||||
* @see com.foxinmy.weixin4j.mp.payment.Refund
|
||||
* @see com.foxinmy.weixin4j.mp.payment.RefundDetail
|
||||
*/
|
||||
public class RefundConverter {
|
||||
private final static XStream xStream = XStream.get();
|
||||
@ -1,4 +1,4 @@
|
||||
package com.foxinmy.weixin4j.mp.payment.v3;
|
||||
package com.foxinmy.weixin4j.mp.payment;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@ -32,7 +32,15 @@ public class RefundDetail implements Serializable {
|
||||
@XStreamAlias("coupon_refund_fee")
|
||||
private int couponRefundFee; // 现金券退款金额<=退款金额,退款金额-现金券退款金额为现金
|
||||
@XStreamAlias("refund_status")
|
||||
private RefundStatus refundStatus; // 退款状态
|
||||
private String refundStatus; // 退款状态
|
||||
@XStreamAlias("recv_user_id")
|
||||
private String recvUserId;// 转账退款接收退款的财付通帐号
|
||||
@XStreamAlias("reccv_user_name")
|
||||
private String reccvUserName;// 转账退款接收退款的姓名(需与接收退款的财 付通帐号绑定的姓名一致)
|
||||
@XStreamAlias("sign_key_index")
|
||||
private String signKeyIndex;// 多密钥支持的密钥序号,默认 1
|
||||
@XStreamAlias("sign_type")
|
||||
private String signType;// 签名类型,取值:MD5、RSA,默认:MD5
|
||||
|
||||
public String getOutRefundNo() {
|
||||
return outRefundNo;
|
||||
@ -43,8 +51,16 @@ public class RefundDetail implements Serializable {
|
||||
}
|
||||
|
||||
public String getRefundChannel() {
|
||||
return StringUtils.isBlank(refundChannel) ? RefundChannel.BALANCE
|
||||
.name() : refundChannel;
|
||||
if (StringUtils.isBlank(refundChannel)) {
|
||||
return RefundChannel.BALANCE.name();
|
||||
}
|
||||
// V2
|
||||
if (refundChannel.equals("0")) {
|
||||
return RefundChannel.TENPAY.name();
|
||||
} else if (refundChannel.equals("1")) {
|
||||
return RefundChannel.BALANCE.name();
|
||||
}
|
||||
return refundChannel;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -66,7 +82,36 @@ public class RefundDetail implements Serializable {
|
||||
}
|
||||
|
||||
public RefundStatus getRefundStatus() {
|
||||
return refundStatus;
|
||||
// V2
|
||||
if ("4,10,".contains(refundStatus + ",")) {
|
||||
return RefundStatus.SUCCES;
|
||||
} else if ("3,5,6,".contains(refundStatus + ",")) {
|
||||
return RefundStatus.FAIL;
|
||||
} else if ("8,9,10,".contains(refundStatus + ",")) {
|
||||
return RefundStatus.PROCESSING;
|
||||
} else if ("1,2,".contains(refundStatus + ",")) {
|
||||
return RefundStatus.NOTSURE;
|
||||
} else if ("7,".contains(refundStatus + ",")) {
|
||||
return RefundStatus.CHANGE;
|
||||
} else {
|
||||
return RefundStatus.valueOf(refundStatus);
|
||||
}
|
||||
}
|
||||
|
||||
public String getRecvUserId() {
|
||||
return recvUserId;
|
||||
}
|
||||
|
||||
public String getReccvUserName() {
|
||||
return reccvUserName;
|
||||
}
|
||||
|
||||
public String getSignKeyIndex() {
|
||||
return signKeyIndex;
|
||||
}
|
||||
|
||||
public String getSignType() {
|
||||
return signType;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -74,6 +119,9 @@ public class RefundDetail implements Serializable {
|
||||
return "RefundDetail [outRefundNo=" + outRefundNo + ", refundId="
|
||||
+ refundId + ", refundChannel=" + refundChannel
|
||||
+ ", refundFee=" + refundFee + ", couponRefundFee="
|
||||
+ couponRefundFee + ", refundStatus=" + refundStatus + "]";
|
||||
+ couponRefundFee + ", refundStatus=" + refundStatus
|
||||
+ ", recvUserId=" + recvUserId + ", reccvUserName="
|
||||
+ reccvUserName + ", signKeyIndex=" + signKeyIndex
|
||||
+ ", signType=" + signType + "]";
|
||||
}
|
||||
}
|
||||
@ -1,8 +1,7 @@
|
||||
package com.foxinmy.weixin4j.mp.payment.v3;
|
||||
package com.foxinmy.weixin4j.mp.payment;
|
||||
|
||||
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;
|
||||
|
||||
@ -41,6 +40,14 @@ public class RefundResult extends ApiResult {
|
||||
// 现金券退款金额<=退款金 额,退款金额-现金券退款金 额为现金
|
||||
@XStreamAlias("coupon_refund_fee")
|
||||
private int couponRefundFee;
|
||||
@XStreamAlias("recv_user_id")
|
||||
private String recvUserId;// 转账退款接收退款的财付通帐号
|
||||
@XStreamAlias("reccv_user_name")
|
||||
private String reccvUserName;// 转账退款接收退款的姓名(需与接收退款的财 付通帐号绑定的姓名一致)
|
||||
@XStreamAlias("sign_key_index")
|
||||
private String signKeyIndex;// 多密钥支持的密钥序号,默认 1
|
||||
@XStreamAlias("sign_type")
|
||||
private String signType;// 签名类型,取值:MD5、RSA,默认:MD5
|
||||
|
||||
public String getTransactionId() {
|
||||
return transactionId;
|
||||
@ -59,8 +66,16 @@ public class RefundResult extends ApiResult {
|
||||
}
|
||||
|
||||
public String getRefundChannel() {
|
||||
return StringUtils.isBlank(refundChannel) ? RefundChannel.BALANCE
|
||||
.name() : refundChannel;
|
||||
if (StringUtils.isBlank(refundChannel)) {
|
||||
return RefundChannel.BALANCE.name();
|
||||
}
|
||||
// V2
|
||||
if (refundChannel.equals("0")) {
|
||||
return RefundChannel.TENPAY.name();
|
||||
} else if (refundChannel.equals("1")) {
|
||||
return RefundChannel.BALANCE.name();
|
||||
}
|
||||
return refundChannel;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -81,14 +96,25 @@ public class RefundResult extends ApiResult {
|
||||
return couponRefundFee / 100d;
|
||||
}
|
||||
|
||||
public String getSignKeyIndex() {
|
||||
return signKeyIndex;
|
||||
}
|
||||
|
||||
public String getSignType() {
|
||||
return signType;
|
||||
}
|
||||
|
||||
@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()="
|
||||
+ couponRefundFee + ", recvUserId=" + recvUserId
|
||||
+ ", reccvUserName=" + reccvUserName + ", signKeyIndex="
|
||||
+ signKeyIndex + ", signType=" + signType + ", getAppId()="
|
||||
+ getAppId() + ", getMchId()=" + getMchId()
|
||||
+ ", getSubMchId()=" + getSubMchId() + ", getNonceStr()="
|
||||
+ getNonceStr() + ", getSign()=" + getSign()
|
||||
+ ", getDeviceInfo()=" + getDeviceInfo() + ", getReturnCode()="
|
||||
+ getReturnCode() + ", getReturnMsg()=" + getReturnMsg()
|
||||
@ -0,0 +1,21 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDezCCAuSgAwIBAgIJAI7aVO7iYwcQMA0GCSqGSIb3DQEBBAUAMIGGMQswCQYD
|
||||
VQQGEwJDTjESMBAGA1UECBMJR1VBTkdET05HMREwDwYDVQQHEwhTSEVOWkhFTjEQ
|
||||
MA4GA1UEChMHVEVOQ0VOVDEMMAoGA1UECxMDT1NTMQwwCgYDVQQDEwNDRlQxIjAg
|
||||
BgkqhkiG9w0BCQEWE3RpcHlsdW9AdGVuY2VudC5jb20wHhcNMDYwMzE0MTQyMjIz
|
||||
WhcNMTYwMzExMTQyMjIzWjCBhjELMAkGA1UEBhMCQ04xEjAQBgNVBAgTCUdVQU5H
|
||||
RE9ORzERMA8GA1UEBxMIU0hFTlpIRU4xEDAOBgNVBAoTB1RFTkNFTlQxDDAKBgNV
|
||||
BAsTA09TUzEMMAoGA1UEAxMDQ0ZUMSIwIAYJKoZIhvcNAQkBFhN0aXB5bHVvQHRl
|
||||
bmNlbnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDZF0wb1UIgAbwq
|
||||
RgnQtGRZon1LG1NLd1CiFQO41aESrJ/3hWvnzlpxepIwi9H3xUuMeoP3kOSJoT5O
|
||||
EKOVkcgkzVcPebfBgnnLToMTduuHHJ+iWWPmzFsJQB5xetJXD1lqsxlDLZk2+eiD
|
||||
FuGfPKDaW76V24YPLCQ6uzaRMiFDaQIDAQABo4HuMIHrMB0GA1UdDgQWBBTi3asX
|
||||
klhRZA2dvy0onxvowmx2YzCBuwYDVR0jBIGzMIGwgBTi3asXklhRZA2dvy0onxvo
|
||||
wmx2Y6GBjKSBiTCBhjELMAkGA1UEBhMCQ04xEjAQBgNVBAgTCUdVQU5HRE9ORzER
|
||||
MA8GA1UEBxMIU0hFTlpIRU4xEDAOBgNVBAoTB1RFTkNFTlQxDDAKBgNVBAsTA09T
|
||||
UzEMMAoGA1UEAxMDQ0ZUMSIwIAYJKoZIhvcNAQkBFhN0aXB5bHVvQHRlbmNlbnQu
|
||||
Y29tggkAjtpU7uJjBxAwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQQFAAOBgQCM
|
||||
VOZNmGO9XAtEPFuA3Q42LkfcwHK9Q0CAMbMPA4pNADxBWaQvv5okE3YG1RNGLp/y
|
||||
wyxXDs62qpEHcDPQh5porQKRP3PB54pL3AFLouEcuH4j7e8f8tqokOMmtTfeSUTJ
|
||||
wYWlbwUEu53AhNBlQl1zATkGmeURsmXg5GnuNAWafg==
|
||||
-----END CERTIFICATE-----
|
||||
@ -3,6 +3,7 @@ package com.foxinmy.weixin4j.mp.payment.v3;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.foxinmy.weixin4j.exception.PayException;
|
||||
import com.foxinmy.weixin4j.model.Consts;
|
||||
import com.foxinmy.weixin4j.mp.payment.ApiResult;
|
||||
import com.foxinmy.weixin4j.mp.payment.PayUtil;
|
||||
import com.foxinmy.weixin4j.util.RandomUtil;
|
||||
@ -27,9 +28,11 @@ public class NativePayResponseV3 extends ApiResult {
|
||||
public NativePayResponseV3(PayPackageV3 payPackage, String returnMsg,
|
||||
String resultMsg) throws PayException {
|
||||
super.setReturnMsg(returnMsg);
|
||||
super.setReturnCode(StringUtils.isNotBlank(returnMsg) ? FAIL : SUCCESS);
|
||||
super.setReturnCode(StringUtils.isNotBlank(returnMsg) ? Consts.FAIL
|
||||
: Consts.SUCCESS);
|
||||
this.setErrCodeDes(resultMsg);
|
||||
this.setResultCode(StringUtils.isNotBlank(resultMsg) ? FAIL : SUCCESS);
|
||||
this.setResultCode(StringUtils.isNotBlank(resultMsg) ? Consts.FAIL
|
||||
: Consts.SUCCESS);
|
||||
this.setMchId(payPackage.getMch_id());
|
||||
this.setAppId(payPackage.getAppid());
|
||||
this.setNonceStr(RandomUtil.generateString(16));
|
||||
|
||||
@ -2,7 +2,7 @@ package com.foxinmy.weixin4j.mp.payment.v3;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.foxinmy.weixin4j.exception.PayException;
|
||||
import com.foxinmy.weixin4j.http.XmlResult;
|
||||
import com.foxinmy.weixin4j.model.Consts;
|
||||
import com.foxinmy.weixin4j.mp.payment.PayRequest;
|
||||
import com.thoughtworks.xstream.annotations.XStreamOmitField;
|
||||
|
||||
@ -32,11 +32,11 @@ public class PayRequestV3 extends PayRequest {
|
||||
private PrePay prePay;
|
||||
|
||||
public PayRequestV3(PrePay prePay) throws PayException {
|
||||
if (!prePay.getReturnCode().equalsIgnoreCase(XmlResult.SUCCESS)) {
|
||||
if (!prePay.getReturnCode().equalsIgnoreCase(Consts.SUCCESS)) {
|
||||
throw new PayException(prePay.getReturnMsg(),
|
||||
prePay.getReturnCode());
|
||||
}
|
||||
if (!prePay.getResultCode().equalsIgnoreCase(XmlResult.SUCCESS)) {
|
||||
if (!prePay.getResultCode().equalsIgnoreCase(Consts.SUCCESS)) {
|
||||
throw new PayException(prePay.getResultCode(),
|
||||
prePay.getErrCodeDes());
|
||||
}
|
||||
|
||||
@ -2,8 +2,6 @@ package com.foxinmy.weixin4j.mp.spider;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@ -12,6 +10,7 @@ import java.util.Map;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.http.Consts;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.HttpResponse;
|
||||
@ -59,8 +58,6 @@ public class WeixinExecutor implements Serializable {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(getClass());
|
||||
|
||||
private final static Charset charset = StandardCharsets.UTF_8;
|
||||
|
||||
private final static Map<String, String> accountMap = new HashMap<String, String>() {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@ -186,13 +183,13 @@ public class WeixinExecutor implements Serializable {
|
||||
if (!StringUtils.isBlank(imgcode)) {
|
||||
method.addHeader("Cookie", "sig=" + sig);
|
||||
}
|
||||
method.setEntity(new UrlEncodedFormEntity(parameters, charset));
|
||||
method.setEntity(new UrlEncodedFormEntity(parameters, Consts.UTF_8));
|
||||
method.addHeader("Referer", weixin.getString("base"));
|
||||
|
||||
HttpResponse response = client.execute(host, method);
|
||||
HttpEntity entity = response.getEntity();
|
||||
Document root = Jsoup.parse(entity.getContent(), charset.name(),
|
||||
weixin.getString("base"));
|
||||
Document root = Jsoup.parse(entity.getContent(),
|
||||
Consts.UTF_8.name(), weixin.getString("base"));
|
||||
StatusLine line = response.getStatusLine();
|
||||
logger.info("step1_login--->status={},body=\n{}", line,
|
||||
root.toString());
|
||||
@ -270,7 +267,8 @@ public class WeixinExecutor implements Serializable {
|
||||
.getValue()).append(";base64,");
|
||||
base64.append(new String(
|
||||
Base64.encodeBase64(IOUtil.toByteArray(response
|
||||
.getEntity().getContent())), charset));
|
||||
.getEntity().getContent())),
|
||||
Consts.UTF_8));
|
||||
weixin.put("verifydata", base64.toString());
|
||||
List<Cookie> cookieList = client.getCookieStore()
|
||||
.getCookies();
|
||||
@ -311,8 +309,8 @@ public class WeixinExecutor implements Serializable {
|
||||
|
||||
HttpResponse response = client.execute(host, method);
|
||||
HttpEntity entity = response.getEntity();
|
||||
Document root = Jsoup.parse(entity.getContent(), charset.name(),
|
||||
weixin.getString("base"));
|
||||
Document root = Jsoup.parse(entity.getContent(),
|
||||
Consts.UTF_8.name(), weixin.getString("base"));
|
||||
StatusLine line = response.getStatusLine();
|
||||
logger.info("step2_setting--->status={},body=\n{}", line,
|
||||
root.toString());
|
||||
@ -331,7 +329,7 @@ public class WeixinExecutor implements Serializable {
|
||||
|
||||
response = client.execute(host, method);
|
||||
entity = response.getEntity();
|
||||
root = Jsoup.parse(entity.getContent(), charset.name(),
|
||||
root = Jsoup.parse(entity.getContent(), Consts.UTF_8.name(),
|
||||
weixin.getString("base"));
|
||||
line = response.getStatusLine();
|
||||
weixin.put("step", "2-1");
|
||||
@ -378,8 +376,8 @@ public class WeixinExecutor implements Serializable {
|
||||
|
||||
response = client.execute(host, method);
|
||||
entity = response.getEntity();
|
||||
root = Jsoup.parse(entity.getContent(), charset.name(),
|
||||
weixin.getString("base"));
|
||||
root = Jsoup.parse(entity.getContent(),
|
||||
Consts.UTF_8.name(), weixin.getString("base"));
|
||||
line = response.getStatusLine();
|
||||
|
||||
if (line.getStatusCode() == HttpStatus.SC_OK) {
|
||||
@ -402,11 +400,12 @@ public class WeixinExecutor implements Serializable {
|
||||
System.currentTimeMillis() + ""));
|
||||
|
||||
post.setEntity(new UrlEncodedFormEntity(parameters,
|
||||
charset));
|
||||
Consts.UTF_8));
|
||||
response = client.execute(host, post);
|
||||
entity = response.getEntity();
|
||||
root = Jsoup.parse(entity.getContent(),
|
||||
charset.name(), weixin.getString("base"));
|
||||
Consts.UTF_8.name(),
|
||||
weixin.getString("base"));
|
||||
line = response.getStatusLine();
|
||||
logger.info(
|
||||
"step2_bedeveloper--->status={},body=\n{}",
|
||||
@ -422,7 +421,7 @@ public class WeixinExecutor implements Serializable {
|
||||
response = client.execute(host, method);
|
||||
entity = response.getEntity();
|
||||
root = Jsoup.parse(entity.getContent(),
|
||||
charset.name(),
|
||||
Consts.UTF_8.name(),
|
||||
weixin.getString("base"));
|
||||
} else {
|
||||
weixin.put("code", "-100");
|
||||
@ -495,13 +494,13 @@ public class WeixinExecutor implements Serializable {
|
||||
.add(new BasicNameValuePair("callback_encrypt_mode", "0"));
|
||||
parameters.add(new BasicNameValuePair("operation_seq", RandomUtil
|
||||
.generateStringByNumberChar(9)));
|
||||
method.setEntity(new UrlEncodedFormEntity(parameters, charset));
|
||||
method.setEntity(new UrlEncodedFormEntity(parameters, Consts.UTF_8));
|
||||
method.addHeader("Referer", weixin.getString("developerModifyUrl"));
|
||||
|
||||
HttpResponse response = client.execute(host, method);
|
||||
HttpEntity entity = response.getEntity();
|
||||
Document root = Jsoup.parse(entity.getContent(), charset.name(),
|
||||
weixin.getString("base"));
|
||||
Document root = Jsoup.parse(entity.getContent(),
|
||||
Consts.UTF_8.name(), weixin.getString("base"));
|
||||
StatusLine line = response.getStatusLine();
|
||||
logger.info("step3_setting--->status={},body=\n{}", line,
|
||||
root.toString());
|
||||
@ -565,13 +564,13 @@ public class WeixinExecutor implements Serializable {
|
||||
.currentTimeMillis() + ""));
|
||||
|
||||
method.setEntity(new UrlEncodedFormEntity(parameters,
|
||||
charset));
|
||||
Consts.UTF_8));
|
||||
method.setURI(URI.create(weixin.getString("start")));
|
||||
|
||||
response = client.execute(host, method);
|
||||
entity = response.getEntity();
|
||||
root = Jsoup.parse(entity.getContent(), charset.name(),
|
||||
weixin.getString("base"));
|
||||
root = Jsoup.parse(entity.getContent(),
|
||||
Consts.UTF_8.name(), weixin.getString("base"));
|
||||
line = response.getStatusLine();
|
||||
logger.info("step3_setting--->status={},body=\n{}",
|
||||
line, root.toString());
|
||||
@ -624,13 +623,14 @@ public class WeixinExecutor implements Serializable {
|
||||
parameters.add(new BasicNameValuePair("lang", "zh_CN"));
|
||||
parameters.add(new BasicNameValuePair("random", System
|
||||
.currentTimeMillis() + ""));
|
||||
method.setEntity(new UrlEncodedFormEntity(parameters, charset));
|
||||
method.setEntity(new UrlEncodedFormEntity(parameters,
|
||||
Consts.UTF_8));
|
||||
method.addHeader("Referer", weixin.getString("developerUrl"));
|
||||
|
||||
HttpResponse response = client.execute(host, method);
|
||||
HttpEntity entity = response.getEntity();
|
||||
Document root = Jsoup.parse(entity.getContent(),
|
||||
charset.name(), weixin.getString("base"));
|
||||
Consts.UTF_8.name(), weixin.getString("base"));
|
||||
StatusLine line = response.getStatusLine();
|
||||
logger.info("step4_back--->status={},body=\n{}", line,
|
||||
root.toString());
|
||||
|
||||
@ -2,6 +2,7 @@ package com.foxinmy.weixin4j.mp.type;
|
||||
|
||||
/**
|
||||
* 对账单类型
|
||||
*
|
||||
* @className BillType
|
||||
* @author jy
|
||||
* @date 2014年10月31日
|
||||
@ -9,5 +10,13 @@ package com.foxinmy.weixin4j.mp.type;
|
||||
* @see
|
||||
*/
|
||||
public enum BillType {
|
||||
ALL, SUCCESS, REFUND
|
||||
ALL(0), SUCCESS(1), REFUND(2);
|
||||
private int val;
|
||||
|
||||
BillType(int val) {
|
||||
this.val = val;
|
||||
}
|
||||
public int getVal() {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,5 +11,8 @@ package com.foxinmy.weixin4j.mp.type;
|
||||
*/
|
||||
public enum RefundChannel {
|
||||
ORIGINAL, // 原路退款
|
||||
BALANCE;// 退回到余额
|
||||
BALANCE,// 退回到余额
|
||||
|
||||
TENPAY, // 财付通
|
||||
BANK; // 银行
|
||||
}
|
||||
|
||||
@ -14,7 +14,6 @@ public enum RefundStatus {
|
||||
FAIL, // 退款失败
|
||||
PROCESSING, // 退款处理中
|
||||
NOTSURE, // 未确定,需要商户 原退款单号重新发起
|
||||
// 转入代发,退款到银行发现用户的卡作废或者冻结了,导致原路退款银行卡失败,资金回流到商户的现金帐号,需要商户人工干
|
||||
// 预,通过线下或者财付通转 账的方式进行退款。
|
||||
CHANGE;
|
||||
CHANGE; // 转入代发,退款到银行发现用户的卡作废或者冻结了,导致原路退款银行卡失败,资金回流到商户的现金帐号,需要商户人工干预,通过线下或者财付通转
|
||||
// 账的方式进行退款。
|
||||
}
|
||||
|
||||
@ -0,0 +1,61 @@
|
||||
package com.foxinmy.weixin4j.mp.type;
|
||||
|
||||
/**
|
||||
* 垂直服务协议
|
||||
*
|
||||
* @className SemCategory
|
||||
* @author jy
|
||||
* @date 2014年11月7日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public enum SemCategory {
|
||||
// 生活类
|
||||
restaurant("生活类", "餐馆", "查询餐馆的服务,例如:中关村附近的面馆"), map("生活类", "地图",
|
||||
"查询地图服务,例如:从银科大厦到天坛公园怎么走"), nearby("生活类", "周边",
|
||||
"查询周边的服务,例如:我想去打保龄球"), coupon("生活类", "优惠券/团购",
|
||||
"查询优惠券/团购的服务,例如:“附 近有什么优惠券”;如果查已有类别 的优惠券,比如:“附近有什么酒店 优惠券”,那么就会优先是酒店类。"),
|
||||
// 旅行类
|
||||
hotel("旅行类", "酒店", "查询酒店服务,例如:查一下中关村附近有没有七天酒店"), travel("旅行类", "旅游",
|
||||
"查询旅游服务,例如:故宫门票多少钱"), flight("旅行类", "航班", "查询航班的服务,例如:明天从北京到上海的机票"), train(
|
||||
"旅行类", "火车", "查询火车服务,例如:查一下从北京到西安的火车"),
|
||||
// 娱乐类
|
||||
movie("娱乐类", "上映电影", "查询上映电影的服务,例如:最近有什么好看的电影"), music("娱乐类", "音乐",
|
||||
"查询音乐的服务,例如:来点刘德华的歌"), video("娱乐类", "视频", "查询视频服务,例如:我想看甄嬛传"), novel(
|
||||
"娱乐类", "小说", "查询小说的服务,例如:来点言情小说看看"),
|
||||
// 工具类
|
||||
weather("工具类", "天气", "查询天气的服务,例如:明天北京天气"), stock("工具类", "股票",
|
||||
"查询股票的服务,例如:腾讯股价多少了"), remind("工具类", "提醒", "提醒服务,例如:提醒我明天上午十点开会"), telephone(
|
||||
"工具类", "常用电影", "查询常用电话号码服务,例如:查询一下招行信用卡的电话"),
|
||||
// 知识类
|
||||
cookbook("知识类", "菜谱", "查询菜谱服务,例如:宫保鸡丁怎么做"), baike("知识类", "百科",
|
||||
"查询百科服务,例如:查一下刘德华的百科资料"), news("知识类", "资讯", "查询新闻服务,例如:今天有什么新闻"),
|
||||
// 其他类
|
||||
tv("其他类", "电视节目预告", "查询电视节目服务,例如:湖南台今晚有什么节目"), instruction("其他类", "通用指令",
|
||||
"通用指令服务,例如:把声音调高一点"), tv_instruction("其他类", "电视指令",
|
||||
"电视指令服务,例如:切换到中央五台"), car_instruction("其他类", "车载指令",
|
||||
"车载指令服务,例如:把空调设为 25 度"), app("其他类", "应用", "查询应用服务,例如:打开愤怒的小鸟"), website(
|
||||
"其他类", "网址", "查询网址服务,例如:帮我打开腾讯网"), search("其他类", "网页搜索",
|
||||
"网页搜索服务,例如:百度一下意大利对乌拉圭");
|
||||
SemCategory(String main, String desc, String remark) {
|
||||
this.main = main;
|
||||
this.desc = desc;
|
||||
this.remark = remark;
|
||||
}
|
||||
|
||||
private String main;
|
||||
private String desc;
|
||||
private String remark;
|
||||
|
||||
public String getMain() {
|
||||
return main;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
public String getRemark() {
|
||||
return remark;
|
||||
}
|
||||
}
|
||||
@ -15,4 +15,4 @@ media_path=/tmp/weixin/media
|
||||
# \u5bf9\u8d26\u5355\u4fdd\u5b58\u8def\u5f84
|
||||
bill_path=/tmp/weixin/bill
|
||||
# ca\u8bc1\u4e66\u5b58\u653e\u7684\u5b8c\u6574\u8def\u5f84
|
||||
ca_file=/tmp/weixin/xxxxx.p12
|
||||
ca_file=/Users/jy/Downloads/1221928801.pfx
|
||||
@ -0,0 +1,27 @@
|
||||
package com.foxinmy.weixin4j.mp.test;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.mp.api.HelperApi;
|
||||
import com.foxinmy.weixin4j.mp.model.SemQuery;
|
||||
import com.foxinmy.weixin4j.mp.type.SemCategory;
|
||||
|
||||
public class SemanticTest extends TokenTest {
|
||||
private HelperApi helperApi;
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
helperApi = new HelperApi(tokenHolder);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testApi() throws WeixinException {
|
||||
SemQuery query = SemQuery.build("附近有啥 100 元以内的保龄球馆");
|
||||
query.city("北京").category(SemCategory.nearby);
|
||||
query.uid("opKwyt6IhrqPmTTZshyqH5W9gIVo");
|
||||
System.out.println(query);
|
||||
System.out.println(helperApi.semantic(query));
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user