Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Creating new fulfillment through API throws 406 error #208

Closed
jskitz opened this issue Aug 16, 2017 · 10 comments
Closed

Creating new fulfillment through API throws 406 error #208

jskitz opened this issue Aug 16, 2017 · 10 comments

Comments

@jskitz
Copy link

jskitz commented Aug 16, 2017

I'm trying to fulfill orders through the Shopify Python API, but cannot seem to create a new fulfillment without being thrown a 406 error. Here is the code that I have written to reproduce:

shopify_order = shopify.Order.find(5641096654)
new_fulfillment = shopify.Fulfillment()
new_fulfillment.order_id = shopify_order.id
new_fulfillment.tracking_company = 'USPS'
new_fulfillment.tracking_number = '9261290116299900821724'
new_fulfillment.line_items = [{ 'id': 10644252046L }]
print(new_fulfillment.attributes)  # The output on the next line
# {'line_items': [{'id': 10644252046L}],
# 'order_id': 5641096654,
# 'tracking_company': u'USPS',
# 'tracking_number': u'9261290116299900821724'}
new_fulfillment.save()

Here is the Traceback I get back from the API on this:

ClientError                               Traceback (most recent call last)
<ipython-input-30-62511ca6557f> in <module>()
----> 1 new_fulfillment.save()

/home/ubuntu/.virtualenvs/goldenv/local/lib/python2.7/site-packages/pyactiveresource/activeresource.pyc in save(self)
    822                         self._collection_path(self._prefix_options),
    823                         self.klass.headers,
--> 824                         data=self.encode())
    825                 new_id = self._id_from_response(response)
    826                 if new_id:

