This is the documentation for LemonStand V1, which has been discontinued. You can learn more and upgrade your store here.

LemonStand Version 1 Has Been Discontinued

This documentation is for LemonStand Version 1. LemonStand is now offered as a cloud-based eCommerce platform.
You can try the new LemonStand and learn about upgrading here.

Implementing Customer Payment Profiles

Customer payment profiles is a LemonStand feature which enables customers to store and reuse their credit card information. Credit card information is safely stored on the payment gateway side. The option of storing customer credit card data is supported by many modern payment gateways. The common name for this option is the tokenization, but different payment gateways have different name for this feature. For example, Braintree Payment Solution offer the Vault service and Authorize.Net has the Customer Information Manager API.

Regardless of the name, the purpose of the tokenization is saving customer credit card with the option of reusing this data for the future payments. This enables LemonStand customers to implement the "Save my credit card" and "Pay with my stored credit card" options. At the time of writing this article, tokenization is supported by the following LemonStand payment modules:

  • Authorize.Net Advanced Integration Method
  • Braintree Transparent Redirect

Please contact us if you want we to add this feature for other payment modules. 

Implementing the Save my Credit Card checkbox

The Save my Credit Card checkbox should be added to the payment form partial of a specific payment method. The name of the payment form partial depends on the payment method and have the following format: payment:payment_method_name. For example, for Authorize.Net AIM payment method the payment form partial name is payment:authorize_net_aim.

Please note that some payment gateways create a test transaction with the amount up to $0.01 in order to validate a credit card. This transaction is automatically voided immediately by the gateway after the validation.

For server-to-server (no redirection) payment methods, like Authorize.NET APM. you can add this checkbox in the following way (please note that the checkbox should have the create_customer_profile name):

<? if ($payment_method->supports_payment_profiles() && $this->customer): ?>
  <input type="checkbox" value="1" name="create_customer_profile" id="create_customer_profile"/>
  <label for="create_customer_profile">Save my credit card</label>
<? endif ?>
{% if payment_method.supports_payment_profiles() and this.customer %}
  <input type="checkbox" value="1" name="create_customer_profile" id="create_customer_profile"/>
  <label for="create_customer_profile">Save my credit card</label>
{% endif %}

For redirection payment methods, like Braintree Transparent Redirect the checkbox implementation depends on a payment gateway. Usually payment form partials of payment modules which support payment profiles contain a commented out code snippet for adding the checkbox. Below is a code for adding the checkbox to the Braintree Transparent Redirect payment form partial (payment:braintree_transpredirect): 

<? if ($payment_method->supports_payment_profiles() && $this->customer): ?>
  <input type="checkbox" name="transaction[options][store_in_vault]" value="true" id="create_customer_profile" />
  <label for="create_customer_profile">Save my credit card</label>
<? endif ?>
{% if payment_method.supports_payment_profiles() and this.customer %}
  <input type="checkbox" name="transaction[options][store_in_vault]" value="true" id="create_customer_profile" />
  <label for="create_customer_profile">Save my credit card</label>
{% endif %}

Creating the Pay With My Saved Card button

This button should be added to the Pay page. It should be visible only if the payment module supports payment profiles, if there is a logged in customer and if a payment profile exists for the current customer.

To add the button, define a new form with the credit card information and the Pay button inside. The form can work on both AJAX and regular POST modes. Regular POST form example: 

<? if ($payment_profile = $payment_method->find_customer_profile($order->customer)): ?>
  <?= open_form() ?>
    Pay using my stored credit card: (<?= 'xxxx'.h($payment_profile->cc_four_digits_num) ?>)
    <input type="submit" value="Submit" name="submit_payment"/>
    <input type="hidden" value="1" name="pay_from_profile"/>
  </form>
<? endif ?>
{% set profile = method.find_customer_profile(this.customer) %}
{% if profile %}
  {{ open_form() }}
    Pay using my stored credit card: ({{ 'xxxx'~payment_profile.cc_four_digits_num }})
    <input type="submit" value="Submit" name="submit_payment"/>
    <input type="hidden" value="1" name="pay_from_profile"/>
  </form>
{% endif %}

AJAX form example: 

