Skip to content

Commit 67d6ebf

Browse files
authored
Merge pull request #8 from sphinxxanxus/master
Schedule Payout
2 parents 6975174 + 70c4f8c commit 67d6ebf

File tree

5 files changed

+153
-13
lines changed

5 files changed

+153
-13
lines changed

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,7 @@
33
test.py
44
kkiapay.egg-info
55
dist
6-
build
6+
build
7+
venv
8+
.idea
9+
__pycache__

kkiapay/core.py

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,22 @@
11
import json
2-
import requests
32
from collections import namedtuple
43

4+
import requests
55

6-
class Kkiapay:
6+
from kkiapay.exceptions import KKiapayAlogrithmException, KKiapayDestinationTypeException
77

8+
9+
class Kkiapay:
810
BASE_URL = "https://api.kkiapay.me"
911
SANDBOX_URL = "https://api-sandbox.kkiapay.me"
12+
ALGORITHMS = {"1": 'rate', "2": 'roof'}
13+
14+
RATE_FREQUENCIES = {"1": '3d', "2": '1w', "3": '1m'}
15+
default_roof_amount = "50000"
16+
DESTINATION_TYPES = {
17+
"1": 'MOBILE_MONEY',
18+
"2": 'BANK_ACCOUNT',
19+
}
1020

1121
def __init__(self, public_key, private_key, secret, sandbox=False):
1222
self.secret = secret
@@ -53,7 +63,30 @@ def refund_transaction(self, transaction_id):
5363
),
5464
)
5565

56-
def setup_payout(self, options):
57-
self.url += "/merchant/payouts/schedule"
58-
r = requests.post(self.url, data=options, headers=self.headers)
59-
return r.text
66+
def setup_payout(self, algorithm: str, destination: str, destination_type: str, roof_amount: str = None,
67+
send_notification: bool = True, rate_frequency: str = RATE_FREQUENCIES["1"],
68+
country_code: str = "229"):
69+
options = {
70+
"destination": country_code + destination if destination_type == "1" else destination,
71+
"send_notification": 1 if send_notification else 0,
72+
}
73+
74+
if destination_type in self.DESTINATION_TYPES.keys():
75+
options["destination_type"] = self.DESTINATION_TYPES[destination_type]
76+
else:
77+
raise KKiapayDestinationTypeException(self.DESTINATION_TYPES)
78+
79+
if algorithm in self.ALGORITHMS.keys():
80+
options['algorithm'] = self.ALGORITHMS[algorithm]
81+
else:
82+
raise KKiapayAlogrithmException(self.ALGORITHMS)
83+
if algorithm == "2":
84+
options["roof_amount"] = roof_amount if roof_amount is not None else self.default_roof_amount
85+
else:
86+
options["rate_frequency"] = rate_frequency if rate_frequency in self.RATE_FREQUENCIES.values() else \
87+
self.RATE_FREQUENCIES["1"]
88+
r = requests.post(self.url + '/merchant/payouts/schedule', data=options, headers=self.headers)
89+
return {
90+
'response': r.json(),
91+
'status_code': r.status_code
92+
}

kkiapay/exceptions.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,16 @@
11
class KkiapayException(Exception):
22
pass
3+
4+
5+
class KKiapayAlogrithmException(Exception):
6+
def __init__(self, algorithms):
7+
Exception.__init__(self,
8+
"algorithm must be {}".format(
9+
" or ".join(" if it's ".join(algorithm) for algorithm in algorithms.items())))
10+
11+
12+
class KKiapayDestinationTypeException(Exception):
13+
def __init__(self, algorithms):
14+
Exception.__init__(self,
15+
"destination_type must be {}".format(
16+
" or ".join(" if it's ".join(algorithm) for algorithm in algorithms.items())))

readme.md

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,57 @@ Here's the plan for what's coming:
5959
- [x] Sandbox and Live environments
6060
- [x] Verify Transaction
6161
- [x] Refund Transaction - `Only available on Live`
62-
- [ ] Schedule Payout
62+
- [x] Schedule Payout
6363
- [ ] Add better errors and exceptions handling
6464
- [ ] Add tests.
6565

