Skip to content

Commit 00f3692

Browse files
SP-527 Make Python SDK at parity with API
1 parent 4a7a1e7 commit 00f3692

File tree

7 files changed

+353
-2
lines changed

7 files changed

+353
-2
lines changed

src/bitpay/client.py

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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
@@ -184,6 +185,25 @@ def get_invoice(
184185
client = self.create_invoice_client()
185186
return client.get(invoice_id, facade, sign_request)
186187

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+
187207
def get_invoices(
188208
self,
189209
date_start: str,
@@ -213,6 +233,21 @@ def get_invoices(
213233
date_start, date_end, status, order_id, limit, offset
214234
)
215235

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+
216251
def update_invoice(
217252
self,
218253
invoice_id: str,
@@ -250,6 +285,21 @@ def cancel_invoice(self, invoice_id: str, force_cancel: bool = False) -> Invoice
250285
client = self.create_invoice_client()
251286
return client.cancel(invoice_id, force_cancel)
252287

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+
253303
def pay_invoice(self, invoice_id: str, complete: bool = True) -> Invoice:
254304
"""
255305
Pay an invoice with a mock transaction - it works only for test environment.
@@ -285,6 +335,7 @@ def create_refund(
285335
immediate: bool = False,
286336
buyer_pays_refund_fee: bool = False,
287337
reference: str = None,
338+
guid: str = None
288339
) -> Refund:
289340
"""
290341
Create a refund for a BitPay invoice.
@@ -300,14 +351,16 @@ def create_refund(
300351
:param str reference: Present only if specified in the request to create the refund.
301352
This is your reference label for this refund. It will be passed-through on each response for you to identify
302353
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.
303356
:return: An updated Refund Object
304357
:rtype: Refund
305358
:raises BitPayException
306359
:raises RefundCreationException
307360
"""
308361
client = self.create_refund_client()
309362
return client.create(
310-
invoice_id, amount, preview, immediate, buyer_pays_refund_fee, reference
363+
invoice_id, amount, preview, immediate, buyer_pays_refund_fee, reference, guid
311364
)
312365

313366
def get_refund(self, refund_id: str) -> Refund:
@@ -323,6 +376,19 @@ def get_refund(self, refund_id: str) -> Refund:
323376
client = self.create_refund_client()
324377
return client.get(refund_id)
325378

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+
326392
def get_refunds(self, invoice_id: str) -> List[Refund]:
327393
"""
328394
Retrieve all refund requests on a BitPay invoice.
@@ -350,6 +416,20 @@ def update_refund(self, refund_id: str, status: str) -> Refund:
350416
client = self.create_refund_client()
351417
return client.update(refund_id, status)
352418

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+
353433
def cancel_refund(self, refund_id: str) -> Refund:
354434
"""
355435
Cancel a previously submitted refund request on a BitPay invoice.
@@ -363,6 +443,19 @@ def cancel_refund(self, refund_id: str) -> Refund:
363443
client = self.create_refund_client()
364444
return client.cancel(refund_id)
365445

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+
366459
def request_refund_notification(self, refund_id: str) -> bool:
367460
"""
368461
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)