#!/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
|
|
|
|