function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Sheri@SupportPaySheri@SupportPay 

Visualforce Digital Signature --> Recurly + Force.com App integration

I'm trying to integrate Recurly subscription management with an application I am running on force.com. I'd like to host the payment and billing pages with VisualForce but use Recurly servers to process the transactions.

In order to do this I am using the Recurly.js files (https://docs.recurly.com/recurlyjs) However, I need a signature to be created - I have tried all of the different ways (Crypto.sign, Apex, doing a canvas app leveraging the prebuilt PHP libraries, etc) but I am wondering if there is an easier way to do this:

Here is the code from the php page that works leveraging the PHP libraries. Does anyone know how to do this in salesforce without having to have a completly different environment host the PHP/Ruby/Python libraries?

<?php
require_once('lib/recurly.php');

// Required for the API
Recurly_Client::$subdomain = 'subdomain';
Recurly_Client::$apiKey = '111111111111111111111111111';
Recurly_js::$privateKey = 'a111111111111111111111111111111';
$planCode = 'innovator-yearly';
$currency = 'USD';
$signature = Recurly_js::sign(array($planCode));   
?>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Innovator Yearly Subscription</title>
<html>
  <head>
  <link rel="stylesheet" href="css/recurly.css" type="text/css" />
<script src="js/jquery.js"></script>
<script src="js/recurly.js"></script>
    <script>
    $(function(){
      Recurly.config({
        subdomain: 'subdomain'
        , currency: 'USD' // GBP | CAD | EUR, etc...
      });

      Recurly.buildSubscriptionForm({
        target: '#recurly-subscribe',
        planCode: 'innovator-yearly',
        successURL: 'success.php',
        signature: '<?php echo $signature;?>',
distinguishContactFromBillingInfo: false,
    collectCompany: false,
    collectContact: true,
    termsOfServiceURL: 'http://subdomain.com/contact/terms-of-use/',
    acceptPaypal: false,
    acceptedCards: ['mastercard',
                    'discover',
                    'american_express',
                    'visa'],
      });

    });
    </script>
</head>
  <body>
   
    <div id="recurly-subscribe">
    </div>
  </body>
</html>
</apex:page>

keywords: digital signature, crypto, PHP, Recurly, Subscription service
Ashish_SFDCAshish_SFDC
Hi Sheri, 


You can try these App Exchange packages, 

Docusign

https://appexchange.salesforce.com/listingDetail?listingId=a0N30000001taX4EAI

Echosign

https://appexchange.salesforce.com/listingDetail?listingId=a0N300000016ZmCEAU


Also see the links below with some sample code, 

https://wiki.developerforce.com/page/Apex_Crypto_Class

http://www.donanza.com/jobs/p7659547-salesforce_apex_code_to_create_digital_signature_for

https://www.elance.com/j/salesforce-apex-code-create-digital-signature-googlemapsapi-business/36435058/


Regards,
Ashish

Matt LunkesMatt Lunkes
Hi Sheri,

I am currently working on the exact same thing.  I don't think that Salesforce supports the use of PHP in Visualforce pages though.  Did you ever find a solution?  If not, how far along did you get in trying to generate a signature with Apex?

-Matt
Paul BachmannPaul Bachmann
Hi Sheri,

This is more complex APEX than I am used to dealing with, but it is close to working (works in preview).  Maybe a collective effort can get us what we both need.
I need to have E-Sig functionality and then a png file on a Case record that I can call in a custom Print Preview.
Problem I have is this is a hodgepodge from different solutions/advice I've found online.  I think my last major issue is to incorporate a standard controller (need to be able to add in standard page layouts) and then tweak it to point to case instead of Account, I keep getting that wrong as the source code I used pointed to Accts

VisualForce Page

<apex:page docType="html-5.0" controller="CapturePSignatureController" showheader="false" sidebar="false" standardStylesheets="false" id="pg">
 <apex:includeScript value="/soap/ajax/28.0/connection.js"/>
 
 <style>
  .container {
   text-align: center;
   font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
   color: cadetblue;
   font-weight: 500;
   font-size: 14px;
  }
  
  .button {
   font-family: calibri;
   border-radius: 8px;
   background-color: rgb(51, 116, 116);
   height: 36px;
   color: azure;
   font-size: 17px;
   border-width: 0px;
   width: 116px;
  }
 </style>
 <apex:form id="pbform">
  <apex:pageMessages />
  <div class="container">
   <h1 class="labelCol vfLabelColTextWrap ">Record Patient Signature:</h1>
   <canvas id="PsignatureCanvas" height="100px" width="350px" style="border: 3px solid antiquewhite; border-radius: 8px;" ></canvas>
  </div><br/>
  
  <div style="margin-left: 41%;">
   <apex:commandButton value="Save Patient Signature" onclick="savePSignature();return false;" styleClass="button"/>&nbsp;&nbsp;&nbsp;
   <apex:commandButton value="Clear" onclick="clearSign();return false;" styleClass="button"/>
  </div>
 </apex:form>

  <script>
  var canvas;
  var context;
  var drawingUtil;
  var isDrawing = false;
  var accountId = '';
  var prevX, prevY, currX, currY = 0;
  var accountId;

   function DrawingUtil() {
   isDrawing = false;
   canvas.addEventListener("mousedown", start, false);
   canvas.addEventListener("mousemove", draw, false);
   canvas.addEventListener("mouseup", stop, false);
   canvas.addEventListener("mouseout", stop, false);
   canvas.addEventListener("touchstart", start, false);
   canvas.addEventListener("touchmove", draw, false);
   canvas.addEventListener("touchend", stop, false);
   w = canvas.width;
      h = canvas.height;
  }

   function start(event) {
   event.preventDefault();
   
   isDrawing = true;
   prevX = currX;
   prevX = currY;
   currX = event.clientX - canvas.offsetLeft;
   currY = event.clientY - canvas.offsetTop;
   
   context.beginPath();
   context.fillStyle = "cadetblue";
   context.fillRect(currX, currY, 2, 2);
            context.closePath();
   
  }

   function draw(event) {
   event.preventDefault();
   if (isDrawing) {
    prevX = currX;
             prevY = currY;
             currX = event.clientX - canvas.offsetLeft;
             currY = event.clientY - canvas.offsetTop;
    context.beginPath();
    context.moveTo(prevX, prevY);
    context.lineTo(currX, currY);
    context.strokeStyle = "cadetblue";
    context.lineWidth = "2";
    context.stroke();
    context.closePath();
   }
  }

   function stop(event) {
   if (isDrawing) {
    context.stroke();
    context.closePath();
    isDrawing = false;
   }
  }
  
  function clearSign() {
   context.clearRect(0,0,w,h);
  }

   canvas = document.getElementById("PsignatureCanvas");
  context = canvas.getContext("2d");
  context.strokeStyle = "black";
  context.lineWidth = "2";
  drawingUtil = new DrawingUtil(canvas);
  

   function savePSignature() {
   var strDataURI = canvas.toDataURL();
   strDataURI = strDataURI.replace(/^data:image\/(png|jpg);base64,/, "");
   var accId = location.href.split('=')[1];
   accountId = accId;
   var result = CapturePSignatureController.savePSignature(strDataURI, accId, processResult);
  }

   function processResult(result) {
   alert(JSON.stringify(result));
   window.location.href = '/'+accountId;
  }

  </script>


</apex:page>




Controller

global with sharing class CapturePSignatureController {
 
 @RemoteAction
 global static String savePSignature(String imageUrl, String accountId) {
  
  try {
   Attachment accSign = new Attachment();
   accSign.ParentID = accountId;
   accSign.Body = EncodingUtil.base64Decode(imageUrl);
   accSign.contentType = 'image/png';
   accSign.Name = 'Patient Signature Image';
   accSign.OwnerId = UserInfo.getUserId();
   insert accSign;
   
   return 'success';
   
  }catch(Exception e){
   system.debug('---------- ' + e.getMessage());
   return JSON.serialize(e.getMessage());
  }
  return null; 
 }

}