Răsfoiți Sursa

Merge branch 'test' of http://192.168.136.99:3000/servers/ASJServer into peng

peng 2 ani în urmă
părinte
comite
27c8d509a6

+ 46 - 31
Controller/DeviceConfirmRegion.py

@@ -1,17 +1,17 @@
-import logging
 import time
 
 from django.utils.decorators import method_decorator
 
 from django.views.decorators.csrf import csrf_exempt
 from django.views.generic import TemplateView
-from Model.models import CountryModel, RegionModel, P2PIpModel, DeviceDomainModel, DeviceDomainRegionModel
+from Model.models import CountryModel, RegionModel, P2PIpModel, DeviceDomainModel, DeviceDomainRegionModel, IPAddr
 from Object.ResponseObject import ResponseObject
 from Service.CommonService import CommonService
+from Object.IPWeatherObject import IPQuery
 
 
-#确认设备所在地区
 class ConfirmRegion(TemplateView):
+    # 设备根据ip获取域名
     @method_decorator(csrf_exempt)
     def dispatch(self, *args, **kwargs):
         return super(ConfirmRegion, self).dispatch(*args, **kwargs)
@@ -21,28 +21,41 @@ class ConfirmRegion(TemplateView):
         request.encoding = 'utf-8'
         try:
             ip = CommonService.get_ip_address(request)
-            device_domain_data = {'ip': ip}
-            ipInfo = CommonService.getIpIpInfo(ip, 'CN')
-            logger = logging.getLogger('info')
-            logger.info('设备获取域名---ip:{},country_code:{}'.format(ip, ipInfo['country_code']))
-            if ipInfo['country_code']:
-                device_domain_data['country_name'] = ipInfo['country_code']
-                device_request_url = CountryModel.objects.filter(country_code=ipInfo['country_code']).values("region__api")
-                if device_request_url.exists():
-                    api = device_request_url[0]['region__api']
-                    device_domain_data['api'] = api
-                    DeviceDomainModel.objects.create(**device_domain_data)
-                    return response.json(0, {'request_api_url': api})
-
-            # 不存在默认返回美洲地区api。
-            api = RegionModel.objects.filter(continent_code='NA').values("api")
-            device_domain_data['country_name'] = 'NA'
-            device_domain_data['api'] = api[0]['api']
-            DeviceDomainModel.objects.create(**device_domain_data)
-            return response.json(0, {'request_api_url': api[0]['api']})
+            device_domain_qs = DeviceDomainModel.objects.filter(ip=ip)
+
+            # 获取国家编码
+            ip_addr_qs = IPAddr.objects.filter(ip=ip).values('country_code')
+            if ip_addr_qs.exists():
+                country_code = ip_addr_qs[0]['country_code']
+            else:
+                ip_qs = IPQuery(ip)
+                country_code = ip_qs.country_id
+
+            if country_code:
+                country_qs = CountryModel.objects.filter(country_code=country_code).\
+                    values('region__api', 'region__push_api')
+                if country_qs.exists():
+                    api = country_qs[0]['region__api']
+                    push_api = country_qs[0]['region__push_api']
+
+                    if not device_domain_qs.exists():
+                        DeviceDomainModel.objects.create(ip=ip, country_name=country_code, api=api)
+
+                    return response.json(0, {'request_api_url': api, 'push_api_url': push_api})
+
+            # 不存在则返回美洲域名
+            region_qs = RegionModel.objects.filter(continent_code='NA').values('api', 'push_api')
+            api = region_qs[0]['api']
+            push_api = region_qs[0]['push_api']
+
+            if not device_domain_qs.exists():
+                DeviceDomainModel.objects.create(ip=ip, country_name='NA', api=api)
+
+            return response.json(0, {'request_api_url': api, 'push_api_url': push_api})
         except Exception as e:
             print(e)
