Printful Integration for WooCommerce - Version 1.0

Version Description

  • First release

=

Download this release

Release Info

Developer printful
Plugin Icon 128x128 Printful Integration for WooCommerce
Version 1.0
Comparing to
See all releases

Version 1.0

Files changed (3) hide show
  1. PrintfulClient.php +177 -0
  2. printful-shipping.php +152 -0
  3. readme.txt +46 -0
PrintfulClient.php ADDED
@@ -0,0 +1,177 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This class helps to use the Printful API
4
+ *
5
+ * Requires PHP version 5, JSON and CURL extensions
6
+ *
7
+ * @package Printful
8
+ * @version 1.0
9
+ * @copyright 2014 Idea Bits LLC
10
+ */
11
+
12
+ class PrintfulClient {
13
+ private $key = false;
14
+ private $lastResponseRaw;
15
+ private $lastResponse;
16
+
17
+ const API_URL = 'https://api.theprintful.com/';
18
+ const USER_AGENT = 'Printful API WooCommerce Library 1.0';
19
+
20
+ /**
21
+ * @param string $key Printful Store API key
22
+ * @throws PrintfulException if the library failed to initialize
23
+ */
24
+ public function __construct($key = ''){
25
+ $key = (string)$key;
26
+
27
+ if(!function_exists('json_decode') || !function_exists('json_encode')){
28
+ throw new PrintfulException('PHP JSON extension is required for the Printful API library to work!');
29
+ }
30
+ if(!function_exists('curl_init') ){
31
+ throw new PrintfulException('PHP CURL extension is required for the Printful API library to work!');
32
+ }
33
+ if(strlen($key) < 32){
34
+ throw new PrintfulException('Missing or invalid Printful store key!');
35
+ }
36
+ $this->key = $key;
37
+ }
38
+
39
+ /**
40
+ * Returns total available item count from the last request if it supports paging (e.g order list) or null otherwise.
41
+ *
42
+ * @return int|null Item count
43
+ */
44
+ public function getItemCount(){
45
+ return isset($this->lastResponse['paging']['total']) ? $this->lastResponse['paging']['total'] : null;
46
+ }
47
+
48
+ /**
49
+ * Perform a GET request to the API
50
+ * @param string $path Request path (e.g. 'orders' or 'orders/123')
51
+ * @param array $params Additional GET parameters as an associative array
52
+ * @return mixed API response
53
+ * @throws PrintfulApiException if the API call status code is not in the 2xx range
54
+ * @throws PrintfulException if the API call has failed or the response is invalid
55
+ */
56
+ public function get($path, $params = array()){
57
+ return $this->request('GET', $path, $params);
58
+ }
59
+
60
+ /**
61
+ * Perform a DELETE request to the API
62
+ * @param string $path Request path (e.g. 'orders' or 'orders/123')
63
+ * @param array $params Additional GET parameters as an associative array
64
+ * @return mixed API response
65
+ * @throws PrintfulApiException if the API call status code is not in the 2xx range
66
+ * @throws PrintfulException if the API call has failed or the response is invalid
67
+ */
68
+ public function delete($path, $params = array()){
69
+ return $this->request('DELETE', $path, $params);
70
+ }
71
+
72
+ /**
73
+ * Perform a POST request to the API
74
+ * @param string $path Request path (e.g. 'orders' or 'orders/123')
75
+ * @param array $data Request body data as an associative array
76
+ * @param array $params Additional GET parameters as an associative array
77
+ * @return mixed API response
78
+ * @throws PrintfulApiException if the API call status code is not in the 2xx range
79
+ * @throws PrintfulException if the API call has failed or the response is invalid
80
+ */
81
+ public function post($path, $data = array(), $params = array()){
82
+ return $this->request('POST', $path, $params, $data);
83
+ }
84
+ /**
85
+ * Perform a PUT request to the API
86
+ * @param string $path Request path (e.g. 'orders' or 'orders/123')
87
+ * @param array $data Request body data as an associative array
88
+ * @param array $params Additional GET parameters as an associative array
89
+ * @return mixed API response
90
+ * @throws PrintfulApiException if the API call status code is not in the 2xx range
91
+ * @throws PrintfulException if the API call has failed or the response is invalid
92
+ */
93
+ public function put($path, $data = array(), $params = array()){
94
+ return $this->request('PUT', $path, $params, $data);
95
+ }
96
+
97
+ /**
98
+ * Return raw response data from the last request
99
+ * @return string|null Response data
100
+ */
101
+ public function getLastResponseRaw(){
102
+ return $this->lastResponseRaw;
103
+ }
104
+ /**
105
+ * Return decoded response data from the last request
106
+ * @return array|null Response data
107
+ */
108
+ public function getLastResponse(){
109
+ return $this->lastResponse;
110
+ }
111
+
112
+ /**
113
+ * Internal request implementation
114
+ */
115
+ private function request($method, $path, array $params = array(), $data = null){
116
+
117
+ $this->lastResponseRaw = null;
118
+ $this->lastResponse = null;
119
+
120
+ $url = trim($path,'/');
121
+
122
+ if(!empty($params)){
123
+ $url .= '?'.http_build_query($params);
124
+ }
125
+
126
+ $version = curl_version();
127
+ $baseUrl = self::API_URL;
128
+ if(!($version['features'] & CURL_VERSION_SSL)){ //Fallback to HTTP
129
+ $baseUrl = str_replace('https://', 'http://', $baseUrl);
130
+ }
131
+
132
+ $curl = curl_init($baseUrl.$url);
133
+
134
+ curl_setopt($curl, CURLOPT_USERPWD, $this->key);
135
+ curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);
136
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
137
+ curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
138
+ curl_setopt($curl, CURLOPT_MAXREDIRS, 3);
139
+
140
+ curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 20);
141
+ curl_setopt($curl, CURLOPT_TIMEOUT, 20);
142
+
143
+ curl_setopt($curl, CURLOPT_USERAGENT, self::USER_AGENT);
144
+
145
+ if($data !==null){
146
+ curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data));
147
+ }
148
+
149
+ $this->lastResponseRaw = curl_exec($curl);
150
+
151
+ $errno = curl_errno($curl);
152
+ $error = curl_error($curl);
153
+ curl_close($curl);
154
+
155
+ if ($errno) throw new PrintfulException('CURL: '.$error, $errno);
156
+
157
+ $this->lastResponse = $response = json_decode($this->lastResponseRaw, true);
158
+
159
+ if(!isset($response['code'], $response['result'])){
160
+ throw new PrintfulException('Invalid API response');
161
+ }
162
+ $status = (int)$response['code'];
163
+ if($status < 200 || $status >= 300){
164
+ throw new PrintfulApiException((string)$response['result'], $status);
165
+ }
166
+ return $response['result'];
167
+ }
168
+ }
169
+
170
+ /**
171
+ * Class PrintfulException Generic Printful exception
172
+ */
173
+ class PrintfulException extends Exception {}
174
+ /**
175
+ * Class PrintfulException Printful exception returned from the API
176
+ */
177
+ class PrintfulApiException extends PrintfulException {}
printful-shipping.php ADDED
@@ -0,0 +1,152 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ Plugin Name: Printful Shipping Rates for WooCommerce
4
+ Plugin URI: https://wordpress.org/plugins/printful-shipping-for-woocommerce/
5
+ Description: Printful shipping rates
6
+ Version: 1.0
7
+ Author: Idea Bits LLC
8
+ License: GPL2 http://www.gnu.org/licenses/gpl-2.0.html
9
+ */
10
+
11
+ add_action('woocommerce_shipping_init', 'printful_shipping_init');
12
+
13
+ add_filter('woocommerce_shipping_methods', 'printful_shipping_add');
14
+
15
+ function printful_shipping_add($methods)
16
+ {
17
+ $methods [] = 'printful_shipping';
18
+ return $methods;
19
+ }
20
+
21
+ function printful_shipping_init()
22
+ {
23
+
24
+ if (!class_exists('WC_Shipping_Method') ) {
25
+ return;
26
+ }
27
+
28
+ class Printful_Shipping extends WC_Shipping_Method
29
+ {
30
+ public $currencyRate = 1;
31
+
32
+
33
+ function __construct()
34
+ {
35
+ $this->id = 'printful_shipping';
36
+ $this->method_title = 'Printful Shipping';
37
+ $this->method_description = 'Calculate live shipping rates based on actual Printful shipping costs';
38
+
39
+ $this->init_form_fields();
40
+ $this->init_settings();
41
+
42
+ add_action('woocommerce_update_options_shipping_' . $this->id, array(&$this, 'process_admin_options'));
43
+
44
+ $this->enabled = $this->get_option('enabled');
45
+ $this->title = $this->get_option('title');
46
+
47
+ if (get_woocommerce_currency() != 'USD') {
48
+ $currencyRate = (float)$this->get_option('rate');
49
+ if($currencyRate>0) {
50
+ $this->currencyRate = $currencyRate;
51
+ }
52
+ }
53
+ $this->type = 'order';
54
+ }
55
+
56
+ function init_form_fields()
57
+ {
58
+ $this->form_fields = array(
59
+ 'enabled' => array(
60
+ 'title' => __( 'Enable/Disable', 'woocommerce' ),
61
+ 'type' => 'checkbox',
62
+ 'label' => __( 'Enable this shipping method', 'woocommerce' ),
63
+ 'default' => 'no'
64
+ ),
65
+ 'title' => array(
66
+ 'title' => __( 'Method Title', 'woocommerce' ),
67
+ 'type' => 'text',
68
+ 'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce' ),
69
+ 'default' => __( 'Printful Shipping', 'woocommerce' ),
70
+ 'desc_tip' => true,
71
+ ),
72
+ 'printful_key' => array(
73
+ 'title' => 'Printful store API key',
74
+ 'type' => 'text',
75
+ 'desc_tip' => true,
76
+ 'description'=> 'Your store\'s Printful API key. Create it in the Prinful dashboard',
77
+ 'default' => '',
78
+ ),
79
+ );
80
+ $currency = get_woocommerce_currency();
81
+ if ($currency != 'USD'){ //Require conversion rate
82
+ $this->form_fields['rate'] = array(
83
+ 'title' => 'Currency conversion rate',
84
+ 'type' => 'text',
85
+ 'desc_tip' => true,
86
+ 'description' => 'Currency rate used to convert Printful shipping prices from USD to ' . $currency .
87
+ '. For example if multiplier is 0.2, Printful price of 2 USD will be converted to 10 '.$currency,
88
+ 'default' => '1',
89
+ );
90
+ }
91
+ }
92
+
93
+ function calculate_shipping($package = array())
94
+ {
95
+ if (!class_exists('PrintfulClient', false)) {
96
+ require dirname(__FILE__) . '/PrintfulClient.php';
97
+ }
98
+
99
+ $request = array(
100
+ 'recipient' => array(
101
+ 'address1' => $package['destination']['address'],
102
+ 'address2' => $package['destination']['address_2'],
103
+ 'city' => $package['destination']['city'],
104
+ 'state_code' => $package['destination']['state'],
105
+ 'country_code' => $package['destination']['country'],
106
+ 'zip' => $package['destination']['postcode'],
107
+ ),
108
+ 'items' => array()
109
+ );
110
+
111
+ foreach ($package['contents'] as $item) {
112
+ $request['items'] []= array(
113
+ 'external_variant_id' => $item['variation_id'] ? $item['variation_id'] : $item['product_id'],
114
+ 'quantity' => $item['quantity']
115
+ );
116
+ }
117
+
118
+ try {
119
+ $printful = new PrintfulClient($this->get_option('printful_key'));
120
+ } catch( PrintfulException $e) {
121
+ wc_add_notice( $e->getMessage(), 'error' );
122
+ return false;
123
+ }
124
+
125
+ try {
126
+ $response = $printful->post('shipping/rates', $request, array(
127
+ 'expedited' => true,
128
+ ));
129
+
130
+ foreach ($response as $rate) {
131
+ $rateData = array(
132
+ 'id' => $this->id . '_' . $rate['id'],
133
+ 'label' => $rate['name'],
134
+ 'cost' => round($rate['rate'] / $this->currencyRate, 2),
135
+ 'taxes' => '',
136
+ 'calc_tax' => 'per_order'
137
+ );
138
+ $this->add_rate($rateData);
139
+ }
140
+ } catch ( PrintfulException $e) {
141
+ if (WP_DEBUG) {
142
+ wc_add_notice( $e->getMessage(), 'error' );
143
+ }
144
+ return false;
145
+ }
146
+ }
147
+ }
148
+ }
149
+
150
+
151
+
152
+
readme.txt ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ === Printful live shipping rates for WooCommerce ===
2
+ Contributors: girts_u
3
+ Tags: woocommerce, printful, shipping, shipping rates, fulfillment, printing, fedex, carriers, checkout
4
+ Requires at least: 3.8
5
+ Tested up to: 4.0
6
+ Stable tag: 1.0
7
+ License: GPLv2 or later
8
+ License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
+
10
+ Calculate live shipping rates based on actual Printful shipping costs
11
+
12
+ == Description ==
13
+
14
+ Display actual live shipping rates from carriers like FedEx on your WooCommerce checkout page. This plugin will return a list of available shipping rates specific to the shipping address your customer provides when checking out. These rates are identical to the list you get when you submit an order manually via Printful dashboard.
15
+
16
+ = Known Limitations =
17
+
18
+ * Works with WooCommmerce 2.1 and up
19
+ * Works only if every item in the order is fulfilled by Printful
20
+
21
+ == Installation ==
22
+ 1. Upload 'printful-shipping' to the '/wp-content/plugins/' directory
23
+ 1. Activate the plugin through the 'Plugins' menu in WordPress
24
+ 1. Enable rate calculation by adding your Printful API key to WooCommerce->Settings->Shipping->Printful Shipping tab
25
+
26
+ == Frequently Asked Questions ==
27
+
28
+ = How do I get Printful API key? =
29
+
30
+ Go to https://www.theprintful.com/dashboard/store , select your WooCommerce store, click "Edit" and then click
31
+ "Enable API Access". Your API key will be generated and displayed there.
32
+
33
+ == Screenshots ==
34
+
35
+ 1. Settings dialog
36
+ 2. Shipping rate selection
37
+
38
+ == Upgrade Notice ==
39
+
40
+ = 1.0 =
41
+ * First release
42
+
43
+ == Changelog ==
44
+
45
+ = 1.0 =
46
+ * First release