If you want to run an online business using printing services like Printful, by far the easiest approach is to use Shopify or any other online business solution. However, I just wanted to attach a small shop to my own website. For such a case Printful provides an API, which however requires a little bit of work.
I am running my app using Flask in combination with a Postgres database behind a SQL alchemy ORM. First I selected the products I wanted to sell and store the products in my database. I will not discuss the details of my database setup here, but the easiest way for you would be to copy the Printful product database layout.
I then built an HTML/Javascript frontend for my store, which you are welcome to visit at www.benty-fields.com/benty-shop. Whenever a customer selects a product, I create an order object in my database, which however requires the variant_id from the Printful API. A simple solution would be to just download the entire product and variant list from Printful. This has the advantage that you would not need to make an API call to get the variant_id and hence can provide quicker response to any customer action. I, however, opted to write a small function, which queries the Printful API and returns the variant id. This way I am more flexible against any changes in the Printful variant_id list.
Here is the function I use:
try: response = requests.get(url) except requests.exceptions.RequestException as e: print("ERROR: %s" % str(e)) return False if response.status_code == 200: data = json.loads(response.text) # We count the number of positive variants we find, # just to be sure that our variant selection is unique count = 0 # Find the variant specified by the color and size of the order for variant in data['result']['variants']: # First we select the size (if size is not null). # Size is null if the product comes in only one size if variant['size'] == 'null': # There is no case I know of where size and color are null if variant['color'] == order.color: variant_id = variant['id'] count += 1 elif variant['size'] == order.size: # Second we select the color (if color is not null). # Color is null if the product comes in only one color if variant['color'] == 'null': variant_id = variant['id'] count += 1 elif variant['color'] == order.color: variant_id = variant['id'] count += 1 # to make absolutely sure that color and size define a variant for this product if count == 0: print("ERROR: No variant found with this size %s and color %s " for product id %d" % (order.size, order.color, order.product.printful_product_id) return False elif count > 1: print("ERROR: Size and color are not enough to define the variant " for product id %d" % order.product.printful_product_id return False else: return variant_id else: print("ERROR: Printful api call unsuccessful, code = %d," "message = %s" % (response.status_code, response.text) return False
Having set the variant id it is quite easy to submit a Printful order after the customer provided the payment details. Here is my function for that:
def create_printful_order(order): ''' This function submits a printful order ''' order_json = { "recipient": { "name": order.shipping_name, "address1": order.shipping_address, "city": order.shipping_city, "state_code": order.shipping_state_code, "country_code": order.shipping_country_code, "zip": order.shipping_zip_code }, "items": [{}] } order_json['retail_costs'] = { "shipping": order.shipping_cost } items = [] # Process each item in the order and attach them to the json object for order_item in order.items: item = { "variant_id": order_item.variant_id, "quantity": order_item.quantity, "name": order_item.product.title, "retail_price": order_item.product.price, "files": [{ "id": order_item.print_file_id }] } items.append(item) order_json['items'] = items url = app.config['PRINTFUL_API_BASE'] + 'orders' b64Val = base64.b64encode(app.config['PRINTFUL_API_KEY']) headers = {'content-type': 'application/json', 'Authorization': "Basic %s" % b64Val} try: response = requests.post(url, data=json.dumps(order_json), headers=headers) print("response = ", response.status_code, response.text)
return True, response except requests.exceptions.RequestException as e: print("ERROR: When submitting order with requests, " "error message: %s" % str(e)) return False, e
I posted the code on GitHub. Let me know if you have any comments.
cheers
Florian
No comments:
Post a Comment