Advertisement
kopyl

Untitled

Mar 18th, 2023
1,406
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.99 KB | None | 0 0
  1. from idied.repository import db
  2. import os
  3. import datetime
  4. from idied.auth.auth_required import auth_required_redirect_to_main
  5. import hmac
  6. import hashlib
  7. from flask_cors import cross_origin
  8. from flask_restx import Namespace, Resource, fields
  9.  
  10. from bson.objectid import ObjectId
  11.  
  12. import time
  13. import requests
  14.  
  15. from flask import render_template, make_response, redirect, request
  16.  
  17.  
  18. # http://localhost | https://idied.org
  19. BASE_URL = os.getenv("BASE_URL")
  20.  
  21. # http://localhost:5001/ | https://idied.org/api/
  22. API_URL = os.getenv("API_URL")
  23.  
  24.  
  25. secret = "..."
  26.  
  27.  
  28. def get_date_of_payment(days=30):
  29.     date = datetime.datetime.now()
  30.     delta = datetime.timedelta(days=days)
  31.     time_in_30_days = date + delta
  32.     return time_in_30_days.strftime("%d.%m.%Y")
  33.  
  34.  
  35. def get_payload(order_id):
  36.  
  37.     date_of_next_payment = get_date_of_payment()
  38.     date_of_end_payment = get_date_of_payment(1000000)  # id.doc.id#2
  39.  
  40.     return {
  41.         "merchantAccount": "idied_org",
  42.         "merchantDomainName": BASE_URL,
  43.         "merchantTransactionSecureType": "AUTO",  # should be hardcoded
  44.         "orderReference": order_id,  # unique ID of a purchase
  45.         "orderDate": str(int(time.time())),
  46.         "amount": "1.99",
  47.         "currency": "USD",
  48.         "productName": ["Monthly Subscription"],
  49.         "productPrice": ["1.00"],
  50.         "productCount": ["1"],
  51.         "regularMode": "monthly",
  52.         "regularOn": "1",
  53.         "returnUrl": f"{API_URL}payment/return",
  54.         "serviceUrl": f"{API_URL}payment/callback",
  55.         "clientPhone": "+380507308141",
  56.         "dateNext": date_of_next_payment,
  57.         "dateEnd": date_of_end_payment,  # id.doc.id#2
  58.     }
  59.  
  60.  
  61. def generate_auth_signature(payload):
  62.     res = (
  63.         ";".join([
  64.             payload["merchantAccount"],
  65.             payload["merchantDomainName"],
  66.             payload["orderReference"],
  67.             payload["orderDate"],
  68.             payload["amount"],
  69.             payload["currency"],
  70.             payload["productName"][0],
  71.             payload["productCount"][0],
  72.             payload["productPrice"][0],
  73.         ])
  74.     )
  75.  
  76.     _bytes = bytes(res, encoding='utf-8')
  77.     _secret = bytes(secret, encoding='utf-8')
  78.  
  79.     md5 = hmac.new(_secret, _bytes, hashlib.md5)
  80.  
  81.     return md5.hexdigest()
  82.  
  83.  
  84. api = Namespace('/payment',
  85.                 description='A list of routes related to the users',
  86.                 decorators=[cross_origin()])
  87.  
  88.  
  89. def check_payment():
  90.  
  91.     orderReference = request.form["orderReference"]
  92.  
  93.     payload = {
  94.         "transactionType": "CHECK_STATUS",
  95.         "merchantAccount": "idied_org",
  96.         "orderReference": orderReference,
  97.         "merchantSignature": "",
  98.         "apiVersion": "2"
  99.     }
  100.  
  101.     signature = f"idied_org;{orderReference}"
  102.     _bytes = bytes(signature, encoding='utf-8')
  103.     _secret = bytes(secret, encoding='utf-8')
  104.     md5 = hmac.new(_secret, _bytes, hashlib.md5)
  105.  
  106.     payload["merchantSignature"] = md5.hexdigest()
  107.  
  108.     response = requests.post('https://api.wayforpay.com/api', json=payload)
  109.  
  110.     return response.json()
  111.  
  112.  
  113. def update_payment_in_payments_db(payment):
  114.  
  115.     current_time = int(time.time())
  116.  
  117.     db.payments_collection.update_one(
  118.         {"_id": ObjectId(payment["orderReference"])},
  119.         {
  120.             "$set": {
  121.                 "status": "paid",
  122.                 "paid_at": current_time
  123.             }
  124.         }
  125.     )
  126.  
  127.  
  128. def update_payment_in_users_db(payment):
  129.     db_payment = db.payments_collection.find_one(
  130.         {"_id": ObjectId(payment["orderReference"])}
  131.     )
  132.     user_id = db_payment.get("user_id")
  133.  
  134.     current_time = int(time.time())
  135.  
  136.     paid_until = (
  137.         db.users_collection.find_one(
  138.             {"user_id": user_id},
  139.             {"paid_until": 1, "_id": 0}
  140.         )
  141.         .get("paid_until", current_time)
  142.     )
  143.  
  144.     # just_paid_until = paid_until + 2592000  # 1 month
  145.     # 100 years. Fake value until we have a payment system
  146.     just_paid_until = paid_until + 3153600000
  147.  
  148.     db.users_collection.update_one(
  149.         {"user_id": user_id},
  150.         {
  151.             "$set": {"paid_until": just_paid_until}
  152.         },
  153.     )
  154.  
  155.  
  156. def inform_admin_about_payment_in_telegram():
  157.     message = "Successful payment! 🔥"
  158.     try:
  159.         requests.post(
  160.             f"https://idied.org/api/tg-report",
  161.             json={
  162.                 "message": message
  163.             }
  164.         )
  165.     except Exception as e:
  166.         print(e)
  167.  
  168.  
  169. def construct_pre_payment(user_id) -> dict:
  170.     current_time = int(time.time())
  171.     payment = {
  172.         "user_id": user_id,
  173.         "status": "requested",
  174.         "paid_at": -1,
  175.         "created_at": current_time
  176.     }
  177.     return payment
  178.  
  179.  
  180. @api.route('')
  181. class UserOnline(Resource):
  182.  
  183.     @auth_required_redirect_to_main
  184.     def get(self, user_info):
  185.  
  186.         user_id = user_info.get("user_id")
  187.  
  188.         payment = construct_pre_payment(user_id)
  189.  
  190.         order = db.payments_collection.insert_one(payment)
  191.         order_id = str(order.inserted_id)
  192.  
  193.         payload = get_payload(order_id)
  194.         signature = generate_auth_signature(payload)
  195.         payload["merchantSignature"] = signature
  196.  
  197.         payload["clientAccountId"] = user_id
  198.         payload["clientEmail"] = user_info.get("email")
  199.  
  200.         url = "https://secure.wayforpay.com/pay?behavior=offline"
  201.         response = requests.post(url, data=payload)
  202.  
  203.         payment_url = response.json().get("url")
  204.  
  205.         print(payment_url)
  206.  
  207.         return redirect(payment_url)
  208.  
  209.  
  210. @api.route('/return')
  211. class UserOnline(Resource):
  212.  
  213.     def post(self):
  214.  
  215.         payment = check_payment()
  216.         status = payment.get("transactionStatus")
  217.  
  218.         if status != "Approved":
  219.             return redirect(f"{BASE_URL}/notes?paid=false")
  220.  
  221.         update_payment_in_payments_db(payment)
  222.         update_payment_in_users_db(payment)
  223.         inform_admin_about_payment_in_telegram()
  224.  
  225.         return redirect(f"{BASE_URL}/notes?paid=true")
  226.  
  227.  
  228. @api.route('/callback')
  229. class UserOnline(Resource):
  230.  
  231.     def post(self):
  232.         return {}
  233.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement