PayFabric

Test Branch

payfabric on sandbox10.

Pay Fabric Setup

Before you setup PayFabric (https://www.payfabric.com/), You must create an account on their site and configure it for sandbox development. Once you have created this account, log in using the PayFabric sandbox login: 

https://sandbox.payfabric.com/Portal/Account/?wforce=1

Once logged in, First you need to create a device to connect as. In this case the device will be Core dna. On PayFabric, Navigate to Settings → Dev Central → Device Management. From here you can add a new device. 

Shown above is the test Core dna device, you can retrieve your device ID and device Password from here.

Now you must create a test gateway account. This depends on your own requirements as many payment account are configurable from here. Go to Settings → Gateway Account Configuration 

In this case we have added a payment gateway called PayflowPro, use this as your Gateway name in the Core dna payment config.

Core dna Setup

Navigate to the config module (cog wheel → site configuration) and add a new payment method under PayFabric. Use all the details set in the previous steps to configure PayFabric in Core dna. 

If you want to have multiple PayFabric payment gateways listed in Core dna, then you must create a payment config per gateway required.

Use the 'Authorize Only' flag to create a transaction and return only the Transaction Key. This key is then available from the order object using $order->getTransactions(). The key is saved into the response data for the transaction.

PayFabric allows the use of credit card tokens for checkout, This allows us to save a credit card token into Core dna and then pass that along to PayFabric. No credit card information is stored in Core dna, apart from the last 4 digits of the card to show to the user during checkout. PayFabric also supports normal credit card checkout. 

Manage Tokens: yoursite.com/?action=pubuser&form_name=tokens

You can find the tokens in the DXP under users. You can add / update / delete tokens here. 

On the site itself, you can only create a token during checkout using the ajax save button on the payment screen. This request is sent to PayFabric who will return a token string on success. Any errors will be displayed on the page.

Note: If you delete a Token in the DXP, it will delete it on PayFabric. If you add on the DXP, it will not add on PayFabric as we do not collect credit card details - therefore making token generation impossible. It will be added to PayFabric if the users saves the card during checkout, as we have the cc details there to use.

Tokens are also deleted on PayFabric from the user front end 'saved cards' view. If a token is not found remotely, Core dna will delete the token locally.

Front End Integration

Below are the files and modifications required to integrate PayFabric into your site. You can test all these changes on sandbox10 as they are currently live in that site.

Please note for the JS function you have two actions. for delete you must pass the token to delete.

&form_name=credit_card_token&form_action=create

&form_name=credit_card_token&form_action=delete&token=xxxx

File Changes

modules/prodcatalogueorder/templates/payment.html

payment html
<{* use 'showTokenCC' to display the tokens or not, you still need to display the credit card *}>
<{* form in order to create new tokens *}>
<{if $curoption->getConfRoutine() eq 'showTokenCC'}>
<{* payfabric requires its own customer number which is mapped to our user id*}>
<input type="hidden" name="payfabric_customer_number" value="<{$user->getId()}>" />
<{* the user does not have to use a token, but if they select one then assing the token value here*}>
<input type="hidden" id="card_token" name="card_token" value="" />
<div id="credit-card-token-errors"></div>
<div class="content__radio__inputs" style="width: 30%; padding-left: 10px;padding-top: 10px;">
 <select id="cc-token-select" name="cc-token-select" onchange="updateToken()">
 <option value="no_card">Enter Credit Card Details</option>
 <{foreach $tokens as $token}>
 <option value="<{$token->getToken()}>">Card ending: <strong><{$token->getCardEnding()}></strong> (<{$token->getComment()}>)</option>
 <{/foreach}>
 </select>
 <br><br>
 <a href="#" class="cta" onclick="createNewToken()">Save Card !</a>
</div>
<{/if}>
<{* credit card form is used to create a new card TOKEN *}>
<{if $curoption->getKey() eq '127' or $curoption->getConfRoutine() eq 'showCC' or $curoption->getConfRoutine() eq 'showTokenCC'}>

JavaScript functions

payment javascript
function updateToken()
{
 var e = document.getElementById("cc-token-select");
 var token = e.options[e.selectedIndex].value;
 document.getElementById("card_token").value = token;
}
function createNewToken()
{
 $('#credit-card-token-errors').html('');
 var card = {
 cardName: $('#cc_owner').val(), // second name is required, Core dna splits by space
 cardNumber: $('#cc_number').val(), // this must a plain string of numbers, no dashes or other characters
 cardExpiry: $('#cc_expires_month').val() + $('#cc_expires_year').val(), // must be in the format of 0120 (Jan 20)
 };
 var url = '/index.php?action=prodcatalogueorder&form_name=credit_card_token&form_action=create&type=json';
 $.ajax({
 dataType: "json",
 url: url,
 data: card,
 type: 'POST',
 success: function(response) {
 $('#credit-card-token-errors').html(response.message);
 if (response.success) {
 // add the card into the select box and select it
 var option = document.createElement("option");
 option.text = "Card ending: " + response.data.card.card_ending + " (" + response.data.card.comment + ")";
 option.value = response.data.card.token;
 var select = document.getElementById("cc-token-select");
 select.appendChild(option);
 document.getElementById("cc-token-select").value = response.data.card.token;
 updateToken();
 }
 },
 error: function (err) {
 $('#credit-card-token-errors').html(err);
 console.log(err);
 }
 });
}

modules/pubuser/templates/token.html

token.html
<{extends file="layout_site.html"}>
<{block name=section}>token<{/block}>
<{block name="body"}>
 <div style="width:50%; padding-left: 10px;">
 <{if $success}>
 <p style="background-color: darkseagreen"><{$success}></p>
 <{/if}>
 <{if $error}>
 <p style="background-color: orangered"><{$error}></p>
 <{/if}>
 <br>
 <a href="/index.php?action=pubuser&form_name=tokens">Back</a>
 <br><br>
 <p>Viewing details for Card Ending in <{$token->getCardEnding()}></p>
 <p>The only thing that we can edit is the comment for the card. if the user wants to add a new card then they go to
 checkout and create a new one. if they wish to edit more than the comment, they delete it and create it again</p>
 <hr>
 <form action="/index.php?action=pubuser&form_name=tokens" method="post" name="tokenForm" class="customer__form">
 <input type="hidden" name="form_action" value="save"/>
 <input type="hidden" name="id" value="<{$token->getId()}>"/>
 <input type="hidden" name="template" value="token.html"/>
 <p>Comment</p>
 <input name="comment" value="<{$token->getComment()}>" style="width: 75%">
 <hr>
 <button type="submit" class="btn">Save</button>
 </form>
 <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
 </div>
<{/block}>


modules/pubuser/templates/tokens.html

token.html
<{extends file="layout_site.html"}>
<{block name=section}>tokens<{/block}>
<{block name="body"}>
 <div style="width:50%; padding-left: 10px;">
 <{if $success}>
 <p style="background-color: darkseagreen"><{$success}></p>
 <{/if}>
 <{if $error}>
 <p style="background-color: orangered"><{$error}></p>
 <{/if}>
 <br>
 <p>Listing Cards for <strong><{$user->getFirstname()}></strong></p>
 <br>
 <{if $tokens}>
 <ul>
 <{foreach $tokens as $token}>
 <li>
 <{*each Token is an instance of an object CreditCardToken*}>
 * Card Ending: <{$token->getCardEnding()}> (<{$token->getComment()}>) |
 <a href="/index.php?action=pubuser&form_name=tokens&form_action=details&id=<{$token->getId()}>">Details</a> |
 <a href="/index.php?action=pubuser&form_name=tokens&form_action=delete&id=<{$token->getId()}>">Delete</a>
 </li><hr>
 <{/foreach}>
 </ul>
 <{/if}>
 <{if !$tokens}>
 <p>No tokens found</p>
 <{/if}>
 <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
 </div>
<{/block}>