增加下载每超过100M消耗一次下载次数

pull/16/head
youngS 4 years ago
parent cad5906404
commit 75630183c6
  1. 35
      fir_client/src/components/apps/FirApps.vue
  2. 50
      fir_client/src/components/user/FirUserOrders.vue
  3. 30
      fir_client/src/components/user/FirUserStorage.vue
  4. 3
      fir_ser/api/base_views.py
  5. 19
      fir_ser/api/migrations/0041_auto_20210416_1438.py
  6. 2
      fir_ser/api/models.py
  7. 5
      fir_ser/api/utils/app/supersignutils.py
  8. 81
      fir_ser/api/utils/baseutils.py
  9. 2
      fir_ser/api/utils/pay/ali.py
  10. 13
      fir_ser/api/utils/storage/caches.py
  11. 75
      fir_ser/api/utils/utils.py
  12. 3
      fir_ser/api/views/apps.py
  13. 8
      fir_ser/api/views/download.py
  14. 5
      fir_ser/api/views/login.py
  15. 6
      fir_ser/api/views/order.py
  16. 14
      fir_ser/api/views/storage.py
  17. 7
      fir_ser/fir_ser/settings.py

@ -284,17 +284,6 @@
<el-divider direction="vertical"></el-divider> <el-divider direction="vertical"></el-divider>
</div> </div>
</el-col> </el-col>
<!-- <el-col :span="8">-->
<!-- <div>-->
<!-- <span class="name">总共下载次数</span>-->
<!-- <el-divider direction="vertical"></el-divider>-->
<!-- </div>-->
<!-- <div>-->
<!-- <span class="value">{{ hdata.all_hits_count}}</span>-->
<!-- <el-divider direction="vertical"></el-divider>-->
<!-- </div>-->
<!-- </el-col>-->
</el-row> </el-row>
</el-col> </el-col>
@ -304,7 +293,10 @@
<el-col :span="9"> <el-col :span="9">
<div> <div>
<el-tooltip placement="top"> <el-tooltip placement="top">
<div slot="content">1.账号下所有应用共用此剩余下载次数<br/>2.每日凌晨 0 点自动重置下载次数</div> <div slot="content">
1.账号下所有应用共用此剩余下载次数<br/>
2.每日凌晨 0 点自动重置下载次数<br/>
</div>
<span class="name">今日剩余免费次数</span> <span class="name">今日剩余免费次数</span>
</el-tooltip> </el-tooltip>
<el-divider direction="vertical"></el-divider> <el-divider direction="vertical"></el-divider>
@ -331,7 +323,13 @@
<el-col :span="6"> <el-col :span="6">
<div> <div>
<span class="name">购买次数</span> <el-tooltip placement="top">
<div slot="content">
1.下载应用每100M消耗一次下载次数<br>
2.超级签下载下载消耗次数翻倍<br>
</div>
<span class="name">购买次数</span>
</el-tooltip>
</div> </div>
<div> <div>
<el-button class="action" size="small" icon="el-icon-shopping-cart-1" <el-button class="action" size="small" icon="el-icon-shopping-cart-1"
@ -536,7 +534,7 @@
if (res.code === 1000) { if (res.code === 1000) {
this.$message.success("下订单成功,正在跳转支付平台"); this.$message.success("下订单成功,正在跳转支付平台");
let pay_url = res.data; let pay_url = res.data;
if(pay_url && pay_url.length > 10){ if (pay_url && pay_url.length > 10) {
window.location.href = pay_url window.location.href = pay_url
} }
} else { } else {
@ -630,13 +628,6 @@
this.analyseappinfo.is_new = data.data.is_new; this.analyseappinfo.is_new = data.data.is_new;
this.analyseappinfo.binary_url = data.data.binary_url; this.analyseappinfo.binary_url = data.data.binary_url;
this.willuploadApp = true; this.willuploadApp = true;
// eslint-disable-next-line no-unused-vars
this.timmer = setTimeout(data => {
let canvas = this.$refs.canvas;
show_beautpic(this, canvas, 666, 0.8);
}, 100);
} else { } else {
this.$message.error("上传token获取失败,请刷新重试") this.$message.error("上传token获取失败,请刷新重试")
} }
@ -677,7 +668,7 @@
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
this.timmer = setTimeout(data => { this.timmer = setTimeout(data => {
let canvas = this.$refs.canvas; let canvas = this.$refs.canvas;
show_beautpic(this, canvas, 888, 0.8); show_beautpic(this, canvas, 888, 0.6);
}, 100); }, 100);
let file = dataURLtoFile(this.analyseappinfo.icon, this.analyseappinfo.png_key); let file = dataURLtoFile(this.analyseappinfo.icon, this.analyseappinfo.png_key);

@ -103,12 +103,12 @@
prop="status" prop="status"
label="状态" label="状态"
align="center" align="center"
width="130"> width="110">
<template slot-scope="scope"> <template slot-scope="scope">
<div v-if="scope.row.status === 1 || scope.row.status === 2"> <div v-if="scope.row.status === 1 || scope.row.status === 2">
<el-button @click="goto_pay(scope.row)" <el-button @click="goto_pay(scope.row)"
type="primary" size="small"> {{ format_status_type(scope.row)}} type="primary" size="small"> {{ format_status_type(scope.row)}}
</el-button> </el-button>
</div> </div>
<div v-else-if="scope.row.status === 0"> <div v-else-if="scope.row.status === 0">
@ -148,12 +148,21 @@
<el-table-column <el-table-column
prop="actual_download_gift_times" prop="actual_download_gift_times"
label="赠送数量" label="赠送数量"
width="100"> width="90">
</el-table-column>
<el-table-column
:formatter="format_payment_type"
prop="payment_type"
align="center"
label="支付方式"
width="80">
</el-table-column> </el-table-column>
<el-table-column <el-table-column
:formatter="format_create_time" :formatter="format_create_time"
prop="created_time" prop="created_time"
width="170"
align="center"
label="订单创建时间" label="订单创建时间"
> >
</el-table-column> </el-table-column>
@ -169,8 +178,8 @@
@click="click_order_info(scope.row)">详情 @click="click_order_info(scope.row)">详情
</el-button> </el-button>
<el-button v-if="scope.row.status === 1 || scope.row.status === 2" <el-button v-if="scope.row.status === 1 || scope.row.status === 2"
size="mini" type="danger" size="mini" type="danger"
@click="cancel_order(scope.row)">取消 @click="cancel_order(scope.row)">取消
</el-button> </el-button>
</template> </template>
</el-table-column> </el-table-column>
@ -213,16 +222,19 @@
} }
}, },
methods: { methods: {
cancel_order(order){ cancel_order(order) {
my_order(res => { my_order(res => {
if (res.code === 1000) { if (res.code === 1000) {
this.$message.success("操作成功"); this.$message.success("操作成功");
this.get_data_from_tabname() this.get_data_from_tabname({
"size": this.pagination.pagesize,
"page": this.pagination.currentPage
})
} else { } else {
this.$message.error("失败了 " + res.msg) this.$message.error("失败了 " + res.msg)
} }
}, { }, {
methods: 'PUT', data: {order_number: order.order_number,act:'cancel'}, methods: 'PUT', data: {order_number: order.order_number, act: 'cancel'},
}) })
}, },
goto_pay(order) { goto_pay(order) {
@ -230,7 +242,7 @@
if (res.code === 1000) { if (res.code === 1000) {
this.$message.success("正在跳转支付平台"); this.$message.success("正在跳转支付平台");
let pay_url = res.data; let pay_url = res.data;
if(pay_url && pay_url.length > 10){ if (pay_url && pay_url.length > 10) {
window.location.href = pay_url window.location.href = pay_url
} }
} else { } else {
@ -241,15 +253,17 @@
}) })
}, },
click_order_info(order) { click_order_info(order) {
my_order(res => { if (order.status === 1 || order.status === 2) {
if (res.code === 1000) { my_order(res => {
this.get_data_from_tabname() if (res.code === 1000) {
} else { this.get_data_from_tabname()
this.$message.error("失败了 " + res.msg) } else {
} this.$message.error("失败了 " + res.msg)
}, { }
methods: 'PUT', data: {order_number: order.order_number,act:'status'}, }, {
}); methods: 'PUT', data: {order_number: order.order_number, act: 'status'},
});
}
this.show_order_info = true; this.show_order_info = true;
this.current_order_info = order; this.current_order_info = order;

@ -90,17 +90,19 @@
</el-option> </el-option>
</el-option-group> </el-option-group>
</el-select> </el-select>
<el-button v-if="use_storage_id!==org_storage_id" style="margin-left: 10px" round type="info" <div v-if="use_storage_id!==org_storage_id" style="margin-top: 20px">
icon="el-icon-thumb" <el-button style="margin-left: 10px" round type="info"
@click="change_storage_info"> icon="el-icon-thumb"
迁移数据并保存 @click="change_storage_info(0)">
</el-button> 迁移数据并保存
</el-button>
<!-- <el-button-group style="margin-left: 10px">--> <el-button style="margin-left: 10px" round type="danger"
<!-- <el-button round type="info" icon="el-icon-edit" @click="change_storage_info"></el-button>--> icon="el-icon-thumb"
<!-- <el-button round type="info" icon="el-icon-plus" @click="add_storage_info"></el-button>--> @click="change_storage_info(1)">
<!-- <el-button round type="info" icon="el-icon-delete" @click="del_storage_info"></el-button>--> 强制迁移忽略数据迁移失败错误可能会导致数据丢失
<!-- </el-button-group>--> </el-button>
</div>
<el-divider></el-divider> <el-divider></el-divider>
<el-form v-if="storageinfo.id && storageinfo.id !==-1" ref="storageinfoform" :model="storageinfo" <el-form v-if="storageinfo.id && storageinfo.id !==-1" ref="storageinfoform" :model="storageinfo"
label-width="80px" style="width: 39%;margin:0 auto;"> label-width="80px" style="width: 39%;margin:0 auto;">
@ -401,7 +403,7 @@
}); });
}, },
change_storage_info() { change_storage_info(force) {
this.$confirm('此操作将导致应用,图片,显示下载异常, 是否继续?', '警告', { this.$confirm('此操作将导致应用,图片,显示下载异常, 是否继续?', '警告', {
confirmButtonText: '确定', confirmButtonText: '确定',
cancelButtonText: '取消', cancelButtonText: '取消',
@ -418,8 +420,10 @@
if (data.code === 1000) { if (data.code === 1000) {
this.$message.success('修改成功'); this.$message.success('修改成功');
this.getstorageinfoFun(); this.getstorageinfoFun();
} else {
this.$message.error(data.msg)
} }
}, {"methods": 'PUT', 'data': {'use_storage_id': this.use_storage_id}}); }, {"methods": 'PUT', 'data': {'use_storage_id': this.use_storage_id, 'force': force}});
this.getstorageinfoFun(); this.getstorageinfoFun();
}).catch(() => { }).catch(() => {
this.$message({ this.$message({

@ -17,7 +17,8 @@ from api.utils.serializer import AppsSerializer, AppReleaseSerializer
from rest_framework.pagination import PageNumberPagination from rest_framework.pagination import PageNumberPagination
import logging import logging
from fir_ser.settings import SERVER_DOMAIN from fir_ser.settings import SERVER_DOMAIN
from api.utils.utils import is_valid_domain, delete_local_files, delete_app_screenshots_files from api.utils.utils import delete_local_files, delete_app_screenshots_files
from api.utils.baseutils import is_valid_domain
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)

@ -0,0 +1,19 @@
# Generated by Django 3.0.3 on 2021-04-16 14:38
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('api', '0040_auto_20210413_1010'),
]
operations = [
migrations.AlterField(
model_name='order',
name='status',
field=models.SmallIntegerField(
choices=[(0, '交易成功'), (1, '待支付'), (2, '订单已创建'), (3, '退费申请中'), (4, '已退费'), (5, '主动取消'), (6, '超时取消')],
verbose_name='状态'),
),
]

@ -360,7 +360,7 @@ class Order(models.Model):
actual_amount = models.BigIntegerField(verbose_name="实付金额,单位分") actual_amount = models.BigIntegerField(verbose_name="实付金额,单位分")
actual_download_times = models.BigIntegerField(verbose_name="实际购买的数量", default=0) actual_download_times = models.BigIntegerField(verbose_name="实际购买的数量", default=0)
actual_download_gift_times = models.BigIntegerField(verbose_name="实际赠送的数量", default=0) actual_download_gift_times = models.BigIntegerField(verbose_name="实际赠送的数量", default=0)
status_choices = ((0, '交易成功'), (1, '待支付'), (2, '订单已创建'), (3, '退费申请中'), (4, '已退费'), (5, '主动取消'), (6, '超时取消')) status_choices = ((0, '交易成功'), (1, '待支付'), (2, '订单已创建'), (3, '退费申请中'), (4, '已退费'), (5, '主动取消'), (6, '超时取消'))
status = models.SmallIntegerField(choices=status_choices, verbose_name="状态") status = models.SmallIntegerField(choices=status_choices, verbose_name="状态")
order_type_choices = ((0, '用户下单'), (1, '后台充值'),) order_type_choices = ((0, '用户下单'), (1, '后台充值'),)
order_type = models.SmallIntegerField(choices=order_type_choices, default=0, verbose_name="订单类型") order_type = models.SmallIntegerField(choices=order_type_choices, default=0, verbose_name="订单类型")

@ -11,9 +11,10 @@ from api.models import APPSuperSignUsedInfo, AppUDID, AppIOSDeveloperInfo, AppRe
UDIDsyncDeveloper, DeveloperAppID, DeveloperDevicesID UDIDsyncDeveloper, DeveloperAppID, DeveloperDevicesID
from api.utils.app.randomstrings import make_app_uuid, make_from_user_uuid from api.utils.app.randomstrings import make_app_uuid, make_from_user_uuid
from api.utils.storage.caches import del_cache_response_by_short, send_msg_over_limit from api.utils.storage.caches import del_cache_response_by_short, send_msg_over_limit
from api.utils.utils import file_format_path, delete_app_to_dev_and_file, delete_app_profile_file, \ from api.utils.utils import delete_app_to_dev_and_file, send_ios_developer_active_status, delete_local_files, \
send_ios_developer_active_status, get_profile_full_path, delete_local_files, download_files_form_oss, \ download_files_form_oss, \
get_developer_udided get_developer_udided
from api.utils.baseutils import file_format_path, delete_app_profile_file, get_profile_full_path
from api.utils.storage.storage import Storage from api.utils.storage.storage import Storage
from django.core.cache import cache from django.core.cache import cache

@ -0,0 +1,81 @@
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# project: 4月
# author: NinEveN
# date: 2021/4/16
import os, re
from fir_ser.settings import SUPER_SIGN_ROOT
from api.models import AppReleaseInfo
from api.utils.app.randomstrings import make_app_uuid
from django.core.validators import validate_email
from django.core.exceptions import ValidationError
import logging
logger = logging.getLogger(__name__)
def get_app_d_count_by_app_id(app_id):
d_count = 1
binary_size = AppReleaseInfo.objects.filter(is_master=True, app_id__app_id=app_id).values('binary_size')
if binary_size and binary_size > 0:
d_count += binary_size // 1024 // 1024 // 100
return d_count
def file_format_path(user_obj, auth=None, email=None):
if email:
cert_dir_name = make_app_uuid(user_obj, email)
else:
pkey = auth.get("username")
if auth.get("issuer_id"):
pkey = auth.get("issuer_id")
cert_dir_name = make_app_uuid(user_obj, pkey)
cert_dir_path = os.path.join(SUPER_SIGN_ROOT, cert_dir_name)
if not os.path.isdir(cert_dir_path):
os.makedirs(cert_dir_path)
file_format_path_name = os.path.join(cert_dir_path, cert_dir_name)
return file_format_path_name
def get_profile_full_path(developer_obj, app_obj):
pkey = developer_obj.email
if developer_obj.issuer_id:
pkey = developer_obj.issuer_id
cert_dir_name = make_app_uuid(developer_obj.user_id, pkey)
cert_dir_path = os.path.join(SUPER_SIGN_ROOT, cert_dir_name, "profile")
provision_name = os.path.join(cert_dir_path, app_obj.app_id)
return provision_name + '.mobileprovision'
def delete_app_profile_file(developer_obj, app_obj):
file = get_profile_full_path(developer_obj, app_obj)
try:
if os.path.isfile(file):
os.remove(file)
except Exception as e:
logger.error("delete_app_profile_file developer_obj:%s app_obj:%s file:%s Exception:%s" % (
developer_obj, app_obj, file, e))
def is_valid_domain(value):
pattern = re.compile(
r'^(([a-zA-Z]{1})|([a-zA-Z]{1}[a-zA-Z]{1})|'
r'([a-zA-Z]{1}[0-9]{1})|([0-9]{1}[a-zA-Z]{1})|'
r'([a-zA-Z0-9][-_.a-zA-Z0-9]{0,61}[a-zA-Z0-9]))\.'
r'([a-zA-Z]{2,13}|[a-zA-Z0-9-]{2,30}.[a-zA-Z]{2,3})$'
)
return True if pattern.match(value) else False
def is_valid_phone(value):
phone_pat = re.compile('^(13\d|14[5|7]|15\d|166|17[3|6|7]|18\d)\d{8}$')
return True if str(value) and re.search(phone_pat, str(value)) else False
def is_valid_email(email):
try:
validate_email(email)
return True
except ValidationError:
return False

@ -76,7 +76,7 @@ class Alipay(object):
data = self.alipay.api_alipay_trade_query(out_trade_no=out_trade_no) data = self.alipay.api_alipay_trade_query(out_trade_no=out_trade_no)
# (0, '交易成功'), (1, '待支付'), (2, '订单已创建'), (3, '退费申请中'), (4, '已退费'), (5, '主动取消'), (6, '超时取消') # (0, '交易成功'), (1, '待支付'), (2, '订单已创建'), (3, '退费申请中'), (4, '已退费'), (5, '主动取消'), (6, '超时取消')
code = data.get("code", '') code = data.get("code", '')
logger.info("out_trade_no: %s info:%s"%(out_trade_no, data)) logger.info("out_trade_no: %s info:%s" % (out_trade_no, data))
if code == '10000': if code == '10000':
trade_status = data.get("trade_status", '') trade_status = data.get("trade_status", '')
if trade_status in ['TRADE_SUCCESS']: if trade_status in ['TRADE_SUCCESS']:

@ -12,7 +12,7 @@ from django.utils import timezone
from fir_ser.settings import CACHE_KEY_TEMPLATE, SERVER_DOMAIN, SYNC_CACHE_TO_DATABASE, DEFAULT_MOBILEPROVISION, \ from fir_ser.settings import CACHE_KEY_TEMPLATE, SERVER_DOMAIN, SYNC_CACHE_TO_DATABASE, DEFAULT_MOBILEPROVISION, \
USER_FREE_DOWNLOAD_TIMES, AUTH_USER_FREE_DOWNLOAD_TIMES USER_FREE_DOWNLOAD_TIMES, AUTH_USER_FREE_DOWNLOAD_TIMES
from api.utils.storage.storage import Storage, LocalStorage from api.utils.storage.storage import Storage, LocalStorage
from api.utils.utils import file_format_path from api.utils.baseutils import get_app_d_count_by_app_id, file_format_path
import logging import logging
from django.db.models import F from django.db.models import F
@ -96,15 +96,20 @@ def get_download_url_by_cache(app_obj, filename, limit, isdownload=True, key='',
def get_app_instance_by_cache(app_id, password, limit, udid): def get_app_instance_by_cache(app_id, password, limit, udid):
if udid: if udid:
return Apps.objects.filter(app_id=app_id).values("pk", 'user_id', 'type', 'password', 'issupersign', app_info = Apps.objects.filter(app_id=app_id).values("pk", 'user_id', 'type', 'password', 'issupersign',
'user_id__certification__status').first() 'user_id__certification__status').first()
if app_info:
app_info['d_count'] = get_app_d_count_by_app_id(app_id)
return app_info
app_key = "_".join([CACHE_KEY_TEMPLATE.get("app_instance_key"), app_id]) app_key = "_".join([CACHE_KEY_TEMPLATE.get("app_instance_key"), app_id])
app_obj_cache = cache.get(app_key) app_obj_cache = cache.get(app_key)
if not app_obj_cache: if not app_obj_cache:
app_obj_cache = Apps.objects.filter(app_id=app_id).values("pk", 'user_id', 'type', 'password', app_obj_cache = Apps.objects.filter(app_id=app_id).values("pk", 'user_id', 'type', 'password',
'issupersign', 'issupersign',
'user_id__certification__status').first() 'user_id__certification__status').first()
cache.set(app_key, app_obj_cache, limit) if app_obj_cache:
app_obj_cache['d_count'] = get_app_d_count_by_app_id(app_id)
cache.set(app_key, app_obj_cache, limit)
app_password = app_obj_cache.get("password") app_password = app_obj_cache.get("password")

@ -3,11 +3,11 @@
# project: 5月 # project: 5月
# author: liuyu # author: liuyu
# date: 2020/5/7 # date: 2020/5/7
import os, re, json, requests, datetime, random import os, json, requests, datetime, random
from fir_ser.settings import SUPER_SIGN_ROOT, SERVER_DOMAIN, CAPTCHA_LENGTH, MEDIA_ROOT from fir_ser.settings import SERVER_DOMAIN, CAPTCHA_LENGTH, MEDIA_ROOT
from api.models import APPSuperSignUsedInfo, APPToDeveloper, \ from api.models import APPSuperSignUsedInfo, APPToDeveloper, \
UDIDsyncDeveloper, UserInfo, AppReleaseInfo, AppScreenShot UDIDsyncDeveloper, UserInfo, AppReleaseInfo, AppScreenShot
from api.utils.app.randomstrings import make_app_uuid from api.utils.storage.caches import get_app_d_count_by_app_id
from api.utils.storage.localApi import LocalStorage from api.utils.storage.localApi import LocalStorage
from api.utils.storage.storage import Storage from api.utils.storage.storage import Storage
from api.utils.tempcaches import tmpCache from api.utils.tempcaches import tmpCache
@ -16,39 +16,13 @@ from api.utils.sendmsg.sendmsg import SendMessage
from django.db.models import Sum from django.db.models import Sum
from captcha.models import CaptchaStore from captcha.models import CaptchaStore
from captcha.helpers import captcha_image_url from captcha.helpers import captcha_image_url
from django.core.validators import validate_email from api.utils.storage.caches import consume_user_download_times
from django.core.exceptions import ValidationError
from django.core.cache import cache from django.core.cache import cache
import logging import logging
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
def file_format_path(user_obj, auth=None, email=None):
if email:
cert_dir_name = make_app_uuid(user_obj, email)
else:
pkey = auth.get("username")
if auth.get("issuer_id"):
pkey = auth.get("issuer_id")
cert_dir_name = make_app_uuid(user_obj, pkey)
cert_dir_path = os.path.join(SUPER_SIGN_ROOT, cert_dir_name)
if not os.path.isdir(cert_dir_path):
os.makedirs(cert_dir_path)
file_format_path_name = os.path.join(cert_dir_path, cert_dir_name)
return file_format_path_name
def get_profile_full_path(developer_obj, app_obj):
pkey = developer_obj.email
if developer_obj.issuer_id:
pkey = developer_obj.issuer_id
cert_dir_name = make_app_uuid(developer_obj.user_id, pkey)
cert_dir_path = os.path.join(SUPER_SIGN_ROOT, cert_dir_name, "profile")
provision_name = os.path.join(cert_dir_path, app_obj.app_id)
return provision_name + '.mobileprovision'
def delete_app_to_dev_and_file(developer_obj, app_id): def delete_app_to_dev_and_file(developer_obj, app_id):
APPToDeveloper_obj = APPToDeveloper.objects.filter(developerid=developer_obj, app_id_id=app_id) APPToDeveloper_obj = APPToDeveloper.objects.filter(developerid=developer_obj, app_id_id=app_id)
if APPToDeveloper_obj: if APPToDeveloper_obj:
@ -59,16 +33,6 @@ def delete_app_to_dev_and_file(developer_obj, app_id):
APPToDeveloper_obj.delete() APPToDeveloper_obj.delete()
def delete_app_profile_file(developer_obj, app_obj):
file = get_profile_full_path(developer_obj, app_obj)
try:
if os.path.isfile(file):
os.remove(file)
except Exception as e:
logger.error("delete_app_profile_file developer_obj:%s app_obj:%s file:%s Exception:%s" % (
developer_obj, app_obj, file, e))
def get_developer_udided(developer_obj): def get_developer_udided(developer_obj):
SuperSignUsed_obj = APPSuperSignUsedInfo.objects.filter(developerid=developer_obj) SuperSignUsed_obj = APPSuperSignUsedInfo.objects.filter(developerid=developer_obj)
UDIDsyncDeveloper_obj = UDIDsyncDeveloper.objects.filter(developerid=developer_obj) UDIDsyncDeveloper_obj = UDIDsyncDeveloper.objects.filter(developerid=developer_obj)
@ -127,29 +91,6 @@ def upload_oss_default_head_img(user_obj, storage_obj):
return storage_obj.upload_file(head_img_full_path) return storage_obj.upload_file(head_img_full_path)
def is_valid_domain(value):
pattern = re.compile(
r'^(([a-zA-Z]{1})|([a-zA-Z]{1}[a-zA-Z]{1})|'
r'([a-zA-Z]{1}[0-9]{1})|([0-9]{1}[a-zA-Z]{1})|'
r'([a-zA-Z0-9][-_.a-zA-Z0-9]{0,61}[a-zA-Z0-9]))\.'
r'([a-zA-Z]{2,13}|[a-zA-Z0-9-]{2,30}.[a-zA-Z]{2,3})$'
)
return True if pattern.match(value) else False
def is_valid_phone(value):
phone_pat = re.compile('^(13\d|14[5|7]|15\d|166|17[3|6|7]|18\d)\d{8}$')
return True if str(value) and re.search(phone_pat, str(value)) else False
def is_valid_email(email):
try:
validate_email(email)
return True
except ValidationError:
return False
def get_sender_token(sender, user_id, target, action, msg=None): def get_sender_token(sender, user_id, target, action, msg=None):
sms_token_obj = DownloadToken() sms_token_obj = DownloadToken()
code = generateNumericTokenOfLength(6) code = generateNumericTokenOfLength(6)
@ -316,6 +257,11 @@ def migrating_storage_file_data(user_obj, filename, new_storage_obj, clean_old_d
def migrating_storage_data(user_obj, new_storage_obj, clean_old_data): def migrating_storage_data(user_obj, new_storage_obj, clean_old_data):
with cache.lock("%s_%s" % ('migrating_storage_data', user_obj.uid)): with cache.lock("%s_%s" % ('migrating_storage_data', user_obj.uid)):
status = user_obj.certification.status
auth_status = False
if status and status == 1:
auth_status = True
for app_release_obj in AppReleaseInfo.objects.filter(app_id__user_id=user_obj).all(): for app_release_obj in AppReleaseInfo.objects.filter(app_id__user_id=user_obj).all():
# 迁移APP数据 # 迁移APP数据
filename = get_filename_from_apptype(app_release_obj.release_id, app_release_obj.release_type) filename = get_filename_from_apptype(app_release_obj.release_id, app_release_obj.release_type)
@ -328,6 +274,9 @@ def migrating_storage_data(user_obj, new_storage_obj, clean_old_data):
for apptodev_obj in APPToDeveloper.objects.filter(app_id=app_release_obj.app_id).all(): for apptodev_obj in APPToDeveloper.objects.filter(app_id=app_release_obj.app_id).all():
filename = get_filename_from_apptype(apptodev_obj.binary_file, app_release_obj.release_type) filename = get_filename_from_apptype(apptodev_obj.binary_file, app_release_obj.release_type)
migrating_storage_file_data(user_obj, filename, new_storage_obj, clean_old_data) migrating_storage_file_data(user_obj, filename, new_storage_obj, clean_old_data)
# 消费下载次数
amount = get_app_d_count_by_app_id(app_release_obj.app_id.app_id)
consume_user_download_times(user_obj.pk, app_release_obj.app_id, amount, auth_status)
return True return True

@ -17,7 +17,8 @@ from api.utils.serializer import AppsSerializer, AppReleaseSerializer
from rest_framework.pagination import PageNumberPagination from rest_framework.pagination import PageNumberPagination
import logging import logging
from fir_ser.settings import SERVER_DOMAIN from fir_ser.settings import SERVER_DOMAIN
from api.utils.utils import is_valid_domain, delete_local_files, delete_app_screenshots_files from api.utils.utils import delete_local_files, delete_app_screenshots_files
from api.utils.baseutils import is_valid_domain
from api.base_views import app_delete from api.base_views import app_delete
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)

@ -20,7 +20,7 @@ from api.utils.serializer import AppsShortSerializer
from api.models import Apps, AppReleaseInfo, APPToDeveloper, APPSuperSignUsedInfo from api.models import Apps, AppReleaseInfo, APPToDeveloper, APPSuperSignUsedInfo
from django.http import FileResponse from django.http import FileResponse
import logging import logging
from api.utils.utils import get_profile_full_path from api.utils.baseutils import get_profile_full_path
from api.utils.throttle import VisitShortThrottle, InstallShortThrottle from api.utils.throttle import VisitShortThrottle, InstallShortThrottle
logger = logging.getLogger(__file__) logger = logging.getLogger(__file__)
@ -240,10 +240,10 @@ class InstallView(APIView):
ip = request.META['REMOTE_ADDR'] ip = request.META['REMOTE_ADDR']
logger.info("remote ip %s short %s download_url %s app_obj %s" % (ip, short, download_url, app_obj)) logger.info("remote ip %s short %s download_url %s app_obj %s" % (ip, short, download_url, app_obj))
set_app_download_by_cache(app_id) set_app_download_by_cache(app_id)
amount = 1 amount = app_obj.get("d_count")
# 超级签需要消耗2个下载次数 # 超级签需要多消耗2倍下载次数
if app_obj.get("issupersign"): if app_obj.get("issupersign"):
amount += 1 amount *= 2
auth_status = False auth_status = False
status = app_obj.get('user_id__certification__status', None) status = app_obj.get('user_id__certification__status', None)
if status and status == 1: if status and status == 1:

@ -6,9 +6,10 @@ from django.core.cache import cache
from rest_framework.views import APIView from rest_framework.views import APIView
import binascii import binascii
import os, datetime import os, datetime
from api.utils.utils import get_captcha, valid_captcha, is_valid_domain, is_valid_phone, \ from api.utils.utils import get_captcha, valid_captcha, \
get_sender_sms_token, is_valid_email, is_valid_sender_code, get_sender_email_token, get_random_username, \ get_sender_sms_token, is_valid_sender_code, get_sender_email_token, get_random_username, \
check_username_exists check_username_exists
from api.utils.baseutils import is_valid_domain, is_valid_phone, is_valid_email
from api.utils.auth import ExpiringTokenAuthentication from api.utils.auth import ExpiringTokenAuthentication
from api.utils.response import BaseResponse from api.utils.response import BaseResponse
from fir_ser.settings import CACHE_KEY_TEMPLATE, SERVER_DOMAIN, REGISTER, LOGIN from fir_ser.settings import CACHE_KEY_TEMPLATE, SERVER_DOMAIN, REGISTER, LOGIN

@ -69,7 +69,7 @@ class OrderView(APIView):
try: try:
order_number = get_order_num() order_number = get_order_num()
actual_amount = price_obj.price actual_amount = price_obj.price
Order.objects.create(payment_type=0, order_number=order_number, Order.objects.create(payment_type=1, order_number=order_number,
account=request.user, status=1, order_type=0, actual_amount=actual_amount, account=request.user, status=1, order_type=0, actual_amount=actual_amount,
actual_download_times=price_obj.package_size, actual_download_times=price_obj.package_size,
actual_download_gift_times=price_obj.download_count_gift) actual_download_gift_times=price_obj.download_count_gift)
@ -95,12 +95,12 @@ class OrderView(APIView):
order_number = request.data.get("order_number", None) order_number = request.data.get("order_number", None)
act = request.data.get("act", None) act = request.data.get("act", None)
if order_number: if order_number:
order_obj = Order.objects.filter(account=request.user, order_number=order_number, status=1).first() order_obj = Order.objects.filter(account=request.user, order_number=order_number).first()
if order_obj: if order_obj:
try: try:
if act == 'cancel' and order_obj.status != 0: if act == 'cancel' and order_obj.status != 0:
update_order_status(order_number, 5) update_order_status(order_number, 5)
elif act == 'status' and order_obj.status == 1: elif act == 'status' and order_obj.status in [1, 2]:
alipay = Alipay() alipay = Alipay()
alipay.update_order_status(order_obj.order_number) alipay.update_order_status(order_obj.order_number)
except Exception as e: except Exception as e:

@ -94,6 +94,7 @@ class StorageView(APIView):
logger.info("user %s update storage data:%s" % (request.user, data)) logger.info("user %s update storage data:%s" % (request.user, data))
use_storage_id = data.get("use_storage_id", None) use_storage_id = data.get("use_storage_id", None)
force = data.get("force", None)
if use_storage_id: if use_storage_id:
if request.user.storage and use_storage_id == request.user.storage.id: if request.user.storage and use_storage_id == request.user.storage.id:
return Response(res.dict) return Response(res.dict)
@ -115,8 +116,17 @@ class StorageView(APIView):
except Exception as e: except Exception as e:
logger.error("update user %s storage failed Exception:%s" % (request.user, e)) logger.error("update user %s storage failed Exception:%s" % (request.user, e))
res.code = 1006 if force:
res.msg = '修改失败' if use_storage_id == -1:
UserInfo.objects.filter(pk=request.user.pk).update(storage=None)
else:
UserInfo.objects.filter(pk=request.user.pk).update(storage_id=use_storage_id)
clean_storage_data(request.user)
else:
res.code = 1006
res.msg = '修改失败'
del_cache_storage(request.user)
return Response(res.dict) return Response(res.dict)
storage_id = data.get("id", None) storage_id = data.get("id", None)

@ -436,14 +436,13 @@ LOGGING = {
PAY_SUCCESS_URL = 'https://app.hehelucky.cn/user/orders' # 前端页面,支付成功跳转页面 PAY_SUCCESS_URL = 'https://app.hehelucky.cn/user/orders' # 前端页面,支付成功跳转页面
PAY_CONFIG = { PAY_CONFIG = {
'ALI': { 'ALI': {
'APP_ID': "2021002132612737", 'APP_ID': "2021002138691845",
'APP_PRIVATE_KEY': '''-----BEGIN RSA PRIVATE KEY----- 'APP_PRIVATE_KEY': '''-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----''', -----END RSA PRIVATE KEY-----''',
'ALI_PUBLIC_KEY': '''-----BEGIN CERTIFICATE----- 'ALI_PUBLIC_KEY': '''-----BEGIN CERTIFICATE-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0Fbo1uH7TRBQUizDFKDSHTqlVCtsRCQuIoD0sqKUOaZ4F1mL9Wz97g//QKkDmQdT6VoDUkEghnxBuZhcMCcEGGEFHICVFfcgzbQQI6ebm58TEQVt/tSIO++FXq23Yglkkd6J8fnBicZfZbTfTysaZemjTvY5+3Nyg5Jp2o3OH1oCp1Xj148laVUrFfzxPaiYyZkyf7Rcd6EdmpZDHqchmB0E1FGK/hi8VnmS9KLtTU2/bIMZeD7Mz9N/6iQPhZImaKzbDr76KSfnNdggbkrD57uhU8tMWZ2QDLYdElCFijJlTPGzVRUqxhG7Wk5JW4cfm0CPNvpBe7xvFnfeCqT6fwIDAQAB MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkru1ulQV1v4q+q38nyzgkdd3evf7C1/Ipu6K+ZFb5FiuxJ7mildkBSuKz/8+TRd+tjgk2lfc2ehK5pja3cxDO/nb25sBoWiU09rtxgXLehLsgRRhatbICrlOnYxg5aiB5odAp3NMRqore4lnVYwfIyL9M49I0G/NbQzYjUQvAQJsnHwc6a6Kuqi1CwR1WXI0sDF9w7KXC4vRFFIUTwI4bVq4HQWI7NhbgEajHM/j6D6Bh/OMcTYnJJzCja0WmZRe5flfCsELlPESOCWUMbYoaNfBzpNvvyOpmRgs9jgy2WY9SeaB9hxwkpr8tOd2Sc7j3221JKCyDaFAX+4zPy7/fQIDAQAB
-----END CERTIFICATE-----''', -----END CERTIFICATE-----''',
'APP_NOTIFY_URL': 'https://app.hehelucky.cn/api/v1/fir/server/pay_success', # 支付支付回调URL 'APP_NOTIFY_URL': 'https://app.hehelucky.cn/api/v1/fir/server/pay_success', # 支付支付回调URL
# 'RETURN_URL': 'https://app.hehelucky.cn/api/v1/fir/server/pay_success', # 支付前端页面回调URL # 'RETURN_URL': 'https://app.hehelucky.cn/api/v1/fir/server/pay_success', # 支付前端页面回调URL

Loading…
Cancel
Save