.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{ . if \nF \{ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "Vend::Payment::GoogleCheckout 3pm" .TH Vend::Payment::GoogleCheckout 3pm "2016-08-31" "perl v5.22.2" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "Interchange GoogleCheckout support" .IX Header "Interchange GoogleCheckout support" .Vb 2 \& http://kiwi.zolotek.net is the home page with the latest version. Also to be found on \& Kevin Walsh\*(Aqs excellent Interchange site, http://interchange.rtfm.info. .Ve .SH "AUTHORS" .IX Header "AUTHORS" .Vb 1 \& Lyn St George .Ve .SH "CREDITS" .IX Header "CREDITS" .Vb 2 \& Steve Graham, mrlock.com, debugging and documentation \& Andy Smith, tvcables.co.uk, debugging and documentation .Ve .SH "PREREQUISITES" .IX Header "PREREQUISITES" XML::Simple and any of its prerequisites (eg XML::Parser or \s-1XML::SAX\s0) MIME::Base64 these should be found anyway on any well-used perl installation. This version was built especially without the Google libraries, so as to work on old machines with perl 5.6.1 and similarly vintaged OSes, and only need XML::Simple. .PP Interchange.cfg should contain this line, with args extra to 'rand' for current \s-1UTF8\s0 problems: SafeUntrap rand require caller dofile print entereval .SH "DESCRIPTION" .IX Header "DESCRIPTION" This integrates Google Checkout quite tightly into Interchange \- it is expected that all coupons, gift certificates, discounts, tax routines and shipping will be processed by Interchange before sending the customer to Google. The customer will see the basket, tax, shipping and total cost when he arrives there. The shipping is sent as a final value, while the tax is sent as a rate for Google to calculate with. The total cost is calculated by Google, and there is the possibility of penny differences due to rounding errors or different rounding methods employed in different countries. As Google won't accept final tax or total cost figures this cannot be helped. .PP This module will authorise and optionally charge the customer's card for the purchase. It will handle all IPNs (notifications sent back by Google of various events in the process) and both log the results and send emails to the merchant and customer as appropriate. IPNs relating to chargebacks, refunds and cancellations are included in this. It can handle commands sent through an admin panel \- though the current \s-1IC\s0 panel is not set up to send these. Commands relating to 'charge', 'refund', 'cancel' etc would normally be sent through the Google admin panel, but the resulting IPNs are handled by this module. .PP In the interests of tighter integration and simplicity, the consensus of opinion has been to allow shipping to only the address taken by Interchange. This means that the shipping charge and tax rate will be correct, but also means that the customer cannot choose another address which he may have on file at Google \- if he does then the system will tell him that \*(L"Merchant xx does not ship to this address\*(R". He of course has the option of clicking \*(L"edit basket\*(R" and changing his address at Interchange to suit. You may want to display some sort of note to this effect prior to sending the customer to Google. If delivery is to a \s-1US\s0 address then the restriction is to the state and the first 3 digits of the zip code; if to anywhere else in the world then the restriction is to that country and the first 3 characters of the postal code (or fewer characters if fewer were entered \- if no postal code was entered then the whole country is allowed). .PP It is likely that I will build another version which does allow the customer to change his address whilst at Google, as this limitation is a little too harsh and not at all helpful for good customer relations. .ie n .SS "\s-1NOTE\s0 ########################################################################################################## # While you can send & and have it returned safely, you cannot send <, > or similar in the # # description field, as it will cause \s-1IC\s0 to throw an error when Google returns the \s-1XML.\s0 Even if you send # # these as < and similar \s-1UTF\-8\s0 entities, Google will return them in the < format. # # # # Note also that you can only send the currency that is ""associated with your seller account"", as # # defined by Google. There is no option to configure this, and they select it according to the country # # you registered in your sign-up account. Nor can you do recurring/subscription billing. # # ##########################################################################################################" .el .SS "\s-1NOTE\s0 ########################################################################################################## # While you can send & and have it returned safely, you cannot send <, > or similar in the # # description field, as it will cause \s-1IC\s0 to throw an error when Google returns the \s-1XML.\s0 Even if you send # # these as < and similar \s-1UTF\-8\s0 entities, Google will return them in the < format. # # # # Note also that you can only send the currency that is ``associated with your seller account'', as # # defined by Google. There is no option to configure this, and they select it according to the country # # you registered in your sign-up account. Nor can you do recurring/subscription billing. # # ##########################################################################################################" .IX Subsection "NOTE ########################################################################################################## # While you can send & and have it returned safely, you cannot send <, > or similar in the # # description field, as it will cause IC to throw an error when Google returns the XML. Even if you send # # these as < and similar UTF-8 entities, Google will return them in the < format. # # # # Note also that you can only send the currency that is associated with your seller account, as # # defined by Google. There is no option to configure this, and they select it according to the country # # you registered in your sign-up account. Nor can you do recurring/subscription billing. # # ##########################################################################################################" .SH "SYNOPSIS" .IX Header "SYNOPSIS" Go to http://checkout.google.com and set up a seller's account. They will give you a merchantid and a merchantkey, which you need to enter into the payment route as described below. While there, go to the \*(L"Settings\*(R" tab, then the \*(L"Integration\*(R" left menu item, and set the radio button for \*(L"\s-1XML\s0 call back\*(R", and enter the \s-1URL\s0 to your callback page \- https://your_site/ord/gcoipn. .PP Place this module in your Vend/Payment/ directory, and call it in interchange.cfg with: Require module Vend::Payment::GoogleCheckout .PP Add these configuration options to the new Google payment route in catalog.cfg: Route googlecheckout merchantid (as given to you by Google at sign-up) Route googlecheckout merchantkey (as given to you by Google at sign-up) Route googlecheckout googlehost 'https://checkout.google.com/cws/v2/Merchant' # live Route googlecheckout gcoipn_url http://your_url/cgi_link/ord/gcoipn (replace 'your_url' and 'cgi_link' with yours) Route googlecheckout currency '\s-1GBP\s0' (or \s-1USD,\s0 or any other \s-1ISO\s0 code accepted by Google) Route googlecheckout edit_basket_url (eg 'http://your_url/cgi_link/ord/basket') Route googlecheckout continue_shopping_url (eg, http://your_url/cgi_link/index) Route googlecheckout bypass_authorization (1 to bypass, empty to use. See below for details) Route googlecheckout default_taxrate (a decimal, eg '0.06', in case the calculation fails) Route googlecheckout sender_email (email address appearing in the 'from' and 'reply\-to' fields) Route googlecheckout merchant_email (email address to which the order should be sent) Route googlecheckout receipt_from_merchant (1 to send an email receipt to the customer) Route googlecheckout email_auth_charge ('charge' to send receipt after card has been charged, 'auth' after card has been authorised) Route googlecheckout html_mail ('1' to send \s-1HTML\s0 instead of plain text mail) Route googlecheckout avs_match_accepted ('full' for full match where \s-1AVS\s0 is available, 'partial' for partial match, 'none' for no match required. Default is 'partial') Route googlecheckout cv2_match_accepted ('yes' for match required, 'none' for no match required. Default is 'yes') Route googlecheckout default_country (2 letter \s-1ISO\s0 country code; use if not taking a delivery country at checkout, otherwise omit) Route googlecheckout default_state (* if you want to allow all states within a country, or omit) Route googlecheckout gco_diagnose (1 if you want to return diagnostics, empty otherwise) Variable \s-1MV_HTTP_CHARSET UTF\-8\s0 The last is essential, otherwise \s-1GCO\s0 will repeat the 'new_order_notification' message ad infinitum and never proceed any further. You will be given no clue as to why this is happening. .PP \&\s-1NB:/\s0 Apache is not built by default to make the \s-1HTTP_AUTHORIZATION\s0 header available to the environment, and so you will either need to rebuild it or set 'bypass_authorization' to 1 \- this latter will not check the returned header to see that it contains your merchantid and merchantkey. Google recommend that you make this check, but it's your choice. .PP Add these order routes to catalog.cfg Route googlecheckout <<\s-1EOF \&\s0 attach 0 empty 1 default 1 supplant 1 no_receipt 1 report etc/log_transaction track logs/tracking.asc counter_tid logs/tid.counter \&\s-1EOF\s0 .PP Route gco_final master 1 Route gco_final cascade \*(L"copy_user main_entry\*(R" Route gco_final empty 1 Route gco_final supplant 1 Route gco_final no_receipt 1 Route gco_final email _\|_ORDERS_TO_\|_ .PP The 'edit basket' \s-1URL\s0 is available to customers when they are at Google, and lets them change either the basket contents or the delivery address. .PP Create a GoogleCheckout button on your checkout page, including the order profile and route like so: [button mv_click=google text=\*(L"GoogleCheckout\*(R" hidetext=1 form=checkout ] mv_order_profile=googlecheckout mv_order_route=googlecheckout mv_todo=submit [/button] .PP Create a page in pages/ord/ called gcoipn.html, consisting of this: [charge route=\*(L"googlecheckout\*(R" gcorequest=\*(L"callback\*(R"] This page is the target of all \s-1IPN\s0 callbacks from Google, and will call the payment module in the correct mode. .PP To have GoogleCheckout co-operate with your normal payment service provider, eg Authorizenet, do the following: .PP Add to etc/profiles.order: .PP _\|_NAME_\|_ googlecheckout _\|_COMMON_ORDER_PROFILE_\|_ &fatal = yes email=required email=email &set=mv_payment \s-1GCO\s0 &set=psp \s-1GCO\s0 &set=mv_payment_route googlecheckout &set=mv_order_route googlecheckout &final = yes &setcheck = payment_method googlecheckout _\|_END_\|_ or, if you want to use \s-1GCO\s0 as a 'Buy now' button without taking any customer details, then omit the _\|_COMMON_ORDER_PROFILE_\|_ and the two 'email=...' lines above. Google are in fact quite finicky about you not taking your customer's details, so you have the option of complying with Google or complying with your own policy. .PP You must have \s-1MV_PAYMENT_MODE\s0 set in products/variable.txt to either your standard payment processor or to 'googlecheckout'; though you may instead set this in catalog.cfg rather than variable txt as: Variable \s-1MV_PAYMENT_MODE\s0 googlecheckout .PP Within the 'credit_card' section of etc/profiles.order leave \&\*(L"\s-1MV_PAYMENT_MODE\*(R" \s0 as set and add &set=psp _\|_MV_PAYMENT_PSP_\|_ &set=mv_payment_route authorizenet (or your preferred gateway) as the last entries in the section. .PP and then add Variable \s-1MV_PAYMENT_PSP \s0\*(L"foo\*(R" to catalog.cfg, where \*(L"foo\*(R" is the name of your gateway or acquirer, formatted as you want it to appear on the receipt. Eg, \*(L"Bank of America\*(R" (rather than boa), \*(L"AuthorizeNet\*(R" (rather than authorizenet). .PP Run the following at a MySQL prompt to add the requisite fields to your transactions table: (with thanks to Steve Graham) .PP \&\s-1ALTER TABLE\s0 `transactions` \s-1ADD\s0 `gco_order_number` \s-1VARCHAR\s0( 64 ) \s-1CHARACTER SET\s0 utf8 \s-1COLLATE\s0 utf8_general_ci , \&\s-1ADD\s0 `gco_buyers_id` \s-1VARCHAR\s0( 64 ) \s-1CHARACTER SET\s0 utf8 \s-1COLLATE\s0 utf8_general_ci, \&\s-1ADD\s0 `gco_fulfillment_state` \s-1VARCHAR\s0( 64 ) \s-1CHARACTER SET\s0 utf8 \s-1COLLATE\s0 utf8_general_ci, \&\s-1ADD\s0 `gco_serial_number` \s-1VARCHAR\s0( 64 ) \s-1CHARACTER SET\s0 utf8 \s-1COLLATE\s0 utf8_general_ci, \&\s-1ADD\s0 `gco_avs_response` \s-1VARCHAR\s0( 64 ) \s-1CHARACTER SET\s0 utf8 \s-1COLLATE\s0 utf8_general_ci, \&\s-1ADD\s0 `gco_cvn_response` \s-1VARCHAR\s0( 64 ) \s-1CHARACTER SET\s0 utf8 \s-1COLLATE\s0 utf8_general_ci, \&\s-1ADD\s0 `gco_protection` \s-1VARCHAR\s0( 64 ) \s-1CHARACTER SET\s0 utf8 \s-1COLLATE\s0 utf8_general_ci, \&\s-1ADD\s0 `gco_cc_number` \s-1VARCHAR\s0( 64 ) \s-1CHARACTER SET\s0 utf8 \s-1COLLATE\s0 utf8_general_ci, \&\s-1ADD\s0 `gco_timestamp` \s-1VARCHAR\s0( 64 ) \s-1CHARACTER SET\s0 utf8 \s-1COLLATE\s0 utf8_general_ci, \&\s-1ADD\s0 `gco_reason` \s-1TEXT CHARACTER SET\s0 utf8 \s-1COLLATE\s0 utf8_general_ci , \&\s-1ADD\s0 `gco_latest_charge_amount` \s-1VARCHAR\s0( 64 ) \s-1CHARACTER SET\s0 utf8 \s-1COLLATE\s0 utf8_general_ci, \&\s-1ADD\s0 `gco_total_charge_amount` \s-1VARCHAR\s0( 64 ) \s-1CHARACTER SET\s0 utf8 \s-1COLLATE\s0 utf8_general_ci, \&\s-1ADD\s0 `gco_latest_chargeback_amount` \s-1VARCHAR\s0( 64 ) \s-1CHARACTER SET\s0 utf8 \s-1COLLATE\s0 utf8_general_ci, \&\s-1ADD\s0 `gco_total_chargeback_amount` \s-1VARCHAR\s0( 64 ) \s-1CHARACTER SET\s0 utf8 \s-1COLLATE\s0 utf8_general_ci , \&\s-1ADD\s0 `gco_total_refund_amount` \s-1VARCHAR\s0( 64 ) \s-1CHARACTER SET\s0 utf8 \s-1COLLATE\s0 utf8_general_ci, \&\s-1ADD\s0 `gco_latest_refund_amount` \s-1VARCHAR\s0( 64 ) \s-1CHARACTER SET\s0 utf8 \s-1COLLATE\s0 utf8_general_ci, \&\s-1ADD\s0 `lead_source` \s-1VARCHAR\s0(255) \s-1CHARACTER SET\s0 utf8 \s-1COLLATE\s0 utf8_general_ci, \&\s-1ADD\s0 `referring_url` \s-1VARCHAR\s0(255) \s-1CHARACTER SET\s0 utf8 \s-1COLLATE\s0 utf8_general_ci, \&\s-1ADD\s0 `locale` \s-1\fIVARCHAR\s0\fR\|(6) \s-1CHARACTER SET\s0 utf8 \s-1COLLATE\s0 utf8_general_ci, \&\s-1ADD\s0 `currency_locale` \s-1\fIVARCHAR\s0\fR\|(6) \s-1CHARACTER SET\s0 utf8 \s-1COLLATE\s0 utf8_general_ci, \&\s-1ADD\s0 `txtype` \s-1VARCHAR\s0(64) \s-1CHARACTER SET\s0 utf8 \s-1COLLATE\s0 utf8_general_ci, \&\s-1ADD\s0 `cart` \s-1BLOB\s0; .PP And run these to allow for temporary order numbers of greater than the default 14 character field type \&\s-1ALTER TABLE\s0 `transactions` \s-1MODIFY\s0 `order_number` varchar(32); \&\s-1ALTER TABLE\s0 `orderline` \s-1MODIFY\s0 `order_number` varchar(32); .PP In etc/log_transction, immediately after the [elsif variable \s-1MV_PAYMENT_MODE\s0] [calc] insert this line: undef \f(CW$Session\fR\->{payment_result}{MStatus}; .PP and leave [elsif variable \s-1MV_PAYMENT_MODE\s0] as set (contrary to earlier revisions of this document), but within the same section change the following two instances of [var \s-1MV_PAYMENT_MODE\s0] to [value mv_payment_route] .PP Also add these five lines to the end of the section that starts \*(L"[import table=transactions \*(R": lead_source: [data session source] referring_url: [data session referer] locale: [scratch mv_locale] currency_locale: [scratch mv_currency] cart: [calc]uneval($Items)[/calc] for use when sending the merchant report and customer receipt emails out. .PP Still in etc/log_transaction, find the section that starts \*(L"Set order number in values: \*(R" and insert this just before it: [if value mv_order_profile =~ /googlecheckout/] [value name=mv_order_number set=\*(L"[scratch purchaseID]\*(R" scratch=1] [else] and a closing [/else][/if] at the end of that section, just before the \&\*(L"Set order number in session:\*(R" line. The order number is generated by the module and passed to Google at an early stage, and then passed back to Interchange at a later stage. This prevents Interchange generating another order number. If your Interchange installation is 5.2.0 or older this line will not exist \- set oldic to '1' in the payment route and allow Interchange to generate the order number instead. Note: the initial order number uses the username.counter number prefixed with 'GCOtmp', and a normal order number is created and the initial order number replaced only when Google reports that the card has been charged. This is to avoid gaps in the order number sequence caused by customers abandoning the transaction while at Google. .IP "Failed atttempts to authorise or charge the buyer's card. If the card is declined by the bank then \s-1IC\s0 will be updated with the new status and a brief email sent to the buyer telling him of the fact, and asking him to try another payment method." 4 .IX Item "Failed atttempts to authorise or charge the buyer's card. If the card is declined by the bank then IC will be updated with the new status and a brief email sent to the buyer telling him of the fact, and asking him to try another payment method." .PD 0 .IP "\s-1AVS\s0 and \s-1CV2\s0 risk assessment: avs_match_accepted partial|full|none" 4 .IX Item "AVS and CV2 risk assessment: avs_match_accepted partial|full|none" .PD \&\s-1AVS\s0 options and returned values are these: Y \- Full \s-1AVS\s0 match (address and postal code) P \- Partial \s-1AVS\s0 match (postal code only) A \- Partial \s-1AVS\s0 match (address only) N \- no \s-1AVS\s0 match U \- \s-1AVS\s0 not supported by issuer If the route is set to 'full' then, unless \s-1AVS\s0 is not supported (eg in cards foreign to the country doing the processing), a full match is required. Set to 'partial' (the default) for partial match, or \&'none' for no match required. .Sp \&\s-1CV2\s0 values: cv2_match_accepted yes|none M \- \s-1CVN\s0 match N \- No \s-1CVN\s0 match U \- \s-1CVN\s0 not available E \- \s-1CVN\s0 error If the route is set to 'yes' then the \s-1CV2\s0 must match unless it is not available. If set to 'none' then a match is not required. Default is 'yes'. .Sp Both of these must be positive according to your rules for the transaction to be charged \- if not positive then the transaction will be refused and a brief email sent to the prospective buyer to say so. .IP "Google Analytics" 4 .IX Item "Google Analytics" This page: http://code.google.com/apis/checkout/developer/checkout_analytics_integration.html will tell you how to integrate Analytics into the system. This module will pass the data as an 'analyticsdata' value from the checkout form, encoded as \s-1UTF\-8. \s0 .IP "Error messages from \s-1GCO\s0" 4 .IX Item "Error messages from GCO" \&\s-1GCO\s0 will send error messages with a '<' in the title, which Interchange interprets as a possible attack and so immediately stops reading the page and throws the user to the 'violation' page (defined in your catalog.cfg as 'SpecialPage ../special_pages/violation' normally, though may be different). Insert the following at the top of that page, which will test for the string sent by Google and then bounce the user back to the checkout page with a suitable error message. This uses the 'env' UserTag. .Sp [tmp uri][env \s-1REQUEST_URI\s0][/tmp] [if type=explicit compare=`$Scratch\->{uri} =~ /%20400%20Bad%20Request%3C\e?xml/`] [perl] \f(CW$msg\fR = errmsg(\*(L"GoogleCheckout has encountered an error \- if all of your address and shipping entries are correct, please consider using our 'Credit Card Checkout' instead. Our apologies for any inconvenience.\*(R"); \f(CW$::Session\fR\->{errors}{GoogleCheckout} = \f(CW$msg\fR; [/perl] [bounce href=\*(L"[area ord/checkout]\*(R"] [/if] .SH "Bugs" .IX Header "Bugs" The default CharSet.pm in Interchange 5.6 (and possibly earlier) will fail on \s-1GCO\s0's notifications. The sympton is that \s-1GCO\s0 keeps repeating the 'new order notification' as though it has not received one, but does not return any errors. Set a variable in your catalog.cfg, thus: Variable \s-1MV_HTTP_CHARSET UTF\-8\s0 but be aware that this may break the display of some upper \s-1ASCII\s0 characters, eg the \s-1GBP\s0 £ sign (use £ instead of £) .SH "Changelog" .IX Header "Changelog" v.0.7.0, 29.01.2009 \- added locale, currency_locale, and cart fields to transaction tbl \- log basket to transaction tbl to be read and inserted back into session for final order route \- altered main 'googlecheckout' order route and added new 'gco_final' order route. Replaced previous method of sending emails with this final route. \- added failsafe logging prior to going to Google, in orders/gco/, file name is 'date.session_id' .PP v 0.7.1, May 2009. \- changed order number creation to only come after Google reports the card as charged. Initially uses the tid (from tid.counter) as a temporary order number. .PP v0.7.2, May 2009, \- updated documentation, simplifed system for co-operating with other payment systems. .PP v0.7.3, June 2009 \- added code to update userdb, decrement inventory table and add more meaningful order subject (thanks to Andy Smith of tvcables.co.uk) \- also fixed an error whereby \s-1KDE\s0's Kate had fooled me with incorrect bracket matching. .SH "POD ERRORS" .IX Header "POD ERRORS" Hey! \fBThe above document had some coding errors, which are explained below:\fR .IP "Around line 342:" 4 .IX Item "Around line 342:" Non-ASCII character seen before =encoding in '£'. Assuming \s-1UTF\-8\s0