diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index 70ac690..0000000
--- a/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-*.log
-/build/
\ No newline at end of file
diff --git a/.idea/.gitignore b/.idea/.gitignore
deleted file mode 100644
index 13566b8..0000000
--- a/.idea/.gitignore
+++ /dev/null
@@ -1,8 +0,0 @@
-# Default ignored files
-/shelf/
-/workspace.xml
-# Editor-based HTTP Client requests
-/httpRequests/
-# Datasource local storage ignored files
-/dataSources/
-/dataSources.local.xml
diff --git a/.idea/deployment.xml b/.idea/deployment.xml
deleted file mode 100644
index 4f73c50..0000000
--- a/.idea/deployment.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
deleted file mode 100644
index 03d9549..0000000
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
deleted file mode 100644
index 105ce2d..0000000
--- a/.idea/inspectionProfiles/profiles_settings.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
deleted file mode 100644
index a6218fe..0000000
--- a/.idea/misc.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/payment.iml b/.idea/payment.iml
deleted file mode 100644
index f617e98..0000000
--- a/.idea/payment.iml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
deleted file mode 100644
index a171b33..0000000
--- a/.idea/vcs.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/payment_backend/.gitignore b/payment_backend/.gitignore
deleted file mode 100644
index a3627a0..0000000
--- a/payment_backend/.gitignore
+++ /dev/null
@@ -1,32 +0,0 @@
-/data/
-
-# Python:
-*.ipynb
-*/__pycache__
-/.vagrant
-/scrapy.iml
-*.pyc
-_trial_temp*
-dropin.cache
-docs/build
-*egg-info
-.tox
-venv
-build
-dist
-.idea
-htmlcov/
-.coverage
-.pytest_cache/
-.coverage.*
-.cache/
-.mypy_cache/
-/tests/keys/localhost.crt
-/tests/keys/localhost.key
-key.txt
-key.txt.pub
-
-# Windows
-Thumbs.db
-ehthumbs.db
-Desktop.ini
diff --git a/payment_backend/README.md b/payment_backend/README.md
deleted file mode 100644
index f919462..0000000
--- a/payment_backend/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# payment
-
-支付系统
\ No newline at end of file
diff --git a/payment_backend/__init__.py b/payment_backend/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/payment_backend/api/__init__.py b/payment_backend/api/__init__.py
deleted file mode 100644
index 9e281b9..0000000
--- a/payment_backend/api/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from tronscan import Tronscan
diff --git a/payment_backend/api/tronscan.py b/payment_backend/api/tronscan.py
deleted file mode 100644
index 36395dc..0000000
--- a/payment_backend/api/tronscan.py
+++ /dev/null
@@ -1,411 +0,0 @@
-import requests
-
-from custom_decorators import singleton
-from utils.tronscan import convert_to_tronscan_timestamp
-
-trc20token_info = {
- "usdt": {"tokenId": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
- "tokenAbbr": "USDT",
- "tokenName": "Tether USD",
- "tokenLogo": "https://static.tronscan.org/production/logo/usdtlogo.png",
- "issuerAddr": "THPvaUhoh2Qn2y9THCZML3H815hhFhn5YC",
- "vip": True}
-}
-
-@singleton
-class Tronscan:
- def __init__(self, api_key):
- self.api_key = api_key
-
- def accountv2(self, address):
- """
- Get account detail information
- :param address: Account address
- :return: Returns the detail information of an account.
- """
- response = requests.get(f"https://apilist.tronscanapi.com/api/accountv2?address={address}",
- headers={'TRON-PRO-API-KEY': self.api_key})
- return response.json()
-
- def transactions(self, start=0, limit=10, start_timestamp=None, end_timestamp=None,
- from_address=None, to_address=None, tokens=None, block=None,
- type_=None, method=None):
- """
- Get a list of transactions.
- :param start: Start number. Default 0
- :param limit: Number of items per page. Default 10
- :param start_timestamp: Start time
- :param end_timestamp: End time
- :param from_address: Sender's address.
- :param to_address: Recipient's address.
- :param tokens: Tokens involved
- :param block: Block
- :param type_: Transaction type
- :param method: Method called in a smart contract signature. Only one value can be specified each time.
- :return: Getx a list of transactions.
- """
- params = {
- "sort": "-timestamp",
- "count": "true",
- "start": start,
- "limit": limit,
- }
-
- if start_timestamp is not None:
- params["start_timestamp"] = convert_to_tronscan_timestamp(start_timestamp)
- if end_timestamp is not None:
- params["end_timestamp"] = convert_to_tronscan_timestamp(end_timestamp)
- if from_address is not None:
- params["fromAddress"] = from_address
- if to_address is not None:
- params["toAddress"] = to_address
- if tokens is not None:
- params["tokens"] = tokens
- if block is not None:
- params["block"] = block
- if type_ is not None:
- params["type"] = type_
- if method is not None:
- params["method"] = method
-
- response = requests.get(
- "https://apilist.tronscanapi.com/api/transaction",
- headers={'TRON-PRO-API-KEY': self.api_key},
- params=params
- )
- return response.json()
-
- def transaction_info(self, hash_):
- """
- Get transaction detail information by transaction hash.
- :param hash_: Transaction hash
- :return: Get transaction information.
- """
- params = {
- "hash": hash_,
- }
- response = requests.get(
- "https://apilist.tronscanapi.com/api/transaction-info",
- headers={'TRON-PRO-API-KEY': self.api_key},
- params=params
- )
- return response.json()
-
- def token_trc20_transfers(self, start=None, limit=None, contract_address=None,
- start_timestamp=None, end_timestamp=None, confirm=True,
- related_address=None, from_address=None, to_address=None):
- """
- Get the transfer list of TRC20 and TRC721 tokens.
- :param start: Start number. Default 0
- :param limit: Number of items per page. Default 10
- :param contract_address: Contract address
- :param start_timestamp: Start time
- :param end_timestamp: End time
- :param confirm: Whether to return confirmed transfers only. Default: True
- :param related_address: Account address
- :param from_address: Sender's address
- :param to_address: Recipient's address
- :return: Get the transfer list of TRC20 and TRC721 tokens.
- """
- params = {
- "filterTokenValue": 1
- }
- if start is not None:
- params["start"] = start
- if limit is not None:
- params["limit"] = limit
- if contract_address is not None:
- params["contract_address"] = contract_address
- if start_timestamp is not None:
- params["start_timestamp"] = convert_to_tronscan_timestamp(start_timestamp)
- if end_timestamp is not None:
- params["end_timestamp"] = convert_to_tronscan_timestamp(end_timestamp)
- if confirm is not None:
- params["confirm"] = str(confirm).lower()
- if related_address is not None:
- params["relatedAddress"] = related_address
- if from_address is not None:
- params["fromAddress"] = from_address
- if to_address is not None:
- params["toAddress"] = to_address
-
- response = requests.get(
- "https://apilist.tronscanapi.com/api/token_trc20/transfers",
- headers={'TRON-PRO-API-KEY': self.api_key},
- params=params
- )
- return response.json()
-
- def transfer(self, sort="-timestamp", start=0, limit=10, count="true",
- address=None, from_address=None, to_address=None, tokens=None, block=None):
- """
- Get account's transfer list.
- :param sort: Sort type
- :param start: Start index, default is 0
- :param limit: Number of transfers per page
- :param count: Whether to return total transfer number.
- :param address: Address, like contract address
- :param from_address: Sender's address
- :param to_address: Recipient's address
- :param tokens: Specific tokens
- :param block: Block number
- :return: Get account's transfer list.
- """
- params = {
- "sort": sort,
- "start": start,
- "limit": limit,
- "count": count,
- "filterTokenValue": 1
- }
-
- if address is not None:
- params["address"] = address
- if from_address is not None:
- params["fromAddress"] = from_address
- if to_address is not None:
- params["toAddress"] = to_address
- if tokens is not None:
- params["tokens"] = tokens
- if block is not None:
- params["block"] = block
-
- response = requests.get(
- "https://apilist.tronscanapi.com/api/transfer",
- headers={'TRON-PRO-API-KEY': self.api_key},
- params=params
- )
- return response.json()
-
- def internal_transactions(self, start=0, limit=10, address=None, contract=None, block=None):
- """
- Get internal transaction list for a specific address or block.
- :param start: Start index, default is 0
- :param limit: Number of transfers per page
- :param address: Specific address. At least one of address, block, or contract must be specified
- :param contract: Sender's address
- :param block: Block number
- :return: Get the internal transaction list.
- """
- params = {
- "start": start,
- "limit": limit
- }
-
- if address is not None:
- params["address"] = address
- if contract is not None:
- params["contract"] = contract
- if block is not None:
- params["block"] = block
-
- response = requests.get(
- "https://apilist.tronscanapi.com/api/internal-transaction",
- headers={'TRON-PRO-API-KEY': self.api_key},
- params=params
- )
- return response.json()
-
- def token_trc20_transfers_with_status(self, start=0, limit=10, trc20Id=None, address=None,
- direction=0, db_version=0, reverse="false"):
- """
- Get account's transaction data.
- :param start: Start index, default is 0
- :param limit: Number of transfers per page
- :param trc20Id: TRC20 token address
- :param address: Account address
- :param direction: 0 for all, 1 for transfer-out, 2 for transfer-in
- :param db_version: Whether to include approval transfers. 1 for include, 0 for exclude
- :param reverse: Sort by creation time. Valid values: "true" or "false"
- :return: Get account's transaction data.
- """
- params = {
- "start": start,
- "limit": limit,
- "direction": direction,
- "db_version": db_version,
- "reverse": reverse
- }
-
- if trc20Id is not None:
- params["trc20Id"] = trc20Id
- if address is not None:
- params["address"] = address
-
- response = requests.get(
- "https://apilist.tronscanapi.com/api/token_trc20/transfers-with-status",
- headers={'TRON-PRO-API-KEY': self.api_key},
- params=params
- )
- return response.json()
-
- def search(self, term, type="token", start=0, limit=10):
- """
- Search token/contract/account information
- Note : The maximum value for limit is 50.
- :param term: Search term
- :param type: Search type, including "token", "address", "contract", "transaction" and "block"
- :param start: Start number. Default: 0
- :param limit: Number of items per page. Default: 10
- :return: Returns account authorization change records.
- """
- params = {
- "term": term,
- "type": type,
- "start": start,
- "limit": limit,
- }
- response = requests.get("https://apilist.tronscanapi.com/api/search/v2",
- headers={'TRON-PRO-API-KEY': self.api_key},
- params=params)
- return response.json()
-
- def approve_change(self, contract_address, from_address, to_address, start=0, limit=20, show=3):
- """
- Returns account authorization change records.
- :param contract_address: Contract address
- :param from_address: Originator address
- :param to_address: Recipient address
- :param start: Start number. Default: 0
- :param limit: Number of items per page. Default: 20
- :param show: Token type. 1: TRC20 2: TRC721 3: ALL(default) 4: TRC1155
- :return:
- """
- params = {
- "contract_address": contract_address,
- "from_address": from_address,
- "to_address": to_address,
- "start": start,
- "limit": limit,
- "show": show,
- "type": "approve",
- }
- response = requests.get("https://apilist.tronscanapi.com/api/account/approve/change",
- headers={'TRON-PRO-API-KEY': self.api_key},
- params=params)
- return response.json()
-
- def transfer_trx(self, address, start_timestamp=None, end_timestamp=None, start=0, limit=20, direction=1,
- db_version=0,
- reverse=True, fee=False):
- """
- Get the list of trx transfers related to a specific address
- Note : The value sum of start and limit must be less than or equal to 10000.
- :param address: Query address
- :param start_timestamp: Start timestamp
- :param end_timestamp: End timestamp
- :param start: Start number. Default: 0
- :param limit: Number of items per page. Default: 20
- :param direction: Default: 1. 1 represents inbound transfers, 2 represents outbound transfers, and 0 represents both.
- :param db_version: Default: 0, which indicates to filter transfers with invalid “to” or “from” addresses out.
- :param reverse: Sort the data in a descending order. Default: true
- :param fee: Whether to return data of TRX burning for resource consumption. Default: false
- :return: Returns the list of TRX transfers for a specific address.
- """
- params = {
- "address": address,
- "start": start,
- "limit": limit,
- "direction": direction,
- "db_version": db_version,
- "reverse": reverse,
- "fee": fee,
- }
- if start_timestamp is not None:
- params["start_timestamp"] = convert_to_tronscan_timestamp(start_timestamp)
- if end_timestamp is not None:
- params["end_timestamp"] = convert_to_tronscan_timestamp(end_timestamp)
- response = requests.get("https://apilist.tronscanapi.com/api/transfer/trx",
- headers={'TRON-PRO-API-KEY': self.api_key},
- params=params)
- return response.json()
-
- def transfer_token10(self, address, trc10Id, start_timestamp=None, end_timestamp=None, start=0, limit=20,
- direction=1, db_version=0, reverse=True):
- """
- Get the transfer list of a specific TRC10 token for a certain address
- Note : The value sum of start and limit must be less than or equal to 10000.
- :param address: Query address
- :param trc10Id: TRC10 token ID
- :param start_timestamp: Start timestamp
- :param end_timestamp: End timestamp
- :param start: Start number. Default: 0
- :param limit: Number of items per page. Default: 20
- :param direction: Default: 1. 1 represents inbound transfers, 2 represents outbound transfers, and 0 represents both.
- :param db_version: Default: 0, which indicates to filter transfers with invalid “to” or “from” addresses out.
- :param reverse: Sort the data in a descending order. Default: true
- :return: Returns the transfer list of a TRC10 token for a specific account.
- """
- params = {
- "address": address,
- "trc10Id": trc10Id,
- "start": start,
- "limit": limit,
- "direction": direction,
- "db_version": db_version,
- "reverse": reverse,
- }
- if start_timestamp is not None:
- params["start_timestamp"] = convert_to_tronscan_timestamp(start_timestamp)
- if end_timestamp is not None:
- params["end_timestamp"] = convert_to_tronscan_timestamp(end_timestamp)
- response = requests.get("https://apilist.tronscanapi.com/api/transfer/token10",
- headers={'TRON-PRO-API-KEY': self.api_key},
- params=params)
- return response.json()
-
- def transfer_trc20(self, address, trc20Id, start_timestamp=None, end_timestamp=None, start=0, limit=20,
- direction=1, db_version=0, reverse=True):
- """
- Get the transfer list of a specific TRC20 token for a certain address
- Note : The value sum of start and limit must be less than or equal to 10000.
- :param address: Query address
- :param trc20Id: TRC20 token ID
- :param start_timestamp: Start timestamp
- :param end_timestamp: End timestamp
- :param start: Start number. Default: 0
- :param limit: Number of items per page. Default: 20
- :param direction: Default: 1. 1 represents inbound transfers, 2 represents outbound transfers, and 0 represents both.
- :param db_version: Default: 0, which indicates to filter transfers with invalid “to” or “from” addresses out.
- :param reverse: Sort the data in a descending order. Default: true
- :return: Returns the transfer list of a TRC20 token for a specific account.
- """
- params = {
- "address": address,
- "trc20Id": trc20Id,
- "start": start,
- "limit": limit,
- "direction": direction,
- "db_version": db_version,
- "reverse": reverse,
- }
- if start_timestamp is not None:
- params["start_timestamp"] = convert_to_tronscan_timestamp(start_timestamp)
- if end_timestamp is not None:
- params["end_timestamp"] = convert_to_tronscan_timestamp(end_timestamp)
- response = requests.get("https://apilist.tronscanapi.com/api/transfer/trc20",
- headers={'TRON-PRO-API-KEY': self.api_key},
- params=params)
- return response.json()
-
- def account_wallet(self, address, asset_type=0):
- """
- Get the information of tokens held and followed in the account's web wallet
- :param address: Query address
- :param asset_type: Asset types: 0 - All (default); 1 - Assets (TRX, TRC10, TRC20); 2 - Collectibles (TRC721 and TRC1155)
- :return: Returns a list of tokens held and followed by an account.
- """
- params = {
- "address": address,
- "asset_type": asset_type,
- }
- response = requests.get("https://apilist.tronscanapi.com/api/account/wallet",
- headers={'TRON-PRO-API-KEY': self.api_key},
- params=params)
- return response.json()
-
-
-if __name__ == '__main__':
- address = "TB592A5QwHvvcJoCmvALmzT3S9Pux91Gub"
- tronscan = Tronscan(api_key='cc87d361-7cd6-4f69-a57b-f0a77a213355')
- print(tronscan.transfer_trc20(address, trc20token_info["usdt"]["tokenId"]))
diff --git a/payment_backend/app.py b/payment_backend/app.py
deleted file mode 100644
index 48aa46c..0000000
--- a/payment_backend/app.py
+++ /dev/null
@@ -1,42 +0,0 @@
-from flask import Flask, request, jsonify
-
-from config import get_config
-from services.order import OrderService
-
-config = get_config()
-
-app = Flask(__name__)
-order_service = OrderService() # 获取单例实例
-
-@app.route('/createOrder', methods=['POST'])
-def create_order():
- data = request.get_json()
- phone = data.get('phone', None)
- email = data.get('email', None)
- address = data.get('address', None)
- try:
- payment_method = data['paymentMethod']
- except KeyError:
- return jsonify({
- "message": "Unsupported payment method. Currently, only USDT payments are supported."
- }), 400
-
- addresses = order_service.get_user_addresses(phone, email, address, payment_method)
-
- if not addresses:
- return jsonify({
- "message": "No payment address associated with you was found. Please provide a payment address."
- }), 400
-
- if len(addresses) == 1:
- order_id = order_service.create_order(addresses[0])
- return jsonify({"order_id": order_id}), 200
-
- # 多个地址的情况
- return jsonify({
- "message": "请选择一个地址进行下单。",
- "addresses": addresses
- }), 200
-
-if __name__ == '__main__':
- app.run(debug=True)
diff --git a/payment_backend/config/__init__.py b/payment_backend/config/__init__.py
deleted file mode 100644
index 1f12718..0000000
--- a/payment_backend/config/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from .utils import get_config
diff --git a/payment_backend/config/db.py b/payment_backend/config/db.py
deleted file mode 100644
index 595714f..0000000
--- a/payment_backend/config/db.py
+++ /dev/null
@@ -1,7 +0,0 @@
-config = {
- 'user': 'your_mysql_username',
- 'password': 'your_mysql_password',
- 'host': 'localhost',
- 'database': 'your_database_name',
- 'autocommit': False,
-}
diff --git a/payment_backend/config/param.ini b/payment_backend/config/param.ini
deleted file mode 100644
index 93bc4de..0000000
--- a/payment_backend/config/param.ini
+++ /dev/null
@@ -1,13 +0,0 @@
-[APIKey]
-tronscan=cc87d361-7cd6-4f69-a57b-f0a77a213355
-
-[PaymentAddresses]
-usdt=TB592A5QwHvvcJoCmvALmzT3S9Pux91Gub
-
-[MYSQL]
-user: 'your_mysql_username'
-password: 'your_mysql_password'
-host: 'localhost'
-database: 'your_database_name'
-autocommit: false
-allow_multi_statements: True
\ No newline at end of file
diff --git a/payment_backend/config/utils.py b/payment_backend/config/utils.py
deleted file mode 100644
index 4a6d836..0000000
--- a/payment_backend/config/utils.py
+++ /dev/null
@@ -1,145 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: UTF-8 -*-
-"""
-@Project :payment
-@File :__init__.py.py
-@IDE :PyCharm
-@Author :rengengchen
-@Time :2024/11/06 16:11
-"""
-import argparse
-import os
-import random
-import sys
-from argparse import Namespace
-from configparser import ConfigParser
-
-import requests
-from loguru import logger
-
-random_seed = 20240717
-ROOT_DIR = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
-
-
-def setup_seed(seed):
- # import torch
- # torch.manual_seed(seed)
- # torch.cuda.manual_seed_all(seed)
- # torch.backends.cudnn.deterministic = True
- # import numpy as np
- # np.random.seed(seed)
- random.seed(seed)
-
-
-setup_seed(random_seed)
-
-
-class Setting:
- def __init__(self,
- config_parser: ConfigParser = None,
- argument_parser: Namespace = None,
- _visited=None,
- _parent=None,
- **kwargs):
- self._parent = _parent
- if config_parser:
- for section in config_parser.sections():
- section_config = Setting(_parent=self)
- for option in config_parser.options(section):
- section_config[option] = config_parser.get(section, option)
- self.__dict__[section] = section_config
-
- if argument_parser:
- for k in vars(argument_parser):
- self.__dict__[k] = getattr(argument_parser, k)
-
- if _visited is None:
- _visited = set()
- self.update(_visited=_visited, **kwargs)
-
- def update(self, _visited=None, **kwargs):
- if _visited is None:
- _visited = {}
- for k, v in kwargs.items():
- cls_attr = getattr(self.__class__, k, None)
- if callable(cls_attr):
- raise KeyError(f"The key '{k}' conflicts with an existing class method. you can use {k}_ instead.")
- if isinstance(v, dict):
- obj_id = id(v)
- if obj_id in _visited:
- logger.warning(f"Circular reference detected in key: '{k}'.")
- v = _visited[obj_id]
- else:
- v = Setting(_visited=_visited, _parent=self, **v)
- _visited[obj_id] = v
- self.__dict__[k] = v
-
- def get(self, item, default=None):
- if item not in self.__dict__ and self._parent is not None:
- return self._parent.get(item, default)
- return default
-
- def get_int(self, item):
- return int(self.get(item))
-
- def get_float(self, item):
- return float(self.get(item))
-
- def get_bool(self, item):
- return bool(self.get(item))
-
- def set(self, item, value):
- self.__dict__[item] = value
-
- def __getitem__(self, item):
- return self.__dict__[item]
-
- def __setitem__(self, key, value):
- self.__dict__[key] = value
-
- def __getattr__(self, key):
- return self.get(key)
-
- def __str__(self):
- def _str_helper(config, indent=0, visited=None):
- if visited is None:
- visited = set()
- lines = []
- indent_str = ' ' * indent
- for key, value in config.__dict__.items():
- if key.startswith('_'):
- continue
- if isinstance(value, Setting):
- if id(value) in visited:
- lines.append(f"{indent_str}{key}: ")
- else:
- visited.add(id(value))
- lines.append(f"{indent_str}{key}:")
- lines.append(_str_helper(value, indent + 1, visited))
- else:
- lines.append(f"{indent_str}{key}: {value}")
- return '\n'.join(lines)
-
- return _str_helper(self)
-
-
-def log_config(config):
- # fmt = '%(asctime)s [%(name)s] %(levelname)s: %(message)s'
- # datefmt = "%Y-%m-%d %H:%M:%S"
- logger.remove()
- logger.add(sys.stdout, level=config.log_level)
- logger.add(sys.stderr, level="ERROR")
- logger.add(os.path.join(ROOT_DIR, "logs", "{time}.log"), level="DEBUG", encoding='utf8', rotation="100 MB",
- retention=3)
-
-
-def get_config(config_file=fr'{ROOT_DIR}/config/param.ini') -> Setting:
- requests.adapters.DEFAULT_RETRIES = 3
-
- configparser = ConfigParser()
- configparser.read(config_file)
- parser = argparse.ArgumentParser(description='payment system')
- parser.add_argument("--seed", type=int, default=2024)
- args = parser.parse_args()
- config = Setting(configparser, args)
- return config
diff --git a/payment_backend/custom_decorators.py b/payment_backend/custom_decorators.py
deleted file mode 100644
index 947e4e8..0000000
--- a/payment_backend/custom_decorators.py
+++ /dev/null
@@ -1,17 +0,0 @@
-def singleton(cls):
- """
- Decorator for making a class a singleton.
- This ensures that only one instance of the class exists.
- """
- instances = {} # Dictionary to store the instance of the singleton class
-
- def get_instance(*args, **kwargs):
- """
- If an instance of the class does not exist, create one and store it.
- If it exists, return the existing instance.
- """
- if cls not in instances:
- instances[cls] = cls(*args, **kwargs)
- return instances[cls]
-
- return get_instance
diff --git a/payment_backend/database.py b/payment_backend/database.py
deleted file mode 100644
index b6758c2..0000000
--- a/payment_backend/database.py
+++ /dev/null
@@ -1,66 +0,0 @@
-from loguru import logger
-from mysql.connector import connect, Error, OperationalError
-from mysql.connector import errors as db_errors
-
-from custom_decorators import singleton
-
-
-@singleton
-class Database:
- def __init__(self, config):
- self.connection = None
- self.config = config
- self.connect()
-
- def connect(self):
- """Establish a new database connection."""
- try:
- self.connection = connect(**self.config)
- if self.connection.is_connected():
- logger.info("Connected to MySQL database")
- except Error as e:
- logger.info(f"Error while connecting to MySQL: {e}")
- self.connection = None
-
- def get_connection(self):
- """Get the database connection, with reconnection logic."""
- if self.connection is None or not self.connection.is_connected():
- logger.info("Reconnecting to the database...")
- self.connect()
- return self.connection
-
- def close_connection(self):
- if self.connection and self.connection.is_connected():
- self.connection.close()
- logger.info("MySQL connection is closed")
-
- def execute_query(self, query, params=None):
- """Execute a query with optional parameters, supports transactions."""
- cursor = None
- try:
- connection = self.get_connection()
- cursor = connection.cursor()
- cursor.execute(query, params)
- return cursor
- except OperationalError as e:
- logger.info(f"Operational error: {e}. Attempting to reconnect...")
- self.connect()
- cursor = self.get_connection().cursor()
- cursor.execute(query, params)
- return cursor
- except db_errors.Error as e:
- logger.info(f"Database error: {e}")
- raise
- finally:
- if cursor:
- cursor.close()
-
- def commit(self):
- """Commit the current transaction."""
- if self.connection:
- self.connection.commit()
-
- def rollback(self):
- """Rollback the current transaction."""
- if self.connection:
- self.connection.rollback()
diff --git a/payment_backend/models.py b/payment_backend/models.py
deleted file mode 100644
index 1dd08ea..0000000
--- a/payment_backend/models.py
+++ /dev/null
@@ -1,93 +0,0 @@
-from utils.database import pack_params
-
-
-class User:
- def __init__(self, id_=None, name=None, phone=None, email=None, address=None, payment_method=None):
- self.id = id_
- self.name = name
- self.phone = phone
- self.email = email
- self.address = address
- self.payment_method = payment_method
-
- def insert_sql(self, params_format="list"):
- params_sql, params = pack_params(params_format=params_format, param_sql="{param}", join_str=",",
- name=self.name, phone=self.phone, email=self.email, address=self.address,
- payment_method=self.payment_method)
- return f"INSERT INTO user ({params_sql}) VALUES ({','.join('%s' for _ in params)})", params
-
- def select_sql(self, condition="AND", params_format="list"):
- params_sql, params = pack_params(params_format=params_format, param_sql="{param}=%s", join_str=f" {condition} ",
- name=self.name, phone=self.phone, email=self.email, address=self.address,
- payment_method=self.payment_method)
- return f"SELECT id, name, phone, email, address, payment_method FROM user WHERE {params_sql}", params
-
- def exists_sql(self, condition="AND", params_format="list"):
- params_sql, params = pack_params(params_format=params_format, param_sql="{param}=%s", join_str=f" {condition} ",
- name=self.name, phone=self.phone, email=self.email, address=self.address,
- payment_method=self.payment_method)
- return f"SELECT id FROM user WHERE {params_sql} LIMIT 1", params
-
- def params(self, format="dict"):
- if format == "list":
- params = []
- elif format == "dict":
- params = {}
- else:
- raise ValueError("format must be list or dict")
- if self.uid:
- if format == "list":
- params.append(self.uid)
- elif format == "dict":
- params["uid"] = self.uid
- if self.name:
- if format == "list":
- params.append(self.name)
- elif format == "dict":
- params["name"] = self.name
- if self.phone:
- if format == "list":
- params.append(self.phone)
- elif format == "dict":
- params["phone"] = self.phone
- if self.email:
- if format == "list":
- params.append(self.email)
- elif format == "dict":
- params["email"] = self.email
- if self.address:
- if format == "list":
- params.append(self.address)
- elif format == "dict":
- params["address"] = self.address
- if self.payment_method:
- if format == "list":
- params.append(self.payment_method)
- elif format == "dict":
- params["payment_method"] = self.payment_method
- return params
-
- def get_difference(self, other_user):
- different_attrs = {}
- if self.uid != other_user.uid:
- different_attrs["uid"] = (self.uid, other_user.uid)
- if self.name != other_user.name:
- different_attrs["name"] = (self.name, other_user.name)
- if self.phone != other_user.phone:
- different_attrs["phone"] = (self.phone, other_user.phone)
- if self.email != other_user.email:
- different_attrs["email"] = (self.email, other_user.email)
- if self.address != other_user.address:
- different_attrs["address"] = (self.address, other_user.address)
- if self.payment_method != other_user.payment_method:
- different_attrs["payment_method"] = (self.payment_method, other_user.payment_method)
- return different_attrs
-
- def __eq__(self, other):
- if isinstance(other, User):
- return ((self.name, self.phone, self.email, self.address, self.payment_method)
- == (other.name, other.phone, other.email, other.address, other.payment_method))
- return False
-
- def __hash__(self):
- return hash((self.name, self.phone, self.email, self.address, self.payment_method))
diff --git a/payment_backend/repositories/__init__.py b/payment_backend/repositories/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/payment_backend/repositories/order.py b/payment_backend/repositories/order.py
deleted file mode 100644
index ac92ad8..0000000
--- a/payment_backend/repositories/order.py
+++ /dev/null
@@ -1,41 +0,0 @@
-from ruamel_yaml.util import create_timestamp
-
-from custom_decorators import singleton
-from database import Database
-from utils.datetime import current_timestamp
-
-
-@singleton
-class OrderRepository:
- def __init__(self, config):
- self.db = Database(config['MYSQL'])
-
- def create(self, order_id, from_address, to_address):
- cur_time = current_timestamp()
- try:
- self.db.execute_query(
- "INSERT INTO orders (order_id, from_address, to_address, create_timestamp, update_timestamp) "
- "VALUES (%s, %s, %s, %s, %s)",
- [order_id, from_address, to_address, cur_time, cur_time]
- )
- self.db.commit()
- except Exception:
- self.db.rollback()
- raise
-
- def update_status(self, order_id, status):
- try:
- self.db.execute_query("UPDATE orders "
- "SET status = %s, update_timestamp = %s "
- "WHERE order_id = %s",
- [status, current_timestamp(), order_id])
- self.db.commit()
- except Exception:
- self.db.rollback()
- raise
-
- def get_order_info(self, order_id):
- self.db.execute_query("SELECT quant, from_address, to_address, create_timestamp "
- "FROM orders "
- "WHERE order_id = %s",
- [order_id])
diff --git a/payment_backend/repositories/user.py b/payment_backend/repositories/user.py
deleted file mode 100644
index b580fdc..0000000
--- a/payment_backend/repositories/user.py
+++ /dev/null
@@ -1,74 +0,0 @@
-import itertools
-
-from custom_decorators import singleton
-from database import Database
-from models import User
-
-
-@singleton
-class UserRepository:
- def __init__(self, config):
- self.db = Database(config['MYSQL'])
-
- def get_or_create(self, user):
- users = []
- cursor = self.db.execute_query(*user.select_sql(condition="OR"))
- same_users = cursor.fetchall()
- new_user = not len(same_users)
- # 对用户已存在的属性判断是否有新属性
- update_user = set()
- update_sqls = []
- update_params_list = []
- delete_params = []
- exist_conflicting_attr = False
- for same_user in same_users:
- exist_conflicting_attr = False
- different_attrs = user.get_difference(same_user)
- # 用于判断是否有新属性
- update_sql_params = []
- update_params = []
- for k, v in different_attrs.items():
- new_attr, exist_attr = v
- if exist_attr is None:
- setattr(same_user, k, new_attr)
- update_sql_params.append(f"{k}=%s")
- update_params.append(new_attr)
- else:
- # 出现冲突的属性,考虑新增一行记录
- exist_conflicting_attr = True
- break
-
- if same_user in update_user:
- delete_params.append((same_user.id,))
- else:
- users.append(same_user)
- exist_new_attr = bool(update_params)
- if exist_new_attr:
- update_user.add(same_user)
- update_sqls.append(f'UPDATE user SET {",".join(update_sql_params)} WHERE id=%s;')
- update_params.append(same_user.id)
- update_params_list.append(update_params)
- sql_flag = False
- try:
- if delete_params:
- sql_flag = True
- self.db.get_connection().cursor().executemany("DELETE FROM user WHERE id=%s", delete_params)
- if update_user:
- sql_flag = True
- self.db.get_connection().cursor().execute("".join(update_sqls),
- list(itertools.chain.from_iterable(update_params_list)),
- multi=True)
- if sql_flag:
- self.db.commit()
- except Exception:
- self.db.rollback()
- raise
- if new_user or exist_conflicting_attr:
- try:
- self.db.execute_query(*user.insert_sql())
- self.db.commit()
- except Exception:
- self.db.rollback()
- raise
- users.append(user)
- return users
diff --git a/payment_backend/requirements.txt b/payment_backend/requirements.txt
deleted file mode 100644
index 1e21fb7..0000000
--- a/payment_backend/requirements.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-loguru==0.7.2
-mysql-connector-python==9.1.0
-Requests==2.32.3
diff --git a/payment_backend/services/__init__.py b/payment_backend/services/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/payment_backend/services/order.py b/payment_backend/services/order.py
deleted file mode 100644
index 1272db4..0000000
--- a/payment_backend/services/order.py
+++ /dev/null
@@ -1,58 +0,0 @@
-import uuid
-
-from custom_decorators import singleton
-from models import User
-from repositories.order import OrderRepository
-from repositories.user import UserRepository
-from services.payment import PaymentService
-from utils.datetime import current, current_timestamp, is_time_difference_greater_than
-
-
-@singleton
-class OrderService:
- def __init__(self, config):
- self.config = config
- self.payment_service = PaymentService()
- self.order_repo = OrderRepository(config)
- self.user_repo = UserRepository(config)
-
- def get_user_addresses(self, phone=None, email=None, address=None, payment_method=None):
- if address is None:
- if phone or email:
- users = self.user_repo.get_or_create(User(phone=phone, email=email))
- addresses = set(user.address for user in users if address)
- return list(addresses)
- raise ValueError('A phone number, email, or address is required.')
- return [address]
-
- def create_order(self, address=None):
- date_str = current().strftime('%Y%m%d%H%M%S')
- unique_id = str(uuid.uuid4()).split('-')[0]
- order_id = f"{date_str}-{unique_id}"
-
- self.order_repo.create(order_id, address,
- self.config['PaymentAddresses'])
- return order_id
-
- def finish_order(self, order_id):
- # 判断支付时间是否超过订单存活时间
- quant, from_address, to_address, create_timestamp = self.order_repo.get_order_info(order_id)
- current = current_timestamp()
- status = 0
- if is_time_difference_greater_than(create_timestamp, current, minutes=15):
- # 订单超时
- status = 4
- else:
- correct_quant, confirmed = self.payment_service.check_payment(quant, from_address, to_address, create_timestamp, current)
- if correct_quant and confirmed:
- # 支付成功
- status = 1
- elif correct_quant < 0:
- # 没有转账
- status = 2
- elif confirmed:
- # 金额不对
- status = 3
- if status:
- self.order_repo.update_status(order_id, status)
- return status
diff --git a/payment_backend/services/payment.py b/payment_backend/services/payment.py
deleted file mode 100644
index b602376..0000000
--- a/payment_backend/services/payment.py
+++ /dev/null
@@ -1,23 +0,0 @@
-from api import Tronscan
-from custom_decorators import singleton
-from utils.datetime import current_timestamp
-
-
-@singleton
-class PaymentService:
- def __init__(self, api_key):
- self.tronscan = Tronscan(api_key)
-
- def check_payment(self, quant, from_address, to_address, order_create_timestamp, end_timestamp=None):
- if end_timestamp is None:
- end_timestamp = current_timestamp()
- result = self.tronscan.token_trc20_transfers(limit=100,
- from_address=from_address, to_address=to_address,
- start_timestamp=order_create_timestamp, end_timestamp=end_timestamp)
- if result['rangeTotal'] == 0:
- return -1, 0
- token_transfers = result['token_transfers']
- token_transfer = token_transfers[-1]
- confirmed = token_transfer['confirmed']
- correct_quant = int(quant == (token_transfer['quant'] / 6))
- return correct_quant, confirmed
diff --git a/payment_backend/services/user.py b/payment_backend/services/user.py
deleted file mode 100644
index 7fbae0d..0000000
--- a/payment_backend/services/user.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from custom_decorators import singleton
-
-
-@singleton
-class UserService:
- pass
diff --git a/payment_backend/tests/test_tronscan.py b/payment_backend/tests/test_tronscan.py
deleted file mode 100644
index f558fcd..0000000
--- a/payment_backend/tests/test_tronscan.py
+++ /dev/null
@@ -1,35 +0,0 @@
-import unittest
-from unittest.mock import patch
-
-from api import Tronscan
-
-
-class TestExternalAPICalls(unittest.TestCase):
-
- def setUp(self):
- # Setup code runs before every test method
- self.tronscan = Tronscan(api_key='cc87d361-7cd6-4f69-a57b-f0a77a213355')
-
- @unittest.skip("Skipping this test temporarily")
- @patch('requests.get')
- def test_real_api_call(self, mock_get):
- # Mocking API response
- mock_response = {
- "data": [{"name": "ExampleToken", "symbol": "ETK"}]
- }
- mock_get.return_value.status_code = 200
- mock_get.return_value.json.return_value = mock_response
-
- # Call the method
- response = self.tronscan.search(term="example", type="token")
-
- # Assert the response
- self.assertEqual(response, mock_response)
- mock_get.assert_called_once_with(
- "https://apilist.tronscanapi.com/api/search/v2",
- headers={'TRON-PRO-API-KEY': self.api_key},
- params={"term": "example", "type": "token", "start": 0, "limit": 10}
- )
-
-if __name__ == "__main__":
- unittest.main()
diff --git a/payment_backend/utils/__init__.py b/payment_backend/utils/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/payment_backend/utils/database.py b/payment_backend/utils/database.py
deleted file mode 100644
index f173ff3..0000000
--- a/payment_backend/utils/database.py
+++ /dev/null
@@ -1,16 +0,0 @@
-def pack_params(params_format="list", param_sql="{param}=%s", join_str=" AND ", **kwargs):
- if params_format == "list":
- params = []
- elif params_format == "dict":
- params = {}
- else:
- raise ValueError("Unknown params format")
- param_sqls = []
- for k, v in kwargs.items():
- if v is not None:
- if params_format == "list":
- params.append(v)
- elif params_format == "dict":
- params[k] = v
- param_sqls.append(param_sql.format(param=k))
- return join_str.join(param_sqls), params
diff --git a/payment_backend/utils/datetime.py b/payment_backend/utils/datetime.py
deleted file mode 100644
index 40a2c50..0000000
--- a/payment_backend/utils/datetime.py
+++ /dev/null
@@ -1,35 +0,0 @@
-import datetime
-
-
-def current():
- return datetime.datetime.now()
-
-def current_timestamp():
- datetime.datetime.now().timestamp()
-
-def is_time_difference_greater_than(timestamp1, timestamp2, hours=0, minutes=0, seconds=0):
- """
- 判断两个时间戳的时间差是否大于指定的小时、分钟和秒数
-
- 参数:
- timestamp1 (int): 第一个时间戳
- timestamp2 (int): 第二个时间戳
- hours (int): 要比较的小时数,默认是0小时
- minutes (int): 要比较的分钟数,默认是0分钟
- seconds (int): 要比较的秒数,默认是0秒
-
- 返回:
- bool: 如果时间差大于指定的小时、分钟和秒数返回True,否则返回False
- """
- # 将时间戳转换为 datetime 对象
- time1 = datetime.fromtimestamp(timestamp1)
- time2 = datetime.fromtimestamp(timestamp2)
-
- # 计算时间差
- time_difference = abs(time2 - time1)
-
- # 计算指定的时间差值
- threshold = datetime.timedelta(hours=hours, minutes=minutes, seconds=seconds)
-
- # 判断时间差是否大于指定的时间
- return time_difference > threshold
\ No newline at end of file
diff --git a/payment_backend/utils/tronscan.py b/payment_backend/utils/tronscan.py
deleted file mode 100644
index 65310b4..0000000
--- a/payment_backend/utils/tronscan.py
+++ /dev/null
@@ -1,2 +0,0 @@
-def convert_to_tronscan_timestamp(timestamp):
- return int(timestamp * 1000)
diff --git a/payment_headend/.gitignore b/payment_headend/.gitignore
deleted file mode 100644
index 99d8734..0000000
--- a/payment_headend/.gitignore
+++ /dev/null
@@ -1,30 +0,0 @@
-# Python:
-*.ipynb
-*/__pycache__
-/.vagrant
-/scrapy.iml
-*.pyc
-_trial_temp*
-dropin.cache
-docs/build
-*egg-info
-.tox
-venv
-build
-dist
-.idea
-htmlcov/
-.coverage
-.pytest_cache/
-.coverage.*
-.cache/
-.mypy_cache/
-/tests/keys/localhost.crt
-/tests/keys/localhost.key
-key.txt
-key.txt.pub
-
-# Windows
-Thumbs.db
-ehthumbs.db
-Desktop.ini
diff --git a/payment_headend/index.html b/payment_headend/index.html
deleted file mode 100644
index 432556d..0000000
--- a/payment_headend/index.html
+++ /dev/null
@@ -1,131 +0,0 @@
-
-
-
-
- 创建订单
-
-
-
-创建订单
-
-
-
-
-
-
-
-
-
diff --git a/payment_headend/index.js b/payment_headend/index.js
deleted file mode 100644
index 04bf26e..0000000
--- a/payment_headend/index.js
+++ /dev/null
@@ -1 +0,0 @@
-console.log('Happy developing ✨')
diff --git a/payment_headend/package.json b/payment_headend/package.json
deleted file mode 100644
index 340c6a1..0000000
--- a/payment_headend/package.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "name": "payment_headend",
- "version": "1.0.0",
- "description": "",
- "main": "index.js",
- "scripts": {
- "test": "echo \"Error: no test specified\" && exit 1"
- },
- "private": true
-}