<? if ($payment_profile = $payment_method->find_customer_profile($order->customer)): ?>
  <?= open_form() ?>
    Pay using my stored credit card: (<?= 'xxxx'.h($payment_profile->cc_four_digits_num) ?>)
    <input type="submit" value="Submit" name="submit_payment" onclick="return
      $(this).getForm().sendRequest('shop:on_pay')"/>
    <input type="hidden" value="1" name="pay_from_profile"/>
  </form>
<? endif ?>
{% set profile = method.find_customer_profile(this.customer) %}
{% if profile %}
  {{ open_form() }}
    Pay using my stored credit card: ({{ 'xxxx'~payment_profile.cc_four_digits_num }})
    <input type="submit" value="Submit" name="submit_payment" onclick="return
      $(this).getForm().sendRequest('shop:on_pay')"/>
    <input type="hidden" value="1" name="pay_from_profile"/>
  </form>
{% endif %}

Creating the Payment Profiles page

The Payment Profiles page displays a list of payment methods which support payment profiles and allows a customer to create, modify or delete a payment profile associated with a specific payment method. The payment profile page security configuration should not allow guest visitors to see it. The page should only be available for logged in customers, in HTTPS mode.

Please use the shop:payment_profiles action as a base CMS action for the page. The action creates the $payment_methods array, which contains a list of payment methods which support customer payment profiles. Use a simple foreach loop to display payment method names and links to the customer profile page. 

<?= flash_message() ?>
<? if (!$payment_methods): ?>
  <p>Payment profiles not found</p>
<? else: ?>
  <ul>
    <? foreach ($payment_methods as $method): ?>
      <li>
         <h4><?= h($method->name) ?></h4>
         <?
           $profile = $method->find_customer_profile($this->customer);
           if ($profile):
         ?>
          <p>Stored credit card: <?= 'xxxx'.$profile->cc_four_digits_num ?>
          - <a href="<?= root_url('/payment_profile/'.$method->id) ?>">Update or delete</a></p>
        <? else: ?>
          <p><a href="<?= root_url('/payment_profile/'.$method->id) ?>">Enter credit card details</a></p>
         <? endif ?>        
      </li>
    <? endforeach ?>
  </ul>
<? endif ?>
{{ flash_message() }}
{% if not payment_methods %}
  <p>Payment profiles not found</p>
{% else %}
  <ul>
    {% for method in payment_methods %}
      <li>
         <h4>{{ method.name }}</h4>
         {% set profile = method.find_customer_profile(this.customer) %}
         {% if profile %}
          <p>Stored credit card: {{ 'xxxx'~profile.cc_four_digits_num }}
          - <a href="{{ root_url('/payment_profile/'~method.id) }}">Update or delete</a></p>
         {% else %}
          <p><a href="{{ root_url('/payment_profile/'~method.id) }}">Enter credit card details</a></p>
         {% endif %}
      </li>
    {% endfor %}
  </ul>
{% endif %}

Implementing the Payment Profile page

The Payment Profile page displays an existing customer payment profile information and a form for creating or updating the payment profile. The page security configuration should not allow guest customers to access the payment profile page. The page should be available only for logged in customers, in HTTPS mode.

Use the shop:payment_profile action as a base CMS action for the page. Use the following code snippet for the payment profile page: 

<? if (!$payment_method): ?>
  <p>Payment method not found.</p>
<? else: ?>
  <? if ($payment_profile): ?>
    <?= open_form() ?>
      <p>
        Stored credit card: <?= 'xxxx'.h($payment_profile->cc_four_digits_num) ?>
        <input type="submit" name="delete_profile" value="Delete card"/>
      </p>
      <input type="hidden" name="redirect" value="<?= root_url('payment_profiles') ?>">
     </form>
  <? endif ?>

  <? $payment_method->render_payment_profile_form($this) ?>
<? endif ?>
{% if not payment_method %}
  <p>Payment method not found.</p>
{% else %}
  {% if payment_profile %}
    {{ open_form() }}
      <p>
        Stored credit card: {{ 'xxxx'~payment_profile.cc_four_digits_num }}
        <input type="submit" name="delete_profile" value="Delete card"/>
      </p>
      <input type="hidden" name="redirect" value="{{ root_url('payment_profiles') }}">
     </form>
  {% endif %}

  {{ payment_method.render_payment_profile_form(this) }}
{% endif %}


Previous: Custom Payment Methods and Bank Transfers
Return to Payment