+ Start a Discussion
ajitvermaajitverma 

Simulate Cybersource Hosted Order Page in Apex

Hi All,

 

I have requirement where I have to implement Cybersource payment gateway in Salesforce.com. I am trying to use Cybersource Hosted Order Page approach to implement this functionality.

 

Cybersource has provided me some sample JSP pages which I can use in any java based web application and implement the payment gateway within that application and I am able to do that.

 

Now I have to simulate the same functionality in Salesforce.com using Visualforce and Apex. I am able to simulate most of the code in Apex but got stuck while simulating Message Authentication code and secret key. Below is the code written in java which I need to simulate in Apex.

 

 

  public String getPublicDigest(String customValues) throws Exception{
    String pub =  "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2L8taoXQvBV5xddZp58JE2i3rQauaBe1U1lEQCIYNYlIQSt4J6++F6NBgmCx1vnSCX2s4O0FI3S5b/No7QTfKkO19ofJVYBB6hdlcPStHsnYLV9mDmHuFfiR8Ebk3dUWYVCQX+eyZj99WQmYiTPIEZSAuB54jTMRQwyAE5GsVwIDAQAB";    
    BASE64Encoder encoder = new BASE64Encoder();
    Mac sha1Mac = Mac.getInstance("HmacSHA1");
    SecretKeySpec publicKeySpec = new SecretKeySpec(pub.getBytes(), "HmacSHA1");
    sha1Mac.init(publicKeySpec);
    byte[] publicBytes = sha1Mac.doFinal(customValues.getBytes());
    String publicDigest = encoder.encodeBuffer(publicBytes);
    return publicDigest.replaceAll("\n", "");
  }

Here is the code which I simulated in Apex but the key generated is still invalid.

 

 

    public String getPublicDigest(String customValues){
	String secretKey = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2L8taoXQvBV5xddZp58JE2i3rQauaBe1U1lEQCIYNYlIQSt4J6++F6NBgmCx1vnSCX2s4O0FI3S5b/No7QTfKkO19ofJVYBB6hdlcPStHsnYLV9mDmHuFfiR8Ebk3dUWYVCQX+eyZj99WQmYiTPIEZSAuB54jTMRQwyAE5GsVwIDAQAB';
        //Blob blobDigest = Crypto.generateDigest('hmacSHA1', Blob.valueOf(pub));
        Blob sha1Mac = Crypto.generateMac('hmacSHA1', Blob.valueOf(customValues), EncodingUtil.base64Decode(secretKey));
        String publicDigest = Encodingutil.convertToHex(sha1Mac);
        return publicDigest;
    }

 

 

Any help is appreciated.

 

 

Dogen ZenjiDogen Zenji

Did you ever figure this out?

ajitvermaajitverma

No, In fact I skipped this approach and redirected user to Cyber source payment page for processing of payment.

 

EastwayEastway

Hi, does this require the user to re-enter the payment (card, direct debit etc) details in the cybersource page?

MoggyMoggy
Has this ever been solved?

The only thing in your code is that you use HmacSHA1, what i get from all the Cybersource documentation is that you have to use HmacSHA256

Question I have is how does the HTTP request header has to look like, as I get this "invalid security" no wsse header error despite that i use the trans action securtyi keys...
Frank Mamone 6Frank Mamone 6

Hi https://cgi-sfdc.atlassian.net/secure/Dashboard.jspa

Has this been solved?

-Frank

Saket GoyalSaket Goyal
Hi Ajit Verma,
 I am also using cybersource for payment processing. Can you help me out with the apex code to redirect to the payment gateway page? Also what are the fields we require to fill while going before payment gateway page.

Thanks & regards
Sourabh
MoggyMoggy
What method are you using, we used the silent gateway. The trick is that you don't store the details on your side, you fetch with a page the contact details, store them as you already have in your salesforce contact list you the generate the first part of the cybersource then display the payment details page which does not store anything on your end , it will use a secure chanel directly to cybersource on submit but with the before created encrypted details

your details for cybersource are ideally stored encrypted in custom settings ( use the utility class encoded / decoded to store and retrieve )

