integration stripe et mise au norme API cashless
This commit is contained in:
parent
b9f8324333
commit
ba7d4af4d6
|
|
@ -7,6 +7,7 @@ from django.contrib.auth.admin import UserAdmin, GroupAdmin
|
||||||
from Customers.models import Client, Domain
|
from Customers.models import Client, Domain
|
||||||
from AuthBillet.models import TibilletUser, HumanUser, TermUser, SuperHumanUser
|
from AuthBillet.models import TibilletUser, HumanUser, TermUser, SuperHumanUser
|
||||||
from django.utils.translation import gettext, gettext_lazy as _
|
from django.utils.translation import gettext, gettext_lazy as _
|
||||||
|
from QrcodeCashless.models import Detail, CarteCashless
|
||||||
|
|
||||||
|
|
||||||
# from boutique.models import Category, Product, Tag, VAT, Event, LandingPageContent, Billet
|
# from boutique.models import Category, Product, Tag, VAT, Event, LandingPageContent, Billet
|
||||||
|
|
@ -128,5 +129,35 @@ class ClientAdmin(admin.ModelAdmin):
|
||||||
'created_on',
|
'created_on',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
public_admin_site.register(Client, ClientAdmin)
|
public_admin_site.register(Client, ClientAdmin)
|
||||||
|
|
||||||
|
|
||||||
|
class DetailAdmin(admin.ModelAdmin):
|
||||||
|
list_display = (
|
||||||
|
'base_url',
|
||||||
|
'origine',
|
||||||
|
'generation',
|
||||||
|
'img_url',
|
||||||
|
'img',
|
||||||
|
)
|
||||||
|
|
||||||
|
public_admin_site.register(Detail, DetailAdmin)
|
||||||
|
|
||||||
|
class CarteCashlessAdmin(admin.ModelAdmin):
|
||||||
|
|
||||||
|
|
||||||
|
list_display = (
|
||||||
|
'tag_id',
|
||||||
|
'uuid',
|
||||||
|
'number',
|
||||||
|
'get_origin',
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_origin(self, obj):
|
||||||
|
return obj.detail.origine
|
||||||
|
get_origin.short_description = 'Origine'
|
||||||
|
|
||||||
|
search_fields = ('tag_id', 'uuid', 'number')
|
||||||
|
list_filter = ('tag_id', 'uuid', 'number')
|
||||||
|
|
||||||
|
public_admin_site.register(CarteCashless, CarteCashlessAdmin)
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ from BaseBillet.models import Configuration, Event, OptionGenerale, Article, Bil
|
||||||
from django.contrib.auth.admin import UserAdmin
|
from django.contrib.auth.admin import UserAdmin
|
||||||
|
|
||||||
from Customers.models import Client
|
from Customers.models import Client
|
||||||
|
from PaiementStripe.models import Paiement_stripe
|
||||||
|
|
||||||
|
|
||||||
class StaffAdminSite(AdminSite):
|
class StaffAdminSite(AdminSite):
|
||||||
|
|
@ -117,6 +118,9 @@ class ConfigurationAdmin(SingletonModelAdmin):
|
||||||
('Paiements', {
|
('Paiements', {
|
||||||
'fields': (
|
'fields': (
|
||||||
'mollie_api_key',
|
'mollie_api_key',
|
||||||
|
'stripe_api_key',
|
||||||
|
'stripe_test_api_key',
|
||||||
|
'stripe_mode_test',
|
||||||
),
|
),
|
||||||
}),
|
}),
|
||||||
('Billetterie', {
|
('Billetterie', {
|
||||||
|
|
@ -172,13 +176,51 @@ class ReservationAdmin(admin.ModelAdmin):
|
||||||
|
|
||||||
staff_admin_site.register(Reservation, ReservationAdmin)
|
staff_admin_site.register(Reservation, ReservationAdmin)
|
||||||
|
|
||||||
|
class ArticleAdmin(admin.ModelAdmin):
|
||||||
|
list_display = (
|
||||||
|
'name',
|
||||||
|
'prix',
|
||||||
|
'stock',
|
||||||
|
'reservation_par_user_max',
|
||||||
|
'vat',
|
||||||
|
'publish',
|
||||||
|
)
|
||||||
|
list_editable = (
|
||||||
|
'prix',
|
||||||
|
'stock',
|
||||||
|
'reservation_par_user_max',
|
||||||
|
'vat',
|
||||||
|
'publish',
|
||||||
|
)
|
||||||
|
|
||||||
staff_admin_site.register(OptionGenerale, OptionGeneraleAdmin)
|
staff_admin_site.register(Article, ArticleAdmin)
|
||||||
|
|
||||||
staff_admin_site.register(Billet, admin.ModelAdmin)
|
|
||||||
staff_admin_site.register(Article, admin.ModelAdmin)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
staff_admin_site.register(LigneArticle, admin.ModelAdmin)
|
staff_admin_site.register(LigneArticle, admin.ModelAdmin)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
staff_admin_site.register(OptionGenerale, OptionGeneraleAdmin)
|
||||||
|
|
||||||
|
staff_admin_site.register(Billet, admin.ModelAdmin)
|
||||||
|
|
||||||
|
|
||||||
|
class PaiementStripeAdmin(admin.ModelAdmin):
|
||||||
|
list_display = (
|
||||||
|
'detail',
|
||||||
|
'total',
|
||||||
|
'order_date',
|
||||||
|
'user',
|
||||||
|
'status',
|
||||||
|
)
|
||||||
|
ordering = ('-order_date',)
|
||||||
|
# readonly_fields = (
|
||||||
|
# 'reservations',
|
||||||
|
# )
|
||||||
|
|
||||||
|
|
||||||
|
staff_admin_site.register(Paiement_stripe, PaiementStripeAdmin)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -169,7 +169,6 @@ class HumanUserManager(TibilletManager):
|
||||||
is_superuser=False,
|
is_superuser=False,
|
||||||
client_achat__id__in=[connection.tenant.id, ],
|
client_achat__id__in=[connection.tenant.id, ],
|
||||||
)
|
)
|
||||||
# .distinct() ???
|
|
||||||
|
|
||||||
|
|
||||||
class HumanUser(TibilletUser):
|
class HumanUser(TibilletUser):
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,10 @@ class Configuration(SingletonModel):
|
||||||
mollie_api_key = models.CharField(max_length=50,
|
mollie_api_key = models.CharField(max_length=50,
|
||||||
blank=True, null=True)
|
blank=True, null=True)
|
||||||
|
|
||||||
|
stripe_api_key = models.CharField(max_length=110, blank=True, null=True)
|
||||||
|
stripe_test_api_key = models.CharField(max_length=110, blank=True, null=True)
|
||||||
|
stripe_mode_test = models.BooleanField(default=True)
|
||||||
|
|
||||||
jauge_max = models.PositiveSmallIntegerField(default=50)
|
jauge_max = models.PositiveSmallIntegerField(default=50)
|
||||||
|
|
||||||
option_generale_radio = models.ManyToManyField(OptionGenerale,
|
option_generale_radio = models.ManyToManyField(OptionGenerale,
|
||||||
|
|
@ -105,6 +109,18 @@ class Billet(models.Model):
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.name}"
|
return f"{self.name}"
|
||||||
|
|
||||||
|
class VAT(models.Model):
|
||||||
|
"""
|
||||||
|
Les différents taux de TVA sont associés à des produits.
|
||||||
|
"""
|
||||||
|
percent = models.FloatField(verbose_name="Taux de TVA (%)")
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = _('TVA')
|
||||||
|
verbose_name_plural = _('TVA')
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"{self.percent}%"
|
||||||
|
|
||||||
class Article(models.Model):
|
class Article(models.Model):
|
||||||
name = models.CharField(max_length=50,
|
name = models.CharField(max_length=50,
|
||||||
|
|
@ -113,6 +129,9 @@ class Article(models.Model):
|
||||||
stock = models.SmallIntegerField(blank=True, null=True)
|
stock = models.SmallIntegerField(blank=True, null=True)
|
||||||
|
|
||||||
reservation_par_user_max = models.PositiveSmallIntegerField(default=10)
|
reservation_par_user_max = models.PositiveSmallIntegerField(default=10)
|
||||||
|
vat = models.ForeignKey(VAT, on_delete=models.PROTECT, verbose_name="TVA", null=True, blank=True)
|
||||||
|
|
||||||
|
publish = models.BooleanField(default=False)
|
||||||
|
|
||||||
def range_max(self):
|
def range_max(self):
|
||||||
return range(self.reservation_par_user_max + 1)
|
return range(self.reservation_par_user_max + 1)
|
||||||
|
|
@ -224,7 +243,7 @@ class LigneArticle(models.Model):
|
||||||
qty = models.SmallIntegerField()
|
qty = models.SmallIntegerField()
|
||||||
reste = models.SmallIntegerField()
|
reste = models.SmallIntegerField()
|
||||||
paiement_stripe = models.ForeignKey(Paiement_stripe, on_delete=models.PROTECT, blank=True, null=True)
|
paiement_stripe = models.ForeignKey(Paiement_stripe, on_delete=models.PROTECT, blank=True, null=True)
|
||||||
|
datetime = models.DateTimeField(auto_now=True)
|
||||||
# def __str__(self):
|
# def __str__(self):
|
||||||
# if self.reservation :
|
# if self.reservation :
|
||||||
# if self.article :
|
# if self.article :
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
from django.db import models
|
from django.db import models
|
||||||
import uuid
|
import uuid
|
||||||
# Create your models here.
|
# Create your models here.
|
||||||
|
from TiBillet import settings
|
||||||
|
|
||||||
|
# class Configuration_stripe(models.Model):
|
||||||
|
|
||||||
|
|
||||||
class Paiement_stripe(models.Model):
|
class Paiement_stripe(models.Model):
|
||||||
|
|
@ -8,34 +11,29 @@ class Paiement_stripe(models.Model):
|
||||||
La commande
|
La commande
|
||||||
"""
|
"""
|
||||||
uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, unique=True, db_index=True)
|
uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, unique=True, db_index=True)
|
||||||
|
detail = models.CharField(max_length=50, blank=True, null=True)
|
||||||
|
|
||||||
id_stripe = models.CharField(max_length=20, blank=True, null=True)
|
id_stripe = models.CharField(max_length=80, blank=True, null=True)
|
||||||
|
|
||||||
order_date = models.DateTimeField(auto_now=True, verbose_name="Date")
|
order_date = models.DateTimeField(auto_now=True, verbose_name="Date")
|
||||||
|
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.PROTECT, blank=True, null=True)
|
||||||
|
|
||||||
NON, OPEN, PENDING, PAID, VALID, CANCELED = 'N', 'O', 'W', 'P', 'V', 'C'
|
NON, OPEN, PENDING, EXPIRE, PAID, VALID, CANCELED = 'N', 'O', 'W', 'E', 'P', 'V', 'C'
|
||||||
STATUT_CHOICES = (
|
STATUT_CHOICES = (
|
||||||
(NON, 'Lien de paiement non crée'),
|
(NON, 'Lien de paiement non crée'),
|
||||||
(OPEN, 'Envoyée a Stripe'),
|
(OPEN, 'Envoyée a Stripe'),
|
||||||
(PENDING, 'En attente de paiement'),
|
(PENDING, 'En attente de paiement'),
|
||||||
|
(EXPIRE, 'Expiré'),
|
||||||
(PAID, 'Payée'),
|
(PAID, 'Payée'),
|
||||||
(VALID, 'Payée et validée'), # envoyé sur serveur cashless
|
(VALID, 'Payée et validée'), # envoyé sur serveur cashless
|
||||||
(CANCELED, 'Annulée'),
|
(CANCELED, 'Annulée'),
|
||||||
)
|
)
|
||||||
status = models.CharField(max_length=1, choices=STATUT_CHOICES, default=NON, verbose_name="Statut de la commande")
|
status = models.CharField(max_length=1, choices=STATUT_CHOICES, default=NON, verbose_name="Statut de la commande")
|
||||||
|
|
||||||
# a remplir par default sur le front par User.email.
|
total = models.FloatField(default=0)
|
||||||
email_billet = models.CharField(max_length=30, verbose_name="Email de récéption des billets", blank=True)
|
|
||||||
|
|
||||||
# def total(self):
|
|
||||||
# total = 0
|
|
||||||
# for article in ArticleCommande.objects.filter(commande=self):
|
|
||||||
# total += article.total()
|
|
||||||
#
|
|
||||||
# return total
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.status
|
return f"{self.detail} - {self.status}"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
from django.urls import include, path, re_path
|
||||||
|
|
||||||
|
from .views import retour_stripe
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path('return/<uuid:uuid>', retour_stripe.as_view()),
|
||||||
|
path('webhook_stripe', retour_stripe.as_view()),
|
||||||
|
]
|
||||||
|
|
@ -1,3 +1,67 @@
|
||||||
from django.shortcuts import render
|
from datetime import datetime
|
||||||
|
|
||||||
|
from django.http import HttpResponse
|
||||||
|
from django.shortcuts import render, get_object_or_404
|
||||||
|
import stripe
|
||||||
# Create your views here.
|
# Create your views here.
|
||||||
|
from django.views import View
|
||||||
|
|
||||||
|
from BaseBillet.models import Configuration
|
||||||
|
from PaiementStripe.models import Paiement_stripe
|
||||||
|
|
||||||
|
|
||||||
|
class retour_stripe(View):
|
||||||
|
|
||||||
|
def get(self, request, uuid):
|
||||||
|
configuration = Configuration.get_solo()
|
||||||
|
paiement_stripe = get_object_or_404(Paiement_stripe, uuid=uuid)
|
||||||
|
|
||||||
|
if configuration.stripe_mode_test:
|
||||||
|
stripe.api_key = configuration.stripe_test_api_key
|
||||||
|
else:
|
||||||
|
stripe.api_key = configuration.stripe_api_key
|
||||||
|
|
||||||
|
|
||||||
|
if paiement_stripe.status != Paiement_stripe.VALID :
|
||||||
|
|
||||||
|
checkout_session = stripe.checkout.Session.retrieve(paiement_stripe.id_stripe)
|
||||||
|
if checkout_session.payment_status == "unpaid":
|
||||||
|
paiement_stripe.status = Paiement_stripe.PENDING
|
||||||
|
if checkout_session.expires_at > datetime.now().timestamp() :
|
||||||
|
paiement_stripe.status = Paiement_stripe.EXPIRE
|
||||||
|
elif checkout_session.payment_status == "paid":
|
||||||
|
paiement_stripe.status = Paiement_stripe.PAID
|
||||||
|
else:
|
||||||
|
paiement_stripe.status = Paiement_stripe.CANCELED
|
||||||
|
|
||||||
|
paiement_stripe.save()
|
||||||
|
return HttpResponse(f'ok {uuid}')
|
||||||
|
|
||||||
|
|
||||||
|
class webhook_stripe(View):
|
||||||
|
def get(self, request):
|
||||||
|
print(f"webhook_stripe GET")
|
||||||
|
return HttpResponse(f'ok')
|
||||||
|
|
||||||
|
def post(self, request):
|
||||||
|
endpoint_secret = 'whsec_1Urn98yUMsgwdXA7vhN5dwDTRQLD2vmD'
|
||||||
|
event = None
|
||||||
|
payload = request.data
|
||||||
|
sig_header = request.headers['STRIPE_SIGNATURE']
|
||||||
|
|
||||||
|
try:
|
||||||
|
event = stripe.Webhook.construct_event(
|
||||||
|
payload, sig_header, endpoint_secret
|
||||||
|
)
|
||||||
|
except ValueError as e:
|
||||||
|
# Invalid payload
|
||||||
|
raise e
|
||||||
|
except stripe.error.SignatureVerificationError as e:
|
||||||
|
# Invalid signature
|
||||||
|
raise e
|
||||||
|
|
||||||
|
# Handle the event
|
||||||
|
print('Unhandled event type {}'.format(event['type']))
|
||||||
|
|
||||||
|
print(f"webhook_stripe POST {event}")
|
||||||
|
return HttpResponse(f'ok {event}')
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
import os
|
||||||
|
|
||||||
|
from django.core.exceptions import ValidationError
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
from Customers.models import Client, Domain
|
||||||
|
from QrcodeCashless.models import Detail, CarteCashless
|
||||||
|
from django.core.validators import URLValidator
|
||||||
|
|
||||||
|
import csv, uuid
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
|
||||||
|
def is_string_an_url(self, url_string):
|
||||||
|
validate_url = URLValidator()
|
||||||
|
|
||||||
|
try:
|
||||||
|
validate_url(url_string)
|
||||||
|
except ValidationError as e:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
for client in Client.objects.all():
|
||||||
|
print (client.schema_name)
|
||||||
|
|
||||||
|
input_client = input('quel client ? \n')
|
||||||
|
client_tenant = Client.objects.get(schema_name=input_client)
|
||||||
|
print(' ')
|
||||||
|
|
||||||
|
input_generation = input('quelle génération ? \n')
|
||||||
|
print(' ')
|
||||||
|
|
||||||
|
print('url, numéro imprimé len(8), fisrt tag id len(8)')
|
||||||
|
input_fichier_csv = input('path fichier csv ? \n')
|
||||||
|
file = open(input_fichier_csv)
|
||||||
|
|
||||||
|
# file = open('data/raffinerie_1_RETOUR_USINE.csv')
|
||||||
|
|
||||||
|
|
||||||
|
csv_parser = csv.reader(file)
|
||||||
|
list_csv = []
|
||||||
|
for line in csv_parser:
|
||||||
|
list_csv.append(line)
|
||||||
|
|
||||||
|
# on saucissonne l'url d'une ligne au pif :
|
||||||
|
part = list_csv[10][0].partition('/qr/')
|
||||||
|
base_url = f"{part[0]}{part[1]}"
|
||||||
|
if self.is_string_an_url(base_url) :
|
||||||
|
detail_carte, created = Detail.objects.get_or_create(
|
||||||
|
base_url=base_url,
|
||||||
|
origine=client_tenant,
|
||||||
|
generation=input_generation,
|
||||||
|
)
|
||||||
|
|
||||||
|
numline = 1
|
||||||
|
for line in list_csv:
|
||||||
|
print(numline)
|
||||||
|
part = line[0].partition('/qr/')
|
||||||
|
try:
|
||||||
|
uuid_url = uuid.UUID(part[2])
|
||||||
|
print(f"uuid_url : {uuid_url}")
|
||||||
|
print(f"number : {line[1]}")
|
||||||
|
print(f"tag_id : {line[2]}")
|
||||||
|
if str(uuid_url).partition('-')[0].upper() != line[1]:
|
||||||
|
print('ERROR PRINT != uuid')
|
||||||
|
break
|
||||||
|
|
||||||
|
|
||||||
|
carte, created = CarteCashless.objects.get_or_create(
|
||||||
|
tag_id=line[2],
|
||||||
|
uuid=uuid_url,
|
||||||
|
number=line[1],
|
||||||
|
detail=detail_carte,
|
||||||
|
)
|
||||||
|
|
||||||
|
numline += 1
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
|
||||||
|
from django.core.exceptions import ValidationError
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
from Customers.models import Client, Domain
|
||||||
|
from QrcodeCashless.models import Detail, CarteCashless
|
||||||
|
from django.core.validators import URLValidator
|
||||||
|
|
||||||
|
import csv, uuid
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
|
||||||
|
def is_string_an_url(self, url_string):
|
||||||
|
validate_url = URLValidator()
|
||||||
|
|
||||||
|
try:
|
||||||
|
validate_url(url_string)
|
||||||
|
except ValidationError as e:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
for client in Client.objects.all():
|
||||||
|
print (client.schema_name)
|
||||||
|
|
||||||
|
input_client = input('quel client ? \n')
|
||||||
|
client_tenant = Client.objects.get(schema_name=input_client)
|
||||||
|
print(' ')
|
||||||
|
print('url, numéro imprimé len(8), fisrt tag id len(8)')
|
||||||
|
|
||||||
|
input_generation = input('quelle génération ? \n')
|
||||||
|
print(' ')
|
||||||
|
|
||||||
|
detail_carte, created = Detail.objects.get_or_create(
|
||||||
|
base_url='https://m.tibillet.re/',
|
||||||
|
origine=client_tenant,
|
||||||
|
generation=input_generation,
|
||||||
|
)
|
||||||
|
|
||||||
|
file = open('data/CarteCashlessBisik.json')
|
||||||
|
json_dict = json.load(file)
|
||||||
|
|
||||||
|
for card in json_dict:
|
||||||
|
tag_id = card['fields']['tag_id']
|
||||||
|
number = card['fields']['number']
|
||||||
|
if tag_id and number:
|
||||||
|
# on va generer un faux uuid pour le bisik
|
||||||
|
# Namespace hardcodé volontairement pour vérification
|
||||||
|
namespace = uuid.UUID('6ba7b811-9dad-11d1-80b4-00c04fd430c8')
|
||||||
|
gen_uuid = uuid.uuid5(namespace, number)
|
||||||
|
|
||||||
|
print(tag_id)
|
||||||
|
print(number)
|
||||||
|
print(gen_uuid)
|
||||||
|
|
||||||
|
carte, created = CarteCashless.objects.get_or_create(
|
||||||
|
tag_id=tag_id,
|
||||||
|
uuid=gen_uuid,
|
||||||
|
number=number,
|
||||||
|
detail=detail_carte,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,8 +1,29 @@
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
# Create your models here.
|
# Create your models here.
|
||||||
|
from stdimage import StdImageField
|
||||||
|
from stdimage.validators import MaxSizeValidator
|
||||||
|
|
||||||
from Customers.models import Client as Customers_Client
|
from Customers.models import Client as Customers_Client
|
||||||
|
|
||||||
|
class Detail(models.Model):
|
||||||
|
img = StdImageField(upload_to='images/',
|
||||||
|
null=True, blank=True,
|
||||||
|
validators=[MaxSizeValidator(1920, 1920)],
|
||||||
|
variations={
|
||||||
|
'med': (480, 480),
|
||||||
|
'thumbnail': (150, 90),
|
||||||
|
},
|
||||||
|
delete_orphans=True,
|
||||||
|
verbose_name='Recto de la carte'
|
||||||
|
)
|
||||||
|
img_url = models.URLField(null=True, blank=True)
|
||||||
|
base_url = models.CharField(max_length=60, null=True, blank=True)
|
||||||
|
origine = models.ForeignKey(Customers_Client, on_delete=models.PROTECT, null=True, blank=True)
|
||||||
|
generation = models.SmallIntegerField()
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.base_url
|
||||||
|
|
||||||
class CarteCashless(models.Model):
|
class CarteCashless(models.Model):
|
||||||
tag_id = models.CharField(
|
tag_id = models.CharField(
|
||||||
|
|
@ -11,7 +32,7 @@ class CarteCashless(models.Model):
|
||||||
unique=True
|
unique=True
|
||||||
)
|
)
|
||||||
|
|
||||||
uuid_qrcode = models.UUIDField(
|
uuid = models.UUIDField(
|
||||||
blank=True, null=True,
|
blank=True, null=True,
|
||||||
verbose_name='Uuid',
|
verbose_name='Uuid',
|
||||||
)
|
)
|
||||||
|
|
@ -19,9 +40,9 @@ class CarteCashless(models.Model):
|
||||||
number = models.CharField(
|
number = models.CharField(
|
||||||
db_index=True,
|
db_index=True,
|
||||||
max_length=8,
|
max_length=8,
|
||||||
blank=True,
|
|
||||||
null=True,
|
|
||||||
unique=True
|
unique=True
|
||||||
)
|
)
|
||||||
|
|
||||||
origine = models.ForeignKey(Customers_Client, on_delete=models.PROTECT)
|
detail = models.ForeignKey(Detail, on_delete=models.CASCADE, null=True, blank=True)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
from django.urls import include, path, re_path
|
from django.urls import include, path, re_path
|
||||||
|
|
||||||
from .views import index_scan
|
from .views import index_scan, gen_one_bisik
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('<uuid:uuid>', index_scan.as_view()),
|
path('<uuid:uuid>', index_scan.as_view()),
|
||||||
|
path('', gen_one_bisik.as_view())
|
||||||
]
|
]
|
||||||
|
|
@ -1,19 +1,47 @@
|
||||||
import requests, json
|
import requests, json
|
||||||
from django.http import HttpResponseRedirect, HttpResponse
|
from django.contrib.auth import get_user_model
|
||||||
|
from django.db import connection
|
||||||
|
from django.http import HttpResponseRedirect, HttpResponse, Http404
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
|
from rest_framework.generics import get_object_or_404
|
||||||
|
|
||||||
|
import stripe
|
||||||
|
|
||||||
# Create your views here.
|
# Create your views here.
|
||||||
from django.views import View
|
from django.views import View
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
|
||||||
from BaseBillet.models import Configuration
|
from AuthBillet.models import TibilletUser, HumanUser
|
||||||
|
from BaseBillet.models import Configuration, Article
|
||||||
|
from PaiementStripe.models import Paiement_stripe
|
||||||
|
from QrcodeCashless.models import CarteCashless
|
||||||
|
|
||||||
|
def get_domain(request):
|
||||||
|
absolute_uri = request.build_absolute_uri()
|
||||||
|
for domain in request.tenant.domains.all():
|
||||||
|
if domain.domain in absolute_uri:
|
||||||
|
return domain.domain
|
||||||
|
|
||||||
|
raise Http404
|
||||||
|
|
||||||
|
class gen_one_bisik(View):
|
||||||
|
def get(self, request, numero_carte):
|
||||||
|
print(numero_carte)
|
||||||
|
carte = get_object_or_404(CarteCashless, number=numero_carte)
|
||||||
|
address = request.build_absolute_uri()
|
||||||
|
return HttpResponseRedirect(address.replace("://m.", "://bisik.").replace(f"{carte.number}", f"qr/{carte.uuid}"))
|
||||||
|
|
||||||
|
|
||||||
class index_scan(View):
|
class index_scan(View):
|
||||||
template_name = "RechargementWebUuid.html"
|
template_name = "RechargementWebUuid.html"
|
||||||
|
|
||||||
def check_carte(self, uuid):
|
def check_carte_local(self, uuid):
|
||||||
|
carte = get_object_or_404(CarteCashless, uuid=uuid)
|
||||||
|
return carte
|
||||||
|
|
||||||
|
|
||||||
|
def check_carte_serveur_cashless(self, uuid):
|
||||||
configuration = Configuration.get_solo()
|
configuration = Configuration.get_solo()
|
||||||
# on questionne le serveur cashless pour voir si la carte existe :
|
# on questionne le serveur cashless pour voir si la carte existe :
|
||||||
|
|
||||||
|
|
@ -28,81 +56,47 @@ class index_scan(View):
|
||||||
'uuid': f'{uuid}',
|
'uuid': f'{uuid}',
|
||||||
})
|
})
|
||||||
except requests.exceptions.ConnectionError:
|
except requests.exceptions.ConnectionError:
|
||||||
reponse = HttpResponse("Serveur non disponible. Merci de revenir ultérieurement.", status=status.HTTP_503_SERVICE_UNAVAILABLE)
|
reponse = HttpResponse("Serveur non disponible. Merci de revenir ultérieurement.",
|
||||||
|
status=status.HTTP_503_SERVICE_UNAVAILABLE)
|
||||||
|
|
||||||
sess.close()
|
sess.close()
|
||||||
return reponse
|
return reponse
|
||||||
|
|
||||||
def post(self, request, uuid):
|
|
||||||
data = request.POST
|
|
||||||
reponse_server_cashless = self.check_carte(uuid)
|
|
||||||
|
|
||||||
if data.get('numero_carte_cashless') == str(uuid).split('-')[0].upper() and \
|
|
||||||
reponse_server_cashless.status_code == 200:
|
|
||||||
|
|
||||||
userWeb, created = User.objects.get_or_create(
|
|
||||||
username="RechargementWeb",
|
|
||||||
email="rechargementweb@tibillet.re")
|
|
||||||
|
|
||||||
vat, created = VAT.objects.get_or_create(percent=0)
|
|
||||||
|
|
||||||
commande = Commande.objects.create(
|
|
||||||
user=userWeb,
|
|
||||||
email_billet=data.get('email'),
|
|
||||||
)
|
|
||||||
|
|
||||||
art, created = Product.objects.get_or_create(
|
|
||||||
name="CashlessRechargementWeb",
|
|
||||||
price_ttc="1",
|
|
||||||
publish=False,
|
|
||||||
vat=vat
|
|
||||||
)
|
|
||||||
|
|
||||||
ArticleCommande.objects.create(
|
|
||||||
product=art,
|
|
||||||
quantity=data.get('thune'),
|
|
||||||
commande=commande,
|
|
||||||
)
|
|
||||||
|
|
||||||
domain = get_domain(request)
|
|
||||||
sub_domain = str(domain).split('.')[0]
|
|
||||||
absolute_domain = request.build_absolute_uri().partition('/qr')[0]
|
|
||||||
|
|
||||||
Paiement = CreationPaiementMollie(commande, domain,
|
|
||||||
description=f"Rechargez votre carte {sub_domain.capitalize()}",
|
|
||||||
redirectUrl=f"{absolute_domain}/RechargementWebAfterMollie/{commande.uuid}",
|
|
||||||
webhookUrl=f"{absolute_domain}/RechargementWebAfterMollie/{commande.uuid}",
|
|
||||||
numero_carte_cashless=data.get('numero_carte_cashless'))
|
|
||||||
|
|
||||||
if Paiement.is_send():
|
|
||||||
return HttpResponseRedirect(Paiement.is_send())
|
|
||||||
|
|
||||||
|
|
||||||
def get(self, request, uuid):
|
def get(self, request, uuid):
|
||||||
|
carte = self.check_carte_local(uuid)
|
||||||
|
if carte.detail.origine != connection.tenant :
|
||||||
|
raise Http404
|
||||||
|
|
||||||
|
# dette technique ...
|
||||||
|
# pour rediriger les premières générations de qrcode
|
||||||
|
# m.tibillet.re et raffinerie
|
||||||
|
|
||||||
# pour rediriger les carte imprimés a la raffinerie vers le bon tenant.
|
|
||||||
address = request.build_absolute_uri()
|
address = request.build_absolute_uri()
|
||||||
host = address.partition('://')[2]
|
host = address.partition('://')[2]
|
||||||
sub_addr = host.partition('.')[0]
|
sub_addr = host.partition('.')[0]
|
||||||
if sub_addr == "m":
|
if sub_addr == "m":
|
||||||
return HttpResponseRedirect(address.replace("://m.", "://raffinerie."))
|
return HttpResponseRedirect(address.replace("://m.", "://raffinerie."))
|
||||||
|
|
||||||
|
|
||||||
configuration = Configuration.get_solo()
|
configuration = Configuration.get_solo()
|
||||||
if not configuration.server_cashless:
|
if not configuration.server_cashless:
|
||||||
return HttpResponse(
|
return HttpResponse(
|
||||||
"L'adresse du serveur cashless n'est pas renseignée dans la configuration de la billetterie.")
|
"L'adresse du serveur cashless n'est pas renseignée dans la configuration de la billetterie.")
|
||||||
|
if not configuration.stripe_api_key or not configuration.stripe_test_api_key:
|
||||||
|
return HttpResponse(
|
||||||
|
"Pas d'information de configuration pour paiement en ligne.")
|
||||||
|
|
||||||
reponse_server_cashless = self.check_carte(uuid)
|
reponse_server_cashless = self.check_carte_serveur_cashless(carte.uuid)
|
||||||
|
if reponse_server_cashless.status_code == 200:
|
||||||
json_reponse = json.loads(reponse_server_cashless.json())
|
json_reponse = json.loads(reponse_server_cashless.json())
|
||||||
liste_assets = json_reponse.get('liste_assets')
|
liste_assets = json_reponse.get('liste_assets')
|
||||||
email = json_reponse.get('email')
|
email = json_reponse.get('email')
|
||||||
|
|
||||||
if reponse_server_cashless.status_code == 200:
|
|
||||||
return render(
|
return render(
|
||||||
request,
|
request,
|
||||||
self.template_name,
|
self.template_name,
|
||||||
{
|
{
|
||||||
'numero_carte': str(uuid).split('-')[0].upper(),
|
'numero_carte': carte.number,
|
||||||
'domain': sub_addr,
|
'domain': sub_addr,
|
||||||
'informations_carte': reponse_server_cashless.text,
|
'informations_carte': reponse_server_cashless.text,
|
||||||
'liste_assets': liste_assets,
|
'liste_assets': liste_assets,
|
||||||
|
|
@ -117,3 +111,126 @@ class index_scan(View):
|
||||||
elif reponse_server_cashless.status_code == 500:
|
elif reponse_server_cashless.status_code == 500:
|
||||||
# Serveur cashless hors ligne
|
# Serveur cashless hors ligne
|
||||||
return reponse_server_cashless
|
return reponse_server_cashless
|
||||||
|
|
||||||
|
def post(self, request, uuid):
|
||||||
|
carte = self.check_carte_local(uuid)
|
||||||
|
if carte.detail.origine != connection.tenant :
|
||||||
|
raise Http404
|
||||||
|
|
||||||
|
data = request.POST
|
||||||
|
reponse_server_cashless = self.check_carte_serveur_cashless(carte.uuid)
|
||||||
|
montant_recharge = float(data.get('thune'))
|
||||||
|
configuration = Configuration.get_solo()
|
||||||
|
|
||||||
|
if data.get('numero_carte_cashless') == str(uuid).split('-')[0].upper() and \
|
||||||
|
reponse_server_cashless.status_code == 200 and \
|
||||||
|
montant_recharge > 0:
|
||||||
|
|
||||||
|
User = get_user_model()
|
||||||
|
user_recharge, created = User.objects.get_or_create(
|
||||||
|
email=data.get('email'))
|
||||||
|
if created:
|
||||||
|
user_recharge: HumanUser
|
||||||
|
user_recharge.client_source = connection.tenant
|
||||||
|
user_recharge.client_achat.add(connection.tenant)
|
||||||
|
user_recharge.is_active = False
|
||||||
|
else:
|
||||||
|
user_recharge.client_achat.add(connection.tenant)
|
||||||
|
user_recharge.save()
|
||||||
|
|
||||||
|
art, created = Article.objects.get_or_create(
|
||||||
|
name="Recharge Stripe",
|
||||||
|
prix="1",
|
||||||
|
publish=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
paiementStripe = Paiement_stripe.objects.create(
|
||||||
|
user=user_recharge,
|
||||||
|
detail=f"{art.name}",
|
||||||
|
total=float("{0:.2f}".format(montant_recharge)),
|
||||||
|
)
|
||||||
|
|
||||||
|
domain = get_domain(request)
|
||||||
|
absolute_domain = request.build_absolute_uri().partition('/qr')[0]
|
||||||
|
|
||||||
|
if configuration.stripe_mode_test:
|
||||||
|
stripe.api_key = configuration.stripe_test_api_key
|
||||||
|
else:
|
||||||
|
stripe.api_key = configuration.stripe_api_key
|
||||||
|
|
||||||
|
checkout_session = stripe.checkout.Session.create(
|
||||||
|
customer_email=f'{user_recharge.email}',
|
||||||
|
line_items=[{
|
||||||
|
'price_data': {
|
||||||
|
'currency': 'eur',
|
||||||
|
|
||||||
|
'product_data': {
|
||||||
|
'name': 'Recharge Cashless',
|
||||||
|
"images": [f'{carte.detail.img_url}', ],
|
||||||
|
},
|
||||||
|
'unit_amount': int("{0:.2f}".format(montant_recharge).replace('.', '')),
|
||||||
|
},
|
||||||
|
'quantity': 1,
|
||||||
|
|
||||||
|
}],
|
||||||
|
payment_method_types=[
|
||||||
|
'card',
|
||||||
|
],
|
||||||
|
mode='payment',
|
||||||
|
metadata={
|
||||||
|
'Carte': str(uuid).split('-')[0].upper()
|
||||||
|
},
|
||||||
|
success_url=f'{absolute_domain}/stripe/return/{paiementStripe.uuid}',
|
||||||
|
cancel_url=f'{absolute_domain}/stripe/return/{paiementStripe.uuid}',
|
||||||
|
# submit_type='Go go go',
|
||||||
|
client_reference_id=f"{data.get('numero_carte_cashless')}",
|
||||||
|
)
|
||||||
|
|
||||||
|
print(checkout_session.id)
|
||||||
|
paiementStripe.id_stripe = checkout_session.id
|
||||||
|
paiementStripe.status = Paiement_stripe.PENDING
|
||||||
|
paiementStripe.save()
|
||||||
|
|
||||||
|
return HttpResponseRedirect(checkout_session.url)
|
||||||
|
|
||||||
|
# Paiement = CreationPaiementMollie(commande, domain,
|
||||||
|
# description=f"Rechargez votre carte {sub_domain.capitalize()}",
|
||||||
|
# redirectUrl=f"{absolute_domain}/RechargementWebAfterMollie/{commande.uuid}",
|
||||||
|
# webhookUrl=f"{absolute_domain}/RechargementWebAfterMollie/{commande.uuid}",
|
||||||
|
# numero_carte_cashless=data.get('numero_carte_cashless'))
|
||||||
|
#
|
||||||
|
# if Paiement.is_send():
|
||||||
|
# return HttpResponseRedirect(Paiement.is_send())
|
||||||
|
|
||||||
|
#
|
||||||
|
# def postPaimentRecharge(paiementStripe: Paiement_stripe):
|
||||||
|
#
|
||||||
|
# if paiementStripe.status == Paiement_stripe.PAID :
|
||||||
|
#
|
||||||
|
# sess = requests.Session()
|
||||||
|
# configuration = Configuration.get_solo()
|
||||||
|
# r = sess.post(f'{configuration.server_cashless}/wv/rechargementWeb',
|
||||||
|
# data={
|
||||||
|
# 'number': numero_carte_cashless,
|
||||||
|
# 'qty': commande.total(),
|
||||||
|
# 'uuid_commande': commande_uuid,
|
||||||
|
# 'API_TIBILLET_BILLETERIE_VERS_CASHLESS': os.getenv(
|
||||||
|
# 'API_TIBILLET_BILLETERIE_VERS_CASHLESS'),
|
||||||
|
# })
|
||||||
|
#
|
||||||
|
# sess.close()
|
||||||
|
#
|
||||||
|
# if r.status_code == 200:
|
||||||
|
# # la commande a été envoyé au serveur cashless, on la met en validée
|
||||||
|
# commande.status = 'V'
|
||||||
|
# commande.save()
|
||||||
|
#
|
||||||
|
# return HttpResponse(
|
||||||
|
# f"<center><h1>Paiement validé, vous avez rechargé votre carte ! Disponible : {r.text}</h1></center>")
|
||||||
|
#
|
||||||
|
# elif commande.status == "V":
|
||||||
|
# # Le paiement a bien été accepté par le passé et envoyé au serveur cashless.
|
||||||
|
# return HttpResponse(
|
||||||
|
# f"<center><h1>Paiement bien validé, vous avez rechargé votre carte !</h1></center>")
|
||||||
|
#
|
||||||
|
# return HttpResponse("<center><h1>Paiement non valide. Contactez un responsable.<h1></center>")
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,11 @@ urlpatterns = [
|
||||||
re_path(r'api/', include('ApiBillet.urls')),
|
re_path(r'api/', include('ApiBillet.urls')),
|
||||||
re_path(r'qr/', include('QrcodeCashless.urls')),
|
re_path(r'qr/', include('QrcodeCashless.urls')),
|
||||||
|
|
||||||
|
# pour carte GEN1 Bisik
|
||||||
|
re_path(r'(?P<numero_carte>^\w{5}$)', include('QrcodeCashless.urls')),
|
||||||
|
|
||||||
|
re_path(r'stripe/', include('PaiementStripe.urls')),
|
||||||
|
|
||||||
|
|
||||||
path('', include('BaseBillet.urls')),
|
path('', include('BaseBillet.urls')),
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ services:
|
||||||
container_name: tibillet_postgres
|
container_name: tibillet_postgres
|
||||||
image: postgres:11.5-alpine
|
image: postgres:11.5-alpine
|
||||||
restart: always
|
restart: always
|
||||||
|
ports:
|
||||||
|
- 5432:5432
|
||||||
volumes:
|
volumes:
|
||||||
- "../../Postgres/dbdata:/var/lib/postgresql/data"
|
- "../../Postgres/dbdata:/var/lib/postgresql/data"
|
||||||
- "/etc/localtime:/etc/localtime:ro"
|
- "/etc/localtime:/etc/localtime:ro"
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,7 @@ RUN pip install django-stdimage
|
||||||
# RUN pip install -U social-auth-app-django
|
# RUN pip install -U social-auth-app-django
|
||||||
# RUN pip install -U django-templated-mail
|
# RUN pip install -U django-templated-mail
|
||||||
|
|
||||||
|
RUN pip install stripe
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue