diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMarketingService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMarketingService.java new file mode 100644 index 000000000..f59158b2b --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMarketingService.java @@ -0,0 +1,71 @@ +package me.chanjar.weixin.mp.api; + +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.mp.bean.marketing.WxMpAdLeadFilter; +import me.chanjar.weixin.mp.bean.marketing.WxMpAdLeadResult; +import me.chanjar.weixin.mp.bean.marketing.WxMpUserAction; +import me.chanjar.weixin.mp.bean.marketing.WxMpUserActionSet; + +import java.io.IOException; +import java.util.Date; +import java.util.List; + +/** + *
+ * 微信营销接口
+ * 
+ * + * @author 007 + */ +public interface WxMpMarketingService { + String API_URL_PREFIX = "https://api.weixin.qq.com/marketing/"; + + /** + *
+   * 创建数据源
+   * 接口调用请求说明
+   * https://wximg.qq.com/wxp/pdftool/get.html?id=rkalQXDBM&pa=39
+   * 
+ * + * @param type 用户行为源类型 + * @param name 用户行为源名称 必填 + * @param description 用户行为源描述,字段长度最小 1 字节,长度最大 128 字节 + */ + long addUserActionSets(String type, String name, String description) throws WxErrorException; + + /** + *
+   * 获取数据源信息
+   * 
+ * + * @param userActionSetId 数据源唯一ID + */ + List getUserActionSets(Long userActionSetId) throws WxErrorException; + + /** + * 回传数据 + * 接口调用请求说明 + * https://wximg.qq.com/wxp/pdftool/get.html?id=rkalQXDBM&pa=39 + * + * @param actions 用户行为源类型 + */ + void addUserAction(List actions) throws WxErrorException; + + /** + *
+   * 获取朋友圈销售线索数据接口
+   * 接口调用请求说明
+   *
+   * http请求方式: POST
+   * http://api.weixin.qq.com/cgi-bin/media/voice/translatecontent?access_token=ACCESS_TOKEN&lfrom=xxx<o=xxx
+   *
+   * 
+ * + * @param beginDate 开始日期 + * @param endDate 结束日期 + * @param filtering 过滤条件 + * @param page 页码,获取指定页数据 + * @param page_size 一页获取的数据条数(1-100) + */ + WxMpAdLeadResult getAdLeads(Date beginDate, Date endDate, List filtering, Integer page, Integer page_size) throws WxErrorException, IOException; +} 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 fead289a3..991e1de15 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 @@ -411,6 +411,13 @@ public interface WxMpService { */ WxMpMemberCardService getMemberCardService(); + /** + * 返回营销相关接口方法的实现类对象,以方便调用其各个接口. + * + * @return WxMpMarketingService + */ + WxMpMarketingService getMarketingService(); + /** * 初始化http请求对象. */ @@ -473,4 +480,6 @@ public interface WxMpService { void setMassMessageService(WxMpMassMessageService massMessageService); void setAiOpenService(WxMpAiOpenService aiOpenService); + + void setMarketingService(WxMpMarketingService marketingService); } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/BaseWxMpServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/BaseWxMpServiceImpl.java index f72046165..2db223c33 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/BaseWxMpServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/BaseWxMpServiceImpl.java @@ -3,6 +3,7 @@ package me.chanjar.weixin.mp.api.impl; import java.io.IOException; import java.util.concurrent.locks.Lock; +import me.chanjar.weixin.mp.api.*; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -24,26 +25,6 @@ import me.chanjar.weixin.common.util.http.RequestHttp; import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor; import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor; import me.chanjar.weixin.common.util.http.URIUtil; -import me.chanjar.weixin.mp.api.WxMpAiOpenService; -import me.chanjar.weixin.mp.api.WxMpCardService; -import me.chanjar.weixin.mp.api.WxMpConfigStorage; -import me.chanjar.weixin.mp.api.WxMpDataCubeService; -import me.chanjar.weixin.mp.api.WxMpDeviceService; -import me.chanjar.weixin.mp.api.WxMpKefuService; -import me.chanjar.weixin.mp.api.WxMpMassMessageService; -import me.chanjar.weixin.mp.api.WxMpMaterialService; -import me.chanjar.weixin.mp.api.WxMpMemberCardService; -import me.chanjar.weixin.mp.api.WxMpMenuService; -import me.chanjar.weixin.mp.api.WxMpQrcodeService; -import me.chanjar.weixin.mp.api.WxMpService; -import me.chanjar.weixin.mp.api.WxMpShakeService; -import me.chanjar.weixin.mp.api.WxMpStoreService; -import me.chanjar.weixin.mp.api.WxMpSubscribeMsgService; -import me.chanjar.weixin.mp.api.WxMpTemplateMsgService; -import me.chanjar.weixin.mp.api.WxMpUserBlacklistService; -import me.chanjar.weixin.mp.api.WxMpUserService; -import me.chanjar.weixin.mp.api.WxMpUserTagService; -import me.chanjar.weixin.mp.api.WxMpWifiService; import me.chanjar.weixin.mp.bean.WxMpSemanticQuery; import me.chanjar.weixin.mp.bean.result.WxMpCurrentAutoReplyInfo; import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken; @@ -81,6 +62,7 @@ public abstract class BaseWxMpServiceImpl implements WxMpService, RequestH private WxMpMassMessageService massMessageService = new WxMpMassMessageServiceImpl(this); private WxMpAiOpenService aiOpenService = new WxMpAiOpenServiceImpl(this); private WxMpWifiService wifiService = new WxMpWifiServiceImpl(this); + private WxMpMarketingService marketingService = new WxMpMarketingServiceImpl(this); private int retrySleepMillis = 1000; private int maxRetryTimes = 5; @@ -545,4 +527,14 @@ public abstract class BaseWxMpServiceImpl implements WxMpService, RequestH public WxMpWifiService getWifiService() { return this.wifiService; } + + @Override + public WxMpMarketingService getMarketingService() { + return this.marketingService; + } + + @Override + public void setMarketingService(WxMpMarketingService marketingService) { + this.marketingService = marketingService; + } } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMarketingServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMarketingServiceImpl.java new file mode 100644 index 000000000..91e7d4c1b --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMarketingServiceImpl.java @@ -0,0 +1,92 @@ +package me.chanjar.weixin.mp.api.impl; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.mp.api.WxMpMarketingService; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.marketing.WxMpAdLeadFilter; +import me.chanjar.weixin.mp.bean.marketing.WxMpAdLeadResult; +import me.chanjar.weixin.mp.bean.marketing.WxMpUserAction; +import me.chanjar.weixin.mp.bean.marketing.WxMpUserActionSet; +import org.apache.commons.lang3.time.DateFormatUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.Date; +import java.util.List; + +/** + * @author 007 + */ +public class WxMpMarketingServiceImpl implements WxMpMarketingService { + protected final Logger log = LoggerFactory.getLogger(this.getClass()); + private WxMpService wxMpService; + + public WxMpMarketingServiceImpl(WxMpService wxMpService) { + this.wxMpService = wxMpService; + } + + @Override + public long addUserActionSets(String type, String name, String description) throws WxErrorException { + String url = API_URL_PREFIX + "user_action_sets/add?version=v1.0"; + JsonObject json = new JsonObject(); + json.addProperty("type", type); + json.addProperty("name", name); + json.addProperty("description", description); + String responseContent = wxMpService.post(url, json.toString()); + JsonElement tmpJsonElement = new JsonParser().parse(responseContent); + return tmpJsonElement.getAsJsonObject().get("data").getAsJsonObject().get("user_action_set_id").getAsLong(); + } + + @Override + public List getUserActionSets(Long userActionSetId) throws WxErrorException { + String url = API_URL_PREFIX + "user_action_sets/get"; + String responseContent = wxMpService.get(url, "version=v1.0&user_action_set_id=" + userActionSetId); + return WxMpUserActionSet.fromJson(responseContent); + } + + @Override + public void addUserAction(List actions) throws WxErrorException { + String url = API_URL_PREFIX + "user_actions/add?version=v1.0"; + JsonArray json = new JsonArray(); + for (WxMpUserAction action : actions) { + json.add(action.toJsonObject()); + } + wxMpService.post(url, json.toString()); + } + + @Override + public WxMpAdLeadResult getAdLeads(Date beginDate, Date endDate, List filtering, Integer page, Integer page_size) throws WxErrorException, IOException { + Date today = new Date(); + if (beginDate == null) { + beginDate = today; + } + if (endDate == null) { + endDate = today; + } + String url = API_URL_PREFIX + "wechat_ad_leads/get"; + String params = "version=v1.0"; + JsonObject dateRange = new JsonObject(); + dateRange.addProperty("begin_date", DateFormatUtils.format(beginDate, "yyyy-MM-dd")); + dateRange.addProperty("end_date", DateFormatUtils.format(endDate, "yyyy-MM-dd")); + params += "&date_range=" + URLEncoder.encode(dateRange.toString(), StandardCharsets.UTF_8.name()); + params += "&page=" + page; + params += "&page_size=" + page_size; + if (filtering != null) { + JsonArray filterJson = new JsonArray(); + for (WxMpAdLeadFilter filter : filtering) { + filterJson.add(filter.toJsonObject()); + } + params += "&filtering=" + URLEncoder.encode(filterJson.toString(), StandardCharsets.UTF_8.name()); + ; + } + String responseContent = wxMpService.get(url, params); + return WxMpAdLeadResult.fromJson(responseContent); + } +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/marketing/WxMpAdLead.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/marketing/WxMpAdLead.java new file mode 100644 index 000000000..868d22a96 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/marketing/WxMpAdLead.java @@ -0,0 +1,55 @@ +package me.chanjar.weixin.mp.bean.marketing; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +/** + * @author 007 + */ +@Data +public class WxMpAdLead implements Serializable { + private static final long serialVersionUID = -8889087268596440407L; + /** + * 点击ID + */ + @SerializedName("click_id") + private String click_id; + /** + * 广告组ID + */ + @SerializedName("adgroup_id") + private Long adgroup_id; + /** + * 广告组名称 + */ + @SerializedName("adgroup_name") + private String adgroup_name; + /** + * 推广计划ID + */ + @SerializedName("campaign_id") + private Long campaign_id; + /** + * 推广计划名称 + */ + @SerializedName("campaign_name") + private String campaign_name; + /** + * 代理ID + */ + @SerializedName("agency_id") + private String agency_id; + /** + * 代理名称 + */ + @SerializedName("agency_name") + private String agency_name; + /** + * 销售线索信息 + */ + @SerializedName("leads_info") + private List leads_info; +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/marketing/WxMpAdLeadFilter.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/marketing/WxMpAdLeadFilter.java new file mode 100644 index 000000000..392302533 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/marketing/WxMpAdLeadFilter.java @@ -0,0 +1,32 @@ +package me.chanjar.weixin.mp.bean.marketing; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +/** + * @author 007 + */ +@Data +public class WxMpAdLeadFilter implements Serializable { + private static final long serialVersionUID = -1469998986497327439L; + private String field; + private String operator; + private List values; + + public JsonObject toJsonObject() { + JsonObject json = new JsonObject(); + json.addProperty("field", field); + json.addProperty("operator", operator); + if (values != null) { + JsonArray vs = new JsonArray(); + for (String value : values) { + vs.add(value); + } + } + return json; + } +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/marketing/WxMpAdLeadInfo.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/marketing/WxMpAdLeadInfo.java new file mode 100644 index 000000000..859a0dca5 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/marketing/WxMpAdLeadInfo.java @@ -0,0 +1,18 @@ +package me.chanjar.weixin.mp.bean.marketing; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author 007 + */ +@Data +public class WxMpAdLeadInfo implements Serializable { + private static final long serialVersionUID = -6462312242780350479L; + @SerializedName("key") + private String key; + @SerializedName("value") + private String value; +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/marketing/WxMpAdLeadPageInfo.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/marketing/WxMpAdLeadPageInfo.java new file mode 100644 index 000000000..296a3fef8 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/marketing/WxMpAdLeadPageInfo.java @@ -0,0 +1,23 @@ +package me.chanjar.weixin.mp.bean.marketing; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author 007 + */ +@Data +public class WxMpAdLeadPageInfo implements Serializable { + private static final long serialVersionUID = -896765006445604780L; + @SerializedName("page") + private Integer page; + @SerializedName("page_size") + private Integer pageSize; + @SerializedName("total_page") + private Integer totalPage; + @SerializedName("total_number") + private Integer totalNumber; + +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/marketing/WxMpAdLeadResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/marketing/WxMpAdLeadResult.java new file mode 100644 index 000000000..61805018b --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/marketing/WxMpAdLeadResult.java @@ -0,0 +1,32 @@ +package me.chanjar.weixin.mp.bean.marketing; + +import com.google.gson.JsonParser; +import com.google.gson.annotations.SerializedName; +import com.google.gson.reflect.TypeToken; +import lombok.Data; +import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + * @author 007 + */ +@Data +public class WxMpAdLeadResult implements Serializable { + private static final long serialVersionUID = -1526796632563660821L; + protected static final JsonParser JSON_PARSER = new JsonParser(); + + @SerializedName("page_info") + private WxMpAdLeadPageInfo pageInfo; + @SerializedName("list") + private List adLeads; + + public static WxMpAdLeadResult fromJson(String json) { + + return WxMpGsonBuilder.create().fromJson( + JSON_PARSER.parse(json).getAsJsonObject().get("data"), + new TypeToken() { + }.getType()); + } +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/marketing/WxMpUserAction.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/marketing/WxMpUserAction.java new file mode 100644 index 000000000..69fced907 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/marketing/WxMpUserAction.java @@ -0,0 +1,39 @@ +package me.chanjar.weixin.mp.bean.marketing; + +import com.google.gson.JsonObject; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author 007 + */ + +@Data +public class WxMpUserAction implements Serializable { + private static final long serialVersionUID = 7042393762652152209L; + private Long userActionSetId; + private String url; + private Boolean actionTime; + private String actionType; + private String clickId; + private Integer actionParam; + + public JsonObject toJsonObject() { + JsonObject json = new JsonObject(); + json.addProperty("user_action_set_id", this.userActionSetId); + json.addProperty("url", this.url); + json.addProperty("action_time", this.actionTime); + if (this.clickId != null) { + JsonObject traceJson = new JsonObject(); + traceJson.addProperty("click_id", this.clickId); + json.add("trace", traceJson); + } + if (this.actionParam != null) { + JsonObject actionParamJson = new JsonObject(); + actionParamJson.addProperty("value", actionParam); + json.add("action_param", actionParamJson); + } + return json; + } +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/marketing/WxMpUserActionSet.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/marketing/WxMpUserActionSet.java new file mode 100644 index 000000000..84b0f4bba --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/marketing/WxMpUserActionSet.java @@ -0,0 +1,56 @@ +package me.chanjar.weixin.mp.bean.marketing; + +import com.google.gson.JsonParser; +import com.google.gson.annotations.SerializedName; +import com.google.gson.reflect.TypeToken; +import lombok.Data; +import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + * @author 007 + */ + +@Data +public class WxMpUserActionSet implements Serializable { + private static final long serialVersionUID = 1979861770645159905L; + protected static final JsonParser JSON_PARSER = new JsonParser(); + + /** + * user_action_set_id + * 用户行为源名称 + */ + @SerializedName("user_action_set_id") + private Long userActionSetId; + + /** + * title. + * 用户行为源描述 + */ + @SerializedName("description") + private String description; + + /** + * activate_status. + * 数据接入状态, true 表示已接入, false 表示未接入 + */ + @SerializedName("activate_status") + private Boolean activate_status; + + /** + * created_time. + * 创建时间 + */ + @SerializedName("created_time") + private String createdTime; + + public static List fromJson(String json) { + return WxMpGsonBuilder.create().fromJson( + JSON_PARSER.parse(json).getAsJsonObject().get("data").getAsJsonObject().get("list"), + new TypeToken>() { + }.getType()); + } + +} diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/result/WxMpAdLeadResultTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/result/WxMpAdLeadResultTest.java new file mode 100644 index 000000000..faf354f11 --- /dev/null +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/result/WxMpAdLeadResultTest.java @@ -0,0 +1,75 @@ +package me.chanjar.weixin.mp.bean.result; + +import me.chanjar.weixin.mp.bean.marketing.WxMpAdLeadResult; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertTrue; + +/** + * @author 007 + */ +public class WxMpAdLeadResultTest { + @Test + public void testFromJson() throws Exception { + String json = "{\n" + + "\t\"data\": {\n" + + "\t\t\"page_info\": {\n" + + "\t\t\t\"total_number\": 39,\n" + + "\t\t\t\"page\": 1,\n" + + "\t\t\t\"page_size\": 100,\n" + + "\t\t\t\"total_page\": 1\n" + + "\t\t},\n" + + "\t\t\"list\": [{\n" + + "\t\t\t\"click_id\": \"\",\n" + + "\t\t\t\"adgroup_name\": \"\",\n" + + "\t\t\t\"campaign_id\": 1800000001,\n" + + "\t\t\t\"leads_info\": [{\n" + + "\t\t\t\t\"value\": \"13800138000\",\n" + + "\t\t\t\t\"key\": \"电话号码\"\n" + + "\t\t\t}, {\n" + + "\t\t\t\t\"value\": \"2019-03-14 00:54:34\",\n" + + "\t\t\t\t\"key\": \"提交时间\"\n" + + "\t\t\t}, {\n" + + "\t\t\t\t\"value\": \"123\",\n" + + "\t\t\t\t\"key\": \"自定义问题\"\n" + + "\t\t\t}],\n" + + "\t\t\t\"agency_name\": \"\",\n" + + "\t\t\t\"agency_id\": \"\",\n" + + "\t\t\t\"campaign_name\": \"\",\n" + + "\t\t\t\"adgroup_id\": 1800000002\n" + + "\t\t}, {\n" + + "\t\t\t\"click_id\": \"\",\n" + + "\t\t\t\"adgroup_name\": \"\",\n" + + "\t\t\t\"campaign_id\": 1800000001,\n" + + "\t\t\t\"leads_info\": [{\n" + + "\t\t\t\t\"value\": \"13800138001\",\n" + + "\t\t\t\t\"key\": \"电话号码\"\n" + + "\t\t\t}, {\n" + + "\t\t\t\t\"value\": \"2019-03-14 02:10:39\",\n" + + "\t\t\t\t\"key\": \"提交时间\"\n" + + "\t\t\t}, {\n" + + "\t\t\t\t\"value\": \"321\",\n" + + "\t\t\t\t\"key\": \"自定义问题\"\n" + + "\t\t\t}],\n" + + "\t\t\t\"agency_name\": \"\",\n" + + "\t\t\t\"agency_id\": \"\",\n" + + "\t\t\t\"campaign_name\": \"\",\n" + + "\t\t\t\"adgroup_id\": 1800000002\n" + + "\t\t}]\n" + + "\t},\n" + + "\t\"errcode\": 0,\n" + + "\t\"errmsg\": \"\"\n" + + "}"; + + WxMpAdLeadResult adLeadResult = WxMpAdLeadResult.fromJson(json); + + assertNotNull(adLeadResult); + assertNotNull(adLeadResult.getPageInfo()); + assertNotNull(adLeadResult.getAdLeads()); + assertTrue(adLeadResult.getAdLeads().size() > 0); + + System.out.println(adLeadResult); + } + +}