0.12.36 pays and subscribes

This commit is contained in:
SDE
2024-04-20 12:15:55 +03:00
parent 5c06aceb27
commit bb319780b6
17 changed files with 347 additions and 19 deletions

View File

@@ -18,7 +18,7 @@ from django.contrib.contenttypes.fields import GenericRelation
# add_introspection_rules([], ["^tinymce\.models\.HTMLField"]) # add_introspection_rules([], ["^tinymce\.models\.HTMLField"])
class BaseModel(models.Model): class BaseModel(models.Model):
name = models.TextField(verbose_name=_('Название'), name = models.TextField(verbose_name=_("Название"),
help_text=_('Название'), null=True, blank=True) help_text=_('Название'), null=True, blank=True)
name_plural = models.TextField(verbose_name=_('Название (множественное число)'), name_plural = models.TextField(verbose_name=_('Название (множественное число)'),
null=True, blank=True) null=True, blank=True)

View File

@@ -1,20 +1,100 @@
import json
import requests import requests
from requests_pkcs12 import get,post
pkcs12_filename = 'dvldigitalprojects.p12'
pkcs12_password = 'QNlhRStcY7mB'
def get_domain_url():
return 'https://sandboxapi.paymtech.kz/'
def get_kwargs_for_request():
return {
'headers': {
'content-type': 'application/json',
},
'auth': ('dvldigitalprojects', 'aPqSRVZhxFjjSqbB'),
'pkcs12_filename': pkcs12_filename,
'pkcs12_password': pkcs12_password
}
def ping(): def ping():
req_str = f'https://developerhub.alfabank.by:8273/partner/1.0.1/public/nationalRates{code_str}{date_str}' url = f'{get_domain_url()}ping'
data = {} data = {}
headers = {
'content-type': 'application/json'
}
try: try:
msg = f'GET {req_str}' msg = f'GET {url}'
print(msg) print(msg)
res = requests.get(req_str, data=data, headers=headers) res = get(
url,
**get_kwargs_for_request()
)
msg = f'answer received = {str(res)}' msg = f'answer received = {str(res)}'
print(msg) print(msg)
except Exception as e: except Exception as e:
msg = f'Exception GET {req_str} = {str(e)} ({str(res)})' msg = f'Exception GET {url} = {str(e)} ({str(res)})'
print(msg) print(msg)
res = None res = None
return False
return True
def get_order_status(bank_order_id):
url = f'{get_domain_url()}orders/{str(bank_order_id)}'
res = None
data = {
'expand': [
'card', 'client', 'location', 'custom_fields',
'issuer', 'secure3d', 'operations', 'cashflow'
]
}
try:
msg = f'GET {url}'
print(msg)
res = get(
url,
data=json.dumps(data),
**get_kwargs_for_request()
)
msg = f'create_order answer received = {str(res)}'
print(msg)
except Exception as e:
msg = f'Exception create_order GET {url} = {str(e)} ({str(res)})'
print(msg)
res = None
return res
def create_order(data):
url = f'{get_domain_url()}orders/create'
res = None
try:
msg = f'POST {url}'
print(msg)
res = post(
url,
data=json.dumps(data),
**get_kwargs_for_request()
)
msg = f'create_order answer received = {str(res)}'
print(msg)
except Exception as e:
msg = f'Exception create_order POST {url} = {str(e)} ({str(res)})'
print(msg)
res = None
return res

0
BillingApp/__init__.py Normal file
View File

37
BillingApp/admin.py Normal file
View File

@@ -0,0 +1,37 @@
from sets.admin import *
from .models import *
from django.contrib import admin
class Admin_SubscribeOrder(Admin_BaseModel):
fieldsets = (
(None, {
'classes': ['wide'],
'fields': (
('user', 'subscribe', 'subscribe_for_user'),
('enable', 'order'),
('sum', 'currency'),
('status', 'last_operation_status'),
('bank_order_id', 'pay_page'),
)
}),
)
list_display = [
'id', 'enable',
'user', 'subscribe', 'subscribe_for_user',
'sum', 'currency',
'status', 'last_operation_status',
'order', 'modifiedDT', 'createDT'
]
list_display_links = ['id', 'user', 'subscribe']
list_editable = ['enable']
readonly_fields = ['subscribe_for_user', 'sum', 'currency', 'modifiedDT', 'createDT']
list_filter = ['enable', 'status', 'modifiedDT', 'createDT']
search_fields = ['id', 'last_operation_status', 'status']
# filter_horizontal = ['options']
admin.site.register(SubscribeOrder, Admin_SubscribeOrder)

