nopERcart  free  shopping-cart

Do you want to put up a simple store-front, but lack CGI access or expertise?  Then this free JavaScript shopping-cart is exactly what you need.  This software only needs JavaScript, which every browser supports these days.  You won't have to become a database-administrator!  Your products can be on many separate pages.  This complete, simple, easy-to-use shopping-cart makes it easy to implement any e-commerce site.  All that's required is pasting-in the supplied source-code on each page that customers can purchase products from, and revising the supplied shoppingcart.htm file to identify the payment-processor you've chosen.  NopERcart by Eugene Reimer is an enhanced variant of nopcart v4.4.

Who uses this shopping-cart?  Some of the sites using it are:


Features at a glance:


An Example, or two:

Many of us learn by example, so I recommend looking at one or more of the following selling pages, along with the View-Cart page they take you to.

The first example is for a Canadian retailer who ships via Canada-Post:
  • Sample selling page, and
  • Javascript source, with Canada-Post shipping-table, and a packing-rules example

  • A second example is for a US retailer shipping via UPS & USPS, payment-processing by Google-Checkout or PayPal;  it illustrates an alternate user-interface using add-to-cart popups and non-automatic switching to view-cart;  and it illustrates the use of thumbnail-images on the view-cart page:
  • UPS+USPS-Demo selling page
  • Javascript source, with UPS+USPS shipping-table

  • A third example is for a Dutch retailer shipping via TNT-Post, with payment-processing by PayPal in Euros: 
  • TNT-Post-Demo selling page (in Dutch)
  • Javascript source, with TNT-Post shipping-table, and another packing-rules example

  • A fourth example is for a British retailer shipping via Royal-Mail, with payment-processing by PayPal in Pounds-Sterling: 
  • Royal-Mail-Demo selling page
  • Javascript source, with a Royal-Mail shipping-table that offers a 6-way choice

  • A fifth example demonstrates the use of Coupon Discounts, adding multiple items with one Add-to-Cart, and payment-processing by Authorize.net: 
  • Coupon-Demo selling page
  • CGI script to connect to Authorize.net payment-processor

  • A sixth example demonstrates two-step checkout using a CGI-interface to a payment-processor such as OptimalPayments: 
  • Two-Step-Demo selling page
  • CGI script to send emails and connect to payment-processor

  • A seventh example demonstrates a non-trivial set of Sales-Tax Regions, Rates, Exemptions, and payment-processing by InternetSecure: 
  • New-York-State Demo selling page


  • How To Use this Shopping-cart:

    Here are the few easy steps to installing & running this shopping-cart:
    1. Download the cart here:

    2. Unzip.  If you don't have an unzipper, head over to www.winzip.com to get one. 

    3. Configure the options, if you wish.  To configure the options, open file nopercart.js in your favorite text-editor.  If you don't have one, use notepad on Windows; Linux users won't need a recommendation. 

      Some of the options that are configurable:

      • DisplayPopupOnAdd: Controls whether the user is provided with a popup when adding to the cart. 
      • DisplayTaxIncluded: Controls whether the viewcart and checkout pages display prices with Tax included, in which case the tax-subtotal line(s) will be shown after the Total line, with the phrase "included in total".
      • TaxNames: Use this to give names to your taxes, if you have several kinds and want them shown separately. 
      • TaxRates: The various tax-rates you need to charge; for example, if you have a 7.5% tax and a 5% tax, you set TaxRates = [0.075, 0.05]; set it to [] (empty array) if you have no taxes. 
      • TaxesByRegion: This option specifies which taxes apply in each region; for example if you have two taxes, both apply in Region#0, only Tax#1 in Region#1, then use TaxesByRegion = [[0,1],[1]]. 
      • RegionTable: This option defines your Regions; for example: ["Manitoba", "Other Canadian Province", "Other Country"]. 
      • MoneySymbol: The symbol which represents dollars/rubles/euros/etc, in your locale. 
      • MoneyPLACES: Controls rounding & display of money-amounts; for example, use 2 for US-dollars rounded to cents and shown as dollars and cents; or -3 if amounts are to be rounded to multiples of 1000 and shown without any fractional part. 
      • WTUNITS: The units for item & package weights, eg: "lb".
      • SZUNITS: The units for item & package sizes, eg: "cm".
      • NOTE: the PaymentProcessor and PaymentProcessor2 options are obsolete, as of 2009-04-01, having been replaced by a PaymentProcessor parameter to the ManageCart, CheckoutCart, and PaymentProcessorFields routines.
      • AllInOne: true/false; when true then the entire cart contents are presented as one item;  for some time one had to use true with PayPal to get around serious flaws in their cart-support, but this is no longer the case. 

      Other Options:  See the Javascript file nopercart.js for a complete list, and description, of all options.  Near the top of the file you'll see comments describing all the options, and after that you'll see assignment statements giving values to them.  Most options are either true/false, a string, or a number;  for true/false options, you enter either true or false, replacing the existing value;  for string options, enter any text you wish between the quote-marks -- this can include HTML tags;  for numeric options, simply enter the number you wish.  However, the ShipTable and PackTable options are arrays of structures that are made up of strings and numbers; the examples in nopercart.js will show you how to specify these options. 

      When editing the options, be aware that punctuation matters;  however, everything after a "//" is a comment, where anything goes.


    4. On each page you wish to sell products from, include the lines:
      <script src=nopercart.js></script> <!-- nopERcart Shopping-Cart, from http://ereimer.net/nopercart.htm -->
      <script src=noper-language-XX.js></script>
      Don't worry -- none of that text will be visible to users on your site.  The only way anyone will you see it is by doing a 'view source' on a page.  The first line is essential; it instructs the browser to load the file containing the Javascript shopping-cart routines. 

      The 2nd line is optional, only needed to make nopERcart use a language other than English.  The language-pack choices are:

      noper-language-cs_CZ.utf8.js Czech (by Jan Egert)
      noper-language-da_DK.utf8.js Danish (by Glenn Jensen)
      noper-language-de.utf8.js German (by bjarnat_r@hotmail.com)
      noper-language-de_alt.utf8.js German (alternate by Mike)
      noper-language-el_GR.utf8.js Greek-Modern (by bill@vpournaras.gr) -- new in nopERcart 2007-08-05
      noper-language-eo.ascii.js Esperanto (by Ernie Knolfson of zengarten.com) -- new in nopERcart 2007-08-05
      noper-language-es.utf8.js Spanish (by Capitán Nemo Comunicaciones)
      noper-language-et.utf8.js Estonian (by pilv) -- new in nopERcart 2007-08-05
      noper-language-fi.utf8.js Finnish (by Mikko Lähteenmäki aka ifreq)
      noper-language-fr.utf8.js French (by Fred of noe.master.online.fr and Jean-Pierre David of pages.videotron.com/jpdsig)
      noper-language-he_IL.utf8.js Hebrew (by Mr. Eliezer Tavor / MOR / Web-Master)
      noper-language-hu.utf8.js Hungarian (by Robert Horvath)
      noper-language-it.utf8.js Italian (by Colomela Francesco)
      noper-language-ms_MY.ascii.js Malay (by bennyong of hostonfire.com)
      noper-language-nl.utf8.js Dutch (by Ron A.J. Hartendorp of Computer Network Services, pra@xidis.com, and Corina van Weert of catchy-eyes.nl)
      noper-language-no.utf8.js Norwegian (by Thomas A. Amundsen of graphic.no)
      noper-language-pdt.utf8.js Plautdietsch (by me, Eugene Reimer) -- new in nopERcart 2007-08-05
      noper-language-pl.utf8.js Polish (by Archmag)
      noper-language-pt_BR.utf8.js Portuguese-Brazil (by Jane Araújo)
      noper-language-pt_PT.utf8.js Portuguese-Portugal (by Phosphoros) -- new in nopERcart 2007-08-05
      noper-language-ro.ascii.js Romanian (by Florin B)
      noper-language-ru.utf8.js Russian (by Vladimir of lukianov.ru) -- new in nopERcart 2007-08-05
      noper-language-sk.utf8.js Slovak (by Jaro Nemcok)
      noper-language-sl_SI.utf8.js Slovenian (by Berto art-reef.com) -- new in nopERcart 2007-08-05
      noper-language-sv_SE.utf8.js Swedish (by Artur Stensson)
      noper-language-sv_SE_alt.utf8.js Swedish (improved alternate by Béatrice: bea@ludd.luth.se or www.ludd.luth.se/~bea)
      noper-language-tr.utf8.js Turkish (by Yetkin Degirmenci of yetkindegirmenci.com) -- new in nopERcart 2007-08-05
      noper-language-zh_CN.utf8.js Chinese-Simplified (by AHU of 52q.net) -- new in nopERcart 2010-01-28
      noper-language-zh_TW.utf8.js Chinese-Traditional (by C.J. Ho of SunnyFactory)


    5. For each product you wish to sell, create a small FORM tag that looks something like:
      <FORM action="shoppingcart.htm" onSubmit="return AddToCart(this)">
      <input type=hidden  _ID="SP001" _NAME="My Sample Product" _PRICE="19.95" _WEIGHT="30" _LENGTH="25" _WIDTH="16" _HEIGHT="10">
      Quantity: 
      <input type=text  name="_QUANTITY" value="1" size=2 maxlength=3 onChange="this.value=CKquantity(this.value)">    
      <input type=SUBMIT  value="Add to Cart">
      </FORM>
      
      Of course you will replace the right-side of _ID, _NAME, _PRICE, _WEIGHT, _LENGTH, _WIDTH, _HEIGHT with information for your product.  If shipping-size doesn't affect your shipping-costs, simply omit the _LENGTH, _WIDTH, _HEIGHT attributes.  On the other hand, if size alone determines your shipping-costs then omit the _WEIGHT attribute. 

      For Quantity-Discount pricing, the _PRICE can be a comma-separated list of terms, such as:

      3.95 -- means 3.95 each;
      3.95,2:3.00 -- means 3.95 for the first, 2nd and subsequent are 3.00 each;
      3.95,10=2.99 -- means 3.95 each, or exactly 10 for 29.90;
      3.95,10=2.99,10:2.99 -- means 3.95 each, 10 or more are 2.99 each;
      3.95,2:3.00,4:2.75,8:2.50  -- means 2nd...are 3.00, 4th...are 2.75, 8th and subsequent are 2.50;
      3.95,2:-30,GRP01 -- means 2nd and subsequent are 30% off, and this applies across all products in the group GRP01;
      One _PRICE can contain any number of ":" or "=" terms, at most one starting with a letter to name a group;  the ":" and "=" terms may be interspersed, or not, but the ":" terms must appear in increasing order by left-side, and "=" terms likewise.  Exact-quantity ("=") discount-prices are only permitted within a group where all products have identical prices (anything else would be just too bloody hard to explain);  no such restriction applies to the N-or-more (":") discount-prices.

      For Promotional Discounts (eg: Coupons), the _PRICE can be something like:

      >=40:-15.00   -- means if the pre-tax pre-shipping subtotal is at least 40.00 this 15.00 discount applies;
      >=0:-10.00 -- means this 10.00 discount applies without any qualification;
      >=0:-25% -- means this 25% discount applies without any qualification;

      If you have USERCHOICE's for your customers (eg: for Colour, Style, etc), then your form will look something like:

      <FORM action="shoppingcart.htm" onSubmit="return AddToCart(this)">
      <input type=hidden  _ID="SP001" _NAME="My Sample Product" _PRICE="19.95" _WEIGHT="30" _LENGTH="25" _WIDTH="16" _HEIGHT="10">
      Size: 
      <select name=USERCHOICE>
          <option _ID="+S" _NAME="+ Small">  Small
          <option _ID="+M" _NAME="+ Medium"> Medium
          <option _ID="+L" _NAME="+ Large">  Large
      </select>
      Colour: 
      <select name=USERCHOICE2>
          <option _ID="+R" _NAME="+ Red">   Red
          <option _ID="+W" _NAME="+ White"> White
          <option _ID="+B" _NAME="+ Blue">  Blue
      </select>
      Quantity: 
      <input type=text  name="_QUANTITY" value="1" size=2 maxlength=3 onChange="this.value=CKquantity(this.value)">    
      <input type=SUBMIT  value="Add to Cart">
      </FORM>
      

      Other sorts of USERCHOICE selectors are illustrated in the supplied shopping.htm example.  A product can have up to ten such USERCHOICEn choices, for n being emptystring or 1..9;  each can be either a select-statement or a set of radio-buttons;  each can supply values for any of _ID, _NAME, _PRICE, _WEIGHT, _LENGTH, _WIDTH, _HEIGHT;  and each value is either a replacement or a to-be-added value, the latter case indicated by a leading plus-sign;  for _ID or _NAME adding is string-catenation, for the others it is arithmetic-addition. 

      The above code snippets will take your customer directly to the View-Cart page upon clicking Add-to-Cart.  If you wish to avoid that:  remove the ACTION part of the FORM tag;  consider enabling the DisplayPopupOnAdd option;  consider adding the following to the above snippet so that customers see a summary of their cart-contents, and can get to your View-Cart page when they wish to:
      <p>Your cart contains <script>Print_cart_summary(" item"," items"," at a cost of ");</script> &nbsp; <a href=shoppingcart.htm>View Cart</a>

      Tip from Art Held: when removing the ACTION part of the FORM tag in order to stay on the same page, you may want to modify your onSubmit code to return false, thereby avoiding the "movement" to top of page;  that will however interfere with the use of Print_cart_summary, which needs the page to be reloaded.


    6. Setup a View-Cart page (named shoppingcart.htm in these examples). 

      First it contains:
      <FORM>
      <SCRIPT> ManageCart(""); </SCRIPT>
      </FORM>

      Then ONE of the following, depending on the PaymentProcessor you've chosen.  (Or more than one for multiple payment methods.)

      PayPal (PaymentProcessor "pp"):
      <FORM action="https://www.paypal.com/cgi-bin/webscr" method=POST onSubmit="return ValidateCart(this)">
      <SCRIPT> PaymentProcessorFields("pp"); </SCRIPT>
      <input type=hidden name="currency_code" value="USD">
      <input type=hidden name="return" value="http://YOUR-DOMAIN-NAME/shoppingthanks.htm">
      <input type=hidden name="business" value="YOUR-EMAIL">
      <input type=SUBMIT value="Check-Out">
      </FORM>

      You will replace USD with the currency-code for your currency; eg: CAD.  You will replace "http://YOUR-DOMAIN-NAME/shoppingthanks.htm" with the URL of your own Thanks-for-your-Purchase page.  You will replace YOUR-EMAIL with the email-address that identifies your Merchant-Account at PayPal. 

      Google-Checkout (PaymentProcessor "gc"):
      <FORM action="https://checkout.google.com/api/checkout/v2/checkout/Merchant/YOUR-MERCHANT-ID" method=POST onSubmit="return ValidateCart(this)">
      <SCRIPT> gcCurrency="USD"; PaymentProcessorFields("gc"); </SCRIPT>
      <input type=IMAGE src="http://checkout.google.com/buttons/checkout.gif?merchant_id=YOUR-MERCHANT-ID&w=180&h=46&style=white&variant=text&loc=en_US">
      </FORM>

      You will replace USD with the currency-code for your currency; eg: GBP.  You will replace BOTH occurrences of YOUR-MERCHANT-ID with your Merchant-ID at Google. 

      AlertPay (PaymentProcessor "ap"):
      <FORM action="https://www.alertpay.com/PayProcess.aspx" method=POST onSubmit="return ValidateCart(this)">
      <SCRIPT> PaymentProcessorFields("ap"); </SCRIPT>
      <input type=hidden name="ap_currency" value="USD">
      <input type=hidden name="ap_merchant" value="YOUR-EMAIL">
      <input type=SUBMIT value="Check-Out">
      </FORM>

      You will replace USD with the currency-code for your currency; eg: CAD.  You will replace YOUR-EMAIL with the email-address that identifies your Merchant-Account at AlertPay. 
      2009-03-06: AlertPay is not accepting credit-cards.  2009-04-01: the AlertPay website is dead!  2009-05-19: AlertPay has come back to life, and is accepting credit-cards.
      2010-03-23: AlertPay has made INCOMPATIBLE changes to its interface; I'm dropping support for AlertPay; if you want to use them you're on your own.

      VirtualTerminalNetwork (PaymentProcessor "vt"):
      <FORM action="https://www.virtualterminalnetwork.com/Merchant/ConfirmPayment.asp" method=POST onSubmit="return ValidateCart(this)">
      <SCRIPT> PaymentProcessorFields("vt"); </SCRIPT>
      <input type=hidden name="merchant_email_id" value="YOUR-EMAIL">
      <input type=SUBMIT value="Check-Out">
      </FORM>

      You will replace YOUR-EMAIL with the email-address that identifies your Merchant-Account at VirtualTerminalNetwork. 

      InternetSecure (PaymentProcessor "is"):
      <FORM action="https://secure.internetsecure.com/process.cgi" method=POST onSubmit="return ValidateCart(this)">
      <SCRIPT> PaymentProcessorFields("is"); </SCRIPT>
      <input type=hidden name="GatewayID" value="YOUR-MERCHANT-ID">
      <input type=hidden name="language" value="English">
      <input type=hidden name="ReturnURL" value="http://YOUR-DOMAIN-NAME/shoppingthanks.htm">
      <input type=SUBMIT value="Check-Out">
      </FORM>

      You will replace YOUR-MERCHANT-ID with the identifier for your Merchant-Account at InternetSecure. 

      LinkPoint (PaymentProcessor "lp"):
      <FORM action="https://secure.linkpt.net/lpcentral/servlet/lppay" method=POST onSubmit="return ValidateCart(this)">
      <SCRIPT> PaymentProcessorFields("lp"); </SCRIPT>
      <input type=hidden name="storename" value="YOUR-STORE-ID">
      <input type=SUBMIT value="Check-Out">
      </FORM>

      WorldPay (PaymentProcessor "wp"):
      <FORM action="https://select.worldpay.com/wcc/purchase" method=POST onSubmit="return ValidateCart(this)">
      <SCRIPT> PaymentProcessorFields("wp"); </SCRIPT>
      <input type=hidden name="instId" value="YOUR-WORLDPAY-ID">
      <input type=hidden name="currency" value="USD">
      <input type=hidden name="testMode" value="0">
      <input type=hidden name="cartId" value="WebPurchase">
      <input type=SUBMIT value="Check-Out">
      </FORM>

      Authorize.net (PaymentProcessor "an"):
      <FORM action="/cgi-bin/shoppingcheckout-an.pl" method=POST onSubmit="return ValidateCart(this)">
      <SCRIPT> PaymentProcessorFields("an"); </SCRIPT>
      <input type=SUBMIT value="Check-Out">
      </FORM>

      You will modify the supplied shoppingcheckout-an.pl replacing the loginID and transactionKey values with those for your account at Authorize.net. 

      CGI Checkout (PaymentProcessor "cgi"):
      to use a CGI-script called /cgi-bin/shoppingcheckout-op.pl that accepts POST mode:
      <FORM action="/cgi-bin/shoppingcheckout-op.pl" method=POST onSubmit="return ValidateCart(this)">
      <SCRIPT> PaymentProcessorFields("cgi"); </SCRIPT>
      </FORM>

      HTML Checkout, when using the two-step approach:
      <FORM action="shoppingcheckout.htm" onSubmit="return ValidateCart(this)">
      </FORM>


    7. Most of you are now done!  ONLY if you've chosen TWO-step checkout, do you need a checkout page.  Your checkout page, will be almost identical to ONE of the variants from the preceding step.  The only essential difference: it calls CheckoutCart(PaymentProcessor) instead of ManageCart(PaymentProcessor).  Also it needn't call ValidateCart(this), since CheckoutCart has no provision for making changes.  The supplied example (shoppingcheckout.htm) also has a form for the customer to enter name & address, and is accompanied by a Perl-script (shoppingcheckout-op.pl) to send emails and invoke a payment-processor. 


    8. (Optional) Include a "Javascript Needed" warning in your pages, to alert any user who has disabled Javascript to enable it in order to shop at your store;  note that a NOSCRIPT element should immediately follow a SCRIPT tag (my old examples before 2011-June were incorrect in this regard, although they worked as intended with Opera and Firefox, IE unknown).  And a "Cookies Needed" warning to alert a user who has disabled cookies.  Here are snippets you can add to all your shopping pages, to issue those warnings when they're needed:
      <NOSCRIPT>Our shopping-cart needs JavaScript.  Please enable JavaScript in your browser's preferences.</NOSCRIPT>
      <script>if(typeof navigator.cookieEnabled=="boolean" && !navigator.cookieEnabled)alert("You need to enable Cookies in your browser, before our shopping-cart will work for you.");</script>


    Changing the look of the viewcart or checkout page:

    You can redesign the look of this shopping-cart with no modifications to the code at all.  Here are the (CSS) STYLE classes you can redefine in your viewcart and checkout pages, and what they are used for:


    Frequently Asked Questions:

    Q: How do I configure nopERcart to not charge any taxes?
    A: Specify the options: TaxNames=[]; TaxRates=[]; TaxesByRegion=[]; RegionTable=[]; RegionFromZone=[]; DisplayTaxRow=false;

    Q: How do I charge shipping as a fraction of price?
    A: Give each product a weight equal to its price; the rest of the solution will be obvious.

    Q: Why did you drop AlertPay, and how much work would it be to support their new interface?
    A: For one thing AlertPay has been borderline useless as a payment-processor what with being completely dead at times, and being semi-alive but not accepting any credit-cards at other times.  But when they made, without notice, an incompatible change to their interface such that previously working websites abruptly became broken, that's when I said "I'm not willing to play that game".  Before they added "multiple-items", the single ap_description field was allowed to be more than 2,000 characters which was ample for "All-In-One" use; then they added support for multiple items, and simultaneously reduced the maximum length on the ap_description field to 150-characters.  Thereby forcing any website using AlertPay to instantly make these changes, by rendering the site completely non-functional without those changes.  That sort of customer-appreciation seems an effective way to drive away any customers they had left, leaving me baffled by their still being in business.  However they are available in many more countries than PayPal or Google-Checkout, and that may be their reason for being. 
    A-2: Supporting their new "multi-item" orders would involve very little work.  Anyone wanting to use AlertPay is invited to make those changes to nopERcart, and I'll be happy to post the result.  Just take a look at the two AddPaymentProcessorFields routines, and you'll see what changes are needed to change the "ap" payment-processor from being handled as all-in-one to the multiple-item style used for the other cart-supporting payment-processors. 

    Q: I'm using Internet-Explorer and have no idea why nothing works?
    A: To enable the display of error messages in Internet Explorer: click Tools, then Internet Options, then Advanced, then in the list under browsing:
      (1) deselect the "Disable script debugging" option,
      (2) enable the "Display a notification about every script error" option.
    Doing (1) is essential; (2) is optional - having it enabled is nicest while debugging, but can become annoying when visiting buggy websites.  If you've done (1) but not (2), then IE will display an error icon on the status line when an error occurs.  You can double-click this icon to display the error message.  It'll be a yellow triangle near bottom-left corner of your window.


    Licensing?

    This code is Free!  That means commercial or non-commercial use.  The only conditions are those of the Lesser GPL -- see http://www.gnu.org/licenses/ for the details. 


    Support?

    To hire someone with experience in using nopERcart, try:  fredmace@bellsouth.net catchy-eyesOlympic Peninsula Web SolutionsFiddleFace DesignInformation Systems UnificationArt Held

    You may be interested in the modifications by Art Held to support Free Shipping and a few other things; see www.hikerscamerabelt.com/Scripts/nopercart.js

    You may find something of interest on the Support Forum for nopcart;  but be aware that nopcart and nopERcart are different, and anything found there would need to be adapted for nopERcart.


    That's all there is to it.

    Have fun, and happy selling! 

    As you may realise Eugene passed away in November, 2011. We'd still like to hear from you if you're using this cart, even if you're not having problems. We would like to mention your site as one using it.
    WebMaster   2012-February-11