Skip to content

Commit 3023652

Browse files
authored
Merge pull request #23 from mwarzybok-sumoheavy/feature/SP-527
SP-527 API Parity
2 parents 91d97de + 00f3692 commit 3023652

File tree

7 files changed

+362
-7
lines changed

7 files changed

+362
-7
lines changed

src/bitpay/client.py

Lines changed: 103 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Class Client
33
package Bitpay
44
author Antonio Buedo
5-
version 14.3.2203
5+
version 4.0.0
66
See bitpay.com/api for more information.
77
"""
88
import os
@@ -24,6 +24,7 @@
2424
from .environment import Environment
2525
from .models.facade import Facade
2626
from .models.bill.bill import Bill
27+
from .models.invoice.invoice_event_token import InvoiceEventToken
2728
from .models.rate.rate import Rate
2829
from .utils.guid_generator import GuidGenerator
2930
from .models.rate.rates import Rates
@@ -50,14 +51,18 @@ class Client:
5051
* See bitpay.com/api for more information.
5152
"""
5253

53-
__guid_generator = None
54-
__bitpay_client = None
55-
__token_container = None
54+
__bitpay_client = BitPayClient
55+
__token_container = TokenContainer
56+
__guid_generator = GuidGenerator
5657

57-
def __init__(self, bitpay_client, token_container, guid_generator):
58+
def __init__(
59+
self, bitpay_client: BitPayClient, token_container: TokenContainer, guid_generator: GuidGenerator = None
60+
):
5861
try:
5962
self.__bitpay_client = bitpay_client
6063
self.__token_container = token_container
64+
if guid_generator is None:
65+
guid_generator = GuidGenerator()
6166
self.__guid_generator = guid_generator
6267
except Exception as exe:
6368
raise BitPayException("failed to initiate client: " + str(exe))
@@ -180,6 +185,25 @@ def get_invoice(
180185
client = self.create_invoice_client()
181186
return client.get(invoice_id, facade, sign_request)
182187

188+
def get_invoice_by_guid(
189+
self, guid: str, facade: str = Facade.MERCHANT, sign_request: bool = True
190+
) -> Invoice:
191+
"""
192+
Retrieve a BitPay invoice by invoice id using the specified facade.
193+
The client must have been previously authorized for the specified
194+
facade (the public facade requires no authorization)
195+
196+
:param str guid: The id of the invoice to retrieve
197+
:param str facade: The facade used to create it
198+
:param bool sign_request: Signed request
199+
:return: A BitPay Invoice object
200+
:rtype: Invoice
201+
:raises BitPayException
202+
:raises InvoiceQueryException
203+
"""
204+
client = self.create_invoice_client()
205+
return client.get_by_guid(guid, facade, sign_request)
206+
183207
def get_invoices(
184208
self,
185209
date_start: str,
@@ -209,6 +233,21 @@ def get_invoices(
209233
date_start, date_end, status, order_id, limit, offset
210234
)
211235

236+
def get_invoice_event_token(self, invoice_id: str) -> InvoiceEventToken:
237+
"""
238+
Retrieves a bus token which can be used to subscribe to invoice events.
239+
240+
:param str invoice_id: The id of the invoice for which you want to fetch an event token.
241+
:return: Invoice Event Token.
242+
:rtype: InvoiceEventToken
243+
:raises BitPayException
244+
:raises InvoiceQueryException
245+
"""
246+
client = self.create_invoice_client()
247+
return client.get_event_token(
248+
invoice_id
249+
)
250+
212251
def update_invoice(
213252
self,
214253
invoice_id: str,
@@ -246,6 +285,21 @@ def cancel_invoice(self, invoice_id: str, force_cancel: bool = False) -> Invoice
246285
client = self.create_invoice_client()
247286
return client.cancel(invoice_id, force_cancel)
248287

288+
def cancel_invoice_by_guid(self, guid: str, force_cancel: bool = False) -> Invoice:
289+
"""
290+
Delete a previously created BitPay invoice.
291+
292+
:param str guid: The GUID of the BitPay invoice to be canceled.
293+
:param bool force_cancel: Query param that will cancel the invoice even if
294+
no contact information is present
295+
:return: A BitPay generated Invoice object.
296+
:rtype: Invoice
297+
:raises BitPayException
298+
:raises InvoiceCancellationException
299+
"""
300+
client = self.create_invoice_client()
301+
return client.cancel_by_guid(guid, force_cancel)
302+
249303
def pay_invoice(self, invoice_id: str, complete: bool = True) -> Invoice:
250304
"""
251305
Pay an invoice with a mock transaction - it works only for test environment.
@@ -281,6 +335,7 @@ def create_refund(
281335
immediate: bool = False,
282336
buyer_pays_refund_fee: bool = False,
283337
reference: str = None,
338+
guid: str = None
284339
) -> Refund:
285340
"""
286341
Create a refund for a BitPay invoice.
@@ -296,14 +351,16 @@ def create_refund(
296351
:param str reference: Present only if specified in the request to create the refund.
297352
This is your reference label for this refund. It will be passed-through on each response for you to identify
298353
the refund in your system. Maximum string length is 100 characters.
354+
:param str guid: Variable provided by the merchant and designed to be used by the merchant
355+
to correlate the refund with a refund ID in their system.
299356
:return: An updated Refund Object
300357
:rtype: Refund
301358
:raises BitPayException
302359
:raises RefundCreationException
303360
"""
304361
client = self.create_refund_client()
305362
return client.create(
306-
invoice_id, amount, preview, immediate, buyer_pays_refund_fee, reference
363+
invoice_id, amount, preview, immediate, buyer_pays_refund_fee, reference, guid
307364
)
308365

309366
def get_refund(self, refund_id: str) -> Refund:
@@ -319,6 +376,19 @@ def get_refund(self, refund_id: str) -> Refund:
319376
client = self.create_refund_client()
320377
return client.get(refund_id)
321378

379+
def get_refund_by_guid(self, guid: str) -> Refund:
380+
"""
381+
Retrieve a previously made refund request on a BitPay invoice.
382+
383+
:param str guid: The BitPay refund GUID.
384+
:return: BitPay Refund object with the associated Refund object.
385+
:rtype: Refund
386+
:raises BitPayException
387+
:raises RefundQueryException
388+
"""
389+
client = self.create_refund_client()
390+
return client.get_by_guid(guid)
391+
322392
def get_refunds(self, invoice_id: str) -> List[Refund]:
323393
"""
324394
Retrieve all refund requests on a BitPay invoice.
@@ -346,6 +416,20 @@ def update_refund(self, refund_id: str, status: str) -> Refund:
346416
client = self.create_refund_client()
347417
return client.update(refund_id, status)
348418

419+
def update_refund_by_guid(self, refund_guid: str, status: str) -> Refund:
420+
"""
421+
Update the status of a BitPay invoice refund.
422+
423+
:param str refund_guid: BitPay refund GUID.
424+
:param str status: The new status for the refund to be updated
425+
:return: A BitPay generated Refund object.
426+
:rtype: Refund
427+
:raises BitPayException
428+
:raises RefundUpdateException
429+
"""
430+
client = self.create_refund_client()
431+
return client.update_by_guid(refund_guid, status)
432+
349433
def cancel_refund(self, refund_id: str) -> Refund:
350434
"""
351435
Cancel a previously submitted refund request on a BitPay invoice.
@@ -359,6 +443,19 @@ def cancel_refund(self, refund_id: str) -> Refund:
359443
client = self.create_refund_client()
360444
return client.cancel(refund_id)
361445

446+
def cancel_refund_by_guid(self, guid: str) -> Refund:
447+
"""
448+
Cancel a previously submitted refund request on a BitPay invoice.
449+
450+
:param str guid: The refund GUID for the refund to be canceled.
451+
:return: Cancelled refund Object.
452+
:rtype: Refund
453+
:raises BitPayException
454+
:raises RefundCancellationException
455+
"""
456+
client = self.create_refund_client()
457+
return client.cancel_by_guid(guid)
458+
362459
def request_refund_notification(self, refund_id: str) -> bool:
363460
"""
364461
Send a refund notification.

src/bitpay/client/invoice_client.py

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from bitpay.exceptions.invoice_update_exception import InvoiceUpdateException
1515
from bitpay.models.facade import Facade
1616
from bitpay.models.invoice.invoice import Invoice
17+
from bitpay.models.invoice.invoice_event_token import InvoiceEventToken
1718
from bitpay.utils.guid_generator import GuidGenerator
1819
from bitpay.utils.token_container import TokenContainer
1920

@@ -48,6 +49,9 @@ def create(
4849
:raises InvoiceCreationException
4950
"""
5051
try:
52+
if invoice.get_guid() is None:
53+
invoice.set_guid(self.__guid_generator.execute())
54+
5155
invoice.set_token(self.__token_container.get_access_token(facade))
5256
invoice_json = invoice.to_json()
5357
response_json = self.__bitpay_client.post(
@@ -114,6 +118,47 @@ def get(
114118

115119
return invoice
116120

121+
def get_by_guid(
122+
self, guid: str, facade: str = Facade.MERCHANT, sign_request: bool = True
123+
) -> Invoice:
124+
"""
125+
Retrieve a BitPay invoice by invoice id using the specified facade.
126+
The client must have been previously authorized for the specified
127+
facade (the public facade requires no authorization)
128+
129+
:param str guid: The GUID of the invoice to retrieve
130+
:param str facade: The facade used to create it
131+
:param bool sign_request: Signed request
132+
:return: A BitPay Invoice object
133+
:rtype: Invoice
134+
:raises BitPayException
135+
:raises InvoiceQueryException
136+
"""
137+
try:
138+
params = {"token": self.__token_container.get_access_token(facade)}
139+
response_json = self.__bitpay_client.get(
140+
"invoices/guid/%s" % guid, params, sign_request
141+
)
142+
except BitPayException as exe:
143+
raise InvoiceQueryException(
144+
"failed to serialize Invoice object : " "%s" % str(exe),
145+
exe.get_api_code(),
146+
)
147+
except Exception as exe:
148+
raise InvoiceQueryException(
149+
"failed to serialize Invoice object :" " %s" % str(exe)
150+
)
151+
152+
try:
153+
invoice = Invoice(**response_json)
154+
except Exception as exe:
155+
raise InvoiceQueryException(
156+
"failed to deserialize BitPay server response"
157+
" (Invoice) : %s" % str(exe)
158+
)
159+
160+
return invoice
161+
117162
def get_invoices(
118163
self,
119164
date_start: str,
@@ -267,6 +312,78 @@ def cancel(self, invoice_id: str, force_cancel: bool = False) -> Invoice:
267312
)
268313
return invoice
269314

315+
def cancel_by_guid(self, guid, force_cancel) -> Invoice:
316+
"""
317+
Delete a previously created BitPay invoice.
318+
319+
:param str guid: The GUID of the BitPay invoice to be canceled.
320+
:param bool force_cancel: Query param that will cancel the invoice even if
321+
no contact information is present
322+
:return: A BitPay generated Invoice object.
323+
:rtype: Invoice
324+
:raises BitPayException
325+
:raises InvoiceCancellationException
326+
"""
327+
try:
328+
params = {
329+
"token": self.__token_container.get_access_token(Facade.MERCHANT),
330+
"forceCancel": force_cancel,
331+
}
332+
response_json = self.__bitpay_client.delete(
333+
"invoices/guid/%s" % guid, params
334+
)
335+
except BitPayException as exe:
336+
raise InvoiceCancellationException(
337+
"failed to serialize Invoice object : %s" % str(exe), exe.get_api_code()
338+
)
339+
except Exception as exe:
340+
raise InvoiceCancellationException(
341+
"failed to serialize Invoice object : %s" % str(exe)
342+
)
343+
344+
try:
345+
invoice = Invoice(**response_json)
346+
except Exception as exe:
347+
raise InvoiceCancellationException(
348+
"failed to deserialize BitPay server"
349+
" response (Invoice) : %s" % str(exe)
350+
)
351+
return invoice
352+
353+
def get_event_token(self, invoice_id: str) -> InvoiceEventToken:
354+
"""
355+
Retrieves a bus token which can be used to subscribe to invoice events.
356+
357+
:param str invoice_id: The id of the invoice for which you want to fetch an event token.
358+
:return: Invoice Event Token.
359+
:rtype: InvoiceEventToken
360+
:raises BitPayException
361+
:raises InvoiceQueryException
362+
"""
363+
try:
364+
params = {
365+
"token": self.__token_container.get_access_token(Facade.MERCHANT),
366+
}
367+
response_json = self.__bitpay_client.delete(
368+
"invoices/%s/events" % invoice_id, params
369+
)
370+
except BitPayException as exe:
371+
raise InvoiceCancellationException(
372+
"failed to serialize Invoice object : %s" % str(exe), exe.get_api_code()
373+
)
374+
except Exception as exe:
375+
raise InvoiceCancellationException(
376+
"failed to serialize Invoice object : %s" % str(exe)
377+
)
378+
379+
try:
380+
return InvoiceEventToken(**response_json)
381+
except Exception as exe:
382+
raise InvoiceCancellationException(
383+
"failed to deserialize BitPay server"
384+
" response (Invoice) : %s" % str(exe)
385+
)
386+
270387
def pay(self, invoice_id: str, complete: bool = True) -> Invoice:
271388
"""
272389
Pay an invoice with a mock transaction - it works only for test environment.

src/bitpay/client/payout_recipient_client.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ def submit(self, recipients: PayoutRecipients) -> List[PayoutRecipient]:
5050
:raises PayoutRecipientCreationException
5151
"""
5252
try:
53+
if recipients.get_guid() is None:
54+
recipients.set_guid(self.__guid_generator.execute())
55+
5356
recipients.set_token(self.__token_container.get_access_token(Facade.PAYOUT))
5457

5558
response_json = self.__bitpay_client.post(

0 commit comments

Comments
 (0)