/home/ubuntu/.virtualenvs/goldenv/local/lib/python2.7/site-packages/pyactiveresource/connection.pyc in post(self, path, headers, data)
    362             A Response object.
    363         """
--> 364         return self._open('POST', path, headers=headers, data=data)
    365 
    366     def head(self, path, headers=None):

/home/ubuntu/.virtualenvs/goldenv/local/lib/python2.7/site-packages/shopify/base.pyc in _open(self, *args, **kwargs)
     21         self.response = None
     22         try:
---> 23             self.response = super(ShopifyConnection, self)._open(*args, **kwargs)
     24         except pyactiveresource.connection.ConnectionError as err:
     25             self.response = err.response

/home/ubuntu/.virtualenvs/goldenv/local/lib/python2.7/site-packages/pyactiveresource/connection.pyc in _open(self, method, path, headers, data)
    286                 http_response = self._handle_error(self._urlopen(request))
    287             except urllib.error.HTTPError as err:
--> 288                 http_response = self._handle_error(err)
    289             except urllib.error.URLError as err:
    290                 raise Error(err, url)

/home/ubuntu/.virtualenvs/goldenv/local/lib/python2.7/site-packages/pyactiveresource/connection.pyc in _handle_error(self, err)
    414             raise ResourceInvalid(err)
    415         elif 401 <= err.code < 500:
--> 416             raise ClientError(err)
    417         elif 500 <= err.code < 600:
    418             raise ServerError(err)

ClientError: Response(code=406, body="", headers={'x-sorting-hat-section': 'pod', 'x-shopify-shop-api-call-limit': '1/80', 'x-shopid': '19326945', 'http_x_shopify_shop_api_call_limit': '1/80', 'x-sorting-hat-shopid-cached': '0', 'x-request-id': '71731a83-31ca-4954-b80d-02ef44a5d96d', 'x-xss-protection': '1; mode=block; report=/xss-report?source%5Baction%5D=error_404&source%5Bapp%5D=Shopify&source%5Bcontroller%5D=admin%2Ferrors&source%5Bsection%5D=admin_api&source%5Buuid%5D=71731a83-31ca-4954-b80d-02ef44a5d96d', 'x-content-type-options': 'nosniff', 'x-stats-apiclientid': 'xxxxxxxxx', 'x-shardid': '13', 'x-stats-apipermissionid': 'xxxxxxxxxx', 'referrer-policy': 'origin-when-cross-origin', 'x-sorting-hat-shopid': '19326945', 'x-download-options': 'noopen', 'transfer-encoding': 'chunked', 'date': 'Wed, 16 Aug 2017 19:32:57 GMT', 'x-stats-userid': '0', 'content-security-policy': "default-src 'self' data: blob: 'unsafe-inline' 'unsafe-eval' https://* shopify-pos://*; block-all-mixed-content; child-src 'self' https://* shopify-pos://*; connect-src 'self' wss://* https://*; script-src https://cdn.shopify.com https://checkout.shopifycs.com https://js-agent.newrelic.com https://bam.nr-data.net https://dme0ih8comzn4.cloudfront.net https://api.stripe.com https://mpsnare.iesnare.com https://appcenter.intuit.com https://www.paypal.com https://maps.googleapis.com https://stats.g.doubleclick.net https://www.google-analytics.com https://visitors.shopify.com https://v.shopify.com https://widget.intercom.io https://js.intercomcdn.com 'self' 'unsafe-inline' 'unsafe-eval'; upgrade-insecure-requests; report-uri /csp-report?source%5Baction%5D=error_404&source%5Bapp%5D=Shopify&source%5Bcontroller%5D=admin%2Ferrors&source%5Bsection%5D=admin_api&source%5Buuid%5D=71731a83-31ca-4954-b80d-02ef44a5d96d", 'x-dc': 'chi2', 'strict-transport-security': 'max-age=7776000', 'x-sorting-hat-podid': '13', 'server': 'nginx', 'connection': 'close', 'x-permitted-cross-domain-policies': 'none', 'x-frame-options': 'DENY', 'x-sorting-hat-podid-cached': '0', 'content-type': 'application/json'}, msg="Not Acceptable")
@jamiemtdwyer
Copy link
Contributor

I've inspected the logs, and the URI you are actually posting to is:

/admin/orders//fulfillments.json

It looks like shopify_order.id might be nil.

@jamiemtdwyer
Copy link
Contributor

Also, not sure if you've tried to obscure those line item IDs or something, but they should be entirely numeric identifiers.

@jskitz
Copy link
Author

jskitz commented Aug 16, 2017

I think I may have figured out a work around by reading through a lot of the other tickets on eCommerce U.

Looks like you have to instantiate a Fulfillment object with the order_id. I have a myriad of questions about this interface however.

For example, does line_items have to be an array of line_item() objects or can it be a list of dictionaries that contain the 'id' as a key? Also, it appears that you have to pass a list of tracking_numbers, and sending an individual tracking number as above does not work. It would really be amazing if there were some docs that went with this project. There is lots of confusion about how to use the APIs, and just pointing people at active resources docs are not the same as knowing how to use this tool.

@jskitz
Copy link
Author

jskitz commented Aug 16, 2017

The IDs are just Long numbers. When storing shopify IDs in the database, they come out as Longs. They are numeric.

@jskitz
Copy link
Author

jskitz commented Aug 16, 2017

Just in case other people run into this, here is the missing piece:

https://ecommerce.shopify.com/c/shopify-apis-and-technology/t/how-to-fulfill-a-line-item-on-an-order-with-the-python-sdk-206326

The code that I found works, looks like this:

shopify_order = shopify.Order.find(5641096654)
new_fulfillment = shopify.Fulfillment({ 'order_id': shopify_order.id, 'line_items': shopify_order.line_items })
new_fulfillment.tracking_company = 'USPS'
new_fulfillment.tracking_numbers = ['9261290116299900821724']
new_fulfillment.save()

Closing for now, since it's not a bug but more that this project desperately needs some docs.

@jskitz jskitz closed this as completed Aug 16, 2017
@jamiemtdwyer
Copy link
Contributor

Sorry for the confusion, been spending too much time in Ruby-land.

The documentation is here, this library is simply a wrapper. It does assume a bit of knowledge of ActiveResource though, since it's built on pyactiveresource which is itself a port of ActiveResource from Rails.

The data should be passed as indicated in the documentation – line items is an array of dicts, each with a single key value pair for id.

@jskitz
Copy link
Author

jskitz commented Aug 16, 2017

Okay, that works. Would it be accurate, that whenever in the docs, there is an endpoint such as /admin/orders/#{id}/fulfillments.json, and I want to create a new Fulfillment, that the order ID has to be passed in on instantiation of the Fulfillment object? Seems like this would be the missing piece that you should add to the README. This is really the missing piece I think. I thought I could instantiate a Fulfillment, and then add the order_id after the fact. But you cannot. OrderID must be provided on instantiation as far as I can tell.

@jamiemtdwyer
Copy link
Contributor

Thanks for the actionable feedback! Let's re-open this and I'll close it when I've addressed your concerns in the README.

@jamiemtdwyer jamiemtdwyer reopened this Aug 16, 2017
@jamiemtdwyer
Copy link
Contributor

For now, if you're ever confused about usage I recommend looking at the API docs, and double-checking against the unit tests in this repo when you're confused about specific usage when it relates to ActiveResource. Admittedly, the test that would have clarified this (creating a new fulfilment) doesn't seem to exist, so perhaps should be added.

If you're not a Rails developer, this primer on ActiveResource was very helpful for me: http://tutorials.jumpstartlab.com/topics/web_services/active_resource.html

@jamiemtdwyer
Copy link
Contributor

Closed by #228.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants