Python SDK for DERO Merchant REST API
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

182 lines
6.3KB

  1. import requests
  2. import json
  3. from .crypto_util import sign_message
  4. from .api_error import APIError
  5. DEFAULT_SCHEME = "https"
  6. DEFAULT_HOST = "merchant.dero.io"
  7. DEFAULT_API_VERSION = "v1"
  8. class Client:
  9. """Dero Merchant Client. Has methods to interact with the Dero Merchant REST API.
  10. Attributes:
  11. __scheme: String of the scheme of the URL of the API.
  12. __host: String of the host of the URL of the API.
  13. __api_version: String of the version of the API.
  14. __base_url: URL of the API.
  15. timeout: Integer of the seconds before a connection to the API times out.
  16. __api_key: String of the API Key of the Client.
  17. __secret_key: String of the Secret Key of the Client.
  18. """
  19. def __init__(self, api_key: str, secret_key: str, scheme=DEFAULT_SCHEME, host=DEFAULT_HOST, api_version=DEFAULT_API_VERSION):
  20. """Inits Client with API Key, Secret Key, scheme, host and API Version
  21. Args:
  22. api_key: String of the API Key of the Client.
  23. secret_key: String of the Secret Key of the Client.
  24. scheme: String of the scheme of the URL of the API.
  25. host: String of the host of the URL of the API.
  26. api_version: String of the version of the API.
  27. """
  28. self.__scheme = scheme
  29. self.__host = host
  30. self.__api_version = api_version
  31. self.__base_url = f'{self.__scheme}://{self.__host}/api/{self.__api_version}'
  32. self.timeout = 10
  33. self.__api_key = api_key
  34. self.__secret_key = secret_key
  35. def __send_request(self, method: str, endpoint: str, query_params: dict=None, payload=None, sign_body=False) -> dict:
  36. """Sends a request to the API.
  37. Args:
  38. method: String of the method of the request.
  39. endpoint: String of the endpoint of the request.
  40. query_params: Dictionary of the query params to send in the request.
  41. payload: Payload to send as the JSON body of the request.
  42. sign_body: Bool of whether the request body has to be signed or not.
  43. Returns:
  44. A dictionary of the JSON response.
  45. Raises:
  46. Exception: An error occured send the request.
  47. APIError: An error was returned as a response by the API.
  48. """
  49. url = self.__base_url + endpoint
  50. headers = {
  51. "User-Agent": "DeroMerchant_Client_Python/1.0",
  52. "X-API-Key": self.__api_key,
  53. }
  54. json_payload = None
  55. json_res = None
  56. try:
  57. if payload is not None:
  58. headers["Content-Type"] = "application/json"
  59. headers["Accept"] = "applciation/json"
  60. json_payload = json.dumps(payload, separators=(",", ":"))
  61. if sign_body is not False:
  62. signature = sign_message(json_payload, self.__secret_key)
  63. headers["X-Signature"] = signature
  64. res = requests.request(method, url, timeout=self.timeout, params=query_params, headers=headers, data=json_payload)
  65. if "application/json" in res.headers.get("Content-Type"):
  66. json_res = res.json()
  67. if (res.status_code < 200) or (res.status_code > 299):
  68. if (json_res is not None) and ("error" in json_res):
  69. raise APIError(json_res["error"]["code"], json_res["error"]["message"])
  70. else:
  71. if res.status_code == 404:
  72. raise Exception(f'error 404: page {res.url} not found')
  73. else:
  74. raise Exception(f'error {res.status_code} returned by {res.url}')
  75. except Exception as err:
  76. raise Exception(f'DeroMerchant Client: {err}')
  77. else:
  78. return json_res
  79. def ping(self) -> dict:
  80. """Pings the API.
  81. Returns:
  82. A dictionary with the JSON response.
  83. """
  84. return self.__send_request(
  85. method="GET",
  86. endpoint="/ping"
  87. )
  88. def create_payment(self, currency: str, amount: float) -> dict:
  89. """Creates a new payment.
  90. Args:
  91. currency: String of the currency of the payment.
  92. amount: Float of the amount of the payment.
  93. Returns:
  94. A dictionary with the JSON response of the newly created Payment.
  95. """
  96. return self.__send_request(
  97. method="POST",
  98. endpoint="/payment",
  99. payload={
  100. "currency": currency,
  101. "amount": amount,
  102. },
  103. sign_body=True
  104. )
  105. def get_payment(self, payment_id: str) -> dict:
  106. """Gets a payment from its ID.
  107. Args:
  108. payment_id: String of the payment ID.
  109. Returns:
  110. A dictionary with the JSON response of the requested Payment.
  111. """
  112. return self.__send_request(
  113. method="GET",
  114. endpoint=f'/payment/{payment_id}'
  115. )
  116. def get_payments(self, payment_ids: list) -> list:
  117. """Gets payments from their IDs.
  118. Args:
  119. payment_ids: List of strings of the payment IDs.
  120. Returns:
  121. A list containing dictionaries with the JSON response of the requested payments.
  122. """
  123. return self.__send_request(
  124. method="POST",
  125. endpoint="/payments",
  126. payload=payment_ids
  127. )
  128. def get_filtered_payments(self, limit: int=None, page: int=None, sort_by: str=None, order_by: str=None, filter_status:str=None, filter_currency: str=None) -> dict:
  129. """Gets filtered payments"""
  130. return self.__send_request(
  131. method="GET",
  132. endpoint="/payments",
  133. query_params={
  134. "limit": limit,
  135. "page": page,
  136. "sort_by": sort_by,
  137. "order_by": order_by,
  138. "filter_status": filter_status,
  139. "filter_currency": filter_currency,
  140. }
  141. )
  142. def get_pay_helper_url(self, payment_id: str) -> str:
  143. """Gets the URL of the Pay helper page of the payment ID.
  144. Args:
  145. payment_id: String of the payment ID.
  146. Returns:
  147. String with the URL of the Pay helper page of the payment ID.
  148. """
  149. return f'{self.__scheme}://{self.__host}/pay/{payment_id}'