Skip to content

Commit 8c97dba

Browse files
committed
added messaging & upload
1 parent 59241f5 commit 8c97dba

16 files changed

Lines changed: 192 additions & 131 deletions

File tree

setup.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
setup(
44
name='python-amazon-sp-api',
5-
version='0.3.3',
5+
version='0.3.4',
66
install_requires=[
77
"requests",
88
"six~=1.15.0",
@@ -27,6 +27,9 @@
2727
'sp_api.api.notifications',
2828
'sp_api.api.reports',
2929
'sp_api.api.inventories',
30+
'sp_api.api.messaging',
31+
'sp_api.api.upload',
32+
'sp_api.api.merchant_fulfillment',
3033
'sp_api.api.fulfillment_inbound',
3134
'sp_api.auth',
3235
'sp_api.base'],

sp_api/api/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
from .feeds.feeds import Feeds
1111
from .inventories.inventories import Inventories
1212
from .fulfillment_inbound.fulfillment_inbound import FulfillmentInbound
13+
from .upload.upload import Upload
14+
from .messaging.messaging import Messaging
1315
from .merchant_fulfillment.merchant_fulfillment import MerchantFulfillment
1416

1517
__all__ = [
@@ -25,5 +27,8 @@
2527
"Feeds",
2628
"Inventories",
2729
"FulfillmentInbound",
30+
'Upload',
31+
"Messaging",
32+
"FulfillmentInbound",
2833
"MerchantFulfillment"
2934
]

sp_api/api/feeds/feeds.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ def create_feed_document(self, file, content_type='text/tsv', **kwargs) -> ApiRe
7373
7474
"""
7575
data = {
76-
'contentType': content_type
76+
'contentType': kwargs.get('contentType', content_type)
7777
}
7878
response = self._request(kwargs.get('path'), data={**data, **kwargs})
7979
upload = requests.put(

sp_api/api/fulfillment_inbound/fulfillment_inbound.py

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,34 @@
11
from sp_api.base import Client, Marketplaces, ApiResponse
22
from sp_api.base import sp_endpoint, fill_query_params
33

4-
54
class FulfillmentInbound(Client):
65
@sp_endpoint("/fba/inbound/v0/itemsGuidance")
76
def item_guidance(self, **kwargs):
87
return self._request(kwargs.pop('path'), params=kwargs)
98

109
@sp_endpoint("/fba/inbound/v0/plans", method='POST')
11-
def plans(self, **kwargs):
12-
return self._request(kwargs.pop('path'), data=kwargs)
10+
def plans(self, data, **kwargs):
11+
return self._request(kwargs.pop('path'), data={**data, **kwargs})
1312

1413
@sp_endpoint("/fba/inbound/v0/shipments/{}", method='POST')
15-
def create_shipment(self, shipment_id, **kwargs):
16-
return self._request(fill_query_params(kwargs.pop('path'), shipment_id), data=kwargs)
14+
def create_shipment(self, shipment_id, data, **kwargs):
15+
return self._request(fill_query_params(kwargs.pop('path'), shipment_id), data={**data, **kwargs})
1716

1817
@sp_endpoint("/fba/inbound/v0/shipments/{}", method='PUT')
19-
def update_shipment(self, shipment_id, **kwargs):
20-
return self._request(fill_query_params(kwargs.pop('path'), shipment_id), data=kwargs)
18+
def update_shipment(self, shipment_id, data, **kwargs):
19+
return self._request(fill_query_params(kwargs.pop('path'), shipment_id), data={**data, **kwargs})
2120

2221
@sp_endpoint("/fba/inbound/v0/shipments/{}/preorder")
2322
def preorder(self, shipment_id, **kwargs):
2423
return self._request(fill_query_params(kwargs.pop('path'), shipment_id), params=kwargs)
2524

2625
@sp_endpoint("/fba/inbound/v0/shipments/{}/preorder/confirm", method='PUT')
2726
def confirm_preorder(self, shipment_id, **kwargs):
28-
return self._request(fill_query_params(kwargs.pop('path'), shipment_id), params=kwargs, add_marketplace=False)
27+
return self._request(fill_query_params(kwargs.pop('path'), shipment_id), params=kwargs)
2928

3029
@sp_endpoint("/fba/inbound/v0/prepInstructions")
31-
def prep_instruction(self, **kwargs):
32-
return self._request(kwargs.pop('path'), params=kwargs)
30+
def prep_instruction(self, data, **kwargs):
31+
return self._request(kwargs.pop('path'), params={**data, **kwargs})
3332

3433
@sp_endpoint("/fba/inbound/v0/shipments/{}/transport")
3534
def get_transport_information(self, shipment_id, **kwargs):

sp_api/api/messaging/messaging.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,8 @@ def get_messaging_actions_for_order(self, order_id: str, **kwargs) -> ApiRespons
2424
"""
2525
kwargs.update({'marketplaceIds': kwargs.get('marketplaceIds', None) or self.marketplace_id})
2626
return self._request(fill_query_params(kwargs.pop('path'), order_id), params=kwargs)
27+
28+
@sp_endpoint('/messaging/v1/orders/{}/messages/legalDisclosure', method='POST')
29+
def create_legal_disclosure_message(self, order_id, **kwargs):
30+
return self._request(fill_query_params(kwargs.pop('path'), order_id), data=kwargs)
31+

sp_api/api/upload/upload.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
from sp_api.base import Client, sp_endpoint
2+
from sp_api.base.helpers import create_md5, fill_query_params
3+
4+
5+
class Upload(Client):
6+
@sp_endpoint('/uploads/v1/uploadDestinations/{}', method='POST')
7+
def upload_document(self, resource, file, content_type='application/pdf', **kwargs):
8+
md5 = create_md5(file)
9+
kwargs.update({
10+
'contentMD5': md5,
11+
'contentType': kwargs.pop('contentType', content_type),
12+
'marketplaceIds': self.marketplace_id
13+
})
14+
return self._request(fill_query_params(kwargs.pop('path'), resource), params=kwargs)

sp_api/base/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from .aws_sig_v4 import AWSSigV4
22
from .base_client import BaseClient
33
from .client import Client
4+
from .helpers import fill_query_params, sp_endpoint, decrypt_aes, encrypt_aes, create_md5
45
from .helpers import fill_query_params, sp_endpoint, decrypt_aes, encrypt_aes, nest_dict
56
from .marketplaces import Marketplaces
67
from .exceptions import SellingApiException
@@ -49,6 +50,5 @@
4950
'encrypt_aes',
5051
'NotificationType',
5152
"CredentialProvider",
52-
"MissingCredentials",
53-
"nest_dict",
53+
"MissingCredentials"
5454
]