-            return response.json(0, {'request_api_url': 'https://www.dvema.com'})
+            return response.json(0, {'request_api_url': 'https://www.dvema.com',
+                                     'push_api_url': 'https://push.dvema.com'})
 
 
 # 根据设备的ip返回域名和地区id
@@ -101,16 +114,15 @@ class ConfirmRegionV2(TemplateView):
         region_id = region_qs[0]['id']
         return api, region_id
 
-#确认设备所在地区
+
 class Device_Region(object):
 
     def get_device_region(self, ip):
-
         ipInfo = CommonService.getIpIpInfo(ip, "CN")
-
-        #暂时测试国外
+        # 暂时测试国外
         if ipInfo['country_code']:
-            device_request_url = CountryModel.objects.filter(country_code=ipInfo['country_code']).values("region__api","region__id")
+            device_request_url = CountryModel.objects.filter(country_code=ipInfo['country_code']).\
+                values("region__api", "region__id")
             if device_request_url.exists():
                 return device_request_url[0]['region__id']
         # 不存在默认返回美洲地区api
@@ -149,7 +161,8 @@ class StatisticsIpRegion(TemplateView):
                 # 已存在数据,更新p2p请求次数和relay请求次数
                 p2p_request_times = p2p_ip_qs[0]['p2p_request_times'] + p2p_request_times
                 relay_request_times = p2p_ip_qs[0]['relay_request_times'] + relay_request_times
-                p2p_ip_qs.update(p2p_request_times=p2p_request_times, relay_request_times=relay_request_times, update_time=now_time)
+                p2p_ip_qs.update(p2p_request_times=p2p_request_times, relay_request_times=relay_request_times,
+                                 update_time=now_time)
             else:
                 # 根据ip确定位置信息
                 ip_info = CommonService.getIpIpInfo(ip, 'CN')
@@ -163,13 +176,15 @@ class StatisticsIpRegion(TemplateView):
                 region_name = ip_info['region_name']
                 city_name = ip_info['city_name']
                 P2PIpModel.objects.create(uid=uid, ip=ip, continent_name=continent_name, country_name=country_name,
-                                          region_name=region_name, city_name=city_name, p2p_request_times=p2p_request_times,
-                                          relay_request_times=relay_request_times, add_time=now_time, update_time=now_time)
+                                          region_name=region_name, city_name=city_name,
+                                          p2p_request_times=p2p_request_times, relay_request_times=relay_request_times,
+                                          add_time=now_time, update_time=now_time)
             return response.json(0)
         except Exception as e:
             print(e)
             return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