6
BillingApp/apps.py Normal file
View File

@@ -0,0 +1,6 @@
from django.apps import AppConfig
class BillingappConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'BillingApp'

88
BillingApp/funcs.py Normal file
View File

@@ -0,0 +1,88 @@
from datetime import datetime
from .models import *
import json
def get_order_status(order):
from BaseModels.pay_systems.DVL_Group_kaz.api.funcs import get_order_status
res_status = None
try:
res_data = get_order_status(order.bank_order_id)
res = json.loads(res_data.text)
order.json_data['status'] = res
res = res['orders'][0]
order.status = res['status']
# if res['amount'] == res['amount_charged'] and res['status'] == 'charged':
order.save()
return order.status
except Exception as e:
msg = f'Exception get_order_status = {str(e)}'
if order:
msg = f'Exception get_order_status (data = {str(order.id)}) = {str(e)}'
print(msg)
return None
def get_orders_for_user(user):
orders = SubscribeOrder.objects.filter(
enable=True,
user=user,
subscribe_for_user=None
).order_by('-modifiedDT')
return orders
def create_subscribe_order(data):
order = None
try:
order = SubscribeOrder.objects.create(**data)
from GeneralApp.funcs_options import get_options_by_opt_types, get_mail_send_options
sets = get_options_by_opt_types(['domain', 'project_name'], only_vals=True)
from BaseModels.pay_systems.DVL_Group_kaz.api.funcs import create_order
data = {
'currency': data['currency'],
'amount': data['sum'],
'description': f'Заказ {order.id} на подписку '
f'{data["subscribe"].name} '
f'для пользователя {data["user"].username}',
'options': {
'auto_charge': 1,
'return_url': f'{sets["domain"]}/profile/page/my_subscribe/'
}
}
res_data = create_order(data)
order.pay_page = res_data.headers.get('location')
res = json.loads(res_data.text)
order.json_data['create_order'] = res
res = res['orders'][0]
order.modifiedDT = datetime.strptime(res['updated'], '%Y-%m-%d %H:%M:%S')
order.status = res['status']
order.bank_order_id = res['id']
if 'segment' in res:
order.segment = res['segment']
if 'merchant_order_id' in res:
order.merchant_order_id = res['merchant_order_id']
order.save()
except Exception as e:
msg = f'Exception create_subscribe_order (data = {str(data)}) = {str(e)}'
print(msg)
return order

View File

51
BillingApp/models.py Normal file
View File

@@ -0,0 +1,51 @@
from django.db import models
from BaseModels.base_models import BaseModel
from SubscribesApp.models import Subscribe, SubscribeForUser
from AuthApp.models import User
from django.utils.translation import gettext as _
class SubscribeOrder(BaseModel):
subscribe = models.ForeignKey(
Subscribe, verbose_name=_('Подписка'),
on_delete=models.SET_NULL, blank=True, null=True,
related_name='subscribe_orders_for_subscribe'
)
user = models.ForeignKey(
User, verbose_name=_('Пользователь'),
on_delete=models.SET_NULL, blank=True, null=True,
related_name='subscribe_orders_for_user'
)
subscribe_for_user = models.OneToOneField(
SubscribeForUser, verbose_name=_('Подписка пользователя'),
on_delete=models.SET_NULL, blank=True, null=True,
related_name='subscribe_orders_for_user_subscribe'
)
sum = models.PositiveSmallIntegerField(verbose_name=_('Сумма'), default=0)
currency = models.CharField(verbose_name=_('Валюта'), max_length=3, default='USD')
segment = models.CharField(verbose_name=_('ID Сегмента'), null=True, default=None)
merchant_order_id = models.CharField(verbose_name=_('merchant_order_id'), null=True, default=None)
bank_order_id = models.CharField(verbose_name=_('ID заказа в банке'), null=True, default=None)
status = models.CharField(verbose_name=_('Статус заказа в банке'), null=True, default=None)
last_operation_status = models.CharField(verbose_name=_('Статус последней операции'), null=True, default=None)
pay_page = models.URLField(verbose_name=_('Ссылка на страницу оплаты'), null=True, blank=True, default=None)
class Meta:
verbose_name = _('Заказ на подписку')
verbose_name_plural = _('Заказы на подписки')
def __str__(self):
res = 'Заказ'
if self.subscribe:
res += f' на подписку {self.subscribe.name}'
if self.user:
res += f' для {self.user.username}'
if not res:
res += f' {str(self.id)}'
return res

