====== Customers: Notes and Features ====== Without the customer, e-commerce wouldn't be very exciting (or profitable), so a thorough understanding mof the customer as treated by FoxyCart is important for any merchant or developer using FoxyCart. ===== How Customers Are Defined and Created ===== There are two ways to create a customer record in FoxyCart. The first and most common is to allow the customer record to be created automatically upon a successful transaction. The second method is to create the customer record directly via [[.:api|the API]]. Regardless the method of creation, the single most important piece of a customer record is the email address used. The email address can be considered the unique key for the customer; there cannot be two different (non-guest) customer records with the same email address in a single store. ===== Guest Customers and Saved Customers ===== Depending on the store configuration, FoxyCart can allow customers to checkout as guests or to checkout with an account. Guest customers: * Do not enter a password. * Can enter an email address already used by other guest or saved customer records. * Cannot purchase a subscription. (Guest mode as an option is hidden if a subscription is in the cart.) * Cannot be retrieved, created or edited via the API. * Cannot retrieve their information if they purchase again in the future and enter their previously used email. (Because they have no password, there'd be no way for the customer to authenticate anyway.) * Cannot be converted into a non-guest customer. To set up your checkout to use guest customers only, follow the instructions [[:v:2.0:customers:customers_step_by_step:guest_only_checkout|here]]. Non-guest customers: * Must have an email address unique among non-guest customers. * Can be created and edited via the API. * Can enter their previously used password when returning to a checkout page, or can checkout as a guest (if guest checkout is allowed by the store) to have their saved information automatically populated on the checkout. * Cannot be converted into a guest customer. **Saved Password Reset** If a user has a previously saved username but forgets their password, the FoxyCart checkout allows for a password reset. The password flow is like this: * User clicks "Email me a temporary password" * An email is immediately sent to the user with a temporary password * Once they enter the temp password, they are prompted to create a new password for their account * if they enter a new password, the password is not saved until the checkout is successfully completed The password reset email is only good for 30 minutes, after which time a new email must be requested. ===== Saved Payment Information ===== Customers can have one and //only one// saved payment method associated with their account. If a customer has a subscription associated with his or her account, the checkbox to elect to save the payment method on checkout is required to be checked, and an error explaining this is displayed if it is unchecked. What is important to note is that if a customer has an active subscription being paid for by credit card xxxx1234 and makes another purchase in the future using card xxx5678, that new card becomes the only saved payment method for the customer, and all active subscriptions will use that new card when they run. (While this may sound problematic, in 3+ years we haven't heard of it being an issue. That said, if you have a situation where multiple separate payment methods are required please [[http://forum.foxycart.com/|let us know]].) ===== Synchronizing Users and Passwords ===== Because FoxyCart was built from the ground up to augment and not replace external systems, it is a common occurrence that FoxyCart customer records will need to be created or updated from an external system, or that FoxyCart customers will need to automatically create users in external systems (like a CMS or CRM). Typically an integration like this will primarily use [[.:transaction_xml_datafeed|the Transaction XML Datafeed]] and [[.:api|the API]] to create and sync users, and [[.:sso|Single Sign-On (SSO)]] to make the customer checkout experience seamless. While the possibilities for this type of synchronization are near limitless, the single most important thing is usually the customer's password. FoxyCart customer passwords are returned by the XML datafeed and the API as [[wp>Hash_function|hashes]], and not the actual cleartext password. While the initial user creation is generally straightforward it can get tricky to maintain sync when passwords are reset, so if you tackle an advanced integration you must ensure that any and all password resetting functionality on your systems simultaneously updates the FoxyCart customer record through [[.:api|the API]]. Password hashes are represented in the API and Datafeed XML as hexadecimal strings, for example "''2e29f4fa2efb67dc28860abf''". Depending on your library's hash functions, you may need to convert the output of the hash function to a hexadecimal string in order to compare passwords. Any "salt" value generated by FoxyCart is a random string of letters and numbers. FoxyCart currently supports the following hashing methods (in alphabetical order, and in PHP pseudocode, using ''$'' to denote a variable, ''.'' to denote concatenation, and a single quote to encapsulate a string): ; ''Argon2id'': : **Method:** ''argon2id'' : **Notes:** It will use the default configuration options when generating the hash ; ''BCrypt (with cost)'': : **Method:** ''bcrypt'' : **Configuration:** The cost, default 14 : **Notes:** This is the recommended hashing method. It will generate the standard ''$2y$'' crypt format, which is always 60 characters wide. : **Supported Systems:** * [[https://drupal.org/|Drupal]] 10.1.0+ (use a cost of 10) ; ''concrete5'' : **Method:** ''md5($password.':'.$salt)'' : **Configuration:** The configuration value is the one single salt used for all customer records, since Concrete5 uses a single site-wide salt. ; ''Craft CMS'': : **Method:** Specific to Craft. ; ''ExpressionEngine'': : **Method:** Specific to ExpressionEngine. ; ''joomla'' : **Method:** ''md5($password.$salt).':'.$salt'' : **Configuration:** The length of the randomly generated salt. : **Notes:** This is the method used as of Joomla 1.0.13. ; ''kohana3'' : **Method:** The hashing methods in the [[https://github.com/kohana/auth/blob/3.0/master/classes/kohana/auth.php|Kohana3 Auth module]]. : **Configuration:** The Auth module's ''$config['salt_pattern']'' value. FoxyCart defaults to the default value in the Auth module. ; ''Magento MD5'': : **Method:** For older Magento installations. ; ''md5'' : **Method:** ''md5($password)'' : **Configuration:** n/a : **Notes:** This is provided for legacy purposes, as many older systems may use unsalted MD5 hashes. It is not recommended unless you need to sync with a system that requires it. ; ''md5_salted_suffix'' : **Method:** ''md5($password.$salt)'' : **Configuration:** The length of the randomly generated salt. ; ''md5_salted_suffix_2char'' : **Method:** ''md5($password.$salt)'' : **Configuration:** n/a : **Notes:** This really should only be used for synching to osCommerce prior to v2.3. ; ''pbkdf2'' : **Method:** Microsoft Identity v2 PBKDF2 implementation : **Configuration:** Comma separated values for ''iterations'', ''key length'', ''algorithm'', ''salt size''. Defaults to ''1000, 32, sha1, 16''. : **Notes:** Returns a base64 encoded string, made up of a concatenated string using ''"\0" . $salt . $hash''. No separate salt is returned, and the hash should be base64 decoded before encoding the concatenated string. ; ''pbkdf2'' : **Method:** From [[https://github.com/modxcms/revolution/blob/develop/core/model/modx/hashing/modpbkdf2.class.php|MODX Revolution's code]]. Note that MODX no longer uses this method. : **Configuration:** Comma separated values for ''iterations'', ''key length'', ''algorithm''. Defaults to ''1000, 32, sha256''. : **Notes:** Returns a base64 encoded hash, and uses a 32 character long salt : **Supported Systems:** * [[http://modx.com/|MODX Revolution 2.x]] (old default configuration; no longer default) ; ''phpass'' : **Method:** Uses the [[http://www.openwall.com/phpass/|phpass library]] in "portable" mode. (Portable mode is what most systems that use phpass default to.) : **Configuration:** The configuration value sets the iterations used to instantiate the ''PasswordHash'' class. Defaults to 8, which is what Wordpress and most other systems default to. : **Supported Systems:** * [[http://wordpress.org/|Wordpress]] * osCommerce 2.3+ ; ''sha1'' : **Method:** ''sha1($password)'' : **Configuration:** n/a : **Notes:** This is provided for legacy purposes, as many older systems may use unsalted MD5 hashes. It is not recommended unless you need to sync with a system that requires it. ; ''sha1_salted_suffix'' : **Method:** ''sha1($password.$salt)'' : **Configuration:** The length of the randomly generated salt. : **Supported Systems:** * [[http://silverstripe.org/|Silverstripe]] (default configuration) ; ''sha256_salted_suffix'': : **Method:** ''sha256($password.$salt)'' : **Configuration:** The length of the randomly generated salt. ; ''sha256_salted_prefix'': : **Method:** ''sha256($salt.$password)'' : **Configuration:** The length of the randomly generated salt. ; ''drupal sha512'': : **Method:** ''sha512($salt.$password)^$iterations'' : **Configuration:** The iterations the password is stretched by. : **Supported Systems:** * [[https://drupal.org/|Drupal]] 7+ : **Notes:** Beginning in v10.1.0, Drupal uses PHP's standard ''password_hash()'' function, which uses bcrypt, which we support and is detailed below. ; ''Webvanta SHA1'': : **Method:** Specific to Webvanta. If you need alternate hashing methods please [[http://foxy.io/contact|let us know]]. Once the user creation and synchronization functionality is handled, [[.:sso|Single Sign-On (SSO)]] allows a customer who's already logged into the merchant's site to continue through to checkout with their user already loaded. This prevents users from needing to log in once to a site, then again on checkout. (SSO checkouts require the [[wp>Card_Security_Code|CSC]] to be entered, in order to minimize the risk of a malicious user stealing a cookie and processing an order using saved payment information.) ==== Changing hashing methods ==== The customers hashing method is stored against their user record (which you can in turn access via the [[.:transaction_xml_datafeed|XML datafeed]] and the [[.:api|API]] as well), and that is the hashing method used to validate their password when they login. If you've changed the hashing method from one to another, any existing customers will be validated against their old hashing method on login, and then once they complete a checkout for your store their password will be rehashed with the new hashing method selected in your stores settings. ===== Viewing Customer Transactions ===== While a store admin can easily view and filter transactions by a number of criteria (including by customer email) both in the store admin as well as via the API, FoxyCart does not currently provide a method for a customer to view their own order history. We have discussed adding a customer portal in a future version, so if this appeals to you please [[http://requests.foxycart.com/forums/4162-general-requests/suggestions/1104571-customer-portal-to-view-transactions-subscription|let us know]]. We do have a high-level explanation of how you could accomplish this in the meantime, however, and many of our users have taken an approach like this: [[./customer_portal|Building a Customer Portal in FoxyCart]]