1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
##@package
#
# @todo: 基于头条广告API对接广告点击 激活 注册 付费信息交互
#
# @author: Alee
# @date 2018-5-4 22:10:51
# @version 1.0
#
# @note: 中文必须传utf8,收到的为urlencode内容  .decode('gbk').encode('utf8')
# !!!注意大小写区分
#
#---------------------------------------------------------------------
 
from bottle import Bottle, request
from lib import mylog, CommFunc
import ADDB
import json
import md5
import time
 
myapp = Bottle()
 
Def_URLPARAM_STR = "__"  # 参数两边用两个下划线包裹
 
#====================
# 参数adid cid timestamp callback_url mac1 ua1 idfa androidid1 imei ip
#====================
 
 
#center.secondworld.net.cn:53004/ad/feedback/2001?adid=__AID__&cid=__CID__&csite=__CSITE__&ctype=__CTYPE__&mac1=__MAC1__&ua1=__UA1__&androidid1=__ANDROIDID1__&imei=__IMEI__&os=__OS__&ip=__IP__&ts=__TS__&callback_url=__CALLBACK_URL__
#接口1 
# 点击广告记录,通过广告ID、包体ID和唯一标识(IMEI或MAC等)匹配对应后续的激活注册付费操作
# 情况1-重复:同一用户多次点击同一个广告ID下载
# 情况2-重复:同一用户多次点击不同广告ID下载
# 情况3-无点击: 不是从广告进入的用户
@myapp.route('/ad/feedback/:packid')
def ADFeedback(packid):
    getDict = request.GET
    
    #print "---------"
    for key in getDict:
        mylog.debug("feedback: %s-%s"%(key, getDict[key]))
        
    adid = getDict.get("adid", "")
    if not adid:
        mylog.error("no adid")
        return json.dumps({"status":-1}, ensure_ascii=False)
    
    if adid == "__AID__":
        return
    dbController = ADDB.GetDBEventCon()
    if not dbController:
        # 无法获取数据库
        mylog.debug("no dbController")
        return json.dumps({"status":-1}, ensure_ascii=False)
    
    #adid 和 包ID为唯一标识
        
    result, findDict = FindUserFromAD(dbController, getDict, packid, adid)
    mylog.debug("result:%s-%s"%(result, findDict))
    newDict = {"adid":adid}     # 广告计划ID
    newDict["cid"] = getDict.get("cid", "") # 广告创意ID
    newDict["csite"] = getDict.get("csite", "") # 广告投放位置
    newDict["ctype"] = getDict.get("ctype", "") # 创意样式
    newDict["mac1"] = getDict.get("mac1", "") # 入网硬件地址 eth0 MAC    md5
    newDict["ua1"] = getDict.get("ua1", "") # user-agent
    newDict["idfa"] = getDict.get("idfa", "")   # 苹果的idfa
    newDict["androidid1"] = getDict.get("androidid1", "")
    newDict["imei"] = getDict.get("imei", "")  # md5
    newDict["os"] = getDict.get("os", "")
    newDict["ip"] = getDict.get("ip", "")
    newDict["ts"] = int(getDict.get("ts", time.time()*1000))   # 时间戳毫秒 点击和激活最长7天
    newDict["callback_url"] = getDict.get("callback_url", "")
 
    newDict["packid"] = packid  #包ID
    if not result:
        newDict["clickcnt"] = 1 # 重复点击数
        newDict["event_type"] = 0
        #插入新数据
        dbController.insert(ADDB.AdColName, newDict)
    else:
        # 更新数据
        newDict["clickcnt"] = result[0].get("clickcnt", 0) + 1 # 重复点击数
        newDict["event_type"] = result[0].get("event_type", 0)
        dbController.update(ADDB.AdColName, findDict, newDict)
        
    return json.dumps({"status":0}, ensure_ascii=False)
 
 
 
#center.secondworld.net.cn:53004/ad/eventtype/包id?mac1=xxx....event_type=0
# 客户端激活 注册 付费
# MAC1 UA IDFA ANDROIDID1 IMEI IP  event_type
@myapp.route('/ad/eventtype/:packid')
def ClientActive(packid):
    getDict = request.GET
    
    #print "---------"
    for key in getDict:
        mylog.debug("ClientActive: %s-%s"%(key, getDict[key]))
    
    mylog.info("ClientActive - IMEI:%s ANDROIDID1: %s event_type: %s"%(
            getDict.get("IMEI", ""), getDict.get("ANDROIDID1", ""), getDict.get("event_type", "")))
         
    event_type = getDict.get("event_type", "")
    if event_type == "":
        mylog.error("no event_type")
        return
    event_type = CommFunc.ToIntDef(event_type, 0)
        
    dbController = ADDB.GetDBEventCon()
    if not dbController:
        # 无法获取数据库
        mylog.debug("no dbController")
        return
         
    # 理论上adid和packid是唯一对应,此处最多只能找到一个
    result, findDict = FindUserFromClient(dbController, getDict, packid)
    if not result:
        # 非广告用户
        return
    
    if len(result) > 1:
        mylog.warn("more result:%s-%s"%(len(result), findDict))
    
    dbEvent = result[0]['event_type']
    clientEvent = pow(2, event_type)
    if dbEvent&clientEvent != 0:
        # 已设置过,不处理
        return
    
    if dbEvent == 0 and event_type > 0:
        # 未设置过激活不设置注册和付费
        return
    
    callback_url = result[0]['callback_url']
    
    # 发送给头条广告
    try:
        result = CommFunc.DoGet(callback_url + "&event_type=%s"%event_type)
    except:
        mylog.warn("toutiao no answer")
        result = None
    
    if result:
        resultDict = json.loads(result)
        mylog.debug("%s"%resultDict)
        if resultDict.get("ret", -1) == 0:
            dbController.update(ADDB.AdColName, findDict, {"$set":{'event_type':dbEvent|clientEvent}})
    return
 