3
BillingApp/tests.py Normal file
View File

@@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

3
BillingApp/views.py Normal file
View File

@@ -0,0 +1,3 @@
from django.shortcuts import render
# Create your views here.

View File

@@ -24,8 +24,11 @@ def test_code(request):
# apps = SocialApp.objects.all() # apps = SocialApp.objects.all()
# apps.delete() # apps.delete()
from PushMessages.views import send_push # from PushMessages.views import send_push
send_push(request.user, 'test_title', 'test_content') # send_push(request.user, 'test_title', 'test_content')
from BaseModels.pay_systems.DVL_Group_kaz.api.funcs import create_order
create_order()
# from RoutesApp.search_matches import search_matches # from RoutesApp.search_matches import search_matches
# search_matches() # search_matches()

View File

@@ -1,6 +1,7 @@
from .models import * from .models import *
from django.template.loader import render_to_string from django.template.loader import render_to_string
from django.utils.translation import get_language, activate from django.utils.translation import get_language, activate
from datetime import datetime, timedelta
def get_cur_user_subscribe(user): def get_cur_user_subscribe(user):
@@ -13,7 +14,7 @@ def get_cur_user_subscribe(user):
return user_subscribe return user_subscribe
def get_subsribes_w_options(): def get_subscribes_w_options():
all_options = SubscribeOption.objects.filter(enable=True) all_options = SubscribeOption.objects.filter(enable=True)
subscribes = Subscribe.objects.filter(enable=True) subscribes = Subscribe.objects.filter(enable=True)
for subscribe in subscribes: for subscribe in subscribes:
@@ -23,6 +24,28 @@ def get_subsribes_w_options():
return subscribes, all_options return subscribes, all_options
def check_n_enable_subscribe_by_order(order):
subscribes_for_user = SubscribeForUser.objects.filter(user=order.user)
if order and order.enable and order.status == 'charged':
kwargs = {
'user': order.user,
'subscribe': order.subscribe,
'last_paid_DT': datetime.now(),
'paid_period_from_DT': datetime.now(),
'paid_period_to_DT': datetime.now() + timedelta(hours=order.subscribe.period),
'receive_finish_subscribe_msg': True,
}
subscribe_for_user = SubscribeForUser.objects.create(**kwargs)
order.subscribe_for_user = subscribe_for_user
order.save()
subscribes_for_user = [subscribe_for_user]
return subscribes_for_user
def get_profile_subscribe_page_content_html(request): def get_profile_subscribe_page_content_html(request):
try: try:
@@ -32,9 +55,20 @@ def get_profile_subscribe_page_content_html(request):
# data = json.loads(request.body) # data = json.loads(request.body)
# all_options = SubscribeOption.objects.filter(enable=True) # all_options = SubscribeOption.objects.filter(enable=True)
subscribes, all_options = get_subsribes_w_options() subscribes, all_options = get_subscribes_w_options()
subscribe_for_user = None
if request.user and request.user.is_authenticated:
from BillingApp.funcs import get_orders_for_user, get_order_status
orders = get_orders_for_user(request.user)
for order in orders:
res = get_order_status(order)
subscribe_for_user = check_n_enable_subscribe_by_order(order)
if not subscribe_for_user:
subscribe_for_user = SubscribeForUser.objects.filter(user=request.user) subscribe_for_user = SubscribeForUser.objects.filter(user=request.user)
if not subscribe_for_user: if not subscribe_for_user:
tpl_name = 'blocks/profile/b_subscribe_variants.html' tpl_name = 'blocks/profile/b_subscribe_variants.html'
else: else:

