修复媒体消息转换错误bug & 新增创建卡券二维码接口
This commit is contained in:
@@ -160,7 +160,7 @@
|
||||
|
||||
* 2016-08-05
|
||||
|
||||
+ model包拆分media/paing
|
||||
+ model包拆分media/paging
|
||||
|
||||
+ type包拆分card/mch
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package com.foxinmy.weixin4j.http;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import com.foxinmy.weixin4j.util.StringUtil;
|
||||
@@ -35,12 +37,14 @@ public class MimeType implements Serializable {
|
||||
public static final MimeType TEXT_XML;
|
||||
public static final MimeType TEXT_JSON;
|
||||
|
||||
public static final List<MimeType> STREAM_MIMETYPES;
|
||||
|
||||
static {
|
||||
APPLICATION_FORM_URLENCODED = valueOf("application/x-www-form-urlencoded");
|
||||
APPLICATION_JSON = valueOf("application/json");
|
||||
APPLICATION_OCTET_STREAM = valueOf("application/octet-stream");
|
||||
APPLICATION_XML = valueOf("application/xml");
|
||||
MULTIPART_FORM_DATA = MimeType.valueOf("multipart/form-data");
|
||||
MULTIPART_FORM_DATA = valueOf("multipart/form-data");
|
||||
TEXT_HTML = valueOf("text/html");
|
||||
TEXT_PLAIN = valueOf("text/plain");
|
||||
IMAGE_JPG = valueOf("image/jpg");
|
||||
@@ -48,6 +52,12 @@ public class MimeType implements Serializable {
|
||||
VIDEO_MPEG4 = valueOf("video/mpeg4");
|
||||
TEXT_XML = valueOf("text/xml");
|
||||
TEXT_JSON = valueOf("text/json");
|
||||
|
||||
STREAM_MIMETYPES = new ArrayList<MimeType>(4);
|
||||
STREAM_MIMETYPES.add(APPLICATION_OCTET_STREAM);
|
||||
STREAM_MIMETYPES.add(valueOf("image/*"));
|
||||
STREAM_MIMETYPES.add(valueOf("audio/*"));
|
||||
STREAM_MIMETYPES.add(valueOf("video/*"));
|
||||
}
|
||||
|
||||
public MimeType(String type) {
|
||||
@@ -72,28 +82,33 @@ public class MimeType implements Serializable {
|
||||
}
|
||||
|
||||
public boolean isWildcardSubtype() {
|
||||
return WILDCARD_TYPE.equals(getSubType()) || getSubType().startsWith("*+");
|
||||
return WILDCARD_TYPE.equals(getSubType())
|
||||
|| getSubType().startsWith("*+");
|
||||
}
|
||||
|
||||
public static MimeType valueOf(String value) {
|
||||
if (StringUtil.isBlank(value)) {
|
||||
return null;
|
||||
}
|
||||
String mimeType = StringUtil.tokenizeToStringArray(value, ";")[0].trim().toLowerCase(Locale.ENGLISH);
|
||||
String mimeType = StringUtil.tokenizeToStringArray(value, ";")[0]
|
||||
.trim().toLowerCase(Locale.ENGLISH);
|
||||
if (WILDCARD_TYPE.equals(mimeType)) {
|
||||
mimeType = "*/*";
|
||||
}
|
||||
int subIndex = mimeType.indexOf('/');
|
||||
if (subIndex == -1) {
|
||||
throw new IllegalArgumentException(mimeType + ":does not contain '/'");
|
||||
throw new IllegalArgumentException(mimeType
|
||||
+ ":does not contain '/'");
|
||||
}
|
||||
if (subIndex == mimeType.length() - 1) {
|
||||
throw new IllegalArgumentException(mimeType + ":does not contain subtype after '/'");
|
||||
throw new IllegalArgumentException(mimeType
|
||||
+ ":does not contain subtype after '/'");
|
||||
}
|
||||
String type = mimeType.substring(0, subIndex);
|
||||
String subType = mimeType.substring(subIndex + 1, mimeType.length());
|
||||
if (WILDCARD_TYPE.equals(type) && !WILDCARD_TYPE.equals(subType)) {
|
||||
throw new IllegalArgumentException(mimeType + ":wildcard type is legal only in '*/*' (all mime types)");
|
||||
throw new IllegalArgumentException(mimeType
|
||||
+ ":wildcard type is legal only in '*/*' (all mime types)");
|
||||
}
|
||||
return new MimeType(type, subType);
|
||||
}
|
||||
@@ -121,10 +136,14 @@ public class MimeType implements Serializable {
|
||||
// application/*+xml includes application/soap+xml
|
||||
int otherPlusIdx = other.getSubType().indexOf('+');
|
||||
if (otherPlusIdx != -1) {
|
||||
String thisSubtypeNoSuffix = getSubType().substring(0, thisPlusIdx);
|
||||
String thisSubtypeSuffix = getSubType().substring(thisPlusIdx + 1);
|
||||
String otherSubtypeSuffix = other.getSubType().substring(otherPlusIdx + 1);
|
||||
if (thisSubtypeSuffix.equals(otherSubtypeSuffix) && WILDCARD_TYPE.equals(thisSubtypeNoSuffix)) {
|
||||
String thisSubtypeNoSuffix = getSubType().substring(0,
|
||||
thisPlusIdx);
|
||||
String thisSubtypeSuffix = getSubType().substring(
|
||||
thisPlusIdx + 1);
|
||||
String otherSubtypeSuffix = other.getSubType()
|
||||
.substring(otherPlusIdx + 1);
|
||||
if (thisSubtypeSuffix.equals(otherSubtypeSuffix)
|
||||
&& WILDCARD_TYPE.equals(thisSubtypeNoSuffix)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -148,7 +167,8 @@ public class MimeType implements Serializable {
|
||||
return false;
|
||||
}
|
||||
MimeType otherType = (MimeType) other;
|
||||
return this.type.equalsIgnoreCase(otherType.type) && this.subType.equalsIgnoreCase(otherType.subType);
|
||||
return this.type.equalsIgnoreCase(otherType.type)
|
||||
&& this.subType.equalsIgnoreCase(otherType.subType);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+29
-2
@@ -15,6 +15,7 @@ import com.foxinmy.weixin4j.http.HttpMethod;
|
||||
import com.foxinmy.weixin4j.http.HttpParams;
|
||||
import com.foxinmy.weixin4j.http.HttpRequest;
|
||||
import com.foxinmy.weixin4j.http.HttpResponse;
|
||||
import com.foxinmy.weixin4j.http.MimeType;
|
||||
import com.foxinmy.weixin4j.http.URLParameter;
|
||||
import com.foxinmy.weixin4j.http.apache.FormBodyPart;
|
||||
import com.foxinmy.weixin4j.http.apache.HttpMultipartMode;
|
||||
@@ -129,8 +130,6 @@ public class WeixinRequestExecutor {
|
||||
+ request.getURI().toString());
|
||||
HttpResponse httpResponse = httpClient.execute(request);
|
||||
WeixinResponse response = new WeixinResponse(httpResponse);
|
||||
logger.info("weixin response << " + httpResponse.getProtocol()
|
||||
+ httpResponse.getStatus() + ":" + response.getAsString());
|
||||
handleResponse(response);
|
||||
return response;
|
||||
} catch (HttpClientException e) {
|
||||
@@ -138,6 +137,24 @@ public class WeixinRequestExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 响应内容是否为流
|
||||
*
|
||||
* @param response
|
||||
* 微信响应
|
||||
* @return true/false
|
||||
*/
|
||||
private boolean hasStreamMimeType(WeixinResponse response) {
|
||||
MimeType responseMimeType = MimeType.valueOf(response.getHeaders()
|
||||
.getContentType());
|
||||
for (MimeType streamMimeType : MimeType.STREAM_MIMETYPES) {
|
||||
if (streamMimeType.includes(responseMimeType)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* handle the weixin response
|
||||
*
|
||||
@@ -147,6 +164,16 @@ public class WeixinRequestExecutor {
|
||||
*/
|
||||
protected void handleResponse(WeixinResponse response)
|
||||
throws WeixinException {
|
||||
boolean hasStreamMimeType = hasStreamMimeType(response);
|
||||
logger.info("weixin response << "
|
||||
+ response.getProtocol()
|
||||
+ response.getStatus()
|
||||
+ ":"
|
||||
+ (hasStreamMimeType ? response.getHeaders().getContentType()
|
||||
: response.getAsString()));
|
||||
if (hasStreamMimeType) {
|
||||
return;
|
||||
}
|
||||
ApiResult result = response.getAsResult();
|
||||
if (!SUCCESS_CODE.contains(String.format(",%s,", result.getReturnCode()
|
||||
.toLowerCase()))) {
|
||||
|
||||
@@ -5,7 +5,6 @@ import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.fastjson.TypeReference;
|
||||
import com.foxinmy.weixin4j.http.HttpHeaders;
|
||||
@@ -34,6 +33,8 @@ public class WeixinResponse implements HttpResponse {
|
||||
};
|
||||
private final TypeReference<XmlResult> XMLRESULT_CLAZZ = new TypeReference<XmlResult>() {
|
||||
};
|
||||
private final TypeReference<JSONObject> JSONOBJECT_CLAZZ = new TypeReference<JSONObject>() {
|
||||
};
|
||||
|
||||
static {
|
||||
messageConverters.add(new JsonMessageConverter());
|
||||
@@ -56,7 +57,7 @@ public class WeixinResponse implements HttpResponse {
|
||||
}
|
||||
|
||||
public JSONObject getAsJson() {
|
||||
return JSON.parseObject(getAsString());
|
||||
return getAsObject(JSONOBJECT_CLAZZ);
|
||||
}
|
||||
|
||||
public XmlResult getAsXml() {
|
||||
@@ -71,7 +72,8 @@ public class WeixinResponse implements HttpResponse {
|
||||
try {
|
||||
return messageConverter.convert(clazz, response);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("IO error on convert to " + typeReference, e);
|
||||
throw new RuntimeException("IO error on convert to "
|
||||
+ typeReference, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ public class Button implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个菜单
|
||||
* 创建一个具有子菜单的菜单
|
||||
*
|
||||
* @param name
|
||||
* 菜单名
|
||||
@@ -76,7 +76,7 @@ public class Button implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个菜单
|
||||
* 创建一个普通菜单
|
||||
*
|
||||
* @param name
|
||||
* 菜单名
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.foxinmy.weixin4j.card;
|
||||
package com.foxinmy.weixin4j.model.card;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.foxinmy.weixin4j.type.card.CardType;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.foxinmy.weixin4j.card;
|
||||
package com.foxinmy.weixin4j.model.card;
|
||||
|
||||
/**
|
||||
* 卡券构造器
|
||||
@@ -0,0 +1,156 @@
|
||||
package com.foxinmy.weixin4j.model.card;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
|
||||
/**
|
||||
* 卡券二维码参数
|
||||
*
|
||||
* @className CardQR
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2016年8月9日
|
||||
* @since JDK 1.6
|
||||
* @see Builder
|
||||
*/
|
||||
public class CardQR implements Serializable {
|
||||
private static final long serialVersionUID = -2810577326677518511L;
|
||||
|
||||
/**
|
||||
* 卡券ID
|
||||
*/
|
||||
@JSONField(name = "card_id")
|
||||
private String cardId;
|
||||
/**
|
||||
* 卡券Code码,use_custom_code字段为true的卡券必须填写,非自定义code和导入code模式的卡券不必填写。
|
||||
*/
|
||||
@JSONField(name = "code")
|
||||
private String cardCode;
|
||||
/**
|
||||
* 指定领取者的openid,只有该用户能领取。bind_openid字段为true的卡券必须填写,非指定openid不必填写。
|
||||
*/
|
||||
@JSONField(name = "openid")
|
||||
private String openId;
|
||||
/**
|
||||
* 领取场景值,用于领取渠道的数据统计,默认值为0,字段类型为整型,长度限制为60位数字。用户领取卡券后触发的事件推送中会带上此自定义场景值。
|
||||
*/
|
||||
@JSONField(name = "outer_str")
|
||||
private String sceneValue;
|
||||
/**
|
||||
* 指定下发二维码,生成的二维码随机分配一个code,领取后不可再次扫描。填写true或false。默认false,注意填写该字段时,
|
||||
* 卡券须通过审核且库存不为0。
|
||||
*/
|
||||
@JSONField(name = "is_unique_code")
|
||||
private boolean isUniqueCode;
|
||||
|
||||
private CardQR(Builder builder) {
|
||||
this.cardId = builder.cardId;
|
||||
this.cardCode = builder.cardCode;
|
||||
this.isUniqueCode = builder.isUniqueCode;
|
||||
this.openId = builder.openId;
|
||||
this.sceneValue = builder.sceneValue;
|
||||
}
|
||||
|
||||
public String getCardId() {
|
||||
return cardId;
|
||||
}
|
||||
|
||||
public String getCardCode() {
|
||||
return cardCode;
|
||||
}
|
||||
|
||||
public String getOpenId() {
|
||||
return openId;
|
||||
}
|
||||
|
||||
public String getSceneValue() {
|
||||
return sceneValue;
|
||||
}
|
||||
|
||||
public boolean isUniqueCode() {
|
||||
return isUniqueCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CardQR [cardId=" + cardId + ", cardCode=" + cardCode
|
||||
+ ", openId=" + openId + ", sceneValue=" + sceneValue
|
||||
+ ", isUniqueCode=" + isUniqueCode + "]";
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
/**
|
||||
* 卡券ID
|
||||
*/
|
||||
private String cardId;
|
||||
/**
|
||||
* 卡券Code码,use_custom_code字段为true的卡券必须填写,非自定义code和导入code模式的卡券不必填写。
|
||||
*/
|
||||
private String cardCode;
|
||||
/**
|
||||
* 指定领取者的openid,只有该用户能领取。bind_openid字段为true的卡券必须填写,非指定openid不必填写。
|
||||
*/
|
||||
private String openId;
|
||||
/**
|
||||
* 用户首次领卡时,会通过领取事件推送给商户;
|
||||
* 对于会员卡的二维码,用户每次扫码打开会员卡后点击任何url,会将该值拼入url中,方便开发者定位扫码来源
|
||||
*/
|
||||
private String sceneValue;
|
||||
/**
|
||||
* 指定下发二维码,生成的二维码随机分配一个code,领取后不可再次扫描。填写true或false。默认false,注意填写该字段时,
|
||||
* 卡券须通过审核且库存不为0。
|
||||
*/
|
||||
private boolean isUniqueCode;
|
||||
|
||||
public Builder(String cardId) {
|
||||
this.cardId = cardId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 卡券Code码,use_custom_code字段为true的卡券必须填写,非自定义code和导入code模式的卡券不必填写。
|
||||
*
|
||||
* @param cardCode
|
||||
* 卡券code码
|
||||
*/
|
||||
public Builder cardCode(String cardCode) {
|
||||
this.cardCode = cardCode;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定领取者的openid,只有该用户能领取。bind_openid字段为true的卡券必须填写,非指定openid不必填写。
|
||||
*
|
||||
* @param openId
|
||||
* 用户openid
|
||||
*/
|
||||
public Builder openId(String openId) {
|
||||
this.openId = openId;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户首次领卡时,会通过领取事件推送给商户;
|
||||
* 对于会员卡的二维码,用户每次扫码打开会员卡后点击任何url,会将该值拼入url中,方便开发者定位扫码来源
|
||||
*
|
||||
* @param sceneValue
|
||||
* 场景值
|
||||
*/
|
||||
public Builder sceneValuer(String sceneValue) {
|
||||
this.sceneValue = sceneValue;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定下发二维码,生成的二维码随机分配一个code,领取后不可再次扫描。填写true或false。默认false,注意填写该字段时,
|
||||
* 卡券须通过审核且库存不为0。
|
||||
*/
|
||||
public Builder openUniqueCode() {
|
||||
this.isUniqueCode = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CardQR build() {
|
||||
return new CardQR(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.foxinmy.weixin4j.card;
|
||||
package com.foxinmy.weixin4j.model.card;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.foxinmy.weixin4j.type.card.CardType;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.foxinmy.weixin4j.card;
|
||||
package com.foxinmy.weixin4j.model.card;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.foxinmy.weixin4j.card;
|
||||
package com.foxinmy.weixin4j.model.card;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.foxinmy.weixin4j.card;
|
||||
package com.foxinmy.weixin4j.model.card;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.foxinmy.weixin4j.type.card.CardType;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.foxinmy.weixin4j.card;
|
||||
package com.foxinmy.weixin4j.model.card;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.foxinmy.weixin4j.type.card.CardType;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.foxinmy.weixin4j.card;
|
||||
package com.foxinmy.weixin4j.model.card;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.foxinmy.weixin4j.type.card.CardType;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.foxinmy.weixin4j.card;
|
||||
package com.foxinmy.weixin4j.model.card;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.foxinmy.weixin4j.type.card.CardType;
|
||||
@@ -0,0 +1,173 @@
|
||||
package com.foxinmy.weixin4j.model.qr;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.foxinmy.weixin4j.model.card.CardQR;
|
||||
import com.foxinmy.weixin4j.type.QRType;
|
||||
|
||||
/**
|
||||
* 二维码参数对象
|
||||
*
|
||||
* @className QRParameter
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2014年4月8日
|
||||
* @since JDK 1.6
|
||||
* @see #createTemporaryQR(int, long) 创建整型临时二维码
|
||||
* @see #createPermanenceQR(int) 创建整型永久二维码
|
||||
* @see #createPermanenceQR(String) 创建字符串型永久二维码
|
||||
* @see #createCardCouponQR(Integer, CardQR...) 创建卡券二维码
|
||||
*/
|
||||
public class QRParameter implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 6611187606558274253L;
|
||||
|
||||
/**
|
||||
* 二维码的类型
|
||||
*
|
||||
* @see com.foxinmy.weixin4j.type.QRType
|
||||
*/
|
||||
@JSONField(name = "action_name")
|
||||
private QRType qrType;
|
||||
/**
|
||||
* 二维码的有效时间
|
||||
*/
|
||||
@JSONField(name = "expire_seconds")
|
||||
private Integer expireSeconds;
|
||||
/**
|
||||
* 二维码的内容
|
||||
*/
|
||||
@JSONField(name = "action_info")
|
||||
private JSONObject sceneContent;
|
||||
|
||||
private QRParameter(QRType qrType, Integer expireSeconds,
|
||||
JSONObject sceneContent) {
|
||||
this.qrType = qrType;
|
||||
this.expireSeconds = expireSeconds;
|
||||
this.sceneContent = sceneContent;
|
||||
}
|
||||
|
||||
public Integer getExpireSeconds() {
|
||||
return expireSeconds;
|
||||
}
|
||||
|
||||
public QRType getQrType() {
|
||||
return qrType;
|
||||
}
|
||||
|
||||
public JSONObject getSceneContent() {
|
||||
return sceneContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建临时二维码
|
||||
*
|
||||
* @param expireSeconds
|
||||
* 二维码有效时间,以秒为单位。 最大不超过2592000(即30天)
|
||||
* @param sceneValue
|
||||
* 二维码的场景值 <font color="red">临时二维码最大值为无符号32位非0整型</font>
|
||||
* @return 二维码参数
|
||||
*/
|
||||
public static QRParameter createTemporaryQR(int expireSeconds,
|
||||
long sceneValue) {
|
||||
JSONObject sceneContent = new JSONObject();
|
||||
JSONObject scene = new JSONObject();
|
||||
scene.put("scene_id", sceneValue);
|
||||
sceneContent.put("scene", scene);
|
||||
return new QRParameter(QRType.QR_SCENE, expireSeconds, sceneContent);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建永久二维码(场景值为int)
|
||||
*
|
||||
* @param sceneValue
|
||||
* 场景值 最大值为100000 (目前参数只支持1--100000)
|
||||
*/
|
||||
public static QRParameter createPermanenceQR(int sceneValue) {
|
||||
JSONObject sceneContent = new JSONObject();
|
||||
JSONObject scene = new JSONObject();
|
||||
scene.put("scene_id", sceneValue);
|
||||
sceneContent.put("scene", scene);
|
||||
return new QRParameter(QRType.QR_LIMIT_SCENE, null, sceneContent);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建永久二维码(场景值为string)
|
||||
*
|
||||
* @param sceneValue
|
||||
* 场景值
|
||||
*/
|
||||
public static QRParameter createPermanenceQR(String sceneValue) {
|
||||
JSONObject sceneContent = new JSONObject();
|
||||
JSONObject scene = new JSONObject();
|
||||
scene.put("scene_str", sceneValue);
|
||||
sceneContent.put("scene", scene);
|
||||
return new QRParameter(QRType.QR_LIMIT_STR_SCENE, null, sceneContent);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建卡券二维码
|
||||
*
|
||||
* @param expireSeconds
|
||||
* 指定二维码的有效时间,范围是60 ~ 1800秒。不填默认为365天有效
|
||||
* @param cardQRs
|
||||
* 二维码参数:二维码领取单张卡券/多张卡券
|
||||
*/
|
||||
public static QRParameter createCardCouponQR(Integer expireSeconds,
|
||||
CardQR... cardQRs) {
|
||||
QRType qrType = QRType.QR_CARD;
|
||||
JSONObject sceneContent = new JSONObject();
|
||||
if (cardQRs.length > 1) {
|
||||
qrType = QRType.QR_MULTIPLE_CARD;
|
||||
JSONObject multipleCard = new JSONObject();
|
||||
multipleCard.put("card_list", cardQRs);
|
||||
sceneContent.put("multiple_card", multipleCard);
|
||||
} else {
|
||||
sceneContent.put("card", cardQRs[0]);
|
||||
}
|
||||
return new QRParameter(qrType, expireSeconds, sceneContent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result
|
||||
+ ((expireSeconds == null) ? 0 : expireSeconds.hashCode());
|
||||
result = prime * result + ((qrType == null) ? 0 : qrType.hashCode());
|
||||
result = prime * result
|
||||
+ ((sceneContent == null) ? 0 : sceneContent.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
QRParameter other = (QRParameter) obj;
|
||||
if (expireSeconds == null) {
|
||||
if (other.expireSeconds != null)
|
||||
return false;
|
||||
} else if (!expireSeconds.equals(other.expireSeconds))
|
||||
return false;
|
||||
if (qrType != other.qrType)
|
||||
return false;
|
||||
if (sceneContent == null) {
|
||||
if (other.sceneContent != null)
|
||||
return false;
|
||||
} else if (!sceneContent.equals(other.sceneContent))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "QRParameter [qrType=" + qrType + ", expireSeconds="
|
||||
+ expireSeconds + ", sceneContent=" + sceneContent + "]";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.foxinmy.weixin4j.model.qr;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
|
||||
/**
|
||||
* 二维码
|
||||
*
|
||||
* @className QRResult
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2015年7月29日
|
||||
* @since JDK 1.6
|
||||
* @see
|
||||
*/
|
||||
public class QRResult implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 7730781702153258151L;
|
||||
|
||||
private String ticket;
|
||||
private String url;
|
||||
@JSONField(name = "show_qrcode_url")
|
||||
private String showUrl;
|
||||
@JSONField(name = "expire_seconds")
|
||||
private int expireSeconds;
|
||||
private byte[] content;
|
||||
|
||||
public String getTicket() {
|
||||
return ticket;
|
||||
}
|
||||
|
||||
public void setTicket(String ticket) {
|
||||
this.ticket = ticket;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public String getShowUrl() {
|
||||
return showUrl;
|
||||
}
|
||||
|
||||
public void setShowUrl(String showUrl) {
|
||||
this.showUrl = showUrl;
|
||||
}
|
||||
|
||||
public int getExpireSeconds() {
|
||||
return expireSeconds;
|
||||
}
|
||||
|
||||
public void setExpireSeconds(int expireSeconds) {
|
||||
this.expireSeconds = expireSeconds;
|
||||
}
|
||||
|
||||
public byte[] getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(byte[] content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "QRResult [ticket=" + ticket + ", url=" + url + ", showUrl="
|
||||
+ showUrl + ", expireSeconds=" + expireSeconds
|
||||
+ ", content=..." + "]";
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,7 @@ public class TokenManager extends CacheManager<Token> {
|
||||
/**
|
||||
* 获取token字符串
|
||||
*
|
||||
* @return
|
||||
* @return token字符串
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public String getAccessToken() throws WeixinException {
|
||||
|
||||
@@ -21,5 +21,13 @@ public enum QRType {
|
||||
/**
|
||||
* 永久二维码(场景值为字符串长度在1-64之间)
|
||||
*/
|
||||
QR_LIMIT_STR_SCENE;
|
||||
QR_LIMIT_STR_SCENE,
|
||||
/**
|
||||
* 卡券二维码:单个卡券
|
||||
*/
|
||||
QR_CARD,
|
||||
/**
|
||||
* 卡券二维码:多个卡券
|
||||
*/
|
||||
QR_MULTIPLE_CARD;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user