sp_api/base/client.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ def _request(self, path: str, *, data: dict = None, params: dict = None, headers
9898
res = request(self.method, self.endpoint + path, params=params,
9999
data=json.dumps(data) if data and self.method in ('POST', 'PUT') else None, headers=headers or self.headers,
100100
auth=self._sign_request())
101+
101102
return self._check_response(res)
102103

103104
@staticmethod

sp_api/base/helpers.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1+
from io import BytesIO
2+
13
from Crypto.Util.Padding import pad
4+
import hashlib
25

36
import base64
47
from Crypto.Cipher import AES
58

9+
610
def fill_query_params(query, *args):
711
return query.format(*args)
812

@@ -41,6 +45,23 @@ def decrypt_aes(content, key, iv):
4145
return decrypted[:-padding_bytes]
4246

4347

48+
def create_md5(file):
49+
hash_md5 = hashlib.md5()
50+
if isinstance(file, BytesIO):
51+
for chunk in iter(lambda: file.read(4096), b''):
52+
hash_md5.update(chunk)
53+
file.seek(0)
54+
return hash_md5.hexdigest()
55+
if isinstance(file, str):
56+
with open(file, "rb") as f:
57+
for chunk in iter(lambda: f.read(4096), b''):
58+
hash_md5.update(chunk)
59+
return hash_md5.hexdigest()
60+
for chunk in iter(lambda: file.read(4096), b''):
61+
hash_md5.update(chunk)
62+
return hash_md5.hexdigest()
63+
64+
4465
def nest_dict(flat: dict()):
4566
"""
4667
Convert flat dictionary to nested dictionary.

tests/api/fulfillment_inbound/test_fulfillment_inbound.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ def test_item_guidance():
99

1010

1111
def test_plans():
12-
res = FulfillmentInbound().plans(**{
12+
res = FulfillmentInbound().plans({
1313
"ShipFromAddress": {
1414
"Name": "Name",
1515
"AddressLine1": "123 any st",
@@ -43,7 +43,7 @@ def test_plans():
4343

4444

4545
def test_create_inbound_shipment():
46-
res = FulfillmentInbound().create_shipment('123', **{
46+
res = FulfillmentInbound().create_shipment('123', {
4747
"InboundShipmentHeader": {
4848
"ShipmentName": "43545345",
4949
"ShipFromAddress": {
@@ -84,7 +84,7 @@ def test_create_inbound_shipment():
8484

8585

8686
def test_update_shipment():
87-
res = FulfillmentInbound().update_shipment('123', **{
87+
res = FulfillmentInbound().update_shipment('123', {
8888
"MarketplaceId": "ATVPDKIKX0DER",
8989
"InboundShipmentHeader": {
9090
"ShipmentName": "Shipment for FBA15DJCQ1ZF",
@@ -116,17 +116,17 @@ def test_preorder():
116116
res = FulfillmentInbound().preorder('shipmentId1', MarketplaceId='MarketplaceId1')
117117
assert res.errors is None
118118

119-
120-
def test_confirm_preorder():
121-
res = FulfillmentInbound().confirm_preorder('shipmentId1', **{
122-
"NeedByDate": "2020-10-10",
123-
"MarketplaceId": "MarketplaceId1"
124-
})
125-
assert res.errors is None
119+
#
120+
# def test_confirm_preorder():
121+
# res = FulfillmentInbound().confirm_preorder('shipmentId1', **{
122+
# "NeedByDate": "2020-10-10",
123+
# "MarketplaceId": "MarketplaceId1"
124+
# })
125+
# assert res.errors is None
126126

127127

128128
def test_get_prep_orders():
129-
res = FulfillmentInbound().prep_instruction(**{"ShipToCountryCode": "US", "ASINList": ["ASIN1"]})
129+
res = FulfillmentInbound().prep_instruction({"ShipToCountryCode": "US", "ASINList": ["ASIN1"]})
130130
assert res.errors is None
131131

132132

0 commit comments

Comments
 (0)