the controller looks like
public with sharing class Cybersource_Controller{

    private  Map<string,string> oPassedParams = new Map<String,String>();  //ApexPages.currentPage().getParameters();
    
    private String access_key = getHOLO();
    private String transaction_uuid = getUUID();
    private String signed_field_names = 'access_key,profile_id,transaction_uuid,signed_field_names,unsigned_field_names,signed_date_time,locale,ignoreAVSResult,transaction_type,reference_number,' +
                                        'amount,currency,payment_method,bill_to_forename,bill_to_surname,bill_to_email,bill_to_address_line1,bill_to_address_city,bill_to_address_country,' + 
                                        'bill_to_address_postal_code';
    private String unsigned_field_names = 'card_type,card_number,card_expiry_date';
    private String signed_date_time = getUTCDateTime();
    private String locale = 'en';
    private String ignoreAVSResult = 'true';
    public String transaction_type {get;private set;} //either sale or sale,create_payment_token
    private String reference_number = userinfo.getuserid();
    public String amount {get;set;}
    private String currency1 ;
    public String payment_method {get;set;}
    public String bill_to_forename {get;set;}
    public String bill_to_surname {get;set;}
    public String bill_to_email {get;set;}
    public String bill_to_address_line1 {get;set;}
    public String bill_to_address_city {get;set;}
    private String bill_to_address_country;
    public String bill_to_address_postal_code {get;set;}
    public String card_type {get;set;}
    public String card_number {get;set;}
    public String card_expiry_date {get;private set;}// ?? format is MM-YYYY
    public String card_expiry_date_month {get;set;}// ?? format is MM-YYYY --->> picklist
    public String card_expiry_date_year {get;set;}// ?? format is MM-YYYY  --->> picklist ( current + 9 )  
    private boolean enabled = true;
    private String ccselection;
    
    public static String sign(Map<string, string> paramsArray)  {
        String result = sign(buildDataToSign(paramsArray), Cybersource_Controller.recover());
        return result;
    }
    
     public String getUUID(){
        string oGUID = GuidUtil.NewGuid();
        return oGUID;
    }
    
    public String getUTCDateTime(){
        DateTime oUTSDateTime = System.now();//Original code was DateTime.Now.ToUniversalTime(); ... possible issues with the date time format
        String strUTCDateTime = oUTSDateTime.format('yyyy-MM-dd\'T\'HH:mm:ss\'Z\'');
        return strUTCDateTime;
    }
    
    
    Public String getHOLO(){
      return EncodingUtil.base64decode(CyberSource__c.getValues('testcenter').Accesskey__c).toString();
    }
  
    Public String getHOLO1(){
      return EncodingUtil.base64decode(CyberSource__c.getValues('testcenter').ProfileId__c).toString();
   }
   
   public String getParametersValues(){
        //Map<string,string> oPassedParams = ApexPages.currentPage().getParameters();
        String result = '';
        
       for (String oKey : oPassedParams.KeySet()){ 
            result += '<div>';
            result += '<input type="hidden" id="' + oKey + '" name="' + oKey + '" value="' + oPassedParams.get(oKey) + '"/>';
            result += '</div>';
        }
        
        return result;
    }
    
    public String getParametersValuesHidden(){
        //Map<string,string> oPassedParams = ApexPages.currentPage().getParameters();
        String result = '';
        for (String oKey : oPassedParams.KeySet()){ 
            result += '<input type="hidden" id="' + oKey + '" name="' + oKey + '" value="' + oPassedParams.get(oKey) + '"/>';
        }
        
        return result;
    }
    
    public String getSignedData(){
        //Map<string,string> oPassedParams = ApexPages.currentPage().getParameters();
        String result = '';
        result += '<input type="hidden" id="signature" name="signature" value="' + Cybersource_Controller.sign(oPassedParams) + '"/>';
        return result;
    }
     
    
    public string getEndp(){
       
        return CyberSource__c.getValues('testcenter').sale_endpoint__c;
      
    }
    
    private void popParams(){
        oPassedParams.put('access_key',getHOLO());
        oPassedParams.put('profile_id',getHOLO1());
        oPassedParams.put('transaction_uuid',getUUID());
        oPassedParams.put('signed_field_names','access_key,profile_id,transaction_uuid,signed_field_names,unsigned_field_names,' +
                           'signed_date_time,locale,ignoreAVSResult,transaction_type,reference_number,amount,currency,payment_method,' +
                           'bill_to_forename,bill_to_surname,bill_to_email,bill_to_address_line1,bill_to_address_city,bill_to_address_country,bill_to_address_postal_code');
        oPassedParams.put('unsigned_field_names','card_type,card_number,card_expiry_date'); 
        oPassedParams.put('signed_date_time',getUTCDateTime());
        oPassedParams.put('locale','en');
        oPassedParams.put('ignoreAVSResult','true');
        oPassedParams.put('transaction_type','sale,create_payment_token');
        oPassedParams.put('reference_number',reference_number);
        oPassedParams.put('amount',amount);
        oPassedParams.put('currency',getBillCurren());
        oPassedParams.put('payment_method',payment_method);
        oPassedParams.put('bill_to_forename',bill_to_forename);
        oPassedParams.put('bill_to_surname',bill_to_surname);
        oPassedParams.put('bill_to_email',bill_to_email);
        oPassedParams.put('bill_to_address_line1',bill_to_address_line1);
        oPassedParams.put('bill_to_address_city',bill_to_address_city);
        oPassedParams.put('bill_to_address_country',bill_to_address_country);
        oPassedParams.put('bill_to_address_postal_code',bill_to_address_postal_code);
                   
    }
    
    private Static String recover(){
     String a = CyberSource__c.getValues('testcenter').SecKey1__c;
     String b = CyberSource__c.getValues('testcenter').SecKey2__c;
     String c = a + b;
     String d = EncodingUtil.base64decode(c).toString();
     return d;
   }
  
    private static String commaSeparate(List<string> dataToSign) {
        String result = '';
        for(String Str : dataToSign) {
            result += (result==''?'':',')+Str;
        }
        return result;                         
    }

    private static String buildDataToSign(Map<string,string> paramsArray) {
        String[] signedFieldNames = paramsArray.get('signed_field_names').Split(',');
        List<string> dataToSign = new List<string>();

        for (String oSignedFieldName : signedFieldNames){
             dataToSign.Add(oSignedFieldName + '=' + paramsArray.get(oSignedFieldName));
        }
        return commaSeparate(dataToSign);
    }
    
     private static String sign(String data, String secretKey) {
        String result = EncodingUtil.base64Encode(Crypto.generateMac('hmacSHA256', Blob.valueOf(data), Blob.valueOf(secretKey)));
        return result;
    }
    
    public List<SelectOption> getCountry(){
        List<CS_Country__c> cou = CS_Country__c.getAll().values();
        List<SelectOption> options = new List<SelectOption>();
        for(CS_Country__c c :cou){
        if(c.isActive__c){options.add(new SelectOption(c.Isocode__c,c.Name));}
        }
        return options;
    }
    public void setBillCountry(String Country){
        this.bill_to_address_country = Country;
    }
    
    public String getBillCountry(){
      return bill_to_address_country;
    }
    
    public List<SelectOption> getCurren(){
        List<CS_currencies__c> curr = CS_currencies__c.getAll().values();
        List<SelectOption> options = new List<SelectOption>();
        for(CS_currencies__c c :curr){
        if(c.isActive__c){options.add(new SelectOption(c.Isocode__c,c.Name));}
        }
        return options;
    }
    public void setBillCurren(String Curren){
        this.currency1 = curren;
    }
    
    public String getBillCurren(){
      return currency1;
    }
    
    public PageReference visa(){
    enabled = false;
    payment_method ='card';
    card_type = CS_CC__c.getValues('Visa').type__c;
    setCcselection('Icon_visa');
    popParams();
    return null;
    }
    
    public PageReference master(){
    enabled = false;
    payment_method ='card';
    card_type = CS_CC__c.getValues('MasterCard').type__c;
    setCcselection('Icon_Master');
    popParams();
    return null;
    }
    
    public PageReference maestro(){
    enabled = false;
    payment_method ='card';
    card_type = CS_CC__c.getValues('Maestro UK Domestic').type__c;
    setCcselection('Icon_Maestro');
    popParams();
    return null;
    }
    
    public PageReference Amexo(){
    enabled = false;
    payment_method ='card';
    card_type = CS_CC__c.getValues('American Express').type__c;
    setCcselection('Icon_Amex');
    popParams();
    return null;
    }
    
    public PageReference VisaE(){
    enabled = false;
    payment_method ='card';
    card_type = CS_CC__c.getValues('Visa Electron').type__c;
    setCcselection('Icon_visa_e');
    popParams();
    return null;
    }
    
    public PageReference MaestroInt(){
    enabled = false;
    payment_method ='card';
    card_type = CS_CC__c.getValues('Maestro International').type__c;
    setCcselection('Icon_MaestroIn');
    popParams();
    return null;
    }
    
    public PageReference DirDeb(){
    enabled = false;
    setCcselection('Icon_DD');
    return null;
    }
    
    public PageReference paypal(){
    enabled = false;
    setCcselection('Icon_paypal');
    return null;
    }
    
    public boolean getEnabled(){
      return enabled;
    }
    
    private void setCcselection(String val){
    ccselection = val;
    }
    
    public String getCcselection(){
    return ccselection;
    }
}

