1524 lines
60 KiB
Python
1524 lines
60 KiB
Python
#! /usr/bin/env python3.6
|
|
"""
|
|
Python 3.6 or newer required.
|
|
"""
|
|
import pymongo
|
|
import stripe
|
|
import json
|
|
import os
|
|
|
|
from flask import Flask, render_template, jsonify, request
|
|
from dotenv import load_dotenv, find_dotenv
|
|
import GlobalVariable as MYSY_GV
|
|
from pymongo import ReturnDocument
|
|
import prj_common as mycommon
|
|
|
|
import inspect
|
|
import sys, os
|
|
import time
|
|
from datetime import datetime, timedelta
|
|
from dateutil.relativedelta import relativedelta
|
|
import email_mgt as email_mgt
|
|
import lms_chamilo.mysy_lms as mysy_lms
|
|
|
|
# Setup Stripe python client library
|
|
load_dotenv(find_dotenv())
|
|
|
|
# For sample support and debugging, not required for production:
|
|
stripe.set_app_info(
|
|
'stripe-samples/subscription-use-cases/fixed-price',
|
|
version='0.0.1',
|
|
url='https://github.com/stripe-samples/subscription-use-cases/fixed-price')
|
|
|
|
stripe.api_version = '2020-08-27'
|
|
stripe.api_key = MYSY_GV.STRIPE_CONFIG_API_KEY
|
|
|
|
#static_dir = str(os.path.abspath(os.path.join(__file__, "..", os.getenv("STATIC_DIR"))))
|
|
static_dir = "./"
|
|
app = Flask(__name__, static_folder=static_dir, static_url_path="", template_folder=static_dir)
|
|
|
|
|
|
@app.route('/', methods=['GET'])
|
|
def get_index():
|
|
return render_template('register.html')
|
|
|
|
|
|
@app.route('/config', methods=['GET'])
|
|
def get_config():
|
|
# Retrieves two prices with the lookup_keys
|
|
# `sample_basic` and `sample_premium`. To
|
|
# create these prices, you can use the Stripe
|
|
# CLI fixtures command with the supplied
|
|
# `seed.json` fixture file like so:
|
|
#
|
|
# stripe fixtures seed.json
|
|
#
|
|
|
|
prices = stripe.Price.list(
|
|
|
|
)
|
|
|
|
return jsonify(
|
|
publishableKey= MYSY_GV.STRIPE_CONFIG_KEY_PUB,
|
|
prices=prices.data,
|
|
)
|
|
|
|
"""
|
|
Creation d'un client dans Stripe
|
|
"""
|
|
|
|
def create_customer(diction):
|
|
# Reads application/json and returns a response
|
|
#data = json.loads(request.data)
|
|
try:
|
|
|
|
field_list = ['name', 'email', 'country', 'city']
|
|
|
|
# recuperation des infos du partenaire
|
|
cust_name = ""
|
|
if ("name" in diction.keys()):
|
|
if diction['name']:
|
|
cust_name = diction['name']
|
|
|
|
cust_email = ""
|
|
if ("email" in diction.keys()):
|
|
if diction['email']:
|
|
cust_email = diction['email']
|
|
|
|
cust_country = ""
|
|
if ("country" in diction.keys()):
|
|
if diction['country']:
|
|
cust_country = diction['country']
|
|
|
|
cust_city = ""
|
|
if ("city" in diction.keys()):
|
|
if diction['city']:
|
|
cust_city = diction['city']
|
|
|
|
|
|
# Create a new customer object
|
|
#customer = stripe.Customer.create(email=data['email'])
|
|
customer = stripe.Customer.create(
|
|
email=cust_email,
|
|
name=cust_name,
|
|
address={
|
|
"city": cust_city,
|
|
"country": cust_country,
|
|
},
|
|
)
|
|
|
|
if( customer and customer.id ):
|
|
mycommon.myprint(
|
|
str(inspect.stack()[0][3]) + " - le partenaire "+str(cust_email)+" a été correctement créé dans Stripe. Son Id = "+str(customer.id))
|
|
return True, str(customer.id)
|
|
else:
|
|
mycommon.myprint(
|
|
str(inspect.stack()[0][3]) + " WARNING - Impossble de créer le partenaire " + str(
|
|
cust_email) + " Stripe.")
|
|
return False, False
|
|
|
|
|
|
except Exception as e:
|
|
exc_type, exc_obj, exc_tb = sys.exc_info()
|
|
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
|
|
return False, False
|
|
|
|
|
|
"""
|
|
Recuperation des mode de payement d'un customer
|
|
"""
|
|
def get_customer_payement_cards(diction):
|
|
try:
|
|
|
|
field_list = ['stripe_account_id']
|
|
# recuperation des infos du partenaire
|
|
stripe_account_id = ""
|
|
if ("stripe_account_id" in diction.keys()):
|
|
if diction['stripe_account_id']:
|
|
stripe_account_id = diction['stripe_account_id']
|
|
|
|
customer_payments = stripe.Customer.list_payment_methods(
|
|
str(stripe_account_id),
|
|
type="card",
|
|
)
|
|
|
|
#print(" ### customer_payments = "+str(customer_payments.data))
|
|
|
|
RetObject = []
|
|
nb_carte = 0
|
|
for val in customer_payments.data :
|
|
nb_carte = nb_carte + 1
|
|
my_card = {}
|
|
my_card['nom_carte'] = str(val.billing_details.name)
|
|
my_card['brand'] = str(val.card.brand)
|
|
my_card['exp_month'] = str(val.card.exp_month)
|
|
my_card['exp_year'] = str(val.card.exp_year)
|
|
my_card['last4'] = str(val.card.last4)
|
|
my_card['createdatetime'] = str( datetime.fromtimestamp(int(str(val.created))) )
|
|
|
|
|
|
RetObject.append(mycommon.JSONEncoder().encode(my_card))
|
|
|
|
|
|
|
|
#print(" ### RetObject = "+str( RetObject ))
|
|
|
|
return True, RetObject, str(nb_carte)
|
|
except Exception as e:
|
|
exc_type, exc_obj, exc_tb = sys.exc_info()
|
|
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
|
|
return False, False, False
|
|
|
|
"""
|
|
Creation d'une carte de payement
|
|
"""
|
|
def create_update_payment_card(diction):
|
|
try:
|
|
|
|
field_list_obligatoire = ['name', 'number', 'exp_month', 'exp_year', 'cvc', 'customerid', 'stripe_paymentmethod_id']
|
|
for val in field_list_obligatoire:
|
|
if val not in diction:
|
|
mycommon.myprint(
|
|
str(inspect.stack()[0][3]) + " - La valeur '" + val + "' n'est pas presente dans liste ")
|
|
return False, " Impossible de créer el moyen de payement"
|
|
|
|
name = ""
|
|
if ("name" in diction.keys()):
|
|
if diction['name']:
|
|
name = diction['name']
|
|
|
|
number = ""
|
|
if ("number" in diction.keys()):
|
|
if diction['number']:
|
|
number = diction['number']
|
|
|
|
exp_month = ""
|
|
if ("exp_month" in diction.keys()):
|
|
if diction['exp_month']:
|
|
exp_month = diction['exp_month']
|
|
|
|
exp_year = ""
|
|
if ("exp_year" in diction.keys()):
|
|
if diction['exp_year']:
|
|
exp_year = diction['exp_year']
|
|
|
|
cvc = ""
|
|
if ("cvc" in diction.keys()):
|
|
if diction['cvc']:
|
|
cvc = diction['cvc']
|
|
|
|
customer_id = ""
|
|
if ("customerid" in diction.keys()):
|
|
if diction['customerid']:
|
|
customer_id = diction['customerid']
|
|
|
|
stripe_paymentmethod_id = ""
|
|
if ("stripe_paymentmethod_id" in diction.keys()):
|
|
if diction['stripe_paymentmethod_id']:
|
|
stripe_paymentmethod_id = diction['stripe_paymentmethod_id']
|
|
|
|
|
|
"""
|
|
/!\ IMPORTANT :
|
|
Si Le champ "stripe_paymentmethod_id" est rempli alors c'est une mise à jour :
|
|
a) on detache
|
|
b) on créer la nouvelle carte
|
|
c) on rattacjhe
|
|
|
|
Si Le champ "stripe_paymentmethod_id" est vide, alors c'est une creation + Attachement au client
|
|
"""
|
|
print(" ## stripe_paymentmethod_id existe. donc suppression de = "+str(stripe_paymentmethod_id))
|
|
if (len(stripe_paymentmethod_id) > 2):
|
|
print(" ### UPDATE ==> detache")
|
|
detache = stripe.PaymentMethod.detach(
|
|
stripe_paymentmethod_id,
|
|
)
|
|
|
|
#print(" #### detache "+str(detache))
|
|
|
|
|
|
|
|
|
|
#print(" ### CREATE ")
|
|
new_card = stripe.PaymentMethod.create(
|
|
type="card",
|
|
card={
|
|
"number": number,
|
|
"exp_month": int(exp_month),
|
|
"exp_year": int(exp_year),
|
|
"cvc": cvc,
|
|
},
|
|
billing_details={
|
|
"name": str(name)
|
|
},
|
|
)
|
|
|
|
#print(" new_card = "+str(new_card))
|
|
|
|
#print(" l'ID de la carte est : "+str(new_card.id))
|
|
|
|
|
|
|
|
attache = stripe.PaymentMethod.attach(
|
|
str(new_card.id),
|
|
customer=str(customer_id),
|
|
)
|
|
|
|
#print(" attache = "+str(attache))
|
|
|
|
return True, new_card
|
|
except Exception as e:
|
|
exc_type, exc_obj, exc_tb = sys.exc_info()
|
|
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
|
|
return False, False
|
|
|
|
|
|
"""
|
|
Cette fonction confirme un abonnement
|
|
"""
|
|
def confirm_suscription(diction):
|
|
try:
|
|
field_list_obligatoire = ['stripe_payment_id','token']
|
|
for val in field_list_obligatoire:
|
|
if val not in diction:
|
|
mycommon.myprint(
|
|
str(inspect.stack()[0][3]) + " - La valeur '" + val + "' n'est pas presente dans liste ")
|
|
return False, " Impossible de créer el moyen de payement", False, False
|
|
|
|
|
|
stripe_payment_id = ""
|
|
if ("stripe_payment_id" in diction.keys()):
|
|
if diction['stripe_payment_id']:
|
|
stripe_payment_id = diction['stripe_payment_id']
|
|
|
|
token = ""
|
|
if ("token" in diction.keys()):
|
|
if diction['token']:
|
|
token = diction['token']
|
|
|
|
# Recuperation du payement methode du client.
|
|
local_ret_val = MYSY_GV.dbname['partnair_account'].find_one(
|
|
{'token': token, 'active': '1', 'locked': '0'})
|
|
|
|
if (local_ret_val['stripe_paymentmethod_id'] is None):
|
|
mycommon.myprint(
|
|
str(inspect.stack()[0][3]) + " Impossible de finaliser le payement")
|
|
return False, " Impossible de finaliser le payement ", False, False
|
|
|
|
# Recuperation de la dernière commande du client
|
|
cmd_ret_val = MYSY_GV.dbname['sales_order'].find(
|
|
{'client_recid': str(local_ret_val['recid']), 'valide': '1'}).sort([("_id",pymongo.DESCENDING) ])
|
|
|
|
if(cmd_ret_val[0] is None or cmd_ret_val[0]['order_id'] is None ):
|
|
mycommon.myprint(
|
|
str(inspect.stack()[0][3]) + " Impossible de finaliser le payement")
|
|
return False, " Impossible de finaliser le payement ", False, False
|
|
|
|
cmd_order_id = cmd_ret_val[0]['order_id']
|
|
mydata_update = {'stripe_pi':stripe_payment_id}
|
|
|
|
### Mise à jour de la commande avec le payement id
|
|
local_update_val = MYSY_GV.dbname['sales_order'].find_one_and_update(
|
|
{'order_id':str(cmd_order_id)},
|
|
{"$set": mydata_update},
|
|
upsert=False,
|
|
return_document=ReturnDocument.AFTER
|
|
)
|
|
|
|
if (local_update_val['_id'] is None):
|
|
mycommon.myprint(
|
|
str(inspect.stack()[0][3]) + " Impossible de finaliser le payement 2")
|
|
return False, " Impossible de finaliser le payement (2) ", False, False
|
|
|
|
#print(" ### stripe_payment_id = ", stripe_payment_id, " ### stripe_paymentmethod_id = ", local_ret_val['stripe_paymentmethod_id'])
|
|
confirmation_payement = stripe.PaymentIntent.confirm(
|
|
stripe_payment_id,
|
|
payment_method=str(local_ret_val['stripe_paymentmethod_id']),
|
|
return_url= MYSY_GV.CLIENT_URL_BASE+"OrderConfirmation_3DS/"+str(cmd_order_id)+"/"+str(local_ret_val['pack_service'])
|
|
|
|
)
|
|
|
|
"""
|
|
/!\ : le client a demarré un payement.
|
|
1 - je supprimer son pack abonnement pour se premunir d'un echec au prelevement
|
|
2 - Je remettrai le bon pack lors qu'il aura confirmé
|
|
|
|
"""
|
|
### Mise à jour de la commande avec le payement id
|
|
local_update_cust = MYSY_GV.dbname['partnair_account'].find_one_and_update(
|
|
{'token': token, 'active': '1', 'locked': '0'},
|
|
{"$set": {'pack_service':'', }},
|
|
upsert=False,
|
|
return_document=ReturnDocument.AFTER
|
|
)
|
|
|
|
if (local_update_cust['_id'] is None):
|
|
mycommon.myprint(
|
|
str(inspect.stack()[0][3]) + " Impossible de finaliser le payement 3")
|
|
return False, " Impossible de finaliser le payement (3) ", False, False
|
|
|
|
#print(' #### confirmation_payement = ', confirmation_payement)
|
|
myredirect_to_url = ""
|
|
if( confirmation_payement.next_action and confirmation_payement.next_action.redirect_to_url and confirmation_payement.next_action.redirect_to_url.url ):
|
|
myredirect_to_url = confirmation_payement.next_action.redirect_to_url.url
|
|
else:
|
|
myredirect_to_url = MYSY_GV.CLIENT_URL_BASE+"OrderConfirmation_3DS/"+str(cmd_order_id)+"/"+str(local_ret_val['pack_service'])
|
|
|
|
return True, confirmation_payement.id, confirmation_payement.status, myredirect_to_url
|
|
|
|
|
|
except Exception as e:
|
|
exc_type, exc_obj, exc_tb = sys.exc_info()
|
|
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
|
|
return False, False, False, False
|
|
|
|
"""
|
|
Cette fonction verifier si un payement est ok ou Ko"""
|
|
def payment_retrieve_status(diction):
|
|
try:
|
|
field_list_obligatoire = ['stripe_payment_id','token', 'packs']
|
|
for val in field_list_obligatoire:
|
|
if val not in diction:
|
|
mycommon.myprint(
|
|
str(inspect.stack()[0][3]) + " - La valeur '" + val + "' n'est pas presente dans liste ")
|
|
return False, " Impossible de verifier le payement les données obligatoires ne sont pas fournies",
|
|
|
|
|
|
stripe_payment_id = ""
|
|
if ("stripe_payment_id" in diction.keys()):
|
|
if diction['stripe_payment_id']:
|
|
stripe_payment_id = diction['stripe_payment_id']
|
|
|
|
token = ""
|
|
if ("token" in diction.keys()):
|
|
if diction['token']:
|
|
token = diction['token']
|
|
|
|
packs = ""
|
|
if ("packs" in diction.keys()):
|
|
if diction['packs']:
|
|
packs = diction['packs']
|
|
|
|
# Recuperation du payement methode du client.
|
|
local_ret_val = MYSY_GV.dbname['partnair_account'].find_one(
|
|
{'token': token, 'active': '1', 'locked': '0'})
|
|
|
|
if (local_ret_val['stripe_paymentmethod_id'] is None):
|
|
mycommon.myprint(
|
|
str(inspect.stack()[0][3]) + " Impossible de verifier le payement 'stripe_paymentmethod_id' instrouvable ")
|
|
return False, " Impossible de verifier le payement 'stripe_paymentmethod_id' instrouvable "
|
|
|
|
|
|
payement_retrive_status = stripe.PaymentIntent.retrieve(
|
|
stripe_payment_id,
|
|
)
|
|
|
|
#print(" ### payement_retrive_status = ", payement_retrive_status, )
|
|
|
|
if( payement_retrive_status is None or payement_retrive_status['status'] is None):
|
|
mycommon.myprint(
|
|
str(inspect.stack()[0][3]) + " le Payement "+str(stripe_payment_id)+" n'est pas validé")
|
|
return False, " le Payement "+str(stripe_payment_id)+" n'est pas validé"
|
|
|
|
if( payement_retrive_status['status'] and str(payement_retrive_status['status'] ).strip() == "succeeded" ):
|
|
|
|
#On reactive le pack du partner
|
|
local_coll_name = MYSY_GV.dbname['partnair_account']
|
|
|
|
now = datetime.now()
|
|
ret_val = local_coll_name.find_one_and_update({'token': token, 'active': '1', 'locked': '0', 'pack_service':''},
|
|
{"$set":
|
|
{"pack_service": str(packs).lower(),
|
|
"date_update": str(now)}
|
|
},
|
|
upsert=False,
|
|
return_document=ReturnDocument.AFTER
|
|
)
|
|
|
|
mycommon.myprint(
|
|
str(inspect.stack()[0][3]) + " le Payement "+str(stripe_payment_id)+" est validé")
|
|
return True, " le Payement "+str(stripe_payment_id)+" est validé"
|
|
|
|
mycommon.myprint(
|
|
str(inspect.stack()[0][3]) + " Impossible de connaitre le status du payement " + str(stripe_payment_id) + " ")
|
|
return False, " Impossible de connaitre le status du payement " + str(stripe_payment_id) + " "
|
|
|
|
|
|
except Exception as e:
|
|
exc_type, exc_obj, exc_tb = sys.exc_info()
|
|
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
|
|
return False, False
|
|
|
|
|
|
"""
|
|
Cette fonction schedul un payeement
|
|
"""
|
|
def Schedule_Stripe_Payement(diction):
|
|
try:
|
|
|
|
field_list_obligatoire = ['token', ]
|
|
for val in field_list_obligatoire:
|
|
if val not in diction:
|
|
mycommon.myprint(
|
|
str(inspect.stack()[0][3]) + " - La valeur '" + val + "' n'est pas presente dans liste ")
|
|
return False, " - La valeur '" + val + "' n'est pas presente dans liste "
|
|
|
|
|
|
mytoken = ""
|
|
if ("token" in diction.keys()):
|
|
if (str(diction['token'])):
|
|
mytoken = str(diction['token'])
|
|
|
|
# recuperation de la susbscription du client
|
|
local_ret_val = MYSY_GV.dbname['partnair_account'].find_one({'token':mytoken,'active':'1', 'locked':'0'})
|
|
|
|
if( local_ret_val['stripe_subscription_id'] is None ):
|
|
mycommon.myprint(
|
|
str(inspect.stack()[0][3]) + " Impossible de trouver la suscritpion, planification annulée ")
|
|
return False, " Impossible de trouver la suscritpion, planification annulée "
|
|
|
|
schedul = stripe.SubscriptionSchedule.create(
|
|
from_subscription=str(local_ret_val['stripe_subscription_id']),
|
|
)
|
|
|
|
print(" ### Schedule id = ", schedul['id'])
|
|
|
|
"""
|
|
Mise à jour du partenaire avec la valeur du suscription id
|
|
"""
|
|
local_coll_name = MYSY_GV.dbname['partnair_account']
|
|
|
|
now = datetime.now()
|
|
ret_val = local_coll_name.find_one_and_update({'token':mytoken, 'active': '1', 'locked': '0'},
|
|
{"$set":
|
|
{"stripe_subscription_schedule_id": str(schedul['id']),
|
|
"date_update": str(now)}
|
|
},
|
|
upsert=False,
|
|
return_document=ReturnDocument.AFTER
|
|
)
|
|
|
|
if (ret_val is None or ret_val['_id'] is None):
|
|
mycommon.myprint(
|
|
str(inspect.stack()[0][3]) + " - planification des payement : impossible de mettre à jour le client")
|
|
return False, False, "Planification des payement : impossible de mettre à jour le client"
|
|
|
|
return True, " La planification des payement a bien été activée"
|
|
|
|
|
|
except Exception as e:
|
|
exc_type, exc_obj, exc_tb = sys.exc_info()
|
|
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
|
|
return False, " Impossible d'activer la plafinification recurrente du payement",
|
|
|
|
|
|
def create_subscription(diction):
|
|
try:
|
|
"""
|
|
Controle des champs autorisés
|
|
"""
|
|
field_list = ['customerid', 'pack', 'qty', 'discount_code', 'discount_type','discount_valeur']
|
|
incom_keys = diction.keys()
|
|
for val in incom_keys:
|
|
if val not in field_list and val.startswith('my_') is False:
|
|
mycommon.myprint(str(
|
|
inspect.stack()[0][3]) + " Le champ '" + val + "' n'existe pas. ")
|
|
return False, " Les informations fournies sont incorrecte",
|
|
|
|
"""
|
|
Controle des champs Obligatoires
|
|
"""
|
|
field_list_obligatoire = ['customerid', 'pack', 'qty']
|
|
|
|
for val in field_list_obligatoire:
|
|
if val not in diction:
|
|
mycommon.myprint(str(inspect.stack()[0][3]) + " - Impossible de créer la souscription La valeur '" + val + "' n'est pas presente dans liste ")
|
|
return False, " Impossible de créer le souscription. Toutes les données obligatoires ne sont pas fournies"
|
|
|
|
# Simulating authenticated user. Lookup the logged in user in your
|
|
# database, and set customer_id to the Stripe Customer ID of that user.
|
|
customer_id = ""
|
|
if ("customerid" in diction.keys()):
|
|
if diction['customerid']:
|
|
customer_id = diction['customerid']
|
|
|
|
pack = ""
|
|
if ("pack" in diction.keys()):
|
|
if diction['pack']:
|
|
pack = diction['pack']
|
|
|
|
discount_code = ""
|
|
if ("discount_code" in diction.keys()):
|
|
if diction['discount_code']:
|
|
discount_code = diction['discount_code']
|
|
|
|
discount_type = ""
|
|
if ("discount_type" in diction.keys()):
|
|
if diction['discount_type']:
|
|
discount_type = diction['discount_type']
|
|
|
|
discount_valeur = ""
|
|
if ("discount_valeur" in diction.keys()):
|
|
if diction['discount_valeur']:
|
|
discount_valeur = diction['discount_valeur']
|
|
|
|
|
|
price_id = ""
|
|
if( str(pack).lower() == "gold" ):
|
|
price_id = MYSY_GV.STRIPE_GOLD_PRICE_ID
|
|
# On ecrase la valeur celle du discount si il existe une discount
|
|
if( str(discount_valeur) == "50" and str(discount_type) == "percent"):
|
|
price_id = MYSY_GV.STRIPE_GOLD_PRICE_ID_50_OFF
|
|
elif (str(discount_valeur) == "95" and str(discount_type) == "percent"):
|
|
price_id = MYSY_GV.STRIPE_GOLD_PRICE_ID_95_OFF
|
|
|
|
|
|
|
|
elif( str(pack).lower() == "standard"):
|
|
price_id = MYSY_GV.STRIPE_STANDARD_PRICE_ID
|
|
# On ecrase la valeur celle du discount si il existe une discount
|
|
if (str(discount_valeur) == "50" and str(discount_type) == "percent"):
|
|
price_id = MYSY_GV.STRIPE_STANDARD_PRICE_ID_50_OFF
|
|
elif (str(discount_valeur) == "95" and str(discount_type) == "percent"):
|
|
price_id = MYSY_GV.STRIPE_STANDARD_PRICE_ID_95_OFF
|
|
|
|
|
|
elif (str(pack).lower() == "test"):
|
|
price_id = MYSY_GV.STRIPE_TEST_PRICE_ID
|
|
|
|
qty = ""
|
|
if ("qty" in diction.keys()):
|
|
if diction['qty']:
|
|
qty = diction['qty']
|
|
|
|
local_status, new_int = mycommon.IsInt(qty)
|
|
if ( local_status is False ):
|
|
mycommon.myprint(str(inspect.stack()[0][
|
|
3]) + " - Impossible de realiser le souscription. La quantité n'est pas correcte")
|
|
return False, " - Impossible de realiser le souscription. La quantité n'est pas correcte"
|
|
|
|
# Extract the price ID from environment variables given the name
|
|
# of the price passed from the front end.
|
|
#
|
|
|
|
print(" ### price_id = ", price_id)
|
|
|
|
# Create the subscription. Note we're using
|
|
# expand here so that the API will return the Subscription's related
|
|
# latest invoice, and that latest invoice's payment_intent
|
|
# so we can collect payment information and confirm the payment on the front end.
|
|
|
|
# Create the subscription
|
|
subscription = stripe.Subscription.create(
|
|
customer=customer_id,
|
|
items=[{
|
|
'price': price_id,
|
|
'quantity': qty,
|
|
}],
|
|
payment_behavior='default_incomplete',
|
|
expand=['latest_invoice.payment_intent'],
|
|
)
|
|
|
|
print(" ### subscription ID =", subscription['id'])
|
|
print(" ### customer_id = ", customer_id)
|
|
##print(" ### payment_intent = id = " + str(subscription.latest_invoice.payment_intent.id))
|
|
|
|
"""
|
|
Mise à jour du partenaire avec la valeur du suscription id
|
|
"""
|
|
local_coll_name = MYSY_GV.dbname['partnair_account']
|
|
|
|
now = datetime.now()
|
|
ret_val = local_coll_name.find_one_and_update({'stripe_account_id':customer_id, 'active':'1', 'locked':'0'},
|
|
{"$set":
|
|
{"stripe_subscription_id":str(subscription['id']),
|
|
"stripe_subscription_created_timestemp": str(subscription['created']),
|
|
"date_update": str(now)}
|
|
},
|
|
upsert=False,
|
|
return_document=ReturnDocument.AFTER
|
|
)
|
|
|
|
if ('_id' not in ret_val.keys()):
|
|
mycommon.myprint(
|
|
str(inspect.stack()[0][3]) + " - Creation payement : impossible de mettre à jour le client")
|
|
return False, False, "Creation payement : impossible de mettre à jour le client"
|
|
|
|
|
|
"""
|
|
/!\ Une fois l'abonnement créer, il faut l'enregistrer dans la collection 'abonnement'
|
|
"""
|
|
# Recuperation du recid du client dans mysy
|
|
local_partner_data = MYSY_GV.dbname['partnair_account'].find_one({'stripe_account_id':customer_id, 'active':'1', 'locked':'0'})
|
|
|
|
if( 'recid' not in local_partner_data):
|
|
mycommon.myprint(
|
|
str(inspect.stack()[0][3]) + " - Creation payement : impossible de récupérer les données client (3)")
|
|
return False, False, "Creation payement : impossible de récupérer les données client (3) "
|
|
|
|
|
|
abonnement_data = {}
|
|
|
|
abonnement_data['partner_recid'] = local_partner_data['recid']
|
|
|
|
#print(" ### ret_val apres souscription id = ", str(ret_val))
|
|
#print(" ### ret_val apres subscription = ", str(subscription))
|
|
|
|
if ('_id' in ret_val.keys()):
|
|
abonnement_data['stripe_subscription_id'] = str(ret_val['stripe_subscription_id'])
|
|
|
|
if ('billing_cycle_anchor' in ret_val.keys()):
|
|
abonnement_data['billing_cycle_anchor'] = subscription['billing_cycle_anchor']
|
|
|
|
if ('created' in ret_val.keys()):
|
|
abonnement_data['created'] = subscription['created']
|
|
|
|
if ('current_period_end' in ret_val.keys()):
|
|
abonnement_data['current_period_end'] = subscription['current_period_end']
|
|
|
|
if ('customer' in ret_val.keys()):
|
|
abonnement_data['stripe_customer_id'] = subscription['customer']
|
|
|
|
if ('latest_invoice' in ret_val.keys()):
|
|
abonnement_data['latest_invoice'] = subscription['latest_invoice']
|
|
|
|
if ('status' in ret_val.keys()):
|
|
abonnement_data['status'] = subscription['status']
|
|
|
|
now = datetime.now()
|
|
abonnement_data['date_update'] = str(now)
|
|
|
|
ret_val_abonnement = MYSY_GV.dbname['abonnement'].find_one_and_update(
|
|
{'stripe_subscription_id': str(ret_val['_id']), },
|
|
{"$set":
|
|
abonnement_data
|
|
},
|
|
upsert=True,
|
|
return_document=ReturnDocument.AFTER
|
|
)
|
|
|
|
if ('_id' not in ret_val_abonnement.keys()):
|
|
mycommon.myprint(
|
|
str(inspect.stack()[0][3]) + " - Creation payement : impossible de finaliser la creation de l'abonnement")
|
|
return False, False, "Creation payement : impossible de finaliser la creation de l'abonnement"
|
|
|
|
return True, subscription.latest_invoice.payment_intent.id, subscription.latest_invoice.payment_intent.client_secret
|
|
|
|
|
|
except Exception as e:
|
|
exc_type, exc_obj, exc_tb = sys.exc_info()
|
|
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
|
|
return False, False, False,
|
|
|
|
|
|
@app.route('/cancel-subscription', methods=['POST'])
|
|
def cancel_subscription():
|
|
data = json.loads(request.data)
|
|
try:
|
|
# Cancel the subscription by deleting it
|
|
deletedSubscription = stripe.Subscription.delete(data['subscriptionId'])
|
|
return jsonify(subscription=deletedSubscription)
|
|
except Exception as e:
|
|
return jsonify(error=str(e)), 403
|
|
|
|
|
|
@app.route('/subscriptions', methods=['GET'])
|
|
def list_subscriptions():
|
|
# Simulating authenticated user. Lookup the logged in user in your
|
|
# database, and set customer_id to the Stripe Customer ID of that user.
|
|
customer_id = request.cookies.get('customer')
|
|
|
|
try:
|
|
# Cancel the subscription by deleting it
|
|
subscriptions = stripe.Subscription.list(
|
|
customer=customer_id,
|
|
status='all',
|
|
expand=['data.default_payment_method']
|
|
)
|
|
return jsonify(subscriptions=subscriptions)
|
|
except Exception as e:
|
|
return jsonify(error=str(e)), 403
|
|
|
|
|
|
@app.route('/invoice-preview', methods=['GET'])
|
|
def preview_invoice():
|
|
# Simulating authenticated user. Lookup the logged in user in your
|
|
# database, and set customer_id to the Stripe Customer ID of that user.
|
|
customer_id = request.cookies.get('customer')
|
|
|
|
subscription_id = request.args.get('subscriptionId')
|
|
new_price_lookup_key = request.args.get('newPriceLookupKey')
|
|
|
|
try:
|
|
# Retrieve the subscription
|
|
subscription = stripe.Subscription.retrieve(subscription_id)
|
|
|
|
# Retrive the Invoice
|
|
invoice = stripe.Invoice.upcoming(
|
|
customer=customer_id,
|
|
subscription=subscription_id,
|
|
subscription_items=[{
|
|
'id': subscription['items']['data'][0].id,
|
|
'price': os.getenv(new_price_lookup_key),
|
|
}],
|
|
)
|
|
return jsonify(invoice=invoice)
|
|
except Exception as e:
|
|
return jsonify(error=str(e)), 403
|
|
|
|
|
|
@app.route('/update-subscription', methods=['POST'])
|
|
def update_subscription():
|
|
data = json.loads(request.data)
|
|
try:
|
|
subscription = stripe.Subscription.retrieve(data['subscriptionId'])
|
|
|
|
update_subscription = stripe.Subscription.modify(
|
|
data['subscriptionId'],
|
|
items=[{
|
|
'id': subscription['items']['data'][0].id,
|
|
'price': os.getenv(data['newPriceLookupKey'].upper()),
|
|
}]
|
|
)
|
|
return jsonify(update_subscription)
|
|
except Exception as e:
|
|
return jsonify(error=str(e)), 403
|
|
|
|
|
|
"""
|
|
Cette fonction arrete la prelevement d'un payement à la fin du mois en cours
|
|
"""
|
|
def stop_strip_subscription(diction):
|
|
try:
|
|
|
|
field_list_obligatoire = ['token',]
|
|
for val in field_list_obligatoire:
|
|
if val not in diction:
|
|
mycommon.myprint(
|
|
str(inspect.stack()[0][3]) + " - La valeur '" + val + "' n'est pas presente dans liste , toutes le données obligatoire ne sont pas fournies ")
|
|
return False, " Impossible de supprimer le moyen de payement, toutes le données obligatoire ne sont pas fournies"
|
|
|
|
mytoken = ""
|
|
if ("token" in diction.keys()):
|
|
if diction['token']:
|
|
mytoken = diction['token']
|
|
|
|
retval = mycommon.check_partner_token_validity("", str(mytoken))
|
|
|
|
if retval is False:
|
|
mycommon.myprint(str(inspect.stack()[0][3]) + " - La session de connexion n'est pas valide")
|
|
return False, "Les informations d'identification ne sont pas valident"
|
|
|
|
# Recuperation du recid du partenaire
|
|
partner_recid = mycommon.get_parnter_recid_from_token(str(mytoken))
|
|
if partner_recid is False:
|
|
mycommon.myprint(str(inspect.stack()[0][3]) + " - Impossible de récupérer le recid du partenaire")
|
|
return False, " Les informations d'identification sont incorrectes"
|
|
|
|
# recuperation de la susbscription du client
|
|
local_ret_val = MYSY_GV.dbname['partnair_account'].find_one(
|
|
{'token': mytoken, 'active': '1', 'locked': '0'})
|
|
|
|
if (local_ret_val['stripe_subscription_id'] is None):
|
|
mycommon.myprint(
|
|
str(inspect.stack()[0][3]) + " Impossible d'annuler le payement ")
|
|
return False, " Impossible d'annuler le payement "
|
|
|
|
|
|
|
|
#a = stripe.SubscriptionSchedule.release( str(local_ret_val['stripe_subscription_id']), )
|
|
a = stripe.Subscription.modify(
|
|
str(local_ret_val['stripe_subscription_id']),
|
|
cancel_at_period_end=True
|
|
)
|
|
|
|
|
|
arret_abonnement = datetime.today().date() + relativedelta(months=+1)
|
|
arrete_abonnement_formated = arret_abonnement.strftime("%d/%m/%Y")
|
|
|
|
#mise à jour du partenaire
|
|
local_coll_name = MYSY_GV.dbname['partnair_account']
|
|
|
|
now = datetime.now()
|
|
ret_val = local_coll_name.find_one_and_update({'token': mytoken, 'active': '1', 'locked': '0'},
|
|
{"$set":
|
|
{"end_date_abonnement": str(arrete_abonnement_formated),
|
|
"date_update": str(now)}
|
|
},
|
|
upsert=False,
|
|
return_document=ReturnDocument.AFTER
|
|
)
|
|
|
|
if (ret_val is None or ret_val['_id'] is None):
|
|
mycommon.myprint(
|
|
str(inspect.stack()[0][3]) + " - Arret abonnement : impossible de mettre à jour le client")
|
|
return False, False, "Arret abonnement : impossible de mettre à jour le client"
|
|
|
|
partners_email = local_ret_val['email']
|
|
partners_nom = local_ret_val['nom']
|
|
partners_pack_service = local_ret_val['pack_service']
|
|
partners_date_arret = arrete_abonnement_formated
|
|
|
|
local_ret_val = email_mgt.EmailStopAbonnement( partners_email, partners_pack_service, partners_date_arret, partners_nom)
|
|
|
|
if( local_ret_val is False):
|
|
mycommon.myprint(
|
|
str(inspect.stack()[0][3]) + " - WARNING : Arret abonnement, Impossible d'envoyer le mail de notification au partenaire")
|
|
|
|
return True, " Votre abonnement va s'arreter le "+str(arrete_abonnement_formated)
|
|
|
|
|
|
except Exception as e:
|
|
exc_type, exc_obj, exc_tb = sys.exc_info()
|
|
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
|
|
return False, "Impossible d'annuler votre abonnement"
|
|
|
|
|
|
"""
|
|
Cette fonction permet de modifier la quantité d'un abonnement
|
|
par exemple lorqu'un partenaire change de nombre de formation sur le meme pack
|
|
"""
|
|
|
|
def strip_update_subscription_qty(diction):
|
|
try:
|
|
"""
|
|
Controle des champs autorisés
|
|
"""
|
|
field_list = ['token','qty', 'old_qty','discount_code', 'discount_type','discount_valeur']
|
|
incom_keys = diction.keys()
|
|
for val in incom_keys:
|
|
if val not in field_list and val.startswith('my_') is False:
|
|
mycommon.myprint(str(
|
|
inspect.stack()[0][3]) + " Le champ '" + val + "' n'existe pas. ")
|
|
return False, " Les informations fournies sont incorrecte",
|
|
|
|
print(" ### strip_update_subscription_qty : diction = ", diction)
|
|
"""
|
|
Controle des champs Obligatoires
|
|
"""
|
|
|
|
field_list_obligatoire = ['token','qty', 'old_qty']
|
|
for val in field_list_obligatoire:
|
|
if val not in diction:
|
|
mycommon.myprint(
|
|
str(inspect.stack()[0][3]) + " - La valeur '" + val + "' n'est pas presente dans liste , toutes le données obligatoire ne sont pas fournies ")
|
|
return False, " Impossible de supprimer le moyen de payement, toutes le données obligatoire ne sont pas fournies"
|
|
|
|
mytoken = ""
|
|
if ("token" in diction.keys()):
|
|
if diction['token']:
|
|
mytoken = diction['token']
|
|
|
|
qty = ""
|
|
if ("qty" in diction.keys()):
|
|
if diction['qty']:
|
|
qty = diction['qty']
|
|
|
|
old_qty = ""
|
|
if ("old_qty" in diction.keys()):
|
|
if diction['old_qty']:
|
|
old_qty = diction['old_qty']
|
|
|
|
retval = mycommon.check_partner_token_validity("", str(mytoken))
|
|
|
|
if retval is False:
|
|
mycommon.myprint(str(inspect.stack()[0][3]) + " - La session de connexion n'est pas valide")
|
|
return False, "Les informations d'identification ne sont pas valident"
|
|
|
|
# Recuperation du recid du partenaire
|
|
partner_recid = mycommon.get_parnter_recid_from_token(str(mytoken))
|
|
if partner_recid is False:
|
|
mycommon.myprint(str(inspect.stack()[0][3]) + " - Impossible de récupérer le recid du partenaire")
|
|
return False, " Les informations d'identification sont incorrectes"
|
|
|
|
# recuperation de la susbscription du client
|
|
local_ret_val = MYSY_GV.dbname['partnair_account'].find_one(
|
|
{'token': mytoken, 'active': '1', 'locked': '0'})
|
|
|
|
if (local_ret_val['stripe_subscription_id'] is None):
|
|
mycommon.myprint(
|
|
str(inspect.stack()[0][3]) + " Impossible d'annuler le payement ")
|
|
return False, " Impossible de changer la quantité de l'abonnement "
|
|
|
|
print(" ### local_ret_val = ", local_ret_val)
|
|
pack = ""
|
|
if ("pack_service" in local_ret_val.keys()):
|
|
if local_ret_val['pack_service']:
|
|
pack = local_ret_val['pack_service']
|
|
|
|
print(" ### pack = ", pack)
|
|
discount_code = ""
|
|
if ("discount_code" in diction.keys()):
|
|
if diction['discount_code']:
|
|
discount_code = diction['discount_code']
|
|
|
|
discount_type = ""
|
|
if ("discount_type" in diction.keys()):
|
|
if diction['discount_type']:
|
|
discount_type = diction['discount_type']
|
|
|
|
discount_valeur = ""
|
|
if ("discount_valeur" in diction.keys()):
|
|
if diction['discount_valeur']:
|
|
discount_valeur = diction['discount_valeur']
|
|
|
|
price_id = ""
|
|
if (str(pack).lower() == "gold"):
|
|
price_id = MYSY_GV.STRIPE_GOLD_PRICE_ID
|
|
# On ecrase la valeur celle du discount si il existe une discount
|
|
if (str(discount_valeur) == "50" and str(discount_type) == "percent"):
|
|
price_id = MYSY_GV.STRIPE_GOLD_PRICE_ID_50_OFF
|
|
elif (str(discount_valeur) == "95" and str(discount_type) == "percent"):
|
|
price_id = MYSY_GV.STRIPE_GOLD_PRICE_ID_95_OFF
|
|
|
|
|
|
|
|
elif (str(pack).lower() == "standard" ):
|
|
price_id = MYSY_GV.STRIPE_STANDARD_PRICE_ID
|
|
# On ecrase la valeur celle du discount si il existe une discount
|
|
if (str(discount_valeur) == "50" and str(discount_type) == "percent"):
|
|
price_id = MYSY_GV.STRIPE_STANDARD_PRICE_ID_50_OFF
|
|
elif (str(discount_valeur) == "95" and str(discount_type) == "percent"):
|
|
price_id = MYSY_GV.STRIPE_STANDARD_PRICE_ID_95_OFF
|
|
|
|
|
|
elif (str(pack).lower() == "test"):
|
|
price_id = MYSY_GV.STRIPE_TEST_PRICE_ID
|
|
|
|
|
|
print(" #### str(local_ret_val['stripe_subscription_id']) = ", str(local_ret_val['stripe_subscription_id']))
|
|
|
|
print(" ### price_id = ", price_id)
|
|
|
|
current_subscription = stripe.Subscription.retrieve(str(local_ret_val['stripe_subscription_id']))
|
|
|
|
#a = stripe.SubscriptionSchedule.release( str(local_ret_val['stripe_subscription_id']), )
|
|
if( discount_code ):
|
|
a = stripe.Subscription.modify(
|
|
str(local_ret_val['stripe_subscription_id']),
|
|
proration_behavior='create_prorations',
|
|
items=[{
|
|
'id': current_subscription['items'].data[0].id,
|
|
'price': price_id,
|
|
'quantity': qty,
|
|
}]
|
|
)
|
|
|
|
else:
|
|
a = stripe.Subscription.modify(
|
|
str(local_ret_val['stripe_subscription_id']),
|
|
proration_behavior='create_prorations',
|
|
items=[{
|
|
'id': current_subscription['items'].data[0].id,
|
|
'price': price_id,
|
|
'quantity': qty,
|
|
}]
|
|
)
|
|
|
|
|
|
#print(" ### aa = ", a)
|
|
arret_abonnement = datetime.today().date() + relativedelta(months=+1)
|
|
arrete_abonnement_formated = arret_abonnement.strftime("%d/%m/%Y")
|
|
|
|
now = datetime.now()
|
|
|
|
|
|
|
|
partners_email = local_ret_val['email']
|
|
partners_nom = local_ret_val['nom']
|
|
partners_pack_service = local_ret_val['pack_service']
|
|
partners_date_arret = arrete_abonnement_formated
|
|
|
|
local_ret_val = email_mgt.EmailChangeAbonnementQty( partners_email, partners_pack_service, partners_date_arret, partners_nom, old_qty, qty)
|
|
|
|
if( local_ret_val is False):
|
|
mycommon.myprint(
|
|
str(inspect.stack()[0][3]) + " - WARNING : changement qté abonnement, Impossible d'envoyer le mail de notification au partenaire")
|
|
|
|
return True, " ok"
|
|
|
|
|
|
except Exception as e:
|
|
exc_type, exc_obj, exc_tb = sys.exc_info()
|
|
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
|
|
return False, " Impossible de changer la quantité de l'abonnement "
|
|
|
|
|
|
"""
|
|
Cette fonction permet de changer l'abonnement d'un partenaire.
|
|
Par exemple cas d'un "standard" qui passe "Gold" ou vice-versa.
|
|
|
|
IMPORTANT :
|
|
Le changement de plan d'abonnement entraine la desactivation et depublucation
|
|
des formations dans MySy et dans le LMS.
|
|
|
|
Par la suite, le client pourra reactivier et republier ses formations selon
|
|
les nouvelles conditions de son abonnement.
|
|
|
|
"""
|
|
def strip_update_subscription_plan(diction):
|
|
try:
|
|
|
|
"""
|
|
Controle des champs autorisés
|
|
"""
|
|
field_list = ['token','pack', 'qty', 'discount_code', 'discount_type','discount_valeur']
|
|
incom_keys = diction.keys()
|
|
for val in incom_keys:
|
|
if val not in field_list and val.startswith('my_') is False:
|
|
mycommon.myprint(str(
|
|
inspect.stack()[0][3]) + " Le champ '" + val + "' n'existe pas. ")
|
|
return False, " Les informations fournies sont incorrecte",
|
|
|
|
print(" ### strip_update_subscription_plan : diction = ", diction)
|
|
"""
|
|
Controle des champs Obligatoires
|
|
"""
|
|
|
|
field_list_obligatoire = ['token','pack', 'qty']
|
|
for val in field_list_obligatoire:
|
|
if val not in diction:
|
|
mycommon.myprint(
|
|
str(inspect.stack()[0][3]) + " - La valeur '" + val + "' n'est pas presente dans liste , toutes le données obligatoire ne sont pas fournies ")
|
|
return False, " Toutes le données obligatoire ne sont pas fournies"
|
|
|
|
mytoken = ""
|
|
if ("token" in diction.keys()):
|
|
if diction['token']:
|
|
mytoken = diction['token']
|
|
|
|
pack = ""
|
|
if ("pack" in diction.keys()):
|
|
if diction['pack']:
|
|
pack = diction['pack']
|
|
|
|
qty = ""
|
|
if ("qty" in diction.keys()):
|
|
if diction['qty']:
|
|
qty = diction['qty']
|
|
|
|
|
|
retval = mycommon.check_partner_token_validity("", str(mytoken))
|
|
|
|
if retval is False:
|
|
mycommon.myprint(str(inspect.stack()[0][3]) + " - La session de connexion n'est pas valide")
|
|
return False, "Les informations d'identification ne sont pas valident"
|
|
|
|
# Recuperation du recid du partenaire
|
|
partner_recid = mycommon.get_parnter_recid_from_token(str(mytoken))
|
|
if partner_recid is False:
|
|
mycommon.myprint(str(inspect.stack()[0][3]) + " - Impossible de récupérer le recid du partenaire")
|
|
return False, " Les informations d'identification sont incorrectes"
|
|
|
|
# recuperation de la susbscription du client
|
|
local_ret_val = MYSY_GV.dbname['partnair_account'].find_one(
|
|
{'token': mytoken, 'active': '1', 'locked': '0'})
|
|
|
|
if (local_ret_val['stripe_subscription_id'] is None):
|
|
mycommon.myprint(
|
|
str(inspect.stack()[0][3]) + " Impossible d'annuler le payement ")
|
|
return False, " Impossible de changer l'abonnement "
|
|
|
|
|
|
lms_user_id = ""
|
|
if ("mysy_lms_user_id" in local_ret_val.keys()):
|
|
if local_ret_val['mysy_lms_user_id']:
|
|
lms_user_id = local_ret_val['mysy_lms_user_id']
|
|
"""
|
|
qty = ""
|
|
if ("nb_formation" in local_ret_val.keys()):
|
|
if local_ret_val['nb_formation']:
|
|
qty = local_ret_val['nb_formation']
|
|
"""
|
|
|
|
discount_code = ""
|
|
if ("discount_code" in diction.keys()):
|
|
if diction['discount_code']:
|
|
discount_code = diction['discount_code']
|
|
|
|
discount_type = ""
|
|
if ("discount_type" in diction.keys()):
|
|
if diction['discount_type']:
|
|
discount_type = diction['discount_type']
|
|
|
|
discount_valeur = ""
|
|
if ("discount_valeur" in diction.keys()):
|
|
if diction['discount_valeur']:
|
|
discount_valeur = diction['discount_valeur']
|
|
|
|
price_id = ""
|
|
if (str(pack).lower() == "gold"):
|
|
price_id = MYSY_GV.STRIPE_GOLD_PRICE_ID
|
|
# On ecrase la valeur celle du discount si il existe une discount
|
|
if (str(discount_valeur) == "50" and str(discount_type) == "percent"):
|
|
price_id = MYSY_GV.STRIPE_GOLD_PRICE_ID_50_OFF
|
|
elif (str(discount_valeur) == "95" and str(discount_type) == "percent"):
|
|
price_id = MYSY_GV.STRIPE_GOLD_PRICE_ID_95_OFF
|
|
|
|
|
|
elif (str(pack).lower() == "standard"):
|
|
price_id = MYSY_GV.STRIPE_STANDARD_PRICE_ID
|
|
# On ecrase la valeur celle du discount si il existe une discount
|
|
if (str(discount_valeur) == "50" and str(discount_type) == "percent"):
|
|
price_id = MYSY_GV.STRIPE_STANDARD_PRICE_ID_50_OFF
|
|
elif (str(discount_valeur) == "95" and str(discount_type) == "percent"):
|
|
price_id = MYSY_GV.STRIPE_STANDARD_PRICE_ID_95_OFF
|
|
|
|
|
|
elif (str(pack).lower() == "test"):
|
|
price_id = MYSY_GV.STRIPE_TEST_PRICE_ID
|
|
|
|
|
|
print(" ### pack = ", pack, " ## price_id = ", price_id, " ### qty = ", qty)
|
|
print(" #### str(local_ret_val['stripe_subscription_id']) = ", str(local_ret_val['stripe_subscription_id']))
|
|
|
|
current_subscription = stripe.Subscription.retrieve(str(local_ret_val['stripe_subscription_id']))
|
|
|
|
#a = stripe.SubscriptionSchedule.release( str(local_ret_val['stripe_subscription_id']), )
|
|
a = stripe.Subscription.modify(
|
|
str(local_ret_val['stripe_subscription_id']),
|
|
cancel_at_period_end=False,
|
|
proration_behavior='create_prorations',
|
|
items=[{
|
|
'id': current_subscription['items'].data[0].id,
|
|
'price': price_id,
|
|
'quantity': qty,
|
|
|
|
}]
|
|
)
|
|
|
|
#print(" ### aa = ", a)
|
|
arret_abonnement = datetime.today().date() + relativedelta(months=+1)
|
|
arrete_abonnement_formated = arret_abonnement.strftime("%d/%m/%Y")
|
|
|
|
now = datetime.now()
|
|
|
|
|
|
partners_email = local_ret_val['email']
|
|
partners_nom = local_ret_val['nom']
|
|
partners_pack_service = local_ret_val['pack_service']
|
|
|
|
local_ret_val = email_mgt.EmailChangeAbonnementPlan( partners_email, pack, partners_nom, qty, )
|
|
|
|
if( local_ret_val is False):
|
|
mycommon.myprint(
|
|
str(inspect.stack()[0][3]) + " - WARNING : changement qté abonnement, Impossible d'envoyer le mail de notification au partenaire")
|
|
|
|
|
|
"""
|
|
Important :
|
|
Le changement de plan d'abonnement entraine la desactivation et depublucation
|
|
des formations dans MySy et dans le LMS.
|
|
|
|
Par la suite, le client pourra reactivier et republier ses formations selon
|
|
les nouvelles conditions de son abonnement.
|
|
"""
|
|
|
|
# 1 - Depublication des formations dans MySy
|
|
#print(" ### str(local_ret_val['recid']) = ", str(partner_recid))
|
|
local_result = MYSY_GV.dbname['myclass'].update_many({'partner_owner_recid':str(partner_recid)}, {"$set":{'published':'0'}})
|
|
#print(" #### "+str(local_result.matched_count)+" Formations ont été depubliées dans MySy ")
|
|
|
|
# 2 - Desactivation des formations dans le LMS
|
|
new_diction = {}
|
|
new_diction['lms_user_id'] = lms_user_id
|
|
print(" #### new_diction = ", new_diction)
|
|
local_status, local_message = mysy_lms.Disable_MySy_LMS_Class_Of_User(new_diction)
|
|
print(" ### local_status = "+str(local_status)+" mysy_lms.Disable_MySy_LMS_Class_Of_User = "+str(local_message))
|
|
return True, " ok"
|
|
|
|
except Exception as e:
|
|
exc_type, exc_obj, exc_tb = sys.exc_info()
|
|
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
|
|
return False, " Impossible de changer l'abonnement "
|
|
|
|
|
|
|
|
|
|
@app.route('/webhook', methods=['POST'])
|
|
def webhook_received():
|
|
# You can use webhooks to receive information about asynchronous payment events.
|
|
# For more about our webhook events check out https://stripe.com/docs/webhooks.
|
|
webhook_secret = os.getenv('STRIPE_WEBHOOK_SECRET')
|
|
request_data = json.loads(request.data)
|
|
|
|
if webhook_secret:
|
|
# Retrieve the event by verifying the signature using the raw body and secret if webhook signing is configured.
|
|
signature = request.headers.get('stripe-signature')
|
|
try:
|
|
event = stripe.Webhook.construct_event(
|
|
payload=request.data, sig_header=signature, secret=webhook_secret)
|
|
data = event['data']
|
|
except Exception as e:
|
|
return e
|
|
event_type = event['type']
|
|
else:
|
|
data = request_data['data']
|
|
event_type = request_data['type']
|
|
|
|
data_object = data['object']
|
|
|
|
if event_type == 'invoice.payment_succeeded':
|
|
if data_object['billing_reason'] == 'subscription_create':
|
|
# The subscription automatically activates after successful payment
|
|
# Set the payment method used to pay the first invoice
|
|
# as the default payment method for that subscription
|
|
subscription_id = data_object['subscription']
|
|
payment_intent_id = data_object['payment_intent']
|
|
|
|
# Retrieve the payment intent used to pay the subscription
|
|
payment_intent = stripe.PaymentIntent.retrieve(payment_intent_id)
|
|
|
|
# Set the default payment method
|
|
stripe.Subscription.modify(
|
|
subscription_id,
|
|
default_payment_method=payment_intent.payment_method
|
|
)
|
|
|
|
print("Default payment method set for subscription:" + payment_intent.payment_method)
|
|
elif event_type == 'invoice.payment_failed':
|
|
# If the payment fails or the customer does not have a valid payment method,
|
|
# an invoice.payment_failed event is sent, the subscription becomes past_due.
|
|
# Use this webhook to notify your user that their payment has
|
|
# failed and to retrieve new card details.
|
|
# print(data)
|
|
print('Invoice payment failed: %s', event.id)
|
|
|
|
elif event_type == 'invoice.finalized':
|
|
# If you want to manually send out invoices to your customers
|
|
# or store them locally to reference to avoid hitting Stripe rate limits.
|
|
# print(data)
|
|
print('Invoice finalized: %s', event.id)
|
|
|
|
elif event_type == 'customer.subscription.deleted':
|
|
# handle subscription cancelled automatically based
|
|
# upon your subscription settings. Or if the user cancels it.
|
|
# print(data)
|
|
print('Subscription canceled: %s', event.id)
|
|
|
|
return jsonify({'status': 'success'})
|
|
|
|
|
|
|
|
"""
|
|
Cette fonction récupérer les informations sur l'abonnement
|
|
d'un client. Par exemple,
|
|
- date de prochaine facturation
|
|
- montant de prochaine facture
|
|
"""
|
|
def Strip_Get_Customer_Abonnement_Data(diction):
|
|
try:
|
|
|
|
field_list_obligatoire = ['recid']
|
|
|
|
for val in field_list_obligatoire:
|
|
if val not in diction:
|
|
mycommon.myprint(
|
|
str(inspect.stack()[0][
|
|
3]) + " La valeur '" + val + "' n'est pas presente dans liste ")
|
|
return False, " Les informations fournies sont incorrectes"
|
|
|
|
recid = ""
|
|
if ("recid" in diction.keys()):
|
|
if diction['recid']:
|
|
recid = diction['recid']
|
|
|
|
|
|
# Recuperation du recid du partenaire
|
|
local_status, partner_data = mycommon.get_partner_data_from_recid(str(recid))
|
|
if local_status is False:
|
|
mycommon.myprint(str(inspect.stack()[0][3]) + " - Impossible de récupérer les données du partenaire")
|
|
return False, " Impossible de récupérer les données du partenaire"
|
|
|
|
if ("stripe_account_id" not in partner_data.keys()):
|
|
mycommon.myprint(str(inspect.stack()[0][3]) + " - Impossible de récupérer les données du partenaire (2)")
|
|
return False, " Impossible de récupérer les données du partenaire (2)"
|
|
|
|
|
|
stripe_account_id = partner_data["stripe_account_id"]
|
|
local_ret_val = stripe.Invoice.upcoming(
|
|
customer=stripe_account_id,
|
|
)
|
|
|
|
#print(" #### local_ret_val : ", str(local_ret_val))
|
|
|
|
|
|
lines_to_invoice = local_ret_val.lines.list()
|
|
|
|
stripe_account_id_JSON = json.loads(str(local_ret_val))
|
|
|
|
lines_to_invoice_JSON = json.loads(str(lines_to_invoice))
|
|
|
|
return_data = {}
|
|
return_data['recid'] = str(recid)
|
|
period_start = ""
|
|
period_end = ""
|
|
total = ""
|
|
|
|
if( "period_start" in stripe_account_id_JSON.keys()):
|
|
# convert the timestamp to a datetime object in the local timezone
|
|
dt_object = datetime.fromtimestamp(stripe_account_id_JSON["period_start"]).strftime("%d/%m/%Y")
|
|
return_data['period_start'] = str(dt_object)[0:10]
|
|
period_start = str(dt_object)[0:10]
|
|
|
|
if ("period_end" in stripe_account_id_JSON.keys()):
|
|
# convert the timestamp to a datetime object in the local timezone
|
|
dt_object = datetime.fromtimestamp(stripe_account_id_JSON["period_end"]).strftime("%d/%m/%Y")
|
|
return_data['period_end'] = str(dt_object)[0:10]
|
|
period_end = str(dt_object)[0:10]
|
|
|
|
if ("total" in stripe_account_id_JSON.keys()):
|
|
total_local = mycommon.tryFloat(str(stripe_account_id_JSON["total"])) / 100
|
|
return_data['total'] = str(total_local)
|
|
total = str(total_local)
|
|
|
|
return_data['main_description'] = "Facture à venir : Ceci est un aperçu de la facture qui sera émise "+str(period_end)+"." \
|
|
" Elle est susceptible d'être modifiée si l'abonnement est mis à jour."
|
|
|
|
return_data['lines'] = []
|
|
|
|
|
|
for val in lines_to_invoice_JSON['data']:
|
|
|
|
local_diction = {}
|
|
|
|
local_diction['id'] = str(val['id'])
|
|
|
|
period = val['period']
|
|
|
|
local_diction['period_end'] = str(datetime.fromtimestamp(period['end']).strftime("%d/%m/%Y-%H:%M:%S"))
|
|
local_diction['period_start'] = str(datetime.fromtimestamp(period['start']).strftime("%d/%m/%Y-%H:%M:%S"))
|
|
|
|
local_diction['period_end_month'] = str(datetime.fromtimestamp(period['end']).strftime("%m"))
|
|
|
|
|
|
local_diction['unit_amount'] = mycommon.tryFloat(str(val['price']['unit_amount'])) / 100
|
|
|
|
local_diction['quantity'] = str(val['quantity'])
|
|
|
|
local_diction['description'] = str(val['description']).replace("Unused time on", "Temps non utilisé sur").replace("Remaining time on", "Temps restant sur").replace("after", "apres")
|
|
|
|
local_diction['amount'] = mycommon.tryFloat(str(val['amount'])) / 100
|
|
return_data['lines'].append(local_diction)
|
|
|
|
|
|
|
|
|
|
print(" ## return_data = ", return_data)
|
|
|
|
RetObject = []
|
|
RetObject.append(mycommon.JSONEncoder().encode(return_data))
|
|
return True, RetObject
|
|
|
|
except Exception as e:
|
|
exc_type, exc_obj, exc_tb = sys.exc_info()
|
|
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
|
|
return False, " Impossible de récupérer les données de l'abonnement "
|
|
|
|
|
|
|
|
"""
|
|
Cette fonction est un job qui va aller chercher tous les client/partner
|
|
pour lesquels il faut envoyer les elements de facturation
|
|
"send_pre_invoice_data" : '1',
|
|
"datetime_pre_invoice_created" < date_time_now + 5 min.
|
|
|
|
"""
|
|
def Cron_Strip_Get_Customer_Abonnement_Data():
|
|
try:
|
|
|
|
query = {}
|
|
query['send_pre_invoice_data'] = '1'
|
|
query['datetime_pre_invoice_created'] = { '$lte' : str( datetime.now() - timedelta(minutes=3) )}
|
|
#{}: {"$lte" :1355414400} #datetime.datetime.now() - datetime.timedelta(minutes=5)
|
|
query['locked'] = '0'
|
|
query['active'] = '1'
|
|
|
|
|
|
|
|
#print(" ### query = ", query)
|
|
|
|
cpt = 0
|
|
cpt_erreur = 0
|
|
cpt_ok = 0
|
|
|
|
for val in MYSY_GV.dbname['partnair_account'].find(query):
|
|
cpt = cpt + 1
|
|
data = {}
|
|
data['recid'] = val['recid']
|
|
local_status, local_retval = email_mgt.Strip_Get_Customer_Upcoming_Invoice(data)
|
|
if( local_status is False):
|
|
cpt_erreur = cpt_erreur +1
|
|
mycommon.myprint(
|
|
str(inspect.stack()[0][3]) + " - WARNING : impossible d'envoyer les elements de prefacturation pour le recid : "+str(val['recid']))
|
|
else:
|
|
cpt_ok = cpt_ok + 1
|
|
# Les elements ont bien ete envoyé, alors on fait la mise à jour du partenaire en mettant : "send_pre_invoice_data" : '2', (2 veut dire que c'est fait)
|
|
ret_val_local = MYSY_GV.dbname['partnair_account'].find_one_and_update(
|
|
{"recid": str(val['recid']), 'active': '1', 'locked': '0'},
|
|
{"$set": {'send_pre_invoice_data': '2', 'datetime_pre_invoice_created': str(datetime.now())}},
|
|
upsert=False,
|
|
return_document=ReturnDocument.AFTER
|
|
)
|
|
|
|
output_message = time.strftime("%A, %d. %B %Y %I:%M:%S %p")+" : Envoie des données de prefacturation : - "+str(cpt)+ " clients ==> A traiter. - "+str(cpt_ok)+ " clients==> traiter OKK. - "+str(cpt_erreur)+ " clients ==> traiter ERREUR. "
|
|
mycommon.myprint(str(output_message))
|
|
return True, str(output_message)
|
|
|
|
except Exception as e:
|
|
exc_type, exc_obj, exc_tb = sys.exc_info()
|
|
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
|
|
return False, time.strftime("%A, %d. %B %Y %I:%M:%S %p")+" Impossible d'executer le job : Cron_Strip_Get_Customer_Abonnement_Data "
|
|
|
|
|
|
|
|
"""
|
|
Cette fonction verifie si un client a deja une facture stripe.
|
|
si c'est le cas, ca veut qu'on est en mode update avec ce client
|
|
si non il faut créer la première facture
|
|
"""
|
|
def Stripe_Customer_Has_Invoice(stripe_customer_id):
|
|
try:
|
|
|
|
retval = stripe.Invoice.search(query="customer:'"+str(stripe_customer_id)+"'")
|
|
|
|
stripe_list_invoice_JSON = json.loads(str(retval))
|
|
|
|
for val in stripe_list_invoice_JSON["data"] :
|
|
if( "id" in val.keys() ):
|
|
return True
|
|
|
|
return False
|
|
|
|
except Exception as e:
|
|
exc_type, exc_obj, exc_tb = sys.exc_info()
|
|
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
|
|
return False
|
|
|
|
|
|
|
|
"""
|
|
fonction de test stripe
|
|
"""
|
|
def test_stripe():
|
|
try:
|
|
|
|
retval = stripe.Invoice.search(query="customer:'cus_OEsPgUkuj2UIES'")
|
|
#print(" #### retval = ", str(retval))
|
|
|
|
stripe_list_invoice_JSON = json.loads(str(retval))
|
|
|
|
|
|
for val in stripe_list_invoice_JSON["data"] :
|
|
print(" #### stripe_list_invoice_JSON_data = ", str(val))
|
|
if( "id" in val.keys() ):
|
|
print(" ### l'id de la facture est ", str(val['id']))
|
|
|
|
return "OK"
|
|
|
|
except Exception as e:
|
|
exc_type, exc_obj, exc_tb = sys.exc_info()
|
|
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
|
|
return False
|
|
|