diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b776f0b..b53bd4b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## NEXT RELEASE - Adds support to pass `end_shipper_id` on the buy call of a Shipment +- Migrates the Partner White Label (Referral) function from beta to the general library namespace and deprecates the beta functions ## v7.5.0 (2022-08-25) diff --git a/easypost/__init__.py b/easypost/__init__.py index 4bf8807d..eb6a4959 100644 --- a/easypost/__init__.py +++ b/easypost/__init__.py @@ -17,6 +17,7 @@ from easypost.pickup_rate import PickupRate from easypost.postage_label import PostageLabel from easypost.rate import Rate +from easypost.referral import Referral from easypost.refund import Refund from easypost.report import Report from easypost.scanform import ScanForm diff --git a/easypost/referral.py b/easypost/referral.py new file mode 100644 index 00000000..4acf8932 --- /dev/null +++ b/easypost/referral.py @@ -0,0 +1,174 @@ +from typing import ( + Any, + Dict, + List, + Optional, +) + +import requests + +from easypost.easypost_object import convert_to_easypost_object +from easypost.error import Error +from easypost.requestor import ( + RequestMethod, + Requestor, +) + + +class Referral: + @staticmethod + def create( + api_key: Optional[str] = None, + **params, + ) -> Dict[str, Any]: + """Create a referral user. + + This function requires the Partner User's API key. + """ + requestor = Requestor(local_api_key=api_key) + new_params = {"user": params} + response, api_key = requestor.request( + method=RequestMethod.POST, + url="/referral_customers", + params=new_params, + ) + return convert_to_easypost_object(response=response, api_key=api_key) + + @staticmethod + def update_email( + email, + user_id, + api_key: Optional[str] = None, + ) -> bool: + """Update a referral user. + + This function requires the Partner User's API key. + """ + requestor = Requestor(local_api_key=api_key) + url = f"/referral_customers/{user_id}" + wrapped_params = { + "user": { + "email": email, + } + } + _, _ = requestor.request( + method=RequestMethod.PUT, + url=url, + params=wrapped_params, + ) + + # Return true if succeeds, an error will be thrown if it fails + return True + + @staticmethod + def all( + api_key: Optional[str] = None, + **params, + ) -> List: + """Retrieve a list of referral users. + + This function requires the Partner User's API key. + """ + requestor = Requestor(local_api_key=api_key) + response, api_key = requestor.request( + method=RequestMethod.GET, + url="/referral_customers", + params=params, + ) + return convert_to_easypost_object(response=response, api_key=api_key) + + @staticmethod + def add_credit_card( + referral_api_key: str, + number: str, + expiration_month: int, + expiration_year: int, + cvc: str, + primary_or_secondary: str = "primary", + ) -> Dict[str, Any]: + """Add credit card to a referral user. + + This function requires the Referral User's API key. + """ + easypost_stripe_api_key = Referral._retrieve_easypost_stripe_api_key() + + try: + stripe_token = Referral._create_stripe_token( + number, expiration_month, expiration_year, cvc, easypost_stripe_api_key + ) + except Exception: + raise Error(message="Could not send card details to Stripe, please try again later") + + response = Referral._create_easypost_credit_card( + referral_api_key, + stripe_token.get("id", ""), + priority=primary_or_secondary, + ) + return convert_to_easypost_object(response) + + @staticmethod + def _retrieve_easypost_stripe_api_key() -> str: + """Retrieve EasyPost's Stripe public API key.""" + requestor = Requestor() + public_key, _ = requestor.request( + method=RequestMethod.GET, + url="/partners/stripe_public_key", + ) + return public_key.get("public_key", "") + + @staticmethod + def _create_stripe_token( + number: str, + expiration_month: int, + expiration_year: int, + cvc: str, + easypost_stripe_key: str, + ) -> Dict[str, Any]: + """Get credit card token from Stripe.""" + headers = { + # This Stripe endpoint only accepts URL form encoded bodies + "Content-type": "application/x-www-form-urlencoded", + } + + credit_card_dict = { + "card": { + "number": number, + "exp_month": expiration_month, + "exp_year": expiration_year, + "cvc": cvc, + } + } + + form_encoded_params = Requestor.form_encode_params(credit_card_dict) + url = "https://api.stripe.com/v1/tokens" + + stripe_response = requests.post( + url, + params=form_encoded_params, + headers=headers, + auth=requests.auth.HTTPBasicAuth(easypost_stripe_key, ""), + ) + return stripe_response.json() + + @staticmethod + def _create_easypost_credit_card( + referral_api_key: str, + stripe_object_id: str, + priority: str = "primary", + ) -> Dict[str, Any]: + """Submit Stripe credit card token to EasyPost.""" + requestor = Requestor(local_api_key=referral_api_key) + + params = { + "credit_card": { + "stripe_object_id": stripe_object_id, + "priority": priority, + } + } + + response, _ = requestor.request( + method=RequestMethod.POST, + params=params, + url="/credit_cards", + ) + return response diff --git a/tests/cassettes/test_beta_referral_add_credit_card.yaml b/tests/cassettes/test_beta_referral_add_credit_card.yaml new file mode 100644 index 00000000..744b8ab8 --- /dev/null +++ b/tests/cassettes/test_beta_referral_add_credit_card.yaml @@ -0,0 +1,202 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + authorization: + - + user-agent: + - + method: GET + uri: https://api.easypost.com/beta/partners/stripe_public_key + response: + body: + string: '{"public_key": "pk_x3JSr5eOVWNTLRej8cZDde9VQ0AT5"}' + headers: + cache-control: + - private, no-cache, no-store + content-length: + - '49' + content-type: + - application/json; charset=utf-8 + etag: + - W/"86cc970265a111486b443bf66ef85e91" + expires: + - '0' + pragma: + - no-cache + referrer-policy: + - strict-origin-when-cross-origin + strict-transport-security: + - max-age=31536000; includeSubDomains; preload + transfer-encoding: + - chunked + x-backend: + - easypost + x-content-type-options: + - nosniff + x-download-options: + - noopen + x-ep-request-uuid: + - fb9a52c063236813e787d9630008228f + x-frame-options: + - SAMEORIGIN + x-node: + - bigweb1nuq + x-permitted-cross-domain-policies: + - none + x-proxied: + - intlb1nuq 6aa9972c1e + - extlb2nuq 9ce216bfac + x-runtime: + - '0.016665' + x-version-label: + - easypost-202209142327-76d51e2e7e-master + x-xss-protection: + - 1; mode=block + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + Content-type: + - application/x-www-form-urlencoded + authorization: + - + user-agent: + - + method: POST + uri: https://api.stripe.com/v1/tokens?card%5Bexp_month%5D=05&card%5Bexp_year%5D=2028 + response: + body: + string: '{"id": "tok_0LiMLnDqT4huGUvdvZyWIgsK", "object": "token", "card": {"id": + "card_0LiMLnDqT4huGUvdGbeEFGjx", "object": "card", "address_city": null, "address_country": + null, "address_line1": null, "address_line1_check": null, "address_line2": + null, "address_state": null, "address_zip": null, "address_zip_check": null, + "brand": "Visa", "country": "US", "cvc_check": "unchecked", "dynamic_last4": + null, "exp_month": 5, "exp_year": 2028, "funding": "credit", "last4": "6170", + "name": null, "tokenization_method": null}, "client_ip": "", "created": + 1663264787, "livemode": true, "type": "card", "used": false}' + headers: + Connection: + - keep-alive + Content-Length: + - '719' + Content-Type: + - application/json + Date: + - Thu, 15 Sep 2022 17:59:47 GMT + Server: + - nginx + Strict-Transport-Security: + - max-age=63072000; includeSubDomains; preload + access-control-allow-credentials: + - 'true' + access-control-allow-methods: + - GET, POST, HEAD, OPTIONS, DELETE + access-control-allow-origin: + - '*' + access-control-expose-headers: + - Request-Id, Stripe-Manage-Version, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required + access-control-max-age: + - '300' + cache-control: + - no-cache, no-store + idempotency-key: + - f660924b-9bbb-40ff-ae1a-352c13e90f2c + original-request: + - req_YIhWYKCN7zRU06 + request-id: + - req_YIhWYKCN7zRU06 + stripe-should-retry: + - 'false' + stripe-version: + - '2020-08-27' + status: + code: 200 + message: OK +- request: + body: '{"credit_card": {"stripe_object_id": "tok_0LiMLnDqT4huGUvdvZyWIgsK", "priority": + "primary"}}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '92' + Content-Type: + - application/json + authorization: + - + user-agent: + - + method: POST + uri: https://api.easypost.com/beta/credit_cards + response: + body: + string: '{"id": "card_a81abaa3005e49d282cd0d4d1b52cca1", "disabled_at": null, + "object": "CreditCard", "name": null, "last4": "6170", "exp_month": 5, "exp_year": + 2028, "brand": "Visa"}' + headers: + cache-control: + - private, no-cache, no-store + content-length: + - '159' + content-type: + - application/json; charset=utf-8 + etag: + - W/"2ae1e2cf14e78c251587f5fd465c3ddc" + expires: + - '0' + pragma: + - no-cache + referrer-policy: + - strict-origin-when-cross-origin + strict-transport-security: + - max-age=31536000; includeSubDomains; preload + transfer-encoding: + - chunked + x-backend: + - easypost + x-content-type-options: + - nosniff + x-download-options: + - noopen + x-ep-request-uuid: + - fb9a52c063236813e787d963000822d1 + x-frame-options: + - SAMEORIGIN + x-node: + - bigweb5nuq + x-permitted-cross-domain-policies: + - none + x-proxied: + - intlb1nuq 6aa9972c1e + - extlb2nuq 9ce216bfac + x-runtime: + - '3.398040' + x-version-label: + - easypost-202209142327-76d51e2e7e-master + x-xss-protection: + - 1; mode=block + status: + code: 201 + message: Created +version: 1 diff --git a/tests/cassettes/test_beta_referral_user_all.yaml b/tests/cassettes/test_beta_referral_user_all.yaml new file mode 100644 index 00000000..29b53f35 --- /dev/null +++ b/tests/cassettes/test_beta_referral_user_all.yaml @@ -0,0 +1,100 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + authorization: + - + user-agent: + - + method: GET + uri: https://api.easypost.com/beta/referral_customers?page_size=5 + response: + body: + string: '{"has_more": true, "referral_customers": [{"id": "user_634b6daa05744bfaa205058f06864363", + "object": "User", "parent_id": null, "name": "Firstname Lastname", "phone_number": + "8888888888", "verified": true, "created_at": "2022-04-26T15:50:28Z", "balance": + "0.00000", "price_per_shipment": "0.00000", "recharge_amount": null, "secondary_recharge_amount": + null, "recharge_threshold": null, "has_billing_method": null, "cc_fee_rate": + "0.0325", "default_insurance_amount": "50.00", "insurance_fee_rate": "0.005", + "insurance_fee_minimum": "0.25", "email": "email@example.com", "children": + []}, {"id": "user_35cb81fb8af1454dabf1f6afa7330634", "object": "User", "parent_id": + null, "name": "Firstname Lastname", "phone_number": "8888888888", "verified": + true, "created_at": "2022-04-27T20:20:52Z", "balance": "0.00000", "price_per_shipment": + "0.00000", "recharge_amount": "100.00", "secondary_recharge_amount": "100.00", + "recharge_threshold": "0.00", "has_billing_method": true, "cc_fee_rate": "0.0325", + "default_insurance_amount": "50.00", "insurance_fee_rate": "0.005", "insurance_fee_minimum": + "0.25", "email": "email@example.com", "children": []}, {"id": "user_fa93cc16bcc24c078ee057ce82f38eed", + "object": "User", "parent_id": null, "name": "test test", "phone_number": + "8888888888", "verified": true, "created_at": "2022-04-28T22:34:38Z", "balance": + "0.00000", "price_per_shipment": "0.00000", "recharge_amount": null, "secondary_recharge_amount": + null, "recharge_threshold": null, "has_billing_method": null, "cc_fee_rate": + "0.0325", "default_insurance_amount": "50.00", "insurance_fee_rate": "0.005", + "insurance_fee_minimum": "0.25", "email": "email@example.com", "children": + []}, {"id": "user_4a22730cdc844ce1bc2efbed999c869f", "object": "User", "parent_id": + null, "name": "test test", "phone_number": "8888888888", "verified": true, + "created_at": "2022-04-29T19:35:33Z", "balance": "0.00000", "price_per_shipment": + "0.00000", "recharge_amount": null, "secondary_recharge_amount": null, "recharge_threshold": + null, "has_billing_method": null, "cc_fee_rate": "0.0325", "default_insurance_amount": + "50.00", "insurance_fee_rate": "0.005", "insurance_fee_minimum": "0.25", "email": + "test@test.com", "children": []}, {"id": "user_488e391395f4416196a31965fecac409", + "object": "User", "parent_id": null, "name": "Firstname Lastname", "phone_number": + "8888888888", "verified": true, "created_at": "2022-05-02T18:48:22Z", "balance": + "0.00000", "price_per_shipment": "0.00000", "recharge_amount": "100.00", "secondary_recharge_amount": + "100.00", "recharge_threshold": "0.00", "has_billing_method": true, "cc_fee_rate": + "0.0325", "default_insurance_amount": "50.00", "insurance_fee_rate": "0.005", + "insurance_fee_minimum": "0.25", "email": "email@example.com", "children": + []}]}' + headers: + cache-control: + - private, no-cache, no-store + content-length: + - '2573' + content-type: + - application/json; charset=utf-8 + etag: + - W/"279cdeec93979855fbae0e836593122e" + expires: + - '0' + pragma: + - no-cache + referrer-policy: + - strict-origin-when-cross-origin + strict-transport-security: + - max-age=31536000; includeSubDomains; preload + transfer-encoding: + - chunked + x-backend: + - easypost + x-canary: + - direct + x-content-type-options: + - nosniff + x-download-options: + - noopen + x-ep-request-uuid: + - fb9a52bd63236812e787d9620008223a + x-frame-options: + - SAMEORIGIN + x-node: + - bigweb7nuq + x-permitted-cross-domain-policies: + - none + x-proxied: + - intlb1nuq 6aa9972c1e + - extlb2nuq 9ce216bfac + x-runtime: + - '0.261582' + x-version-label: + - easypost-202209142327-76d51e2e7e-master + x-xss-protection: + - 1; mode=block + status: + code: 200 + message: OK +version: 1 diff --git a/tests/cassettes/test_beta_referral_user_create.yaml b/tests/cassettes/test_beta_referral_user_create.yaml new file mode 100644 index 00000000..3463f312 --- /dev/null +++ b/tests/cassettes/test_beta_referral_user_create.yaml @@ -0,0 +1,75 @@ +interactions: +- request: + body: '{"user": {"name": "test test", "email": "test@test.com", "phone": "8888888888"}}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '80' + Content-Type: + - application/json + authorization: + - + user-agent: + - + method: POST + uri: https://api.easypost.com/beta/referral_customers + response: + body: + string: '{"id": "user_2f55f59b52d44b97a4d2e7363fb3aa29", "object": "User", "parent_id": + null, "name": "test test", "phone_number": "", "verified": true, + "created_at": "2022-09-15T17:59:44Z", "balance": "0.00000", "price_per_shipment": + "0.00000", "recharge_amount": null, "secondary_recharge_amount": null, "recharge_threshold": + null, "has_billing_method": null, "cc_fee_rate": "0.0375", "default_insurance_amount": + "50.00", "insurance_fee_rate": "0.005", "insurance_fee_minimum": "0.25", "email": + "", "children": "", "api_keys": ""}' + headers: + cache-control: + - private, no-cache, no-store + content-length: + - '961' + content-type: + - application/json; charset=utf-8 + etag: + - W/"41869d3faa3d0def1ab04682c8619758" + expires: + - '0' + pragma: + - no-cache + referrer-policy: + - strict-origin-when-cross-origin + strict-transport-security: + - max-age=31536000; includeSubDomains; preload + transfer-encoding: + - chunked + x-backend: + - easypost + x-content-type-options: + - nosniff + x-download-options: + - noopen + x-ep-request-uuid: + - fb9a52bd63236810e787d9600008215d + x-frame-options: + - SAMEORIGIN + x-node: + - bigweb5nuq + x-permitted-cross-domain-policies: + - none + x-proxied: + - intlb2nuq 6aa9972c1e + - extlb2nuq 9ce216bfac + x-runtime: + - '0.967381' + x-version-label: + - easypost-202209142327-76d51e2e7e-master + x-xss-protection: + - 1; mode=block + status: + code: 201 + message: Created +version: 1 diff --git a/tests/cassettes/test_beta_referral_user_update.yaml b/tests/cassettes/test_beta_referral_user_update.yaml new file mode 100644 index 00000000..6b9e5de7 --- /dev/null +++ b/tests/cassettes/test_beta_referral_user_update.yaml @@ -0,0 +1,197 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + authorization: + - + user-agent: + - + method: GET + uri: https://api.easypost.com/beta/referral_customers + response: + body: + string: '{"has_more": true, "referral_customers": [{"id": "user_634b6daa05744bfaa205058f06864363", + "object": "User", "parent_id": null, "name": "Firstname Lastname", "phone_number": + "8888888888", "verified": true, "created_at": "2022-04-26T15:50:28Z", "balance": + "0.00000", "price_per_shipment": "0.00000", "recharge_amount": null, "secondary_recharge_amount": + null, "recharge_threshold": null, "has_billing_method": null, "cc_fee_rate": + "0.0325", "default_insurance_amount": "50.00", "insurance_fee_rate": "0.005", + "insurance_fee_minimum": "0.25", "email": "email@example.com", "children": + []}, {"id": "user_35cb81fb8af1454dabf1f6afa7330634", "object": "User", "parent_id": + null, "name": "Firstname Lastname", "phone_number": "8888888888", "verified": + true, "created_at": "2022-04-27T20:20:52Z", "balance": "0.00000", "price_per_shipment": + "0.00000", "recharge_amount": "100.00", "secondary_recharge_amount": "100.00", + "recharge_threshold": "0.00", "has_billing_method": true, "cc_fee_rate": "0.0325", + "default_insurance_amount": "50.00", "insurance_fee_rate": "0.005", "insurance_fee_minimum": + "0.25", "email": "email@example.com", "children": []}, {"id": "user_fa93cc16bcc24c078ee057ce82f38eed", + "object": "User", "parent_id": null, "name": "test test", "phone_number": + "8888888888", "verified": true, "created_at": "2022-04-28T22:34:38Z", "balance": + "0.00000", "price_per_shipment": "0.00000", "recharge_amount": null, "secondary_recharge_amount": + null, "recharge_threshold": null, "has_billing_method": null, "cc_fee_rate": + "0.0325", "default_insurance_amount": "50.00", "insurance_fee_rate": "0.005", + "insurance_fee_minimum": "0.25", "email": "email@example.com", "children": + []}, {"id": "user_4a22730cdc844ce1bc2efbed999c869f", "object": "User", "parent_id": + null, "name": "test test", "phone_number": "8888888888", "verified": true, + "created_at": "2022-04-29T19:35:33Z", "balance": "0.00000", "price_per_shipment": + "0.00000", "recharge_amount": null, "secondary_recharge_amount": null, "recharge_threshold": + null, "has_billing_method": null, "cc_fee_rate": "0.0325", "default_insurance_amount": + "50.00", "insurance_fee_rate": "0.005", "insurance_fee_minimum": "0.25", "email": + "test@test.com", "children": []}, {"id": "user_488e391395f4416196a31965fecac409", + "object": "User", "parent_id": null, "name": "Firstname Lastname", "phone_number": + "8888888888", "verified": true, "created_at": "2022-05-02T18:48:22Z", "balance": + "0.00000", "price_per_shipment": "0.00000", "recharge_amount": "100.00", "secondary_recharge_amount": + "100.00", "recharge_threshold": "0.00", "has_billing_method": true, "cc_fee_rate": + "0.0325", "default_insurance_amount": "50.00", "insurance_fee_rate": "0.005", + "insurance_fee_minimum": "0.25", "email": "email@example.com", "children": + []}, {"id": "user_91b120087ff843349b9a3f0675572bb1", "object": "User", "parent_id": + null, "name": "test test", "phone_number": "8888888888", "verified": true, + "created_at": "2022-05-02T19:04:10Z", "balance": "0.00000", "price_per_shipment": + "0.00000", "recharge_amount": null, "secondary_recharge_amount": null, "recharge_threshold": + null, "has_billing_method": null, "cc_fee_rate": "0.0325", "default_insurance_amount": + "50.00", "insurance_fee_rate": "0.005", "insurance_fee_minimum": "0.25", "email": + "test@test.com", "children": []}, {"id": "user_4ae0d572fbe542deb7efa51935a5b826", + "object": "User", "parent_id": null, "name": "test test", "phone_number": + "8888888888", "verified": true, "created_at": "2022-05-02T23:08:40Z", "balance": + "0.00000", "price_per_shipment": "0.00000", "recharge_amount": "100.00", "secondary_recharge_amount": + "100.00", "recharge_threshold": "0.00", "has_billing_method": true, "cc_fee_rate": + "0.0325", "default_insurance_amount": "50.00", "insurance_fee_rate": "0.005", + "insurance_fee_minimum": "0.25", "email": "test@test.com", "children": []}, + {"id": "user_71189529eba747ce83aa69303e22c7df", "object": "User", "parent_id": + null, "name": "Firstname Lastname", "phone_number": "8888888888", "verified": + true, "created_at": "2022-05-04T22:05:27Z", "balance": "0.00000", "price_per_shipment": + "0.00000", "recharge_amount": null, "secondary_recharge_amount": null, "recharge_threshold": + null, "has_billing_method": null, "cc_fee_rate": "0.0325", "default_insurance_amount": + "50.00", "insurance_fee_rate": "0.005", "insurance_fee_minimum": "0.25", "email": + "email@example.com", "children": []}, {"id": "user_c13290f1f6a442d79657b8bfe5daeeba", + "object": "User", "parent_id": null, "name": "test test", "phone_number": + "8888888888", "verified": true, "created_at": "2022-05-05T16:54:58Z", "balance": + "0.00000", "price_per_shipment": "0.00000", "recharge_amount": null, "secondary_recharge_amount": + null, "recharge_threshold": null, "has_billing_method": null, "cc_fee_rate": + "0.0325", "default_insurance_amount": "50.00", "insurance_fee_rate": "0.005", + "insurance_fee_minimum": "0.25", "email": "email@example.com", "children": + []}, {"id": "user_b73fdc6c6a58421ea884a82ad14520a5", "object": "User", "parent_id": + null, "name": "test test", "phone_number": "8888888888", "verified": true, + "created_at": "2022-05-05T16:55:59Z", "balance": "0.00000", "price_per_shipment": + "0.00000", "recharge_amount": "100.00", "secondary_recharge_amount": "100.00", + "recharge_threshold": "0.00", "has_billing_method": true, "cc_fee_rate": "0.0325", + "default_insurance_amount": "50.00", "insurance_fee_rate": "0.005", "insurance_fee_minimum": + "0.25", "email": "email@example.com", "children": []}]}' + headers: + cache-control: + - private, no-cache, no-store + content-length: + - '5084' + content-type: + - application/json; charset=utf-8 + etag: + - W/"834efd0f889ecef4b1c13a4e74b357b4" + expires: + - '0' + pragma: + - no-cache + referrer-policy: + - strict-origin-when-cross-origin + strict-transport-security: + - max-age=31536000; includeSubDomains; preload + transfer-encoding: + - chunked + x-backend: + - easypost + x-content-type-options: + - nosniff + x-download-options: + - noopen + x-ep-request-uuid: + - fb9a52bb63236812e787d961000821d8 + x-frame-options: + - SAMEORIGIN + x-node: + - bigweb2nuq + x-permitted-cross-domain-policies: + - none + x-proxied: + - intlb1nuq 6aa9972c1e + - extlb2nuq 9ce216bfac + x-runtime: + - '0.400328' + x-version-label: + - easypost-202209142327-76d51e2e7e-master + x-xss-protection: + - 1; mode=block + status: + code: 200 + message: OK +- request: + body: '{"user": {"email": "email@example.com"}}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '40' + Content-Type: + - application/json + authorization: + - + user-agent: + - + method: PUT + uri: https://api.easypost.com/beta/referral_customers/user_634b6daa05744bfaa205058f06864363 + response: + body: + string: '{"message": "Referral Customer email updated successfully"}' + headers: + cache-control: + - private, no-cache, no-store + content-length: + - '59' + content-type: + - application/json; charset=utf-8 + etag: + - W/"7b30d603e3257aee787616dc99d6d4af" + expires: + - '0' + pragma: + - no-cache + referrer-policy: + - strict-origin-when-cross-origin + strict-transport-security: + - max-age=31536000; includeSubDomains; preload + transfer-encoding: + - chunked + x-backend: + - easypost + x-content-type-options: + - nosniff + x-download-options: + - noopen + x-ep-request-uuid: + - fb9a52bb63236812e787d9610008220e + x-frame-options: + - SAMEORIGIN + x-node: + - bigweb4nuq + x-permitted-cross-domain-policies: + - none + x-proxied: + - intlb2nuq 6aa9972c1e + - extlb2nuq 9ce216bfac + x-runtime: + - '0.119584' + x-version-label: + - easypost-202209142327-76d51e2e7e-master + x-xss-protection: + - 1; mode=block + status: + code: 200 + message: OK +version: 1 diff --git a/tests/cassettes/test_referral_add_credit_card.yaml b/tests/cassettes/test_referral_add_credit_card.yaml index 7d2e1520..6876c802 100644 --- a/tests/cassettes/test_referral_add_credit_card.yaml +++ b/tests/cassettes/test_referral_add_credit_card.yaml @@ -13,7 +13,7 @@ interactions: user-agent: - method: GET - uri: https://api.easypost.com/beta/partners/stripe_public_key + uri: https://api.easypost.com/v2/partners/stripe_public_key response: body: string: '{"public_key": "pk_x3JSr5eOVWNTLRej8cZDde9VQ0AT5"}' @@ -43,7 +43,7 @@ interactions: x-download-options: - noopen x-ep-request-uuid: - - 042f43df62fa9806e79afec900253325 + - fb9a52be6323681ae787d97f00082572 x-frame-options: - SAMEORIGIN x-node: @@ -54,9 +54,9 @@ interactions: - intlb1nuq 6aa9972c1e - extlb2nuq 9ce216bfac x-runtime: - - '0.019000' + - '0.016635' x-version-label: - - easypost-202208151827-9b2100b5ad-master + - easypost-202209142327-76d51e2e7e-master x-xss-protection: - 1; mode=block status: @@ -83,23 +83,23 @@ interactions: uri: https://api.stripe.com/v1/tokens?card%5Bexp_month%5D=05&card%5Bexp_year%5D=2028 response: body: - string: '{"id": "tok_0LX8XSDqT4huGUvdbMClgjJq", "object": "token", "card": {"id": - "card_0LX8XSDqT4huGUvdubEO7rXf", "object": "card", "address_city": null, "address_country": + string: '{"id": "tok_0LiMLuDqT4huGUvdJkBtSAad", "object": "token", "card": {"id": + "card_0LiMLuDqT4huGUvdwvFxsoce", "object": "card", "address_city": null, "address_country": null, "address_line1": null, "address_line1_check": null, "address_line2": null, "address_state": null, "address_zip": null, "address_zip_check": null, "brand": "Visa", "country": "US", "cvc_check": "unchecked", "dynamic_last4": null, "exp_month": 5, "exp_year": 2028, "funding": "credit", "last4": "6170", "name": null, "tokenization_method": null}, "client_ip": "", "created": - 1660590086, "livemode": true, "type": "card", "used": false}' + 1663264794, "livemode": true, "type": "card", "used": false}' headers: Connection: - keep-alive Content-Length: - - '720' + - '719' Content-Type: - application/json Date: - - Mon, 15 Aug 2022 19:01:26 GMT + - Thu, 15 Sep 2022 17:59:54 GMT Server: - nginx Strict-Transport-Security: @@ -117,11 +117,11 @@ interactions: cache-control: - no-cache, no-store idempotency-key: - - 05c77ca4-37fa-4479-a71d-6a0dbc8609d3 + - 08669557-88f3-4a81-89b7-79d6b53b98f1 original-request: - - req_SpW4MxfPjQhzdj + - req_Rjld5zF1YhBeQs request-id: - - req_SpW4MxfPjQhzdj + - req_Rjld5zF1YhBeQs stripe-should-retry: - 'false' stripe-version: @@ -130,7 +130,7 @@ interactions: code: 200 message: OK - request: - body: '{"credit_card": {"stripe_object_id": "tok_0LX8XSDqT4huGUvdbMClgjJq", "priority": + body: '{"credit_card": {"stripe_object_id": "tok_0LiMLuDqT4huGUvdJkBtSAad", "priority": "primary"}}' headers: Accept: @@ -148,10 +148,10 @@ interactions: user-agent: - method: POST - uri: https://api.easypost.com/beta/credit_cards + uri: https://api.easypost.com/v2/credit_cards response: body: - string: '{"id": "card_31e7e32b36154309850dc57b63dd4ad7", "disabled_at": null, + string: '{"id": "card_55b732842711403ca4d34abbae7e6884", "disabled_at": null, "object": "CreditCard", "name": null, "last4": "6170", "exp_month": 5, "exp_year": 2028, "brand": "Visa"}' headers: @@ -162,7 +162,7 @@ interactions: content-type: - application/json; charset=utf-8 etag: - - W/"5d93f8393833ade4f2943d3d1c4002e3" + - W/"2a6f8717ccd56df83817bc8b10feac63" expires: - '0' pragma: @@ -175,25 +175,27 @@ interactions: - chunked x-backend: - easypost + x-canary: + - direct x-content-type-options: - nosniff x-download-options: - noopen x-ep-request-uuid: - - 042f43df62fa9807e79afec90025337e + - fb9a52be6323681ae787d97f000825b8 x-frame-options: - SAMEORIGIN x-node: - - bigweb2nuq + - bigweb7nuq x-permitted-cross-domain-policies: - none x-proxied: - - intlb1nuq 6aa9972c1e + - intlb2nuq 6aa9972c1e - extlb2nuq 9ce216bfac x-runtime: - - '4.554615' + - '3.417627' x-version-label: - - easypost-202208151827-9b2100b5ad-master + - easypost-202209142327-76d51e2e7e-master x-xss-protection: - 1; mode=block status: diff --git a/tests/cassettes/test_referral_user_all.yaml b/tests/cassettes/test_referral_user_all.yaml index 953b65b2..d7c68bf5 100644 --- a/tests/cassettes/test_referral_user_all.yaml +++ b/tests/cassettes/test_referral_user_all.yaml @@ -13,7 +13,7 @@ interactions: user-agent: - method: GET - uri: https://api.easypost.com/beta/referral_customers?page_size=5 + uri: https://api.easypost.com/v2/referral_customers?page_size=5 response: body: string: '{"has_more": true, "referral_customers": [{"id": "user_634b6daa05744bfaa205058f06864363", @@ -22,7 +22,7 @@ interactions: "0.00000", "price_per_shipment": "0.00000", "recharge_amount": null, "secondary_recharge_amount": null, "recharge_threshold": null, "has_billing_method": null, "cc_fee_rate": "0.0325", "default_insurance_amount": "50.00", "insurance_fee_rate": "0.005", - "insurance_fee_minimum": "0.25", "email": "email2@example.com", "children": + "insurance_fee_minimum": "0.25", "email": "email@example.com", "children": []}, {"id": "user_35cb81fb8af1454dabf1f6afa7330634", "object": "User", "parent_id": null, "name": "Firstname Lastname", "phone_number": "8888888888", "verified": true, "created_at": "2022-04-27T20:20:52Z", "balance": "0.00000", "price_per_shipment": @@ -54,11 +54,11 @@ interactions: cache-control: - private, no-cache, no-store content-length: - - '2574' + - '2573' content-type: - application/json; charset=utf-8 etag: - - W/"4c924b27f4db03a3f95fab711aef938d" + - W/"279cdeec93979855fbae0e836593122e" expires: - '0' pragma: @@ -76,20 +76,20 @@ interactions: x-download-options: - noopen x-ep-request-uuid: - - f43af47b62fa95dde79a7a4900262c87 + - fb9a52c063236819e787d97e00082542 x-frame-options: - SAMEORIGIN x-node: - - bigweb4nuq + - bigweb2nuq x-permitted-cross-domain-policies: - none x-proxied: - - intlb2nuq 6aa9972c1e - - extlb1nuq 9ce216bfac + - intlb1nuq 6aa9972c1e + - extlb2nuq 9ce216bfac x-runtime: - - '0.189660' + - '0.273447' x-version-label: - - easypost-202208151827-9b2100b5ad-master + - easypost-202209142327-76d51e2e7e-master x-xss-protection: - 1; mode=block status: diff --git a/tests/cassettes/test_referral_user_create.yaml b/tests/cassettes/test_referral_user_create.yaml index b942987c..315dae6f 100644 --- a/tests/cassettes/test_referral_user_create.yaml +++ b/tests/cassettes/test_referral_user_create.yaml @@ -17,12 +17,12 @@ interactions: user-agent: - method: POST - uri: https://api.easypost.com/beta/referral_customers + uri: https://api.easypost.com/v2/referral_customers response: body: - string: '{"id": "user_40d92e3d63874774a52e5ba8d3a265f6", "object": "User", "parent_id": + string: '{"id": "user_6b88c51984604133afad43001ae2170a", "object": "User", "parent_id": null, "name": "test test", "phone_number": "", "verified": true, - "created_at": "2022-08-15T18:52:11Z", "balance": "0.00000", "price_per_shipment": + "created_at": "2022-09-15T17:59:51Z", "balance": "0.00000", "price_per_shipment": "0.00000", "recharge_amount": null, "secondary_recharge_amount": null, "recharge_threshold": null, "has_billing_method": null, "cc_fee_rate": "0.0375", "default_insurance_amount": "50.00", "insurance_fee_rate": "0.005", "insurance_fee_minimum": "0.25", "email": @@ -35,7 +35,7 @@ interactions: content-type: - application/json; charset=utf-8 etag: - - W/"9ca8f753aa7815fbd52a8cec563ba91d" + - W/"1a6ed597198c8ec85b0d933d032d62aa" expires: - '0' pragma: @@ -53,20 +53,20 @@ interactions: x-download-options: - noopen x-ep-request-uuid: - - f43af47d62fa95dbe79a7a4700262ba2 + - fb9a52ba63236817e787d96500082469 x-frame-options: - SAMEORIGIN x-node: - - bigweb9nuq + - bigweb8nuq x-permitted-cross-domain-policies: - none x-proxied: - intlb1nuq 6aa9972c1e - - extlb1nuq 9ce216bfac + - extlb2nuq 9ce216bfac x-runtime: - - '0.987999' + - '1.084522' x-version-label: - - easypost-202208151827-9b2100b5ad-master + - easypost-202209142327-76d51e2e7e-master x-xss-protection: - 1; mode=block status: diff --git a/tests/cassettes/test_referral_user_update.yaml b/tests/cassettes/test_referral_user_update.yaml index a09c2e03..4660a4f2 100644 --- a/tests/cassettes/test_referral_user_update.yaml +++ b/tests/cassettes/test_referral_user_update.yaml @@ -13,7 +13,7 @@ interactions: user-agent: - method: GET - uri: https://api.easypost.com/beta/referral_customers + uri: https://api.easypost.com/v2/referral_customers response: body: string: '{"has_more": true, "referral_customers": [{"id": "user_634b6daa05744bfaa205058f06864363", @@ -22,7 +22,7 @@ interactions: "0.00000", "price_per_shipment": "0.00000", "recharge_amount": null, "secondary_recharge_amount": null, "recharge_threshold": null, "has_billing_method": null, "cc_fee_rate": "0.0325", "default_insurance_amount": "50.00", "insurance_fee_rate": "0.005", - "insurance_fee_minimum": "0.25", "email": "email2@example.com", "children": + "insurance_fee_minimum": "0.25", "email": "email@example.com", "children": []}, {"id": "user_35cb81fb8af1454dabf1f6afa7330634", "object": "User", "parent_id": null, "name": "Firstname Lastname", "phone_number": "8888888888", "verified": true, "created_at": "2022-04-27T20:20:52Z", "balance": "0.00000", "price_per_shipment": @@ -86,11 +86,11 @@ interactions: cache-control: - private, no-cache, no-store content-length: - - '5085' + - '5084' content-type: - application/json; charset=utf-8 etag: - - W/"4f0f67696bb0be5416f71ff9e5da47e0" + - W/"834efd0f889ecef4b1c13a4e74b357b4" expires: - '0' pragma: @@ -108,20 +108,20 @@ interactions: x-download-options: - noopen x-ep-request-uuid: - - 042f43e562fa98b6e79b06a900257ae1 + - fb9a52c063236819e787d966000824ea x-frame-options: - SAMEORIGIN x-node: - - bigweb2nuq + - bigweb9nuq x-permitted-cross-domain-policies: - none x-proxied: - intlb1nuq 6aa9972c1e - extlb2nuq 9ce216bfac x-runtime: - - '0.448293' + - '0.372611' x-version-label: - - easypost-202208151827-9b2100b5ad-master + - easypost-202209142327-76d51e2e7e-master x-xss-protection: - 1; mode=block status: @@ -145,7 +145,7 @@ interactions: user-agent: - method: PUT - uri: https://api.easypost.com/beta/referral_customers/user_634b6daa05744bfaa205058f06864363 + uri: https://api.easypost.com/v2/referral_customers/user_634b6daa05744bfaa205058f06864363 response: body: string: '{"message": "Referral Customer email updated successfully"}' @@ -175,20 +175,20 @@ interactions: x-download-options: - noopen x-ep-request-uuid: - - 042f43e562fa98b7e79b06a900257b0d + - fb9a52c063236819e787d96600082522 x-frame-options: - SAMEORIGIN x-node: - - bigweb9nuq + - bigweb8nuq x-permitted-cross-domain-policies: - none x-proxied: - - intlb1nuq 6aa9972c1e + - intlb2nuq 6aa9972c1e - extlb2nuq 9ce216bfac x-runtime: - - '0.123340' + - '0.120668' x-version-label: - - easypost-202208151827-9b2100b5ad-master + - easypost-202209142327-76d51e2e7e-master x-xss-protection: - 1; mode=block status: diff --git a/tests/test_beta_referral.py b/tests/test_beta_referral.py new file mode 100644 index 00000000..99ec1a66 --- /dev/null +++ b/tests/test_beta_referral.py @@ -0,0 +1,72 @@ +import os + +import pytest + +import easypost + + +REFERRAL_USER_PROD_API_KEY = os.getenv("REFERRAL_USER_PROD_API_KEY", "123") + + +@pytest.mark.vcr() +def test_beta_referral_user_create(partner_prod_api_key): + """This test requires a partner user's production API key via EASYPOST_PROD_API_KEY.""" + created_referral_user = easypost.beta.Referral.create( + name="test test", + email="test@test.com", + phone="8888888888", + ) + + assert isinstance(created_referral_user, easypost.User) + assert str.startswith(created_referral_user.id, "user_") + assert created_referral_user.name == "test test" + + +@pytest.mark.vcr() +def test_beta_referral_user_update(partner_prod_api_key): + """This test requires a partner user's production API key via EASYPOST_PROD_API_KEY.""" + referral_users = easypost.beta.Referral.all() + + updated_referral_user = easypost.beta.Referral.update_email( + "email@example.com", + referral_users.referral_customers[0].id, + ) + + assert updated_referral_user is True + + +@pytest.mark.vcr() +def test_beta_referral_user_all(partner_prod_api_key, page_size): + """This test requires a partner user's production API key via EASYPOST_PROD_API_KEY.""" + referral_users = easypost.beta.Referral.all(page_size=page_size) + + referral_users_array = referral_users["referral_customers"] + + assert len(referral_users_array) <= page_size + assert referral_users["has_more"] is not None + assert all(isinstance(referral_user, easypost.User) for referral_user in referral_users_array) + + +# PyVCR is having troubles matching the body of the form-encoded data here, override the default +@pytest.mark.vcr( + match_on=[ + "headers", + "method", + "query", + "uri", + ] +) +def test_beta_referral_add_credit_card(partner_prod_api_key, credit_card_details): + """This test requires a partner user's production API key via EASYPOST_PROD_API_KEY + as well as one of that user's referral's production API keys via REFERRAL_USER_PROD_API_KEY. + """ + added_credit_card = easypost.beta.Referral.add_credit_card( + referral_api_key=REFERRAL_USER_PROD_API_KEY, + number=credit_card_details["number"], + expiration_month=credit_card_details["expiration_month"], + expiration_year=credit_card_details["expiration_year"], + cvc=credit_card_details["cvc"], + ) + + assert str.startswith(added_credit_card.id, "card_") + assert added_credit_card.last4 == "6170" diff --git a/tests/test_referral.py b/tests/test_referral.py index b444f1b4..81e74870 100644 --- a/tests/test_referral.py +++ b/tests/test_referral.py @@ -11,7 +11,7 @@ @pytest.mark.vcr() def test_referral_user_create(partner_prod_api_key): """This test requires a partner user's production API key via EASYPOST_PROD_API_KEY.""" - created_referral_user = easypost.beta.Referral.create( + created_referral_user = easypost.Referral.create( name="test test", email="test@test.com", phone="8888888888", @@ -25,9 +25,9 @@ def test_referral_user_create(partner_prod_api_key): @pytest.mark.vcr() def test_referral_user_update(partner_prod_api_key): """This test requires a partner user's production API key via EASYPOST_PROD_API_KEY.""" - referral_users = easypost.beta.Referral.all() + referral_users = easypost.Referral.all() - updated_referral_user = easypost.beta.Referral.update_email( + updated_referral_user = easypost.Referral.update_email( "email@example.com", referral_users.referral_customers[0].id, ) @@ -38,7 +38,7 @@ def test_referral_user_update(partner_prod_api_key): @pytest.mark.vcr() def test_referral_user_all(partner_prod_api_key, page_size): """This test requires a partner user's production API key via EASYPOST_PROD_API_KEY.""" - referral_users = easypost.beta.Referral.all(page_size=page_size) + referral_users = easypost.Referral.all(page_size=page_size) referral_users_array = referral_users["referral_customers"] @@ -60,7 +60,7 @@ def test_referral_add_credit_card(partner_prod_api_key, credit_card_details): """This test requires a partner user's production API key via EASYPOST_PROD_API_KEY as well as one of that user's referral's production API keys via REFERRAL_USER_PROD_API_KEY. """ - added_credit_card = easypost.beta.Referral.add_credit_card( + added_credit_card = easypost.Referral.add_credit_card( referral_api_key=REFERRAL_USER_PROD_API_KEY, number=credit_card_details["number"], expiration_month=credit_card_details["expiration_month"],