the page look like 
<apex:page id="CSPayment" showHeader="false" controller="Cybersource_Controller" title="Payment gateway">
   <apex:define name="header">
      <center>
        <apex:form id="theInput" >
         <apex:panelGrid columns="2" style="margin-top:1em;">
           <apex:outputLabel value="First Name" for="firstName"/>
           <apex:inputText required="true" id="firstName" value="{!bill_to_forename}" disabled="{!enabled==false}" />
           <apex:outputLabel value="Last Name" for="lastName"/>
           <apex:inputText required="true" id="lastName" value="{!bill_to_surname}" disabled="{!enabled==false}"/>
           <apex:outputLabel value="Email" for="email"/>
           <apex:inputText required="true" id="email" value="{!bill_to_email}" disabled="{!enabled==false}"/>
           <apex:outputLabel value="Street" for="address1"/>
           <apex:inputText required="true" id="address1" value="{!bill_to_address_line1}" disabled="{!enabled==false}"/>
           <apex:outputLabel value="City" for="city"/>
           <apex:inputText required="true" id="city" value="{!bill_to_address_city}" disabled="{!enabled==false}"/>
           <apex:outputLabel value="Country" for="country"/>
           <apex:selectList title="Country" value="{!BillCountry}" multiselect="false" size="1" id="country" disabled="{!enabled==false}">   
           <apex:selectOptions value="{!Country}"/>
           </apex:selectList>
           <apex:outputLabel value="Zip/Postcode" for="postal"/>
           <apex:inputText required="true" id="postal" value="{!bill_to_address_postal_code}" disabled="{!enabled==false}"/>
           <apex:outputLabel value="Currency" for="curren"/>
           <apex:selectList title="curren" value="{!BillCurren}" multiselect="false" size="1" id="curren" disabled="{!enabled==false}">   
           <apex:selectOptions value="{!Curren}"/>
           </apex:selectList>
           <apex:outputLabel value="Amount" for="amount"/>
           <apex:inputText required="true" id="amount" value="{!amount}" disabled="{!enabled==false}"/>
            
           <apex:outputText value="Please select a payment method!"/>
            
         </apex:panelGrid> 
      <apex:outputPanel id="testout" rendered="{!enabled==true}">
         <apex:outputText value="{!enabled}"/>
         <apex:panelGrid columns="7" style="margin-top:2em;">
         <apex:commandButton id="visa" image="{!$Resource.Icon_visa}" action="{!visa}" disabled="{!enabled==false}" />
         <apex:commandButton id="master" image="{!$Resource.Icon_Master}" action="{!master}" disabled="{!enabled==false}"/>
         <apex:commandButton id="maestrouk" image="{!$Resource.Icon_Maestro}" action="{!maestro}" disabled="true"/>
        <!-- <apex:commandButton id="maestroin" image="{!$Resource.Icon_visa}" action="{!visa}"/> -->
         <apex:commandButton id="Amex" image="{!$Resource.Icon_Amex}" action="{!Amexo}" disabled="true"/>
         <apex:commandButton id="visaE" image="{!$Resource.Icon_visa_e}" action="{!visaE}" disabled="true"/>
         <apex:commandButton id="DD" image="{!$Resource.Icon_DD}" action="{!DirDeb}" disabled="true"/>
         <apex:commandButton id="PP" image="{!$Resource.Icon_paypal}" action="{!paypal}" disabled="true"/>
         </apex:panelGrid> 
       </apex:outputPanel>  
        </apex:form>
     </center>
   </apex:define>
   <apex:outputPanel id="testcard" rendered="{!enabled==false}">
    <apex:define name="body" >  
      <center>
        <form id="theForm" action="{!endp}" method="post">
                    <apex:panelGrid columns="1" style="margin-top:1em;">
                    <apex:image id="visa" value="{!$Resource.Icon_visa}" rendered="{!ccselection=='Icon_visa'}"/>
                    <apex:image id="master" value="{!$Resource.Icon_Master}" rendered="{!ccselection=='Icon_Master'}"/>
                    <apex:image id="maestrouk" value="{!$Resource.Icon_Maestro}" rendered="{!ccselection=='Icon_Maestro'}"/>
               <!-- <apex:image id="maestroin" value="{!$Resource.Icon_visa}"  /> -->
                    <apex:image id="Amex" value="{!$Resource.Icon_Amex}" rendered="{!ccselection=='Icon_Amex'}"/>
                    <apex:image id="visaE" value="{!$Resource.Icon_visa_e}" rendered="{!ccselection=='Icon_visa_e'}"/>
                    <apex:image id="DD" value="{!$Resource.Icon_DD}" rendered="{!ccselection=='Icon_DD'}"/>
                    <apex:image id="PP" value="{!$Resource.Icon_paypal}" rendered="{!ccselection=='Icon_paypal'}"/>
                    <div>
                     <apex:outputtext escape="false" value="{!ParametersValues}"></apex:outputtext>
                    </div>
                    <apex:outputtext escape="false" value="{!ParametersValuesHidden}"></apex:outputtext>
                    <apex:outputtext escape="false" value="{!SignedData}"></apex:outputtext>
                    </apex:panelGrid>
                    <apex:panelGrid columns="2" style="margin-top:1em;">
                    <input type="hidden" name="card_type" value="{!card_type}"/>
                    <span>card_number     :</span><input type="text" name="card_number"/><br/>
                    <span>card_expiry_date:</span><input type="text" name="card_expiry_date"/><span> format MM-YYYY</span><br/>
                    <input type="submit" id="submit" value="Confirm "/>  
                    </apex:panelGrid> 
                  <br/>
        </form>
     </center>
  </apex:define>
