commiting uncommited changes on live site
[weblabels.fsf.org.git] / crm.fsf.org / 20131203 / files / sites / all / modules-old / civicrm / packages / Google / library / googlecart.php
1 <?php
2 /*
3 * Copyright (C) 2007 Google Inc.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 /**
19 * Classes used to build a shopping cart and submit it to Google Checkout
20 * @version $Id: googlecart.php 1234 2007-09-25 14:58:57Z ropu $
21 */
22
23 define('MAX_DIGITAL_DESC', 1024);
24
25 /**
26 * Creates a Google Checkout shopping cart and posts it
27 * to the google checkout sandbox or production environment
28 * Refer demo/cartdemo.php for different use case scenarios for this code
29 */
30 class GoogleCart {
31 var $merchant_id;
32 var $merchant_key;
33 var $variant = false;
34 var $currency;
35 var $server_url;
36 var $schema_url;
37 var $base_url;
38 var $checkout_url;
39 var $checkout_diagnose_url;
40 var $request_url;
41 var $request_diagnose_url;
42
43 var $cart_expiration = "";
44 var $merchant_private_data = "";
45 var $edit_cart_url = "";
46 var $continue_shopping_url = "";
47 var $request_buyer_phone = "";
48 var $merchant_calculated_tax = "";
49 var $merchant_calculations_url = "";
50 var $accept_merchant_coupons = "";
51 var $accept_gift_certificates = "";
52 var $rounding_mode;
53 var $rounding_rule;
54 var $analytics_data;
55
56 var $item_arr;
57 var $shipping_arr;
58 var $default_tax_rules_arr;
59 var $alternate_tax_tables_arr;
60 var $xml_data;
61
62 var $googleAnalytics_id = false;
63 var $thirdPartyTackingUrl = false;
64 var $thirdPartyTackingParams = array();
65
66 // For HTML API Conversion
67
68 // This tags are those that can be used more than once as a sub tag
69 // so a "-#" must be added always
70 /**
71 * used when using the html api
72 * tags that can be used more than once, so they need to be numbered
73 * ("-#" suffix)
74 */
75 var $multiple_tags = array(
76 'flat-rate-shipping' => array(),
77 'merchant-calculated-shipping' => array(),
78 'pickup' => array(),
79 'parameterized-url' => array(),
80 'url-parameter' => array(),
81 'item' => array(),
82 'us-state-area' => array('tax-area'),
83 'us-zip-area' => array('tax-area'),
84 'us-country-area' => array('tax-area'),
85 'postal-area' => array('tax-area'),
86 'alternate-tax-table' => array(),
87 'world-area' => array('tax-area'),
88 'default-tax-rule' => array(),
89 'alternate-tax-rule' => array(),
90 'gift-certificate-adjustment' => array(),
91 'coupon-adjustment' => array(),
92 'coupon-result' => array(),
93 'gift-certificate-result' => array(),
94 'method' => array(),
95 'anonymous-address' => array(),
96 'result' => array(),
97 'string' => array(),
98 );
99
100 var $ignore_tags = array(
101 'xmlns' => true,
102 'checkout-shopping-cart' => true,
103 // Dont know how to translate these tag yet
104 'merchant-private-data' => true,
105 'merchant-private-item-data' => true,
106 );
107
108
109
110 /**
111 * Has all the logic to build the cart's xml (or html) request to be
112 * posted to google's servers.
113 *
114 * @param string $id the merchant id
115 * @param string $key the merchant key
116 * @param string $server_type the server type of the server to be used, one
117 * of 'sandbox' or 'production'.
118 * defaults to 'sandbox'
119 * @param string $currency the currency of the items to be added to the cart
120 * , as of now values can be 'USD' or 'GBP'.
121 * defaults to 'USD'
122 */
123 function GoogleCart($id, $key, $server_type="sandbox", $currency="USD") {
124 $this->merchant_id = $id;
125 $this->merchant_key = $key;
126 $this->currency = $currency;
127
128 if(strtolower($server_type) == "sandbox") {
129 $this->server_url = "https://sandbox.google.com/checkout/";
130 } else {
131 $this->server_url= "https://checkout.google.com/";
132 }
133
134
135 $this->schema_url = "http://checkout.google.com/schema/2";
136 $this->base_url = $this->server_url . "api/checkout/v2/";
137 $this->checkout_url = $this->base_url . "checkout/Merchant/" . $this->merchant_id;
138 $this->checkoutForm_url = $this->base_url . "checkoutForm/Merchant/" . $this->merchant_id;
139
140 //The item, shipping and tax table arrays are initialized
141 $this->item_arr = array();
142 $this->shipping_arr = array();
143 $this->alternate_tax_tables_arr = array();
144 }
145
146 /**
147 * Sets the cart's expiration date
148 *
149 * GC tag: {@link http://code.google.com/apis/checkout/developer/index.html#tag_good-until-date <good-until-date>}
150 *
151 * @param string $cart_expire a string representing a date in the
152 * iso 8601 date and time format: {@link http://www.w3.org/TR/NOTE-datetime}
153 *
154 * @return void
155 */
156 function SetCartExpiration($cart_expire) {
157 $this->cart_expiration = $cart_expire;
158 }
159
160 /**
161 * Sets the merchant's private data.
162 *
163 * Google Checkout will return this data in the
164 * <merchant-calculation-callback> and the
165 * <new-order-notification> for the order.
166 *
167 * GC tag: {@link http://code.google.com/apis/checkout/developer/index.html#tag_merchant-private-data <merchant-private-data>}
168 *
169 * @param MerchantPrivateData $data an object which contains the data to be
170 * sent as merchant-private-data
171 *
172 * @return void
173 */
174 function SetMerchantPrivateData($data) {
175 $this->merchant_private_data = $data;
176 }
177
178 /**
179 * Sets the url where the customer can edit his cart.
180 *
181 * GC tag: {@link http://code.google.com/apis/checkout/developer/index.html#tag_edit-cart-url <edit-cart-url>}
182 *
183 * @param string $url the merchant's site edit cart url
184 * @return void
185 */
186 function SetEditCartUrl($url) {
187 $this->edit_cart_url= $url;
188 }
189
190 /**
191 * Sets the continue shopping url, which allows the customer to return
192 * to the merchant's site after confirming an order.
193 *
194 * GC tag: {@link http://code.google.com/apis/checkout/developer/index.html#tag_continue-shopping-url <continue-shopping-url>}
195 *
196 * @param string $url the merchant's site continue shopping url
197 * @return void
198 */
199 function SetContinueShoppingUrl($url) {
200 $this->continue_shopping_url = $url;
201 }
202
203 /**
204 * Sets whether the customer must enter a phone number to complete an order.
205 * If set to true, the customer must enter a number, which Google Checkout
206 * will return in the new order notification for the order.
207 *
208 * GC tag: {@link http://code.google.com/apis/checkout/developer/index.html#tag_request-buyer-phone-number <request-buyer-phone-number>}
209 *
210 * @param bool $req true if the customer's phone number is *required*
211 * to complete an order.
212 * defaults to false.
213 * @return void
214 */
215 function SetRequestBuyerPhone($req) {
216 $this->request_buyer_phone = $this->_GetBooleanValue($req, "false");
217 }
218
219 /**
220 * Sets the information about calculations that will be performed by the
221 * merchant.
222 *
223 * GC tag: {@link http://code.google.com/apis/checkout/developer/index.html#tag_merchant-calculations <merchant-calculations>}
224 *
225 * @param string $url the merchant calculations callback url
226 * @param bool $tax_option true if the merchant has to do tax calculations.
227 * defaults to false.
228 * @param bool $coupons true if the merchant accepts discount coupons.
229 * defaults to false.
230 * @param bool $gift_cert true if the merchant accepts gift certificates.
231 * defaults to false.
232 * @return void
233 */
234 function SetMerchantCalculations($url, $tax_option = "false",
235 $coupons = "false", $gift_cert = "false") {
236 $this->merchant_calculations_url = $url;
237 $this->merchant_calculated_tax = $this->_GetBooleanValue($tax_option, "false");
238 $this->accept_merchant_coupons = $this->_GetBooleanValue($coupons, "false");
239 $this->accept_gift_certificates = $this->_GetBooleanValue($gift_cert, "false");
240 }
241
242 /**
243 * Add an item to the cart.
244 *
245 * GC tag: {@link http://code.google.com/apis/checkout/developer/index.html#tag_item <item>}
246 *
247 * @param GoogleItem $google_item an object that represents an item
248 * (defined in googleitem.php)
249 *
250 * @return void
251 */
252 function AddItem($google_item) {
253 $this->item_arr[] = $google_item;
254 }
255
256 /**
257 * Add a shipping method to the cart.
258 *
259 * GC tag: {@link http://code.google.com/apis/checkout/developer/index.html#tag_shipping-methods <shipping-methods>}
260 *
261 * @param object $ship an object that represents a shipping method, must be
262 * one of the methods defined in googleshipping.php
263 *
264 * @return void
265 */
266 function AddShipping($ship) {
267 $this->shipping_arr[] = $ship;
268 }
269
270 /**
271 * Add a default tax rule to the cart.
272 *
273 * GC tag: {@link http://code.google.com/apis/checkout/developer/index.html#tag_default-tax-rule <default-tax-rule>}
274 *
275 * @param GoogleDefaultTaxRule $rules an object that represents a default
276 * tax rule (defined in googletax.php)
277 *
278 * @return void
279 */
280 function AddDefaultTaxRules($rules) {
281 $this->default_tax_table = true;
282 $this->default_tax_rules_arr[] = $rules;
283 }
284
285 /**
286 * Add an alternate tax table to the cart.
287 *
288 * GC tag: {@link http://code.google.com/apis/checkout/developer/index.html#tag_alternate-tax-table <alternate-tax-table>}
289 *
290 * @param GoogleAlternateTaxTable $tax an object that represents an
291 * alternate tax table
292 * (defined in googletax.php)
293 *
294 * @return void
295 */
296 function AddAlternateTaxTables($tax) {
297 $this->alternate_tax_tables_arr[] = $tax;
298 }
299
300 /**
301 * Set the policy to be used to round monetary values.
302 * Rounding policy explanation here:
303 * {@link http://code.google.com/apis/checkout/developer/Google_Checkout_Rounding_Policy.html}
304 *
305 * GC tag: {@link http://code.google.com/apis/checkout/developer/index.html#tag_rounding-policy <rounding-policy>}
306 *
307 * @param string $mode one of "UP", "DOWN", "CEILING", "HALF_DOWN"
308 * or "HALF_EVEN", described here: {@link http://java.sun.com/j2se/1.5.0/docs/api/java/math/RoundingMode.html}
309 * @param string $rule one of "PER_LINE", "TOTAL"
310 *
311 * @return void
312 */
313 function AddRoundingPolicy($mode, $rule) {
314 switch ($mode) {
315 case "UP":
316 case "DOWN":
317 case "CEILING":
318 case "HALF_UP":
319 case "HALF_DOWN":
320 case "HALF_EVEN":
321 $this->rounding_mode = $mode;
322 break;
323 default:
324 break;
325 }
326 switch ($rule) {
327 case "PER_LINE":
328 case "TOTAL":
329 $this->rounding_rule = $rule;
330 break;
331 default:
332 break;
333 }
334 }
335
336 /**
337 * Set the google analytics data.
338 *
339 * {@link http://code.google.com/apis/checkout/developer/checkout_analytics_integration.html info on Checkout and Analytics integration}
340 *
341 * @param string $data the analytics data
342 *
343 * @return void
344 */
345 function SetAnalyticsData($data) {
346 $this->analytics_data = $data;
347 }
348
349 /**
350 * Add a google analytics tracking id.
351 *
352 * {@link http://code.google.com/apis/checkout/developer/checkout_analytics_integration.html info on Checkout and Analytics integration}
353 *
354 * @param string $GA_id the google analytics id
355 *
356 * @return void
357 */
358 function AddGoogleAnalyticsTracking($GA_id) {
359 $this->googleAnalytics_id = $GA_id;
360 }
361
362 /**
363 * Add third-party tracking to the cart
364 *
365 * Described here:
366 * {@link http://code.google.com/apis/checkout/developer/checkout_analytics_integration.html#googleCheckoutAnalyticsIntegrationAlternate}
367 *
368 * @param $tracking_attr_types attributes to be tracked, one of
369 * ('buyer-id',
370 * 'order-id',
371 * 'order-subtotal',
372 * 'order-subtotal-plus-tax',
373 * 'order-subtotal-plus-shipping',
374 * 'order-total',
375 * 'tax-amount',
376 * 'shipping-amount',
377 * 'coupon-amount',
378 * 'coupon-amount',
379 * 'billing-city',
380 * 'billing-region',
381 * 'billing-postal-code',
382 * 'billing-country-code',
383 * 'shipping-city',
384 * 'shipping-region',
385 * 'shipping-postal-code',
386 * 'shipping-country-code')
387 * More info http://code.google.com/apis/checkout/developer/checkout_pixel_tracking.html#googleCheckout_tag_url-parameter
388 */
389 function AddThirdPartyTracking($url, $tracking_param_types = array()) {
390 $this->thirdPartyTackingUrl = $url;
391 $this->thirdPartyTackingParams = $tracking_param_types;
392 }
393
394 /**
395 * Builds the cart's xml to be sent to Google Checkout.
396 *
397 * @return string the cart's xml
398 */
399 function GetXML() {
400 require_once(dirname(__FILE__).'/xml-processing/gc_xmlbuilder.php');
401
402 $xml_data = new gc_XmlBuilder();
403
404 $xml_data->Push('checkout-shopping-cart',
405 array('xmlns' => $this->schema_url));
406 $xml_data->Push('shopping-cart');
407
408 //Add cart expiration if set
409 if($this->cart_expiration != "") {
410 $xml_data->Push('cart-expiration');
411 $xml_data->Element('good-until-date', $this->cart_expiration);
412 $xml_data->Pop('cart-expiration');
413 }
414
415 //Add XML data for each of the items
416 $xml_data->Push('items');
417 foreach($this->item_arr as $item) {
418 $xml_data->Push('item');
419 $xml_data->Element('item-name', $item->item_name);
420 $xml_data->Element('item-description', $item->item_description);
421 $xml_data->Element('unit-price', $item->unit_price,
422 array('currency' => $this->currency));
423 $xml_data->Element('quantity', $item->quantity);
424 if($item->merchant_private_item_data != '') {
425 // echo get_class($item->merchant_private_item_data);
426 if(is_a($item->merchant_private_item_data,
427 'merchantprivate')) {
428 $item->merchant_private_item_data->AddMerchantPrivateToXML($xml_data);
429 }
430 else {
431 $xml_data->Element('merchant-private-item-data',
432 $item->merchant_private_item_data);
433 }
434 }
435 if($item->merchant_item_id != '')
436 $xml_data->Element('merchant-item-id', $item->merchant_item_id);
437 if($item->tax_table_selector != '')
438 $xml_data->Element('tax-table-selector', $item->tax_table_selector);
439 // Carrier calculation
440 if($item->item_weight != '' && $item->numeric_weight !== '') {
441 $xml_data->EmptyElement('item-weight', array( 'unit' => $item->item_weight,
442 'value' => $item->numeric_weight
443 ));
444 }
445 // Digital Delivery Tags
446 if($item->digital_content) {
447 $xml_data->Push('digital-content');
448 if(!empty($item->digital_url)) {
449 $xml_data->Element('description', substr($item->digital_description,
450 0, MAX_DIGITAL_DESC));
451 $xml_data->Element('url', $item->digital_url);
452 // To avoid NULL key message in GC confirmation Page
453 if(!empty($item->digital_key)) {
454 $xml_data->Element('key', $item->digital_key);
455 }
456 }
457 else if(!empty($item->digital_description)) {
458 $xml_data->element('description', substr($item->digital_description, 0,MAX_DIGITAL_DESC));
459 }
460 else {
461 $xml_data->Element('email-delivery',
462 $this->_GetBooleanValue($item->email_delivery, "true"));
463 }
464 $xml_data->pop('digital-content');
465 }
466 // BETA Subscription Tags
467 if($item->subscription){
468 $sub = $item->subscription;
469 $xml_data->Push('subscription', array('type' => $sub->subscription_type,
470 'period' => $sub->subscription_period,
471 'start-date' => $sub->subscription_start_date,
472 'no-charge-after' => $sub->subscription_no_charge_after));
473 $xml_data->Push('payments');
474 $xml_data->Push('subscription-payment', array('times' => $sub->subscription_payment_times));
475 $xml_data->Element('maximum-charge', $sub->maximum_charge, array('currency' => $this->currency));
476 $xml_data->Pop('subscription-payment');
477 $xml_data->Pop('payments');
478 if(!empty($sub->recurrent_item)){
479 $recurrent_item = $sub->recurrent_item;
480 //Google Handled Subscriptions
481 if($sub->subscription_type == 'google'){
482 $xml_data->Push('recurrent-item');
483 $xml_data->Element('item-name', $recurrent_item->item_name);
484 $xml_data->Element('item-description', $recurrent_item->item_description);
485 $xml_data->Element('unit-price', $recurrent_item->unit_price,
486 array('currency' => $this->currency));
487 $xml_data->Element('quantity', $recurrent_item->quantity);
488 if($recurrent_item->merchant_private_item_data != '') {
489 // echo get_class($item->merchant_private_item_data);
490 if(is_a($recurrent_item->merchant_private_item_data,
491 'merchantprivate')) {
492 $recurrent_item->merchant_private_item_data->AddMerchantPrivateToXML($xml_data);
493 }
494 else {
495 $xml_data->Element('merchant-private-item-data',
496 $recurrent_item->merchant_private_item_data);
497 }
498 }
499 if($recurrent_item->merchant_item_id != '')
500 $xml_data->Element('merchant-item-id', $recurrent_item->merchant_item_id);
501 if($recurrent_item->tax_table_selector != '')
502 $xml_data->Element('tax-table-selector', $recurrent_item->tax_table_selector);
503 // recurring Carrier calculation
504 if($recurrent_item->item_weight != '' && $recurrent_item->numeric_weight !== '') {
505 $xml_data->EmptyElement('item-weight', array( 'unit' => $recurrent_item->item_weight,
506 'value' => $recurrent_item->numeric_weight
507 ));
508 }
509 // recurring Digital Delivery Tags
510 if($recurrent_item->digital_content) {
511 $xml_data->Push('digital-content');
512 if(!empty($recurrent_item->digital_url)) {
513 $xml_data->Element('description', substr($recurrent_item->digital_description,
514 0, MAX_DIGITAL_DESC));
515 $xml_data->Element('url', $recurrent_item->digital_url);
516 // To avoid NULL key message in GC confirmation Page
517 if(!empty($recurrent_item->digital_key)) {
518 $xml_data->Element('key', $recurrent_item->digital_key);
519 }
520 }
521 else if(!empty($item->digital_description)) {
522 $xml_data->element('description', substr($item->digital_description, 0,MAX_DIGITAL_DESC));
523 }
524 else {
525 $xml_data->Element('email-delivery',
526 $this->_GetBooleanValue($recurrent_item->email_delivery, "true"));
527 }
528 $xml_data->pop('digital-content');
529 }
530 $xml_data->Pop('recurrent-item');
531 }
532 }
533 $xml_data->pop('subscription');
534 }
535 $xml_data->Pop('item');
536 }
537 $xml_data->Pop('items');
538
539 if($this->merchant_private_data != '') {
540 if(is_a($this->merchant_private_data, 'merchantprivate')) {
541 $this->merchant_private_data->AddMerchantPrivateToXML($xml_data);
542 }
543 else {
544 $xml_data->Element('merchant-private-data',
545 $this->merchant_private_data);
546 }
547 }
548 $xml_data->Pop('shopping-cart');
549
550 $xml_data->Push('checkout-flow-support');
551 $xml_data->Push('merchant-checkout-flow-support');
552 if($this->edit_cart_url != '')
553 $xml_data->Element('edit-cart-url', $this->edit_cart_url);
554 if($this->continue_shopping_url != '')
555 $xml_data->Element('continue-shopping-url',
556 $this->continue_shopping_url);
557
558 if(count($this->shipping_arr) > 0)
559 $xml_data->Push('shipping-methods');
560
561 //Add the shipping methods
562 foreach($this->shipping_arr as $ship) {
563 //Pickup shipping handled in else part
564 if($ship->type == "flat-rate-shipping" ||
565 $ship->type == "merchant-calculated-shipping"
566 // If shipping-company calc support addr-filtering and shipping restrictions as a subatag of shipping-company-calculated-shipping
567 // ||$ship->type == "shipping-company-calculated-shipping"
568 ) {
569 $xml_data->Push($ship->type, array('name' => $ship->name));
570 $xml_data->Element('price', $ship->price,
571 array('currency' => $this->currency));
572
573 $shipping_restrictions = $ship->shipping_restrictions;
574 if (isset($shipping_restrictions)) {
575 $xml_data->Push('shipping-restrictions');
576
577 if ($shipping_restrictions->allow_us_po_box === true) {
578 $xml_data->Element('allow-us-po-box', "true");
579 } else {
580 $xml_data->Element('allow-us-po-box', "false");
581 }
582
583 //Check if allowed restrictions specified
584 if($shipping_restrictions->allowed_restrictions) {
585 $xml_data->Push('allowed-areas');
586 if($shipping_restrictions->allowed_country_area != "")
587 $xml_data->EmptyElement('us-country-area',
588 array('country-area' =>
589 $shipping_restrictions->allowed_country_area));
590 foreach($shipping_restrictions->allowed_state_areas_arr as $current) {
591 $xml_data->Push('us-state-area');
592 $xml_data->Element('state', $current);
593 $xml_data->Pop('us-state-area');
594 }
595 foreach($shipping_restrictions->allowed_zip_patterns_arr as $current) {
596 $xml_data->Push('us-zip-area');
597 $xml_data->Element('zip-pattern', $current);
598 $xml_data->Pop('us-zip-area');
599 }
600 if($shipping_restrictions->allowed_world_area === true) {
601 $xml_data->EmptyElement('world-area');
602 }
603 for($i=0; $i<count($shipping_restrictions->allowed_country_codes_arr); $i++) {
604 $xml_data->Push('postal-area');
605 $country_code = $shipping_restrictions->allowed_country_codes_arr[$i];
606 $postal_pattern = $shipping_restrictions->allowed_postal_patterns_arr[$i];
607 $xml_data->Element('country-code', $country_code);
608 if ($postal_pattern != "") {
609 $xml_data->Element('postal-code-pattern', $postal_pattern);
610 }
611 $xml_data->Pop('postal-area');
612 }
613 $xml_data->Pop('allowed-areas');
614 }
615
616 if($shipping_restrictions->excluded_restrictions) {
617 if (!$shipping_restrictions->allowed_restrictions) {
618 $xml_data->EmptyElement('allowed-areas');
619 }
620 $xml_data->Push('excluded-areas');
621 if($shipping_restrictions->excluded_country_area != "")
622 $xml_data->EmptyElement('us-country-area',
623 array('country-area' =>
624 $shipping_restrictions->excluded_country_area));
625 foreach($shipping_restrictions->excluded_state_areas_arr as $current) {
626 $xml_data->Push('us-state-area');
627 $xml_data->Element('state', $current);
628 $xml_data->Pop('us-state-area');
629 }
630 foreach($shipping_restrictions->excluded_zip_patterns_arr as $current) {
631 $xml_data->Push('us-zip-area');
632 $xml_data->Element('zip-pattern', $current);
633 $xml_data->Pop('us-zip-area');
634 }
635 for($i=0; $i<count($shipping_restrictions->excluded_country_codes_arr); $i++) {
636 $xml_data->Push('postal-area');
637 $country_code = $shipping_restrictions->excluded_country_codes_arr[$i];
638 $postal_pattern = $shipping_restrictions->excluded_postal_patterns_arr[$i];
639 $xml_data->Element('country-code', $country_code);
640 if ($postal_pattern != "") {
641 $xml_data->Element('postal-code-pattern', $postal_pattern);
642 }
643 $xml_data->Pop('postal-area');
644 }
645 $xml_data->Pop('excluded-areas');
646 }
647 $xml_data->Pop('shipping-restrictions');
648 }
649
650 if ($ship->type == "merchant-calculated-shipping") {
651 $address_filters = $ship->address_filters;
652 if (isset($address_filters)) {
653 $xml_data->Push('address-filters');
654
655 if ($address_filters->allow_us_po_box === true) {
656 $xml_data->Element('allow-us-po-box', "true");
657 } else {
658 $xml_data->Element('allow-us-po-box', "false");
659 }
660
661 //Check if allowed restrictions specified
662 if($address_filters->allowed_restrictions) {
663 $xml_data->Push('allowed-areas');
664 if($address_filters->allowed_country_area != "")
665 $xml_data->EmptyElement('us-country-area',
666 array('country-area' =>
667 $address_filters->allowed_country_area));
668 foreach($address_filters->allowed_state_areas_arr as $current) {
669 $xml_data->Push('us-state-area');
670 $xml_data->Element('state', $current);
671 $xml_data->Pop('us-state-area');
672 }
673 foreach($address_filters->allowed_zip_patterns_arr as $current) {
674 $xml_data->Push('us-zip-area');
675 $xml_data->Element('zip-pattern', $current);
676 $xml_data->Pop('us-zip-area');
677 }
678 if($address_filters->allowed_world_area === true) {
679 $xml_data->EmptyElement('world-area');
680 }
681 for($i=0; $i<count($address_filters->allowed_country_codes_arr); $i++) {
682 $xml_data->Push('postal-area');
683 $country_code = $address_filters->allowed_country_codes_arr[$i];
684 $postal_pattern = $address_filters->allowed_postal_patterns_arr[$i];
685 $xml_data->Element('country-code', $country_code);
686 if ($postal_pattern != "") {
687 $xml_data->Element('postal-code-pattern', $postal_pattern);
688 }
689 $xml_data->Pop('postal-area');
690 }
691 $xml_data->Pop('allowed-areas');
692 }
693
694 if($address_filters->excluded_restrictions) {
695 if (!$address_filters->allowed_restrictions) {
696 $xml_data->EmptyElement('allowed-areas');
697 }
698 $xml_data->Push('excluded-areas');
699 if($address_filters->excluded_country_area != "")
700 $xml_data->EmptyElement('us-country-area',
701 array('country-area' =>
702 $address_filters->excluded_country_area));
703 foreach($address_filters->excluded_state_areas_arr as $current) {
704 $xml_data->Push('us-state-area');
705 $xml_data->Element('state', $current);
706 $xml_data->Pop('us-state-area');
707 }
708 foreach($address_filters->excluded_zip_patterns_arr as $current) {
709 $xml_data->Push('us-zip-area');
710 $xml_data->Element('zip-pattern', $current);
711 $xml_data->Pop('us-zip-area');
712 }
713 for($i=0; $i<count($address_filters->excluded_country_codes_arr); $i++) {
714 $xml_data->Push('postal-area');
715 $country_code = $address_filters->excluded_country_codes_arr[$i];
716 $postal_pattern = $address_filters->excluded_postal_patterns_arr[$i];
717 $xml_data->Element('country-code', $country_code);
718 if ($postal_pattern != "") {
719 $xml_data->Element('postal-code-pattern', $postal_pattern);
720 }
721 $xml_data->Pop('postal-area');
722 }
723 $xml_data->Pop('excluded-areas');
724 }
725 $xml_data->Pop('address-filters');
726 }
727 }
728 $xml_data->Pop($ship->type);
729 }
730 else if ($ship->type == "carrier-calculated-shipping"){
731 // $xml_data->Push($ship->type, array('name' => $ship->name));
732 $xml_data->Push($ship->type);
733 $xml_data->Push('carrier-calculated-shipping-options');
734 $CCSoptions = $ship->CarrierCalculatedShippingOptions;
735 foreach($CCSoptions as $CCSoption){
736 $xml_data->Push('carrier-calculated-shipping-option');
737 $xml_data->Element('price', $CCSoption->price,
738 array('currency' => $this->currency));
739 $xml_data->Element('shipping-company', $CCSoption->shipping_company);
740 $xml_data->Element('shipping-type', $CCSoption->shipping_type);
741 $xml_data->Element('carrier-pickup', $CCSoption->carrier_pickup);
742 if(!empty($CCSoption->additional_fixed_charge)) {
743 $xml_data->Element('additional-fixed-charge',
744 $CCSoption->additional_fixed_charge,
745 array('currency' => $this->currency));
746 }
747 if(!empty($CCSoption->additional_variable_charge_percent)) {
748 $xml_data->Element('additional-variable-charge-percent',
749 $CCSoption->additional_variable_charge_percent);
750 }
751 $xml_data->Pop('carrier-calculated-shipping-option');
752 }
753 $xml_data->Pop('carrier-calculated-shipping-options');
754 // $ShippingPackage = $ship->ShippingPackage;
755 $xml_data->Push('shipping-packages');
756 $xml_data->Push('shipping-package');
757 $xml_data->Push('ship-from', array('id' => $ship->ShippingPackage->ship_from->id));
758 $xml_data->Element('city', $ship->ShippingPackage->ship_from->city);
759 $xml_data->Element('region', $ship->ShippingPackage->ship_from->region);
760 $xml_data->Element('postal-code', $ship->ShippingPackage->ship_from->postal_code);
761 $xml_data->Element('country-code', $ship->ShippingPackage->ship_from->country_code);
762 $xml_data->Pop('ship-from');
763
764 $xml_data->EmptyElement('width', array('unit' => $ship->ShippingPackage->unit,
765 'value' => $ship->ShippingPackage->width
766 ));
767 $xml_data->EmptyElement('length', array('unit' => $ship->ShippingPackage->unit,
768 'value' => $ship->ShippingPackage->length
769 ));
770 $xml_data->EmptyElement('height', array('unit' => $ship->ShippingPackage->unit,
771 'value' => $ship->ShippingPackage->height
772 ));
773 $xml_data->Element('delivery-address-category',
774 $ship->ShippingPackage->delivery_address_category);
775 $xml_data->Pop('shipping-package');
776 $xml_data->Pop('shipping-packages');
777
778 $xml_data->Pop($ship->type);
779 }
780 else if ($ship->type == "pickup") {
781 $xml_data->Push('pickup', array('name' => $ship->name));
782 $xml_data->Element('price', $ship->price,
783 array('currency' => $this->currency));
784 $xml_data->Pop('pickup');
785 }
786 }
787 if(count($this->shipping_arr) > 0)
788 $xml_data->Pop('shipping-methods');
789
790 if($this->request_buyer_phone != "")
791 $xml_data->Element('request-buyer-phone-number',
792 $this->request_buyer_phone);
793
794 if($this->merchant_calculations_url != "") {
795 $xml_data->Push('merchant-calculations');
796 $xml_data->Element('merchant-calculations-url',
797 $this->merchant_calculations_url);
798 if($this->accept_merchant_coupons != "") {
799 $xml_data->Element('accept-merchant-coupons',
800 $this->accept_merchant_coupons);
801 }
802 if($this->accept_gift_certificates != "") {
803 $xml_data->Element('accept-gift-certificates',
804 $this->accept_gift_certificates);
805 }
806 $xml_data->Pop('merchant-calculations');
807 }
808 //Set Third party Tracking
809 if($this->thirdPartyTackingUrl) {
810 $xml_data->Push('parameterized-urls');
811 $xml_data->Push('parameterized-url',
812 array('url' => $this->thirdPartyTackingUrl));
813 if(is_array($this->thirdPartyTackingParams)
814 && count($this->thirdPartyTackingParams)>0) {
815 $xml_data->Push('parameters');
816 foreach($this->thirdPartyTackingParams as $tracking_param_name =>
817 $tracking_param_type) {
818 $xml_data->emptyElement('url-parameter',
819 array('name' => $tracking_param_name,
820 'type' => $tracking_param_type));
821 }
822 $xml_data->pop('parameters');
823 }
824 $xml_data->pop('parameterized-url');
825 $xml_data->pop('parameterized-urls');
826 }
827
828 //Set Default and Alternate tax tables
829 if( (count($this->alternate_tax_tables_arr) != 0)
830 || (count($this->default_tax_rules_arr) != 0)) {
831 if($this->merchant_calculated_tax != "") {
832 $xml_data->Push('tax-tables',
833 array('merchant-calculated' => $this->merchant_calculated_tax));
834 }
835 else {
836 $xml_data->Push('tax-tables');
837 }
838 if(count($this->default_tax_rules_arr) != 0) {
839 $xml_data->Push('default-tax-table');
840 $xml_data->Push('tax-rules');
841 foreach($this->default_tax_rules_arr as $curr_rule) {
842
843 if($curr_rule->country_area != "") {
844 $xml_data->Push('default-tax-rule');
845 $xml_data->Element('shipping-taxed', $curr_rule->shipping_taxed);
846 $xml_data->Element('rate', $curr_rule->tax_rate);
847 $xml_data->Push('tax-area');
848 $xml_data->EmptyElement('us-country-area',
849 array('country-area' => $curr_rule->country_area));
850 $xml_data->Pop('tax-area');
851 $xml_data->Pop('default-tax-rule');
852 }
853
854 foreach($curr_rule->state_areas_arr as $current) {
855 $xml_data->Push('default-tax-rule');
856 $xml_data->Element('shipping-taxed', $curr_rule->shipping_taxed);
857 $xml_data->Element('rate', $curr_rule->tax_rate);
858 $xml_data->Push('tax-area');
859 $xml_data->Push('us-state-area');
860 $xml_data->Element('state', $current);
861 $xml_data->Pop('us-state-area');
862 $xml_data->Pop('tax-area');
863 $xml_data->Pop('default-tax-rule');
864 }
865
866 foreach($curr_rule->zip_patterns_arr as $current) {
867 $xml_data->Push('default-tax-rule');
868 $xml_data->Element('shipping-taxed', $curr_rule->shipping_taxed);
869 $xml_data->Element('rate', $curr_rule->tax_rate);
870 $xml_data->Push('tax-area');
871 $xml_data->Push('us-zip-area');
872 $xml_data->Element('zip-pattern', $current);
873 $xml_data->Pop('us-zip-area');
874 $xml_data->Pop('tax-area');
875 $xml_data->Pop('default-tax-rule');
876 }
877
878 for($i=0; $i<count($curr_rule->country_codes_arr); $i++) {
879 $xml_data->Push('default-tax-rule');
880 $xml_data->Element('shipping-taxed', $curr_rule->shipping_taxed);
881 $xml_data->Element('rate', $curr_rule->tax_rate);
882 $xml_data->Push('tax-area');
883 $xml_data->Push('postal-area');
884 $country_code = $curr_rule->country_codes_arr[$i];
885 $postal_pattern = $curr_rule->postal_patterns_arr[$i];
886 $xml_data->Element('country-code', $country_code);
887 if ($postal_pattern != "") {
888 $xml_data->Element('postal-code-pattern', $postal_pattern);
889 }
890 $xml_data->Pop('postal-area');
891 $xml_data->Pop('tax-area');
892 $xml_data->Pop('default-tax-rule');
893 }
894
895 if ($curr_rule->world_area === true) {
896 $xml_data->Push('default-tax-rule');
897 $xml_data->Element('shipping-taxed', $curr_rule->shipping_taxed);
898 $xml_data->Element('rate', $curr_rule->tax_rate);
899 $xml_data->Push('tax-area');
900 $xml_data->EmptyElement('world-area');
901 $xml_data->Pop('tax-area');
902 $xml_data->Pop('default-tax-rule');
903 }
904 }
905 $xml_data->Pop('tax-rules');
906 $xml_data->Pop('default-tax-table');
907 }
908
909 if(count($this->alternate_tax_tables_arr) != 0) {
910 $xml_data->Push('alternate-tax-tables');
911 foreach($this->alternate_tax_tables_arr as $curr_table) {
912 $xml_data->Push('alternate-tax-table',
913 array('standalone' => $curr_table->standalone,
914 'name' => $curr_table->name));
915 $xml_data->Push('alternate-tax-rules');
916
917 foreach($curr_table->tax_rules_arr as $curr_rule) {
918 if($curr_rule->country_area != "") {
919 $xml_data->Push('alternate-tax-rule');
920 $xml_data->Element('rate', $curr_rule->tax_rate);
921 $xml_data->Push('tax-area');
922 $xml_data->EmptyElement('us-country-area',
923 array('country-area' => $curr_rule->country_area));
924 $xml_data->Pop('tax-area');
925 $xml_data->Pop('alternate-tax-rule');
926 }
927
928 foreach($curr_rule->state_areas_arr as $current) {
929 $xml_data->Push('alternate-tax-rule');
930 $xml_data->Element('rate', $curr_rule->tax_rate);
931 $xml_data->Push('tax-area');
932 $xml_data->Push('us-state-area');
933 $xml_data->Element('state', $current);
934 $xml_data->Pop('us-state-area');
935 $xml_data->Pop('tax-area');
936 $xml_data->Pop('alternate-tax-rule');
937 }
938
939 foreach($curr_rule->zip_patterns_arr as $current) {
940 $xml_data->Push('alternate-tax-rule');
941 $xml_data->Element('rate', $curr_rule->tax_rate);
942 $xml_data->Push('tax-area');
943 $xml_data->Push('us-zip-area');
944 $xml_data->Element('zip-pattern', $current);
945 $xml_data->Pop('us-zip-area');
946 $xml_data->Pop('tax-area');
947 $xml_data->Pop('alternate-tax-rule');
948 }
949
950 for($i=0; $i<count($curr_rule->country_codes_arr); $i++) {
951 $xml_data->Push('alternate-tax-rule');
952 $xml_data->Element('rate', $curr_rule->tax_rate);
953 $xml_data->Push('tax-area');
954 $xml_data->Push('postal-area');
955 $country_code = $curr_rule->country_codes_arr[$i];
956 $postal_pattern = $curr_rule->postal_patterns_arr[$i];
957 $xml_data->Element('country-code', $country_code);
958 if ($postal_pattern != "") {
959 $xml_data->Element('postal-code-pattern', $postal_pattern);
960 }
961 $xml_data->Pop('postal-area');
962 $xml_data->Pop('tax-area');
963 $xml_data->Pop('alternate-tax-rule');
964 }
965
966 if ($curr_rule->world_area === true) {
967 $xml_data->Push('alternate-tax-rule');
968 $xml_data->Element('rate', $curr_rule->tax_rate);
969 $xml_data->Push('tax-area');
970 $xml_data->EmptyElement('world-area');
971 $xml_data->Pop('tax-area');
972 $xml_data->Pop('alternate-tax-rule');
973 }
974 }
975 $xml_data->Pop('alternate-tax-rules');
976 $xml_data->Pop('alternate-tax-table');
977 }
978 $xml_data->Pop('alternate-tax-tables');
979 }
980 $xml_data->Pop('tax-tables');
981 }
982
983 if (($this->rounding_mode != "") && ($this->rounding_rule != "")) {
984 $xml_data->Push('rounding-policy');
985 $xml_data->Element('mode', $this->rounding_mode);
986 $xml_data->Element('rule', $this->rounding_rule);
987 $xml_data->Pop('rounding-policy');
988 }
989 if($this->analytics_data != ''){
990 $xml_data->Element('analytics-data', $this->analytics_data);
991 }
992
993 $xml_data->Pop('merchant-checkout-flow-support');
994 $xml_data->Pop('checkout-flow-support');
995 $xml_data->Pop('checkout-shopping-cart');
996
997 return $xml_data->GetXML();
998 }
999
1000 /**
1001 * Set the Google Checkout button's variant.
1002 * {@link http://code.google.com/apis/checkout/developer/index.html#google_checkout_buttons}
1003 *
1004 * @param bool $variant true for an enabled button, false for a
1005 * disabled one
1006 *
1007 * @return void
1008 */
1009 function SetButtonVariant($variant) {
1010 switch ($variant) {
1011 case false:
1012 $this->variant = "disabled";
1013 break;
1014 case true:
1015 default:
1016 $this->variant = "text";
1017 break;
1018 }
1019 }
1020
1021 /**
1022 * Submit a server-to-server request.
1023 * Creates a GoogleRequest object (defined in googlerequest.php) and sends
1024 * it to the Google Checkout server.
1025 *
1026 * more info:
1027 * {@link http://code.google.com/apis/checkout/developer/index.html#alternate_technique}
1028 *
1029 * @return array with the returned http status code (200 if OK) in index 0
1030 * and the redirect url returned by the server in index 1
1031 */
1032 function CheckoutServer2Server($proxy=array(), $certPath='') {
1033 require_once(dirname(__FILE__).'/library/googlerequest.php');
1034 $GRequest = new GoogleRequest($this->merchant_id,
1035 $this->merchant_key,
1036 $this->server_url=="https://checkout.google.com/"?
1037 "Production":"sandbox",
1038 $this->currency);
1039 $GRequest->SetProxy($proxy);
1040 $GRequest->SetCertificatePath($certPath);
1041
1042 return $GRequest->SendServer2ServerCart($this->GetXML());
1043 }
1044
1045 /**
1046 * Get the Google Checkout button's html to be used in a server-to-server
1047 * request.
1048 *
1049 * {@link http://code.google.com/apis/checkout/developer/index.html#google_checkout_buttons}
1050 *
1051 * @param string $url the merchant's site url where the form will be posted
1052 * to
1053 * @param string $size the size of the button, one of 'large', 'medium' or
1054 * 'small'.
1055 * defaults to 'large'
1056 * @param bool $variant true for an enabled button, false for a
1057 * disabled one. defaults to true. will be ignored if
1058 * SetButtonVariant() was used before.
1059 * @param string $loc the locale of the button's text, the only valid value
1060 * is 'en_US' (used as default)
1061 * @param bool $showtext whether to show Google Checkout text or not,
1062 * defaults to true.
1063 * @param string $style the background style of the button, one of 'white'
1064 * or 'trans'. defaults to "trans"
1065 *
1066 * @return string the button's html
1067 */
1068 function CheckoutServer2ServerButton($url, $size="large", $variant=true,
1069 $loc="en_US",$showtext=true, $style="trans") {
1070
1071 switch (strtolower($size)) {
1072 case "medium":
1073 $width = "168";
1074 $height = "44";
1075 break;
1076
1077 case "small":
1078 $width = "160";
1079 $height = "43";
1080 break;
1081 case "large":
1082 default:
1083 $width = "180";
1084 $height = "46";
1085 break;
1086 }
1087
1088 if($this->variant == false) {
1089 switch ($variant) {
1090 case false:
1091 $this->variant = "disabled";
1092 break;
1093 case true:
1094 default:
1095 $this->variant = "text";
1096 break;
1097 }
1098 }
1099 $data = "<div style=\"width: ".$width."px\">";
1100 if ($this->variant == "text") {
1101 $data .= "<div align=\"center\"><form method=\"post\" action=\"".
1102 $url . "\"" . ($this->googleAnalytics_id?
1103 " onsubmit=\"setUrchinInputCode();\"":"") . ">
1104 <input type=\"image\" name=\"Checkout\" alt=\"Checkout\"
1105 src=\"". $this->server_url."buttons/checkout.gif?merchant_id=" .
1106 $this->merchant_id."&amp;w=".$width. "&amp;h=".$height."&amp;style=".
1107 $style."&amp;variant=".$this->variant."&amp;loc=".$loc."\"
1108 style=\"height:".$height."px;width:".$width. "px\" />";
1109
1110 if($this->googleAnalytics_id) {
1111 $data .= "<input type=\"hidden\" name=\"analyticsdata\" value=\"\" />";
1112 }
1113 $data .= "</form></div>";
1114 if($this->googleAnalytics_id) {
1115 $data .= "<!-- Start Google analytics -->
1116 <script src=\"https://ssl.google-analytics.com/urchin.js\" type=\"".
1117 "text/javascript\">
1118 </script>
1119 <script type=\"text/javascript\">
1120 _uacct = \"" . $this->googleAnalytics_id . "\";
1121 urchinTracker();
1122 </script>
1123 <script src=\"https://checkout.google.com/files/digital/urchin_po" .
1124 "st.js\" type=\"text/javascript\"></script>
1125 <!-- End Google analytics -->";
1126 } } else {
1127 $data .= "<div><img alt=\"Checkout\" src=\"" .
1128 "". $this->server_url."buttons/checkout.gif?merchant_id=" .
1129 "".$this->merchant_id."&amp;w=".$width. "&amp;h=".$height."&amp;style=".$style.
1130 "&amp;variant=".$this->variant."&amp;loc=".$loc."\" height=\"".$height."\"".
1131 " width=\"".$width. "\" /></div>";
1132
1133 }
1134 $data .= "</div>";
1135 return $data;
1136 }
1137
1138 /**
1139 * Get the Google Checkout button's html.
1140 *
1141 * {@link http://code.google.com/apis/checkout/developer/index.html#google_checkout_buttons}
1142 *
1143 * @param string $size the size of the button, one of 'large', 'medium' or
1144 * 'small'.
1145 * defaults to 'large'
1146 * @param bool $variant true for an enabled button, false for a
1147 * disabled one. defaults to true. will be ignored if
1148 * SetButtonVariant() was used before.
1149 * @param string $loc the locale of the button's text, the only valid value
1150 * is 'en_US' (used as default)
1151 * @param bool $showtext whether to show Google Checkout text or not,
1152 * defaults to true.
1153 * @param string $style the background style of the button, one of 'white'
1154 * or 'trans'. defaults to "trans"
1155 *
1156 * @return string the button's html
1157 */
1158 function CheckoutButtonCode($size="large", $variant=true, $loc="en_US",
1159 $showtext=true, $style="trans") {
1160
1161 switch (strtolower($size)) {
1162 case "medium":
1163 $width = "168";
1164 $height = "44";
1165 break;
1166
1167 case "small":
1168 $width = "160";
1169 $height = "43";
1170 break;
1171 case "large":
1172 default:
1173 $width = "180";
1174 $height = "46";
1175 break;
1176 }
1177
1178 if($this->variant == false) {
1179 switch ($variant) {
1180 case false:
1181 $this->variant = "disabled";
1182 break;
1183 case true:
1184 default:
1185 $this->variant = "text";
1186 break;
1187 }
1188 }
1189
1190
1191 $data = "<div style=\"width: ".$width."px\">";
1192 if ($this->variant == "text") {
1193 $data .= "<div align=\"center\"><form method=\"post\" action=\"".
1194 $this->checkout_url . "\"" . ($this->googleAnalytics_id?
1195 " onsubmit=\"setUrchinInputCode();\"":"") . ">
1196 <input type=\"hidden\" name=\"cart\" value=\"".
1197 base64_encode($this->GetXML()) ."\">
1198 <input type=\"hidden\" name=\"signature\" value=\"".
1199 base64_encode($this->CalcHmacSha1($this->GetXML())). "\">
1200 <input type=\"image\" name=\"Checkout\" alt=\"Checkout\"
1201 src=\"". $this->server_url."buttons/checkout.gif?merchant_id=" .
1202 $this->merchant_id."&amp;w=".$width. "&amp;h=".$height."&amp;style=".
1203 $style."&amp;variant=".$this->variant."&amp;loc=".$loc."\"
1204 style=\"height:".$height."px;width:".$width. "px\" />";
1205
1206 if($this->googleAnalytics_id) {
1207 $data .= "<input type=\"hidden\" name=\"analyticsdata\" value=\"\" />";
1208 }
1209 $data .= "</form></div>";
1210 if($this->googleAnalytics_id) {
1211 $data .= "<!-- Start Google analytics -->
1212 <script src=\"https://ssl.google-analytics.com/urchin.js\" type=\"".
1213 "text/javascript\">
1214 </script>
1215 <script type=\"text/javascript\">
1216 _uacct = \"" . $this->googleAnalytics_id . "\";
1217 urchinTracker();
1218 </script>
1219 <script src=\"https://checkout.google.com/files/digital/urchin_po" .
1220 "st.js\" type=\"text/javascript\"></script>
1221 <!-- End Google analytics -->";
1222 }
1223 } else {
1224 $data .= "<div><img alt=\"Checkout\" src=\"" .
1225 "". $this->server_url."buttons/checkout.gif?merchant_id=" .
1226 "".$this->merchant_id."&amp;w=".$width. "&amp;h=".$height."&amp;style=".$style.
1227 "&amp;variant=".$this->variant."&amp;loc=".$loc."\" height=\"".$height."\"".
1228 " width=\"".$width. "\" /></div>";
1229 }
1230 if($showtext) {
1231 $data .="<div align=\"center\"><a href=\"javascript:void(window.ope".
1232 "n('http://checkout.google.com/seller/what_is_google_checkout.html'" .
1233 ",'whatischeckout','scrollbars=0,resizable=1,directories=0,height=2" .
1234 "50,width=400'));\" onmouseover=\"return window.status = 'What is G" .
1235 "oogle Checkout?'\" onmouseout=\"return window.status = ''\"><font " .
1236 "size=\"-2\">What is Google Checkout?</font></a></div>";
1237 }
1238 $data .= "</div>";
1239 return $data;
1240 }
1241 //Code for generating Checkout button
1242 //@param $variant will be ignored if SetButtonVariant() was used before
1243 function CheckoutButtonNowCode($size="large", $variant=true, $loc="en_US",
1244 $showtext=true, $style="trans") {
1245
1246 switch (strtolower($size)) {
1247 case "small":
1248 $width = "121";
1249 $height = "44";
1250 break;
1251 case "large":
1252 default:
1253 $width = "117";
1254 $height = "48";
1255 break;
1256 }
1257
1258 if($this->variant == false) {
1259 switch ($variant) {
1260 case false:
1261 $this->variant = "disabled";
1262 break;
1263 case true:
1264 default:
1265 $this->variant = "text";
1266 break;
1267 }
1268 }
1269
1270
1271
1272 $data = "<div style=\"width: ".$width."px\">";
1273 if ($this->variant == "text") {
1274 $data .= "<div align=\"center\"><form method=\"post\" action=\"".
1275 $this->checkout_url . "\"" . ($this->googleAnalytics_id?
1276 " onsubmit=\"setUrchinInputCode();\"":"") . ">
1277 <input type=\"hidden\" name=\"buyButtonCart\" value=\"".
1278 base64_encode($this->GetXML()) ."//separator//" .
1279 base64_encode($this->CalcHmacSha1($this->GetXML())) . "\">
1280 <input type=\"image\" name=\"Checkout\" alt=\"BuyNow\"
1281 src=\"". $this->server_url."buttons/buy.gif?merchant_id=" .
1282 $this->merchant_id."&amp;w=".$width. "&amp;h=".$height."&amp;style=".
1283 $style."&amp;variant=".$this->variant."&amp;loc=".$loc."\"
1284 style=\"height:".$height."px;width:".$width. "px\" />";
1285
1286 if($this->googleAnalytics_id) {
1287 $data .= "<input type=\"hidden\" name=\"analyticsdata\" value=\"\" />";
1288 }
1289 $data .= "</form></div>";
1290 if($this->googleAnalytics_id) {
1291 $data .= "<!-- Start Google analytics -->
1292 <script src=\"https://ssl.google-analytics.com/urchin.js\" type=\"".
1293 "text/javascript\">
1294 </script>
1295 <script type=\"text/javascript\">
1296 _uacct = \"" . $this->googleAnalytics_id . "\";
1297 urchinTracker();
1298 </script>
1299 <script src=\"https://checkout.google.com/files/digital/urchin_po" .
1300 "st.js\" type=\"text/javascript\"></script>
1301 <!-- End Google analytics -->";
1302 }
1303 // ask for link to BuyNow disable button
1304 } else {
1305 $data .= "<div><img alt=\"Checkout\" src=\"" .
1306 "". $this->server_url."buttons/buy.gif?merchant_id=" .
1307 "".$this->merchant_id."&w=".$width. "&h=".$height."&style=".$style.
1308 "&variant=".$this->variant."&loc=".$loc."\" height=\"".$height."\"".
1309 " width=\"".$width. "\" /></div>";
1310 }
1311 if($showtext) {
1312 $data .="<div align=\"center\"><a href=\"javascript:void(window.ope".
1313 "n('http://checkout.google.com/seller/what_is_google_checkout.html'" .
1314 ",'whatischeckout','scrollbars=0,resizable=1,directories=0,height=2" .
1315 "50,width=400'));\" onmouseover=\"return window.status = 'What is G" .
1316 "oogle Checkout?'\" onmouseout=\"return window.status = ''\"><font " .
1317 "size=\"-2\">What is Google Checkout?</font></a></div>";
1318 }
1319 $data .= "</div>";
1320 return $data;
1321 }
1322
1323
1324 /**
1325 * Get the Google Checkout button's html to be used with the html api.
1326 *
1327 * {@link http://code.google.com/apis/checkout/developer/index.html#google_checkout_buttons}
1328 *
1329 * @param string $size the size of the button, one of 'large', 'medium' or
1330 * 'small'.
1331 * defaults to 'large'
1332 * @param bool $variant true for an enabled button, false for a
1333 * disabled one. defaults to true. will be ignored if
1334 * SetButtonVariant() was used before.
1335 * @param string $loc the locale of the button's text, the only valid value
1336 * is 'en_US' (used as default)
1337 * @param bool $showtext whether to show Google Checkout text or not,
1338 * defaults to true.
1339 * @param string $style the background style of the button, one of 'white'
1340 * or 'trans'. defaults to "trans"
1341 *
1342 * @return string the button's html
1343 */
1344 function CheckoutHTMLButtonCode($size="large", $variant=true, $loc="en_US",
1345 $showtext=true, $style="trans") {
1346
1347 switch (strtolower($size)) {
1348 case "medium":
1349 $width = "168";
1350 $height = "44";
1351 break;
1352
1353 case "small":
1354 $width = "160";
1355 $height = "43";
1356 break;
1357 case "large":
1358 default:
1359 $width = "180";
1360 $height = "46";
1361 break;
1362 }
1363
1364 if($this->variant == false) {
1365 switch ($variant) {
1366 case false:
1367 $this->variant = "disabled";
1368 break;
1369 case true:
1370 default:
1371 $this->variant = "text";
1372 break;
1373 }
1374 }
1375
1376
1377 $data = "<div style=\"width: ".$width."px\">";
1378 if ($this->variant == "text") {
1379 $data .= "<div align=\"center\"><form method=\"post\" action=\"".
1380 $this->checkoutForm_url . "\"" . ($this->googleAnalytics_id?
1381 " onsubmit=\"setUrchinInputCode();\"":"") . ">";
1382
1383 $request = $this->GetXML();
1384 require_once(dirname(__FILE__).'/xml-processing/gc_xmlparser.php');
1385 $xml_parser = new gc_xmlparser($request);
1386 $root = $xml_parser->GetRoot();
1387 $XMLdata = $xml_parser->GetData();
1388 $this->xml2html($XMLdata[$root], '', $data);
1389 $data .= "<input type=\"image\" name=\"Checkout\" alt=\"Checkout\" " .
1390 "src=\"". $this->server_url."buttons/checkout.gif?merchant_id=".
1391 $this->merchant_id."&w=".$width. "&h=".$height."&style=".
1392 $style."&variant=".$this->variant."&loc=".$loc."\"
1393 height=\"".$height."\" width=\"".$width. "\" />";
1394
1395 if($this->googleAnalytics_id) {
1396 $data .= "<input type=\"hidden\" name=\"analyticsdata\" value=\"\" />";
1397 }
1398 $data .= "</form></div>";
1399 if($this->googleAnalytics_id) {
1400 $data .= "<!-- Start Google analytics -->
1401 <script src=\"https://ssl.google-analytics.com/urchin.js\" type=\"".
1402 "text/javascript\">
1403 </script>
1404 <script type=\"text/javascript\">
1405 _uacct = \"" . $this->googleAnalytics_id . "\";
1406 urchinTracker();
1407 </script>
1408 <script src=\"https://checkout.google.com/files/digital/urchin_po" .
1409 "st.js\" type=\"text/javascript\"></script>
1410 <!-- End Google analytics -->";
1411 }
1412 } else {
1413 $data .= "<div align=\"center\"><img alt=\"Checkout\" src=\"" .
1414 "". $this->server_url."buttons/checkout.gif?merchant_id=" .
1415 "".$this->merchant_id."&amp;w=".$width. "&amp;h=".$height."&amp;style=".$style.
1416 "&amp;variant=".$this->variant."&amp;loc=".$loc."\" height=\"".$height."\"".
1417 " width=\"".$width. "\" /></div>";
1418 }
1419 if($showtext){
1420 $data .= "<div align=\"center\"><a href=\"javascript:void(window.ope" .
1421 "n('http://checkout.google.com/seller/what_is_google_checkout.html'" .
1422 ",'whatischeckout','scrollbars=0,resizable=1,directories=0,height=2" .
1423 "50,width=400'));\" onmouseover=\"return window.status = 'What is G" .
1424 "oogle Checkout?'\" onmouseout=\"return window.status = ''\"><font " .
1425 "size=\"-2\">What is Google Checkout?</font></a></div>";
1426 }
1427 $data .= "</div>";
1428
1429
1430 return $data;
1431
1432 }
1433
1434 /**
1435 * @access private
1436 */
1437 function xml2html($data, $path = '', &$rta){
1438 // global $multiple_tags,$ignore_tags;
1439 // $arr = gc_get_arr_result($data);
1440 foreach($data as $tag_name => $tag) {
1441 if(isset($this->ignore_tags[$tag_name])){
1442 continue;
1443 }
1444 if(is_array($tag)){
1445 // echo print_r($tag, true) . $tag_name . "<- tag name\n";
1446 if(!$this->is_associative_array($data)) {
1447 $new_path = $path . '-' . ($tag_name +1);
1448 } else {
1449 if(isset($this->multiple_tags[$tag_name])
1450 && $this->is_associative_array($tag)
1451 && !$this->isChildOf($path, $this->multiple_tags[$tag_name])){
1452 $tag_name .= '-1';
1453 }
1454 $new_path = $path . (empty($path)?'':'.') . $tag_name;
1455 }
1456 $this->xml2html($tag, $new_path, $rta);
1457 }
1458 else {
1459 $new_path = $path;
1460 if($tag_name != 'VALUE'){
1461 $new_path = $path . "." . $tag_name;
1462 }
1463 $rta .= '<input type="hidden" name="' .
1464 $new_path . '" value="' .$tag . '"/>'."\n";
1465 }
1466 }
1467 }
1468
1469 // Returns true if a given variable represents an associative array
1470 /**
1471 * @access private
1472 */
1473 function is_associative_array($var) {
1474 return is_array($var) && !is_numeric(implode('', array_keys($var)));
1475 }
1476
1477 /**
1478 * @access private
1479 */
1480 function isChildOf($path='', $parents=array()){
1481 $intersect =array_intersect(explode('.',$path), $parents);
1482 return !empty($intersect);
1483 }
1484
1485 /**
1486 * Get the Google Checkout acceptance logos html
1487 *
1488 * {@link http://checkout.google.com/seller/acceptance_logos.html}
1489 *
1490 * @param integer $type the acceptance logo type, valid values: 1, 2, 3
1491 *
1492 * @return string the logo's html
1493 */
1494 function CheckoutAcceptanceLogo($type=1) {
1495 switch ($type) {
1496 case 2:
1497 return '<link rel="stylesheet" href="https://checkout.google.com/' .
1498 'seller/accept/s.css" type="text/css" media="screen" /><scrip' .
1499 't type="text/javascript" src="https://checkout.google.com/se' .
1500 'ller/accept/j.js"></script><script type="text/javascript">sh' .
1501 'owMark(1);</script><noscript><img src="https://checkout.goog' .
1502 'le.com/seller/accept/images/st.gif" width="92" height="88" a' .
1503 'lt="Google Checkout Acceptance Mark" /></noscript>';
1504 break;
1505 case 3:
1506 return '<link rel="stylesheet" href="https://checkout.google.com/' .
1507 'seller/accept/s.css" type="text/css" media="screen" /><scrip' .
1508 't type="text/javascript" src="https://checkout.google.com/se' .
1509 'ller/accept/j.js"></script><script type="text/javascript">sh' .
1510 'owMark(2);</script><noscript><img src="https://checkout.goog' .
1511 'le.com/seller/accept/images/ht.gif" width="182" height="44" ' .
1512 'alt="Google Checkout Acceptance Mark" /></noscript>';
1513 break;
1514 case 1:
1515 default:
1516 return '<link rel="stylesheet" href="https://checkout.google.com/' .
1517 'seller/accept/s.css" type="text/css" media="screen" /><scrip' .
1518 't type="text/javascript" src="https://checkout.google.com/se' .
1519 'ller/accept/j.js"></script><script type="text/javascript">sh' .
1520 'owMark(3);</script><noscript><img src="https://checkout.goog' .
1521 'le.com/seller/accept/images/sc.gif" width="72" height="73" a' .
1522 'lt="Google Checkout Acceptance Mark" /></noscript>';
1523 break;
1524 }
1525 }
1526
1527 /**
1528 * Calculates the cart's hmac-sha1 signature, this allows google to verify
1529 * that the cart hasn't been tampered by a third-party.
1530 *
1531 * {@link http://code.google.com/apis/checkout/developer/index.html#create_signature}
1532 *
1533 * @param string $data the cart's xml
1534 * @return string the cart's signature (in binary format)
1535 */
1536 function CalcHmacSha1($data) {
1537 $key = $this->merchant_key;
1538 $blocksize = 64;
1539 $hashfunc = 'sha1';
1540 if (strlen($key) > $blocksize) {
1541 $key = pack('H*', $hashfunc($key));
1542 }
1543 $key = str_pad($key, $blocksize, chr(0x00));
1544 $ipad = str_repeat(chr(0x36), $blocksize);
1545 $opad = str_repeat(chr(0x5c), $blocksize);
1546 $hmac = pack(
1547 'H*', $hashfunc(
1548 ($key^$opad).pack(
1549 'H*', $hashfunc(
1550 ($key^$ipad).$data
1551 )
1552 )
1553 )
1554 );
1555 return $hmac;
1556 }
1557
1558 //Method used internally to set true/false cart variables
1559 /**
1560 * @access private
1561 */
1562 function _GetBooleanValue($value, $default) {
1563 switch(strtolower($value)){
1564 case "true":
1565 return "true";
1566 break;
1567 case "false":
1568 return"false";
1569 break;
1570 default:
1571 return $default;
1572 break;
1573 }
1574 }
1575 //Method used internally to set true/false cart variables
1576 // Deprecated, must NOT use eval, bug-prune function
1577 /**
1578 * @access private
1579 */
1580 function _SetBooleanValue($string, $value, $default) {
1581 $value = strtolower($value);
1582 if($value == "true" || $value == "false")
1583 eval('$this->'.$string.'="'.$value.'";');
1584 else
1585 eval('$this->'.$string.'="'.$default.'";');
1586 }
1587 }
1588
1589 /**
1590 * @abstract
1591 * Abstract class that represents the merchant-private-data.
1592 *
1593 * See {@link MerchantPrivateData} and {@link MerchantPrivateItemData}
1594 *
1595 * GC tag: {@link http://code.google.com/apis/checkout/developer/index.html#tag_merchant-private-data <merchant-private-data>}
1596 */
1597 class MerchantPrivate {
1598 var $data;
1599 var $type = "Abstract";
1600 function MerchantPrivate() {
1601 }
1602
1603 function AddMerchantPrivateToXML(&$xml_data) {
1604 if(is_array($this->data)) {
1605 $xml_data->Push($this->type);
1606 $this->_recursiveAdd($xml_data, $this->data);
1607 $xml_data->Pop($this->type);
1608 }
1609 else {
1610 $xml_data->Element($this->type, (string)$this->data);
1611 }
1612 }
1613
1614 /**
1615 * @access private
1616 */
1617 function _recursiveAdd(&$xml_data, $data){
1618 foreach($data as $name => $value) {
1619 if(is_array($value)) {
1620 $xml_data->Push($name);
1621 $this->_recursiveAdd($xml_data, $name);
1622 $xml_data->Pop($name);
1623 }
1624 else {
1625 $xml_data->Element($name, (string)$value);
1626 }
1627 }
1628 }
1629 }
1630
1631 /**
1632 * Class that represents the merchant-private-data.
1633 *
1634 * GC tag: {@link http://code.google.com/apis/checkout/developer/index.html#tag_merchant-private-data <merchant-private-data>}
1635 */
1636 class MerchantPrivateData extends MerchantPrivate {
1637 /**
1638 * @param mixed $data a string with the data that will go in the
1639 * merchant-private-data tag or an array that will
1640 * be mapped to xml, formatted like (e.g.):
1641 * array('my-order-id' => 34234,
1642 * 'stuff' => array('registered' => 'yes',
1643 * 'category' => 'hip stuff'))
1644 * this will map to:
1645 * <my-order-id>
1646 * <stuff>
1647 * <registered>yes</registered>
1648 * <category>hip stuff</category>
1649 * </stuff>
1650 * </my-order-id>
1651 */
1652 function MerchantPrivateData($data = array()) {
1653 $this->data = $data;
1654 $this->type = 'merchant-private-data';
1655 }
1656 }
1657
1658 /**
1659 * Class that represents a merchant-private-item-data.
1660 *
1661 * GC tag: {@link http://code.google.com/apis/checkout/developer/index.html#tag_merchant-private-item-data <merchant-private-data>}
1662 */
1663 class MerchantPrivateItemData extends MerchantPrivate {
1664 /**
1665 * @param mixed $data a string with the data that will go in the
1666 * merchant-private-item-data tag or an array that will
1667 * be mapped to xml, formatted like:
1668 * array('my-item-id' => 34234,
1669 * 'stuff' => array('label' => 'cool',
1670 * 'category' => 'hip stuff'))
1671 * this will map to:
1672 * <my-item-id>
1673 * <stuff>
1674 * <label>cool</label>
1675 * <category>hip stuff</category>
1676 * </stuff>
1677 * </my-item-id>
1678 */
1679 function MerchantPrivateItemData($data = array()) {
1680 $this->data = $data;
1681 $this->type = 'merchant-private-item-data';
1682 }
1683 }
1684 ?>