diff --git a/CHANGELOG.md b/CHANGELOG.md index b8f3d641..d6217f49 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ Given a version number MAJOR.MINOR.PATCH, increment: ## [Unreleased] +### Added +- url attribute to IssuingToken resource ## [0.28.0] - 2026-06-24 ### Added diff --git a/starkinfra/issuingbalance/__issuingbalance.py b/starkinfra/issuingbalance/__issuingbalance.py index d39ddd22..bca863b4 100644 --- a/starkinfra/issuingbalance/__issuingbalance.py +++ b/starkinfra/issuingbalance/__issuingbalance.py @@ -12,14 +12,18 @@ class IssuingBalance(Resource): - id [string]: unique id returned when IssuingBalance is created. ex: "5656565656565656" - amount [integer]: current balance amount of the Workspace in cents. ex: 200 (= R$ 2.00) - currency [string]: currency of the current Workspace. Expect others to be added eventually. ex: "BRL" + - limit [integer]: Spending limit of the balance + - max_limit [integer]: Maximum spending limit. This field is currently always equal to limit - updated [datetime.datetime]: latest update datetime for the IssuingBalance. ex: datetime.datetime(2020, 3, 10, 10, 30, 0, 0) """ - def __init__(self, id, amount, currency, updated): + def __init__(self, id, amount, currency, updated, limit=None, max_limit=None): Resource.__init__(self, id=id) self.amount = amount self.currency = currency + self.limit = limit + self.max_limit = max_limit self.updated = updated diff --git a/starkinfra/issuingbillinginvoice/__issuingbillinginvoice.py b/starkinfra/issuingbillinginvoice/__issuingbillinginvoice.py index 79ebd9d2..01e8cfac 100644 --- a/starkinfra/issuingbillinginvoice/__issuingbillinginvoice.py +++ b/starkinfra/issuingbillinginvoice/__issuingbillinginvoice.py @@ -6,6 +6,9 @@ class IssuingBillingInvoice(Resource): """# IssuingBillingInvoice object Check out our API Documentation at https://starkinfra.com/docs/api#issuing-billing-invoice + ## Attributes (return-only): + - fine [float]: Fine percentage applied when paid after the due date. ex: 2.0 + - interest [float]: Monthly interest percentage applied when paid after the due date. ex: 1.0 """ def __init__(self, id=None, name=None, tax_id=None, fine=None, interest=None, status=None, amount=None, diff --git a/starkinfra/issuingbillingtransaction/__issuingbillingtransaction.py b/starkinfra/issuingbillingtransaction/__issuingbillingtransaction.py index f7be5d86..87147c6e 100644 --- a/starkinfra/issuingbillingtransaction/__issuingbillingtransaction.py +++ b/starkinfra/issuingbillingtransaction/__issuingbillingtransaction.py @@ -6,6 +6,9 @@ class IssuingBillingTransaction(Resource): """# IssuingBillingTransaction object Check out our API Documentation at https://starkinfra.com/docs/api#issuing-billing-transaction + ## Attributes (return-only): + - rate [float]: Conversion rate applied to international transactions + - tax [integer]: IOF amount in cents applied to the transaction """ def __init__(self, id=None, amount=None, invoice_id=None, installment=None, installment_count=None, diff --git a/starkinfra/issuingcard/__issuingcard.py b/starkinfra/issuingcard/__issuingcard.py index 9346a308..36d6a2c6 100644 --- a/starkinfra/issuingcard/__issuingcard.py +++ b/starkinfra/issuingcard/__issuingcard.py @@ -28,6 +28,7 @@ class IssuingCard(Resource): - holder_id [string]: card holder unique id. ex: "5656565656565656" - type [string]: card type. ex: "virtual" - status [string]: current IssuingCard status. ex: "active", "blocked", "canceled", "expired" + - is_pin_defined [bool]: Whether the card has a PIN defined. Returned only when "expand=isPinDefined" is informed in the request - number [string]: [EXPANDABLE] masked card number. Expand to unmask the value. ex: "123" - security_code [string]: [EXPANDABLE] masked card verification value (cvv). Expand to unmask the value. ex: "123" - expiration [datetime.datetime]: [EXPANDABLE] masked card expiration datetime. Expand to unmask the value. ex: datetime.datetime(2020, 3, 10, 10, 30, 0, 0) @@ -37,8 +38,8 @@ class IssuingCard(Resource): def __init__(self, holder_name, holder_tax_id, holder_external_id, display_name=None, rules=None, product_id=None, tags=None, street_line_1=None, street_line_2=None, district=None, city=None, state_code=None, - zip_code=None, id=None, holder_id=None, type=None, status=None, number=None, security_code=None, - expiration=None, created=None, updated=None): + zip_code=None, id=None, holder_id=None, type=None, status=None, is_pin_defined=None, number=None, + security_code=None, expiration=None, created=None, updated=None): Resource.__init__(self, id=id) self.holder_name = holder_name @@ -57,6 +58,7 @@ def __init__(self, holder_name, holder_tax_id, holder_external_id, display_name= self.holder_id = holder_id self.type = type self.status = status + self.is_pin_defined = is_pin_defined self.number = number self.security_code = security_code self.expiration = check_datetime(expiration) diff --git a/starkinfra/issuingproduct/__issuingproduct.py b/starkinfra/issuingproduct/__issuingproduct.py index 29930cbc..fddf97dd 100644 --- a/starkinfra/issuingproduct/__issuingproduct.py +++ b/starkinfra/issuingproduct/__issuingproduct.py @@ -12,16 +12,18 @@ class IssuingProduct(Resource): - funding_type [string]: type of funding used for payment. ex: "credit", "debit" - holder_type [string]: holder type. ex: "business", "individual" - code [string]: internal code from card flag informing the product. ex: "MRW", "MCO", "MWB", "MCS" + - customer_type [string]: Same as holderType. Kept for backward compatibility - created [datetime.datetime]: creation datetime for the IssuingProduct. ex: datetime.datetime(2020, 3, 10, 10, 30, 0, 0) """ - def __init__(self, id=None, network=None, funding_type=None, holder_type=None, code=None, created=None): + def __init__(self, id=None, network=None, funding_type=None, holder_type=None, code=None, customer_type=None, created=None): Resource.__init__(self, id=id) self.network = network self.funding_type = funding_type self.holder_type = holder_type self.code = code + self.customer_type = customer_type self.created = created diff --git a/starkinfra/issuingpurchase/__issuingpurchase.py b/starkinfra/issuingpurchase/__issuingpurchase.py index ccd6bf0d..6af97319 100644 --- a/starkinfra/issuingpurchase/__issuingpurchase.py +++ b/starkinfra/issuingpurchase/__issuingpurchase.py @@ -26,6 +26,7 @@ class IssuingPurchase(Resource): - merchant_currency_symbol [string]: merchant currency symbol. ex: "$" - merchant_category_code [string]: merchant category code. ex: "fastFoodRestaurants" - merchant_category_type [string]: merchant category type. ex "food" + - merchant_category_number [integer]: MCC number of the merchant category. ex: 5814 - merchant_country_code [string]: merchant country code. ex: "USA" - acquirer_id [string]: acquirer ID. ex: "5656565656565656" - merchant_id [string]: merchant ID. ex: "5656565656565656" @@ -34,6 +35,7 @@ class IssuingPurchase(Resource): - wallet_id [string]: virtual wallet ID. ex: "5656565656565656" - method_code [string]: method code. Options: "chip", "token", "server", "manual", "magstripe" or "contactless" - score [float]: internal score calculated for the authenticity of the purchase. None in case of insufficient data. ex: 7.6 + - confirmed [datetime.datetime]: Confirmation datetime. Null until the purchase is confirmed. ex: datetime.datetime(2020, 3, 10, 10, 30, 0, 0) - end_to_end_id [string]: Unique id used to identify the transaction through all of its life cycle, even before the purchase is denied or approved and gets its usual id. ex: "679cd385-642b-49d0-96b7-89491e1249a5" - tags [list of strings]: list of strings for tagging returned by the sub-issuer during the authorization. ex: ["travel", "food"] ## Attributes (IssuingPurchase only): @@ -56,8 +58,9 @@ def __init__(self, holder_name=None, product_id=None, card_id=None, card_ending= installment_count=None, amount=None, tax=None, issuer_amount=None, issuer_currency_code=None, issuer_currency_symbol=None, merchant_amount=None, merchant_currency_code=None, merchant_currency_symbol=None, merchant_category_code=None, merchant_category_type=None, - merchant_country_code=None, acquirer_id=None, merchant_id=None, merchant_name=None, merchant_fee=None, - wallet_id=None, method_code=None, score=None, end_to_end_id=None, tags=None, id=None, + merchant_category_number=None, merchant_country_code=None, acquirer_id=None, merchant_id=None, + merchant_name=None, merchant_fee=None, wallet_id=None, method_code=None, score=None, confirmed=None, + end_to_end_id=None, tags=None, id=None, issuing_transaction_ids=None, status=None, description=None, metadata=None, zip_code=None, updated=None, created=None, is_partial_allowed=None, card_tags=None, holder_id=None, holder_tags=None): Resource.__init__(self, id=id) @@ -78,6 +81,7 @@ def __init__(self, holder_name=None, product_id=None, card_id=None, card_ending= self.merchant_currency_symbol = merchant_currency_symbol self.merchant_category_code = merchant_category_code self.merchant_category_type = merchant_category_type + self.merchant_category_number = merchant_category_number self.merchant_country_code = merchant_country_code self.acquirer_id = acquirer_id self.merchant_id = merchant_id @@ -86,6 +90,7 @@ def __init__(self, holder_name=None, product_id=None, card_id=None, card_ending= self.wallet_id = wallet_id self.method_code = method_code self.score = score + self.confirmed = check_datetime(confirmed) self.end_to_end_id = end_to_end_id self.tags = tags self.issuing_transaction_ids = issuing_transaction_ids diff --git a/starkinfra/issuingrule/__issuingrule.py b/starkinfra/issuingrule/__issuingrule.py index 7fa1125e..8349d6f3 100644 --- a/starkinfra/issuingrule/__issuingrule.py +++ b/starkinfra/issuingrule/__issuingrule.py @@ -22,10 +22,13 @@ class IssuingRule(Resource): - counter_amount [integer]: current rule spent amount. ex: 1000 - currency_symbol [string]: currency symbol. ex: "R$" - currency_name [string]: currency name. ex: "Brazilian Real" + - schedule [string]: Optional schedule dictating when the rule can be used. Some examples: "everyday from 09:00 to 18:00 in America/Sao_Paulo" - every day, 09:00-18:00 Sao Paulo time; "every monday, wednesday, friday from 08:00 to 12:00 in America/Sao_Paulo" - only those weekdays, mornings; "every saturday, sunday" - weekends, all day, in UTC + - purposes [list of strings]: Optional list of transaction purposes the rule applies to. Options: "purchase", "withdrawal", "verification". The rule then limits only purchases of those purposes; omit it to allow any purposes. Example: ["purchase", "verification"] if you want us to automatically deny withdrawal. """ def __init__(self, name, amount, id=None, interval=None, currency_code=None, categories=None, countries=None, - methods=None, counter_amount=None, currency_symbol=None, currency_name=None): + methods=None, counter_amount=None, currency_symbol=None, currency_name=None, schedule=None, + purposes=None): Resource.__init__(self, id=id) self.name = name @@ -38,6 +41,8 @@ def __init__(self, name, amount, id=None, interval=None, currency_code=None, cat self.counter_amount = counter_amount self.currency_symbol = currency_symbol self.currency_name = currency_name + self.schedule = schedule + self.purposes = purposes _resource = {"class": IssuingRule, "name": "IssuingRule"} diff --git a/starkinfra/issuingstock/__issuingstock.py b/starkinfra/issuingstock/__issuingstock.py index 655ee2e0..369cd7e0 100644 --- a/starkinfra/issuingstock/__issuingstock.py +++ b/starkinfra/issuingstock/__issuingstock.py @@ -11,16 +11,18 @@ class IssuingStock(Resource): - balance [integer]: [EXPANDABLE] current stock balance. ex: 1000 - design_id [string]: IssuingDesign unique id. ex: "5656565656565656" - embosser_id [string]: Embosser unique id. ex: "5656565656565656" + - embosser_name [string]: Name of the embosser that holds this stock - updated [datetime.datetime]: latest update datetime for the IssuingStock. ex: datetime.datetime(2020, 3, 10, 10, 30, 0, 0) - created [datetime.datetime]: creation datetime for the IssuingStock. ex: datetime.datetime(2020, 3, 10, 10, 30, 0, 0) """ - def __init__(self, balance=None, design_id=None, embosser_id=None, id=None, created=None, updated=None): + def __init__(self, balance=None, design_id=None, embosser_id=None, embosser_name=None, id=None, created=None, updated=None): Resource.__init__(self, id=id) self.balance = balance self.design_id = design_id self.embosser_id = embosser_id + self.embosser_name = embosser_name self.created = check_datetime(created) self.updated = check_datetime(updated) diff --git a/starkinfra/issuingtoken/__issuingtoken.py b/starkinfra/issuingtoken/__issuingtoken.py index d9b61a0c..d340f950 100644 --- a/starkinfra/issuingtoken/__issuingtoken.py +++ b/starkinfra/issuingtoken/__issuingtoken.py @@ -1,5 +1,5 @@ from json import dumps -from starkinfra.utils import rest +from ..utils import rest from starkcore.utils.api import api_json from ..utils.parse import parse_and_verify from starkcore.utils.resource import Resource @@ -14,6 +14,8 @@ class IssuingToken(Resource): - wallet_id [string]: wallet provider which the token is bounded to. ex: "google" - wallet_name [string]: wallet name. ex: "GOOGLE" - merchant_id [string]: merchant unique id. ex: "5656565656565656" + - wallet_device_score [float]: Device score informed by the digital wallet. + - wallet_account_score [float]: Account score informed by the digital wallet ## Attributes (IssuingToken only): - id [string]: unique id returned when IssuingToken is created. ex: "5656565656565656" - external_id [string]: a unique string among all your IssuingTokens, used to avoid resource duplication. ex: "DSHRMC00002626944b0e3b539d4d459281bdba90c2588791" @@ -33,7 +35,8 @@ class IssuingToken(Resource): - wallet_instance_id [string]: unique id refered to the wallet app in the current device. ex: "71583be4777eb89aaf0345eebeb82594f096615ed17862d0" """ - def __init__(self, card_id=None, wallet_id=None, wallet_name=None, merchant_id=None, id=None, + def __init__(self, card_id=None, wallet_id=None, wallet_name=None, merchant_id=None, wallet_device_score=None, + wallet_account_score=None, id=None, external_id=None, tags=None, status=None, updated=None, created=None, activation_code=None, method_code=None, device_type=None, device_name=None, device_serial_number=None, device_os_name=None, device_os_version=None, device_imei=None, wallet_instance_id=None): @@ -43,11 +46,13 @@ def __init__(self, card_id=None, wallet_id=None, wallet_name=None, merchant_id=N self.wallet_id = wallet_id self.wallet_name = wallet_name self.merchant_id = merchant_id + self.wallet_device_score = wallet_device_score + self.wallet_account_score = wallet_account_score self.external_id = external_id self.tags = tags self.status = status - self.updated = updated - self.created = created + self.updated = check_datetime(updated) + self.created = check_datetime(created) self.activation_code = activation_code self.method_code = method_code self.device_type = device_type @@ -75,7 +80,7 @@ def get(id, user=None): return rest.get_id(resource=_resource, id=id, user=user) -def query(limit=None, after=None, before=None, status=None, card_ids=None, tags=None, ids=None, user=None, external_ids=None): +def query(limit=None, after=None, before=None, status=None, card_ids=None, tags=None, ids=None, external_ids=None, user=None): """# Retrieve IssuingTokens Receive a generator of IssuingToken objects previously created in the Stark Infra API ## Parameters (optional): @@ -86,8 +91,8 @@ def query(limit=None, after=None, before=None, status=None, card_ids=None, tags= - card_ids [list of strings, default None]: list of card_ids to filter retrieved objects. ex: ["5656565656565656", "4545454545454545"] - tags [list of strings, default None]: list of strings for tagging. ex: ["travel", "food"] - ids [list of strings, default None]: list of ids to filter retrieved objects. ex: ["5656565656565656", "4545454545454545"] - - user [Organization/Project object, default None]: Organization or Project object. Not necessary if starkinfra.user was set before function call - external_ids [list of strings, default None]: external IDs. ex: ["DSHRMC00002626944b0e3b539d4d459281bdba90c2588791", "DSHRMC00002626941c531164a0b14c66ad9602ee716f1e85"] + - user [Organization/Project object, default None]: Organization or Project object. Not necessary if starkinfra.user was set before function call ## Return: - generator of IssuingToken objects with updated attributes """ @@ -100,12 +105,12 @@ def query(limit=None, after=None, before=None, status=None, card_ids=None, tags= card_ids=card_ids, tags=tags, ids=ids, - user=user, external_ids=external_ids, + user=user, ) -def page(cursor=None, limit=None, after=None, before=None, status=None, card_ids=None, tags=None, ids=None, user=None, external_ids=None): +def page(cursor=None, limit=None, after=None, before=None, status=None, card_ids=None, tags=None, ids=None, external_ids=None, user=None): """# Retrieve paged IssuingTokens Receive a list of IssuingToken objects previously created in the Stark Infra API and the cursor to the next page. Use this function instead of query if you want to manually page your requests. @@ -118,8 +123,8 @@ def page(cursor=None, limit=None, after=None, before=None, status=None, card_ids - card_ids [list of strings, default None]: list of card_ids to filter retrieved objects. ex: ["5656565656565656", "4545454545454545"] - tags [list of strings, default None]: list of strings for tagging. ex: ["travel", "food"] - ids [list of strings, default None]: list of ids to filter retrieved objects. ex: ["5656565656565656", "4545454545454545"] - - user [Organization/Project object, default None]: Organization or Project object. Not necessary if starkinfra.user was set before function call - external_ids [list of strings, default None]: external IDs. ex: ["5656565656565656", "4545454545454545"] + - user [Organization/Project object, default None]: Organization or Project object. Not necessary if starkinfra.user was set before function call ## Return: - list of IssuingToken objects with updated attributes - cursor to retrieve the next page of IssuingToken objects @@ -134,8 +139,8 @@ def page(cursor=None, limit=None, after=None, before=None, status=None, card_ids card_ids=card_ids, tags=tags, ids=ids, - user=user, external_ids=external_ids, + user=user, ) diff --git a/starkinfra/merchantcategory/__merchantcategory.py b/starkinfra/merchantcategory/__merchantcategory.py index dd9d8e16..07519f85 100644 --- a/starkinfra/merchantcategory/__merchantcategory.py +++ b/starkinfra/merchantcategory/__merchantcategory.py @@ -14,13 +14,15 @@ class MerchantCategory(SubResource): ## Attributes (return-only): - name [string]: category's name. ex: "Veterinary services", "Fast food restaurants" - number [string]: category's number. ex: "742", "5814" + - group [string]: category's group. ex: "pets", "food" """ - def __init__(self, code=None, type=None, name=None, number=None): + def __init__(self, code=None, type=None, name=None, number=None, group=None): self.code = code self.type = type self.name = name self.number = number + self.group = group _resource = {"class": MerchantCategory, "name": "MerchantCategory"} diff --git a/tests/sdk/testIssuingToken.py b/tests/sdk/testIssuingToken.py index 61e42d6e..17b105e9 100644 --- a/tests/sdk/testIssuingToken.py +++ b/tests/sdk/testIssuingToken.py @@ -50,10 +50,11 @@ def test_success(self): self.assertEqual(canceled_token.id, str(canceled_token.id)) -class TestIssuingTokenParseRight(TestCase): +class TestIssuingTokenProcess(TestCase): content = "{\"deviceName\": \"My phone\", \"methodCode\": \"manual\", \"walletName\": \"Google Pay\", \"activationCode\": \"\", \"deviceSerialNumber\": \"2F6D63\", \"deviceImei\": \"352099001761481\", \"deviceType\": \"Phone\", \"walletInstanceId\": \"1b24f24a24ba98e27d43e345b532a245e4723d7a9c4f624e\", \"deviceOsVersion\": \"4.4.4\", \"cardId\": \"5189831499972623\", \"deviceOsName\": \"Android\", \"merchantId\": \"12345678901\", \"walletId\": \"google\"}" valid_signature = "MEYCIQC4XbhjxEp9VhowLeg9JbSOo94FCRWE9GI7l7OuHh0bUwIhAJBuLDl5DAT9L4iMI0qYQ+PVmBIG5scxxvkWSsoWmwi4" invalid_signature = "MEUCIQDOpo1j+V40DNZK2URL2786UQK/8mDXon9ayEd8U0/l7AIgYXtIZJBTs8zCRR3vmted6Ehz/qfw1GRut/eYyvf1yOk=" + malformed_signature = "something is definitely wrong" def test_success(self): event = starkinfra.issuingtoken.parse( @@ -76,6 +77,13 @@ def test_invalid_signature(self): signature=self.invalid_signature, ) + def test_malformed_signature(self): + with self.assertRaises(InvalidSignatureError): + starkinfra.issuingtoken.parse( + content=self.content, + signature=self.malformed_signature, + ) + class TestIssuingTokenResponseAuthorization(TestCase):