</apex:outputPanel>
</apex:page>

for storing the secret details of you cyber connection you could use something like
//Controller
public with sharing class CSInput{
    CyberSource__c CS = CyberSource__c.getValues('testcenter');
    Public String Seckey {get;set;}
    public String akey {get;set;}
    public String prof {get;set;}
    public boolean s {get;private set;}
    public boolean a {get;private set;}
    public boolean p {get;private set;}  
    private String FRU = URL.getSalesforceBaseUrl().toExternalForm() + '/';      
    
  public CSInput(){
    CS.Accesskey__c= '';
    CS.ProfileId__c ='';
    CS.SecKey1__c = '';
    CS.SecKey2__c = '';
    Seckey = '';
    akey = '';
    prof ='';
    s = false;
    a = false;
    p = false;
  }

  public PageReference Cancel(){
        PageReference newPage = New PageReference(FRU);
        newPage.setRedirect(true);
        return newPage;
  }
  
   public PageReference encodeS(){
    if(seckey != ''){
      blob b = Blob.valueOf(Seckey);
      String outp = EncodingUtil.base64Encode(b);
      CS.SecKey1__c = outp.left(199);
      CS.SecKey2__c = outp.substring(199);
      update CS;
      s = true;
      }
  return null;
  }
  
  public PageReference encodeA(){
    if(akey != ''){
     blob b = Blob.valueOf(akey);
     CS.Accesskey__c = EncodingUtil.base64Encode(b);
     update CS;
     a = true;
     }
     return null;
  }
  
  public PageReference encodeP(){
   if(prof != ''){
     blob b = Blob.valueOf(prof);
     CS.ProfileId__c = EncodingUtil.base64Encode(b);
     update CS;
     p = true;
     }
     return null;
  }



}