+
 def confirm_country_with_ip(request):
     '''
     根据ip统计设备所在国家的程序,

+ 11 - 1
Controller/EquipmentManagerV3.py

@@ -21,6 +21,7 @@ from Model.models import Device_Info, UID_Bucket, UID_Preview, UidSetModel, UidC
     DeviceCloudPhotoInfo, UidPushModel, ExperienceContextModel, LogModel
 from Object.ResponseObject import ResponseObject
 from Object.TokenObject import TokenObject
+from Object.utils import LocalDateTimeUtil
 from Service.CommonService import CommonService
 from Service.EquipmentInfoService import EquipmentInfoService
 from Service.ModelService import ModelService
@@ -796,7 +797,16 @@ class EquipmentManagerV3(View):
                 p['uid_version'] = ''
                 p['ucode'] = ''
             p['View_Password'] = self.encrypt_pwd(p['View_Password'])
-
+            if p['is_ai'] != 2:
+                timestamp = int(time.time())  # 时间戳值
+                timezone_offset = "+08:00"  # 时区偏移量(例如:+08:00)
+                now_time = LocalDateTimeUtil.get_date_time(timestamp, timezone_offset)
+                datetime_bj = 1692979200
+                # 转换为日期时间对象
+                dt = LocalDateTimeUtil.get_date_time(datetime_bj, timezone_offset)
+                if now_time >= dt:
+                    logging.info('{}不显示AI按钮'.format(p_uid))
+                    p['is_ai'] = 2
             # 判断设备是否支持4G
             uid_set_qs = UidSetModel.objects.filter(uid=p['UID']).values('mobile_4g')
             if uid_set_qs.exists():

+ 17 - 5
Controller/ShadowController.py

@@ -5,7 +5,7 @@ from django.http import JsonResponse
 
 from Ansjer.config import SERVER_TYPE, LOGGER
 from Model.models import Device_Info, UidSetModel, UID_Preview, VoicePromptModel, UID_Bucket, UidChannelSetModel, \
-    AiService, CountryModel, CityInformation
+    AiService, CountryModel, CityInformation, IPAddr
 from Object.ETkObject import ETkObject
 from Service.CommonService import CommonService
 from Object.IPWeatherObject import IPQuery
@@ -75,8 +75,9 @@ def update_device_shadow(request):
             uid_set_qs = UidSetModel.objects.filter(uid=uid).values('ip')
             if uid_set_qs.exists():
                 if ip != uid_set_qs[0]['ip']:
-                    ip_qs = IPQuery(ip)
-                    district = ip_qs.district
+                    # 查询ip区级信息
+                    district = get_district(ip)
+
                     city_information_qs = CityInformation.objects.filter(district=district).values('city_id')
                     if city_information_qs.exists():
                         city_id = city_information_qs[0]['city_id']
@@ -148,8 +149,9 @@ def update_device_shadow(request):
             qs_dict['tb_country'] = country
         LOGGER.info('{} qs_dict: {}'.format(uid, qs_dict))
 
-        ip_qs = IPQuery(ip)
-        district = ip_qs.district
+        # 查询ip区级信息
+        district = get_district(ip)
+
         city_information_qs = CityInformation.objects.filter(district=district).values('city_id')
         if city_information_qs.exists():
             city_id = city_information_qs[0]['city_id']
@@ -172,3 +174,13 @@ def update_device_shadow(request):
     except Exception as e:
         LOGGER.info('更新设备影子异常: {}'.format(repr(e)))
         return JsonResponse(status=200, data={'code': 1000001, 'update_shadow_error': repr(e)})
+
+
+def get_district(ip):
+    ip_addr_qs = IPAddr.objects.filter(ip=ip).values('district')
+    if ip_addr_qs.exists():
+        district = ip_addr_qs[0]['district']
+    else:
+        ip_qs = IPQuery(ip)
+        district = ip_qs.district
+    return district

+ 8 - 8
Controller/UnicomCombo/WXTechController.py

@@ -269,7 +269,7 @@ class WXTechController(View):
                     return response.json(444)  # 参数缺失
                 # 校验兑换码格式是否正确
                 if not (code.isalnum() and len(code) == 10):
-                    return response.json(10040)  # 兑换码格式错误
+                    return response.json(10067)  # 兑换码格式错误
                 device_info_qs = UnicomDeviceInfo.objects.filter(serial_no=serial_number) \
                     .values('iccid', 'card_type')
                 if not device_info_qs.exists():
@@ -278,7 +278,7 @@ class WXTechController(View):
                 exchange_code_qs = ExchangeCode.objects.filter(code=code, status=False) \
                     .values('package_id', 'expire_time', 'package_type')
                 if not exchange_code_qs.exists():
-                    return response.json(10040)  # 兑换码无效
+                    return response.json(10066)  # 兑换码无效
                 combo_id = exchange_code_qs[0]['package_id']
                 # 获取五兴套餐套餐编码
                 package_info_qs = UnicomCombo.objects.filter(id=combo_id, is_del=False) \
@@ -294,8 +294,8 @@ class WXTechController(View):
                                                          user_id, combo_id)
                     if result:
                         exchange_code_qs.update(status=True, updated_time=int(time.time()))
-                        cls.save_log(ip, 200, '兑换成功{},{}'.format(serial_number, code))
-                        return response.json(0)
+                        cls.save_log(ip, 10065, '兑换成功{},{}'.format(serial_number, code))
+                        return response.json(10065)
                 elif card_type == 1:  # 五兴电信无限流量兑换码
                     # 五兴订购流量包请求参数
                     data = {'iccid': iccid, 'operator': WXOperatorEnum.TELECOM.value,
@@ -308,10 +308,10 @@ class WXTechController(View):
                         trade_no = res['data']['orderNumber']
                         cls.created_order(serial_number, user_id, trade_no, combo_id, 11)
                         exchange_code_qs.update(status=True, updated_time=int(time.time()))
-                        cls.save_log(ip, 200, '兑换成功{},{}'.format(serial_number, code))
-                        return response.json(0)
-                cls.save_log(ip, 10040, '兑换失败{},{}'.format(serial_number, code))
-                return response.json(10040)
+                        cls.save_log(ip, 10065, '兑换成功{},{}'.format(serial_number, code))
+                        return response.json(10065)
+                cls.save_log(ip, 10068, '兑换失败{},{}'.format(serial_number, code))
+                return response.json(10068)
             except Exception as e:
                 LOGGER.info('*****WXTechController.wx_exchange_package:errLine:{}, errMsg:{}'
                             .format(e.__traceback__.tb_lineno, repr(e)))

+ 37 - 29
Controller/UserController.py

@@ -12,6 +12,7 @@ import simplejson
 import simplejson as json
 from PIL import Image, ImageDraw, ImageFont
 from django.contrib.auth.hashers import make_password, check_password  # 对密码加密模块
+from django.db import transaction
 from django.db.models import Q
 from django.http import HttpResponseRedirect
 from django.shortcuts import HttpResponse
@@ -311,16 +312,18 @@ class LogoutView(TemplateView):
         if tko.code != 0:
             return response.json(tko.code)
 
-        Device_User.objects.filter(userID=tko.userID).update(online=False)
-        redisObj = RedisObject(db=3)
-        redisObj.del_data(key=tko.userID)
-        Device_Info.objects.filter(userID=tko.userID).update(NotificationMode=0)
         m_code = request_dict.get('m_code', None)
-        if m_code:
-            userID = tko.userID
-            UidPushModel.objects.filter(userID_id=userID, m_code=m_code).delete()
-            GatewayPush.objects.filter(user_id=userID, m_code=m_code).update(logout=True)
-        return response.json(0)
+        try:
+            with transaction.atomic():
+                Device_User.objects.filter(userID=tko.userID).update(online=False)
+                Device_Info.objects.filter(userID=tko.userID).update(NotificationMode=0)
+                if m_code:
+                    userID = tko.userID
+                    UidPushModel.objects.filter(userID_id=userID, m_code=m_code).delete()
+                    GatewayPush.objects.filter(user_id=userID, m_code=m_code).update(logout=True)
+            return response.json(0)
+        except Exception as e:
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
 
 # 修改密码
@@ -425,6 +428,7 @@ class v3ChangePwdView(TemplateView):
                         newPwd = newPwd.decode('utf-8')
                         newPwd = newPwd[3:-3]
         except Exception as e:
+            print(repr(e))
             return response.json(111)
         else:
             if oldPwd is None or newPwd is None or len(newPwd) < 6:
@@ -531,8 +535,7 @@ class ForgetPwdView(TemplateView):
         return self.ValidationError(userName, response)
 
     def ValidationError(self, userName, response):
-        # return response.json(475)
-        if userName != None:
+        if userName is not None:
             userName = userName.strip()
             return self.ForgetPwd(userName, response)
         else:
@@ -669,8 +672,7 @@ class refreshTokenView(TemplateView):
                         }
                         user_ex_qs.update(**update_dict)
                 except Exception as e:
-                    pass
-                # # #
+                    print(repr(e))
                 return response.json(0, res)
             else:
                 return response.json(tko.code)
@@ -1074,7 +1076,7 @@ class v2registerView(TemplateView):
             if number:
                 create_data["region_country"] = number
 
-            users = Device_User.objects.create(**create_data)
+            Device_User.objects.create(**create_data)
         except Exception as e:
             errorInfo = traceback.format_exc()
             print(errorInfo)
@@ -1148,7 +1150,7 @@ class v2registerView(TemplateView):
             }
             if number:
                 create_data["region_country"] = number
-            users = Device_User.objects.create(**create_data)
+            Device_User.objects.create(**create_data)
         except Exception as e:
             errorInfo = traceback.format_exc()
             print(errorInfo)
@@ -1220,6 +1222,7 @@ class v3registerView(TemplateView):
                         password = password[3:-3]
                 print(password)
         except Exception as e:
+            print(repr(e))
             return response.json(111)
         try:
             for i in range(1, 4):
@@ -1235,8 +1238,8 @@ class v3registerView(TemplateView):
                     authcode = base64.b64decode(authcode)
                     authcode = authcode.decode('utf-8')
                     authcode = authcode[3:-3]
-            print(authcode)
         except Exception as e:
+            print(repr(e))
             return response.json(121)
         else:
             if password is None:
@@ -1798,8 +1801,8 @@ class v3resetPwdByCodeView(TemplateView):
                         password = base64.b64decode(password)
                         password = password.decode('utf-8')
                         password = password[3:-3]
-                print(password)
         except Exception as e:
+            print(repr(e))
             return response.json(111)
         try:
             for i in range(1, 4):
@@ -1815,8 +1818,8 @@ class v3resetPwdByCodeView(TemplateView):
                     authcode = base64.b64decode(authcode)
                     authcode = authcode.decode('utf-8')
                     authcode = authcode[3:-3]
-            print(authcode)
         except Exception as e:
+            print(repr(e))
             return response.json(121)
         if phone is not None:
             phone = phone.strip()
@@ -2166,6 +2169,7 @@ class v3LoginView(TemplateView):
                         # 去前3位,后3位
                         password = password[3:-3]
         except Exception as e:
+            print(repr(e))
             return response.json(111)
         else:
             data_valid = DataValid()
@@ -2656,8 +2660,8 @@ class wxAuthSignView(TemplateView):
                 appid = app_config[appBundleID]['appid']
                 secret = app_config[appBundleID]['secret']
                 # 获取access_token请求
-                at_url = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid={appid}&secret={secret}&code={code}&grant_type=authorization_code'.format(
-                    appid=appid, secret=secret, code=grant_code)
+                at_url = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid={appid}&secret={secret}&code={code}' \
+                         '&grant_type=authorization_code'.format(appid=appid, secret=secret, code=grant_code)
                 res_req = requests.get(url=at_url)
                 res_json = res_req.json()
                 print(res_json)
@@ -2667,8 +2671,8 @@ class wxAuthSignView(TemplateView):
                 access_token = res_json['access_token']
                 openid = res_json['openid']
                 if access_token and openid:
-                    info_url = 'https://api.weixin.qq.com/sns/userinfo?access_token={access_token}&openid={openid}'.format(
-                        access_token=access_token, openid=openid)
+                    info_url = 'https://api.weixin.qq.com/sns/userinfo?access_token={access_token}&openid={openid}'.\
+                        format(access_token=access_token, openid=openid)
                     res_req = requests.get(url=info_url)
                     res_req.encoding = res_req.apparent_encoding
                     res_json = res_req.json()
@@ -2807,8 +2811,9 @@ class wxPerfectView(TemplateView):
                     appid = app_config[appBundleID]['appid']
                     secret = app_config[appBundleID]['secret']
                     # 获取access_token请求
-                    at_url = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid={appid}&secret={secret}&code={code}&grant_type=authorization_code'.format(
-                        appid=appid, secret=secret, code=grant_code)
+                    at_url = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid={appid}&secret={secret}&' \
+                             'code={code}&grant_type=authorization_code'.\
+                        format(appid=appid, secret=secret, code=grant_code)
                     res_req = requests.get(url=at_url)
                     res_json = res_req.json()
                     print(res_json)
@@ -2819,8 +2824,8 @@ class wxPerfectView(TemplateView):
                     openid = res_json['openid']
 
                     if access_token and openid:
-                        info_url = 'https://api.weixin.qq.com/sns/userinfo?access_token={access_token}&openid={openid}'.format(
-                            access_token=access_token, openid=openid)
+                        info_url = 'https://api.weixin.qq.com/sns/userinfo?access_token={access_token}&' \
+                                   'openid={openid}'.format(access_token=access_token, openid=openid)
                         res_req = requests.get(url=info_url)
                         res_req.encoding = res_req.apparent_encoding
                         res_json = res_req.json()
@@ -3472,7 +3477,7 @@ class V2LogoutView(TemplateView):
                 try:
                     UidPushModel.objects.filter(userID_id=userID, m_code=m_code).delete()
                 except Exception as e:
-                    pass
+                    print(repr(e))
                 else:
                     pass
             os_type = request_dict.get('os_type', None)
@@ -3650,6 +3655,7 @@ class Image_Code_RegisterView(TemplateView):
                         password = password[3:-3]
                 password = make_password(password)
         except Exception as e:
+            print(repr(e))
             return response.json(111)
         try:
             for i in range(1, 4):
@@ -3666,6 +3672,7 @@ class Image_Code_RegisterView(TemplateView):
                     valid_code = valid_code.decode('utf-8')
                     valid_code = valid_code[3:-3]
         except Exception as e:
+            print(repr(e))
             return response.json(121)
         if not userEmail:
             return response.json(105)
@@ -3850,7 +3857,7 @@ class loginCodeView(View):
 
     def validate(self, request_dict, response):
         phone = request_dict.get('phone', None)
-        country_code = request_dict.get('country_code', None)
+        request_dict.get('country_code', None)
         sign_name = request_dict.get('sign_name', None)
 
         if phone and sign_name:
@@ -4258,7 +4265,7 @@ class LocalUserView(View):
         request_dict = request.POST
         operation = kwargs.get('operation', None)
         print('start_time=' + str((time.time())))
-        ip = CommonService.get_ip_address(request)
+        CommonService.get_ip_address(request)
         print('end_time=' + str((time.time())))
         return self.validate(request_dict, operation)
 
@@ -4461,6 +4468,7 @@ def deleteAccount(request):
                     # 去前3位,后3位
                     password = password[3:-3]
     except Exception as e:
+        print(repr(e))
         return response.json(111)
     else:
         if token is None:

+ 19 - 9
Model/models.py

@@ -159,8 +159,8 @@ class Device_User(AbstractBaseUser):
                                        verbose_name=u'头像',
                                        # 图片将处理成85x85的尺寸
                                        processors=[ResizeToFill(85, 85)], )
-    userIconUrl = models.URLField(blank=True, max_length=128, default=SERVER_DOMAIN
-                                                                      + 'account/getAvatar/User/defaultUser.png')
+    userIconUrl = models.URLField(blank=True, max_length=128,
+                                  default=SERVER_DOMAIN + 'account/getAvatar/User/defaultUser.png')
     NickName = models.CharField(blank=True, max_length=64, default='', verbose_name=u'用户昵称')
     is_superuser = models.IntegerField(blank=True, default=0, verbose_name=u'用户类型')
     is_active = models.BooleanField(blank=True, default=False, verbose_name=u'用户活动状态')
@@ -1485,12 +1485,12 @@ class UserExModel(models.Model):
     id = models.AutoField(primary_key=True, verbose_name='自增id')
     userID = models.ForeignKey(Device_User, to_field='userID', on_delete=models.CASCADE)
     appBundleId = models.CharField(default='', max_length=32, verbose_name=u'appID')
+    # {'cn': '简体中文', 'tc': '繁体中文', 'fr': '法文', 'ru': '俄文', 'es': '西班牙文',
+    # 'pl': '波兰文', 'ja': '日文', 'de': '德文', 'en': '英文'}
     region = models.CharField(default='', max_length=16, verbose_name='区域语言')
     addTime = models.IntegerField(verbose_name='添加时间', default=0)
     updTime = models.IntegerField(verbose_name='更新时间', default=0)
 
-    # {'cn': '简体中文', 'tc': '繁体中文', 'fr': '法文', 'ru': '俄文', 'es': '西班牙文', 'pl': '波兰文', 'ja': '日文', 'de': '德文', 'en': '英文'}
-
     class Meta:
         db_table = 'user_ex'
         verbose_name = '用户扩展信息表'
@@ -1507,8 +1507,6 @@ class UserOauth2Model(models.Model):
     addTime = models.IntegerField(verbose_name='添加时间', default=0)
     updTime = models.IntegerField(verbose_name='更新时间', default=0)
 
-    # {'cn': '简体中文', 'tc': '繁体中文', 'fr': '法文', 'ru': '俄文', 'es': '西班牙文', 'pl': '波兰文', 'ja': '日文', 'de': '德文', 'en': '英文'}
-
     class Meta:
         db_table = 'user_oauth2'
         verbose_name = '用户oauth2关联'
@@ -1855,7 +1853,6 @@ class CDKcontextModel(models.Model):
     is_activate = models.SmallIntegerField(default=0, verbose_name='是否已激活')  # 0 未激活  1 已激活
     is_down = models.SmallIntegerField(default=0, verbose_name='是否已下载')  # 0 未下载 1 已下载
     rank = models.ForeignKey(Store_Meal, to_field='id', default='', on_delete=models.CASCADE, verbose_name='套餐类型')
-    # order = models.ForeignKey(Order_Model, blank=True, max_length=20, to_field='orderID', on_delete=models.CASCADE, verbose_name='订单id', unique=True)
     order = models.CharField(max_length=20, blank=True, unique=True, verbose_name='订单id')
     express_id = models.CharField(blank=True, max_length=128, verbose_name='速卖通订单id')
 
@@ -2641,8 +2638,8 @@ class PaypalWebHookEvent(models.Model):
     id = models.AutoField(primary_key=True, verbose_name=u'自增标记ID')
     webhook_event_id = models.CharField(max_length=200, blank=True, verbose_name='webhook事件ID', default='')
     resource_type = models.CharField(max_length=11, verbose_name='资源类型', blank=True, default='')
-    ## event_type: 1=PAYMENT.SALE.COMPLETED(付款,订阅成功后钩子),2=PAYMENT.SALE.REVERSED(付款撤销)
-    ## event_type: 3=BILLING.SUBSCRIPTION.CANCELLED(订阅取消),4=BILLING.SUBSCRIPTION.SUSPENDED(订阅暂停),
+    # event_type: 1=PAYMENT.SALE.COMPLETED(付款,订阅成功后钩子),2=PAYMENT.SALE.REVERSED(付款撤销)
+    # event_type: 3=BILLING.SUBSCRIPTION.CANCELLED(订阅取消),4=BILLING.SUBSCRIPTION.SUSPENDED(订阅暂停),
     # event_type:  5=BILLING.SUBSCRIPTION.PAYMENT.FAILED(订阅付款失败),6=PAYMENT.SALE.REFUNDED(退款)
     event_type = models.SmallIntegerField(default=0, verbose_name='事件类型')
     summary = models.CharField(max_length=500, verbose_name='事件概要', blank=True, default='')
@@ -3740,3 +3737,16 @@ class CityInformation(models.Model):
         db_table = 'city_information'
         verbose_name = '城市信息'
         verbose_name_plural = verbose_name
+
+
+class IPAddr(models.Model):
+    id = models.AutoField(primary_key=True, verbose_name='主键')
+    ip = models.CharField(default='', max_length=32, verbose_name='ip')
+    district = models.CharField(default='', max_length=32, verbose_name='区')
+    city = models.CharField(default='', max_length=32, verbose_name='市')
+    region = models.CharField(default='', max_length=32, verbose_name='省/州')
+    country_code = models.CharField(default='', max_length=8, verbose_name='国家编码')
+
+    class Meta:
+        db_table = 'ip_addr'
+        verbose_name = 'ip地址信息'

+ 25 - 3
Object/IPWeatherObject.py

@@ -3,6 +3,8 @@
 # @Time      : 2023/8/16 8:56
 import requests
 
+from Model.models import IPAddr
+
 
 class IPQuery:
     """
@@ -15,7 +17,10 @@ class IPQuery:
         self.host = 'https://c2ba.api.huachen.cn'
         self.path = '/ip'
 
-        self.district = None
+        self.district = ''  # 区
+        self.city = ''      # 市
+        self.region = ''    # 省/州
+        self.country_id = ''
 
         param = 'ip=' + ip
         url = self.host + self.path + '?' + param
@@ -28,8 +33,25 @@ class IPQuery:
             res_data = eval(res.content.decode('utf-8'))
             if res_data['ret'] == 200:
                 district = res_data['data']['district']
-                city = res_data['data']['city'] + '市'
-                self.district = district if district else city
+
+                # 城市数据不为空字符,拼上'市'字
+                city = res_data['data']['city']
+                if city != '':
+                    city += '市'
+
+                region = res_data['data']['region']
+                country_id = res_data['data']['country_id']
+
+                # ip地址信息存表
+                IPAddr.objects.create(ip=ip, district=district, city=city, region=region, country_code=country_id)
+
+                # 确定天气城市
+                if district != '':
+                    self.district = district
+                elif city != '':
+                    self.district = city
+
+                self.country_id = country_id
 
 
 class WeatherInfo:

+ 8 - 0
Object/ResponseObject.py

@@ -131,6 +131,10 @@ class ResponseObject(object):
             10062: 'This device has experienced the package',
             10063: 'Failed to claim',
             10064: 'If the claim fails, please contact customer service',
+            10065: 'The redemption is successful and can be viewed in Settings-4G-My Package',
+            10066: 'This code has been redeemed and can be viewed in Settings-4G-My Package',
+            10067: 'Invalid redemption code',
+            10068: 'This device does not support redemption, please contact customer service'
         }
         data_cn = {
             0: '成功',
@@ -252,6 +256,10 @@ class ResponseObject(object):
             10062: '此设备已体验过套餐',
             10063: '领取失败',
             10064: '领取失败,请联系客服',
+            10065: '\t兑换成功\n可在设置-4G-我的套餐中查看',
+            10066: '\t此码已兑换\n可在设置-4G-我的套餐中查看',
+            10067: '无效兑换码',
+            10068: '兑换失败,请联系客服'
         }
 
         msg = data_cn if self.lang == 'cn' or self.lang == 'zh-Hans' or self.lang == 'zh-Hant' else data_en

+ 10 - 0
Object/utils/LocalDateTimeUtil.py

@@ -308,3 +308,13 @@ def get_current_month_first_day(timestamp):
 
     # 将当前月份第一天的datetime对象转换为时间戳并返回
     return int(current_month_first_day.timestamp())
+
+
+def get_date_time(timestamp, timezone_offset):
+    # 计算时区偏移量
+    hours_offset = int(timezone_offset[1:3])
+    minutes_offset = int(timezone_offset[4:6])
+    offset = datetime.timedelta(hours=hours_offset, minutes=minutes_offset)
+
+    # 转换为日期时间对象
+    return datetime.datetime.fromtimestamp(timestamp, tz=datetime.timezone(offset))