Commit 9367305e authored by dingjy's avatar dingjy

modify

parent 966964e8
package com.lwby.marketing.att;
import com.alibaba.fastjson2.JSONObject;
import com.lwby.marketing.flow.FlowExecutor;
import com.lwby.marketing.flow.Rule;
import com.lwby.marketing.vo.BookStoreEvent;
import com.lwby.marketing.vo.NovelAction;
import com.lwby.marketing.vo.StoryNovelAction;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
@Component
public class NovelAttributionMain {
@Resource
ApplicationContext ctx;
public FlowExecutor<NovelAction> executorNovel;
public FlowExecutor<StoryNovelAction> executorStoryNovel;
@PostConstruct
public void init() {
executorNovel = new FlowExecutor<>(ctx, Rule.create().THEN("setup").THEN("prize").THEN("store").THEN("checkerfirst").SWITCH("cross","plan","channel"));
executorStoryNovel = new FlowExecutor<>(ctx, Rule.create().THEN("setupStoreNovel").THEN("storeNovelStore").THEN("checkerNovelStorefirst").SWITCH("payspdu").THEN("uploadcall"));
}
public void test(){
String msg = "{\"bookStoreEvent\":1,\"clientInfo\":{\"channel\":220605094,\"clientIp\":\"171.14.28.126\",\"dID\":\"aad1da5913749ee5\",\"ddid\":\"null\",\"firm\":\"HUAWEI\",\"fixVersion\":12,\"mainVersion\":2,\"oaid\":\"f243f86a-8887-44df-92f3-7efed504b6f7\",\"os\":\"0\",\"phoneModel\":\"NOH-AN00\",\"pkv\":1,\"platformGroupId\":6,\"platformId\":6,\"pm\":\"NOH-AN00\",\"screenSize\":\"1152*2256\",\"sessionid\":\"wnL6tSDnvCjwnLtNJRDK299Z_jQEkUqSj\",\"signVersion\":2,\"subVersion\":27,\"systemVersion\":\"12\",\"ua\":\"Mozilla/5.0 (Linux; Android 12; NOH-AN00 Build/HUAWEINOH-AN00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/99.0.4844.88 Mobile Safari/537.36\",\"user\":{\"career\":\"\",\"channel\":220605094,\"deviceId\":\"aad1da5913749ee5\",\"experience\":1,\"gender\":\"M\",\"headImage\":\"http://cdn.ibreader.com/group1/M00/56/07/rBH0olunjiKAJCYCAAAQJEqQEcM308.png\",\"id\":133842748,\"isKaiqiUser\":false,\"isMajia\":false,\"isPrivate\":false,\"lastLogin\":1705980630000,\"level\":0,\"mainversion\":2,\"nickname\":\"书友742606\",\"platformId\":6,\"registrationDate\":1705980630000,\"subversion\":27,\"userStatus\":0,\"username\":\"bduXujqDcJbCZD\"},\"version\":\"6.2.27.12.220605094\",\"visitor\":\"wnL6tSDnvCjwnLtNJRDK299Z_jQEkUqSj\",\"xClient\":\"dID=aad1da5913749ee5;os=0;firm=HUAWEI;webVersion=new;version=6.2.27.12.220605094;username=wnL6tSDnvCjwnLtNJRDK299Z_jQEkUqSj;ddid=null;sv=12;pm=NOH-AN00;ss=1152*2256;signVersion=2;androidosv=31;oaid=f243f86a-8887-44df-92f3-7efed504b6f7;pkv=1;\"},\"createTime\":1705980632408,\"extraData\":{},\"id\":\"fd17b7d0-2ec2-4392-8980-170dbdf36e69\"}";
BookStoreEvent event = JSONObject.parseObject(msg, BookStoreEvent.class);
NovelAction action = new NovelAction(event.getClientInfo(),msg);
try {
executorNovel.execute(action);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// @KafkaListener(topics = "registerMediaEvent1", groupId = "test")
// public void listen(String message) {
// System.out.println("Received Message: " + message);
//
// BookStoreEvent event = JSONObject.parseObject(message, BookStoreEvent.class);
// NovelAction action = new NovelAction(event.getClientInfo(),message);
//
// try {
// executorNovel.execute(action);
// } catch (Exception e) {
// throw new RuntimeException(e);
// }
// }
}
package com.lwby.marketing.att.novel;
package com.lwby.marketing.att;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alicp.jetcache.anno.CacheRefresh;
import com.alicp.jetcache.anno.CacheType;
import com.alicp.jetcache.anno.Cached;
import com.google.common.collect.ImmutableMap;
import com.lwby.marketing.po.AppChannel;
import com.lwby.marketing.vo.NovelAction;
import com.lwby.marketing.vo.DeliveryDeviceInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.kafka.support.SendResult;
import org.springframework.stereotype.Component;
import org.springframework.util.concurrent.ListenableFuture;
import javax.annotation.Resource;
import java.util.Map;
......@@ -26,73 +20,19 @@ import java.util.concurrent.TimeUnit;
@Slf4j
@Component
public class UniversalProcess {
public static final String PRIZE_FLOW_PREFIX = "c:ouser:";
@Resource
JdbcTemplate lwbyJdbcTemplate;
public JdbcTemplate lwbyJdbcTemplate;
@Resource
private KafkaTemplate<String, String> kafkaTemplate;
public KafkaTemplate<String, String> kafkaTemplate;
@Resource
private RedisTemplate<String, String> redisTemplate;
public RedisTemplate<String, String> redisTemplate;
@Resource
private RedisTemplate<String,String> biRedisTemplate;
public RedisTemplate<String,String> biRedisTemplate;
/******************************************** GENERIC METHOD ***********************************************/
/**
* 通知处理结果
*/
public void notifyResult(NovelAction action, AttributionStatus status) {
DeliveryDeviceInfo ddi = action.getDeliveryDeviceInfo();
if (Objects.isNull(ddi)) {
ddi = new DeliveryDeviceInfo();
String channelStr = String.valueOf(action.getClientInfo().getChannel());
ddi.setMedia(MediaMapping.getMediaNameByChannelId(channelStr));
ddi.setAd_plan_id("0");
ddi.setAd_group_id("0");
ddi.setAd_creative_id("0");
ddi.setPlatform_id(String.valueOf(action.getPlatformId()));
ddi.setDj_channel(channelStr);
}
ddi.setOs(action.getClientInfo().getOs());
ddi.setIs_call(status.id);
ddi.setDevice_id(action.getDeviceId());
ddi.setActive_time(System.currentTimeMillis());
ddi.setChannel(String.valueOf(action.getChannelId()));
ddi.setUserId(action.getUserId());
ddi.setDevice_status(exists(PRIZE_FLOW_PREFIX.concat(String.valueOf(ddi.getUserId()))) ? 2 : 0);
String jsonString = JSONObject.toJSONString(ddi);
ListenableFuture<SendResult<String, String>> active_result = kafkaTemplate.send("ocpc_result_test", jsonString);
active_result.addCallback(
result -> log.info("归因成功[{}],归因类型[{}]", jsonString, status.desc),
ex -> log.error("归因失败[{}],归因类型[{}]", jsonString, status.desc, ex)
);
}
/******************************************** ASSEMBLE KEY ***************************************************/
public String getTotalCountKey(AttributionType attributionType, int platformId, int channelOrPlanId, int sprDedu, String dateStr) {
return String.format("%s_total_%d_%d_%d_%s", attributionType, platformId, channelOrPlanId, sprDedu, dateStr);
}
public String getCallbackCountKey(AttributionType attributionType, int platformId, int channelOrPlanId, int sprDedu, String dateStr) {
return String.format("%s_callback_%d_%d_%d_%s", attributionType, platformId, channelOrPlanId, sprDedu, dateStr);
}
public String getFirstCheckerKey(NovelAction action) {
return String.format("fc_%s_%d_%s_%s", action.getDeviceId(), action.getPlatformId(),action.getMediaName(),action.getCurrentDateStr());
}
public String buildKey(Integer platformId,String deviceId) {
return String.format("market:activeness:30:%d:%s",platformId,deviceId);
}
/******************************************** REDIS **********************************************************/
public boolean existsIsAlive(String key) {
......@@ -126,24 +66,12 @@ public class UniversalProcess {
}
/******************************************** JDBC *************************************************************/
@Cached(name="appchannel_novel", cacheType = CacheType.LOCAL)
@CacheRefresh(refresh = 300)
public Integer getAppChannel(int platformId, int channelId){
try {
return lwbyJdbcTemplate.queryForObject(String.format("select spr_dedu from app_channel where platform_id=%d and channel_id=%s ORDER BY update_time DESC LIMIT 1",platformId,String.valueOf(channelId)),Integer.class);
} catch (EmptyResultDataAccessException e) {
return null;
}
}
/******************************************** INNER CLASS ******************************************************/
/**
* 媒体ID和名称关系映射
*/
static class MediaMapping{
public static class MediaMapping{
static Map<String, String> mediaMap = ImmutableMap.<String, String>builder()
.put("11", "xiaomi")
.put("12", "huawei")
......@@ -163,8 +91,20 @@ public class UniversalProcess {
.put("33", "dystore")
.build();
static String getMediaNameByChannelId(String channelId){
public static String getMediaNameByChannelId(String channelId){
return mediaMap.get(channelId.substring(0, 2));
}
}
/******************************************** JDBC *************************************************************/
@Cached(name="appchannel_novel", cacheType = CacheType.LOCAL)
@CacheRefresh(refresh = 300)
public Integer getAppChannel(int platformId, int channelId){
try {
return lwbyJdbcTemplate.queryForObject(String.format("select spr_dedu from app_channel where platform_id=%d and channel_id=%s ORDER BY update_time DESC LIMIT 1",platformId,String.valueOf(channelId)),Integer.class);
} catch (EmptyResultDataAccessException e) {
return null;
}
}
}
\ No newline at end of file
package com.lwby.marketing.att.storynovel;
package com.lwby.marketing.att.bystory;
import com.lwby.marketing.att.novel.AttributionStatus;
......
package com.lwby.marketing.att.storynovel;
package com.lwby.marketing.att.bystory;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.lwby.marketing.att.NovelAttributionMain;
import com.lwby.marketing.vo.StoryNovelAction;
import com.lwby.marketing.vo.StoreUserUploadEventBO;
import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.kafka.listener.MessageListener;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* @author songxinyu
* @version StoreNovelPayConsumer.java, v 0.1 2024年03月05日 10:40 songxinyu Exp $
*/
@Slf4j
@Component
public class StoryNovelActiveConsumer implements MessageListener<String, String> {
public class DyStoryActiveConsumer implements MessageListener<String, String> {
@Autowired
NovelAttributionMain novelAttributionMain;
@Resource
DyStoryFlowExecutor dyStoryFlowExecutor;
@KafkaListener(topics = {"${story.novel.active.consumer.topic:testStoryNovelActive}"},groupId = "${story.novel.active.consumer.group.id:test_story_dy_active}")
@Override
......@@ -41,7 +41,7 @@ public class StoryNovelActiveConsumer implements MessageListener<String, String>
StoryNovelAction action = new StoryNovelAction(event.getClientInfo(),event.getUserId(),event.getOpenId(),event.getUserUploadEvent());
novelAttributionMain.executorStoryNovel.execute(action);
dyStoryFlowExecutor.getExecutorByStory().execute(action);
} catch (Throwable e) {
log.error("story.novel.active.onMessage failed, data={}, costTime={} ms", data.value(),
System.currentTimeMillis() - begin, e);
......
package com.lwby.marketing.att.bystory;
import com.lwby.marketing.flow.FlowExecutor;
import com.lwby.marketing.flow.Rule;
import com.lwby.marketing.vo.StoryNovelAction;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
@Component
public class DyStoryFlowExecutor {
@Resource
ApplicationContext ctx;
FlowExecutor<StoryNovelAction> executorByStory;
@PostConstruct
public void init(){
executorByStory = new FlowExecutor<>(ctx, Rule.create().THEN("dystory_setup").THEN("dystory_store").THEN("dystory_checkerfirst").SWITCH("dystory_payspdu").THEN("dystory_uploadcall"));
}
public FlowExecutor<StoryNovelAction> getExecutorByStory(){
return this.executorByStory;
}
}
package com.lwby.marketing.att.storynovel;
package com.lwby.marketing.att.bystory;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.lwby.marketing.att.NovelAttributionMain;
import com.lwby.marketing.vo.StoryNovelAction;
import com.lwby.marketing.vo.StoreUserUploadEventBO;
import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.kafka.listener.MessageListener;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
/**
* @author songxinyu
* @version StoreNovelPayConsumer.java, v 0.1 2024年03月05日 10:40 songxinyu Exp $
*/
@Slf4j
@Component
public class StoryNovelPayConsumer implements MessageListener<String, String> {
public class DyStoryPayConsumer extends DyStoryFlowExecutor implements MessageListener<String, String> {
@Autowired
NovelAttributionMain novelAttributionMain;
@Resource
DyStoryFlowExecutor dyStoryFlowExecutor;
@KafkaListener(topics = {"${story.novel.pay.consumer.topic:testStoryNovelpay}"},groupId = "${story.novel.pay.consumer.group.id:test_story_dy_pay}")
@Override
......@@ -41,7 +42,7 @@ public class StoryNovelPayConsumer implements MessageListener<String, String> {
StoryNovelAction action = new StoryNovelAction(event.getClientInfo(),event.getUserId(),event.getOpenId(),event.getUserUploadEvent(),event.getProductId());
novelAttributionMain.executorStoryNovel.execute(action);
dyStoryFlowExecutor.getExecutorByStory().execute(action);
} catch (Throwable e) {
log.error("story.novel.pay.onMessage failed, data={}, costTime={} ms", data.value(),
System.currentTimeMillis() - begin, e);
......@@ -49,4 +50,5 @@ public class StoryNovelPayConsumer implements MessageListener<String, String> {
}
}
}
package com.lwby.marketing.att.storynovel;
package com.lwby.marketing.att.bystory;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alicp.jetcache.anno.CacheRefresh;
import com.alicp.jetcache.anno.CacheType;
import com.alicp.jetcache.anno.Cached;
import com.google.common.collect.ImmutableMap;
import com.lwby.marketing.att.UniversalProcess;
import com.lwby.marketing.att.novel.AttributionStatus;
import com.lwby.marketing.att.novel.AttributionType;
import com.lwby.marketing.vo.DeliveryDeviceInfo;
import com.lwby.marketing.vo.StoryNovelAction;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.kafka.support.SendResult;
import org.springframework.stereotype.Component;
import org.springframework.util.concurrent.ListenableFuture;
import javax.annotation.Resource;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
@Slf4j
@Component
public class UniversalStoryProcess {
@Resource
JdbcTemplate lwbyJdbcTemplate;
@Resource
private KafkaTemplate<String, String> kafkaTemplate;
@Resource
private RedisTemplate<String, String> redisTemplate;
/******************************************** GENERIC METHOD ***********************************************/
public class DyStoryUniversalProcess extends UniversalProcess {
/**
* 通知处理结果
......@@ -85,35 +66,6 @@ public class UniversalStoryProcess {
}
/******************************************** REDIS **********************************************************/
public boolean exists(String key) {
return Boolean.TRUE.equals(redisTemplate.hasKey(key));
}
public void set(String key, int expires, String value) {
redisTemplate.opsForValue().set(key,value,expires, TimeUnit.SECONDS);
}
public <T> T get(Class<T> clazz, String key) {
String value = redisTemplate.opsForValue().get(key);
if(!Objects.isNull(value)){
return JSON.parseObject(value,clazz);
}
return null;
}
public long incrby(String key, int increment, int expireSecond) {
Long v = redisTemplate.opsForValue().increment(key,increment);
redisTemplate.expire(key,expireSecond, TimeUnit.SECONDS);
return Objects.isNull(v)?0: v;
}
public long incrby(String key, int increment) {
return redisTemplate.opsForValue().increment(key,increment);
}
/******************************************** JDBC *************************************************************/
@Cached(name="attribute_rule_store_novel", cacheType = CacheType.LOCAL)
......@@ -125,35 +77,4 @@ public class UniversalStoryProcess {
return null;
}
}
/******************************************** INNER CLASS ******************************************************/
/**
* 媒体ID和名称关系映射
*/
static class MediaMapping{
static Map<String, String> mediaMap = ImmutableMap.<String, String>builder()
.put("11", "xiaomi")
.put("12", "huawei")
.put("13", "oppo")
.put("14", "vivo")
.put("15", "yingyongbao")
.put("16", "meizu")
.put("17", "360zhushou")
.put("18", "baiduzhushou")
.put("19", "other")
.put("21", "jinritoutiao")
.put("22", "guangdiantong")
.put("23", "kuaishou")
.put("24", "uc")
.put("25", "qutoutiao")
.put("28", "youdao")
.put("33", "dystore")
.build();
static String getMediaNameByChannelId(String channelId){
return mediaMap.get(channelId.substring(0, 2));
}
}
}
package com.lwby.marketing.att.storynovel.handle;
package com.lwby.marketing.att.bystory.handle;
import com.lwby.marketing.att.storynovel.UniversalStoryProcess;
import com.lwby.marketing.att.bystory.DyStoryUniversalProcess;
import com.lwby.marketing.flow.NodeFlow;
import com.lwby.marketing.vo.StoryNovelAction;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Component("checkerNovelStorefirst")
public class CheckerNovelStoryFirstFlow extends NodeFlow<StoryNovelAction> {
@Component("dystory_checkerfirst")
public class CheckerDyStoryFirstFlow extends NodeFlow<StoryNovelAction> {
@Resource
UniversalStoryProcess up;
DyStoryUniversalProcess up;
@Override
public void process(StoryNovelAction action) {
......
package com.lwby.marketing.att.storynovel.handle;
package com.lwby.marketing.att.bystory.handle;
import com.alibaba.fastjson.JSONObject;
import com.lwby.marketing.att.novel.UniversalProcess;
import com.lwby.marketing.att.storynovel.media.StoryMedia;
import com.lwby.marketing.att.bystory.DyStoryUniversalProcess;
import com.lwby.marketing.flow.NodeFlow;
import com.lwby.marketing.notify.Media;
import com.lwby.marketing.notify.media.Platform;
import com.lwby.marketing.po.StoryLogin;
import com.lwby.marketing.util.DateTimUtils;
import com.lwby.marketing.util.NumberUtils;
......@@ -16,10 +16,10 @@ import java.util.Objects;
import java.util.UUID;
@Slf4j
@Component("setupStoreNovel")
@Component("dystory_setup")
public class ParameterSetupStoryNovelFlow extends NodeFlow<StoryNovelAction> {
@Resource
UniversalProcess up;
DyStoryUniversalProcess up;
@Override
public void process(StoryNovelAction action) {
......@@ -60,7 +60,7 @@ public class ParameterSetupStoryNovelFlow extends NodeFlow<StoryNovelAction> {
action.setChannelId(NumberUtils.parseInteger(storyLogin.getChannel()));
action.setPlanId(NumberUtils.parseInteger((storyLogin.getAdid())));
action.setMediaName(storyLogin.getMedia());
action.setMedia(StoryMedia.getMedia(action.getMediaName()));
action.setMedia(Media.getMedia(action.getMediaName(), Platform.DY_STORY));
}
}
......
package com.lwby.marketing.att.storynovel.handle;
package com.lwby.marketing.att.bystory.handle;
import com.alibaba.fastjson.JSON;
import com.lwby.marketing.att.novel.AttributionStatus;
import com.lwby.marketing.att.novel.AttributionType;
import com.lwby.marketing.att.storynovel.UniversalStoryProcess;
import com.lwby.marketing.flow.NodeFlow;
import com.lwby.marketing.att.bystory.DyStoryUniversalProcess;
import com.lwby.marketing.flow.NodeSwitchFlow;
import com.lwby.marketing.vo.StoryNovelAction;
import lombok.extern.slf4j.Slf4j;
......@@ -22,11 +21,11 @@ import java.util.concurrent.ThreadLocalRandom;
* @version PaySpduFlow.java, v 0.1 2024年03月04日 18:46 songxinyu Exp $
*/
@Slf4j
@Component("payspdu")
@Component("dystory_payspdu")
public class PaySpduFlow extends NodeSwitchFlow<StoryNovelAction> {
@Resource
UniversalStoryProcess up;
DyStoryUniversalProcess up;
@Override
public void process(StoryNovelAction action) {
......
package com.lwby.marketing.att.storynovel.handle;
package com.lwby.marketing.att.bystory.handle;
import com.lwby.marketing.att.novel.AttributionStatus;
import com.lwby.marketing.att.storynovel.CallBackType;
import com.lwby.marketing.att.storynovel.UniversalStoryProcess;
import com.lwby.marketing.att.bystory.CallBackType;
import com.lwby.marketing.att.bystory.DyStoryUniversalProcess;
import com.lwby.marketing.flow.NodeFlow;
import com.lwby.marketing.vo.StoryNovelAction;
import org.springframework.stereotype.Component;
......@@ -10,10 +10,10 @@ import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Objects;
@Component("storeNovelStore")
public class StoreNovelStoryAttributionFlow extends NodeFlow<StoryNovelAction> {
@Component("dystory_store")
public class StoreDyStoryAttributionFlow extends NodeFlow<StoryNovelAction> {
@Resource
UniversalStoryProcess up;
DyStoryUniversalProcess up;
@Override
public void process(StoryNovelAction action) {
......
package com.lwby.marketing.att.storynovel.handle;
package com.lwby.marketing.att.bystory.handle;
import com.lwby.marketing.att.novel.AttributionStatus;
import com.lwby.marketing.att.storynovel.CallBackType;
import com.lwby.marketing.att.storynovel.UniversalStoryProcess;
import com.lwby.marketing.att.bystory.CallBackType;
import com.lwby.marketing.att.bystory.DyStoryUniversalProcess;
import com.lwby.marketing.flow.NodeFlow;
import com.lwby.marketing.vo.StoryNovelAction;
import org.springframework.stereotype.Component;
......@@ -13,11 +12,11 @@ import javax.annotation.Resource;
* @author songxinyu
* @version ActiveCallFlow.java, v 0.1 2024年03月04日 18:28 songxinyu Exp $
*/
@Component("uploadcall")
@Component("dystory_uploadcall")
public class UploadCallFlow extends NodeFlow<StoryNovelAction> {
@Resource
UniversalStoryProcess up;
DyStoryUniversalProcess up;
@Override
public void process(StoryNovelAction action) {
......@@ -26,7 +25,7 @@ public class UploadCallFlow extends NodeFlow<StoryNovelAction> {
}
private void process0(StoryNovelAction action, CallBackType callBackTypeByType) {
boolean success = action.getMedia().callback(action);
boolean success = action.getMedia().notify(action);
if (success) {
up.notifyResult(action, callBackTypeByType.getTopic(),
callBackTypeByType.getStatus());
......
package com.lwby.marketing.att.novel;
import com.alibaba.fastjson.JSON;
import com.lwby.marketing.att.NovelAttributionMain;
import com.lwby.marketing.flow.FlowExecutor;
import com.lwby.marketing.flow.Rule;
import com.lwby.marketing.vo.BookStoreEvent;
import com.lwby.marketing.vo.NovelAction;
import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.kafka.listener.MessageListener;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
/**
* @author songxinyu
* @version NovelActiveConsumer.java, v 0.1 2024年03月05日 10:40 songxinyu Exp $
......@@ -19,8 +23,15 @@ import org.springframework.stereotype.Component;
@Component
public class NovelActiveConsumer implements MessageListener<String, String> {
@Autowired
NovelAttributionMain novelAttributionMain;
@Resource
ApplicationContext ctx;
FlowExecutor<NovelAction> executorNovel;
@PostConstruct
public void init(){
executorNovel = new FlowExecutor<>(ctx, Rule.create().THEN("novel_setup").THEN("novel_prize").THEN("novel_store").THEN("novel_checkerfirst").SWITCH("novel_cross","novel_plan","novel_channel"));
}
@KafkaListener(topics = {"${novel.active.consumer.topic:testNovelActive}"},groupId = "${novel.active.consumer.group.id:test_novel_dy_active}")
@Override
......@@ -39,7 +50,7 @@ public class NovelActiveConsumer implements MessageListener<String, String> {
NovelAction action = new NovelAction(event.getClientInfo(), data.value());
novelAttributionMain.executorNovel.execute(action);
executorNovel.execute(action);
} catch (Throwable e) {
log.error("novel.active.onMessage failed, data={}, costTime={} ms", data.value(),
System.currentTimeMillis() - begin, e);
......
package com.lwby.marketing.att.novel;
import com.alibaba.fastjson.JSONObject;
import com.alicp.jetcache.anno.CacheRefresh;
import com.alicp.jetcache.anno.CacheType;
import com.alicp.jetcache.anno.Cached;
import com.lwby.marketing.att.UniversalProcess;
import com.lwby.marketing.vo.NovelAction;
import com.lwby.marketing.vo.DeliveryDeviceInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.kafka.support.SendResult;
import org.springframework.stereotype.Component;
import org.springframework.util.concurrent.ListenableFuture;
import java.util.Objects;
@Slf4j
@Component
public class NovelUniversalProcess extends UniversalProcess {
public static final String PRIZE_FLOW_PREFIX = "c:ouser:";
/**
* 通知处理结果
*/
public void notifyResult(NovelAction action, AttributionStatus status) {
DeliveryDeviceInfo ddi = action.getDeliveryDeviceInfo();
if (Objects.isNull(ddi)) {
ddi = new DeliveryDeviceInfo();
String channelStr = String.valueOf(action.getClientInfo().getChannel());
ddi.setMedia(MediaMapping.getMediaNameByChannelId(channelStr));
ddi.setAd_plan_id("0");
ddi.setAd_group_id("0");
ddi.setAd_creative_id("0");
ddi.setPlatform_id(String.valueOf(action.getPlatformId()));
ddi.setDj_channel(channelStr);
}
ddi.setOs(action.getClientInfo().getOs());
ddi.setIs_call(status.id);
ddi.setDevice_id(action.getDeviceId());
ddi.setActive_time(System.currentTimeMillis());
ddi.setChannel(String.valueOf(action.getChannelId()));
ddi.setUserId(action.getUserId());
ddi.setDevice_status(exists(PRIZE_FLOW_PREFIX.concat(String.valueOf(ddi.getUserId()))) ? 2 : 0);
String jsonString = JSONObject.toJSONString(ddi);
ListenableFuture<SendResult<String, String>> active_result = kafkaTemplate.send("ocpc_result_test", jsonString);
active_result.addCallback(
result -> log.info("归因成功[{}],归因类型[{}]", jsonString, status.desc),
ex -> log.error("归因失败[{}],归因类型[{}]", jsonString, status.desc, ex)
);
}
/******************************************** ASSEMBLE KEY ***************************************************/
public String getTotalCountKey(AttributionType attributionType, int platformId, int channelOrPlanId, int sprDedu, String dateStr) {
return String.format("%s_total_%d_%d_%d_%s", attributionType, platformId, channelOrPlanId, sprDedu, dateStr);
}
public String getCallbackCountKey(AttributionType attributionType, int platformId, int channelOrPlanId, int sprDedu, String dateStr) {
return String.format("%s_callback_%d_%d_%d_%s", attributionType, platformId, channelOrPlanId, sprDedu, dateStr);
}
public String getFirstCheckerKey(NovelAction action) {
return String.format("fc_%s_%d_%s_%s", action.getDeviceId(), action.getPlatformId(),action.getMediaName(),action.getCurrentDateStr());
}
public String buildKey(Integer platformId,String deviceId) {
return String.format("market:activeness:30:%d:%s",platformId,deviceId);
}
}
\ No newline at end of file
......@@ -2,9 +2,8 @@ package com.lwby.marketing.att.novel.handle;
import com.lwby.marketing.att.novel.AttributionStatus;
import com.lwby.marketing.att.novel.AttributionType;
import com.lwby.marketing.att.novel.UniversalProcess;
import com.lwby.marketing.att.novel.NovelUniversalProcess;
import com.lwby.marketing.flow.NodeSwitchFlow;
import com.lwby.marketing.po.AppChannel;
import com.lwby.marketing.util.DateTimUtils;
import com.lwby.marketing.vo.NovelAction;
import org.springframework.jdbc.core.JdbcTemplate;
......@@ -16,14 +15,14 @@ import java.math.RoundingMode;
import java.util.concurrent.ThreadLocalRandom;
@Component("channel")
@Component("novel_channel")
public class ChannelAttributionFlow extends NodeSwitchFlow<NovelAction> {
@Resource
JdbcTemplate marketingJdbcTemplate;
@Resource
UniversalProcess up;
NovelUniversalProcess up;
@Override
public boolean checked(NovelAction action) {
......@@ -45,7 +44,7 @@ public class ChannelAttributionFlow extends NodeSwitchFlow<NovelAction> {
//等于空 或 100直接回传
if (sprDedu == null || sprDedu == 100) {
//TODO;channelTotalCount 和 channelCallbackCount不加吗
action.getMedia().callback(action);
action.getMedia().notify(action);
up.notifyResult(action, AttributionStatus.ACTIVE_CALLBACK);
up.set(up.getFirstCheckerKey(action),60 * 60 * 24,"1");
return;
......@@ -70,7 +69,7 @@ public class ChannelAttributionFlow extends NodeSwitchFlow<NovelAction> {
if (isCallback(channelTotalCount, channelCallbackCount, sprDedu)) {
//回传,回传个数 + 1
up.incrby(channelCallback, 1);
action.getMedia().callback(action);
action.getMedia().notify(action);
up.notifyResult(action, AttributionStatus.ACTIVE_CALLBACK);
} else {
up.notifyResult(action, AttributionStatus.NORMAL_DEDUCTION_CALLBACK);
......
package com.lwby.marketing.att.novel.handle;
import com.lwby.marketing.att.novel.UniversalProcess;
import com.lwby.marketing.att.novel.NovelUniversalProcess;
import com.lwby.marketing.flow.NodeFlow;
import com.lwby.marketing.vo.NovelAction;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Component("checkerfirst")
@Component("novel_checkerfirst")
public class CheckerFirstFlow extends NodeFlow<NovelAction> {
@Resource
UniversalProcess up;
NovelUniversalProcess up;
@Override
public void process(NovelAction action) {
......
......@@ -5,9 +5,8 @@ import com.alicp.jetcache.anno.CacheType;
import com.alicp.jetcache.anno.Cached;
import com.lwby.marketing.att.novel.AttributionStatus;
import com.lwby.marketing.att.novel.AttributionType;
import com.lwby.marketing.att.novel.UniversalProcess;
import com.lwby.marketing.att.novel.NovelUniversalProcess;
import com.lwby.marketing.flow.NodeSwitchFlow;
import com.lwby.marketing.po.AppChannel;
import com.lwby.marketing.po.CrossCallback;
import com.lwby.marketing.util.DateTimUtils;
import com.lwby.marketing.vo.NovelAction;
......@@ -22,12 +21,12 @@ import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;
@Component("cross")
@Component("novel_cross")
public class CrossPlatformAttributionFlow extends NodeSwitchFlow<NovelAction> {
@Resource
JdbcTemplate lwbyJdbcTemplate;
@Resource
UniversalProcess up;
NovelUniversalProcess up;
@Override
public boolean checked(NovelAction action) {
......@@ -48,7 +47,7 @@ public class CrossPlatformAttributionFlow extends NodeSwitchFlow<NovelAction> {
//等于空 或 100直接回传
if (sprDedu == null || sprDedu == 100) {
// callbackService.registerCallback(action);
action.getMedia().callback(action);
action.getMedia().notify(action);
up.notifyResult(action, AttributionStatus.ACTIVE_CALLBACK);
up.set(up.getFirstCheckerKey(action),60 * 60 * 24,"1"); //每天扣量过一次,不在重复走
return;
......@@ -66,7 +65,7 @@ public class CrossPlatformAttributionFlow extends NodeSwitchFlow<NovelAction> {
if(isCallback(action,getUserType(action),sprDedu,channelTotalCount,channelCallbackCount)){
up.incrby(channelCallback,1);
//callbackService.registerCallback(action);
action.getMedia().callback(action);
action.getMedia().notify(action);
up.notifyResult(action,AttributionStatus.ACTIVE_CALLBACK);
}else{
up.notifyResult(action,AttributionStatus.NORMAL_DEDUCTION_CALLBACK);
......
......@@ -2,9 +2,10 @@ package com.lwby.marketing.att.novel.handle;
import cn.hutool.crypto.SecureUtil;
import com.lwby.marketing.att.novel.DeviceType;
import com.lwby.marketing.att.novel.UniversalProcess;
import com.lwby.marketing.att.novel.NovelUniversalProcess;
import com.lwby.marketing.flow.NodeFlow;
import com.lwby.marketing.att.novel.media.Media;
import com.lwby.marketing.notify.Media;
import com.lwby.marketing.notify.media.Platform;
import com.lwby.marketing.util.DateTimUtils;
import com.lwby.marketing.util.NumberUtils;
import com.lwby.marketing.vo.NovelAction;
......@@ -18,10 +19,10 @@ import javax.annotation.Resource;
import java.util.Objects;
@Slf4j
@Component("setup")
@Component("novel_setup")
public class ParameterSetupFlow extends NodeFlow<NovelAction> {
@Resource
UniversalProcess up;
NovelUniversalProcess up;
@Override
public void process(NovelAction action) {
......@@ -66,7 +67,7 @@ public class ParameterSetupFlow extends NodeFlow<NovelAction> {
action.setPlanId(NumberUtils.parseInteger((deliveryDeviceInfo.getAd_plan_id())));
action.setAdvertiserId(deliveryDeviceInfo.getAdvertiser_id());
action.setMediaName(deliveryDeviceInfo.getMedia());
action.setMedia(Media.getMedia(action.getMediaName()));
action.setMedia(Media.getMedia(action.getMediaName(), Platform.NOVEL));
}
}
......
......@@ -14,7 +14,7 @@ import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@Component("plan")
@Component("novel_plan")
public class PlanAttributionFlow extends ChannelAttributionFlow {
@Resource
JdbcTemplate lwbyJdbcTemplate;
......
......@@ -2,7 +2,7 @@ package com.lwby.marketing.att.novel.handle;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.lwby.marketing.att.novel.UniversalProcess;
import com.lwby.marketing.att.novel.NovelUniversalProcess;
import com.lwby.marketing.flow.NodeFlow;
import com.lwby.marketing.util.DateTimUtils;
import com.lwby.marketing.vo.NovelAction;
......@@ -12,7 +12,7 @@ import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Objects;
@Component("prize")
@Component("novel_prize")
public class PrizeSevenUserFlow extends NodeFlow<NovelAction> {
//TODO;建议参数先写死
......@@ -20,7 +20,7 @@ public class PrizeSevenUserFlow extends NodeFlow<NovelAction> {
private String platformPrizeExpire;
@Resource
UniversalProcess up;
NovelUniversalProcess up;
@Override
public void process(NovelAction action) {
......@@ -29,7 +29,7 @@ public class PrizeSevenUserFlow extends NodeFlow<NovelAction> {
JSONObject platformPrizeExpireJson = JSON.parseObject(platformPrizeExpire);
Integer platformPrizeExpireStr = platformPrizeExpireJson.getInteger(String.valueOf(action.getPlatformId()));
String prizeAssembleKey = UniversalProcess.PRIZE_FLOW_PREFIX;
String prizeAssembleKey = NovelUniversalProcess.PRIZE_FLOW_PREFIX;
if (Objects.nonNull(platformPrizeExpireStr)) {
//商业化老用户大奖缓存
up.set(prizeAssembleKey.concat(String.valueOf(action.getUserId())), platformPrizeExpireStr, "1");
......
......@@ -2,7 +2,7 @@ package com.lwby.marketing.att.novel.handle;
import com.lwby.marketing.att.novel.AttributionStatus;
import com.lwby.marketing.att.novel.DeviceType;
import com.lwby.marketing.att.novel.UniversalProcess;
import com.lwby.marketing.att.novel.NovelUniversalProcess;
import com.lwby.marketing.flow.NodeFlow;
import com.lwby.marketing.vo.NovelAction;
import org.springframework.stereotype.Component;
......@@ -10,10 +10,10 @@ import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Objects;
@Component("store")
@Component("novel_store")
public class StoreAttributionFlow extends NodeFlow<NovelAction> {
@Resource
UniversalProcess up;
NovelUniversalProcess up;
@Override
public void process(NovelAction action) {
......
package com.lwby.marketing.att.novel.media;
import com.lwby.marketing.vo.NovelAction;
public interface ICallback {
boolean delivery(NovelAction action);
}
package com.lwby.marketing.att.novel.media;
import com.lwby.marketing.att.novel.media.gdt.GDTCallback;
import com.lwby.marketing.att.novel.media.jrtt.JRTTCallback;
import com.lwby.marketing.vo.NovelAction;
import java.util.Arrays;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
public enum Media {
gdt("gdt","广点通",new GDTCallback()),
jrtt("jrtt","今日头条",new JRTTCallback());
final String name;
final String desc;
final ICallback callBack;
final static Map<String, Media> mediaMap = Arrays.stream(Media.values())
.collect(Collectors.toMap(Media::name, Function.identity()));
Media(String name, String desc, ICallback callBack){
this.name = name;
this.desc = desc;
this.callBack = callBack;
}
public boolean callback(NovelAction action){
return callBack.delivery(action);
}
public static Media getMedia(String mediaName){
return mediaMap.get(mediaName);
}
}
\ No newline at end of file
package com.lwby.marketing.att.storynovel.media;
import com.lwby.marketing.vo.StoryNovelAction;
/**
* @author songxinyu
* @version BaseStoreCallback.java, v 0.1 2024年03月04日 17:19 songxinyu Exp $
*/
public abstract class BaseStoryCallback implements IStoryCallback {
@Override
public boolean delivery(StoryNovelAction action) {
return call(action);
}
public abstract boolean call(StoryNovelAction na);
}
package com.lwby.marketing.att.storynovel.media;
import com.lwby.marketing.vo.StoryNovelAction;
/**
* @author songxinyu
* @version IStoreCallback.java, v 0.1 2024年03月04日 17:16 songxinyu Exp $
*/
public interface IStoryCallback {
boolean delivery(StoryNovelAction action);
}
package com.lwby.marketing.att.storynovel.media;
import com.lwby.marketing.att.storynovel.media.jrtt.JRTTActiveCallback;
import com.lwby.marketing.att.storynovel.media.jrtt.JRTTPayCallback;
import com.lwby.marketing.vo.StoryNovelAction;
import java.util.Arrays;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
public enum StoryMedia {
jrtt("jrtt","今日头条",(c)-> c == 0 ? new JRTTActiveCallback() : new JRTTPayCallback());
final String name;
final String desc;
final Function<Integer, IStoryCallback> fun;
final static Map<String, StoryMedia> mediaMap = Arrays.stream(StoryMedia.values())
.collect(Collectors.toMap(StoryMedia::name, Function.identity()));
StoryMedia(String name, String desc, Function<Integer, IStoryCallback> fun){
this.name = name;
this.desc = desc;
this.fun = fun;
}
public boolean callback(StoryNovelAction action){
return fun.apply(action.getType()).delivery(action);
}
public static StoryMedia getMedia(String mediaName){
return mediaMap.get(mediaName);
}
}
\ No newline at end of file
package com.lwby.marketing.att.storynovel.media.jrtt;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lwby.marketing.att.novel.media.jrtt.dto.JrttAttributeRequest;
import com.lwby.marketing.att.storynovel.media.BaseStoryCallback;
import com.lwby.marketing.vo.DeliveryDeviceInfo;
import com.lwby.marketing.vo.StoryNovelAction;
import lombok.extern.slf4j.Slf4j;
/**
* @author songxinyu
* @version JRTTPayCallback.java, v 0.1 2024年03月04日 17:25 songxinyu Exp $
*/
@Slf4j
public class JRTTPayCallback extends BaseStoryCallback {
public static final String ATTRIBUTE_URL = "https://analytics.oceanengine.com/api/v2/conversion";
@Override
public boolean call(StoryNovelAction na) {
DeliveryDeviceInfo ddi = na.getDeliveryDeviceInfo();
JrttAttributeRequest.Ad ad = new JrttAttributeRequest.Ad();
ad.setCallback(ddi.getCallback_param());
JrttAttributeRequest.Context context = new JrttAttributeRequest.Context();
context.setAd(ad);
JrttAttributeRequest request = JrttAttributeRequest.builder().context(context).event_type("active_pay").timestamp(
System.currentTimeMillis()).build();
String userJson = JSONObject.toJSONString(request);
try {
String result = HttpUtil.post(ATTRIBUTE_URL, userJson);
Integer resultCode = (Integer) JSON.parseObject(result).get("code");
log.info("JRTTActiveCallback.story.pay.upload,result={},userId={},channel={},platform={}",JSON.toJSONString(result),na.getUserId(),na.getChannelId(),na.getPlatformId());
return resultCode == 0;
} catch (Exception e) {
return false;
}
}
}
package com.lwby.marketing.att.storynovel.media.jrtt.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author songxinyu
* @version JrttAttributeRequest.java, v 0.1 2024年02月23日 17:05 songxinyu Exp $
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class JrttAttributeRequest {
/**
* {
* "event_type": "active",
* "context": {
* "ad": {
* "callback": "EPHk9cX3pv4CGJax4ZENKI7w4MDev_4C",
* }
* },
* "timestamp": 1604888786102
* }
*/
/**
* 回传的事件,例如”激活“、”付费“
*/
private String event_type;
/**
* 包含一些关键的上下文信息
*/
private Context context;
/**
* 事件发生的毫秒级时间戳
*/
private long timestamp;
@Data
public static class Context {
/**
* 包含一些关键的广告相关信息
*/
private Ad ad;
private Device device;
}
@Data
public static class Ad {
/**
* callback 字段有两个获取途径,对于监测链接归因的方式,需要从监测链接的__CALLBACK_PARAM__这个宏获取这个字段值;
*/
private String callback;
}
@Data
public static class Device {
/**
* 设备平台
*/
private String platform;
private String imei;
private String oaid;
private String idfa;
}
}
......@@ -2,25 +2,18 @@ package com.lwby.marketing.controller;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.lwby.marketing.att.NovelAttributionMain;
import com.lwby.marketing.att.novel.UniversalProcess;
import com.lwby.marketing.att.storynovel.UniversalStoryProcess;
import com.lwby.marketing.att.storynovel.media.IStoryCallback;
import com.lwby.marketing.att.storynovel.media.jrtt.JRTTActiveCallback;
import com.lwby.marketing.att.storynovel.media.jrtt.JRTTPayCallback;
import com.lwby.marketing.po.AppChannel;
import com.lwby.marketing.att.bystory.DyStoryFlowExecutor;
import com.lwby.marketing.att.bystory.DyStoryUniversalProcess;
import com.lwby.marketing.vo.StoryNovelAction;
import com.lwby.marketing.vo.StoreUserUploadEventBO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.Map;
import java.util.function.Function;
/**
* @author songxinyu
......@@ -32,12 +25,15 @@ import java.util.function.Function;
@RequestMapping(value = "/attr")
public class AttrController {
@Autowired
NovelAttributionMain nm;
@Resource
DyStoryUniversalProcess up;
@Resource
private KafkaTemplate<String, String> kafkaTemplate;
@Resource
DyStoryFlowExecutor execute;
@RequestMapping("/testUpload")
public void testUpload() {
String msg = "{\"clientInfo\":{\"channel\":214120503,\"clientIp\":\"183.219.7.180\",\"pkv\":1,\"platformGroupId\":412,"
......@@ -53,23 +49,19 @@ public class AttrController {
event.getProductId());
try {
nm.executorStoryNovel.execute(action);
execute.getExecutorByStory().execute(action);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Resource
UniversalStoryProcess up;
@Resource
UniversalProcess up2;
@RequestMapping("dedu")
public void testDedu() {
Integer platformId = 5;
Integer channelId = 123213;
Integer sprDedu = up2.getAppChannel(platformId, channelId);
Integer sprDedu = up.getAppChannel(platformId, channelId);
if (sprDedu == null || sprDedu == 100) {
System.out.println(sprDedu);
}
......@@ -104,12 +96,12 @@ public class AttrController {
System.out.println(sprDedu);
Function<Integer, IStoryCallback> function = new Function<Integer, IStoryCallback>() {
@Override
public IStoryCallback apply(Integer c) {
return c == 0 ? new JRTTActiveCallback() : new JRTTPayCallback();
}
};
// Function<Integer, IStoryCallback> function = new Function<Integer, IStoryCallback>() {
// @Override
// public IStoryCallback apply(Integer c) {
// return c == 0 ? new JRTTActiveCallback() : new JRTTPayCallback();
// }
// };
}
@RequestMapping("/send")
......
package com.lwby.marketing.notify;
import com.lwby.marketing.flow.Action;
public abstract class BaseNotiry {
public abstract boolean delivery(Action action);
}
package com.lwby.marketing.notify;
import com.lwby.marketing.flow.Action;
import com.lwby.marketing.vo.StoryNovelAction;
public abstract class DYNotify extends BaseNotiry {
public boolean delivery(Action action) {
//TODO;抖音短剧加入后,需要重构StoryNovelAction
StoryNovelAction storyNovelAction = (StoryNovelAction)action;
return storyNovelAction.getType() == 0?active(storyNovelAction):pay(storyNovelAction);
}
public abstract boolean active(StoryNovelAction na);
public abstract boolean pay(StoryNovelAction na);
}
package com.lwby.marketing.notify;
import com.lwby.marketing.flow.Action;
import com.lwby.marketing.notify.media.Platform;
import com.lwby.marketing.notify.media.gdt.NovelGDTNotify;
import com.lwby.marketing.notify.media.jrtt.NovelJRTTNotify;
import com.lwby.marketing.notify.media.jrtt.StoryJRTTNotify;
import java.util.Arrays;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
public enum Media {
NOVEL_GDT("gdt", Platform.NOVEL, "广点通",new NovelGDTNotify()),
NOVEL_JRTT("jrtt", Platform.NOVEL, "今日头条",new NovelJRTTNotify()),
DY_STORY_JRTT("jrtt", Platform.DY_STORY, "今日头条",new StoryJRTTNotify());
final String name;
final Platform platform;
final String desc;
final BaseNotiry baseNotify;
final static Map<String, Media> mediaMap = Arrays.stream(Media.values())
.collect(Collectors.toMap(Media::getKey, Function.identity()));
Media(String name, Platform platform, String desc, BaseNotiry baseNotiry){
this.name = name;
this.platform = platform;
this.desc = desc;
this.baseNotify = baseNotiry;
}
public boolean notify(Action action){
return baseNotify.delivery(action);
}
public static Media getMedia(String mediaName,Platform platform){
return mediaMap.get(String.format("%s_%s",mediaName,platform.getName()));
}
public String getKey(){
return String.format("%s_%s",this.name,this.platform.getName());
}
}
\ No newline at end of file
package com.lwby.marketing.att.novel.media;
package com.lwby.marketing.notify;
import com.lwby.marketing.flow.Action;
import com.lwby.marketing.vo.NovelAction;
import org.apache.commons.lang3.StringUtils;
public abstract class BaseCallback implements ICallback {
public boolean delivery(NovelAction action) {
String os = action.getClientInfo().getOs();
return StringUtils.isNotBlank(os) && os.equals("1")?ios(action):android(action);
public abstract class MobileNotify extends BaseNotiry {
public boolean delivery(Action action) {
NovelAction novelAction = (NovelAction)action;
String os = novelAction.getClientInfo().getOs();
return StringUtils.isNotBlank(os) && os.equals("1")?ios(novelAction):android(novelAction);
}
public abstract boolean android(NovelAction na);
......
package com.lwby.marketing.notify.media;
public enum Platform {
NOVEL("novel","小说APP"),
DY_STORY("dy_story","拦音故事会"),
VIDEO("video","短剧APP"),
DY_VIDEO("dy_video","拦音短剧");
final private String name;
final private String desc;
Platform(String name,String desc){
this.name = name;
this.desc = desc;
}
public String getName(){
return this.name;
}
}
package com.lwby.marketing.att.novel.media.gdt;
package com.lwby.marketing.notify.media.gdt;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lwby.marketing.att.novel.media.BaseCallback;
import com.lwby.marketing.att.novel.media.gdt.dto.Action;
import com.lwby.marketing.att.novel.media.gdt.dto.GdtAttributeRequest;
import com.lwby.marketing.att.novel.media.gdt.dto.UserId;
import com.lwby.marketing.notify.BaseNotiry;
import com.lwby.marketing.notify.MobileNotify;
import com.lwby.marketing.notify.media.gdt.dto.Action;
import com.lwby.marketing.notify.media.gdt.dto.GdtAttributeRequest;
import com.lwby.marketing.notify.media.gdt.dto.UserId;
import com.lwby.marketing.vo.ClientInfo;
import com.lwby.marketing.vo.DeliveryDeviceInfo;
import com.lwby.marketing.vo.NovelAction;
import java.util.Collections;
public class GDTCallback extends BaseCallback {
public class NovelGDTNotify extends MobileNotify {
public boolean android(NovelAction na){
DeliveryDeviceInfo ddi = na.getDeliveryDeviceInfo();
......
package com.lwby.marketing.att.novel.media.gdt.dto;
package com.lwby.marketing.notify.media.gdt.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
......
package com.lwby.marketing.att.novel.media.gdt.dto;
package com.lwby.marketing.notify.media.gdt.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
......
package com.lwby.marketing.att.novel.media.gdt.dto;
package com.lwby.marketing.notify.media.gdt.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
......
package com.lwby.marketing.att.novel.media.jrtt;
package com.lwby.marketing.notify.media.jrtt;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lwby.marketing.att.novel.media.BaseCallback;
import com.lwby.marketing.att.novel.media.jrtt.dto.JrttAttributeRequest;
import com.lwby.marketing.notify.MobileNotify;
import com.lwby.marketing.notify.media.jrtt.dto.JrttAttributeRequest;
import com.lwby.marketing.vo.ClientInfo;
import com.lwby.marketing.vo.DeliveryDeviceInfo;
import com.lwby.marketing.vo.NovelAction;
public class JRTTCallback extends BaseCallback {
public class NovelJRTTNotify extends MobileNotify {
public static final String ATTRIBUTE_URL = "https://analytics.oceanengine.com/api/v2/conversion";
public boolean android(NovelAction na){
......
package com.lwby.marketing.att.storynovel.media.jrtt;
package com.lwby.marketing.notify.media.jrtt;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lwby.marketing.att.novel.media.jrtt.dto.JrttAttributeRequest;
import com.lwby.marketing.att.storynovel.media.BaseStoryCallback;
import com.lwby.marketing.notify.DYNotify;
import com.lwby.marketing.vo.DeliveryDeviceInfo;
import com.lwby.marketing.vo.StoryNovelAction;
import lombok.extern.slf4j.Slf4j;
/**
* @author songxinyu
* @version JRTTActiveCallback.java, v 0.1 2024年03月04日 17:24 songxinyu Exp $
*/
@Slf4j
public class JRTTActiveCallback extends BaseStoryCallback {
public class StoryJRTTNotify extends DYNotify {
public static final String ATTRIBUTE_URL = "https://analytics.oceanengine.com/api/v2/conversion";
@Override
public boolean call(StoryNovelAction na) {
public boolean active(StoryNovelAction na) {
return notify(na,"active");
}
@Override
public boolean pay(StoryNovelAction na) {
return notify(na,"active_pay");
}
public boolean notify(StoryNovelAction na,String eventType) {
DeliveryDeviceInfo ddi = na.getDeliveryDeviceInfo();
JrttAttributeRequest.Ad ad = new JrttAttributeRequest.Ad();
......@@ -28,18 +32,17 @@ public class JRTTActiveCallback extends BaseStoryCallback {
JrttAttributeRequest.Context context = new JrttAttributeRequest.Context();
context.setAd(ad);
JrttAttributeRequest request = JrttAttributeRequest.builder().context(context).event_type("active").timestamp(
JrttAttributeRequest request = JrttAttributeRequest.builder().context(context).event_type(eventType).timestamp(
System.currentTimeMillis()).build();
String userJson = JSONObject.toJSONString(request);
try {
String result = HttpUtil.post(ATTRIBUTE_URL, userJson);
Integer resultCode = (Integer) JSON.parseObject(result).get("code");
log.info("JRTTActiveCallback.story.active.upload,result={},userId={},channel={},platform={}",JSON.toJSONString(result),na.getUserId(),na.getChannelId(),na.getPlatformId());
log.info("JRTTActiveCallback.story.{}.upload,result={},userId={},channel={},platform={}",eventType,JSON.toJSONString(result),na.getUserId(),na.getChannelId(),na.getPlatformId());
return resultCode == 0;
} catch (Exception e) {
return false;
}
}
}
package com.lwby.marketing.att.novel.media.jrtt.dto;
package com.lwby.marketing.notify.media.jrtt.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
......
......@@ -2,7 +2,7 @@ package com.lwby.marketing.vo;
import com.lwby.marketing.att.novel.DeviceType;
import com.lwby.marketing.flow.Action;
import com.lwby.marketing.att.novel.media.Media;
import com.lwby.marketing.notify.Media;
import lombok.Data;
import java.util.Date;
......
package com.lwby.marketing.vo;
import com.lwby.marketing.att.storynovel.media.StoryMedia;
import com.lwby.marketing.flow.Action;
import com.lwby.marketing.notify.Media;
import com.lwby.marketing.po.StoryLogin;
import lombok.Data;
......@@ -22,7 +22,7 @@ public class StoryNovelAction extends Action {
int planId;
String mediaName;
Integer type;
StoryMedia media;
Media media;
String currentDateStr;
String goodId;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment