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

pull/16/head
youngS 4 years ago
parent cad5906404
commit 75630183c6
  1. 33
      fir_client/src/components/apps/FirApps.vue
  2. 28
      fir_client/src/components/user/FirUserOrders.vue
  3. 22
      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. 5
      fir_ser/api/utils/app/supersignutils.py
  7. 81
      fir_ser/api/utils/baseutils.py
  8. 2
      fir_ser/api/utils/pay/ali.py
  9. 9
      fir_ser/api/utils/storage/caches.py
  10. 75
      fir_ser/api/utils/utils.py
  11. 3
      fir_ser/api/views/apps.py
  12. 8
      fir_ser/api/views/download.py
  13. 5
      fir_ser/api/views/login.py
  14. 6
      fir_ser/api/views/order.py
  15. 10
      fir_ser/api/views/storage.py
  16. 7
      fir_ser/fir_ser/settings.py

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

@ -103,7 +103,7 @@
prop="status"
label="状态"
align="center"
width="130">
width="110">
<template slot-scope="scope">
<div v-if="scope.row.status === 1 || scope.row.status === 2">
@ -148,12 +148,21 @@
<el-table-column
prop="actual_download_gift_times"
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
:formatter="format_create_time"
prop="created_time"
width="170"
align="center"
label="订单创建时间"
>
</el-table-column>
@ -213,16 +222,19 @@
}
},
methods: {
cancel_order(order){
cancel_order(order) {
my_order(res => {
if (res.code === 1000) {
this.$message.success("操作成功");
this.get_data_from_tabname()
this.get_data_from_tabname({
"size": this.pagination.pagesize,
"page": this.pagination.currentPage
})
} else {
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) {
@ -230,7 +242,7 @@
if (res.code === 1000) {
this.$message.success("正在跳转支付平台");
let pay_url = res.data;
if(pay_url && pay_url.length > 10){
if (pay_url && pay_url.length > 10) {
window.location.href = pay_url
}
} else {
@ -241,6 +253,7 @@
})
},
click_order_info(order) {
if (order.status === 1 || order.status === 2) {
my_order(res => {
if (res.code === 1000) {
this.get_data_from_tabname()
@ -248,8 +261,9 @@
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.current_order_info = order;

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

@ -17,7 +17,8 @@ from api.utils.serializer import AppsSerializer, AppReleaseSerializer
from rest_framework.pagination import PageNumberPagination
import logging
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__)

@ -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='状态'),
),
]

@ -11,9 +11,10 @@ from api.models import APPSuperSignUsedInfo, AppUDID, AppIOSDeveloperInfo, AppRe
UDIDsyncDeveloper, DeveloperAppID, DeveloperDevicesID
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.utils import file_format_path, delete_app_to_dev_and_file, delete_app_profile_file, \
send_ios_developer_active_status, get_profile_full_path, delete_local_files, download_files_form_oss, \
from api.utils.utils import delete_app_to_dev_and_file, send_ios_developer_active_status, delete_local_files, \
download_files_form_oss, \
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 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)
# (0, '交易成功'), (1, '待支付'), (2, '订单已创建'), (3, '退费申请中'), (4, '已退费'), (5, '主动取消'), (6, '超时取消')
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':
trade_status = data.get("trade_status", '')
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, \
USER_FREE_DOWNLOAD_TIMES, AUTH_USER_FREE_DOWNLOAD_TIMES
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
from django.db.models import F
@ -96,14 +96,19 @@ def get_download_url_by_cache(app_obj, filename, limit, isdownload=True, key='',
def get_app_instance_by_cache(app_id, password, limit, 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()
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_obj_cache = cache.get(app_key)
if not app_obj_cache:
app_obj_cache = Apps.objects.filter(app_id=app_id).values("pk", 'user_id', 'type', 'password',
'issupersign',
'user_id__certification__status').first()
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")

@ -3,11 +3,11 @@
# project: 5月
# author: liuyu
# date: 2020/5/7
import os, re, json, requests, datetime, random
from fir_ser.settings import SUPER_SIGN_ROOT, SERVER_DOMAIN, CAPTCHA_LENGTH, MEDIA_ROOT
import os, json, requests, datetime, random
from fir_ser.settings import SERVER_DOMAIN, CAPTCHA_LENGTH, MEDIA_ROOT
from api.models import APPSuperSignUsedInfo, APPToDeveloper, \
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.storage import Storage
from api.utils.tempcaches import tmpCache
@ -16,39 +16,13 @@ from api.utils.sendmsg.sendmsg import SendMessage
from django.db.models import Sum
from captcha.models import CaptchaStore
from captcha.helpers import captcha_image_url
from django.core.validators import validate_email
from django.core.exceptions import ValidationError
from api.utils.storage.caches import consume_user_download_times
from django.core.cache import cache
import logging
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):
APPToDeveloper_obj = APPToDeveloper.objects.filter(developerid=developer_obj, app_id_id=app_id)
if APPToDeveloper_obj:
@ -59,16 +33,6 @@ def delete_app_to_dev_and_file(developer_obj, app_id):
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):
SuperSignUsed_obj = APPSuperSignUsedInfo.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)
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):
sms_token_obj = DownloadToken()
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):
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():
# 迁移APP数据
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():
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)
# 消费下载次数
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

@ -17,7 +17,8 @@ from api.utils.serializer import AppsSerializer, AppReleaseSerializer
from rest_framework.pagination import PageNumberPagination
import logging
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
logger = logging.getLogger(__name__)

@ -20,7 +20,7 @@ from api.utils.serializer import AppsShortSerializer
from api.models import Apps, AppReleaseInfo, APPToDeveloper, APPSuperSignUsedInfo
from django.http import FileResponse
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
logger = logging.getLogger(__file__)
@ -240,10 +240,10 @@ class InstallView(APIView):
ip = request.META['REMOTE_ADDR']
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)
amount = 1
# 超级签需要消耗2个下载次数
amount = app_obj.get("d_count")
# 超级签需要多消耗2倍下载次数
if app_obj.get("issupersign"):
amount += 1
amount *= 2
auth_status = False
status = app_obj.get('user_id__certification__status', None)
if status and status == 1:

@ -6,9 +6,10 @@ from django.core.cache import cache
from rest_framework.views import APIView
import binascii
import os, datetime
from api.utils.utils import get_captcha, valid_captcha, is_valid_domain, is_valid_phone, \
get_sender_sms_token, is_valid_email, is_valid_sender_code, get_sender_email_token, get_random_username, \
from api.utils.utils import get_captcha, valid_captcha, \
get_sender_sms_token, is_valid_sender_code, get_sender_email_token, get_random_username, \
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.response import BaseResponse
from fir_ser.settings import CACHE_KEY_TEMPLATE, SERVER_DOMAIN, REGISTER, LOGIN

@ -69,7 +69,7 @@ class OrderView(APIView):
try:
order_number = get_order_num()
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,
actual_download_times=price_obj.package_size,
actual_download_gift_times=price_obj.download_count_gift)
@ -95,12 +95,12 @@ class OrderView(APIView):
order_number = request.data.get("order_number", None)
act = request.data.get("act", None)
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:
try:
if act == 'cancel' and order_obj.status != 0:
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.update_order_status(order_obj.order_number)
except Exception as e:

@ -94,6 +94,7 @@ class StorageView(APIView):
logger.info("user %s update storage data:%s" % (request.user, data))
use_storage_id = data.get("use_storage_id", None)
force = data.get("force", None)
if use_storage_id:
if request.user.storage and use_storage_id == request.user.storage.id:
return Response(res.dict)
@ -115,8 +116,17 @@ class StorageView(APIView):
except Exception as e:
logger.error("update user %s storage failed Exception:%s" % (request.user, e))
if force:
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)
storage_id = data.get("id", None)

@ -436,14 +436,13 @@ LOGGING = {
PAY_SUCCESS_URL = 'https://app.hehelucky.cn/user/orders' # 前端页面,支付成功跳转页面
PAY_CONFIG = {
'ALI': {
'APP_ID': "2021002132612737",
'APP_ID': "2021002138691845",
'APP_PRIVATE_KEY': '''-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----''',
'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-----''',
'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

Loading…
Cancel
Save