solidgate-sdk 0.3.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- solidgate/__init__.py +2 -0
- solidgate/api_client.py +129 -0
- solidgate/encryption.py +19 -0
- solidgate/model.py +16 -0
- solidgate_sdk-0.3.2.dist-info/METADATA +135 -0
- solidgate_sdk-0.3.2.dist-info/RECORD +9 -0
- solidgate_sdk-0.3.2.dist-info/WHEEL +5 -0
- solidgate_sdk-0.3.2.dist-info/licenses/LICENSE.md +13 -0
- solidgate_sdk-0.3.2.dist-info/top_level.txt +1 -0
solidgate/__init__.py
ADDED
solidgate/api_client.py
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
import hashlib
|
|
3
|
+
import hmac
|
|
4
|
+
import json
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
from typing import Generator
|
|
7
|
+
|
|
8
|
+
import requests
|
|
9
|
+
|
|
10
|
+
from solidgate.encryption import AESCipher
|
|
11
|
+
from solidgate.model import MerchantData
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class ApiClient:
|
|
15
|
+
BASE_SOLID_GATE_API_URI = 'https://pay.solidgate.com/api/v1/'
|
|
16
|
+
BASE_RECONCILIATION_API_URI = 'https://reports.solidgate.com/'
|
|
17
|
+
|
|
18
|
+
RECONCILIATION_ORDERS_PATH = 'api/v2/reconciliation/orders'
|
|
19
|
+
RECONCILIATION_CHARGEBACKS_PATH = 'api/v2/reconciliation/chargebacks'
|
|
20
|
+
|
|
21
|
+
RECONCILIATION_DATETIME_FORMAT = '%Y-%m-%d %H:%M:%S'
|
|
22
|
+
|
|
23
|
+
def __init__(self, merchant_id: str,
|
|
24
|
+
private_key: str,
|
|
25
|
+
base_solid_gate_api_uri: str = BASE_SOLID_GATE_API_URI,
|
|
26
|
+
base_reconciliations_api_uri: str = BASE_RECONCILIATION_API_URI):
|
|
27
|
+
self.__merchant_id = merchant_id
|
|
28
|
+
self.__private_key = private_key
|
|
29
|
+
self.__base_solid_gate_api_uri = base_solid_gate_api_uri
|
|
30
|
+
self.__base_reconciliations_api_uri = base_reconciliations_api_uri
|
|
31
|
+
|
|
32
|
+
def charge(self, attributes: dict) -> requests.models.Response:
|
|
33
|
+
return self.__send_solidgate_request('charge', attributes)
|
|
34
|
+
|
|
35
|
+
def recurring(self, attributes: dict) -> requests.models.Response:
|
|
36
|
+
return self.__send_solidgate_request('recurring', attributes)
|
|
37
|
+
|
|
38
|
+
def resign(self, attributes: dict) -> requests.models.Response:
|
|
39
|
+
return self.__send_solidgate_request('resign', attributes)
|
|
40
|
+
|
|
41
|
+
def status(self, attributes: dict) -> requests.models.Response:
|
|
42
|
+
return self.__send_solidgate_request('status', attributes)
|
|
43
|
+
|
|
44
|
+
def refund(self, attributes: dict) -> requests.models.Response:
|
|
45
|
+
return self.__send_solidgate_request('refund', attributes)
|
|
46
|
+
|
|
47
|
+
def auth(self, attributes: dict) -> requests.models.Response:
|
|
48
|
+
return self.__send_solidgate_request('auth', attributes)
|
|
49
|
+
|
|
50
|
+
def void(self, attributes: dict) -> requests.models.Response:
|
|
51
|
+
return self.__send_solidgate_request('void', attributes)
|
|
52
|
+
|
|
53
|
+
def settle(self, attributes: dict) -> requests.models.Response:
|
|
54
|
+
return self.__send_solidgate_request('settle', attributes)
|
|
55
|
+
|
|
56
|
+
def arn_code(self, attributes: dict) -> requests.models.Response:
|
|
57
|
+
return self.__send_solidgate_request('arn-code', attributes)
|
|
58
|
+
|
|
59
|
+
def apple_pay(self, attributes: dict) -> requests.models.Response:
|
|
60
|
+
return self.__send_solidgate_request('apple-pay', attributes)
|
|
61
|
+
|
|
62
|
+
def google_pay(self, attributes: dict) -> requests.models.Response:
|
|
63
|
+
return self.__send_solidgate_request('google-pay', attributes)
|
|
64
|
+
|
|
65
|
+
def form_merchant_data(self, attributes: dict) -> FormInitDTO:
|
|
66
|
+
payment_intent = AESCipher(self.__private_key).encrypt(self.__convert_request_attributes_to_str(attributes))
|
|
67
|
+
signature = self.__generate_signature(payment_intent)
|
|
68
|
+
form_init_dto = FormInitDTO(payment_intent=payment_intent, publicKey=self.__merchant_id, signature=signature)
|
|
69
|
+
return form_init_dto
|
|
70
|
+
|
|
71
|
+
def form_update(self, attributes: dict) -> FormUpdateDTO:
|
|
72
|
+
partial_intent = AESCipher(self.__private_key).encrypt(self.__convert_request_attributes_to_str(attributes))
|
|
73
|
+
signature = self.__generate_signature(partial_intent)
|
|
74
|
+
form_update_dto = FormUpdateDTO(partial_intent=partial_intent, signature=signature)
|
|
75
|
+
return form_update_dto
|
|
76
|
+
|
|
77
|
+
def form_resign(self, attributes: dict) -> FormInitDTO:
|
|
78
|
+
resign_intent = AESCipher(self.__private_key).encrypt(self.__convert_request_attributes_to_str(attributes))
|
|
79
|
+
signature = self.__generate_signature(resign_intent)
|
|
80
|
+
form_resign_dto = FormResignDTO(resign_intent=resign_intent, publicKey=self.__merchant_id, signature=signature)
|
|
81
|
+
return form_resign_dto
|
|
82
|
+
|
|
83
|
+
def order_reconciliation(self, date_from: datetime, date_to: datetime) -> Generator:
|
|
84
|
+
return self.__send_reconciliation_request(self.RECONCILIATION_ORDERS_PATH, date_from, date_to)
|
|
85
|
+
|
|
86
|
+
def chargeback_reconciliation(self, date_from: datetime, date_to: datetime) -> Generator:
|
|
87
|
+
return self.__send_reconciliation_request(self.RECONCILIATION_CHARGEBACKS_PATH, date_from, date_to)
|
|
88
|
+
|
|
89
|
+
def __generate_signature(self, data: str) -> str:
|
|
90
|
+
encrypto_data = (self.__merchant_id + data + self.__merchant_id).encode('utf-8')
|
|
91
|
+
sign = hmac.new(self.__private_key.encode('utf-8'), encrypto_data, hashlib.sha512).hexdigest()
|
|
92
|
+
return base64.b64encode(sign.encode('utf-8')).decode('utf-8')
|
|
93
|
+
|
|
94
|
+
def __send_solidgate_request(self, method: str, attributes: dict) -> requests.models.Response:
|
|
95
|
+
full_url = self.__base_solid_gate_api_uri + method
|
|
96
|
+
return self.__send_request(full_url, attributes)
|
|
97
|
+
|
|
98
|
+
def __send_reconciliation_request(self, path: str, date_from: datetime, date_to: datetime) -> Generator:
|
|
99
|
+
full_url = self.__base_reconciliations_api_uri + path
|
|
100
|
+
attributes = {'date_from': date_from.strftime(self.RECONCILIATION_DATETIME_FORMAT),
|
|
101
|
+
'date_to': date_to.strftime(self.RECONCILIATION_DATETIME_FORMAT)}
|
|
102
|
+
while True:
|
|
103
|
+
try:
|
|
104
|
+
response = self.__send_request(full_url, attributes)
|
|
105
|
+
except requests.exceptions.RequestException as err:
|
|
106
|
+
raise Exception("Exception during request:", err)
|
|
107
|
+
|
|
108
|
+
if 200 <= response.status_code < 300:
|
|
109
|
+
response_content = json.loads(response.content)
|
|
110
|
+
for order in response_content['orders']:
|
|
111
|
+
yield order
|
|
112
|
+
|
|
113
|
+
attributes['next_page_iterator'] = response_content['metadata']['next_page_iterator']
|
|
114
|
+
if not attributes['next_page_iterator']:
|
|
115
|
+
break
|
|
116
|
+
else:
|
|
117
|
+
raise Exception('Request is not successful!')
|
|
118
|
+
|
|
119
|
+
def __send_request(self, path: str, attributes: dict) -> requests.models.Response:
|
|
120
|
+
body = self.__convert_request_attributes_to_str(attributes)
|
|
121
|
+
headers = {'Content-Type': 'application/json',
|
|
122
|
+
'Accept': 'application/json',
|
|
123
|
+
'Merchant': self.__merchant_id,
|
|
124
|
+
'Signature': self.__generate_signature(body)}
|
|
125
|
+
return requests.post(path, headers=headers, json=attributes)
|
|
126
|
+
|
|
127
|
+
@staticmethod
|
|
128
|
+
def __convert_request_attributes_to_str(attributes: dict) -> str:
|
|
129
|
+
return json.dumps(attributes)
|
solidgate/encryption.py
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
|
|
3
|
+
from Crypto import Random
|
|
4
|
+
from Crypto.Cipher import AES
|
|
5
|
+
from Crypto.Util.Padding import pad
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class AESCipher:
|
|
9
|
+
MAX_KEY_LEN = 32
|
|
10
|
+
|
|
11
|
+
def __init__(self, key):
|
|
12
|
+
self.__block_size = AES.block_size
|
|
13
|
+
self.__key = key[:self.MAX_KEY_LEN].encode()
|
|
14
|
+
|
|
15
|
+
def encrypt(self, raw: str) -> str:
|
|
16
|
+
raw = pad(raw.encode(), self.__block_size, style='pkcs7')
|
|
17
|
+
iv = Random.new().read(self.__block_size)
|
|
18
|
+
cipher = AES.new(self.__key, AES.MODE_CBC, iv)
|
|
19
|
+
return base64.urlsafe_b64encode(iv + cipher.encrypt(raw)).decode('utf-8')
|
solidgate/model.py
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
class FormInitDTO:
|
|
2
|
+
def __init__(self, payment_intent: str, publicKey: str, signature: str):
|
|
3
|
+
self.payment_intent = payment_intent
|
|
4
|
+
self.merchant = publicKey
|
|
5
|
+
self.signature = signature
|
|
6
|
+
|
|
7
|
+
class FormUpdateDTO:
|
|
8
|
+
def __init__(self, partial_intent: str, signature: str):
|
|
9
|
+
self.partial_intent = partial_intent
|
|
10
|
+
self.signature = signature
|
|
11
|
+
|
|
12
|
+
class FormResignDTO:
|
|
13
|
+
def __init__(self, resignIntent: str, publicKey: str, signature: str):
|
|
14
|
+
self.resign_intent = resignIntent
|
|
15
|
+
self.merchant = publicKey
|
|
16
|
+
self.signature = signature
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: solidgate-sdk
|
|
3
|
+
Version: 0.3.2
|
|
4
|
+
Summary: Python API SDK for SolidGate payment gateway
|
|
5
|
+
Home-page: https://api-docs.solidgate.com/
|
|
6
|
+
Author: SolidGate
|
|
7
|
+
Author-email: info@solidgate.com
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
License-File: LICENSE.md
|
|
13
|
+
Requires-Dist: requests
|
|
14
|
+
Requires-Dist: pycryptodome
|
|
15
|
+
Dynamic: author
|
|
16
|
+
Dynamic: author-email
|
|
17
|
+
Dynamic: classifier
|
|
18
|
+
Dynamic: description
|
|
19
|
+
Dynamic: description-content-type
|
|
20
|
+
Dynamic: home-page
|
|
21
|
+
Dynamic: license-file
|
|
22
|
+
Dynamic: requires-dist
|
|
23
|
+
Dynamic: summary
|
|
24
|
+
|
|
25
|
+
# Solidgate API
|
|
26
|
+
|
|
27
|
+
[](https://badge.fury.io/py/solidgate-sdk)
|
|
28
|
+
|
|
29
|
+
Python SDK provides API options for integrating Solidgate’s payment orchestrator into your Python applications.
|
|
30
|
+
|
|
31
|
+
Check our
|
|
32
|
+
* <a href="https://docs.solidgate.com/" target="_blank">Payment guide</a> to understand business value better
|
|
33
|
+
* <a href="https://api-docs.solidgate.com/" target="_blank">API Reference</a> to find more examples of usage
|
|
34
|
+
|
|
35
|
+
## Structure
|
|
36
|
+
|
|
37
|
+
<table style="width: 100%; background: transparent;">
|
|
38
|
+
<colgroup>
|
|
39
|
+
<col style="width: 50%;">
|
|
40
|
+
<col style="width: 50%;">
|
|
41
|
+
</colgroup>
|
|
42
|
+
<tr>
|
|
43
|
+
<th>SDK for Python contains</th>
|
|
44
|
+
<th>Table of contents</th>
|
|
45
|
+
</tr>
|
|
46
|
+
<tr>
|
|
47
|
+
<td>
|
|
48
|
+
<ul>
|
|
49
|
+
<li>
|
|
50
|
+
<code>solidgate/</code> – main library source code for development
|
|
51
|
+
<ul>
|
|
52
|
+
<li><code>__init__.py</code> – initializes the SDK package for importing</li>
|
|
53
|
+
<li><code>api_client.py</code> – main file for API integration and HTTP request handling</li>
|
|
54
|
+
<li><code>encryption.py</code> – library for encryption-related operations</li>
|
|
55
|
+
<li><code>model.py</code> – defines data structures for payment attributes and responses</li>
|
|
56
|
+
</ul>
|
|
57
|
+
</li>
|
|
58
|
+
<li><code>setup.py</code> – script for managing dependencies and library imports</li>
|
|
59
|
+
</ul>
|
|
60
|
+
</td>
|
|
61
|
+
<td>
|
|
62
|
+
<a href="https://github.com/solidgate-tech/python-sdk?tab=readme-ov-file#requirements">Requirements</a><br>
|
|
63
|
+
<a href="https://github.com/solidgate-tech/python-sdk?tab=readme-ov-file#installation">Installation</a><br>
|
|
64
|
+
<a href="https://github.com/solidgate-tech/python-sdk?tab=readme-ov-file#usage">Usage</a><br>
|
|
65
|
+
<a href="https://github.com/solidgate-tech/python-sdk?tab=readme-ov-file#errors">Errors</a><br>
|
|
66
|
+
</td>
|
|
67
|
+
</tr>
|
|
68
|
+
</table>
|
|
69
|
+
|
|
70
|
+
<br>
|
|
71
|
+
|
|
72
|
+
## Requirements
|
|
73
|
+
|
|
74
|
+
* **Python**: 3.7 or later
|
|
75
|
+
* **Packages**: `requests` library
|
|
76
|
+
* **Solidgate account**: Public and secret key (request via <a href="mailto:sales@solidgate.com">sales@solidgate.com</a>)
|
|
77
|
+
|
|
78
|
+
<br>
|
|
79
|
+
|
|
80
|
+
## Installation
|
|
81
|
+
|
|
82
|
+
To start using the Python SDK:
|
|
83
|
+
|
|
84
|
+
1. Ensure you have your public and secret key.
|
|
85
|
+
2. Install the SDK in your project using pip:
|
|
86
|
+
```bash
|
|
87
|
+
pip install solidgate-card-sdk
|
|
88
|
+
```
|
|
89
|
+
3. Import the classes into your project:
|
|
90
|
+
```
|
|
91
|
+
from solidgate import ApiClient
|
|
92
|
+
client = ApiClient(public_key='YourMerchantId', secret_key='YourPrivateKey')
|
|
93
|
+
```
|
|
94
|
+
4. Use test credentials for integration testing. After successful testing, switch to production credentials.
|
|
95
|
+
|
|
96
|
+
<br>
|
|
97
|
+
|
|
98
|
+
## Usage
|
|
99
|
+
|
|
100
|
+
### Charge a payment
|
|
101
|
+
|
|
102
|
+
Create a class instance of the `ApiClient` class.
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
from solidgate import ApiClient
|
|
106
|
+
|
|
107
|
+
client = ApiClient(public_key, secret_key)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
- `public_key` - unique merchant identification
|
|
111
|
+
- `secret_key` - secret code for request signature, it is provided at the moment of merchant registration
|
|
112
|
+
|
|
113
|
+
### Resign form
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
response = client.form_resign({'order_id': '12345'})
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
<br>
|
|
120
|
+
|
|
121
|
+
## Errors
|
|
122
|
+
|
|
123
|
+
Handle <a href="https://docs.solidgate.com/payments/payments-insights/error-codes/" target="_blank">errors</a>.
|
|
124
|
+
|
|
125
|
+
```python
|
|
126
|
+
try:
|
|
127
|
+
response = client.charge({...})
|
|
128
|
+
except Exception as e:
|
|
129
|
+
print(e)
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
Looking for help? <a href="https://support.solidgate.com/support/tickets/new" target="_blank">Contact us</a> <br>
|
|
135
|
+
Want to contribute? <a href="https://github.com/solidgate-tech/python-sdk/pulls" target="_blank">Submit a pull request</a>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
solidgate/__init__.py,sha256=nOvLT2_gmMOLcDLEdJIDCc_ED5udWhR0858SNOOIp_s,71
|
|
2
|
+
solidgate/api_client.py,sha256=OpOItg46-kDzV47Qwh8x6M4DPU4ELr19kPiLkSqvs1I,6237
|
|
3
|
+
solidgate/encryption.py,sha256=CjLdl11PxDuSb-RG-sp1WpIMjWd4gBjkYWVNas3MfcU,567
|
|
4
|
+
solidgate/model.py,sha256=u6rq_bHppf9wSF9Szz7yDDm8C8nO0c4dAGbnXBFReeI,580
|
|
5
|
+
solidgate_sdk-0.3.2.dist-info/licenses/LICENSE.md,sha256=Gjp7q0zwHb904tsXGdqKf7bNpkNUCOgoUeDihfIfCFY,609
|
|
6
|
+
solidgate_sdk-0.3.2.dist-info/METADATA,sha256=E8FpzHRNnj3BBTMDfWVrvGD3YVUsXCRwlpacsRDlULs,4094
|
|
7
|
+
solidgate_sdk-0.3.2.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
8
|
+
solidgate_sdk-0.3.2.dist-info/top_level.txt,sha256=g77pQ7dBSpjiJQJiDcDjyofS81wrd2jDAfTNlqxhAd4,10
|
|
9
|
+
solidgate_sdk-0.3.2.dist-info/RECORD,,
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Apache License, Version 2.0
|
|
2
|
+
|
|
3
|
+
Copyright 2015 - GTWS Tech Limited (https://solidgate.com/)
|
|
4
|
+
|
|
5
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
you may not use this file except in compliance with the License.
|
|
7
|
+
You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
|
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
See the License for the specific language governing permissions and
|
|
13
|
+
limitations under the License.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
solidgate
|