66+
67+
## Schedule Payout
68+
69+
### Example
70+
Below is an example of the function usage:
71+
```python
72+
# Setup Scheduled Payout using 'ROOF' algorithm
73+
schedule_payout = k.setup_payout(algorithm = '2',
74+
roof_amount = '10000',
75+
destination = '61000000',
76+
destination_type = '1',
77+
send_notification = True,
78+
country_code = '229'
79+
)
80+
81+
print(schedule_payout)
82+
#{
83+
# 'response':
84+
# {
85+
# 'merchant': '5d34445784deb700073a0281',
86+
# 'meta_data': '',
87+
# 'algorithm': 'roof',
88+
# 'rate_frequency': '',
89+
# 'roof_amount': '10000',
90+
# 'active': True,
91+
# 'send_notification': True,
92+
# 'destination_type': 'MOBILE_MONEY',
93+
# 'destination': '22961000000',
94+
# 'job_name': '',
95+
# 'account': '5d34445784deb700073a0282'
96+
# },
97+
# 'status_code': 200
98+
#}
99+
```
100+
101+
### Attribute Matrix
102+
| Name | Required | Possible Values | Description |
103+
|:-----------------:|:--------:|:------------------------------------------:|:---------------------------------------------------------------------------------:|
104+
| **algorithm** | **M** | {"1": 'rate', "2": 'roof'} | Specify the algorithm to be used. |
105+
| **destination_type** | **M** | {"1": 'MOBILE_MONEY', "2": 'BANK_ACCOUNT'} | Specify the Destination type |
106+
| **destination** | **M** | '61000000' | Specify the Destination number/account Number |
107+
| **rate_frequency** | M/O | {"1": '3d', "2": '1w', "3": '1m'} | Specify the Rate Frequency. Required in case 'rate' algorithm is used |
108+
| **roof_amount** | M/O | '10000' | Specify the Roof amount. |
109+
| **send_notification** | O | Boolean (True, False) | Specify is a Notification should be sent |
110+
| **country_code** | O | '229' | Specify the Country Code of the destination number is case 'MOBILE MONEY' is used |
111+
112+
66113
## Contributing
67114

68115
Check our [contribution guide](CONTRIBUTING.md).

tests/test_kkiapay.py

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,55 @@ def teardown_module(module):
1414

1515

1616
class TestKkiapay(object):
17-
def test_urls(self):
18-
live = Kkiapay("public_key", "private_key", "secret")
19-
sandbox = Kkiapay("public_key", "private_key", "secret", sandbox=True)
17+
live = Kkiapay("public_key", "private_key", "secret")
18+
sandbox = Kkiapay("public_key", "private_key", "secret", sandbox=True)
2019

21-
assert live.url == Kkiapay.BASE_URL
22-
assert sandbox.url == Kkiapay.SANDBOX_URL
20+
def test_urls(self):
21+
assert self.live.url == Kkiapay.BASE_URL
22+
assert self.sandbox.url == Kkiapay.SANDBOX_URL
2323

2424
def test_requests(self, requests_mock):
2525
pass
26+
27+
def test_setup_payout(self, monkeypatch):
28+
results = {
29+
'response': {
30+
'merchant': '5d34445784deb700073a0281',
31+
'meta_data': '',
32+
'algorithm': 'roof',
33+
'rate_frequency': '',
34+
'roof_amount': '50000',
35+
'active': True,
36+
'send_notification': True,
37+
'destination_type': 'MOBILE_MONEY',
38+
'destination': '22961000000',
39+
'job_name': '',
40+
'account': '5d34445784deb700073a0282'
41+
},
42+
'status_code': 200}
43+
44+
class MockJsonResponse:
45+
status_code = 200
46+
47+
@staticmethod
48+
def json():
49+
return {
50+
'merchant': '5d34445784deb700073a0281',
51+
'meta_data': '',
52+
'algorithm': 'roof',
53+
'rate_frequency': '',
54+
'roof_amount': '50000',
55+
'active': True,
56+
'send_notification': True,
57+
'destination_type': 'MOBILE_MONEY',
58+
'destination': '22961000000',
59+
'job_name': '',
60+
'account': '5d34445784deb700073a0282'
61+
}
62+
63+
def kkiapay_api_mock_return(*args, **kwargs):
64+
return MockJsonResponse()
65+
66+
monkeypatch.setattr(requests, 'post', kkiapay_api_mock_return)
67+
assert self.sandbox.setup_payout(algorithm="2", destination="61000000", destination_type="1") == results
68+
assert self.live.setup_payout(algorithm="1", destination="61000000", destination_type="1") == results

0 commit comments

Comments
 (0)