//PAGE
<apex:page tabStyle="Lead" Controller="CSInput">
  <apex:form >
      <apex:PageBlock id="itschi">
      <apex:pageBlockButtons >
          <apex:commandButton value="Cancel" action="{!Cancel}"/>
      </apex:pageBlockButtons>
      <apex:pageBlockSection title="Input Screen to store Cybersource Keys" collapsible="FALSE" />
      <apex:pageBlockSection title="Accesskey" collapsible="True" Columns="1" id="AA">
           <apex:inputText value="{!akey}"/>
           <apex:commandButton value="{!IF(a==true,'stored','Save')}" action="{!encodeA}" disabled="{!a}" reRender="AA"/>
      </apex:pageBlockSection>
      <apex:pageBlockSection title="Profile Id" collapsible="True" Columns="1" id="BB">
           <apex:inputText value="{!prof}"/>
           <apex:commandButton value="{!IF(p==true,'stored','Save')}" action="{!encodeP}" disabled="{!p}" reRender="BB"/>
      </apex:pageBlockSection>
      <apex:pageBlockSection title="Security Key" collapsible="True" Columns="1" id="CC">
           <apex:inputText value="{!seckey}"/>
           <apex:commandButton value="{!IF(s==true,'stored','Save')}" action="{!encodeS}" disabled="{!s}" reRender="CC"/>
      
      
      </apex:pageBlockSection>
    </apex:PageBlock>
  </apex:form>
