Version Notes
Don't forget to specify Weight and Dimensions for each Product and to enable Shippo rates here:
System > Configuration > Sales > ShippingMethods > Shippo
Download this release
Release Info
Developer | Buildateam |
Extension | Buildateam_Shippo |
Version | 1.0.2 |
Comparing to | |
See all releases |
Version 1.0.2
- app/code/community/Buildateam/Shippo/Block/Adminhtml/Frontend/Region/Updater.php +47 -0
- app/code/community/Buildateam/Shippo/Helper/Carrier.php +27 -0
- app/code/community/Buildateam/Shippo/Helper/Data.php +230 -0
- app/code/community/Buildateam/Shippo/Helper/Shippo.php +205 -0
- app/code/community/Buildateam/Shippo/Model/Carrier.php +121 -0
- app/code/community/Buildateam/Shippo/Model/Observer.php +5 -0
- app/code/community/Buildateam/Shippo/Model/Parcel.php +71 -0
- app/code/community/Buildateam/Shippo/Model/System/Config/Source/Region.php +7 -0
- app/code/community/Buildateam/Shippo/Model/System/Config/Source/Size.php +21 -0
- app/code/community/Buildateam/Shippo/Model/System/Config/Source/Weight.php +21 -0
- app/code/community/Buildateam/Shippo/controllers/TestController.php +38 -0
- app/code/community/Buildateam/Shippo/etc/adminhtml.xml +23 -0
- app/code/community/Buildateam/Shippo/etc/config.xml +118 -0
- app/code/community/Buildateam/Shippo/etc/system.xml +185 -0
- app/code/community/Buildateam/Shippo/sql/buildateam_shippo_setup/mysql4-upgrade-1.0.0-1.0.1.php +7 -0
- app/code/community/Buildateam/Shippo/sql/buildateam_shippo_setup/mysql4-upgrade-1.0.1-1.0.2.php +32 -0
- app/design/adminhtml/default/default/layout/buildateam/shippo.xml +16 -0
- app/design/adminhtml/default/default/template/buildateam/shippo/catalog/product/js.phtml +15 -0
- app/etc/modules/Buildateam_Shippo.xml +10 -0
- lib/Shippo.php +47 -0
- lib/Shippo/Address.php +61 -0
- lib/Shippo/ApiConnectionError.php +5 -0
- lib/Shippo/ApiError.php +5 -0
- lib/Shippo/ApiRequestor.php +281 -0
- lib/Shippo/ApiResource.php +139 -0
- lib/Shippo/AttachedObject.php +23 -0
- lib/Shippo/AuthenticationError.php +5 -0
- lib/Shippo/CarrierAccount.php +62 -0
- lib/Shippo/CustomsDeclaration.php +50 -0
- lib/Shippo/CustomsItem.php +50 -0
- lib/Shippo/Error.php +27 -0
- lib/Shippo/InvalidRequestError.php +10 -0
- lib/Shippo/List.php +29 -0
- lib/Shippo/Manifest.php +38 -0
- lib/Shippo/Object.php +262 -0
- lib/Shippo/Parcel.php +38 -0
- lib/Shippo/Rate.php +26 -0
- lib/Shippo/RateLimitError.php +9 -0
- lib/Shippo/Refund.php +38 -0
- lib/Shippo/Shipment.php +50 -0
- lib/Shippo/Shippo.php +57 -0
- lib/Shippo/SingletonApiResource.php +31 -0
- lib/Shippo/Transaction.php +38 -0
- lib/Shippo/Util.php +78 -0
- lib/Shippo/Util/Set.php +34 -0
- package.xml +19 -0
app/code/community/Buildateam/Shippo/Block/Adminhtml/Frontend/Region/Updater.php
ADDED
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Buildateam_Shippo_Block_Adminhtml_Frontend_Region_Updater
|
4 |
+
extends Mage_Adminhtml_Block_System_Config_Form_Field
|
5 |
+
{
|
6 |
+
protected $_idCountry = 'carriers_buildateam_shippo_from_country';
|
7 |
+
|
8 |
+
protected $_idRegion = 'carriers_buildateam_shippo_from_region';
|
9 |
+
|
10 |
+
public function getCountryElementId()
|
11 |
+
{
|
12 |
+
return $this->_idCountry;
|
13 |
+
}
|
14 |
+
|
15 |
+
public function getRegionElementId()
|
16 |
+
{
|
17 |
+
return $this->_idRegion;
|
18 |
+
}
|
19 |
+
|
20 |
+
protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
|
21 |
+
{
|
22 |
+
$html = parent::_getElementHtml($element);
|
23 |
+
|
24 |
+
$idCountry = $this->getCountryElementId();
|
25 |
+
$idRegion = $this->getRegionElementId();
|
26 |
+
|
27 |
+
$js = '<script type="text/javascript">
|
28 |
+
var updater = new RegionUpdater("' . $idCountry . '", "none", "' . $idRegion . '", %s, "nullify");
|
29 |
+
if(updater.lastCountryId) {
|
30 |
+
var tmpRegionId = $("' . $idRegion . '").value;
|
31 |
+
var tmpCountryId = updater.lastCountryId;
|
32 |
+
updater.lastCountryId=false;
|
33 |
+
updater.update();
|
34 |
+
updater.lastCountryId = tmpCountryId;
|
35 |
+
$("' . $idRegion .'").value = tmpRegionId;
|
36 |
+
} else {
|
37 |
+
updater.update();
|
38 |
+
}
|
39 |
+
</script>';
|
40 |
+
|
41 |
+
$html .= sprintf($js, $this->helper('directory')->getRegionJson());
|
42 |
+
return $html;
|
43 |
+
}
|
44 |
+
}
|
45 |
+
|
46 |
+
|
47 |
+
|
app/code/community/Buildateam/Shippo/Helper/Carrier.php
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Buildateam_Shippo_Helper_Carrier extends Mage_Core_Helper_Abstract
|
4 |
+
{
|
5 |
+
public function getQuoteFromRateRequest(Mage_Shipping_Model_Rate_Request $request)
|
6 |
+
{
|
7 |
+
if ( count($request->getAllItems()) )
|
8 |
+
{
|
9 |
+
$firstItem = current($request->getAllItems());
|
10 |
+
$quote = $firstItem->getQuote();
|
11 |
+
return $quote;
|
12 |
+
}
|
13 |
+
|
14 |
+
return null;
|
15 |
+
}
|
16 |
+
|
17 |
+
public function getShippingAddressFromRateRequest(Mage_Shipping_Model_Rate_Request $request)
|
18 |
+
{
|
19 |
+
if ( $quote = $this->getQuoteFromRateRequest($request) )
|
20 |
+
{
|
21 |
+
$shippingAddress = $quote->getShippingAddress();
|
22 |
+
return $shippingAddress;
|
23 |
+
}
|
24 |
+
|
25 |
+
return null;
|
26 |
+
}
|
27 |
+
}
|
app/code/community/Buildateam/Shippo/Helper/Data.php
ADDED
@@ -0,0 +1,230 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Buildateam_Shippo_Helper_Data extends Mage_Core_Helper_Abstract
|
4 |
+
{
|
5 |
+
const LOG_FILE = 'buildateam_shippo.log';
|
6 |
+
|
7 |
+
const PATH_ECONOMY_DESCRIPTION = 'carriers/buildateam_shippo/economy_description';
|
8 |
+
const PATH_EXPEDITED_DESCRIPTION = 'carriers/buildateam_shippo/expedited_description';
|
9 |
+
const PATH_OVERNIGHT_DESCRIPTION = 'carriers/buildateam_shippo/overnight_description';
|
10 |
+
const PATH_EXPEDITED_METHOD_COST = 'carriers/buildateam_shippo/expedited_cost';
|
11 |
+
const PATH_OVERNIGHT_METHOD_COST = 'carriers/buildateam_shippo/overnight_cost';
|
12 |
+
const NOTIFY_EMAIL_RECIPIENT = 'carriers/buildateam_shippo/notify_email_recipient';
|
13 |
+
|
14 |
+
const PATH_EMAIL_DELAY_TIME = 'buildateam_shippo/general/email_delay';
|
15 |
+
const PATH_EMAIL_DELAY_ENABLED = 'buildateam_shippo/general/enable';
|
16 |
+
|
17 |
+
|
18 |
+
const PATH_FROM_PRIVATE_AUTH_TOKEN = 'carriers/buildateam_shippo/private_auth_token';
|
19 |
+
|
20 |
+
const PATH_FROM_NAME = 'carriers/buildateam_shippo/from_name';
|
21 |
+
const PATH_FROM_COMPANY = 'carriers/buildateam_shippo/from_company';
|
22 |
+
const PATH_FROM_COUNTRY = 'carriers/buildateam_shippo/from_country';
|
23 |
+
const PATH_FROM_REGION = 'carriers/buildateam_shippo/from_region';
|
24 |
+
const PATH_FROM_POSTCODE = 'carriers/buildateam_shippo/from_postcode';
|
25 |
+
const PATH_FROM_CITY = 'carriers/buildateam_shippo/from_city';
|
26 |
+
const PATH_FROM_STREET = 'carriers/buildateam_shippo/from_street';
|
27 |
+
const PATH_FROM_PHONE = 'carriers/buildateam_shippo/from_phone';
|
28 |
+
const PATH_FROM_EMAIL = 'carriers/buildateam_shippo/from_email';
|
29 |
+
|
30 |
+
const PATH_WEIGHT_UNIT = 'carriers/buildateam_shippo/weight_unit';
|
31 |
+
const PATH_SIZE_UNIT = 'carriers/buildateam_shippo/size_unit';
|
32 |
+
const PATH_HANDLING = 'carriers/buildateam_shippo/shipping_handling';
|
33 |
+
|
34 |
+
|
35 |
+
protected static $methods = array(
|
36 |
+
'tablerate_bestway' => self::PATH_ECONOMY_DESCRIPTION,
|
37 |
+
'buildateam_shippo_expedited' => self::PATH_EXPEDITED_DESCRIPTION,
|
38 |
+
'buildateam_shippo_overnight' => self::PATH_OVERNIGHT_DESCRIPTION,
|
39 |
+
);
|
40 |
+
|
41 |
+
|
42 |
+
public function getPrivateAuthToken($store = null)
|
43 |
+
{
|
44 |
+
return Mage::getStoreConfig(self::PATH_FROM_PRIVATE_AUTH_TOKEN, $store);
|
45 |
+
}
|
46 |
+
|
47 |
+
public function getFromName($store = null)
|
48 |
+
{
|
49 |
+
return Mage::getStoreConfig(self::PATH_FROM_NAME, $store);
|
50 |
+
}
|
51 |
+
|
52 |
+
public function getFromCompany($store = null)
|
53 |
+
{
|
54 |
+
return Mage::getStoreConfig(self::PATH_FROM_COMPANY, $store);
|
55 |
+
}
|
56 |
+
|
57 |
+
public function getFromCountry($store = null)
|
58 |
+
{
|
59 |
+
return Mage::getStoreConfig(self::PATH_FROM_COUNTRY, $store);
|
60 |
+
}
|
61 |
+
|
62 |
+
public function getFromRegion($store = null)
|
63 |
+
{
|
64 |
+
return Mage::getStoreConfig(self::PATH_FROM_REGION, $store);
|
65 |
+
}
|
66 |
+
|
67 |
+
public function getFromPostcode($store = null)
|
68 |
+
{
|
69 |
+
return Mage::getStoreConfig(self::PATH_FROM_POSTCODE, $store);
|
70 |
+
}
|
71 |
+
|
72 |
+
public function getFromCity($store = null)
|
73 |
+
{
|
74 |
+
return Mage::getStoreConfig(self::PATH_FROM_CITY, $store);
|
75 |
+
}
|
76 |
+
|
77 |
+
public function getFromStreet($store = null)
|
78 |
+
{
|
79 |
+
return Mage::getStoreConfig(self::PATH_FROM_STREET, $store);
|
80 |
+
}
|
81 |
+
|
82 |
+
public function getFromPhone($store = null)
|
83 |
+
{
|
84 |
+
return Mage::getStoreConfig(self::PATH_FROM_PHONE, $store);
|
85 |
+
}
|
86 |
+
|
87 |
+
public function getFromEmail($store = null)
|
88 |
+
{
|
89 |
+
return Mage::getStoreConfig(self::PATH_FROM_EMAIL, $store);
|
90 |
+
}
|
91 |
+
|
92 |
+
|
93 |
+
public function getWeightUnit($store = null)
|
94 |
+
{
|
95 |
+
return Mage::getStoreConfig(self::PATH_WEIGHT_UNIT, $store);
|
96 |
+
}
|
97 |
+
|
98 |
+
public function getSizeUnit($store = null)
|
99 |
+
{
|
100 |
+
return Mage::getStoreConfig(self::PATH_SIZE_UNIT, $store);
|
101 |
+
}
|
102 |
+
|
103 |
+
public function getHandling($store = null)
|
104 |
+
{
|
105 |
+
return Mage::getStoreConfig(self::PATH_HANDLING, $store);
|
106 |
+
}
|
107 |
+
|
108 |
+
/**
|
109 |
+
* Returns economy shipping method description.
|
110 |
+
*
|
111 |
+
* @param null $store
|
112 |
+
* @return mixed
|
113 |
+
*/
|
114 |
+
public function getEconomyDescription($store = null)
|
115 |
+
{
|
116 |
+
return Mage::getStoreConfig(self::PATH_ECONOMY_DESCRIPTION, $store);
|
117 |
+
}
|
118 |
+
|
119 |
+
/**
|
120 |
+
* Returns expedited shipping method description.
|
121 |
+
*
|
122 |
+
* @param null $store
|
123 |
+
* @return mixed
|
124 |
+
*/
|
125 |
+
public function getExpeditedDescription($store = null)
|
126 |
+
{
|
127 |
+
return Mage::getStoreConfig(self::PATH_EXPEDITED_DESCRIPTION, $store);
|
128 |
+
}
|
129 |
+
|
130 |
+
/**
|
131 |
+
* Returns overnight shipping method description.
|
132 |
+
*
|
133 |
+
* @param null $store
|
134 |
+
* @return mixed
|
135 |
+
*/
|
136 |
+
public function getOvernightDescription($store = null)
|
137 |
+
{
|
138 |
+
return Mage::getStoreConfig(self::PATH_OVERNIGHT_DESCRIPTION, $store);
|
139 |
+
}
|
140 |
+
|
141 |
+
/**
|
142 |
+
* Returns exppedited shipping method cost.
|
143 |
+
*
|
144 |
+
* @param null $store
|
145 |
+
* @return float
|
146 |
+
*/
|
147 |
+
public function getExpeditedMethodCost($store = null)
|
148 |
+
{
|
149 |
+
return (float)Mage::getStoreConfig(self::PATH_EXPEDITED_METHOD_COST, $store);
|
150 |
+
}
|
151 |
+
|
152 |
+
/**
|
153 |
+
* Returns overnight shipping method cost.
|
154 |
+
*
|
155 |
+
* @param null $store
|
156 |
+
* @return float
|
157 |
+
*/
|
158 |
+
public function getOvernightMethodCost($store = null)
|
159 |
+
{
|
160 |
+
return (float)Mage::getStoreConfig(self::PATH_OVERNIGHT_METHOD_COST, $store);
|
161 |
+
}
|
162 |
+
|
163 |
+
/**
|
164 |
+
* Checks if we can show description.
|
165 |
+
*
|
166 |
+
* @param array $rates
|
167 |
+
* @return bool
|
168 |
+
*/
|
169 |
+
public function canShowDescription($rates)
|
170 |
+
{
|
171 |
+
if (!is_array($rates)) {
|
172 |
+
return false;
|
173 |
+
}
|
174 |
+
return array_key_exists(Buildateam_Shippo_Model_Carrier::CODE, $rates);
|
175 |
+
}
|
176 |
+
|
177 |
+
/**
|
178 |
+
* Returns description for shipping method.
|
179 |
+
*
|
180 |
+
* @param string $code
|
181 |
+
* @return string|null
|
182 |
+
*/
|
183 |
+
public function getDescription($code)
|
184 |
+
{
|
185 |
+
if (!array_key_exists($code, self::$methods)) {
|
186 |
+
return;
|
187 |
+
}
|
188 |
+
|
189 |
+
return Mage::getStoreConfig(self::$methods[$code]);
|
190 |
+
}
|
191 |
+
|
192 |
+
/**
|
193 |
+
* Returns notify email recipient
|
194 |
+
*
|
195 |
+
* @param null $store
|
196 |
+
* @return string|null
|
197 |
+
*/
|
198 |
+
public function getEmailRecipient($store = null)
|
199 |
+
{
|
200 |
+
return (string)Mage::getStoreConfig(self::NOTIFY_EMAIL_RECIPIENT, $store);
|
201 |
+
}
|
202 |
+
|
203 |
+
|
204 |
+
/**
|
205 |
+
* Returns shipping email delay time (when we create it using SOAP request).
|
206 |
+
*
|
207 |
+
* @param null $store
|
208 |
+
* @return float
|
209 |
+
*/
|
210 |
+
public function getEmailDelayTime($store = null)
|
211 |
+
{
|
212 |
+
return (int)Mage::getStoreConfig(self::PATH_EMAIL_DELAY_TIME, $store);
|
213 |
+
}
|
214 |
+
|
215 |
+
/**
|
216 |
+
* Returns if delay is enabled for shipping confirmation emails (when we create shipment using SOAP request)
|
217 |
+
*
|
218 |
+
* @param null $store
|
219 |
+
* @return bool
|
220 |
+
*/
|
221 |
+
public function getEmailDelayEnabled($store = null)
|
222 |
+
{
|
223 |
+
return Mage::getStoreConfigFlag(self::PATH_EMAIL_DELAY_ENABLED, $store);
|
224 |
+
}
|
225 |
+
|
226 |
+
public function log($message)
|
227 |
+
{
|
228 |
+
Mage::log($message, null, self::LOG_FILE);
|
229 |
+
}
|
230 |
+
}
|
app/code/community/Buildateam/Shippo/Helper/Shippo.php
ADDED
@@ -0,0 +1,205 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Buildateam_Shippo_Helper_Shippo extends Mage_Core_Helper_Abstract
|
4 |
+
{
|
5 |
+
public function getRates(Mage_Shipping_Model_Rate_Request $request)
|
6 |
+
{
|
7 |
+
// Replace <API-KEY> with your credentials
|
8 |
+
# From goshippo.com > API > API Keys > Private Auth Token
|
9 |
+
//$devPrivateAuthToken = '167263307a16e8b1c51fbf4b055decc85b683678'; # DEV
|
10 |
+
Shippo::setApiKey( Mage::helper('buildateam_shippo')->getPrivateAuthToken() );
|
11 |
+
|
12 |
+
/*
|
13 |
+
// example fromAddress
|
14 |
+
$fromAddress = array(
|
15 |
+
'object_purpose' => 'PURCHASE',
|
16 |
+
'name' => 'Mr Hippo"',
|
17 |
+
'company' => 'Shippo',
|
18 |
+
'street1' => '215 Clayton St.',
|
19 |
+
'city' => 'San Francisco',
|
20 |
+
'state' => 'CA',
|
21 |
+
'zip' => '94117',
|
22 |
+
'country' => 'US',
|
23 |
+
'phone' => '+1 555 341 9393',
|
24 |
+
'email' => 'mr-hippo@goshipppo.com'
|
25 |
+
);
|
26 |
+
|
27 |
+
|
28 |
+
// example fromAddress
|
29 |
+
$toAddress = array(
|
30 |
+
'object_purpose' => 'PURCHASE',
|
31 |
+
'name' => 'Ms Hippo"',
|
32 |
+
'company' => 'San Diego Zoo"',
|
33 |
+
'street1' => '2920 Zoo Drive"',
|
34 |
+
'city' => 'San Diego',
|
35 |
+
'state' => 'CA',
|
36 |
+
'zip' => '92101',
|
37 |
+
'country' => 'US',
|
38 |
+
'phone' => '+1 555 341 9393',
|
39 |
+
'email' => 'ms-hippo@goshipppo.com'
|
40 |
+
);
|
41 |
+
|
42 |
+
// example parcel
|
43 |
+
$parcel = array(
|
44 |
+
'length'=> '5',
|
45 |
+
'width'=> '5',
|
46 |
+
'height'=> '5',
|
47 |
+
'distance_unit'=> 'in',
|
48 |
+
'weight'=> '2',
|
49 |
+
'mass_unit'=> 'lb',
|
50 |
+
);
|
51 |
+
*/
|
52 |
+
|
53 |
+
$fromAddress = $this->prepareFromAddress();
|
54 |
+
$mageShippingAddress = Mage::helper('buildateam_shippo/carrier')->getShippingAddressFromRateRequest($request);
|
55 |
+
$toAddress = $this->prepareToAddress($mageShippingAddress);
|
56 |
+
Mage::helper('buildateam_shippo')->log('1 toAddress');
|
57 |
+
Mage::helper('buildateam_shippo')->log($toAddress);
|
58 |
+
$parcel = $this->prepareParcel($request);
|
59 |
+
|
60 |
+
// example Shipment object
|
61 |
+
$shipment = Shippo_Shipment::create(array(
|
62 |
+
'object_purpose' => 'PURCHASE',
|
63 |
+
'address_from' => $fromAddress,
|
64 |
+
'address_to' => $toAddress,
|
65 |
+
'parcel' => $parcel,
|
66 |
+
'async' => false
|
67 |
+
));
|
68 |
+
|
69 |
+
// Select the rate you want to purchase.
|
70 |
+
// We simply select the first rate in this example.
|
71 |
+
//$rate = $shipment["rates_list"][0];
|
72 |
+
|
73 |
+
Mage::helper('buildateam_shippo')->log('4 get rates');
|
74 |
+
if ( isset($shipment['rates_list']) ) {
|
75 |
+
if ( count($shipment['rates_list']) ) {
|
76 |
+
//Mage::log( $shipment['rates_list'] );
|
77 |
+
$handling = Mage::helper('buildateam_shippo')->getHandling();
|
78 |
+
foreach($shipment['rates_list'] as &$rate)
|
79 |
+
{
|
80 |
+
$rate['amount'] += $handling;
|
81 |
+
}
|
82 |
+
|
83 |
+
|
84 |
+
Mage::helper('buildateam_shippo')->log(count($shipment['rates_list']) . ' rates received');
|
85 |
+
|
86 |
+
|
87 |
+
return $shipment['rates_list'];
|
88 |
+
} else {
|
89 |
+
Mage::helper('buildateam_shippo')->log('ERROR: NO RATES !!!');
|
90 |
+
}
|
91 |
+
} else {
|
92 |
+
Mage::helper('buildateam_shippo')->log('ERROR: NO RATES !!!');
|
93 |
+
}
|
94 |
+
|
95 |
+
|
96 |
+
return null;
|
97 |
+
}
|
98 |
+
|
99 |
+
public function prepareFromAddress()
|
100 |
+
{
|
101 |
+
$regionId = Mage::helper('buildateam_shippo')->getFromRegion();
|
102 |
+
$region = Mage::getModel('directory/region')->load( $regionId );
|
103 |
+
|
104 |
+
$fromAddress = array(
|
105 |
+
'object_purpose' => 'PURCHASE',
|
106 |
+
'name' => Mage::helper('buildateam_shippo')->getFromName(),
|
107 |
+
'company' => Mage::helper('buildateam_shippo')->getFromCompany(),
|
108 |
+
'street1' => Mage::helper('buildateam_shippo')->getFromStreet(),
|
109 |
+
'city' => Mage::helper('buildateam_shippo')->getFromCity(),
|
110 |
+
'state' => $region->getCode(),
|
111 |
+
'zip' => Mage::helper('buildateam_shippo')->getFromPostcode(),
|
112 |
+
'country' => Mage::helper('buildateam_shippo')->getFromCountry(),
|
113 |
+
'phone' => Mage::helper('buildateam_shippo')->getFromPhone(),
|
114 |
+
'email' => Mage::helper('buildateam_shippo')->getFromEmail()
|
115 |
+
);
|
116 |
+
|
117 |
+
return $fromAddress;
|
118 |
+
}
|
119 |
+
|
120 |
+
public function prepareToAddress($mageShippingAddress)
|
121 |
+
{
|
122 |
+
$street = is_array($mageShippingAddress->getStreet()) ? current($mageShippingAddress->getStreet()) : $mageShippingAddress->getStreet();
|
123 |
+
$state = '';
|
124 |
+
if ( $regionId = $mageShippingAddress->getRegionId() )
|
125 |
+
{
|
126 |
+
$region = Mage::getModel('directory/region')->load( $regionId );
|
127 |
+
$state = $region->getCode();
|
128 |
+
}
|
129 |
+
|
130 |
+
$name = trim($mageShippingAddress->getFirstname() . ' ' . $mageShippingAddress->getLastname());
|
131 |
+
$name = empty($name) ? 'Customer' : $name;
|
132 |
+
|
133 |
+
$email = trim($mageShippingAddress->getEmail());
|
134 |
+
$email = empty($email) ? 'example@example.com' : $email;
|
135 |
+
|
136 |
+
// example fromAddress
|
137 |
+
$toAddress = array(
|
138 |
+
'object_purpose' => 'PURCHASE',
|
139 |
+
'name' => $name,
|
140 |
+
'company' => $mageShippingAddress->getCompany(), # optional
|
141 |
+
'street1' => $street,
|
142 |
+
'city' => $mageShippingAddress->getCity(),
|
143 |
+
'state' => $state,
|
144 |
+
'zip' => $mageShippingAddress->getPostcode(),
|
145 |
+
'country' => $mageShippingAddress->getCountryId(),
|
146 |
+
'phone' => $mageShippingAddress->getTelephone(), # optional
|
147 |
+
'email' => $email,
|
148 |
+
);
|
149 |
+
|
150 |
+
return $toAddress;
|
151 |
+
}
|
152 |
+
|
153 |
+
protected function _prepareParcel($items)
|
154 |
+
{
|
155 |
+
$parcel = new Buildateam_Shippo_Model_Parcel();
|
156 |
+
//$parcel->add(array(1, 5, 2), 1);
|
157 |
+
//$parcel->add(array(2, 4, 3), 2);
|
158 |
+
//$parcel->add(array(7, 1, 1), 1);
|
159 |
+
|
160 |
+
foreach ($items as $item) {
|
161 |
+
if ($item->getParentItem()) {
|
162 |
+
continue;
|
163 |
+
}
|
164 |
+
if ($item->getProduct()->isVirtual()) {
|
165 |
+
continue;
|
166 |
+
}
|
167 |
+
|
168 |
+
if ($item->getProduct()->getVisibility() != Mage_Catalog_Model_Product_Visibility::VISIBILITY_NOT_VISIBLE) {
|
169 |
+
$product = Mage::getModel('catalog/product')->load( $item->getProduct()->getEntityId() );
|
170 |
+
$sDimensions = $product->getData('dimensions_lwh');
|
171 |
+
|
172 |
+
if ( $parcel->validateDimensionsString($sDimensions) ) {
|
173 |
+
$dimensions = $parcel->getDimensionsFromString($sDimensions);
|
174 |
+
|
175 |
+
Mage::helper('buildateam_shippo')->log('2 Parcel add');
|
176 |
+
Mage::helper('buildateam_shippo')->log('2 qty: ' . $item->getQty());
|
177 |
+
Mage::helper('buildateam_shippo')->log($dimensions);
|
178 |
+
|
179 |
+
$parcel->add($dimensions, $item->getQty());
|
180 |
+
}
|
181 |
+
}
|
182 |
+
}
|
183 |
+
|
184 |
+
return $parcel;
|
185 |
+
}
|
186 |
+
|
187 |
+
public function prepareParcel(Mage_Shipping_Model_Rate_Request $request)
|
188 |
+
{
|
189 |
+
$parcel = $this->_prepareParcel( $request->getAllItems() );
|
190 |
+
|
191 |
+
$parcel = array(
|
192 |
+
'length' => $parcel->getLength(),
|
193 |
+
'width' => $parcel->getWidth(),
|
194 |
+
'height' => $parcel->getHeight(),
|
195 |
+
'distance_unit' => Mage::helper('buildateam_shippo')->getSizeUnit(),
|
196 |
+
'weight' => $request->getData('package_weight'),
|
197 |
+
'mass_unit' => Mage::helper('buildateam_shippo')->getWeightUnit(),
|
198 |
+
);
|
199 |
+
|
200 |
+
Mage::helper('buildateam_shippo')->log('3 Parcel');
|
201 |
+
Mage::helper('buildateam_shippo')->log($parcel);
|
202 |
+
|
203 |
+
return $parcel;
|
204 |
+
}
|
205 |
+
}
|
app/code/community/Buildateam/Shippo/Model/Carrier.php
ADDED
@@ -0,0 +1,121 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Buildateam_Shippo_Model_Carrier extends Mage_Shipping_Model_Carrier_Abstract implements Mage_Shipping_Model_Carrier_Interface
|
4 |
+
{
|
5 |
+
const CODE = 'buildateam_shippo'; // for static access
|
6 |
+
|
7 |
+
const EXPEDITED = 'expedited';
|
8 |
+
const OVERNIGHT = 'overnight';
|
9 |
+
|
10 |
+
protected $_code = self::CODE;
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Returns allowed methods.
|
14 |
+
*
|
15 |
+
* @return array
|
16 |
+
*/
|
17 |
+
public function getAllowedMethods()
|
18 |
+
{
|
19 |
+
$helper = Mage::helper('buildateam_shippo');
|
20 |
+
return array(
|
21 |
+
self::EXPEDITED => $helper->__('Expedited'),
|
22 |
+
self::OVERNIGHT => $helper->__('Overnight'),
|
23 |
+
);
|
24 |
+
}
|
25 |
+
|
26 |
+
/**
|
27 |
+
* We have no tracking.
|
28 |
+
*
|
29 |
+
* @return bool
|
30 |
+
*/
|
31 |
+
public function isTrackingAvailable()
|
32 |
+
{
|
33 |
+
return false;
|
34 |
+
}
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Collects shipping rates.
|
38 |
+
*
|
39 |
+
* @param Mage_Shipping_Model_Rate_Request $request
|
40 |
+
* @return bool|Mage_Shipping_Model_Rate_Result|null
|
41 |
+
*/
|
42 |
+
public function collectRates(Mage_Shipping_Model_Rate_Request $request)
|
43 |
+
{
|
44 |
+
/** @var Mage_Shipping_Model_Rate_Result $result */
|
45 |
+
$result = Mage::getModel('shipping/rate_result');
|
46 |
+
|
47 |
+
try {
|
48 |
+
$aRates = Mage::helper('buildateam_shippo/shippo')->getRates($request);
|
49 |
+
|
50 |
+
if ( $aRates )
|
51 |
+
foreach($aRates as $aRate) {
|
52 |
+
$rate = $this->_prepareRate($aRate);
|
53 |
+
$result->append($rate);
|
54 |
+
}
|
55 |
+
|
56 |
+
} catch (Exception $e) {
|
57 |
+
Mage::helper('buildateam_shippo')->log( $e->getMessage() );
|
58 |
+
}
|
59 |
+
|
60 |
+
//$result->append($this->_getExpeditedRate());
|
61 |
+
//$result->append($this->_getOvernightRate());
|
62 |
+
|
63 |
+
return $result;
|
64 |
+
}
|
65 |
+
|
66 |
+
protected function _prepareRate($aRate)
|
67 |
+
{
|
68 |
+
$rate = Mage::getModel('shipping/rate_result_method');
|
69 |
+
|
70 |
+
$rate->setCarrier($this->_code);//($aRate['servicelevel_token']);
|
71 |
+
$rate->setCarrierTitle($aRate['provider']);
|
72 |
+
$rate->setMethod($aRate['servicelevel_token']);
|
73 |
+
$rate->setMethodTitle($aRate['servicelevel_name']);
|
74 |
+
$rate->setPrice($aRate['amount']);
|
75 |
+
$rate->setCost(0);
|
76 |
+
|
77 |
+
return $rate;
|
78 |
+
}
|
79 |
+
|
80 |
+
protected function _getExpeditedRate()
|
81 |
+
{
|
82 |
+
/** @var Mage_Shipping_Model_Rate_Result_Method $rate */
|
83 |
+
$rate = Mage::getModel('shipping/rate_result_method');
|
84 |
+
|
85 |
+
$rate->setCarrier($this->_code);
|
86 |
+
$rate->setCarrierTitle($this->getConfigData('title'));
|
87 |
+
$rate->setMethod(self::EXPEDITED);
|
88 |
+
$rate->setMethodTitle('Expedited');
|
89 |
+
$cost = $this->getDefaultHelper()->getExpeditedMethodCost();
|
90 |
+
$rate->setPrice($cost);
|
91 |
+
$rate->setCost(0);
|
92 |
+
|
93 |
+
return $rate;
|
94 |
+
}
|
95 |
+
|
96 |
+
protected function _getOvernightRate()
|
97 |
+
{
|
98 |
+
/** @var Mage_Shipping_Model_Rate_Result_Method $rate */
|
99 |
+
$rate = Mage::getModel('shipping/rate_result_method');
|
100 |
+
|
101 |
+
$rate->setCarrier($this->_code);
|
102 |
+
$rate->setCarrierTitle($this->getConfigData('title'));
|
103 |
+
$rate->setMethod(self::OVERNIGHT);
|
104 |
+
$rate->setMethodTitle('Overnight');
|
105 |
+
$cost = $this->getDefaultHelper()->getOvernightMethodCost();
|
106 |
+
$rate->setPrice($cost);
|
107 |
+
$rate->setCost(0);
|
108 |
+
|
109 |
+
return $rate;
|
110 |
+
}
|
111 |
+
|
112 |
+
/**
|
113 |
+
* Returns default helper.
|
114 |
+
*
|
115 |
+
* @return buildateam_shippo_Helper_Data
|
116 |
+
*/
|
117 |
+
public function getDefaultHelper()
|
118 |
+
{
|
119 |
+
return Mage::helper('buildateam_shippo');
|
120 |
+
}
|
121 |
+
}
|
app/code/community/Buildateam/Shippo/Model/Observer.php
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Buildateam_Shippo_Model_Observer
|
3 |
+
{
|
4 |
+
|
5 |
+
}
|
app/code/community/Buildateam/Shippo/Model/Parcel.php
ADDED
@@ -0,0 +1,71 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Buildateam_Shippo_Model_Parcel extends Varien_Object
|
4 |
+
{
|
5 |
+
protected $_dimensions = array(0, 0, 0); // Height, Width, Length
|
6 |
+
|
7 |
+
public function add(array $dimensions, $qty)
|
8 |
+
{
|
9 |
+
if ( $this->validateDimensionsArray($dimensions) ) {
|
10 |
+
sort($dimensions); // 1 5 9
|
11 |
+
sort($this->_dimensions);
|
12 |
+
|
13 |
+
$this->_dimensions[2]= max($this->_dimensions[2], $dimensions[2]); // Length
|
14 |
+
$this->_dimensions[1]= max($this->_dimensions[1], $dimensions[1]); // Width
|
15 |
+
$this->_dimensions[0]= $this->_dimensions[0] + ($dimensions[0] * $qty); // Height
|
16 |
+
|
17 |
+
} else {
|
18 |
+
throw new Exception('Dimensions are invalid: ' . print_r($dimensions, 1));
|
19 |
+
}
|
20 |
+
}
|
21 |
+
|
22 |
+
public function validateDimensionsString($str)
|
23 |
+
{
|
24 |
+
$pattern = '/([\.\d])+x([\.\d])+x([\.\d])+/';
|
25 |
+
$result = preg_match($pattern, $str, $match);
|
26 |
+
if ( $match )
|
27 |
+
if ( count($match) ) {
|
28 |
+
$sDimensions = $match[0];
|
29 |
+
$aDimensions = explode('x', $sDimensions);
|
30 |
+
|
31 |
+
$isValid = $this->validateDimensionsArray($aDimensions);
|
32 |
+
return $isValid;
|
33 |
+
}
|
34 |
+
|
35 |
+
return false;
|
36 |
+
}
|
37 |
+
|
38 |
+
public function validateDimensionsArray(array $aDimensions)
|
39 |
+
{
|
40 |
+
if ( is_array($aDimensions) )
|
41 |
+
if ( count($aDimensions) == 3 )
|
42 |
+
if ( @array_walk($aDimensions, 'is_numeric') ) {
|
43 |
+
|
44 |
+
return true;
|
45 |
+
}
|
46 |
+
|
47 |
+
return false;
|
48 |
+
}
|
49 |
+
|
50 |
+
public function getDimensionsFromString($str)
|
51 |
+
{
|
52 |
+
$dimensions = explode('x', $str);
|
53 |
+
$dimensions = array_map('floatval', $dimensions);
|
54 |
+
return $dimensions;
|
55 |
+
}
|
56 |
+
|
57 |
+
public function getLength()
|
58 |
+
{
|
59 |
+
return $this->_dimensions[2];
|
60 |
+
}
|
61 |
+
|
62 |
+
public function getWidth()
|
63 |
+
{
|
64 |
+
return $this->_dimensions[1];
|
65 |
+
}
|
66 |
+
|
67 |
+
public function getHeight()
|
68 |
+
{
|
69 |
+
return $this->_dimensions[0];
|
70 |
+
}
|
71 |
+
}
|
app/code/community/Buildateam/Shippo/Model/System/Config/Source/Region.php
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Buildateam_Shippo_Model_System_Config_Source_Region
|
4 |
+
extends Mage_Tax_Model_System_Config_Source_Tax_Region
|
5 |
+
{
|
6 |
+
|
7 |
+
}
|
app/code/community/Buildateam/Shippo/Model/System/Config/Source/Size.php
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Buildateam_Shippo_Model_System_Config_Source_Size
|
4 |
+
{
|
5 |
+
public function toOptionArray()
|
6 |
+
{
|
7 |
+
return array(
|
8 |
+
array('value' => 'in', 'label'=>Mage::helper('adminhtml')->__('Inches')),
|
9 |
+
array('value' => 'cm', 'label'=>Mage::helper('adminhtml')->__('Centimeters')),
|
10 |
+
);
|
11 |
+
}
|
12 |
+
|
13 |
+
public function toArray()
|
14 |
+
{
|
15 |
+
return array(
|
16 |
+
'in' => Mage::helper('adminhtml')->__('Inches'),
|
17 |
+
'cm' => Mage::helper('adminhtml')->__('Centimeters'),
|
18 |
+
);
|
19 |
+
}
|
20 |
+
|
21 |
+
}
|
app/code/community/Buildateam/Shippo/Model/System/Config/Source/Weight.php
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Buildateam_Shippo_Model_System_Config_Source_Weight
|
4 |
+
{
|
5 |
+
public function toOptionArray()
|
6 |
+
{
|
7 |
+
return array(
|
8 |
+
array('value' => 'lb', 'label'=>Mage::helper('adminhtml')->__('Pounds')),
|
9 |
+
array('value' => 'kg', 'label'=>Mage::helper('adminhtml')->__('Kilograms')),
|
10 |
+
);
|
11 |
+
}
|
12 |
+
|
13 |
+
public function toArray()
|
14 |
+
{
|
15 |
+
return array(
|
16 |
+
'lb' => Mage::helper('adminhtml')->__('Pounds'),
|
17 |
+
'kg' => Mage::helper('adminhtml')->__('Kilograms'),
|
18 |
+
);
|
19 |
+
}
|
20 |
+
|
21 |
+
}
|
app/code/community/Buildateam/Shippo/controllers/TestController.php
ADDED
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Buildateam_Shippo_TestController extends Mage_Core_Controller_Front_Action
|
4 |
+
{
|
5 |
+
public function indexAction()
|
6 |
+
{
|
7 |
+
echo '<br/>';
|
8 |
+
var_dump( Mage::helper('buildateam_shippo')->getPrivateAuthToken() );
|
9 |
+
echo '<br/>';
|
10 |
+
var_dump( Mage::helper('buildateam_shippo')->getFromName() );
|
11 |
+
echo '<br/>';
|
12 |
+
var_dump( Mage::helper('buildateam_shippo')->getFromCompany() );
|
13 |
+
echo '<br/>';
|
14 |
+
var_dump( Mage::helper('buildateam_shippo')->getFromCountry() );
|
15 |
+
echo '<br/>';
|
16 |
+
var_dump( Mage::helper('buildateam_shippo')->getFromRegion() );
|
17 |
+
echo '<br/>';
|
18 |
+
var_dump( Mage::helper('buildateam_shippo')->getFromPostcode() );
|
19 |
+
echo '<br/>';
|
20 |
+
var_dump( Mage::helper('buildateam_shippo')->getFromCity() );
|
21 |
+
echo '<br/>';
|
22 |
+
var_dump( Mage::helper('buildateam_shippo')->getFromStreet() );
|
23 |
+
echo '<br/>';
|
24 |
+
var_dump( Mage::helper('buildateam_shippo')->getFromPhone() );
|
25 |
+
echo '<br/>';
|
26 |
+
var_dump( Mage::helper('buildateam_shippo')->getFromEmail() );
|
27 |
+
|
28 |
+
echo '<br/>';
|
29 |
+
var_dump( Mage::helper('buildateam_shippo')->getWeightUnit() );
|
30 |
+
echo '<br/>';
|
31 |
+
var_dump( Mage::helper('buildateam_shippo')->getSizeUnit() );
|
32 |
+
echo '<br/>';
|
33 |
+
var_dump( Mage::helper('buildateam_shippo')->getHandling() );
|
34 |
+
|
35 |
+
|
36 |
+
}
|
37 |
+
|
38 |
+
}
|
app/code/community/Buildateam/Shippo/etc/adminhtml.xml
ADDED
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<config>
|
3 |
+
<acl>
|
4 |
+
<resources>
|
5 |
+
<admin>
|
6 |
+
<children>
|
7 |
+
<system>
|
8 |
+
<children>
|
9 |
+
<config>
|
10 |
+
<children>
|
11 |
+
<buildateam_shippo translate="title" module="buildateam_shippo">
|
12 |
+
<title>Buildateam Shippo</title>
|
13 |
+
<sort_order>0</sort_order>
|
14 |
+
</buildateam_shippo>
|
15 |
+
</children>
|
16 |
+
</config>
|
17 |
+
</children>
|
18 |
+
</system>
|
19 |
+
</children>
|
20 |
+
</admin>
|
21 |
+
</resources>
|
22 |
+
</acl>
|
23 |
+
</config>
|
app/code/community/Buildateam/Shippo/etc/config.xml
ADDED
@@ -0,0 +1,118 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<config>
|
3 |
+
<modules>
|
4 |
+
<Buildateam_Shippo>
|
5 |
+
<version>1.0.2</version>
|
6 |
+
</Buildateam_Shippo>
|
7 |
+
</modules>
|
8 |
+
<default>
|
9 |
+
<carriers>
|
10 |
+
<buildateam_shippo>
|
11 |
+
<active>0</active>
|
12 |
+
|
13 |
+
<private_auth_token>167263307a16e8b1c51fbf4b055decc85b683678</private_auth_token>
|
14 |
+
|
15 |
+
<from_name>JOHN SMITH</from_name>
|
16 |
+
<from_company>BEST COMPANY EVER</from_company>
|
17 |
+
<from_country>US</from_country>
|
18 |
+
<from_region>19</from_region>
|
19 |
+
<from_postcode>30320</from_postcode>
|
20 |
+
<from_city>Atlanta</from_city>
|
21 |
+
<from_street>9050A ALEXA AVE SE</from_street>
|
22 |
+
<from_phone>111-111-1111</from_phone>
|
23 |
+
<from_email>john.smith@bestcompany.com</from_email>
|
24 |
+
|
25 |
+
<weight_unit>lb</weight_unit>
|
26 |
+
<size_unit>in</size_unit>
|
27 |
+
<shipping_handling>0</shipping_handling>
|
28 |
+
|
29 |
+
<model>buildateam_shippo/carrier</model>
|
30 |
+
<title>Shippo</title>
|
31 |
+
<sort_order>10</sort_order>
|
32 |
+
<sallowspecific>1</sallowspecific>
|
33 |
+
<specificcountry>US</specificcountry>
|
34 |
+
<economy_description>
|
35 |
+
<![CDATA[<div class="s_methodTop">(3-6 business days)</div><div class="s_methodBottom">ORDER BY 1PM PST DEC 15TH TO RECIEVE BY DEC 24TH</div>]]></economy_description>
|
36 |
+
<expedited_description>
|
37 |
+
<![CDATA[<div class="s_methodTop">(2-3 business days)</div><div class="s_methodBottom">ORDER BY 10AM PST DEC 22ND TO RECIEVE BY DEC 24TH</div>]]></expedited_description>
|
38 |
+
<overnight_description>
|
39 |
+
<![CDATA[<div class="s_methodTop">(1-2 business days)</div><div class="s_methodMiddle">ORDERS MUST PLACED BY 10AM PST M-TH</div><div class="s_methodBottom">ORDER BY 1PM PST DEC 23RD TO RECIEVE BY DEC 24TH</div>]]></overnight_description>
|
40 |
+
<expedited_cost>32.00</expedited_cost>
|
41 |
+
<overnight_cost>70.00</overnight_cost>
|
42 |
+
</buildateam_shippo>
|
43 |
+
</carriers>
|
44 |
+
<buildateam_shippo>
|
45 |
+
<general>
|
46 |
+
<email_delay>30</email_delay>
|
47 |
+
<enable>1</enable>
|
48 |
+
</general>
|
49 |
+
</buildateam_shippo>
|
50 |
+
</default>
|
51 |
+
<frontend>
|
52 |
+
<layout>
|
53 |
+
<updates>
|
54 |
+
</updates>
|
55 |
+
</layout>
|
56 |
+
<routers>
|
57 |
+
<buildateam_shippo>
|
58 |
+
<use>standard</use>
|
59 |
+
<args>
|
60 |
+
<module>Buildateam_Shippo</module>
|
61 |
+
<frontName>buildateamshippo</frontName>
|
62 |
+
</args>
|
63 |
+
</buildateam_shippo>
|
64 |
+
</routers>
|
65 |
+
</frontend>
|
66 |
+
<adminhtml>
|
67 |
+
<layout>
|
68 |
+
<updates>
|
69 |
+
<buildateam_shippo>
|
70 |
+
<file>buildateam/shippo.xml</file>
|
71 |
+
</buildateam_shippo>
|
72 |
+
</updates>
|
73 |
+
</layout>
|
74 |
+
</adminhtml>
|
75 |
+
<global>
|
76 |
+
<helpers>
|
77 |
+
<buildateam_shippo>
|
78 |
+
<class>Buildateam_Shippo_Helper</class>
|
79 |
+
</buildateam_shippo>
|
80 |
+
</helpers>
|
81 |
+
<blocks>
|
82 |
+
<buildateam_shippo>
|
83 |
+
<class>Buildateam_Shippo_Block</class>
|
84 |
+
</buildateam_shippo>
|
85 |
+
</blocks>
|
86 |
+
<models>
|
87 |
+
<buildateam_shippo>
|
88 |
+
<class>Buildateam_Shippo_Model</class>
|
89 |
+
<resourceModel>buildateam_shippo_resource</resourceModel>
|
90 |
+
</buildateam_shippo>
|
91 |
+
<buildateam_shippo_resource>
|
92 |
+
<class>Buildateam_Shippo_Model_Resource</class>
|
93 |
+
<entities>
|
94 |
+
</entities>
|
95 |
+
</buildateam_shippo_resource>
|
96 |
+
</models>
|
97 |
+
<resources>
|
98 |
+
<buildateam_shippo_setup>
|
99 |
+
<setup>
|
100 |
+
<module>Buildateam_Shippo</module>
|
101 |
+
</setup>
|
102 |
+
<connection>
|
103 |
+
<use>core_setup</use>
|
104 |
+
</connection>
|
105 |
+
</buildateam_shippo_setup>
|
106 |
+
</resources>
|
107 |
+
<template>
|
108 |
+
<email>
|
109 |
+
</email>
|
110 |
+
</template>
|
111 |
+
<events>
|
112 |
+
</events>
|
113 |
+
</global>
|
114 |
+
<crontab>
|
115 |
+
<jobs>
|
116 |
+
</jobs>
|
117 |
+
</crontab>
|
118 |
+
</config>
|
app/code/community/Buildateam/Shippo/etc/system.xml
ADDED
@@ -0,0 +1,185 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<config>
|
3 |
+
<sections>
|
4 |
+
<carriers>
|
5 |
+
<groups>
|
6 |
+
<buildateam_shippo translate="label" module="buildateam_shippo">
|
7 |
+
<label>Shippo</label>
|
8 |
+
<frontend_type>text</frontend_type>
|
9 |
+
<sort_order>10</sort_order>
|
10 |
+
<show_in_default>1</show_in_default>
|
11 |
+
<show_in_website>1</show_in_website>
|
12 |
+
<show_in_store>1</show_in_store>
|
13 |
+
<fields>
|
14 |
+
<active translate="label">
|
15 |
+
<label>Enabled for Checkout</label>
|
16 |
+
<frontend_type>select</frontend_type>
|
17 |
+
<source_model>adminhtml/system_config_source_yesno</source_model>
|
18 |
+
<sort_order>2</sort_order>
|
19 |
+
<show_in_default>1</show_in_default>
|
20 |
+
<show_in_website>1</show_in_website>
|
21 |
+
<show_in_store>0</show_in_store>
|
22 |
+
</active>
|
23 |
+
|
24 |
+
<private_auth_token translate="label">
|
25 |
+
<label>Private Auth Token</label>
|
26 |
+
<frontend_type>text</frontend_type>
|
27 |
+
<validate>required-entry</validate>
|
28 |
+
<sort_order>8</sort_order>
|
29 |
+
<show_in_default>1</show_in_default>
|
30 |
+
<show_in_website>1</show_in_website>
|
31 |
+
<show_in_store>1</show_in_store>
|
32 |
+
</private_auth_token>
|
33 |
+
|
34 |
+
<from_name translate="label">
|
35 |
+
<label>From Name</label>
|
36 |
+
<frontend_type>text</frontend_type>
|
37 |
+
<validate>required-entry</validate>
|
38 |
+
<sort_order>9</sort_order>
|
39 |
+
<show_in_default>1</show_in_default>
|
40 |
+
<show_in_website>1</show_in_website>
|
41 |
+
<show_in_store>1</show_in_store>
|
42 |
+
</from_name>
|
43 |
+
<from_company translate="label">
|
44 |
+
<label>From Company</label>
|
45 |
+
<frontend_type>text</frontend_type>
|
46 |
+
<validate>required-entry</validate>
|
47 |
+
<sort_order>10</sort_order>
|
48 |
+
<show_in_default>1</show_in_default>
|
49 |
+
<show_in_website>1</show_in_website>
|
50 |
+
<show_in_store>1</show_in_store>
|
51 |
+
</from_company>
|
52 |
+
<from_country translate="label">
|
53 |
+
<label>From Country</label>
|
54 |
+
<frontend_type>select</frontend_type>
|
55 |
+
<validate>required-entry</validate>
|
56 |
+
<source_model>adminhtml/system_config_source_country</source_model>
|
57 |
+
<sort_order>11</sort_order>
|
58 |
+
<show_in_default>1</show_in_default>
|
59 |
+
<show_in_website>1</show_in_website>
|
60 |
+
<show_in_store>1</show_in_store>
|
61 |
+
</from_country>
|
62 |
+
<from_region translate="label">
|
63 |
+
<label><![CDATA[From State/Province]]></label>
|
64 |
+
<frontend_type>select</frontend_type>
|
65 |
+
<validate>required-entry</validate>
|
66 |
+
<frontend_model>buildateam_shippo/adminhtml_frontend_region_updater</frontend_model>
|
67 |
+
<source_model>buildateam_shippo/system_config_source_region</source_model>
|
68 |
+
<sort_order>12</sort_order>
|
69 |
+
<show_in_default>1</show_in_default>
|
70 |
+
<show_in_website>1</show_in_website>
|
71 |
+
<show_in_store>1</show_in_store>
|
72 |
+
</from_region>
|
73 |
+
<from_postcode translate="label">
|
74 |
+
<label><![CDATA[From Zip/Postal Code]]></label>
|
75 |
+
<frontend_type>text</frontend_type>
|
76 |
+
<validate>required-entry</validate>
|
77 |
+
<sort_order>13</sort_order>
|
78 |
+
<show_in_default>1</show_in_default>
|
79 |
+
<show_in_website>1</show_in_website>
|
80 |
+
<show_in_store>1</show_in_store>
|
81 |
+
</from_postcode>
|
82 |
+
<from_city translate="label">
|
83 |
+
<label>From City</label>
|
84 |
+
<frontend_type>text</frontend_type>
|
85 |
+
<validate>required-entry</validate>
|
86 |
+
<sort_order>14</sort_order>
|
87 |
+
<show_in_default>1</show_in_default>
|
88 |
+
<show_in_website>1</show_in_website>
|
89 |
+
<show_in_store>1</show_in_store>
|
90 |
+
</from_city>
|
91 |
+
<from_street translate="label">
|
92 |
+
<label>From Street Address</label>
|
93 |
+
<frontend_type>text</frontend_type>
|
94 |
+
<validate>required-entry</validate>
|
95 |
+
<sort_order>15</sort_order>
|
96 |
+
<show_in_default>1</show_in_default>
|
97 |
+
<show_in_website>1</show_in_website>
|
98 |
+
<show_in_store>1</show_in_store>
|
99 |
+
</from_street>
|
100 |
+
<from_phone translate="label">
|
101 |
+
<label>From Telephone</label>
|
102 |
+
<frontend_type>text</frontend_type>
|
103 |
+
<validate>required-entry</validate>
|
104 |
+
<sort_order>16</sort_order>
|
105 |
+
<show_in_default>1</show_in_default>
|
106 |
+
<show_in_website>1</show_in_website>
|
107 |
+
<show_in_store>1</show_in_store>
|
108 |
+
</from_phone>
|
109 |
+
<from_email translate="label">
|
110 |
+
<label>From Email</label>
|
111 |
+
<frontend_type>text</frontend_type>
|
112 |
+
<validate>required-entry</validate>
|
113 |
+
<sort_order>17</sort_order>
|
114 |
+
<show_in_default>1</show_in_default>
|
115 |
+
<show_in_website>1</show_in_website>
|
116 |
+
<show_in_store>1</show_in_store>
|
117 |
+
</from_email>
|
118 |
+
|
119 |
+
<weight_unit translate="label">
|
120 |
+
<label>Weight Unit</label>
|
121 |
+
<frontend_type>select</frontend_type>
|
122 |
+
<validate>required-entry</validate>
|
123 |
+
<source_model>buildateam_shippo/system_config_source_weight</source_model>
|
124 |
+
<sort_order>19</sort_order>
|
125 |
+
<show_in_default>1</show_in_default>
|
126 |
+
<show_in_website>1</show_in_website>
|
127 |
+
<show_in_store>1</show_in_store>
|
128 |
+
</weight_unit>
|
129 |
+
<size_unit translate="label">
|
130 |
+
<label>Dimensions Unit</label>
|
131 |
+
<frontend_type>select</frontend_type>
|
132 |
+
<validate>required-entry</validate>
|
133 |
+
<source_model>buildateam_shippo/system_config_source_size</source_model>
|
134 |
+
<sort_order>21</sort_order>
|
135 |
+
<show_in_default>1</show_in_default>
|
136 |
+
<show_in_website>1</show_in_website>
|
137 |
+
<show_in_store>1</show_in_store>
|
138 |
+
</size_unit>
|
139 |
+
<shipping_handling translate="label">
|
140 |
+
<label><![CDATA[Shipping & Handling]]></label>
|
141 |
+
<comment>In store currency.</comment>
|
142 |
+
<frontend_type>text</frontend_type>
|
143 |
+
<validate>required-entry validate-number</validate>
|
144 |
+
<sort_order>23</sort_order>
|
145 |
+
<show_in_default>1</show_in_default>
|
146 |
+
<show_in_website>1</show_in_website>
|
147 |
+
<show_in_store>1</show_in_store>
|
148 |
+
</shipping_handling>
|
149 |
+
|
150 |
+
<sallowspecific translate="label">
|
151 |
+
<label>Ship to Applicable Countries</label>
|
152 |
+
<frontend_type>select</frontend_type>
|
153 |
+
<sort_order>70</sort_order>
|
154 |
+
<frontend_class>shipping-applicable-country</frontend_class>
|
155 |
+
<source_model>adminhtml/system_config_source_shipping_allspecificcountries</source_model>
|
156 |
+
<show_in_default>1</show_in_default>
|
157 |
+
<show_in_website>1</show_in_website>
|
158 |
+
<show_in_store>0</show_in_store>
|
159 |
+
</sallowspecific>
|
160 |
+
<specificcountry translate="label">
|
161 |
+
<label>Ship to Specific Countries</label>
|
162 |
+
<frontend_type>multiselect</frontend_type>
|
163 |
+
<sort_order>80</sort_order>
|
164 |
+
<source_model>adminhtml/system_config_source_country</source_model>
|
165 |
+
<show_in_default>1</show_in_default>
|
166 |
+
<show_in_website>1</show_in_website>
|
167 |
+
<show_in_store>0</show_in_store>
|
168 |
+
<can_be_empty>1</can_be_empty>
|
169 |
+
</specificcountry>
|
170 |
+
<!--
|
171 |
+
<sort_order translate="label">
|
172 |
+
<label>Sort Order</label>
|
173 |
+
<frontend_type>text</frontend_type>
|
174 |
+
<sort_order>90</sort_order>
|
175 |
+
<show_in_default>1</show_in_default>
|
176 |
+
<show_in_website>1</show_in_website>
|
177 |
+
<show_in_store>0</show_in_store>
|
178 |
+
</sort_order>
|
179 |
+
-->
|
180 |
+
</fields>
|
181 |
+
</buildateam_shippo>
|
182 |
+
</groups>
|
183 |
+
</carriers>
|
184 |
+
</sections>
|
185 |
+
</config>
|
app/code/community/Buildateam/Shippo/sql/buildateam_shippo_setup/mysql4-upgrade-1.0.0-1.0.1.php
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
$installer = $this;
|
3 |
+
|
4 |
+
$installer->startSetup();
|
5 |
+
|
6 |
+
|
7 |
+
$installer->endSetup();
|
app/code/community/Buildateam/Shippo/sql/buildateam_shippo_setup/mysql4-upgrade-1.0.1-1.0.2.php
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
$installer = $this;
|
4 |
+
|
5 |
+
$installer->startSetup();
|
6 |
+
|
7 |
+
$objCatalogEavSetup = Mage::getResourceModel('catalog/eav_mysql4_setup', 'core_setup');
|
8 |
+
|
9 |
+
$objCatalogEavSetup->addAttribute(
|
10 |
+
"catalog_product", // Entity the new attribute is supposed to be added to
|
11 |
+
"dimensions_lwh", // attribute code
|
12 |
+
array(
|
13 |
+
"type" => "varchar",
|
14 |
+
"label" => "Dimensions",
|
15 |
+
"note" => "Length, Width and Height. Example: 15.5x7.5x5",
|
16 |
+
"input" => "text",
|
17 |
+
"frontend_class" => "validate-dimentions-lwh",
|
18 |
+
"global" => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_GLOBAL,
|
19 |
+
// Dont know if this is really necessary, but it makes sure
|
20 |
+
// the attribute is created as a system attribute:
|
21 |
+
'required' => false,
|
22 |
+
"user_defined" => false,
|
23 |
+
//"apply_to" => Mage_Catalog_Model_Product_Type::TYPE_CONFIGURABLE,
|
24 |
+
'apply_to' => implode(',', array(
|
25 |
+
Mage_Catalog_Model_Product_Type::TYPE_CONFIGURABLE,
|
26 |
+
Mage_Catalog_Model_Product_Type::TYPE_SIMPLE,
|
27 |
+
)),
|
28 |
+
'sort_order' => 9
|
29 |
+
)
|
30 |
+
);
|
31 |
+
|
32 |
+
$installer->endSetup();
|
app/design/adminhtml/default/default/layout/buildateam/shippo.xml
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<layout>
|
3 |
+
<adminhtml_catalog_product_new>
|
4 |
+
<update handle="buildateam_shippo_catalog_product_js"/>
|
5 |
+
</adminhtml_catalog_product_new>
|
6 |
+
|
7 |
+
<adminhtml_catalog_product_edit>
|
8 |
+
<update handle="buildateam_shippo_catalog_product_js"/>
|
9 |
+
</adminhtml_catalog_product_edit>
|
10 |
+
|
11 |
+
<buildateam_shippo_catalog_product_js>
|
12 |
+
<reference name="before_body_end">
|
13 |
+
<block type="core/template" name="buildateam_shippo_product_js" as="buildateam_shippo_product_js" template="buildateam/shippo/catalog/product/js.phtml"/>
|
14 |
+
</reference>
|
15 |
+
</buildateam_shippo_catalog_product_js>
|
16 |
+
</layout>
|
app/design/adminhtml/default/default/template/buildateam/shippo/catalog/product/js.phtml
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
?>
|
4 |
+
<script type="text/javascript">
|
5 |
+
Event.observe(window, 'load', function(){
|
6 |
+
Validation.add('validate-dimentions-lwh','Should be in the form of 17.3x8x7',function(v){
|
7 |
+
|
8 |
+
if ( Validation.get('IsEmpty').test(v) || v.match(/([\.\d])+x([\.\d])+x([\.\d])+/) ) {
|
9 |
+
return true;
|
10 |
+
}
|
11 |
+
|
12 |
+
return false;
|
13 |
+
});
|
14 |
+
});
|
15 |
+
</script>
|
app/etc/modules/Buildateam_Shippo.xml
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<config>
|
3 |
+
<modules>
|
4 |
+
<Buildateam_Shippo>
|
5 |
+
<active>true</active>
|
6 |
+
<codePool>community</codePool>
|
7 |
+
<version>1.0.0</version>
|
8 |
+
</Buildateam_Shippo>
|
9 |
+
</modules>
|
10 |
+
</config>
|
lib/Shippo.php
ADDED
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Tested on PHP 5.2, 5.3
|
4 |
+
if (!function_exists('curl_init')) {
|
5 |
+
throw new Exception('Shippo needs the CURL PHP extension.');
|
6 |
+
}
|
7 |
+
if (!function_exists('json_decode')) {
|
8 |
+
throw new Exception('Shippo needs the JSON PHP extension.');
|
9 |
+
}
|
10 |
+
if (!function_exists('mb_detect_encoding')) {
|
11 |
+
throw new Exception('Shippo needs the Multibyte String PHP extension.');
|
12 |
+
}
|
13 |
+
|
14 |
+
// Shippo singleton
|
15 |
+
require(dirname(__FILE__) . '/Shippo/Shippo.php');
|
16 |
+
|
17 |
+
// Utilities
|
18 |
+
require(dirname(__FILE__) . '/Shippo/Util.php');
|
19 |
+
require(dirname(__FILE__) . '/Shippo/Util/Set.php');
|
20 |
+
|
21 |
+
// Errors
|
22 |
+
require(dirname(__FILE__) . '/Shippo/Error.php');
|
23 |
+
require(dirname(__FILE__) . '/Shippo/ApiError.php');
|
24 |
+
require(dirname(__FILE__) . '/Shippo/ApiConnectionError.php');
|
25 |
+
require(dirname(__FILE__) . '/Shippo/AuthenticationError.php');
|
26 |
+
require(dirname(__FILE__) . '/Shippo/InvalidRequestError.php');
|
27 |
+
require(dirname(__FILE__) . '/Shippo/RateLimitError.php');
|
28 |
+
|
29 |
+
// Plumbing
|
30 |
+
require(dirname(__FILE__) . '/Shippo/Object.php');
|
31 |
+
require(dirname(__FILE__) . '/Shippo/ApiRequestor.php');
|
32 |
+
require(dirname(__FILE__) . '/Shippo/ApiResource.php');
|
33 |
+
require(dirname(__FILE__) . '/Shippo/SingletonApiResource.php');
|
34 |
+
require(dirname(__FILE__) . '/Shippo/AttachedObject.php');
|
35 |
+
require(dirname(__FILE__) . '/Shippo/List.php');
|
36 |
+
|
37 |
+
// Shippo API Resources
|
38 |
+
require(dirname(__FILE__) . '/Shippo/Address.php');
|
39 |
+
require(dirname(__FILE__) . '/Shippo/Parcel.php');
|
40 |
+
require(dirname(__FILE__) . '/Shippo/Shipment.php');
|
41 |
+
require(dirname(__FILE__) . '/Shippo/Rate.php');
|
42 |
+
require(dirname(__FILE__) . '/Shippo/Transaction.php');
|
43 |
+
require(dirname(__FILE__) . '/Shippo/CustomsItem.php');
|
44 |
+
require(dirname(__FILE__) . '/Shippo/CustomsDeclaration.php');
|
45 |
+
require(dirname(__FILE__) . '/Shippo/Refund.php');
|
46 |
+
require(dirname(__FILE__) . '/Shippo/Manifest.php');
|
47 |
+
require(dirname(__FILE__) . '/Shippo/CarrierAccount.php');
|
lib/Shippo/Address.php
ADDED
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Shippo_Address extends Shippo_ApiResource
|
4 |
+
{
|
5 |
+
/**
|
6 |
+
* @param string $class Ignored.
|
7 |
+
*
|
8 |
+
* @return string The class URL for this resource. It needs to be special
|
9 |
+
* cased because it doesn't fit into the standard resource pattern.
|
10 |
+
* The standard resource pattern is name + s, e.g. parcel becomes parcels.
|
11 |
+
*/
|
12 |
+
public static function classUrl($class)
|
13 |
+
{
|
14 |
+
return "/v1/addresses";
|
15 |
+
}
|
16 |
+
|
17 |
+
/**
|
18 |
+
* @param array|null $params
|
19 |
+
* @param string|null $apiKey
|
20 |
+
*
|
21 |
+
* @return Shippo_Adress Create an Address.
|
22 |
+
*/
|
23 |
+
public static function create($params = null, $apiKey = null)
|
24 |
+
{
|
25 |
+
$class = get_class();
|
26 |
+
return self::_scopedCreate($class, $params, $apiKey);
|
27 |
+
}
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @param array|null $params
|
31 |
+
*
|
32 |
+
* @return Shippo_Retrieve Get an address.
|
33 |
+
*/
|
34 |
+
public static function retrieve($id, $apiKey = null)
|
35 |
+
{
|
36 |
+
$class = get_class();
|
37 |
+
return self::_scopedRetrieve($class, $id, $apiKey);
|
38 |
+
}
|
39 |
+
|
40 |
+
/**
|
41 |
+
* @param array|null $params
|
42 |
+
*
|
43 |
+
* @return Shippo_All Get all the addresses.
|
44 |
+
*/
|
45 |
+
public static function all($params = null, $apiKey = null)
|
46 |
+
{
|
47 |
+
$class = get_class();
|
48 |
+
return self::_scopedAll($class, $params, $apiKey);
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* @param array|null $params
|
53 |
+
*
|
54 |
+
* @return Shippo_Validate Validate an address.
|
55 |
+
*/
|
56 |
+
public static function validate($id)
|
57 |
+
{
|
58 |
+
$class = get_class();
|
59 |
+
return self::_scopedValidate($class, $id);
|
60 |
+
}
|
61 |
+
}
|
lib/Shippo/ApiConnectionError.php
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Shippo_ApiConnectionError extends Shippo_Error
|
4 |
+
{
|
5 |
+
}
|
lib/Shippo/ApiError.php
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Shippo_ApiError extends Shippo_Error
|
4 |
+
{
|
5 |
+
}
|
lib/Shippo/ApiRequestor.php
ADDED
@@ -0,0 +1,281 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Shippo_ApiRequestor
|
3 |
+
{
|
4 |
+
/**
|
5 |
+
* @var string $apiKey The API key that's to be used to make requests.
|
6 |
+
*/
|
7 |
+
public $apiKey;
|
8 |
+
|
9 |
+
public function __construct($apiKey = null)
|
10 |
+
{
|
11 |
+
$this->_apiKey = $apiKey;
|
12 |
+
}
|
13 |
+
|
14 |
+
/**
|
15 |
+
* @param string $url The path to the API endpoint.
|
16 |
+
*
|
17 |
+
* @returns string The full path.
|
18 |
+
*/
|
19 |
+
public static function apiUrl($url = '')
|
20 |
+
{
|
21 |
+
$apiBase = Shippo::$apiBase;
|
22 |
+
return "$apiBase$url";
|
23 |
+
}
|
24 |
+
|
25 |
+
/**
|
26 |
+
* @param string|mixed $value A string to UTF8-encode.
|
27 |
+
*
|
28 |
+
* @returns string|mixed The UTF8-encoded string, or the object passed in if
|
29 |
+
* it wasn't a string.
|
30 |
+
*/
|
31 |
+
public static function utf8($value)
|
32 |
+
{
|
33 |
+
if (is_string($value) && mb_detect_encoding($value, "UTF-8", TRUE) != "UTF-8") {
|
34 |
+
return utf8_encode($value);
|
35 |
+
} else {
|
36 |
+
return $value;
|
37 |
+
}
|
38 |
+
}
|
39 |
+
|
40 |
+
private static function _encodeObjects($d)
|
41 |
+
{
|
42 |
+
if ($d instanceof Shippo_ApiResource) {
|
43 |
+
return self::utf8($d->id);
|
44 |
+
} else if ($d instanceof Shippo_Object) {
|
45 |
+
return self::utf8($d->object_id);
|
46 |
+
} else if ($d === true) {
|
47 |
+
return 'true';
|
48 |
+
} else if ($d === false) {
|
49 |
+
return 'false';
|
50 |
+
} else if (is_array($d)) {
|
51 |
+
$res = array();
|
52 |
+
foreach ($d as $k => $v)
|
53 |
+
$res[$k] = self::_encodeObjects($v);
|
54 |
+
return $res;
|
55 |
+
} else {
|
56 |
+
return self::utf8($d);
|
57 |
+
}
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* @param array $arr An map of param keys to values.
|
62 |
+
* @param string|null $prefix (It doesn't look like we ever use $prefix...)
|
63 |
+
*
|
64 |
+
* @returns string A querystring, essentially.
|
65 |
+
*/
|
66 |
+
public static function encode($arr, $prefix = null)
|
67 |
+
{
|
68 |
+
if (!is_array($arr))
|
69 |
+
return $arr;
|
70 |
+
|
71 |
+
$r = array();
|
72 |
+
foreach ($arr as $k => $v) {
|
73 |
+
if (is_null($v))
|
74 |
+
continue;
|
75 |
+
|
76 |
+
if ($prefix && $k && !is_int($k))
|
77 |
+
$k = $prefix . "[" . $k . "]";
|
78 |
+
else if ($prefix)
|
79 |
+
$k = $prefix . "[]";
|
80 |
+
|
81 |
+
if (is_array($v)) {
|
82 |
+
$r[] = self::encode($v, $k, true);
|
83 |
+
} else {
|
84 |
+
$r[] = urlencode($k) . "=" . urlencode($v);
|
85 |
+
}
|
86 |
+
}
|
87 |
+
|
88 |
+
return implode("&", $r);
|
89 |
+
}
|
90 |
+
|
91 |
+
/**
|
92 |
+
* @param string $method
|
93 |
+
* @param string $url
|
94 |
+
* @param array|null $params
|
95 |
+
*
|
96 |
+
* @return array An array whose first element is the response and second
|
97 |
+
* element is the API key used to make the request.
|
98 |
+
*/
|
99 |
+
public function request($method, $url, $params = null)
|
100 |
+
{
|
101 |
+
if (!$params)
|
102 |
+
$params = array();
|
103 |
+
list($rbody, $rcode, $myApiKey) = $this->_requestRaw($method, $url, $params);
|
104 |
+
$resp = $this->_interpretResponse($rbody, $rcode);
|
105 |
+
return array(
|
106 |
+
$resp,
|
107 |
+
$myApiKey
|
108 |
+
);
|
109 |
+
}
|
110 |
+
|
111 |
+
|
112 |
+
/**
|
113 |
+
* @param string $rbody A JSON string.
|
114 |
+
* @param int $rcode
|
115 |
+
* @param array $resp
|
116 |
+
*
|
117 |
+
* @throws Shippo_InvalidRequestError if the error is caused by the user.
|
118 |
+
* @throws Shippo_AuthenticationError if the error is caused by a lack of
|
119 |
+
* permissions.
|
120 |
+
* @throws Shippo_ApiError otherwise.
|
121 |
+
*/
|
122 |
+
public function handleApiError($rbody, $rcode, $resp)
|
123 |
+
{
|
124 |
+
// Array is not currently being returned by API, making the below N/A
|
125 |
+
// if (!is_array($resp) || !isset($resp['error'])) {
|
126 |
+
// $msg = "Invalid response object from API: $rbody "
|
127 |
+
// ."(HTTP response code was $rcode)";
|
128 |
+
// throw new Shippo_ApiError($msg, $rcode, $rbody, $resp);
|
129 |
+
// }
|
130 |
+
|
131 |
+
$msg = "message not set";
|
132 |
+
$param = "parameters not set";
|
133 |
+
$code = "code not set";
|
134 |
+
|
135 |
+
// Temporary setting of msg to rbody
|
136 |
+
$msg = $rbody;
|
137 |
+
|
138 |
+
// Parameters necessary for error code construction are not provided
|
139 |
+
// $error = $resp['error'];
|
140 |
+
// $msg = isset($error['message']) ? $error['message'] : null;
|
141 |
+
// $param = isset($error['param']) ? $error['param'] : null;
|
142 |
+
// $code = isset($error['code']) ? $error['code'] : null;
|
143 |
+
|
144 |
+
switch ($rcode) {
|
145 |
+
case 400:
|
146 |
+
throw new Shippo_InvalidRequestError($msg, $param, $rcode, $rbody, $resp);
|
147 |
+
case 404:
|
148 |
+
throw new Shippo_InvalidRequestError($msg, $param, $rcode, $rbody, $resp);
|
149 |
+
case 401:
|
150 |
+
throw new Shippo_AuthenticationError($msg, $rcode, $rbody, $resp);
|
151 |
+
default:
|
152 |
+
throw new Shippo_ApiError($msg, $rcode, $rbody, $resp);
|
153 |
+
}
|
154 |
+
}
|
155 |
+
|
156 |
+
private function _requestRaw($method, $url, $params)
|
157 |
+
{
|
158 |
+
$myApiKey = $this->_apiKey;
|
159 |
+
if (!$myApiKey)
|
160 |
+
$myApiKey = Shippo::$apiKey;
|
161 |
+
|
162 |
+
if (!$myApiKey) {
|
163 |
+
$msg = 'No credentials provided.';
|
164 |
+
throw new Shippo_AuthenticationError($msg);
|
165 |
+
}
|
166 |
+
|
167 |
+
$absUrl = $this->apiUrl($url);
|
168 |
+
$params = self::_encodeObjects($params);
|
169 |
+
$langVersion = phpversion();
|
170 |
+
$uname = php_uname();
|
171 |
+
$headers = array(
|
172 |
+
'Content-Type: application/json',
|
173 |
+
'Authorization: ShippoToken ' . $myApiKey,
|
174 |
+
'Accept: application/json',
|
175 |
+
'User-Agent: Shippo/v1 PHPBindings/' . Shippo::VERSION
|
176 |
+
);
|
177 |
+
|
178 |
+
list($rbody, $rcode) = $this->_curlRequest($method, $absUrl, $headers, $params);
|
179 |
+
return array(
|
180 |
+
$rbody,
|
181 |
+
$rcode,
|
182 |
+
$myApiKey
|
183 |
+
);
|
184 |
+
}
|
185 |
+
|
186 |
+
private function _interpretResponse($rbody, $rcode)
|
187 |
+
{
|
188 |
+
try {
|
189 |
+
$resp = json_decode($rbody, true);
|
190 |
+
}
|
191 |
+
catch (Exception $e) {
|
192 |
+
$msg = "Invalid response body from API: $rbody " . "(HTTP response code was $rcode)";
|
193 |
+
throw new Shippo_ApiError($msg, $rcode, $rbody);
|
194 |
+
}
|
195 |
+
|
196 |
+
if ($rcode < 200 || $rcode >= 300) {
|
197 |
+
$this->handleApiError($rbody, $rcode, $resp);
|
198 |
+
}
|
199 |
+
return $resp;
|
200 |
+
}
|
201 |
+
|
202 |
+
private function _curlRequest($method, $absUrl, $headers, $params)
|
203 |
+
{
|
204 |
+
$curl = curl_init();
|
205 |
+
$method = strtolower($method);
|
206 |
+
$curlOptions = array();
|
207 |
+
|
208 |
+
// Request Method
|
209 |
+
if ($method == 'get') {
|
210 |
+
$curlOptions[CURLOPT_HTTPGET] = 1;
|
211 |
+
if (count($params) > 0) {
|
212 |
+
$encoded = self::encode($params);
|
213 |
+
$absUrl = "$absUrl?$encoded";
|
214 |
+
}
|
215 |
+
} else if ($method == 'post') {
|
216 |
+
$curlOptions[CURLOPT_POST] = 1;
|
217 |
+
$curlOptions[CURLOPT_POSTFIELDS] = json_encode($params);
|
218 |
+
} else if ($method == 'put') {
|
219 |
+
$curlOptions[CURLOPT_CUSTOMREQUEST] = 'PUT';
|
220 |
+
$curlOptions[CURLOPT_POSTFIELDS] = json_encode($params);
|
221 |
+
} else {
|
222 |
+
throw new Error("Unrecognized method {$method}");
|
223 |
+
}
|
224 |
+
// echo("<br><br>ABSOLUTE URL: " . $absUrl . "<br><br>");
|
225 |
+
$absUrl = self::utf8($absUrl);
|
226 |
+
$curlOptions[CURLOPT_URL] = $absUrl;
|
227 |
+
$curlOptions[CURLOPT_RETURNTRANSFER] = true;
|
228 |
+
$curlOptions[CURLOPT_CONNECTTIMEOUT] = 30;
|
229 |
+
$curlOptions[CURLOPT_TIMEOUT] = 80;
|
230 |
+
$curlOptions[CURLOPT_HTTPHEADER] = $headers;
|
231 |
+
// echo(var_dump($headers));
|
232 |
+
$curlOptions[CURLOPT_FOLLOWLOCATION] = TRUE;
|
233 |
+
|
234 |
+
curl_setopt_array($curl, $curlOptions);
|
235 |
+
$httpBody = curl_exec($curl);
|
236 |
+
|
237 |
+
$errorNum = curl_errno($curl);
|
238 |
+
if ($errorNum == CURLE_SSL_CACERT || $errorNum == CURLE_SSL_PEER_CERTIFICATE || $errorNum == 77) {
|
239 |
+
curl_setopt($curl, CURLOPT_CAINFO, dirname(__FILE__) . '/../cacert.pem');
|
240 |
+
$httpBody = curl_exec($curl);
|
241 |
+
}
|
242 |
+
|
243 |
+
if ($httpBody === false) {
|
244 |
+
$errorNum = curl_errno($curl);
|
245 |
+
$message = curl_error($curl);
|
246 |
+
curl_close($curl);
|
247 |
+
$this->handleCurlError($errorNum, $message);
|
248 |
+
}
|
249 |
+
|
250 |
+
$httpStatus = curl_getinfo($curl, CURLINFO_HTTP_CODE);
|
251 |
+
curl_close($curl);
|
252 |
+
// echo("<br><br>RESPONSE<br><br>".$httpBody);
|
253 |
+
// echo("<br><br>STATUS<br><br>".$httpStatus);
|
254 |
+
return array(
|
255 |
+
$httpBody,
|
256 |
+
$httpStatus
|
257 |
+
);
|
258 |
+
}
|
259 |
+
|
260 |
+
/**
|
261 |
+
* @param number $errno
|
262 |
+
* @param string $message
|
263 |
+
* @throws Shippo_ApiConnectionError
|
264 |
+
*/
|
265 |
+
public function handleCurlError($errno, $message)
|
266 |
+
{
|
267 |
+
$apiBase = Shippo::$apiBase;
|
268 |
+
switch ($errno) {
|
269 |
+
case CURLE_COULDNT_CONNECT:
|
270 |
+
case CURLE_COULDNT_RESOLVE_HOST:
|
271 |
+
case CURLE_OPERATION_TIMEOUTED:
|
272 |
+
$msg = "Could not connect to Shippo ($apiBase).";
|
273 |
+
break;
|
274 |
+
default:
|
275 |
+
$msg = "Unexpected error communicating with Shippo. " . "If this problem persists,";
|
276 |
+
}
|
277 |
+
$msg .= " let us know by contacting us through our contact form.";
|
278 |
+
$msg .= "\n\n(Network error [errno $errno]: $message)";
|
279 |
+
throw new Shippo_ApiConnectionError($msg);
|
280 |
+
}
|
281 |
+
}
|
lib/Shippo/ApiResource.php
ADDED
@@ -0,0 +1,139 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
abstract class Shippo_ApiResource extends Shippo_Object
|
4 |
+
{
|
5 |
+
protected static function _scopedRetrieve($class, $id, $apiKey = null)
|
6 |
+
{
|
7 |
+
$instance = new $class($id, $apiKey);
|
8 |
+
$instance->refresh();
|
9 |
+
return $instance;
|
10 |
+
}
|
11 |
+
|
12 |
+
/**
|
13 |
+
* @returns Shippo_ApiResource The refreshed resource.
|
14 |
+
*/
|
15 |
+
public function refresh()
|
16 |
+
{
|
17 |
+
$requestor = new Shippo_ApiRequestor($this->_apiKey);
|
18 |
+
$url = $this->instanceUrl();
|
19 |
+
|
20 |
+
list($response, $apiKey) = $requestor->request('get', $url, $this->_retrieveOptions);
|
21 |
+
$this->refreshFrom($response, $apiKey);
|
22 |
+
return $this;
|
23 |
+
}
|
24 |
+
|
25 |
+
/**
|
26 |
+
* @param string $class
|
27 |
+
*
|
28 |
+
* @returns string The name of the class, with namespacing and underscores
|
29 |
+
* stripped.
|
30 |
+
*/
|
31 |
+
public static function className($class)
|
32 |
+
{
|
33 |
+
// Useful for namespaces: Foo\Shippo_Shipment
|
34 |
+
if ($postfixNamespaces = strrchr($class, '\\')) {
|
35 |
+
$class = substr($postfixNamespaces, 1);
|
36 |
+
}
|
37 |
+
// Useful for underscored 'namespaces': Foo_Shippo_Shipment
|
38 |
+
if ($postfixFakeNamespaces = strrchr($class, 'Shippo_')) {
|
39 |
+
$class = $postfixFakeNamespaces;
|
40 |
+
}
|
41 |
+
if (substr($class, 0, strlen('Shippo')) == 'Shippo') {
|
42 |
+
$class = substr($class, strlen('Shippo'));
|
43 |
+
}
|
44 |
+
$class = str_replace('_', '', $class);
|
45 |
+
$name = urlencode($class);
|
46 |
+
$name = strtolower($name);
|
47 |
+
return $name;
|
48 |
+
}
|
49 |
+
|
50 |
+
/**
|
51 |
+
* @param string $class
|
52 |
+
*
|
53 |
+
* @returns string The endpoint URL for the given class.
|
54 |
+
*/
|
55 |
+
public static function classUrl($class)
|
56 |
+
{
|
57 |
+
$base = self::_scopedLsb($class, 'className', $class);
|
58 |
+
return "/v1/${base}s";
|
59 |
+
}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* @returns string The full API URL for this API resource.
|
63 |
+
*/
|
64 |
+
public function instanceUrl()
|
65 |
+
{
|
66 |
+
$id = $this['id'];
|
67 |
+
$class = get_class($this);
|
68 |
+
if ($id === null) {
|
69 |
+
$message = "Could not determine which URL to request: " . "$class instance has invalid ID: $id";
|
70 |
+
throw new Shippo_InvalidRequestError($message, null);
|
71 |
+
}
|
72 |
+
$id = Shippo_ApiRequestor::utf8($id);
|
73 |
+
$base = $this->_lsb('classUrl', $class);
|
74 |
+
$extn = urlencode($id);
|
75 |
+
return "$base/$extn";
|
76 |
+
}
|
77 |
+
|
78 |
+
private static function _validateCall($method, $params = null, $apiKey = null)
|
79 |
+
{
|
80 |
+
if ($params && !is_array($params)) {
|
81 |
+
$message = "You must pass an array as the first argument to Shippo API ";
|
82 |
+
throw new Shippo_Error($message);
|
83 |
+
}
|
84 |
+
|
85 |
+
if ($apiKey && !is_string($apiKey)) {
|
86 |
+
$message = 'The second argument to Shippo API method calls is an ' . 'optional per-request apiKey (credentials base_64 encoded), which must be a string';
|
87 |
+
throw new Shippo_Error($message);
|
88 |
+
}
|
89 |
+
}
|
90 |
+
|
91 |
+
protected static function _scopedAll($class, $params = null, $apiKey = null)
|
92 |
+
{
|
93 |
+
self::_validateCall('all', $params, $apiKey);
|
94 |
+
$requestor = new Shippo_ApiRequestor($apiKey);
|
95 |
+
$url = self::_scopedLsb($class, 'classUrl', $class);
|
96 |
+
list($response, $apiKey) = $requestor->request('get', $url, $params);
|
97 |
+
return Shippo_Util::convertToShippoObject($response, $apiKey);
|
98 |
+
}
|
99 |
+
|
100 |
+
protected static function _scopedCreate($class, $params = null, $apiKey = null)
|
101 |
+
{
|
102 |
+
self::_validateCall('create', $params, $apiKey);
|
103 |
+
$requestor = new Shippo_ApiRequestor($apiKey);
|
104 |
+
$url = self::_scopedLsb($class, 'classUrl', $class);
|
105 |
+
// Correction for malformed shippo URLs
|
106 |
+
$url = $url . "/";
|
107 |
+
list($response, $apiKey) = $requestor->request('post', $url, $params);
|
108 |
+
return Shippo_Util::convertToShippoObject($response, $apiKey);
|
109 |
+
}
|
110 |
+
|
111 |
+
protected static function _scopedUpdate($class, $id, $params = null, $apiKey = null)
|
112 |
+
{
|
113 |
+
self::_validateCall('update', $params, $apiKey);
|
114 |
+
$requestor = new Shippo_ApiRequestor($apiKey);
|
115 |
+
$url = self::_scopedLsb($class, 'classUrl', $class) . "/" . $id;
|
116 |
+
list($response, $apiKey) = $requestor->request('put', $url, $params);
|
117 |
+
return Shippo_Util::convertToShippoObject($response, $apiKey);
|
118 |
+
}
|
119 |
+
|
120 |
+
// Special Case for Rates which has parameters of the format: /url/parameter/url
|
121 |
+
protected static function _scopedGet($class, $id, $params = null, $apiKey = null)
|
122 |
+
{
|
123 |
+
self::_validateCall('create', $params, $apiKey);
|
124 |
+
$requestor = new Shippo_ApiRequestor($apiKey);
|
125 |
+
$url = "/v1/shipments/" . $id . "/rates/";
|
126 |
+
list($response, $apiKey) = $requestor->request('get', $url, $params);
|
127 |
+
return Shippo_Util::convertToShippoObject($response, $apiKey);
|
128 |
+
}
|
129 |
+
|
130 |
+
// Special case for Address Validation
|
131 |
+
protected static function _scopedValidate($class, $id, $params = null, $apiKey = null)
|
132 |
+
{
|
133 |
+
self::_validateCall('create', $params, $apiKey);
|
134 |
+
$requestor = new Shippo_ApiRequestor($apiKey);
|
135 |
+
$url = self::_scopedLsb($class, 'classUrl', $class) . "/" . $id . "/validate/";
|
136 |
+
list($response, $apiKey) = $requestor->request('get', $url, $params);
|
137 |
+
return Shippo_Util::convertToShippoObject($response, $apiKey);
|
138 |
+
}
|
139 |
+
}
|
lib/Shippo/AttachedObject.php
ADDED
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// e.g. metadata on Shippo objects.
|
4 |
+
class Shippo_AttachedObject extends Shippo_Object
|
5 |
+
{
|
6 |
+
/**
|
7 |
+
* Updates this object.
|
8 |
+
*
|
9 |
+
* @param array $properties A mapping of properties to update on this object.
|
10 |
+
*/
|
11 |
+
public function replaceWith($properties)
|
12 |
+
{
|
13 |
+
$removed = array_diff(array_keys($this->_values), array_keys($properties));
|
14 |
+
// Don't unset, but rather set to null so we send up '' for deletion.
|
15 |
+
foreach ($removed as $k) {
|
16 |
+
$this->$k = null;
|
17 |
+
}
|
18 |
+
|
19 |
+
foreach ($properties as $k => $v) {
|
20 |
+
$this->$k = $v;
|
21 |
+
}
|
22 |
+
}
|
23 |
+
}
|
lib/Shippo/AuthenticationError.php
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Shippo_AuthenticationError extends Shippo_Error
|
4 |
+
{
|
5 |
+
}
|
lib/Shippo/CarrierAccount.php
ADDED
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Shippo_CarrierAccount extends Shippo_ApiResource
|
4 |
+
{
|
5 |
+
/**
|
6 |
+
* @param string $class Ignored.
|
7 |
+
*
|
8 |
+
* @return string The class URL for this resource. It needs to be special
|
9 |
+
* cased because it doesn't fit into the standard resource pattern.
|
10 |
+
* The standard resource pattern is name + s, e.g. parcel becomes parcels.
|
11 |
+
*/
|
12 |
+
public static function classUrl($class)
|
13 |
+
{
|
14 |
+
return "/v1/carrier_accounts";
|
15 |
+
}
|
16 |
+
|
17 |
+
/**
|
18 |
+
* @param array|null $params
|
19 |
+
* @param string|null $apiKey
|
20 |
+
*
|
21 |
+
* @return Shippo_CustomsItem Create a customs item.
|
22 |
+
*/
|
23 |
+
public static function create($params = null, $apiKey = null)
|
24 |
+
{
|
25 |
+
$class = get_class();
|
26 |
+
return self::_scopedCreate($class, $params, $apiKey);
|
27 |
+
}
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @param array|null $params
|
31 |
+
*
|
32 |
+
* @return Shippo_Retrieve Get a customs item.
|
33 |
+
*/
|
34 |
+
public static function retrieve($id, $apiKey = null)
|
35 |
+
{
|
36 |
+
$class = get_class();
|
37 |
+
return self::_scopedRetrieve($class, $id, $apiKey);
|
38 |
+
}
|
39 |
+
|
40 |
+
/**
|
41 |
+
* @param array|null $params
|
42 |
+
*
|
43 |
+
* @return Shippo_All Get all the customs items.
|
44 |
+
*/
|
45 |
+
public static function all($params = null, $apiKey = null)
|
46 |
+
{
|
47 |
+
$class = get_class();
|
48 |
+
return self::_scopedAll($class, $params, $apiKey);
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* @param id of the CarrierAccount to be updated
|
53 |
+
*
|
54 |
+
* @return Shippo_Retrieve Get a customs item.
|
55 |
+
*/
|
56 |
+
public static function update($id, $params, $apiKey = null)
|
57 |
+
{
|
58 |
+
$class = get_class();
|
59 |
+
return self::_scopedUpdate($class, $id, $params, $apiKey);
|
60 |
+
}
|
61 |
+
|
62 |
+
}
|
lib/Shippo/CustomsDeclaration.php
ADDED
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Shippo_CustomsDeclaration extends Shippo_ApiResource
|
4 |
+
{
|
5 |
+
/**
|
6 |
+
* @param string $class Ignored.
|
7 |
+
*
|
8 |
+
* @return string The class URL for this resource. It needs to be special
|
9 |
+
* cased because it doesn't fit into the standard resource pattern.
|
10 |
+
* The standard resource pattern is name + s, e.g. parcel becomes parcels.
|
11 |
+
*/
|
12 |
+
public static function classUrl($class)
|
13 |
+
{
|
14 |
+
return "/v1/customs/declarations";
|
15 |
+
}
|
16 |
+
|
17 |
+
/**
|
18 |
+
* @param array|null $params
|
19 |
+
* @param string|null $apiKey
|
20 |
+
*
|
21 |
+
* @return Shippo_CustomsDeclaration Create a customs declaration.
|
22 |
+
*/
|
23 |
+
public static function create($params = null, $apiKey = null)
|
24 |
+
{
|
25 |
+
$class = get_class();
|
26 |
+
return self::_scopedCreate($class, $params, $apiKey);
|
27 |
+
}
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @param array|null $params
|
31 |
+
*
|
32 |
+
* @return Shippo_Retrieve Get a customs declaration.
|
33 |
+
*/
|
34 |
+
public static function retrieve($id, $apiKey = null)
|
35 |
+
{
|
36 |
+
$class = get_class();
|
37 |
+
return self::_scopedRetrieve($class, $id, $apiKey);
|
38 |
+
}
|
39 |
+
|
40 |
+
/**
|
41 |
+
* @param array|null $params
|
42 |
+
*
|
43 |
+
* @return Shippo_All Get all the customs declarations.
|
44 |
+
*/
|
45 |
+
public static function all($params = null, $apiKey = null)
|
46 |
+
{
|
47 |
+
$class = get_class();
|
48 |
+
return self::_scopedAll($class, $params, $apiKey);
|
49 |
+
}
|
50 |
+
}
|
lib/Shippo/CustomsItem.php
ADDED
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Shippo_CustomsItem extends Shippo_ApiResource
|
4 |
+
{
|
5 |
+
/**
|
6 |
+
* @param string $class Ignored.
|
7 |
+
*
|
8 |
+
* @return string The class URL for this resource. It needs to be special
|
9 |
+
* cased because it doesn't fit into the standard resource pattern.
|
10 |
+
* The standard resource pattern is name + s, e.g. parcel becomes parcels.
|
11 |
+
*/
|
12 |
+
public static function classUrl($class)
|
13 |
+
{
|
14 |
+
return "/v1/customs/items";
|
15 |
+
}
|
16 |
+
|
17 |
+
/**
|
18 |
+
* @param array|null $params
|
19 |
+
* @param string|null $apiKey
|
20 |
+
*
|
21 |
+
* @return Shippo_CustomsItem Create a customs item.
|
22 |
+
*/
|
23 |
+
public static function create($params = null, $apiKey = null)
|
24 |
+
{
|
25 |
+
$class = get_class();
|
26 |
+
return self::_scopedCreate($class, $params, $apiKey);
|
27 |
+
}
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @param array|null $params
|
31 |
+
*
|
32 |
+
* @return Shippo_Retrieve Get a customs item.
|
33 |
+
*/
|
34 |
+
public static function retrieve($id, $apiKey = null)
|
35 |
+
{
|
36 |
+
$class = get_class();
|
37 |
+
return self::_scopedRetrieve($class, $id, $apiKey);
|
38 |
+
}
|
39 |
+
|
40 |
+
/**
|
41 |
+
* @param array|null $params
|
42 |
+
*
|
43 |
+
* @return Shippo_All Get all the customs items.
|
44 |
+
*/
|
45 |
+
public static function all($params = null, $apiKey = null)
|
46 |
+
{
|
47 |
+
$class = get_class();
|
48 |
+
return self::_scopedAll($class, $params, $apiKey);
|
49 |
+
}
|
50 |
+
}
|
lib/Shippo/Error.php
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Shippo_Error extends Exception
|
4 |
+
{
|
5 |
+
public function __construct($message, $httpStatus = null, $httpBody = null, $jsonBody = null)
|
6 |
+
{
|
7 |
+
parent::__construct($message);
|
8 |
+
$this->httpStatus = $httpStatus;
|
9 |
+
$this->httpBody = $httpBody;
|
10 |
+
$this->jsonBody = $jsonBody;
|
11 |
+
}
|
12 |
+
|
13 |
+
public function getHttpStatus()
|
14 |
+
{
|
15 |
+
return $this->httpStatus;
|
16 |
+
}
|
17 |
+
|
18 |
+
public function getHttpBody()
|
19 |
+
{
|
20 |
+
return $this->httpBody;
|
21 |
+
}
|
22 |
+
|
23 |
+
public function getJsonBody()
|
24 |
+
{
|
25 |
+
return $this->jsonBody;
|
26 |
+
}
|
27 |
+
}
|
lib/Shippo/InvalidRequestError.php
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Shippo_InvalidRequestError extends Shippo_Error
|
4 |
+
{
|
5 |
+
public function __construct($message, $param, $httpStatus = null, $httpBody = null, $jsonBody = null)
|
6 |
+
{
|
7 |
+
parent::__construct($message, $httpStatus, $httpBody, $jsonBody);
|
8 |
+
$this->param = $param;
|
9 |
+
}
|
10 |
+
}
|
lib/Shippo/List.php
ADDED
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Shippo_List extends Shippo_Object
|
4 |
+
{
|
5 |
+
public function all($params = null)
|
6 |
+
{
|
7 |
+
$requestor = new Shippo_ApiRequestor($this->_apiKey);
|
8 |
+
list($response, $apiKey) = $requestor->request('get', $this['url'], $params);
|
9 |
+
return Shippo_Util::convertToShippoObject($response, $apiKey);
|
10 |
+
}
|
11 |
+
|
12 |
+
public function create($params = null)
|
13 |
+
{
|
14 |
+
$requestor = new Shippo_ApiRequestor($this->_apiKey);
|
15 |
+
list($response, $apiKey) = $requestor->request('post', $this['url'], $params);
|
16 |
+
return Shippo_Util::convertToShippoObject($response, $apiKey);
|
17 |
+
}
|
18 |
+
|
19 |
+
public function retrieve($id, $params = null)
|
20 |
+
{
|
21 |
+
$requestor = new Shippo_ApiRequestor($this->_apiKey);
|
22 |
+
$base = $this['url'];
|
23 |
+
$id = Shippo_ApiRequestor::utf8($id);
|
24 |
+
$extn = urlencode($id);
|
25 |
+
list($response, $apiKey) = $requestor->request('get', "$base/$extn", $params);
|
26 |
+
return Shippo_Util::convertToShippoObject($response, $apiKey);
|
27 |
+
}
|
28 |
+
|
29 |
+
}
|
lib/Shippo/Manifest.php
ADDED
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Shippo_Manifest extends Shippo_ApiResource
|
4 |
+
{
|
5 |
+
/**
|
6 |
+
* @param array|null $params
|
7 |
+
* @param string|null $apiKey
|
8 |
+
*
|
9 |
+
* @return Shippo_Manifest Create a manifest.
|
10 |
+
*/
|
11 |
+
public static function create($params = null, $apiKey = null)
|
12 |
+
{
|
13 |
+
$class = get_class();
|
14 |
+
return self::_scopedCreate($class, $params, $apiKey);
|
15 |
+
}
|
16 |
+
|
17 |
+
/**
|
18 |
+
* @param array|null $params
|
19 |
+
*
|
20 |
+
* @return Shippo_Retrieve Get a manifest.
|
21 |
+
*/
|
22 |
+
public static function retrieve($id, $apiKey = null)
|
23 |
+
{
|
24 |
+
$class = get_class();
|
25 |
+
return self::_scopedRetrieve($class, $id, $apiKey);
|
26 |
+
}
|
27 |
+
|
28 |
+
/**
|
29 |
+
* @param array|null $params
|
30 |
+
*
|
31 |
+
* @return Shippo_All Get all the manifests.
|
32 |
+
*/
|
33 |
+
public static function all($params = null, $apiKey = null)
|
34 |
+
{
|
35 |
+
$class = get_class();
|
36 |
+
return self::_scopedAll($class, $params, $apiKey);
|
37 |
+
}
|
38 |
+
}
|
lib/Shippo/Object.php
ADDED
@@ -0,0 +1,262 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Shippo_Object implements ArrayAccess
|
4 |
+
{
|
5 |
+
/**
|
6 |
+
* @var Shippo_Util_Set Attributes that should not be sent to the API because
|
7 |
+
* they're not updatable (e.g. API key, ID).
|
8 |
+
*/
|
9 |
+
public static $permanentAttributes;
|
10 |
+
/**
|
11 |
+
* @var Shippo_Util_Set Attributes that are nested but still updatable from
|
12 |
+
* the parent class's URL (e.g. metadata).
|
13 |
+
*/
|
14 |
+
public static $nestedUpdatableAttributes;
|
15 |
+
|
16 |
+
public static function init()
|
17 |
+
{
|
18 |
+
self::$permanentAttributes = new Shippo_Util_Set(array(
|
19 |
+
'_apiKey',
|
20 |
+
'id'
|
21 |
+
));
|
22 |
+
self::$nestedUpdatableAttributes = new Shippo_Util_Set(array(
|
23 |
+
'metadata'
|
24 |
+
));
|
25 |
+
}
|
26 |
+
|
27 |
+
protected $_apiKey;
|
28 |
+
protected $_values;
|
29 |
+
protected $_unsavedValues;
|
30 |
+
protected $_transientValues;
|
31 |
+
protected $_retrieveOptions;
|
32 |
+
|
33 |
+
public function __construct($id = null, $apiKey = null)
|
34 |
+
{
|
35 |
+
$this->_apiKey = $apiKey;
|
36 |
+
$this->_values = array();
|
37 |
+
$this->_unsavedValues = new Shippo_Util_Set();
|
38 |
+
$this->_transientValues = new Shippo_Util_Set();
|
39 |
+
|
40 |
+
$this->_retrieveOptions = array();
|
41 |
+
if (is_array($id)) {
|
42 |
+
foreach ($id as $key => $value) {
|
43 |
+
if ($key != 'id') {
|
44 |
+
$this->_retrieveOptions[$key] = $value;
|
45 |
+
}
|
46 |
+
}
|
47 |
+
$id = $id['id'];
|
48 |
+
}
|
49 |
+
|
50 |
+
if ($id !== null) {
|
51 |
+
$this->id = $id;
|
52 |
+
}
|
53 |
+
}
|
54 |
+
|
55 |
+
// Standard accessor magic methods
|
56 |
+
public function __set($k, $v)
|
57 |
+
{
|
58 |
+
if ($v === "") {
|
59 |
+
throw new InvalidArgumentException('You cannot set \'' . $k . '\'to an empty string. ' . 'We interpret empty strings as NULL in requests. ' . 'You may set obj->' . $k . ' = NULL to delete the property');
|
60 |
+
}
|
61 |
+
|
62 |
+
if (self::$nestedUpdatableAttributes->includes($k) && isset($this->$k) && is_array($v)) {
|
63 |
+
$this->$k->replaceWith($v);
|
64 |
+
} else {
|
65 |
+
// TODO: may want to clear from $_transientValues (Won't be user-visible).
|
66 |
+
$this->_values[$k] = $v;
|
67 |
+
}
|
68 |
+
if (!self::$permanentAttributes->includes($k))
|
69 |
+
$this->_unsavedValues->add($k);
|
70 |
+
}
|
71 |
+
public function __isset($k)
|
72 |
+
{
|
73 |
+
return isset($this->_values[$k]);
|
74 |
+
}
|
75 |
+
public function __unset($k)
|
76 |
+
{
|
77 |
+
unset($this->_values[$k]);
|
78 |
+
$this->_transientValues->add($k);
|
79 |
+
$this->_unsavedValues->discard($k);
|
80 |
+
}
|
81 |
+
public function __get($k)
|
82 |
+
{
|
83 |
+
if (array_key_exists($k, $this->_values)) {
|
84 |
+
return $this->_values[$k];
|
85 |
+
} else if ($this->_transientValues->includes($k)) {
|
86 |
+
$class = get_class($this);
|
87 |
+
$attrs = join(', ', array_keys($this->_values));
|
88 |
+
$message = "Shippo Notice: Undefined property of $class instance: $k. " . "HINT: The $k attribute was set in the past, however. " . "It was then wiped when refreshing the object " . "with the result returned by Shippo's API, " . "probably as a result of a save(). The attributes currently " . "available on this object are: $attrs";
|
89 |
+
error_log($message);
|
90 |
+
return null;
|
91 |
+
} else {
|
92 |
+
$class = get_class($this);
|
93 |
+
error_log("Shippo Notice: Undefined property of $class instance: $k");
|
94 |
+
return null;
|
95 |
+
}
|
96 |
+
}
|
97 |
+
|
98 |
+
// ArrayAccess methods
|
99 |
+
public function offsetSet($k, $v)
|
100 |
+
{
|
101 |
+
$this->$k = $v;
|
102 |
+
}
|
103 |
+
|
104 |
+
public function offsetExists($k)
|
105 |
+
{
|
106 |
+
return array_key_exists($k, $this->_values);
|
107 |
+
}
|
108 |
+
|
109 |
+
public function offsetUnset($k)
|
110 |
+
{
|
111 |
+
unset($this->$k);
|
112 |
+
}
|
113 |
+
public function offsetGet($k)
|
114 |
+
{
|
115 |
+
return array_key_exists($k, $this->_values) ? $this->_values[$k] : null;
|
116 |
+
}
|
117 |
+
|
118 |
+
public function keys()
|
119 |
+
{
|
120 |
+
return array_keys($this->_values);
|
121 |
+
}
|
122 |
+
|
123 |
+
/**
|
124 |
+
* This unfortunately needs to be public to be used in Util.php
|
125 |
+
*
|
126 |
+
* @param string $class
|
127 |
+
* @param array $values
|
128 |
+
* @param string|null $apiKey
|
129 |
+
*
|
130 |
+
* @return Shippo_Object The object constructed from the given values.
|
131 |
+
*/
|
132 |
+
public static function scopedConstructFrom($class, $values, $apiKey = null)
|
133 |
+
{
|
134 |
+
$obj = new $class(isset($values['id']) ? $values['id'] : null, $apiKey);
|
135 |
+
$obj->refreshFrom($values, $apiKey);
|
136 |
+
return $obj;
|
137 |
+
}
|
138 |
+
|
139 |
+
/**
|
140 |
+
* @param array $values
|
141 |
+
* @param string|null $apiKey
|
142 |
+
*
|
143 |
+
* @return Shippo_Object The object of the same class as $this constructed
|
144 |
+
* from the given values.
|
145 |
+
*/
|
146 |
+
public static function constructFrom($values, $apiKey = null)
|
147 |
+
{
|
148 |
+
return self::scopedConstructFrom(__CLASS__, $values, $apiKey);
|
149 |
+
}
|
150 |
+
|
151 |
+
/**
|
152 |
+
* Refreshes this object using the provided values.
|
153 |
+
*
|
154 |
+
* @param array $values
|
155 |
+
* @param string $apiKey
|
156 |
+
* @param boolean $partial Defaults to false.
|
157 |
+
*/
|
158 |
+
public function refreshFrom($values, $apiKey, $partial = false)
|
159 |
+
{
|
160 |
+
$this->_apiKey = $apiKey;
|
161 |
+
|
162 |
+
// Wipe old state before setting new. This is useful for e.g. updating a
|
163 |
+
// customer, where there is no persistent card parameter. Mark those values
|
164 |
+
// which don't persist as transient
|
165 |
+
if ($partial) {
|
166 |
+
$removed = new Shippo_Util_Set();
|
167 |
+
} else {
|
168 |
+
$removed = array_diff(array_keys($this->_values), array_keys($values));
|
169 |
+
}
|
170 |
+
|
171 |
+
foreach ($removed as $k) {
|
172 |
+
if (self::$permanentAttributes->includes($k))
|
173 |
+
continue;
|
174 |
+
unset($this->$k);
|
175 |
+
}
|
176 |
+
|
177 |
+
foreach ($values as $k => $v) {
|
178 |
+
if (self::$permanentAttributes->includes($k) && isset($this[$k]))
|
179 |
+
continue;
|
180 |
+
|
181 |
+
if (self::$nestedUpdatableAttributes->includes($k) && is_array($v)) {
|
182 |
+
$this->_values[$k] = Shippo_Object::scopedConstructFrom('Shippo_AttachedObject', $v, $apiKey);
|
183 |
+
} else {
|
184 |
+
$this->_values[$k] = Shippo_Util::convertToShippoObject($v, $apiKey);
|
185 |
+
}
|
186 |
+
|
187 |
+
$this->_transientValues->discard($k);
|
188 |
+
$this->_unsavedValues->discard($k);
|
189 |
+
}
|
190 |
+
}
|
191 |
+
|
192 |
+
/**
|
193 |
+
* @return array A recursive mapping of attributes to values for this object,
|
194 |
+
* including the proper value for deleted attributes.
|
195 |
+
*/
|
196 |
+
public function serializeParameters()
|
197 |
+
{
|
198 |
+
$params = array();
|
199 |
+
if ($this->_unsavedValues) {
|
200 |
+
foreach ($this->_unsavedValues->toArray() as $k) {
|
201 |
+
$v = $this->$k;
|
202 |
+
if ($v === NULL) {
|
203 |
+
$v = '';
|
204 |
+
}
|
205 |
+
$params[$k] = $v;
|
206 |
+
}
|
207 |
+
}
|
208 |
+
|
209 |
+
// Get nested updates.
|
210 |
+
foreach (self::$nestedUpdatableAttributes->toArray() as $property) {
|
211 |
+
if (isset($this->$property) && $this->$property instanceOf Shippo_Object) {
|
212 |
+
$params[$property] = $this->$property->serializeParameters();
|
213 |
+
}
|
214 |
+
}
|
215 |
+
return $params;
|
216 |
+
}
|
217 |
+
|
218 |
+
// Pretend to have late static bindings, even in PHP 5.2
|
219 |
+
protected function _lsb($method)
|
220 |
+
{
|
221 |
+
$class = get_class($this);
|
222 |
+
$args = array_slice(func_get_args(), 1);
|
223 |
+
return call_user_func_array(array(
|
224 |
+
$class,
|
225 |
+
$method
|
226 |
+
), $args);
|
227 |
+
}
|
228 |
+
protected static function _scopedLsb($class, $method)
|
229 |
+
{
|
230 |
+
$args = array_slice(func_get_args(), 2);
|
231 |
+
return call_user_func_array(array(
|
232 |
+
$class,
|
233 |
+
$method
|
234 |
+
), $args);
|
235 |
+
}
|
236 |
+
|
237 |
+
public function __toJSON()
|
238 |
+
{
|
239 |
+
if (defined('JSON_PRETTY_PRINT')) {
|
240 |
+
return json_encode($this->__toArray(true), JSON_PRETTY_PRINT);
|
241 |
+
} else {
|
242 |
+
return json_encode($this->__toArray(true));
|
243 |
+
}
|
244 |
+
}
|
245 |
+
|
246 |
+
public function __toString()
|
247 |
+
{
|
248 |
+
return $this->__toJSON();
|
249 |
+
}
|
250 |
+
|
251 |
+
public function __toArray($recursive = false)
|
252 |
+
{
|
253 |
+
if ($recursive) {
|
254 |
+
return Shippo_Util::convertShippoObjectToArray($this->_values);
|
255 |
+
} else {
|
256 |
+
return $this->_values;
|
257 |
+
}
|
258 |
+
}
|
259 |
+
}
|
260 |
+
|
261 |
+
|
262 |
+
Shippo_Object::init();
|
lib/Shippo/Parcel.php
ADDED
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Shippo_Parcel extends Shippo_ApiResource
|
4 |
+
{
|
5 |
+
/**
|
6 |
+
* @param array|null $params
|
7 |
+
* @param string|null $apiKey
|
8 |
+
*
|
9 |
+
* @return Shippo_Parcel Create a Parcel.
|
10 |
+
*/
|
11 |
+
public static function create($params = null, $apiKey = null)
|
12 |
+
{
|
13 |
+
$class = get_class();
|
14 |
+
return self::_scopedCreate($class, $params, $apiKey);
|
15 |
+
}
|
16 |
+
|
17 |
+
/**
|
18 |
+
* @param array|null $params
|
19 |
+
*
|
20 |
+
* @return Shippo_Retrieve Get a Parcel.
|
21 |
+
*/
|
22 |
+
public static function retrieve($id, $apiKey = null)
|
23 |
+
{
|
24 |
+
$class = get_class();
|
25 |
+
return self::_scopedRetrieve($class, $id, $apiKey);
|
26 |
+
}
|
27 |
+
|
28 |
+
/**
|
29 |
+
* @param array|null $params
|
30 |
+
*
|
31 |
+
* @return Shippo_All Get all the Parcels.
|
32 |
+
*/
|
33 |
+
public static function all($params = null, $apiKey = null)
|
34 |
+
{
|
35 |
+
$class = get_class();
|
36 |
+
return self::_scopedAll($class, $params, $apiKey);
|
37 |
+
}
|
38 |
+
}
|
lib/Shippo/Rate.php
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Shippo_Rate extends Shippo_ApiResource
|
4 |
+
{
|
5 |
+
/**
|
6 |
+
* @param array|null $params
|
7 |
+
*
|
8 |
+
* @return Shippo_Retrieve Get a Rate.
|
9 |
+
*/
|
10 |
+
public static function retrieve($id, $apiKey = null)
|
11 |
+
{
|
12 |
+
$class = get_class();
|
13 |
+
return self::_scopedRetrieve($class, $id, $apiKey);
|
14 |
+
}
|
15 |
+
|
16 |
+
/**
|
17 |
+
* @param array|null $params
|
18 |
+
*
|
19 |
+
* @return Shippo_All Get all the Rates.
|
20 |
+
*/
|
21 |
+
public static function all($params = null, $apiKey = null)
|
22 |
+
{
|
23 |
+
$class = get_class();
|
24 |
+
return self::_scopedAll($class, $params, $apiKey);
|
25 |
+
}
|
26 |
+
}
|
lib/Shippo/RateLimitError.php
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Shippo_RateLimitError extends Shippo_InvalidRequestError
|
4 |
+
{
|
5 |
+
public function __construct($message, $param, $httpStatus = null, $httpBody = null, $jsonBody = null)
|
6 |
+
{
|
7 |
+
parent::__construct($message, $httpStatus, $httpBody, $jsonBody);
|
8 |
+
}
|
9 |
+
}
|
lib/Shippo/Refund.php
ADDED
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Shippo_Refund extends Shippo_ApiResource
|
4 |
+
{
|
5 |
+
/**
|
6 |
+
* @param array|null $params
|
7 |
+
* @param string|null $apiKey
|
8 |
+
*
|
9 |
+
* @return Shippo_Refund Create a Refund.
|
10 |
+
*/
|
11 |
+
public static function create($params = null, $apiKey = null)
|
12 |
+
{
|
13 |
+
$class = get_class();
|
14 |
+
return self::_scopedCreate($class, $params, $apiKey);
|
15 |
+
}
|
16 |
+
|
17 |
+
/**
|
18 |
+
* @param array|null $params
|
19 |
+
*
|
20 |
+
* @return Shippo_Retrieve Get a Refund.
|
21 |
+
*/
|
22 |
+
public static function retrieve($id, $apiKey = null)
|
23 |
+
{
|
24 |
+
$class = get_class();
|
25 |
+
return self::_scopedRetrieve($class, $id, $apiKey);
|
26 |
+
}
|
27 |
+
|
28 |
+
/**
|
29 |
+
* @param array|null $params
|
30 |
+
*
|
31 |
+
* @return Shippo_All Get all the Refunds.
|
32 |
+
*/
|
33 |
+
public static function all($params = null, $apiKey = null)
|
34 |
+
{
|
35 |
+
$class = get_class();
|
36 |
+
return self::_scopedAll($class, $params, $apiKey);
|
37 |
+
}
|
38 |
+
}
|
lib/Shippo/Shipment.php
ADDED
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Shippo_Shipment extends Shippo_ApiResource
|
4 |
+
{
|
5 |
+
/**
|
6 |
+
* @param array|null $params
|
7 |
+
* @param string|null $apiKey
|
8 |
+
*
|
9 |
+
* @return Shippo_Shipment Create a Shipment.
|
10 |
+
*/
|
11 |
+
public static function create($params = null, $apiKey = null)
|
12 |
+
{
|
13 |
+
$class = get_class();
|
14 |
+
return self::_scopedCreate($class, $params, $apiKey);
|
15 |
+
}
|
16 |
+
|
17 |
+
/**
|
18 |
+
* @param array|null $params
|
19 |
+
*
|
20 |
+
* @return Shippo_Retrieve Get a Shipment.
|
21 |
+
*/
|
22 |
+
public static function retrieve($id, $apiKey = null)
|
23 |
+
{
|
24 |
+
$class = get_class();
|
25 |
+
return self::_scopedRetrieve($class, $id, $apiKey);
|
26 |
+
}
|
27 |
+
|
28 |
+
/**
|
29 |
+
* @param array|null $params
|
30 |
+
*
|
31 |
+
* @return Shippo_All Get all the Shipments.
|
32 |
+
*/
|
33 |
+
public static function all($params = null, $apiKey = null)
|
34 |
+
{
|
35 |
+
$class = get_class();
|
36 |
+
return self::_scopedAll($class, $params, $apiKey);
|
37 |
+
}
|
38 |
+
|
39 |
+
/**
|
40 |
+
* @param array|null $params
|
41 |
+
*
|
42 |
+
* @return Shippo_Get_Shipping_Rates Get the rates for a Shipment.
|
43 |
+
*/
|
44 |
+
public static function get_shipping_rates($params = null, $apiKey = null)
|
45 |
+
{
|
46 |
+
$class = get_class();
|
47 |
+
$id = $params['id'];
|
48 |
+
return self::_scopedGet($class, $id, $params = null, $apiKey = null);
|
49 |
+
}
|
50 |
+
}
|
lib/Shippo/Shippo.php
ADDED
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
abstract class Shippo
|
4 |
+
{
|
5 |
+
/**
|
6 |
+
* @var string The Shippo API key to be used for requests.
|
7 |
+
*/
|
8 |
+
public static $apiKey;
|
9 |
+
/**
|
10 |
+
* @var string The base URL for the Shippo API.
|
11 |
+
*/
|
12 |
+
public static $apiBase = 'https://api.goshippo.com';
|
13 |
+
/**
|
14 |
+
* @var string|null The version of the Shippo API to use for requests.
|
15 |
+
*/
|
16 |
+
public static $apiVersion = null;
|
17 |
+
/**
|
18 |
+
* @var boolean Defaults to true.
|
19 |
+
*/
|
20 |
+
public static $verifySslCerts = false;
|
21 |
+
const VERSION = '0.0.1';
|
22 |
+
|
23 |
+
/**
|
24 |
+
* @return string The API key used for requests.
|
25 |
+
*/
|
26 |
+
public static function getApiKey()
|
27 |
+
{
|
28 |
+
return self::$apiKey;
|
29 |
+
}
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Sets the API key to be used for requests.
|
33 |
+
*
|
34 |
+
* @param string $apiKey
|
35 |
+
*/
|
36 |
+
public static function setApiKey($apiKey)
|
37 |
+
{
|
38 |
+
self::$apiKey = $apiKey;
|
39 |
+
}
|
40 |
+
|
41 |
+
/**
|
42 |
+
* @return string The API version used for requests. null if we're using the
|
43 |
+
* latest version.
|
44 |
+
*/
|
45 |
+
public static function getApiVersion()
|
46 |
+
{
|
47 |
+
return self::$apiVersion;
|
48 |
+
}
|
49 |
+
|
50 |
+
/**
|
51 |
+
* @param string $apiVersion The API version to use for requests.
|
52 |
+
*/
|
53 |
+
public static function setApiVersion($apiVersion)
|
54 |
+
{
|
55 |
+
self::$apiVersion = $apiVersion;
|
56 |
+
}
|
57 |
+
}
|
lib/Shippo/SingletonApiResource.php
ADDED
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
abstract class Shippo_SingletonApiResource extends Shippo_ApiResource
|
4 |
+
{
|
5 |
+
protected static function _scopedSingletonRetrieve($class, $apiKey = null)
|
6 |
+
{
|
7 |
+
$instance = new $class(null, $apiKey);
|
8 |
+
$instance->refresh();
|
9 |
+
return $instance;
|
10 |
+
}
|
11 |
+
|
12 |
+
/**
|
13 |
+
* @param Shippo_SingletonApiResource $class
|
14 |
+
* @return string The endpoint associated with this singleton class.
|
15 |
+
*/
|
16 |
+
public static function classUrl($class)
|
17 |
+
{
|
18 |
+
$base = self::className($class);
|
19 |
+
return "/v1/${base}";
|
20 |
+
}
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @return string The endpoint associated with this singleton API resource.
|
24 |
+
*/
|
25 |
+
public function instanceUrl()
|
26 |
+
{
|
27 |
+
$class = get_class($this);
|
28 |
+
$base = self::classUrl($class);
|
29 |
+
return "$base";
|
30 |
+
}
|
31 |
+
}
|
lib/Shippo/Transaction.php
ADDED
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Shippo_Transaction extends Shippo_ApiResource
|
4 |
+
{
|
5 |
+
/**
|
6 |
+
* @param array|null $params
|
7 |
+
* @param string|null $apiKey
|
8 |
+
*
|
9 |
+
* @return Shippo_Transaction Create a Transaction.
|
10 |
+
*/
|
11 |
+
public static function create($params = null, $apiKey = null)
|
12 |
+
{
|
13 |
+
$class = get_class();
|
14 |
+
return self::_scopedCreate($class, $params, $apiKey);
|
15 |
+
}
|
16 |
+
|
17 |
+
/**
|
18 |
+
* @param array|null $params
|
19 |
+
*
|
20 |
+
* @return Shippo_Retrieve Get a Transaction.
|
21 |
+
*/
|
22 |
+
public static function retrieve($id, $apiKey = null)
|
23 |
+
{
|
24 |
+
$class = get_class();
|
25 |
+
return self::_scopedRetrieve($class, $id, $apiKey);
|
26 |
+
}
|
27 |
+
|
28 |
+
/**
|
29 |
+
* @param array|null $params
|
30 |
+
*
|
31 |
+
* @return Shippo_All Get all the Transactions.
|
32 |
+
*/
|
33 |
+
public static function all($params = null, $apiKey = null)
|
34 |
+
{
|
35 |
+
$class = get_class();
|
36 |
+
return self::_scopedAll($class, $params, $apiKey);
|
37 |
+
}
|
38 |
+
}
|
lib/Shippo/Util.php
ADDED
@@ -0,0 +1,78 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
abstract class Shippo_Util
|
4 |
+
{
|
5 |
+
/**
|
6 |
+
* Whether the provided array (or other) is a list rather than a dictionary.
|
7 |
+
*
|
8 |
+
* @param array|mixed $array
|
9 |
+
* @return boolean True if the given object is a list.
|
10 |
+
*/
|
11 |
+
public static function isList($array)
|
12 |
+
{
|
13 |
+
if (!is_array($array))
|
14 |
+
return false;
|
15 |
+
|
16 |
+
// TODO: generally incorrect, but it's correct given Shippo's response
|
17 |
+
foreach (array_keys($array) as $k) {
|
18 |
+
if (!is_numeric($k))
|
19 |
+
return false;
|
20 |
+
}
|
21 |
+
return true;
|
22 |
+
}
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Recursively converts the PHP Shippo object to an array.
|
26 |
+
*
|
27 |
+
* @param array $values The PHP Shippo object to convert.
|
28 |
+
* @return array
|
29 |
+
*/
|
30 |
+
public static function convertShippoObjectToArray($values)
|
31 |
+
{
|
32 |
+
$results = array();
|
33 |
+
foreach ($values as $k => $v) {
|
34 |
+
// FIXME: this is an encapsulation violation
|
35 |
+
if ($k[0] == '_') {
|
36 |
+
continue;
|
37 |
+
}
|
38 |
+
if ($v instanceof Shippo_Object) {
|
39 |
+
$results[$k] = $v->__toArray(true);
|
40 |
+
} else if (is_array($v)) {
|
41 |
+
$results[$k] = self::convertShippoObjectToArray($v);
|
42 |
+
} else {
|
43 |
+
$results[$k] = $v;
|
44 |
+
}
|
45 |
+
}
|
46 |
+
return $results;
|
47 |
+
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Converts a response from the Shippo API to the corresponding PHP object.
|
51 |
+
*
|
52 |
+
* @param array $resp The response from the Shippo API.
|
53 |
+
* @param string $apiKey
|
54 |
+
* @return Shippo_Object|array
|
55 |
+
*/
|
56 |
+
public static function convertToShippoObject($resp, $apiKey)
|
57 |
+
{
|
58 |
+
// TODO: Have API Return Object: Type in order to cast properly
|
59 |
+
$types = array(
|
60 |
+
'QUOTE' => 'Shippo_Address'
|
61 |
+
);
|
62 |
+
if (self::isList($resp)) {
|
63 |
+
$mapped = array();
|
64 |
+
foreach ($resp as $i)
|
65 |
+
array_push($mapped, self::convertToShippoObject($i, $apiKey));
|
66 |
+
return $mapped;
|
67 |
+
} else if (is_array($resp)) {
|
68 |
+
if (isset($resp['object_purpose']) && is_string($resp['object_purpose']) && isset($types[$resp['object_purpose']])) {
|
69 |
+
$class = $types[$resp['object_purpose']];
|
70 |
+
} else {
|
71 |
+
$class = 'Shippo_Object';
|
72 |
+
}
|
73 |
+
return Shippo_Object::scopedConstructFrom($class, $resp, $apiKey);
|
74 |
+
} else {
|
75 |
+
return $resp;
|
76 |
+
}
|
77 |
+
}
|
78 |
+
}
|
lib/Shippo/Util/Set.php
ADDED
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Shippo_Util_Set
|
4 |
+
{
|
5 |
+
private $_elts;
|
6 |
+
|
7 |
+
public function __construct($members = array())
|
8 |
+
{
|
9 |
+
$this->_elts = array();
|
10 |
+
foreach ($members as $item)
|
11 |
+
$this->_elts[$item] = true;
|
12 |
+
}
|
13 |
+
|
14 |
+
public function includes($elt)
|
15 |
+
{
|
16 |
+
return isset($this->_elts[$elt]);
|
17 |
+
}
|
18 |
+
|
19 |
+
public function add($elt)
|
20 |
+
{
|
21 |
+
$this->_elts[$elt] = true;
|
22 |
+
}
|
23 |
+
|
24 |
+
public function discard($elt)
|
25 |
+
{
|
26 |
+
unset($this->_elts[$elt]);
|
27 |
+
}
|
28 |
+
|
29 |
+
// TODO: make Set support foreach
|
30 |
+
public function toArray()
|
31 |
+
{
|
32 |
+
return array_keys($this->_elts);
|
33 |
+
}
|
34 |
+
}
|
package.xml
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<package>
|
3 |
+
<name>Buildateam_Shippo</name>
|
4 |
+
<version>1.0.2</version>
|
5 |
+
<stability>stable</stability>
|
6 |
+
<license uri="https://www.buildateam.io/end-user-license-agreement/">Buildateam EULA</license>
|
7 |
+
<channel>community</channel>
|
8 |
+
<extends/>
|
9 |
+
<summary>Shippo integration</summary>
|
10 |
+
<description>An ability to display Shippo rates on checkout</description>
|
11 |
+
<notes>Don't forget to specify Weight and Dimensions for each Product and to enable Shippo rates here:
|
12 |
+
System > Configuration > Sales > ShippingMethods > Shippo</notes>
|
13 |
+
<authors><author><name>Buildateam</name><user>buildateam</user><email>lex.mustafin@gmail.com</email></author></authors>
|
14 |
+
<date>2016-06-25</date>
|
15 |
+
<time>09:25:09</time>
|
16 |
+
<contents><target name="magecommunity"><dir name="Buildateam"><dir name="Shippo"><dir name="Block"><dir name="Adminhtml"><dir name="Frontend"><dir name="Region"><file name="Updater.php" hash="c491ea63bb45159cbda060fdf34b28ed"/></dir></dir></dir></dir><dir name="Helper"><file name="Carrier.php" hash="f93af56bb9826876c268416f9184d5a7"/><file name="Data.php" hash="c3f6ff836f419117d72a9acebe49d44a"/><file name="Shippo.php" hash="3d29ac520a44b9285c2f5e21d047c143"/></dir><dir name="Model"><file name="Carrier.php" hash="40dd78de6c9bd294b211c6f91e6ed689"/><file name="Observer.php" hash="59c46326dccf9c81091c8ca52f68bc5e"/><file name="Parcel.php" hash="30c84b345500aa7cea172c7b2abe61a7"/><dir name="System"><dir name="Config"><dir name="Source"><file name="Region.php" hash="cdf4cbed7d6dceb603cd6401605bb10d"/><file name="Size.php" hash="0ea6eacc2955389c62fcfcdeeaa1fd14"/><file name="Weight.php" hash="3591a1ff37eae8ec84f8b92d5110efbb"/></dir></dir></dir></dir><dir name="controllers"><file name="TestController.php" hash="e19b9a65cd73204b32878d2abdba7b93"/></dir><dir name="etc"><file name="adminhtml.xml" hash="ba1a357269d7968d1e939c3feb7f8a61"/><file name="config.xml" hash="1a36080ffd2b55bcb0e2894e334bffdb"/><file name="system.xml" hash="f5562a9cf3bb7028d498b220d83eb2a7"/></dir><dir name="sql"><dir name="buildateam_shippo_setup"><file name="mysql4-upgrade-1.0.0-1.0.1.php" hash="04e9efc84ad102faf3194e1a5c718e93"/><file name="mysql4-upgrade-1.0.1-1.0.2.php" hash="38cff0661faa7e326b672ce9be98ae3d"/></dir></dir></dir></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="layout"><dir name="buildateam"><file name="shippo.xml" hash="649b5e41b8f0c5ba89489092b072e35b"/></dir></dir><dir name="template"><dir name="buildateam"><dir name="shippo"><dir name="catalog"><dir name="product"><file name="js.phtml" hash="fcc991ee690d1d69aed347bd8e8ff7e4"/></dir></dir></dir></dir></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Buildateam_Shippo.xml" hash="803295b3c8b0d76e0a41fc91deffa015"/></dir></target><target name="mage"><dir name="lib"><dir name="Shippo"><file name="Address.php" hash="0208872b93ba60dde1791f5f67fc7979"/><file name="ApiConnectionError.php" hash="53b5d4a25910750a114999dbb35f4324"/><file name="ApiError.php" hash="5c5e5e113708e24ca10f937dc1f9a5c3"/><file name="ApiRequestor.php" hash="7328a1116ffbf42f0fce6397e6b9271a"/><file name="ApiResource.php" hash="7f92abf3a9499626230c3a036dd40caf"/><file name="AttachedObject.php" hash="98a0779cdb695f2f3dcb32ee2af608b4"/><file name="AuthenticationError.php" hash="745de030343d577e54d349b718270448"/><file name="CarrierAccount.php" hash="dac1ce095ae6a895fbb07e29a9a5834a"/><file name="CustomsDeclaration.php" hash="5c699342e6449c2f800cfe24889c0776"/><file name="CustomsItem.php" hash="25f617bcf964cab836c5d751e1a0fb3f"/><file name="Error.php" hash="d1fc506089f558c7dc48c5ca793d9390"/><file name="InvalidRequestError.php" hash="04204981812de2f60a5d2a2c74cbc581"/><file name="List.php" hash="54858f45588b6ffd4de4557ad45bd118"/><file name="Manifest.php" hash="a417ae0e066e6888a5448d853429ebb0"/><file name="Object.php" hash="28dfb631fb002d85ecff4a7aa6e39199"/><file name="Parcel.php" hash="89019233291f552999a8fc5200f5a030"/><file name="Rate.php" hash="191acfd8220a17a312770074e37a0feb"/><file name="RateLimitError.php" hash="b5665ac78b534e2bba675ba51bf98f2e"/><file name="Refund.php" hash="dad1adad037cde3002b85e02c0f54dc1"/><file name="Shipment.php" hash="faacbd7f16487fc8b14d605f1a9045dc"/><file name="Shippo.php" hash="7d75f1e7bcfb8d7dde994c1052406d2a"/><file name="SingletonApiResource.php" hash="a3a43a218712be59b769b7e7374e4097"/><file name="Transaction.php" hash="353f22ce5fec45737cf111b8609b6d98"/><dir name="Util"><file name="Set.php" hash="6ba0be5f0ac9429fa7e015297bbee99f"/></dir><file name="Util.php" hash="4246ec80cdea8da4505f83946ff8ab4d"/></dir><file name="Shippo.php" hash="fe9f59c6610bf16b1b925921f72f92ae"/></dir></target></contents>
|
17 |
+
<compatible/>
|
18 |
+
<dependencies><required><php><min>5.1.0</min><max>6.0.0</max></php></required></dependencies>
|
19 |
+
</package>
|