diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxConsts.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxConsts.java index 0455e6c2..85efcd3f 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxConsts.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxConsts.java @@ -47,7 +47,7 @@ public class WxConsts { /////////////////////// public static final String MASS_ST_SUCCESS = "send success"; public static final String MASS_ST_FAIL = "send fail"; - public static final String MASS_ST_涉嫌广告 = "err(10001)"; + public static final String MASS_ST_涉嫌广告 = "err(10001)"; public static final String MASS_ST_涉嫌政治 = "err(20001)"; public static final String MASS_ST_涉嫌社会 = "err(20004)"; public static final String MASS_ST_涉嫌色情 = "err(20002)"; @@ -93,6 +93,15 @@ public class WxConsts { public static final String EVT_LOCATION_SELECT = "location_select"; public static final String EVT_TEMPLATESENDJOBFINISH = "TEMPLATESENDJOBFINISH"; public static final String EVT_ENTER_AGENT = "enter_agent"; + public static final String EVT_CARD_PASS_CHECK = "card_pass_check"; + public static final String EVT_CARD_NOT_PASS_CHECK = "card_not_pass_check"; + public static final String EVT_USER_GET_CARD = "user_get_card"; + public static final String EVT_USER_DEL_CARD = "user_del_card"; + public static final String EVT_USER_CONSUME_CARD = "user_consume_card"; + public static final String EVT_USER_PAY_FROM_PAY_CELL = "user_pay_from_pay_cell"; + public static final String EVT_USER_VIEW_CARD = "user_view_card"; + public static final String EVT_USER_ENTER_SESSION_FROM_CARD = "user_enter_session_from_card"; + public static final String EVT_CARD_SKU_REMIND = "card_sku_remind"; // 库存报警 /////////////////////// // 上传多媒体文件的类型 diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/WxCardApiSignature.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/WxCardApiSignature.java new file mode 100644 index 00000000..5d4d46a9 --- /dev/null +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/WxCardApiSignature.java @@ -0,0 +1,102 @@ +package me.chanjar.weixin.common.bean; + +import java.io.Serializable; + +/** + * 卡券Api签名 + * + * @author YuJian + * @version 15/11/8 + */ +public class WxCardApiSignature implements Serializable { + + private String appId; + + private String cardId; + + private String cardType; + + private String locationId; + + private String code; + + private String openId; + + private Long timestamp; + + private String nonceStr; + + private String signature; + + public String getAppId() { + return appId; + } + + public void setAppId(String appId) { + this.appId = appId; + } + + public String getCardId() { + return cardId; + } + + public void setCardId(String cardId) { + this.cardId = cardId; + } + + public String getCardType() { + return cardType; + } + + public void setCardType(String cardType) { + this.cardType = cardType; + } + + public String getLocationId() { + return locationId; + } + + public void setLocationId(String locationId) { + this.locationId = locationId; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getOpenId() { + return openId; + } + + public void setOpenId(String openId) { + this.openId = openId; + } + + public Long getTimestamp() { + return timestamp; + } + + public void setTimestamp(Long timestamp) { + this.timestamp = timestamp; + } + + public String getNonceStr() { + return nonceStr; + } + + public void setNonceStr(String nonceStr) { + this.nonceStr = nonceStr; + } + + public String getSignature() { + return signature; + } + + public void setSignature(String signature) { + this.signature = signature; + } +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpConfigStorage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpConfigStorage.java index 09d90d64..14cc03bf 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpConfigStorage.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpConfigStorage.java @@ -50,6 +50,21 @@ public interface WxMpConfigStorage { */ public void updateJsapiTicket(String jsapiTicket, int expiresInSeconds); + public String getCardApiTicket(); + + public boolean isCardApiTicketExpired(); + + /** + * 强制将卡券api ticket过期掉 + */ + public void expireCardApiTicket(); + + /** + * 应该是线程安全的 + * @param cardApiTicket + */ + public void updateCardApiTicket(String cardApiTicket, int expiresInSeconds); + public String getAppId(); public String getSecret(); diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpInMemoryConfigStorage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpInMemoryConfigStorage.java index e0c7aaa3..9eacbe01 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpInMemoryConfigStorage.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpInMemoryConfigStorage.java @@ -32,6 +32,9 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage { protected volatile String jsapiTicket; protected volatile long jsapiTicketExpiresTime; + protected volatile String cardApiTicket; + protected volatile long cardApiTicketExpiresTime; + /** * 临时文件目录 */ @@ -90,6 +93,27 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage { this.jsapiTicketExpiresTime = 0; } + /** + * 卡券api_ticket + */ + public String getCardApiTicket() { + return cardApiTicket; + } + + public boolean isCardApiTicketExpired() { + return System.currentTimeMillis() > this.cardApiTicketExpiresTime; + } + + public synchronized void updateCardApiTicket(String cardApiTicket, int expiresInSeconds) { + this.cardApiTicket = cardApiTicket; + // 预留200秒的时间 + this.cardApiTicketExpiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000l; + } + + public void expireCardApiTicket() { + this.cardApiTicketExpiresTime = 0; + } + public String getAppId() { return this.appId; } @@ -192,6 +216,8 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage { ", http_proxy_password='" + http_proxy_password + '\'' + ", jsapiTicket='" + jsapiTicket + '\'' + ", jsapiTicketExpiresTime='" + jsapiTicketExpiresTime + '\'' + + ", cardApiTicket='" + cardApiTicket + '\'' + + ", cardApiTicketExpiresTime='" + cardApiTicketExpiresTime + '\'' + ", tmpDirFile='" + tmpDirFile + '\'' + '}'; } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java index e6ce30cf..d0e2c190 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java @@ -1,5 +1,6 @@ package me.chanjar.weixin.mp.api; +import me.chanjar.weixin.common.bean.WxCardApiSignature; import me.chanjar.weixin.common.bean.WxMenu; import me.chanjar.weixin.common.bean.WxJsapiSignature; import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; @@ -770,7 +771,7 @@ public interface WxMpService { * @return */ public boolean checkJSSDKCallbackDataSignature(Map kvm, String signature); - + /** * 发送微信红包给个人用户 * @param parameters @@ -778,4 +779,81 @@ public interface WxMpService { * @throws WxErrorException */ public WxRedpackResult sendRedpack(Map parameters) throws WxErrorException; + + /** + * 获得卡券api_ticket,不强制刷新卡券api_ticket + * @see #getCardApiTicket(boolean) + * @return 卡券api_ticket + * @throws WxErrorException + */ + public String getCardApiTicket() throws WxErrorException; + + /** + *
+   * 获得卡券api_ticket
+   * 获得时会检查卡券apiToken是否过期,如果过期了,那么就刷新一下,否则就什么都不干
+   *
+   * 详情请见:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html#.E9.99.84.E5.BD.954-.E5.8D.A1.E5.88.B8.E6.89.A9.E5.B1.95.E5.AD.97.E6.AE.B5.E5.8F.8A.E7.AD.BE.E5.90.8D.E7.94.9F.E6.88.90.E7.AE.97.E6.B3.95
+   * 
+ * @param forceRefresh 强制刷新 + * @return 卡券api_ticket + * @throws WxErrorException + */ + public String getCardApiTicket(boolean forceRefresh) throws WxErrorException; + + /** + *
+   * 创建调用卡券api时所需要的签名
+   *
+   * 详情请见:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html#.E9.99.84.E5.BD
+   * .954-.E5.8D.A1.E5.88.B8.E6.89.A9.E5.B1.95.E5.AD.97.E6.AE.B5.E5.8F.8A.E7.AD.BE.E5.90.8D.E7.94
+   * .9F.E6.88.90.E7.AE.97.E6.B3.95
+   * 
+ * + * @param optionalSignParam 参与签名的参数数组。 + * 可以为下列字段:app_id, card_id, card_type, code, openid, location_id + * @return 卡券Api签名对象 + */ + public WxCardApiSignature createCardApiSignature(String... optionalSignParam) throws + WxErrorException; + + /** + * 卡券Code解码 + * @param encryptCode 加密Code,通过JSSDK的chooseCard接口获得 + * @return 解密后的Code + * @throws WxErrorException + */ + public String decryptCardCode(String encryptCode) throws WxErrorException; + + /** + * 卡券Code查询 + * @param cardId 卡券ID代表一类卡券 + * @param code 单张卡券的唯一标准 + * @param checkConsume 是否校验code核销状态,填入true和false时的code异常状态返回数据不同 + * @return WxMpCardResult对象 + * @throws WxErrorException + */ + public WxMpCardResult queryCardCode(String cardId, String code, boolean checkConsume) + throws WxErrorException; + + /** + * 卡券Code核销。核销失败会抛出异常 + * @param code 单张卡券的唯一标准 + * @return + * @throws WxErrorException + */ + public void consumeCardCode(String code) throws WxErrorException; + + /** + * 卡券Mark接口。 + * 开发者在帮助消费者核销卡券之前,必须帮助先将此code(卡券串码)与一个openid绑定(即mark住), + * 才能进一步调用核销接口,否则报错。 + * @param code 卡券的code码 + * @param cardId 卡券的ID + * @param openId 用券用户的openid + * @param isMark 是否要mark(占用)这个code,填写true或者false,表示占用或解除占用 + * @throws WxErrorException + */ + public void markCardCode(String code, String cardId, String openId, boolean isMark) throws + WxErrorException; } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java index 7a5b7ace..25f86e56 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java @@ -5,6 +5,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.StringReader; import java.security.NoSuchAlgorithmException; +import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.List; @@ -14,8 +15,10 @@ import java.util.SortedMap; import java.util.TreeMap; import java.util.UUID; +import com.google.gson.JsonPrimitive; import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.bean.WxAccessToken; +import me.chanjar.weixin.common.bean.WxCardApiSignature; import me.chanjar.weixin.common.bean.WxJsapiSignature; import me.chanjar.weixin.common.bean.WxMenu; import me.chanjar.weixin.common.bean.result.WxError; @@ -43,6 +46,7 @@ import me.chanjar.weixin.mp.bean.WxMpMaterialArticleUpdate; import me.chanjar.weixin.mp.bean.WxMpMaterialNews; import me.chanjar.weixin.mp.bean.WxMpSemanticQuery; import me.chanjar.weixin.mp.bean.WxMpTemplateMessage; +import me.chanjar.weixin.mp.bean.result.WxMpCardResult; import me.chanjar.weixin.mp.bean.result.WxMpMassSendResult; import me.chanjar.weixin.mp.bean.result.WxMpMassUploadResult; import me.chanjar.weixin.mp.bean.result.WxMpMaterialCountResult; @@ -112,6 +116,11 @@ public class WxMpServiceImpl implements WxMpService { */ protected final Object globalJsapiTicketRefreshLock = new Object(); + /** + * 全局的是否正在刷新卡券api_ticket的锁 + */ + protected final Object globalCardApiTicketRefreshLock = new Object(); + protected WxMpConfigStorage wxMpConfigStorage; protected CloseableHttpClient httpClient; @@ -1006,4 +1015,172 @@ public class WxMpServiceImpl implements WxMpService { throw new WxErrorException(error); } } + + /** + * 获得卡券api_ticket,不强制刷新卡券api_ticket + * + * @return 卡券api_ticket + * @throws WxErrorException + * @see #getCardApiTicket(boolean) + */ + @Override + public String getCardApiTicket() throws WxErrorException { + return getCardApiTicket(false); + } + + /** + *
+   * 获得卡券api_ticket
+   * 获得时会检查卡券apiToken是否过期,如果过期了,那么就刷新一下,否则就什么都不干
+   *
+   * 详情请见:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html#.E9.99.84.E5.BD
+   * .954-.E5.8D.A1.E5.88.B8.E6.89.A9.E5.B1.95.E5.AD.97.E6.AE.B5.E5.8F.8A.E7.AD.BE.E5.90.8D.E7.94
+   * .9F.E6.88.90.E7.AE.97.E6.B3.95
+   * 
+ * + * @param forceRefresh 强制刷新 + * @return 卡券api_ticket + * @throws WxErrorException + */ + @Override + public String getCardApiTicket(boolean forceRefresh) throws WxErrorException { + if (forceRefresh) { + wxMpConfigStorage.expireCardApiTicket(); + } + if (wxMpConfigStorage.isCardApiTicketExpired()) { + synchronized (globalCardApiTicketRefreshLock) { + if (wxMpConfigStorage.isCardApiTicketExpired()) { + String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=wx_card"; + String responseContent = execute(new JoddGetRequestExecutor(), url, null); + JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent))); + JsonObject tmpJsonObject = tmpJsonElement.getAsJsonObject(); + String cardApiTicket = tmpJsonObject.get("ticket").getAsString(); + int expiresInSeconds = tmpJsonObject.get("expires_in").getAsInt(); + wxMpConfigStorage.updateCardApiTicket(cardApiTicket, expiresInSeconds); + } + } + } + return wxMpConfigStorage.getCardApiTicket(); + } + + /** + *
+   * 创建调用卡券api时所需要的签名
+   *
+   * 详情请见:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html#.E9.99.84.E5.BD
+   * .954-.E5.8D.A1.E5.88.B8.E6.89.A9.E5.B1.95.E5.AD.97.E6.AE.B5.E5.8F.8A.E7.AD.BE.E5.90.8D.E7.94
+   * .9F.E6.88.90.E7.AE.97.E6.B3.95
+   * 
+ * + * @param optionalSignParam 参与签名的参数数组。 + * 可以为下列字段:app_id, card_id, card_type, code, openid, location_id + * @return 卡券Api签名对象 + */ + @Override + public WxCardApiSignature createCardApiSignature(String... optionalSignParam) throws + WxErrorException { + long timestamp = System.currentTimeMillis() / 1000; + String nonceStr = RandomUtils.getRandomStr(); + String cardApiTicket = getCardApiTicket(false); + + String[] signParam = Arrays.copyOf(optionalSignParam, optionalSignParam.length + 3); + signParam[optionalSignParam.length] = String.valueOf(timestamp); + signParam[optionalSignParam.length + 1] = nonceStr; + signParam[optionalSignParam.length + 2] = cardApiTicket; + try { + String signature = SHA1.gen(signParam); + WxCardApiSignature cardApiSignature = new WxCardApiSignature(); + cardApiSignature.setTimestamp(timestamp); + cardApiSignature.setNonceStr(nonceStr); + cardApiSignature.setSignature(signature); + return cardApiSignature; + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + } + + /** + * 卡券Code解码 + * + * @param encryptCode 加密Code,通过JSSDK的chooseCard接口获得 + * @return 解密后的Code + * @throws WxErrorException + */ + @Override + public String decryptCardCode(String encryptCode) throws WxErrorException { + String url = "https://api.weixin.qq.com/card/code/decrypt"; + JsonObject param = new JsonObject(); + param.addProperty("encrypt_code", encryptCode); + String responseContent = post(url, param.toString()); + JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent))); + JsonObject tmpJsonObject = tmpJsonElement.getAsJsonObject(); + JsonPrimitive jsonPrimitive = tmpJsonObject.getAsJsonPrimitive("code"); + return jsonPrimitive.getAsString(); + } + + /** + * 卡券Code查询 + * + * @param cardId 卡券ID代表一类卡券 + * @param code 单张卡券的唯一标准 + * @param checkConsume 是否校验code核销状态,填入true和false时的code异常状态返回数据不同 + * @return WxMpCardResult对象 + * @throws WxErrorException + */ + @Override + public WxMpCardResult queryCardCode(String cardId, String code, boolean checkConsume) throws WxErrorException { + String url = "https://api.weixin.qq.com/card/code/get"; + JsonObject param = new JsonObject(); + param.addProperty("card_id", cardId); + param.addProperty("code", code); + param.addProperty("check_consume", checkConsume); + String responseContent = post(url, param.toString()); + JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent))); + return WxMpGsonBuilder.INSTANCE.create().fromJson(tmpJsonElement, + new TypeToken() { + }.getType()); + } + + /** + * 卡券Code核销。核销失败会抛出异常 + * + * @param code 单张卡券的唯一标准 + * @throws WxErrorException + */ + @Override + public void consumeCardCode(String code) throws WxErrorException { + String url = "https://api.weixin.qq.com/card/code/consume"; + JsonObject param = new JsonObject(); + param.addProperty("code", code); + post(url, param.toString()); + } + + /** + * 卡券Mark接口。 + * 开发者在帮助消费者核销卡券之前,必须帮助先将此code(卡券串码)与一个openid绑定(即mark住), + * 才能进一步调用核销接口,否则报错。 + * + * @param code 卡券的code码 + * @param cardId 卡券的ID + * @param openId 用券用户的openid + * @param isMark 是否要mark(占用)这个code,填写true或者false,表示占用或解除占用 + * @throws WxErrorException + */ + @Override + public void markCardCode(String code, String cardId, String openId, boolean isMark) throws + WxErrorException { + String url = "https://api.weixin.qq.com/card/code/mark"; + JsonObject param = new JsonObject(); + param.addProperty("code", code); + param.addProperty("card_id", cardId); + param.addProperty("openid", openId); + param.addProperty("is_mark", isMark); + String responseContent = post(url, param.toString()); + JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent))); + WxMpCardResult cardResult = WxMpGsonBuilder.INSTANCE.create().fromJson(tmpJsonElement, + new TypeToken() { }.getType()); + if (!cardResult.getErrorCode().equals("0")) { + log.warn("朋友的券mark失败:{}", cardResult.getErrorMsg()); + } + } } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpCard.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpCard.java new file mode 100644 index 00000000..d530fbe8 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpCard.java @@ -0,0 +1,72 @@ +package me.chanjar.weixin.mp.bean; + + +/** + * 微信卡券 + * + * @author YuJian + * @version 15/11/11 + */ +public class WxMpCard { + + private String cardId; + + private Long beginTime; + + private Long endTime; + + private String userCardStatus; + + private Boolean canConsume; + + public String getCardId() { + return cardId; + } + + public void setCardId(String cardId) { + this.cardId = cardId; + } + + public Long getBeginTime() { + return beginTime; + } + + public void setBeginTime(Long beginTime) { + this.beginTime = beginTime; + } + + public Long getEndTime() { + return endTime; + } + + public void setEndTime(Long endTime) { + this.endTime = endTime; + } + + public String getUserCardStatus() { + return userCardStatus; + } + + public void setUserCardStatus(String userCardStatus) { + this.userCardStatus = userCardStatus; + } + + public Boolean getCanConsume() { + return canConsume; + } + + public void setCanConsume(Boolean canConsume) { + this.canConsume = canConsume; + } + + @Override + public String toString() { + return "WxMpCard{" + + "cardId='" + cardId + '\'' + + ", beginTime=" + beginTime + + ", endTime=" + endTime + + ", userCardStatus='" + userCardStatus + '\'' + + ", canConsume=" + canConsume + + '}'; + } +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlMessage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlMessage.java index 8796b110..9f42ffc7 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlMessage.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlMessage.java @@ -150,6 +150,31 @@ public class WxMpXmlMessage implements Serializable { @XStreamAlias("ErrorCount") private Integer errorCount; + /////////////////////////////////////// + // 卡券相关事件推送 + /////////////////////////////////////// + @XStreamAlias("CardId") + @XStreamConverter(value=XStreamCDataConverter.class) + private String cardId; + + @XStreamAlias("FriendUserName") + @XStreamConverter(value=XStreamCDataConverter.class) + private String friendUserName; + + @XStreamAlias("IsGiveByFriend") + private Integer isGiveByFriend; // 是否为转赠,1代表是,0代表否 + + @XStreamAlias("UserCardCode") + @XStreamConverter(value=XStreamCDataConverter.class) + private String userCardCode; + + @XStreamAlias("OldUserCardCode") + @XStreamConverter(value=XStreamCDataConverter.class) + private String oldUserCardCode; + + @XStreamAlias("OuterId") + private Integer outerId; + @XStreamAlias("ScanCodeInfo") private ScanCodeInfo scanCodeInfo = new ScanCodeInfo(); @@ -456,6 +481,54 @@ public class WxMpXmlMessage implements Serializable { this.errorCount = errorCount; } + public String getCardId() { + return cardId; + } + + public void setCardId(String cardId) { + this.cardId = cardId; + } + + public String getFriendUserName() { + return friendUserName; + } + + public void setFriendUserName(String friendUserName) { + this.friendUserName = friendUserName; + } + + public Integer getIsGiveByFriend() { + return isGiveByFriend; + } + + public void setIsGiveByFriend(Integer isGiveByFriend) { + this.isGiveByFriend = isGiveByFriend; + } + + public String getUserCardCode() { + return userCardCode; + } + + public void setUserCardCode(String userCardCode) { + this.userCardCode = userCardCode; + } + + public String getOldUserCardCode() { + return oldUserCardCode; + } + + public void setOldUserCardCode(String oldUserCardCode) { + this.oldUserCardCode = oldUserCardCode; + } + + public Integer getOuterId() { + return outerId; + } + + public void setOuterId(Integer outerId) { + this.outerId = outerId; + } + public WxMpXmlMessage.ScanCodeInfo getScanCodeInfo() { return scanCodeInfo; } @@ -652,6 +725,11 @@ public class WxMpXmlMessage implements Serializable { ", filterCount=" + filterCount + ", sentCount=" + sentCount + ", errorCount=" + errorCount + + ", cardId='" + cardId + '\'' + + ", isGiveByFriend=" + isGiveByFriend + + ", userCardCode='" + userCardCode + '\'' + + ", oldUserCardCode='" + oldUserCardCode + '\'' + + ", outerId=" + outerId + ", scanCodeInfo=" + scanCodeInfo + ", sendPicsInfo=" + sendPicsInfo + ", sendLocationInfo=" + sendLocationInfo + diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/result/WxMpCardResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/result/WxMpCardResult.java new file mode 100644 index 00000000..e6cd9a5f --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/result/WxMpCardResult.java @@ -0,0 +1,87 @@ +package me.chanjar.weixin.mp.bean.result; + +import me.chanjar.weixin.mp.bean.WxMpCard; + +import java.io.Serializable; + +/** + * 卡券查询Code,核销Code接口返回结果 + * + * @author YuJian + * @version 15/11/11 + */ +public class WxMpCardResult implements Serializable { + + private String errorCode; + + private String errorMsg; + + private String openId; + + private WxMpCard card; + + private String userCardStatus; + + private Boolean canConsume; + + public String getErrorCode() { + return errorCode; + } + + public void setErrorCode(String errorCode) { + this.errorCode = errorCode; + } + + public String getErrorMsg() { + return errorMsg; + } + + public void setErrorMsg(String errorMsg) { + this.errorMsg = errorMsg; + } + + public String getOpenId() { + return openId; + } + + public void setOpenId(String openId) { + this.openId = openId; + } + + public WxMpCard getCard() { + return card; + } + + public void setCard(WxMpCard card) { + this.card = card; + } + + @Override + public String toString() { + return "WxMpCardResult{" + + "errorCode='" + errorCode + '\'' + + ", errorMsg='" + errorMsg + '\'' + + ", openId='" + openId + '\'' + + ", card=" + card + + ", userCardStatus='" + userCardStatus + '\'' + + ", canConsume=" + canConsume + + '}'; + } + + public String getUserCardStatus() { + return userCardStatus; + } + + public void setUserCardStatus(String userCardStatus) { + this.userCardStatus = userCardStatus; + } + + public Boolean getCanConsume() { + return canConsume; + } + + public void setCanConsume(Boolean canConsume) { + this.canConsume = canConsume; + } + +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpCardGsonAdapter.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpCardGsonAdapter.java new file mode 100644 index 00000000..dab414a3 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpCardGsonAdapter.java @@ -0,0 +1,38 @@ +package me.chanjar.weixin.mp.util.json; + +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.reflect.TypeToken; +import me.chanjar.weixin.common.util.json.GsonHelper; +import me.chanjar.weixin.mp.bean.WxMpCard; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.reflect.Type; +import java.util.List; + +/** + * Created by YuJian on 15/11/11. + * + * @author YuJian + * @version 15/11/11 + */ +public class WxMpCardGsonAdapter implements JsonDeserializer { + + @Override + public WxMpCard deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext + jsonDeserializationContext) throws JsonParseException { + WxMpCard card = new WxMpCard(); + JsonObject jsonObject = jsonElement.getAsJsonObject(); + + card.setCardId(GsonHelper.getString(jsonObject, "card_id")); + card.setBeginTime(GsonHelper.getLong(jsonObject, "begin_time")); + card.setEndTime(GsonHelper.getLong(jsonObject, "end_time")); + + return card; + } + +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpCardResultGsonAdapter.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpCardResultGsonAdapter.java new file mode 100644 index 00000000..be1a12da --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpCardResultGsonAdapter.java @@ -0,0 +1,45 @@ +package me.chanjar.weixin.mp.util.json; + +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.reflect.TypeToken; +import me.chanjar.weixin.common.util.json.GsonHelper; +import me.chanjar.weixin.mp.bean.WxMpCard; +import me.chanjar.weixin.mp.bean.result.WxMpCardResult; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.reflect.Type; +import java.text.ParseException; +import java.util.List; + +/** + * Created by YuJian on 15/11/11. + * + * @author YuJian + * @version 15/11/11 + */ +public class WxMpCardResultGsonAdapter implements JsonDeserializer { + @Override + public WxMpCardResult deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException { + WxMpCardResult cardResult = new WxMpCardResult(); + JsonObject jsonObject = jsonElement.getAsJsonObject(); + + cardResult.setOpenId(GsonHelper.getString(jsonObject, "openid")); + cardResult.setErrorCode(GsonHelper.getString(jsonObject, "errcode")); + cardResult.setErrorMsg(GsonHelper.getString(jsonObject, "errmsg")); + cardResult.setCanConsume(GsonHelper.getBoolean(jsonObject, "can_consume")); + cardResult.setUserCardStatus(GsonHelper.getString(jsonObject, "user_card_status")); + + WxMpCard card = WxMpGsonBuilder.INSTANCE.create().fromJson(jsonObject.get("card"), + new TypeToken() { + }.getType()); + + cardResult.setCard(card); + + return cardResult; + } +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpGsonBuilder.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpGsonBuilder.java index 20f8d9d4..316f22f5 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpGsonBuilder.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpGsonBuilder.java @@ -38,6 +38,8 @@ public class WxMpGsonBuilder { INSTANCE.registerTypeAdapter(WxMpMaterialNewsBatchGetResult.WxMaterialNewsBatchGetNewsItem.class, new WxMpMaterialNewsBatchGetGsonItemAdapter()); INSTANCE.registerTypeAdapter(WxMpMaterialFileBatchGetResult.class, new WxMpMaterialFileBatchGetGsonAdapter()); INSTANCE.registerTypeAdapter(WxMpMaterialFileBatchGetResult.WxMaterialFileBatchGetNewsItem.class, new WxMpMaterialFileBatchGetGsonItemAdapter()); + INSTANCE.registerTypeAdapter(WxMpCardResult.class, new WxMpCardResultGsonAdapter()); + INSTANCE.registerTypeAdapter(WxMpCard.class, new WxMpCardGsonAdapter()); } public static Gson create() {