View File

@@ -3,7 +3,7 @@ from django.shortcuts import render
from uuid import uuid1 from uuid import uuid1
from .models import * from .models import *
from django.contrib import auth from django.contrib import auth
from django.http import HttpResponse, Http404, JsonResponse from django.http import HttpResponse, Http404, JsonResponse, HttpResponseRedirect
from django.template import loader, RequestContext from django.template import loader, RequestContext
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from BaseModels.mailSender import techSendMail from BaseModels.mailSender import techSendMail
@@ -17,6 +17,7 @@ from datetime import datetime, time, timedelta
from channels.layers import get_channel_layer from channels.layers import get_channel_layer
from asgiref.sync import async_to_sync from asgiref.sync import async_to_sync
from GeneralApp.funcs import get_and_set_lang from GeneralApp.funcs import get_and_set_lang
from django.shortcuts import redirect
@login_required()#login_url='/profile/login/') @login_required()#login_url='/profile/login/')
@@ -33,6 +34,18 @@ def subscribe_now_ajax(request):
subscribe = Subscribe.objects.get(id=data['subscribe_id']) subscribe = Subscribe.objects.get(id=data['subscribe_id'])
kwargs_for_order = {
'user': request.user,
'subscribe': subscribe,
'currency': 'USD',
'sum': subscribe.price,
}
from BillingApp.funcs import create_subscribe_order
order = create_subscribe_order(kwargs_for_order)
if order:
return JsonResponse({'redirect': order.pay_page})
kwargs = { kwargs = {
'user': request.user, 'user': request.user,
'subscribe': subscribe, 'subscribe': subscribe,
@@ -41,13 +54,10 @@ def subscribe_now_ajax(request):
'paid_period_to_DT': datetime.now() + timedelta(hours=subscribe.period), 'paid_period_to_DT': datetime.now() + timedelta(hours=subscribe.period),
'receive_finish_subscribe_msg': True, 'receive_finish_subscribe_msg': True,
} }
subscribe_for_user = SubscribeForUser.objects.filter(user=request.user) subscribe_for_user = SubscribeForUser.objects.filter(user=request.user)
if subscribe_for_user: if subscribe_for_user:
subscribe_for_user.update(**kwargs) subscribe_for_user.update(**kwargs)
subscribe_for_user = subscribe_for_user[0] subscribe_for_user = subscribe_for_user[0]
else:
subscribe_for_user = SubscribeForUser.objects.create(**kwargs)
if not subscribe_for_user: if not subscribe_for_user:
tpl_name = 'blocks/profile/b_subscribe_variants.html' tpl_name = 'blocks/profile/b_subscribe_variants.html'

View File

@@ -50,3 +50,14 @@ class SubscribeForUser(BaseModel):
class Meta: class Meta:
verbose_name = _('Пользовательская подписка') verbose_name = _('Пользовательская подписка')
verbose_name_plural = _('Пользовательские подписки') verbose_name_plural = _('Пользовательские подписки')
def __str__(self):
res = 'Подписка'
if self.subscribe:
res += f' {self.subscribe.name}'
if self.user:
res += f' для {self.user.username}'
if not res:
res += f' {str(self.id)}'
return res

View File

@@ -118,6 +118,7 @@ INSTALLED_APPS = [
'ArticlesApp', 'ArticlesApp',
'SubscribesApp', 'SubscribesApp',
'PushMessages', 'PushMessages',
'BillingApp',
] ]
MIDDLEWARE = [ MIDDLEWARE = [

BIN
dvldigitalprojects.p12 Normal file

Binary file not shown.

View File

@@ -13,5 +13,6 @@ django-colorfield
django-webpush==0.3.5 django-webpush==0.3.5
django-allauth==0.60.0 django-allauth==0.60.0
pytz==2024.1 pytz==2024.1
requests-pkcs12==1.24
#django-tz-detect==0.4.0 #django-tz-detect==0.4.0