Skip to content

Commit 7db8799

Browse files
authored
Merge pull request #28 from mwarzybok-sumoheavy/feature/SP-554
Payout Groups - Python
2 parents 2dc74cf + e1fefb3 commit 7db8799

21 files changed

+371
-46
lines changed

src/bitpay/client.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
from .models.facade import Facade
2626
from .models.bill.bill import Bill
2727
from .models.invoice.invoice_event_token import InvoiceEventToken
28+
from .models.payout.payout_group import PayoutGroup
2829
from .models.rate.rate import Rate
2930
from .utils.guid_generator import GuidGenerator
3031
from .models.rate.rates import Rates
@@ -780,6 +781,28 @@ def request_payout_notification(self, payout_id: str) -> bool:
780781
client = self.create_payout_client()
781782
return client.request_notification(payout_id)
782783

784+
def create_payout_group(self, payouts: List[Payout]) -> PayoutGroup:
785+
"""
786+
Submit a BitPay Payouts. See https://developer.bitpay.com/reference/create-payout-group
787+
788+
:param List[Payout] payouts: Payouts to create
789+
:return: PayoutGroup
790+
:raises BitPayException
791+
"""
792+
client = self.create_payout_client()
793+
return client.create_group(payouts)
794+
795+
def cancel_payout_group(self, group_id: str) -> PayoutGroup:
796+
"""
797+
Cancel a BitPay Payouts. See https://developer.bitpay.com/reference/cancel-a-payout-group
798+
799+
:param group_id The the groupId of the collection of payouts you want to cancel.
800+
:return: PayoutGroup
801+
:raises BitPayException
802+
"""
803+
client = self.create_payout_client()
804+
return client.cancel_group(group_id)
805+
783806
def get_settlements(
784807
self,
785808
currency: Optional[str] = None,

src/bitpay/clients/bill_client.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ def create(
4242
)
4343
except BitPayException as exe:
4444
raise BillCreationException(
45-
"failed to serialize bill object : %s" % str(exe), exe.get_api_code()
45+
"failed to serialize bill object : %s" % str(exe), api_code=exe.get_api_code()
4646
)
4747

4848
try:
@@ -73,7 +73,7 @@ def get(
7373
)
7474
except BitPayException as exe:
7575
raise BillQueryException(
76-
"failed to serialize bill object : %s" % str(exe), exe.get_api_code()
76+
"failed to serialize bill object : %s" % str(exe), api_code=exe.get_api_code()
7777
)
7878

7979
try:
@@ -100,7 +100,7 @@ def get_bills(self, status: Optional[str] = None) -> List[Bill]:
100100
response_json = self.__bitpay_client.get("bills", params, True)
101101
except BitPayException as exe:
102102
raise BillQueryException(
103-
"failed to serialize bill object : %s" % str(exe), exe.get_api_code()
103+
"failed to serialize bill object : %s" % str(exe), api_code=exe.get_api_code()
104104
)
105105

106106
try:
@@ -134,7 +134,7 @@ def update(self, bill: Bill, bill_id: str) -> Bill:
134134
)
135135
except BitPayException as exe:
136136
raise BillUpdateException(
137-
"failed to serialize bill object : %s" % str(exe), exe.get_api_code()
137+
"failed to serialize bill object : %s" % str(exe), api_code=exe.get_api_code()
138138
)
139139

140140
try:
@@ -162,7 +162,7 @@ def deliver(self, bill_id: str, bill_token: str) -> bool:
162162
)
163163
except BitPayException as exe:
164164
raise BillDeliveryException(
165-
"failed to serialize bill object : %s" % str(exe), exe.get_api_code()
165+
"failed to serialize bill object : %s" % str(exe), api_code=exe.get_api_code()
166166
)
167167

168168
try:

src/bitpay/clients/bitpay_client.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ def __init__(
2828
def init(self) -> None:
2929
try:
3030
self.__headers = {
31-
"x-accept-version": Config.BITPAYAPIVERSION,
32-
"x-bitpay-plugin-info": Config.BITPAYPLUGININFO,
33-
"x-bitpay-api-frame": Config.BITPAYAPIFRAME,
34-
"x-bitpay-api-frame-version": Config.BITPAYAPIFRAMEVERSION,
31+
"x-accept-version": Config.BITPAY_API_VERSION.value,
32+
"x-bitpay-plugin-info": Config.BITPAY_PLUGIN_INFO.value,
33+
"x-bitpay-api-frame": Config.BITPAY_API_FRAME.value,
34+
"x-bitpay-api-frame-version": Config.BITPAY_API_FRAME_VERSION.value,
3535
"content-type": "application/json",
3636
"X-accept-version": "2.0.0",
3737
}

src/bitpay/clients/currency_client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def get_currencies(self) -> Dict[str, Currency]:
2626
except BitPayException as exe:
2727
raise CurrencyQueryException(
2828
"failed to serialize Currency object : %s" % str(exe),
29-
exe.get_api_code(),
29+
api_code=exe.get_api_code()
3030
)
3131

3232
try:

src/bitpay/clients/invoice_client.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ def get_invoices(
207207
response_json = self.__bitpay_client.get("invoices/", params, True)
208208
except BitPayException as exe:
209209
raise InvoiceQueryException(
210-
"failed to serialize Invoice object : %s" % str(exe), exe.get_api_code()
210+
"failed to serialize Invoice object : %s" % str(exe), api_code=exe.get_api_code()
211211
)
212212
except Exception as exe:
213213
raise InvoiceQueryException(
@@ -302,7 +302,7 @@ def cancel(self, invoice_id: str, force_cancel: bool = False) -> Invoice:
302302
)
303303
except BitPayException as exe:
304304
raise InvoiceCancellationException(
305-
"failed to serialize Invoice object : %s" % str(exe), exe.get_api_code()
305+
"failed to serialize Invoice object : %s" % str(exe), api_code=exe.get_api_code()
306306
)
307307
except Exception as exe:
308308
raise InvoiceCancellationException(
@@ -340,7 +340,7 @@ def cancel_by_guid(self, guid: str, force_cancel: bool = False) -> Invoice:
340340
)
341341
except BitPayException as exe:
342342
raise InvoiceCancellationException(
343-
"failed to serialize Invoice object : %s" % str(exe), exe.get_api_code()
343+
"failed to serialize Invoice object : %s" % str(exe), api_code=exe.get_api_code()
344344
)
345345
except Exception as exe:
346346
raise InvoiceCancellationException(
@@ -375,7 +375,7 @@ def get_event_token(self, invoice_id: str) -> InvoiceEventToken:
375375
)
376376
except BitPayException as exe:
377377
raise InvoiceCancellationException(
378-
"failed to serialize Invoice object : %s" % str(exe), exe.get_api_code()
378+
"failed to serialize Invoice object : %s" % str(exe), api_code=exe.get_api_code()
379379
)
380380
except Exception as exe:
381381
raise InvoiceCancellationException(
@@ -411,7 +411,7 @@ def pay(self, invoice_id: str, status: str) -> Invoice:
411411
)
412412
except BitPayException as exe:
413413
raise InvoicePaymentException(
414-
"failed to serialize Invoice object : %s" % str(exe), exe.get_api_code()
414+
"failed to serialize Invoice object : %s" % str(exe), api_code=exe.get_api_code()
415415
)
416416
except Exception as exe:
417417
raise InvoicePaymentException(

src/bitpay/clients/ledger_client.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ def get_entries(
3939
response_json = self.__bitpay_client.get("ledgers/%s" % currency, params)
4040
except BitPayException as exe:
4141
raise LedgerQueryException(
42-
"failed to serialize Ledger object : %s" % str(exe), exe.get_api_code()
42+
"failed to serialize Ledger object : %s" % str(exe), api_code=exe.get_api_code()
4343
)
4444

4545
try:
@@ -68,7 +68,7 @@ def get_ledgers(self) -> List[Ledger]:
6868
response_json = self.__bitpay_client.get("ledgers", params)
6969
except BitPayException as exe:
7070
raise LedgerQueryException(
71-
"failed to serialize Ledger object : %s" % str(exe), exe.get_api_code()
71+
"failed to serialize Ledger object : %s" % str(exe), api_code=exe.get_api_code()
7272
)
7373

7474
try:

src/bitpay/clients/payout_client.py

Lines changed: 56 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,13 @@
44
from bitpay.exceptions.bitpay_exception import BitPayException
55
from bitpay.exceptions.payout_cancellation_exception import PayoutCancellationException
66
from bitpay.exceptions.payout_creation_exception import PayoutCreationException
7+
from bitpay.exceptions.payout_exception import PayoutException
78
from bitpay.exceptions.payout_notification_exception import PayoutNotificationException
89
from bitpay.exceptions.payout_query_exception import PayoutQueryException
910
from bitpay.models.facade import Facade
1011
from bitpay.models.payout.payout import Payout
12+
from bitpay.models.payout.payout_group import PayoutGroup
13+
from bitpay.models.payout.payout_group_failed import PayoutGroupFailed
1114
from bitpay.utils.token_container import TokenContainer
1215

1316

@@ -34,7 +37,7 @@ def submit(self, payout: Payout) -> Payout:
3437
response_json = self.__bitpay_client.post("payouts", payout.to_json(), True)
3538
except BitPayException as exe:
3639
raise PayoutCreationException(
37-
"failed to serialize Payout object : %s" % str(exe), exe.get_api_code()
40+
"failed to serialize Payout object : %s" % str(exe), api_code=exe.get_api_code()
3841
)
3942

4043
try:
@@ -62,7 +65,7 @@ def get(self, payout_id: str) -> Payout:
6265
response_json = self.__bitpay_client.get("payouts/%s" % payout_id, params)
6366
except BitPayException as exe:
6467
raise PayoutQueryException(
65-
"failed to serialize Payout object : %s" % str(exe), exe.get_api_code()
68+
"failed to serialize Payout object : %s" % str(exe), api_code=exe.get_api_code()
6669
)
6770

6871
try:
@@ -115,7 +118,7 @@ def get_payouts(
115118
response_json = self.__bitpay_client.get("payouts", params)
116119
except BitPayException as exe:
117120
raise PayoutQueryException(
118-
"failed to serialize Payout object : %s" % str(exe), exe.get_api_code()
121+
"failed to serialize Payout object : %s" % str(exe), api_code=exe.get_api_code()
119122
)
120123

121124
try:
@@ -146,7 +149,8 @@ def cancel(self, payout_id: str) -> bool:
146149
)
147150
except BitPayException as exe:
148151
raise PayoutCancellationException(
149-
"failed to serialize Payout object : %s" % str(exe), exe.get_api_code()
152+
"failed to serialize Payout object : %s" % str(exe),
153+
api_code=exe.get_api_code(),
150154
)
151155

152156
try:
@@ -174,7 +178,8 @@ def request_notification(self, payout_id: str) -> bool:
174178
)
175179
except BitPayException as exe:
176180
raise PayoutNotificationException(
177-
"failed to serialize Payout object : %s" % str(exe), exe.get_api_code()
181+
"failed to serialize Payout object : %s" % str(exe),
182+
api_code=exe.get_api_code(),
178183
)
179184

180185
try:
@@ -184,3 +189,49 @@ def request_notification(self, payout_id: str) -> bool:
184189
"failed to deserialize BitPay server response "
185190
" (Payout) : %s" % str(exe)
186191
)
192+
193+
@staticmethod
194+
def get_payout_group_response(
195+
response_json: dict, response_type: str
196+
) -> PayoutGroup:
197+
try:
198+
payouts = []
199+
for payout in response_json[response_type]:
200+
payouts.append(Payout(**payout))
201+
202+
failed = []
203+
for fail in response_json["failed"]:
204+
failed.append(PayoutGroupFailed(**fail))
205+
206+
return PayoutGroup(payouts, failed)
207+
except:
208+
raise PayoutException("Unable to parse payouts")
209+
210+
def create_group(self, payouts: List[Payout]) -> PayoutGroup:
211+
params = {"token": self.__token_container.get_access_token(Facade.PAYOUT)}
212+
instructions = []
213+
214+
try:
215+
for payout in payouts:
216+
instructions.append(payout.to_json())
217+
218+
params["instructions"] = instructions
219+
220+
response_json = self.__bitpay_client.post("payouts/group", params)
221+
return self.get_payout_group_response(response_json, "created")
222+
except BitPayException as exe:
223+
raise PayoutCreationException(
224+
"failed to serialize Payout object : %s" % str(exe),
225+
api_code=exe.get_api_code(),
226+
)
227+
228+
def cancel_group(self, group_id: str) -> PayoutGroup:
229+
params = {"token": self.__token_container.get_access_token(Facade.PAYOUT)}
230+
try:
231+
response_json = self.__bitpay_client.delete("payouts/group/" + group_id, params)
232+
return self.get_payout_group_response(response_json, "cancelled")
233+
except BitPayException as exe:
234+
raise PayoutCancellationException(
235+
"failed to serialize Payout object : %s" % str(exe),
236+
api_code=exe.get_api_code(),
237+
)

src/bitpay/clients/payout_recipient_client.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ def submit(self, recipients: PayoutRecipients) -> List[PayoutRecipient]:
6161
except BitPayException as exe:
6262
raise PayoutRecipientCreationException(
6363
"failed to serialize PayoutRecipients object : %s" % str(exe),
64-
exe.get_api_code(),
64+
api_code=exe.get_api_code()
6565
)
6666

6767
try:
@@ -94,7 +94,7 @@ def get(self, recipient_id: str) -> PayoutRecipient:
9494
except BitPayException as exe:
9595
raise PayoutRecipientQueryException(
9696
"failed to serialize PayoutRecipients object : %s" % str(exe),
97-
exe.get_api_code(),
97+
api_code=exe.get_api_code(),
9898
)
9999

100100
try:
@@ -132,7 +132,7 @@ def get_recipients(
132132
except BitPayException as exe:
133133
raise PayoutRecipientQueryException(
134134
"failed to serialize PayoutRecipients object : %s" % str(exe),
135-
exe.get_api_code(),
135+
api_code=exe.get_api_code(),
136136
)
137137

138138
try:
@@ -166,7 +166,7 @@ def update(self, recipient_id: str, recipient: PayoutRecipient) -> PayoutRecipie
166166
except BitPayException as exe:
167167
raise PayoutRecipientUpdateException(
168168
"failed to serialize PayoutRecipients object : %s" % str(exe),
169-
exe.get_api_code(),
169+
api_code=exe.get_api_code(),
170170
)
171171

172172
try:
@@ -190,7 +190,7 @@ def delete(self, recipient_id: str) -> bool:
190190
except BitPayException as exe:
191191
raise PayoutRecipientCancellationException(
192192
"failed to serialize PayoutRecipients object : %s" % str(exe),
193-
exe.get_api_code(),
193+
api_code=exe.get_api_code(),
194194
)
195195
try:
196196
response_json = self.__bitpay_client.delete(
@@ -218,7 +218,7 @@ def request_notification(self, recipient_id: str) -> bool:
218218
except BitPayException as exe:
219219
raise PayoutRecipientNotificationException(
220220
"failed to serialize PayoutRecipients object : %s" % str(exe),
221-
exe.get_api_code(),
221+
api_code=exe.get_api_code(),
222222
)
223223

224224
try:

src/bitpay/clients/rate_client.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def get_rates(self) -> Rates:
2626
response_json = self.__bitpay_client.get("rates", None, False)
2727
except BitPayException as exe:
2828
raise RateQueryException(
29-
"failed to serialize Rates object : %s" % str(exe), exe.get_api_code()
29+
"failed to serialize Rates object : %s" % str(exe), api_code=exe.get_api_code()
3030
)
3131

3232
try:
@@ -57,7 +57,7 @@ def get_currency_rates(self, base_currency: str) -> Rates:
5757
)
5858
except BitPayException as exe:
5959
raise RateQueryException(
60-
"failed to serialize Rates object : %s" % str(exe), exe.get_api_code()
60+
"failed to serialize Rates object : %s" % str(exe), api_code=exe.get_api_code()
6161
)
6262

6363
try:
@@ -92,7 +92,7 @@ def get_currency_pair_rate(self, base_currency: str, currency: str) -> Rate:
9292
)
9393
except BitPayException as exe:
9494
raise RateQueryException(
95-
"failed to serialize Rates object : %s" % str(exe), exe.get_api_code()
95+
"failed to serialize Rates object : %s" % str(exe), api_code=exe.get_api_code()
9696
)
9797

9898
try:

0 commit comments

Comments
 (0)