@myapp.route('/ad/getip')
def GetIP():
    return request.environ.get("REMOTE_ADDR", "0.0.0.0")
 
 
# !!!注意大小写区分
# 同类型手机在同wifi网络下 ip和ua可能相同,放最后判断
def FindUserFromAD(dbController, getDict, packid, adid):
    if "idfa" in getDict:
        # 苹果
        if getDict.get("idfa", ""):
            findDict = {"adid":adid, "packid":packid, "idfa":getDict.get("idfa", "")}
            result = dbController.find(ADDB.AdColName, findDict)
            if result[1]:
                return result[1], findDict
        
        if getDict.get("mac1", ""):
            findDict = {"adid":adid, "packid":packid, "mac1":getDict.get("mac1", "")}
            result = dbController.find(ADDB.AdColName, findDict)
            if result[1]:
                return result[1], findDict
 
        if (getDict.get("ip", "") and getDict.get("ua1", "")):
            findDict = {"adid":adid, "packid":packid, "ip":getDict.get("ip", ""), "ua1":getDict.get("ua1", "")}
            result = dbController.find(ADDB.AdColName, findDict)
            if result[1]:
                return result[1], findDict
            
 
    else:
        # 安卓
        
        if getDict.get("imei", ""):
            findDict = {"adid":adid, "packid":packid, "imei":getDict.get("imei", "")}
            result = dbController.find(ADDB.AdColName, findDict)
            if result[1]:
                return result[1], findDict
        
        if getDict.get("androidid1", ""):
            findDict = {"adid":adid, "packid":packid, "androidid1":getDict.get("androidid1", "")}
            result = dbController.find(ADDB.AdColName, findDict)
            if result[1]:
                return result[1], findDict
            
        if getDict.get("mac1", ""):
            findDict = {"adid":adid, "packid":packid, "mac1":getDict.get("mac1", "")}
            result = dbController.find(ADDB.AdColName, findDict)
            if result[1]:
                return result[1], findDict
 
        if (getDict.get("ip", "") and getDict.get("ua1", "")):
            findDict = {"adid":adid, "packid":packid, "ip":getDict.get("ip", ""), "ua1":getDict.get("ua1", "")}
            result = dbController.find(ADDB.AdColName, findDict)
            if result[1]:
                return result[1], findDict
        
    return None, None
 
# MAC1 UA IDFA ANDROIDID1 IMEI IP  event_type
# !!!注意大小写区分
# 同类型手机在同wifi网络下 ip和ua可能相同,放最后判断
def FindUserFromClient(dbController, getDict, packid):
    intime = int(time.time()*1000 - 7*24*60*60*1000)   # 查找7天内的数据
    
    if "IDFA" in getDict:
        # 苹果
        if getDict.get("IDFA", ""):
            findDict = {"packid":packid, "idfa":getDict.get("IDFA", ""), "ts":{'$gt':intime}}
            result = dbController.find(ADDB.AdColName, findDict)
            if result[1]:
                return result[1], findDict
        
        if getDict.get("MAC1", ""):
            findDict = {"packid":packid, "mac1":md5.md5(getDict.get("MAC1", "")).hexdigest(), "ts":{'$gt':intime}}
            result = dbController.find(ADDB.AdColName, findDict)
            if result[1]:
                return result[1], findDict
 
        if (getDict.get("IP", "") and getDict.get("UA", "")):
            findDict = {"packid":packid, "ip":getDict.get("IP", ""), "ua1":getDict.get("UA", ""), "ts":{'$gt':intime}}
            result = dbController.find(ADDB.AdColName, findDict)
            if result[1]:
                return result[1], findDict
            
 
    else:
        # 安卓
        if getDict.get("IMEI", ""):
            findDict = {"packid":packid, "imei":md5.md5(getDict.get("IMEI", "")).hexdigest(), "ts":{'$gt':intime}}
            result = dbController.find(ADDB.AdColName, findDict)
            if result[1]:
                return result[1], findDict
        
        if getDict.get("ANDROIDID1", ""):
            findDict = {"packid":packid, "androidid1":getDict.get("ANDROIDID1", ""), "ts":{'$gt':intime}}
            result = dbController.find(ADDB.AdColName, findDict)
            if result[1]:
                return result[1], findDict
            
        if getDict.get("MAC1", ""):
            findDict = {"packid":packid, "mac1":md5.md5(getDict.get("MAC1", "")).hexdigest(), "ts":{'$gt':intime}}
            result = dbController.find(ADDB.AdColName, findDict)
            if result[1]:
                return result[1], findDict
 
        if (getDict.get("IP", "") and getDict.get("UA", "")):
            findDict = {"packid":packid, "ip":getDict.get("IP", ""), "ua1":getDict.get("UA", ""), "ts":{'$gt':intime}}
            result = dbController.find(ADDB.AdColName, findDict)
            if result[1]:
                return result[1], findDict
        
    return None, None