</apex:page>

you nee to create the equivalent custom settings and entries, you can find in the code
(Cybersource__c and fields as stated and one entry 'testcenter' )

hope that helps (working solution)

I also found this in my resources, but might have been atest?
public class EncryptUtils {
 public String inp {get;set;}
 public String outp {get;set;}
 public string comp {get;set;}
 CyberSource__c CS = CyberSource__c.getValues('testcenter');

  // The key size and the type of encryption used in this class
  // Valid values 128, 192 and 256
  
  private static Integer KEY_SIZE = 256;
  private static String ENCRYPT_TYPE = 'AES' + String.valueOf(KEY_SIZE);
  
  // Generate a new key
  public static Blob generateNewPrivateKey() {
    return Crypto.generateAesKey(KEY_SIZE);
  } // end generate new private key

  // Enrypt given data using given private key
  public static Blob encryptDataWithKey(Blob privateKey, Blob clearData) {
    return Crypto.encryptWithManagedIV(ENCRYPT_TYPE, privateKey, clearData);
  }
  
  // Decrypt given data and private key
  public static Blob decryptDataWithKey(Blob privateKey, Blob encryptedData) {
    return Crypto.decryptWithManagedIV(ENCRYPT_TYPE, privateKey, encryptedData);
  }
  /*
  public PageReference decode(){
  Blob a = EncryptUtils.generateNewPrivateKey();
  blob b = Blob.valueOf(CS.Akey__c);
  blob c = EncryptUtils.decryptDataWithKey(a,b);
  comp = EncodingUtil.base64Encode(c);
  return null;
  }
  
  public PageReference encode(){
  Blob a = EncryptUtils.generateNewPrivateKey();
  blob b = Blob.valueOf(inp);
  blob c = EncryptUtils.encryptDataWithKey(a,b);
  outp = EncodingUtil.base64Encode(c);
  CS.Akey__c = outp;
  update CS;
  return null;
  }
  
  */
  
  public PageReference decode(){
   
  blob b = EncodingUtil.base64decode(CS.Akey__c);
   
  comp = b.toString();
  return null;
  }
  
  public PageReference encode(){
   
  blob b = Blob.valueOf(inp);
  system.debug(b.size());
  outp = EncodingUtil.base64Encode(b);
  CS.Akey__c = outp;
  update CS;
  return null;
  }
  Public String getHOLO(){
  return EncodingUtil.base64decode(CyberSource__c.getValues('testcenter').Akey__c).toString();
  }
  
} // end class

 
Saket GoyalSaket Goyal
Thanks Moggy.
Can you please let me know from where you are getting 'transaction_uuid'. Is it coming from the cybersource?

Thanks & Regards
Sourabh
MoggyMoggy
this is part of the encrypted parameters within the url, which you get from cybersource, ( if i recall it correctly, its been a whiile ( a year or so)), You submit the signed and unsigned data directly to Cybersource and within the response you get all the values back crypted of course.

it is / was working so I don't really spend much attention to the details behind , only important thing was the salesforce contact was able to make a payment and the response from CS was either yes ok or no not ok. this is why we used the silent post as this requires the minimum of signed security for the company ( CSP ) i think its called, as soon you store any credit card details in relation or not you have to go through the highest level as a bank would go through, the chosen way avoids that.
The contact details get encrypted and reflect the signed data ( processed by your server to encryp them, this will then be combined with the entered card details and submitted directly to cybersource (encrypted with the signed data as double protection ( encrypted on top of the encryption which then will be de coded on cybersource end , validated and process if fine, then you get a repsonse inclinding the transaction uuid
which then can be used if you log into cybersource to find the transaction i believe
Saket GoyalSaket Goyal
Thanks Moggy.
Helps a lot.

Thanks & Regards
Sourabh
Kim Carlo NocedaKim Carlo Noceda
Hi Moggy,

I was trying to replicate the sample code that you have posted. But whenever I am clicking on the confirm, I am being redirected to the Cybersource page: 403 - Unauthorized 

You are not authorized to view this page. The transaction has not been processed.

Did I miss any on the code?