diff --git a/microservices/attributioncaseios.py b/microservices/attributioncaseios.py
index 8d8cdd1..540494d 100644
--- a/microservices/attributioncaseios.py
+++ b/microservices/attributioncaseios.py
@@ -1547,7 +1547,7 @@ def test_asa14():
 def test_asa15():
     i = idfacode()
     v = idfvcode()
-    receiveios.data[0]['device_info']['idfa'] = i
+    receiveios.data[0]['device_inf5d7db80b4af9dd26b9723d1eaf5b5249o']['idfa'] = i
     receiveios.data[0]['device_info']['idfa_md5'] = computeMD5(i)
     receiveios.data[0]['device_info']['idfv'] = v
     receiveios.data[0]['device_info']['idfv_md5'] = computeMD5(v)
diff --git a/microservices/receiveios.py b/microservices/receiveios.py
index bfe16f9..14b7491 100644
--- a/microservices/receiveios.py
+++ b/microservices/receiveios.py
@@ -37,7 +37,7 @@ global data
 data = [
     {
         "application_info": {
-            "appkey": "2c81418e218b4879b904a45530f0a09e",
+            "appkey": "2a33891fd3ea53f8edb0fca391a2432e",
             "bundleid": "3423232",
             "app_version": "1.9.0",
             "channel_name": "default"
@@ -160,9 +160,9 @@ def send_request():
     # 对接se地址
     # url = 'http://tmtest-se.trackingio.com/receive/tkiov2/sdk'
     # 测试
-    # url = "http://tmtest.trackingio.com/receive/tkiov2/sdk"
+    url = "http://tmtest.trackingio.com/receive/tkiov2/sdk"
     # 线上
-    url = "http://tkio-receive.solar-engine.com/receive/tkiov2/sdk"
+    # url = "http://tkio-receive.solar-engine.com/receive/tkiov2/sdk"
 
     data[0]['timestamp_info']['install_time'] = int(round(time.time() * 1000))
     data[0]['timestamp_info']['current_event_time'] = int(round(time.time() * 1000))
diff --git a/microservices/redirectios.py b/microservices/redirectios.py
index 35e9e00..d0479ba 100644
--- a/microservices/redirectios.py
+++ b/microservices/redirectios.py
@@ -102,9 +102,9 @@ def send_request(cs):
 def send_request3(cs):
     global parms
     # 测试
-    # url1 = 'http://tmtest.trackingio.com/receive/turl/I3eYvea' + cs
+    url1 = 'http://tmtest.trackingio.com/receive/turl/I3eYvea' + cs
     # 线上
-    url1 = 'http://tkio-redirect.solar-engine.com/receive/turl/qY7fQza' + cs
+    # url1 = 'http://tkio-redirect.solar-engine.com/receive/turl/qY7fQza' + cs
     parms['ts'] = int(round(time.time() * 1000))
     response = requests.get(url=url1, params=parms, timeout=10, verify=False)
     print(response.url)
diff --git a/tkio/attributioncaseandroid.py b/tkio/attributioncaseandroid.py
new file mode 100644
index 0000000..51d54c3
--- /dev/null
+++ b/tkio/attributioncaseandroid.py
@@ -0,0 +1,710 @@
+import socket
+import struct
+import random
+import time
+import string
+
+import hashlib
+from tkio import clickios
+from tkio import tkioreceive
+
+
+# 生成idfa大写
+def idfacode():
+    ret = ''
+    a = "".join(random.sample(string.ascii_letters + string.digits, 8))
+    b = "".join(random.sample(string.ascii_letters + string.digits, 4))
+    c = "".join(random.sample(string.ascii_letters + string.digits, 4))
+    d = "".join(random.sample(string.ascii_letters + string.digits, 4))
+    e = "".join(random.sample(string.ascii_letters + string.digits, 12))
+    i = (a + "-" + b + "-" + c + "-" + d + "-" + e).upper()
+    ret += i
+    return ret
+
+
+# 生成idfa小写
+def idfacode_lower():
+    ret = ''
+    a = "".join(random.sample(string.ascii_letters + string.digits, 8))
+    b = "".join(random.sample(string.ascii_letters + string.digits, 4))
+    c = "".join(random.sample(string.ascii_letters + string.digits, 4))
+    d = "".join(random.sample(string.ascii_letters + string.digits, 4))
+    e = "".join(random.sample(string.ascii_letters + string.digits, 12))
+    i = (a + "-" + b + "-" + c + "-" + d + "-" + e).lower()
+    ret += i
+    return ret
+
+
+# md5加密转大写
+def computeMD5upper(message):
+    m = hashlib.md5()
+    m.update(message.encode(encoding='utf-8'))
+    return m.hexdigest().upper()
+
+
+# md5加密转xiao写
+def computeMD5lower(message):
+    m = hashlib.md5()
+    m.update(message.encode(encoding='utf-8'))
+    return m.hexdigest()
+
+
+# 生成小写字母加数字组合
+n = 10
+
+
+def code_nums1(n=6):
+    ret = ''
+    for i in range(n):
+        num = random.randint(0, 9)
+        letter = chr(random.randint(97, 122))
+        s = str(random.choice([num, letter]))
+        ret += s
+    return ret
+
+
+# 1.点击1:idfa=111,ip=222
+# 2.点击2:idfa=444,ip=333
+# 3.激活:idfa=111,ip=333
+# 归因到点击1
+def test_at1():
+    i = idfacode()
+    i2 = idfacode()
+    ip1 = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    ip2 = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    clickios.parms['idfa'] = i
+    clickios.parms['ip'] = ip1
+    clickios.send_requestandroid('')
+    time.sleep(3)
+    clickios.parms['idfa'] = i2
+    clickios.parms['ip'] = ip2
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i
+    tkioreceive.data['context']['_idfa'] = i
+    tkioreceive.data['context']['_ip'] = ip2
+    tkioreceive.send_request()
+    print(i)
+    print(i2)
+    print(ip1)
+    print(ip2)
+
+
+# 1.点击1:idfa=111,ip=222.点击2:idfa=444,ip=3333.激活:idfa=444,ip=222
+# 归因到点击2
+def test_at2():
+    i = idfacode()
+    i2 = idfacode()
+    ip1 = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    ip2 = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    clickios.parms['idfa'] = i
+    clickios.parms['ip'] = ip1
+    clickios.send_requestandroid('')
+    time.sleep(3)
+    clickios.parms['idfa'] = i2
+    clickios.parms['ip'] = ip2
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i2
+    tkioreceive.data['context']['_idfa'] = i2
+    tkioreceive.data['context']['_ip'] = ip1
+    tkioreceive.send_request()
+    print(i)
+    print(i2)
+    print(ip1)
+    print(ip2)
+
+
+# 点击激活的idfa,caid,ip+ua,ip都相同,归因方式为idfa
+def test_at3():
+    i = idfacode()
+    caid = code_nums1(36)
+    ip1 = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    clickios.parms['idfa'] = i
+    clickios.parms['ip'] = ip1
+    clickios.parms['caid1'] = caid
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i
+    tkioreceive.data['context']['_idfa'] = i
+    tkioreceive.data['context']['_ip'] = ip1
+    tkioreceive.data['context']['_caid'] = caid
+    tkioreceive.send_request()
+    print(i)
+    print(ip1)
+
+
+# 在优先级同样的情况下,优先匹配lastclick
+def test_at4():
+    i = idfacode()
+    i2 = idfacode()
+    ip1 = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    ip2 = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    clickios.parms['idfa'] = i
+    clickios.parms['ip'] = ip1
+    clickios.send_requestandroid('')
+    time.sleep(3)
+    clickios.parms['idfa_MD5'] = computeMD5upper(i)
+    clickios.parms['idfa'] = i2
+    clickios.parms['ip'] = ip2
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i
+    tkioreceive.data['context']['_idfa'] = i
+    tkioreceive.data['context']['_ip'] = ip1
+    tkioreceive.send_request()
+    print(i)
+    print(i2)
+    print(ip1)
+    print(ip2)
+
+
+# 激活的idfa与点击idfa_MD5相同,caid,ip+ua,ip都相同,归因方式为idfa_MD5
+def test_at5():
+    i = idfacode()
+    caid = code_nums1(32)
+    ip = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    clickios.parms['idfa_MD5'] = computeMD5upper(i)
+    clickios.parms['idfa'] = i
+    clickios.parms['ip'] = ip
+    clickios.parms['caid1'] = caid
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i
+    tkioreceive.data['context']['_idfa'] = i
+    tkioreceive.data['context']['_ip'] = ip
+    tkioreceive.data['context']['_caid'] = caid
+    tkioreceive.send_request()
+    print(i)
+    print(ip)
+
+
+# 点击激活的idfa以及idfa_MD5不相同,点击的caid1和激活的caid相同,归因方式为caid
+def test_at6():
+    i = idfacode()
+    i2 = idfacode()
+    caid = code_nums1(32)
+    caid2 = code_nums1(32)
+    ip = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    clickios.parms['idfa_MD5'] = computeMD5upper(i)
+    clickios.parms['idfa'] = i
+    clickios.parms['ip'] = ip
+    clickios.parms['caid1'] = caid
+    clickios.parms['caid2'] = caid2
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i2
+    tkioreceive.data['context']['_idfa'] = i2
+    tkioreceive.data['context']['_ip'] = ip
+    tkioreceive.data['context']['_caid1'] = caid
+    tkioreceive.send_request()
+    print(i2)
+    print(ip)
+
+
+# 点击激活的idfa,idfa_MD5不相同,点击的caid2和激活的caid相同,归因方式为caid
+def test_at7():
+    i = idfacode()
+    i2 = idfacode()
+    caid = code_nums1(32)
+    caid2 = code_nums1(32)
+    ip = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    clickios.parms['idfa_MD5'] = computeMD5upper(i)
+    clickios.parms['idfa'] = i
+    clickios.parms['ip'] = ip
+    clickios.parms['caid1'] = caid
+    clickios.parms['caid2'] = caid2
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i2
+    tkioreceive.data['context']['_idfa'] = i2
+    tkioreceive.data['context']['_ip'] = ip
+    tkioreceive.data['context']['_caid1'] = caid2
+    tkioreceive.send_request()
+    print(i2)
+    print(ip)
+
+
+# 点击激活的idfa,idfa_MD5不相同,点击的caid2和激活的caid相同,归因方式为caid
+def test_at8():
+    i = idfacode()
+    i2 = idfacode()
+    caid = code_nums1(32)
+    caid2 = code_nums1(32)
+    ip = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    clickios.parms['idfa_MD5'] = computeMD5upper(i)
+    clickios.parms['idfa'] = i
+    clickios.parms['ip'] = ip
+    clickios.parms['caid1'] = caid
+    clickios.parms['caid2'] = caid2
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i2
+    tkioreceive.data['context']['_idfa'] = i2
+    tkioreceive.data['context']['_ip'] = ip
+    tkioreceive.data['context']['_caid1'] = caid2
+    tkioreceive.send_request()
+    print(i2)
+    print(ip)
+
+
+# 点击激活的idfa,idfa_MD5不相同,点击的caid2和激活的caid1相同,归因方式为caid
+def test_at9():
+    i = idfacode()
+    i2 = idfacode()
+    caid = code_nums1(32)
+    caid2 = code_nums1(32)
+    ip = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    clickios.parms['idfa_MD5'] = computeMD5upper(i)
+    clickios.parms['idfa'] = i
+    clickios.parms['ip'] = ip
+    clickios.parms['caid1'] = caid
+    clickios.parms['caid2'] = caid2
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i2
+    tkioreceive.data['context']['_idfa'] = i2
+    tkioreceive.data['context']['_ip'] = ip
+    tkioreceive.data['context']['_caid1'] = caid2
+    tkioreceive.data['context']['_caid2'] = ''
+    tkioreceive.send_request()
+    print(i2)
+    print(ip)
+
+
+# 点击激活的idfa,idfa_MD5不相同,点击的caid1和激活的caid2相同,归因方式为caid
+def test_at10():
+    i = idfacode()
+    i2 = idfacode()
+    caid = code_nums1(32)
+    caid2 = code_nums1(32)
+    ip = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    clickios.parms['idfa_MD5'] = computeMD5upper(i)
+    clickios.parms['idfa'] = i
+    clickios.parms['ip'] = ip
+    clickios.parms['caid1'] = caid
+    clickios.parms['caid2'] = caid2
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i2
+    tkioreceive.data['context']['_idfa'] = i2
+    tkioreceive.data['context']['_ip'] = ip
+    tkioreceive.data['context']['_caid1'] = caid
+    tkioreceive.data['context']['_caid2'] = ''
+    tkioreceive.send_request()
+    print(i2)
+    print(ip)
+
+
+# 点击激活的idfa,idfa_MD5,不相同,点击的caid1为原值,激活的caid为md5加密值,无法用caid归因
+def test_at11():
+    i = idfacode()
+    i2 = idfacode()
+    caid = code_nums1(32)
+    caid2 = code_nums1(32)
+    ip = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    clickios.parms['idfa_MD5'] = computeMD5upper(i)
+    clickios.parms['idfa'] = i
+    clickios.parms['ip'] = ip
+    clickios.parms['caid1'] = caid
+    clickios.parms['caid2'] = caid2
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i2
+    tkioreceive.data['context']['_idfa'] = i2
+    tkioreceive.data['context']['_ip'] = ip
+    tkioreceive.data['context']['_caid1'] = computeMD5upper(caid)
+    tkioreceive.data['context']['_caid2'] = ''
+    tkioreceive.send_request()
+    print(i2)
+    print(ip)
+
+
+# 点击激活的idfa,idfa_MD5不相同,点击的caid1和激活的caid相同,归因方式为caid
+def test_at12():
+    i = idfacode()
+    i2 = idfacode()
+    caid = code_nums1(32)
+    caid2 = code_nums1(32)
+    ip = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    clickios.parms['idfa_MD5'] = computeMD5upper(i)
+    clickios.parms['idfa'] = i
+    clickios.parms['ip'] = ip
+    clickios.parms['caid1'] = caid
+    clickios.parms['caid2'] = caid2
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i2
+    tkioreceive.data['context']['_idfa'] = i2
+    tkioreceive.data['context']['_ip'] = ip
+    tkioreceive.data['context']['_caid'] = caid
+    tkioreceive.data['context']['_caid2'] = ''
+    tkioreceive.send_request()
+    print(i2)
+    print(ip)
+
+
+# 点击激活的idfa,idfa_MD5,不相同,点击的caid1为md5加密值,激活的caid为原值,归因方式为caid_MD5
+def test_at13():
+    i = idfacode()
+    i2 = idfacode()
+    caid = code_nums1(32)
+    caid2 = code_nums1(32)
+    ip = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    clickios.parms['idfa_MD5'] = computeMD5upper(i)
+    clickios.parms['idfa'] = i
+    clickios.parms['ip'] = ip
+    clickios.parms['caid1'] = computeMD5upper(caid)
+    clickios.parms['caid2'] = caid2
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i2
+    tkioreceive.data['context']['_idfa'] = i2
+    tkioreceive.data['context']['_ip'] = ip
+    tkioreceive.data['context']['_caid'] = caid
+    tkioreceive.data['context']['_caid2'] = ''
+    tkioreceive.send_request()
+    print(i2)
+    print(ip)
+
+
+# 点击激活的idfa,idfa_MD5,不相同,点击的caid2为原值,激活的caid2为md5加密值,无法用caid归因
+def test_at14():
+    i = idfacode()
+    i2 = idfacode()
+    caid = code_nums1(32)
+    caid2 = code_nums1(32)
+    ip = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    clickios.parms['idfa_MD5'] = computeMD5upper(i)
+    clickios.parms['idfa'] = i
+    clickios.parms['ip'] = ip
+    clickios.parms['caid1'] = ''
+    clickios.parms['caid2'] = caid2
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i2
+    tkioreceive.data['context']['_idfa'] = i2
+    tkioreceive.data['context']['_ip'] = ip
+    tkioreceive.data['context']['_caid'] = caid
+    tkioreceive.data['context']['_caid2'] = computeMD5upper(caid)
+    tkioreceive.send_request()
+    print(i2)
+    print(ip)
+
+
+# 点击激活的idfa,idfa_MD5,不相同,点击的caid2为md5加密值,激活的caid为原值,归因方式为caid_MD5
+def test_at15():
+    i = idfacode()
+    i2 = idfacode()
+    caid = code_nums1(32)
+    caid2 = code_nums1(32)
+    ip = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    clickios.parms['idfa_MD5'] = computeMD5upper(i)
+    clickios.parms['idfa'] = i
+    clickios.parms['ip'] = ip
+    clickios.parms['caid1'] = ''
+    clickios.parms['caid2'] = computeMD5upper(caid2)
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i2
+    tkioreceive.data['context']['_idfa'] = i2
+    tkioreceive.data['context']['_ip'] = ip
+    tkioreceive.data['context']['_caid'] = caid
+    tkioreceive.data['context']['_caid2'] = caid2
+    tkioreceive.send_request()
+    print(i2)
+    print(ip)
+
+
+# 点击激活的idfa,idfa_MD5,caid不相同,点击的ip+ua与激活的相同,归因到ip+ua
+def test_at16():
+    i = idfacode()
+    i2 = idfacode()
+    caid = code_nums1(32)
+    caid2 = code_nums1(32)
+    ip = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    clickios.parms['idfa_MD5'] = computeMD5upper(i)
+    clickios.parms['idfa'] = i
+    clickios.parms[
+        'ua'] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 SP-engine/2.30.0 baiduboxapp/12.13.0.10 (Baidu; P2 13.6.1)'
+    clickios.parms['ip'] = ip
+    clickios.parms['caid1'] = ''
+    clickios.parms['caid2'] = caid
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i2
+    tkioreceive.data['context']['_idfa'] = i2
+    tkioreceive.data['context']['_ip'] = ip
+    tkioreceive.data['context']['_caid'] = ''
+    tkioreceive.data['context']['_caid2'] = ''
+    tkioreceive.data['context'][
+        'ua'] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 SP-engine/2.30.0 baiduboxapp/12.13.0.10 (Baidu; P2 13.6.1)'
+    tkioreceive.send_request()
+    print(i2)
+    print(ip)
+
+
+# 点击激活的idfa,idfa_MD5,caid,ip+ua不相同,点击的ipv6+ua与激活的相同,归因到ipv6+ua
+def test_at17():
+    i = idfacode()
+    i2 = idfacode()
+    caid = code_nums1(32)
+    caid2 = code_nums1(32)
+    ip = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    ip2 = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+
+    clickios.parms['idfa_MD5'] = computeMD5upper(i)
+    clickios.parms['idfa'] = i
+    clickios.parms[
+        'ua'] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 SP-engine/2.30.0 baiduboxapp/12.13.0.10 (Baidu; P2 13.6.1)'
+    clickios.parms['ip'] = ip
+    clickios.parms['caid1'] = ''
+    clickios.parms['caid2'] = caid
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i2
+    tkioreceive.data['context']['_idfa'] = i2
+    tkioreceive.data['context']['_ip'] = ip2
+    tkioreceive.data['context']['_ipv6'] = ip
+    tkioreceive.data['context']['_caid'] = ''
+    tkioreceive.data['context']['_caid2'] = ''
+    tkioreceive.data['context'][
+        'ua'] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 SP-engine/2.30.0 baiduboxapp/12.13.0.10 (Baidu; P2 13.6.1)'
+    tkioreceive.send_request()
+    print(i)
+    print(i2)
+    print(ip)
+
+
+# 点击激活的idfa,idfa_MD5,caid,ip+ua不相同,点击的ip与激活的相同,归因到ip
+def test_at18():
+    i = idfacode()
+    i2 = idfacode()
+    caid = code_nums1(32)
+    caid2 = code_nums1(32)
+    ip = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    ip2 = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+
+    clickios.parms['idfa_MD5'] = computeMD5upper(i)
+    clickios.parms['idfa'] = i
+    clickios.parms[
+        'ua'] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_6_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 SP-engine/2.30.0 baiduboxapp/12.13.0.10 (Baidu; P2 13.6.1)'
+    clickios.parms['ip'] = ip
+    clickios.parms['caid1'] = ''
+    clickios.parms['caid2'] = caid
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i2
+    tkioreceive.data['context']['_idfa'] = i2
+    tkioreceive.data['context']['_ip'] = ip
+    tkioreceive.data['context']['_ipv6'] = ip2
+    tkioreceive.data['context']['_caid'] = ''
+    tkioreceive.data['context']['_caid2'] = ''
+    tkioreceive.data['context'][
+        'ua'] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 SP-engine/2.30.0 baiduboxapp/12.13.0.10 (Baidu; P2 13.6.1)'
+    tkioreceive.send_request()
+    print(i2)
+    print(ip)
+
+
+# 点击激活的idfa,idfa_MD5,caid,ip+ua,ip不相同,点击的ipv6与激活的相同,归因到ipv6
+def test_at19():
+    i = idfacode()
+    i2 = idfacode()
+    caid = code_nums1(32)
+    caid2 = code_nums1(32)
+    ip = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    ip2 = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    clickios.parms['idfa_MD5'] = computeMD5upper(i)
+    clickios.parms['idfa'] = i
+    clickios.parms[
+        'ua'] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_6_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 SP-engine/2.30.0 baiduboxapp/12.13.0.10 (Baidu; P2 13.6.1)'
+    clickios.parms['ip'] = ip2
+    clickios.parms['caid1'] = ''
+    clickios.parms['caid2'] = caid
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i2
+    tkioreceive.data['context']['_idfa'] = i2
+    tkioreceive.data['context']['_ip'] = ip
+    tkioreceive.data['context']['_ipv6'] = ip2
+    tkioreceive.data['context']['_caid'] = ''
+    tkioreceive.data['context']['_caid2'] = ''
+    tkioreceive.data['context'][
+        'ua'] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 SP-engine/2.30.0 baiduboxapp/12.13.0.10 (Baidu; P2 13.6.1)'
+    tkioreceive.send_request()
+    print(i2)
+    print(ip)
+
+
+# 点击激活的idfa,idfa_MD5,caid,ip+ua,ip不相同,归因到自然量
+def test_at20():
+    i = idfacode()
+    i2 = idfacode()
+    caid = code_nums1(32)
+    caid2 = code_nums1(32)
+    ip = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    ip2 = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    clickios.parms['idfa_MD5'] = computeMD5upper(i)
+    clickios.parms['idfa'] = i
+    clickios.parms[
+        'ua'] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_6_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 SP-engine/2.30.0 baiduboxapp/12.13.0.10 (Baidu; P2 13.6.1)'
+    clickios.parms['ip'] = ip2
+    clickios.parms['caid1'] = ''
+    clickios.parms['caid2'] = caid
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i2
+    tkioreceive.data['context']['_idfa'] = i2
+    tkioreceive.data['context']['_ip'] = ip
+    tkioreceive.data['context']['_ipv6'] = '3.3.3.3'
+    tkioreceive.data['context']['_caid'] = ''
+    tkioreceive.data['context']['_caid2'] = ''
+    tkioreceive.data['context'][
+        'ua'] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 SP-engine/2.30.0 baiduboxapp/12.13.0.10 (Baidu; P2 13.6.1)'
+    tkioreceive.send_request()
+    print(i2)
+    print(ip)
+
+
+# 激活中idfa为原值大写,点击为原值小写,可归因上
+def test_at21():
+    i = idfacode_lower()
+    ip = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    clickios.parms['idfa'] = i
+    clickios.parms['ip'] = ip
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i.upper()
+    tkioreceive.data['context']['_idfa'] = i.upper()
+    tkioreceive.data['context']['_ip'] = ip
+    tkioreceive.send_request()
+    print(i)
+
+
+# 激活中idfa为小写原值,点击为小写,可归因上
+def test_at22():
+    i = idfacode_lower()
+    ip = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    clickios.parms['idfa'] = i
+    clickios.parms['ip'] = ip
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i
+    tkioreceive.data['context']['_idfa'] = i
+    tkioreceive.data['context']['_ip'] = ip
+    tkioreceive.send_request()
+    print(i)
+
+
+# 激活中idfa为小写原值,点击为大写,可归因上
+def test_at23():
+    i = idfacode_lower()
+    ip = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    clickios.parms['idfa'] = i.upper()
+    clickios.parms['ip'] = ip
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i
+    tkioreceive.data['context']['_idfa'] = i
+    tkioreceive.data['context']['_ip'] = ip
+    tkioreceive.send_request()
+    print(i)
+
+
+# 激活中idfa为原值md5小写,可归因上
+# 1.点击idfa= AAA,idfa_MD5=MD5 AAA 2.激活idfa=MD5 AAA(小写)
+def test_at24():
+    i = idfacode()
+    ip = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    clickios.parms['idfa'] = i
+    clickios.parms['idfa_MD5'] = computeMD5lower(i)
+    clickios.parms['ip'] = ip
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i
+    tkioreceive.data['context']['_idfa'] = computeMD5lower(i)
+    tkioreceive.data['context']['_ip'] = ip
+    tkioreceive.send_request()
+    print(i)
+
+
+# 激活中idfa为原值md5大写,可归因上
+def test_at25():
+    i = idfacode()
+    ip = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    clickios.parms['idfa'] = i
+    clickios.parms['idfa_MD5'] = computeMD5lower(i)
+    clickios.parms['ip'] = ip
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i
+    tkioreceive.data['context']['_idfa'] = computeMD5upper(i)
+    tkioreceive.data['context']['_ip'] = ip
+    tkioreceive.send_request()
+    print(i)
+
+
+# --------------------------开启自定义归因后,对选择的设备id以及ip验证---------------涉及到配置,所以以下情况用同一条测试用例---------------
+# 自定义未选择idfa且点击激活的idfa相同,可归因上caid
+# 自定义未选择idfa,caid且点击激活的idfa,caid相同,可归因上ip+ua
+# 自定义未选择idfa,caid,ip+ua且点击激活的idfa,caid,ip+ua相同,可归因上ip
+# 自定义归因只选择ip,除ip外其他设备都相同,归因到自然量
+# 自定义归因只选择idfa,除idfa外其他设备都相同,归因到自然量
+# 自定义归因只选择caid,除caid外其他设备都相同,归因到自然量
+
+def test_at26():
+    i = idfacode()
+    i2 = idfacode()
+    caid = code_nums1(36)
+    caid2 = code_nums1(36)
+    ip1 = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    ip2 = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    clickios.parms['idfa'] = i
+    clickios.parms['ip'] = ip1
+    clickios.parms[
+        'ua'] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 SP-engine/2.30.0 baiduboxapp/12.13.0.10 (Baidu; P2 13.6.1)'
+    clickios.parms['caid1'] = caid
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i
+    tkioreceive.data['context']['_idfa'] = i
+    tkioreceive.data['context']['_ip'] = ip1
+    tkioreceive.data['context']['_caid'] = caid
+    tkioreceive.data['context'][
+        'ua'] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 SP-engine/2.30.0 baiduboxapp/12.13.0.10 (Baidu; P2 13.6.1)'
+    tkioreceive.send_request()
+    print(i)
+    print(i2)
+    print(ip1)
+
+# ----------------------归因窗口期逻辑验证---------------涉及到配置,所以以下情况用同一条测试用例---------------
+# 1.开启了自定义归因   2.选择了所有设备和ip  3.【设备ID归因回溯窗口期】为5分钟,【IP归因回溯窗口期】15分钟::1.点击激活中的idfa,ip相同2.发送点击,10分钟后发送一条激活    jointype为ip
+# 1.开启了自定义归因   2.选择了所有设备和ip  3.【设备ID归因回溯窗口期】为5分钟,【IP归因回溯窗口期】5分钟::1.点击激活中的idfa,ip相同2.发送点击,10分钟后发送一条激活     自然量
+# 1.该产品开启了【自定义归因】  2.选择了ip  3.【设备ID归因回溯窗口期】为15分钟,【IP归因回溯窗口期】5分钟::1.点击激活中的idfa,ip相同2.发送点击,10分钟后发送一条激活     自然量
+# 1.该产品开启了【自定义归因】  2.选择了ip  3.【设备ID归因回溯窗口期】为15分钟,【IP归因回溯窗口期】5分钟::1.点击激活中的idfa,ip相同2.发送点击,3分钟后发送一条激活      jointype为ip
+
+def test_at27():
+    i = idfacode()
+    i2 = idfacode()
+    caid = code_nums1(36)
+    caid2 = code_nums1(36)
+    ip1 = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    ip2 = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    clickios.parms['idfa'] = i
+    clickios.parms['ip'] = ip1
+    clickios.parms[
+        'ua'] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 SP-engine/2.30.0 baiduboxapp/12.13.0.10 (Baidu; P2 13.6.1)'
+    clickios.parms['caid1'] = caid
+    clickios.send_requestandroid('')
+    time.sleep(60)
+    tkioreceive.data['context']['_deviceid'] = i
+    tkioreceive.data['context']['_idfa'] = i
+    tkioreceive.data['context']['_ip'] = ip1
+    tkioreceive.data['context']['_caid'] = caid
+    tkioreceive.data['context'][
+        'ua'] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 SP-engine/2.30.0 baiduboxapp/12.13.0.10 (Baidu; P2 13.6.1)'
+    tkioreceive.send_request()
+    print(i)
+    print(i2)
+    print(ip1)
\ No newline at end of file
diff --git a/tkio/attributioncaseios.py b/tkio/attributioncaseios.py
index 7a1900e..51d54c3 100644
--- a/tkio/attributioncaseios.py
+++ b/tkio/attributioncaseios.py
@@ -8,6 +8,8 @@ import hashlib
 from tkio import clickios
 from tkio import tkioreceive
 
+
+# 生成idfa大写
 def idfacode():
     ret = ''
     a = "".join(random.sample(string.ascii_letters + string.digits, 8))
@@ -20,6 +22,18 @@ def idfacode():
     return ret
 
 
+# 生成idfa小写
+def idfacode_lower():
+    ret = ''
+    a = "".join(random.sample(string.ascii_letters + string.digits, 8))
+    b = "".join(random.sample(string.ascii_letters + string.digits, 4))
+    c = "".join(random.sample(string.ascii_letters + string.digits, 4))
+    d = "".join(random.sample(string.ascii_letters + string.digits, 4))
+    e = "".join(random.sample(string.ascii_letters + string.digits, 12))
+    i = (a + "-" + b + "-" + c + "-" + d + "-" + e).lower()
+    ret += i
+    return ret
+
 
 # md5加密转大写
 def computeMD5upper(message):
@@ -28,8 +42,17 @@ def computeMD5upper(message):
     return m.hexdigest().upper()
 
 
+# md5加密转xiao写
+def computeMD5lower(message):
+    m = hashlib.md5()
+    m.update(message.encode(encoding='utf-8'))
+    return m.hexdigest()
+
+
 # 生成小写字母加数字组合
 n = 10
+
+
 def code_nums1(n=6):
     ret = ''
     for i in range(n):
@@ -39,6 +62,7 @@ def code_nums1(n=6):
         ret += s
     return ret
 
+
 # 1.点击1:idfa=111,ip=222
 # 2.点击2:idfa=444,ip=333
 # 3.激活:idfa=111,ip=333
@@ -91,30 +115,23 @@ def test_at2():
     print(ip2)
 
 
-
 # 点击激活的idfa,caid,ip+ua,ip都相同,归因方式为idfa
 def test_at3():
     i = idfacode()
-    i2 = idfacode()
+    caid = code_nums1(36)
     ip1 = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
-    ip2 = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
     clickios.parms['idfa'] = i
     clickios.parms['ip'] = ip1
-    clickios.send_requestandroid('')
-    time.sleep(3)
-    clickios.parms['idfa'] = i2
-    clickios.parms['ip'] = ip2
+    clickios.parms['caid1'] = caid
     clickios.send_requestandroid('')
     time.sleep(5)
-    tkioreceive.data['context']['_deviceid'] = i2
-    tkioreceive.data['context']['_idfa'] = i2
+    tkioreceive.data['context']['_deviceid'] = i
+    tkioreceive.data['context']['_idfa'] = i
     tkioreceive.data['context']['_ip'] = ip1
+    tkioreceive.data['context']['_caid'] = caid
     tkioreceive.send_request()
     print(i)
-    print(i2)
     print(ip1)
-    print(ip2)
-
 
 
 # 在优先级同样的情况下,优先匹配lastclick
@@ -150,13 +167,544 @@ def test_at5():
     clickios.parms['idfa_MD5'] = computeMD5upper(i)
     clickios.parms['idfa'] = i
     clickios.parms['ip'] = ip
-    clickios.parms['caid'] = caid
+    clickios.parms['caid1'] = caid
     clickios.send_requestandroid('')
     time.sleep(5)
     tkioreceive.data['context']['_deviceid'] = i
     tkioreceive.data['context']['_idfa'] = i
     tkioreceive.data['context']['_ip'] = ip
+    tkioreceive.data['context']['_caid'] = caid
+    tkioreceive.send_request()
+    print(i)
+    print(ip)
+
+
+# 点击激活的idfa以及idfa_MD5不相同,点击的caid1和激活的caid相同,归因方式为caid
+def test_at6():
+    i = idfacode()
+    i2 = idfacode()
+    caid = code_nums1(32)
+    caid2 = code_nums1(32)
+    ip = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    clickios.parms['idfa_MD5'] = computeMD5upper(i)
+    clickios.parms['idfa'] = i
+    clickios.parms['ip'] = ip
+    clickios.parms['caid1'] = caid
+    clickios.parms['caid2'] = caid2
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i2
+    tkioreceive.data['context']['_idfa'] = i2
+    tkioreceive.data['context']['_ip'] = ip
+    tkioreceive.data['context']['_caid1'] = caid
+    tkioreceive.send_request()
+    print(i2)
+    print(ip)
+
+
+# 点击激活的idfa,idfa_MD5不相同,点击的caid2和激活的caid相同,归因方式为caid
+def test_at7():
+    i = idfacode()
+    i2 = idfacode()
+    caid = code_nums1(32)
+    caid2 = code_nums1(32)
+    ip = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    clickios.parms['idfa_MD5'] = computeMD5upper(i)
+    clickios.parms['idfa'] = i
+    clickios.parms['ip'] = ip
+    clickios.parms['caid1'] = caid
+    clickios.parms['caid2'] = caid2
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i2
+    tkioreceive.data['context']['_idfa'] = i2
+    tkioreceive.data['context']['_ip'] = ip
+    tkioreceive.data['context']['_caid1'] = caid2
+    tkioreceive.send_request()
+    print(i2)
+    print(ip)
+
+
+# 点击激活的idfa,idfa_MD5不相同,点击的caid2和激活的caid相同,归因方式为caid
+def test_at8():
+    i = idfacode()
+    i2 = idfacode()
+    caid = code_nums1(32)
+    caid2 = code_nums1(32)
+    ip = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    clickios.parms['idfa_MD5'] = computeMD5upper(i)
+    clickios.parms['idfa'] = i
+    clickios.parms['ip'] = ip
+    clickios.parms['caid1'] = caid
+    clickios.parms['caid2'] = caid2
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i2
+    tkioreceive.data['context']['_idfa'] = i2
+    tkioreceive.data['context']['_ip'] = ip
+    tkioreceive.data['context']['_caid1'] = caid2
+    tkioreceive.send_request()
+    print(i2)
+    print(ip)
+
+
+# 点击激活的idfa,idfa_MD5不相同,点击的caid2和激活的caid1相同,归因方式为caid
+def test_at9():
+    i = idfacode()
+    i2 = idfacode()
+    caid = code_nums1(32)
+    caid2 = code_nums1(32)
+    ip = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    clickios.parms['idfa_MD5'] = computeMD5upper(i)
+    clickios.parms['idfa'] = i
+    clickios.parms['ip'] = ip
+    clickios.parms['caid1'] = caid
+    clickios.parms['caid2'] = caid2
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i2
+    tkioreceive.data['context']['_idfa'] = i2
+    tkioreceive.data['context']['_ip'] = ip
+    tkioreceive.data['context']['_caid1'] = caid2
+    tkioreceive.data['context']['_caid2'] = ''
+    tkioreceive.send_request()
+    print(i2)
+    print(ip)
+
+
+# 点击激活的idfa,idfa_MD5不相同,点击的caid1和激活的caid2相同,归因方式为caid
+def test_at10():
+    i = idfacode()
+    i2 = idfacode()
+    caid = code_nums1(32)
+    caid2 = code_nums1(32)
+    ip = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    clickios.parms['idfa_MD5'] = computeMD5upper(i)
+    clickios.parms['idfa'] = i
+    clickios.parms['ip'] = ip
+    clickios.parms['caid1'] = caid
+    clickios.parms['caid2'] = caid2
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i2
+    tkioreceive.data['context']['_idfa'] = i2
+    tkioreceive.data['context']['_ip'] = ip
     tkioreceive.data['context']['_caid1'] = caid
+    tkioreceive.data['context']['_caid2'] = ''
+    tkioreceive.send_request()
+    print(i2)
+    print(ip)
+
+
+# 点击激活的idfa,idfa_MD5,不相同,点击的caid1为原值,激活的caid为md5加密值,无法用caid归因
+def test_at11():
+    i = idfacode()
+    i2 = idfacode()
+    caid = code_nums1(32)
+    caid2 = code_nums1(32)
+    ip = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    clickios.parms['idfa_MD5'] = computeMD5upper(i)
+    clickios.parms['idfa'] = i
+    clickios.parms['ip'] = ip
+    clickios.parms['caid1'] = caid
+    clickios.parms['caid2'] = caid2
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i2
+    tkioreceive.data['context']['_idfa'] = i2
+    tkioreceive.data['context']['_ip'] = ip
+    tkioreceive.data['context']['_caid1'] = computeMD5upper(caid)
+    tkioreceive.data['context']['_caid2'] = ''
+    tkioreceive.send_request()
+    print(i2)
+    print(ip)
+
+
+# 点击激活的idfa,idfa_MD5不相同,点击的caid1和激活的caid相同,归因方式为caid
+def test_at12():
+    i = idfacode()
+    i2 = idfacode()
+    caid = code_nums1(32)
+    caid2 = code_nums1(32)
+    ip = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    clickios.parms['idfa_MD5'] = computeMD5upper(i)
+    clickios.parms['idfa'] = i
+    clickios.parms['ip'] = ip
+    clickios.parms['caid1'] = caid
+    clickios.parms['caid2'] = caid2
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i2
+    tkioreceive.data['context']['_idfa'] = i2
+    tkioreceive.data['context']['_ip'] = ip
+    tkioreceive.data['context']['_caid'] = caid
+    tkioreceive.data['context']['_caid2'] = ''
+    tkioreceive.send_request()
+    print(i2)
+    print(ip)
+
+
+# 点击激活的idfa,idfa_MD5,不相同,点击的caid1为md5加密值,激活的caid为原值,归因方式为caid_MD5
+def test_at13():
+    i = idfacode()
+    i2 = idfacode()
+    caid = code_nums1(32)
+    caid2 = code_nums1(32)
+    ip = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    clickios.parms['idfa_MD5'] = computeMD5upper(i)
+    clickios.parms['idfa'] = i
+    clickios.parms['ip'] = ip
+    clickios.parms['caid1'] = computeMD5upper(caid)
+    clickios.parms['caid2'] = caid2
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i2
+    tkioreceive.data['context']['_idfa'] = i2
+    tkioreceive.data['context']['_ip'] = ip
+    tkioreceive.data['context']['_caid'] = caid
+    tkioreceive.data['context']['_caid2'] = ''
+    tkioreceive.send_request()
+    print(i2)
+    print(ip)
+
+
+# 点击激活的idfa,idfa_MD5,不相同,点击的caid2为原值,激活的caid2为md5加密值,无法用caid归因
+def test_at14():
+    i = idfacode()
+    i2 = idfacode()
+    caid = code_nums1(32)
+    caid2 = code_nums1(32)
+    ip = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    clickios.parms['idfa_MD5'] = computeMD5upper(i)
+    clickios.parms['idfa'] = i
+    clickios.parms['ip'] = ip
+    clickios.parms['caid1'] = ''
+    clickios.parms['caid2'] = caid2
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i2
+    tkioreceive.data['context']['_idfa'] = i2
+    tkioreceive.data['context']['_ip'] = ip
+    tkioreceive.data['context']['_caid'] = caid
+    tkioreceive.data['context']['_caid2'] = computeMD5upper(caid)
+    tkioreceive.send_request()
+    print(i2)
+    print(ip)
+
+
+# 点击激活的idfa,idfa_MD5,不相同,点击的caid2为md5加密值,激活的caid为原值,归因方式为caid_MD5
+def test_at15():
+    i = idfacode()
+    i2 = idfacode()
+    caid = code_nums1(32)
+    caid2 = code_nums1(32)
+    ip = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    clickios.parms['idfa_MD5'] = computeMD5upper(i)
+    clickios.parms['idfa'] = i
+    clickios.parms['ip'] = ip
+    clickios.parms['caid1'] = ''
+    clickios.parms['caid2'] = computeMD5upper(caid2)
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i2
+    tkioreceive.data['context']['_idfa'] = i2
+    tkioreceive.data['context']['_ip'] = ip
+    tkioreceive.data['context']['_caid'] = caid
+    tkioreceive.data['context']['_caid2'] = caid2
+    tkioreceive.send_request()
+    print(i2)
+    print(ip)
+
+
+# 点击激活的idfa,idfa_MD5,caid不相同,点击的ip+ua与激活的相同,归因到ip+ua
+def test_at16():
+    i = idfacode()
+    i2 = idfacode()
+    caid = code_nums1(32)
+    caid2 = code_nums1(32)
+    ip = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    clickios.parms['idfa_MD5'] = computeMD5upper(i)
+    clickios.parms['idfa'] = i
+    clickios.parms[
+        'ua'] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 SP-engine/2.30.0 baiduboxapp/12.13.0.10 (Baidu; P2 13.6.1)'
+    clickios.parms['ip'] = ip
+    clickios.parms['caid1'] = ''
+    clickios.parms['caid2'] = caid
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i2
+    tkioreceive.data['context']['_idfa'] = i2
+    tkioreceive.data['context']['_ip'] = ip
+    tkioreceive.data['context']['_caid'] = ''
+    tkioreceive.data['context']['_caid2'] = ''
+    tkioreceive.data['context'][
+        'ua'] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 SP-engine/2.30.0 baiduboxapp/12.13.0.10 (Baidu; P2 13.6.1)'
+    tkioreceive.send_request()
+    print(i2)
+    print(ip)
+
+
+# 点击激活的idfa,idfa_MD5,caid,ip+ua不相同,点击的ipv6+ua与激活的相同,归因到ipv6+ua
+def test_at17():
+    i = idfacode()
+    i2 = idfacode()
+    caid = code_nums1(32)
+    caid2 = code_nums1(32)
+    ip = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    ip2 = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+
+    clickios.parms['idfa_MD5'] = computeMD5upper(i)
+    clickios.parms['idfa'] = i
+    clickios.parms[
+        'ua'] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 SP-engine/2.30.0 baiduboxapp/12.13.0.10 (Baidu; P2 13.6.1)'
+    clickios.parms['ip'] = ip
+    clickios.parms['caid1'] = ''
+    clickios.parms['caid2'] = caid
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i2
+    tkioreceive.data['context']['_idfa'] = i2
+    tkioreceive.data['context']['_ip'] = ip2
+    tkioreceive.data['context']['_ipv6'] = ip
+    tkioreceive.data['context']['_caid'] = ''
+    tkioreceive.data['context']['_caid2'] = ''
+    tkioreceive.data['context'][
+        'ua'] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 SP-engine/2.30.0 baiduboxapp/12.13.0.10 (Baidu; P2 13.6.1)'
     tkioreceive.send_request()
     print(i)
+    print(i2)
+    print(ip)
+
+
+# 点击激活的idfa,idfa_MD5,caid,ip+ua不相同,点击的ip与激活的相同,归因到ip
+def test_at18():
+    i = idfacode()
+    i2 = idfacode()
+    caid = code_nums1(32)
+    caid2 = code_nums1(32)
+    ip = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    ip2 = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+
+    clickios.parms['idfa_MD5'] = computeMD5upper(i)
+    clickios.parms['idfa'] = i
+    clickios.parms[
+        'ua'] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_6_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 SP-engine/2.30.0 baiduboxapp/12.13.0.10 (Baidu; P2 13.6.1)'
+    clickios.parms['ip'] = ip
+    clickios.parms['caid1'] = ''
+    clickios.parms['caid2'] = caid
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i2
+    tkioreceive.data['context']['_idfa'] = i2
+    tkioreceive.data['context']['_ip'] = ip
+    tkioreceive.data['context']['_ipv6'] = ip2
+    tkioreceive.data['context']['_caid'] = ''
+    tkioreceive.data['context']['_caid2'] = ''
+    tkioreceive.data['context'][
+        'ua'] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 SP-engine/2.30.0 baiduboxapp/12.13.0.10 (Baidu; P2 13.6.1)'
+    tkioreceive.send_request()
+    print(i2)
+    print(ip)
+
+
+# 点击激活的idfa,idfa_MD5,caid,ip+ua,ip不相同,点击的ipv6与激活的相同,归因到ipv6
+def test_at19():
+    i = idfacode()
+    i2 = idfacode()
+    caid = code_nums1(32)
+    caid2 = code_nums1(32)
+    ip = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    ip2 = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    clickios.parms['idfa_MD5'] = computeMD5upper(i)
+    clickios.parms['idfa'] = i
+    clickios.parms[
+        'ua'] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_6_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 SP-engine/2.30.0 baiduboxapp/12.13.0.10 (Baidu; P2 13.6.1)'
+    clickios.parms['ip'] = ip2
+    clickios.parms['caid1'] = ''
+    clickios.parms['caid2'] = caid
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i2
+    tkioreceive.data['context']['_idfa'] = i2
+    tkioreceive.data['context']['_ip'] = ip
+    tkioreceive.data['context']['_ipv6'] = ip2
+    tkioreceive.data['context']['_caid'] = ''
+    tkioreceive.data['context']['_caid2'] = ''
+    tkioreceive.data['context'][
+        'ua'] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 SP-engine/2.30.0 baiduboxapp/12.13.0.10 (Baidu; P2 13.6.1)'
+    tkioreceive.send_request()
+    print(i2)
+    print(ip)
+
+
+# 点击激活的idfa,idfa_MD5,caid,ip+ua,ip不相同,归因到自然量
+def test_at20():
+    i = idfacode()
+    i2 = idfacode()
+    caid = code_nums1(32)
+    caid2 = code_nums1(32)
+    ip = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    ip2 = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    clickios.parms['idfa_MD5'] = computeMD5upper(i)
+    clickios.parms['idfa'] = i
+    clickios.parms[
+        'ua'] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_6_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 SP-engine/2.30.0 baiduboxapp/12.13.0.10 (Baidu; P2 13.6.1)'
+    clickios.parms['ip'] = ip2
+    clickios.parms['caid1'] = ''
+    clickios.parms['caid2'] = caid
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i2
+    tkioreceive.data['context']['_idfa'] = i2
+    tkioreceive.data['context']['_ip'] = ip
+    tkioreceive.data['context']['_ipv6'] = '3.3.3.3'
+    tkioreceive.data['context']['_caid'] = ''
+    tkioreceive.data['context']['_caid2'] = ''
+    tkioreceive.data['context'][
+        'ua'] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 SP-engine/2.30.0 baiduboxapp/12.13.0.10 (Baidu; P2 13.6.1)'
+    tkioreceive.send_request()
+    print(i2)
     print(ip)
+
+
+# 激活中idfa为原值大写,点击为原值小写,可归因上
+def test_at21():
+    i = idfacode_lower()
+    ip = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    clickios.parms['idfa'] = i
+    clickios.parms['ip'] = ip
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i.upper()
+    tkioreceive.data['context']['_idfa'] = i.upper()
+    tkioreceive.data['context']['_ip'] = ip
+    tkioreceive.send_request()
+    print(i)
+
+
+# 激活中idfa为小写原值,点击为小写,可归因上
+def test_at22():
+    i = idfacode_lower()
+    ip = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    clickios.parms['idfa'] = i
+    clickios.parms['ip'] = ip
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i
+    tkioreceive.data['context']['_idfa'] = i
+    tkioreceive.data['context']['_ip'] = ip
+    tkioreceive.send_request()
+    print(i)
+
+
+# 激活中idfa为小写原值,点击为大写,可归因上
+def test_at23():
+    i = idfacode_lower()
+    ip = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    clickios.parms['idfa'] = i.upper()
+    clickios.parms['ip'] = ip
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i
+    tkioreceive.data['context']['_idfa'] = i
+    tkioreceive.data['context']['_ip'] = ip
+    tkioreceive.send_request()
+    print(i)
+
+
+# 激活中idfa为原值md5小写,可归因上
+# 1.点击idfa= AAA,idfa_MD5=MD5 AAA 2.激活idfa=MD5 AAA(小写)
+def test_at24():
+    i = idfacode()
+    ip = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    clickios.parms['idfa'] = i
+    clickios.parms['idfa_MD5'] = computeMD5lower(i)
+    clickios.parms['ip'] = ip
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i
+    tkioreceive.data['context']['_idfa'] = computeMD5lower(i)
+    tkioreceive.data['context']['_ip'] = ip
+    tkioreceive.send_request()
+    print(i)
+
+
+# 激活中idfa为原值md5大写,可归因上
+def test_at25():
+    i = idfacode()
+    ip = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    clickios.parms['idfa'] = i
+    clickios.parms['idfa_MD5'] = computeMD5lower(i)
+    clickios.parms['ip'] = ip
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i
+    tkioreceive.data['context']['_idfa'] = computeMD5upper(i)
+    tkioreceive.data['context']['_ip'] = ip
+    tkioreceive.send_request()
+    print(i)
+
+
+# --------------------------开启自定义归因后,对选择的设备id以及ip验证---------------涉及到配置,所以以下情况用同一条测试用例---------------
+# 自定义未选择idfa且点击激活的idfa相同,可归因上caid
+# 自定义未选择idfa,caid且点击激活的idfa,caid相同,可归因上ip+ua
+# 自定义未选择idfa,caid,ip+ua且点击激活的idfa,caid,ip+ua相同,可归因上ip
+# 自定义归因只选择ip,除ip外其他设备都相同,归因到自然量
+# 自定义归因只选择idfa,除idfa外其他设备都相同,归因到自然量
+# 自定义归因只选择caid,除caid外其他设备都相同,归因到自然量
+
+def test_at26():
+    i = idfacode()
+    i2 = idfacode()
+    caid = code_nums1(36)
+    caid2 = code_nums1(36)
+    ip1 = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    ip2 = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    clickios.parms['idfa'] = i
+    clickios.parms['ip'] = ip1
+    clickios.parms[
+        'ua'] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 SP-engine/2.30.0 baiduboxapp/12.13.0.10 (Baidu; P2 13.6.1)'
+    clickios.parms['caid1'] = caid
+    clickios.send_requestandroid('')
+    time.sleep(5)
+    tkioreceive.data['context']['_deviceid'] = i
+    tkioreceive.data['context']['_idfa'] = i
+    tkioreceive.data['context']['_ip'] = ip1
+    tkioreceive.data['context']['_caid'] = caid
+    tkioreceive.data['context'][
+        'ua'] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 SP-engine/2.30.0 baiduboxapp/12.13.0.10 (Baidu; P2 13.6.1)'
+    tkioreceive.send_request()
+    print(i)
+    print(i2)
+    print(ip1)
+
+# ----------------------归因窗口期逻辑验证---------------涉及到配置,所以以下情况用同一条测试用例---------------
+# 1.开启了自定义归因   2.选择了所有设备和ip  3.【设备ID归因回溯窗口期】为5分钟,【IP归因回溯窗口期】15分钟::1.点击激活中的idfa,ip相同2.发送点击,10分钟后发送一条激活    jointype为ip
+# 1.开启了自定义归因   2.选择了所有设备和ip  3.【设备ID归因回溯窗口期】为5分钟,【IP归因回溯窗口期】5分钟::1.点击激活中的idfa,ip相同2.发送点击,10分钟后发送一条激活     自然量
+# 1.该产品开启了【自定义归因】  2.选择了ip  3.【设备ID归因回溯窗口期】为15分钟,【IP归因回溯窗口期】5分钟::1.点击激活中的idfa,ip相同2.发送点击,10分钟后发送一条激活     自然量
+# 1.该产品开启了【自定义归因】  2.选择了ip  3.【设备ID归因回溯窗口期】为15分钟,【IP归因回溯窗口期】5分钟::1.点击激活中的idfa,ip相同2.发送点击,3分钟后发送一条激活      jointype为ip
+
+def test_at27():
+    i = idfacode()
+    i2 = idfacode()
+    caid = code_nums1(36)
+    caid2 = code_nums1(36)
+    ip1 = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    ip2 = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+    clickios.parms['idfa'] = i
+    clickios.parms['ip'] = ip1
+    clickios.parms[
+        'ua'] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 SP-engine/2.30.0 baiduboxapp/12.13.0.10 (Baidu; P2 13.6.1)'
+    clickios.parms['caid1'] = caid
+    clickios.send_requestandroid('')
+    time.sleep(60)
+    tkioreceive.data['context']['_deviceid'] = i
+    tkioreceive.data['context']['_idfa'] = i
+    tkioreceive.data['context']['_ip'] = ip1
+    tkioreceive.data['context']['_caid'] = caid
+    tkioreceive.data['context'][
+        'ua'] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 SP-engine/2.30.0 baiduboxapp/12.13.0.10 (Baidu; P2 13.6.1)'
+    tkioreceive.send_request()
+    print(i)
+    print(i2)
+    print(ip1)
\ No newline at end of file
diff --git a/tkio/clickandroid.py b/tkio/clickandroid.py
new file mode 100644
index 0000000..5f4b729
--- /dev/null
+++ b/tkio/clickandroid.py
@@ -0,0 +1,40 @@
+from numpy import long
+
+from android_event.android_script import allEvent
+import random
+import requests
+import socket
+import struct
+import time
+import datetime
+# 导入hashlib模块进行md5操作
+import hashlib
+
+ip = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+
+
+
+
+
+parms = {
+    'click_time': str(round(time.time() * 1000)),
+    'idfa': '',
+    'idfa_MD5': '',
+    # 'idfv': 'IFV_64F5A794-A942-4209-81B0-D28FD01E9287',
+    'ip': ip,
+    'ua': 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 SP-engine/2.30.0 baiduboxapp/12.13.0.10 (Baidu; P2 13.6.1)',
+    # ios
+    # Mozilla/5.0 (iPhone; CPU iPhone OS 13_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 SP-engine/2.30.0 baiduboxapp/12.13.0.10 (Baidu; P2 13.6.1)
+    # android
+    # Mozilla/5.0 (Linux; U; Android 7.0; zh-cn; Nexus 5X Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko)Version/4.0 Chrome/37.0.0.0 MQQBrowser/7.3 Mobile Safari/537.36
+
+}
+
+
+def send_requestandroid(hc):
+    url1 = 'http://52.80.137.106:8083/tkio/3u63Uza?noredirect=true' + hc
+    # url1 = 'https://uri6.com/tkio/Q3um6na?noredirect=true' + hc
+    response = requests.get(url=url1, params=parms, timeout=10, verify=False)
+    print(response.text)
+    print(url1)
+    return response
diff --git a/tkio/tkioreceiveandroid.py b/tkio/tkioreceiveandroid.py
new file mode 100644
index 0000000..42de362
--- /dev/null
+++ b/tkio/tkioreceiveandroid.py
@@ -0,0 +1,60 @@
+import requests
+import time
+import json
+import socket
+import struct
+import random
+import hashlib
+
+data = {
+    "what": "install",
+    "appid": "7f43b32bad452c092096136c9be73d09",
+    "context": {
+        "_deviceid": "",
+        "_idfa": "",
+        "_idfv": "",
+        "_ip": "",
+        "_manufacturer": "vivo",
+        "_ryos": "ios",
+        "_rydevicetype": "vivox9",
+        "_networktype": "5g",
+        "_resolution": "1344*750",
+        "_carrier": "111",
+        "_timestamp": 1655291783782,
+        "_model": "jixing",
+        "_ryosversion": "13.6.1",
+        "__model": "jixing"
+    },
+    "when": int(round(time.time() * 1000)),
+    "ds": "2022-06-15",
+    "who": "lxx_test"
+}
+
+headers = {
+    'Content-Type': 'application/json'
+}
+
+data_temp = json.dumps(data)
+
+
+def send_request():
+    global data
+    # 测试
+    url = "http://52.80.137.106:8080/receive/tkio/install"
+    # 线上
+    # url = "http://log.trackingio.com/receive/tkio/install"
+    data['context']['install_time'] = int(round(time.time() * 1000))
+    print(data)
+    response = requests.request("POST", url, headers=headers, data=json.dumps(data))
+    print(response.text)
+    # 全局data
+    data = json.loads(data_temp)
+    response = json.loads(response.text)
+    s = str(response["status"])
+    response["status"] = s
+    return response
+
+
+def test_se1():
+    data["appid"] = "16dc0cb882d3dbec4f7f66251a84d6dd"
+    send_request()