News:

Support the VirtueMart project and become a member

Main Menu

Intergration of Mastercard Gateway in Australia

Started by aussieute, July 11, 2006, 22:16:18 PM

Previous topic - Next topic

tez

Here is a link to their support info if anyone needs it. I know it is impossible to find otherwise (intentionally I bet!).

http://business.commbank.com.au/merchants/

tez

Seems my client doesn't even have the Merchant Account required to get a Sercure Hash. It took me feakin ages to work this out as the CommBank support refuse to discuss anything unless I am the account holder and the account holder is too technophobic to handle the situation.

Is there a Virtuemart plugin for a Commbank payment gateway (go from your shop to CBA site to pay and then back to shop). I don't know what the merchant accounts or terminology for this is because none of the documentation or login screens or anything I can find mentions anything helpful!

Sorry... I really really hate payment systems with such abysmal documentation and support. And it's freakin CBA! WTF!

brandon23

This may or may not help for any of you having a play with this code. We have gotten the code to work Server side MIGS by including the required variables and sending them across to vpcpay. Make sure you include your info for md5HashData and vpc_ReturnURL. The MIGS gateway requires the info sent across sorted and encrypted which you can see below.


Quote/**************************************************************************
        ** name: process_payment()
   ** created by: findshorty.com
   ** modified to work as a Server hosted by Paul(outsourced) and Brandon www.lateralplains.com
   ** description: Server Hosted, 3-Party Payment
   ** returns:
   ***************************************************************************/
   function process_payment($order_number, $order_total, &$d) {
      global $vendor_mail, $vendor_currency, $VM_LANG, $vmLogger;
      $database = new ps_DB;
      $ps_vendor_id = $_SESSION["ps_vendor_id"];
      $auth = $_SESSION['auth'];
      $ps_checkout = new ps_checkout;
      require_once(CLASSPATH ."payment/".$this->classname.".cfg.php");
         
      $database->query( "SELECT DECODE(payment_passkey,'".ENCODE_KEY."') as passkey FROM #__{vm}_payment_method WHERE payment_class='".$this->classname."' AND shopper_group_id='".$auth['shopper_group_id']."'" );
      
      $transaction = $database->record[0];

      if( empty($transaction->passkey)) {

         $vmLogger->err( $VM_LANG->_PHPSHOP_PAYMENT_ERROR.'. Technical Note: The required transaction key is empty! The payment method settings must be reviewed.' );
         return false;
      }

            $vpcURL   = "https://".virtualPaymentClientURL."?";   
            $md5HashData = "";
            $formdata = array (
            'vpc_ReturnURL' => '',
            'vpc_Version' => vpc_Version,
            'vpc_Command' => vpc_Command,
            'vpc_MerchTxnRef' => $order_number,
            'vpc_AccessCode' => vpc_AccessCode,
            'vpc_Merchant' => vpc_Merchant,
            // Invoice Information
            'vpc_OrderInfo' => $order_number,
            // Transaction Data
            'vpc_Amount' => $order_total*100,      
            );         
            ksort($formdata);
            // Get the URL and append the variables
            foreach($formdata as $key => $value) {
               if(!empty($value)) { // Eliminate the empty variables
                  $vpcURL .= urlencode($key) . '=' . urlencode($value) . '&';
                  $md5HashData .= $value;   // Append to md5 hash data
               }
            }
            $vpcURL .= "vpc_SecureHash=" . strtoupper(md5($md5HashData));
            header("Location: " . $vpcURL);   
      return true;
   }

This may or may not help you and we hold no responsibilities as to how it will go for you.

yerg

Ok seeing as I started this thread I figured I'd return and see if anyone is willing to assist me and receive some stackable stuff in return for getting VM working with MIGS for me?

Alternatively give me some pointers ... I coped the wrath of MIGS them having claimed I brought their system down when setting up OSC. (don't see how but I'm not about to go there again)

So can you PM me or email me as per my original post?

1Rover1

Sorry, I couldn't see your original post... I'm only a n00b as far as forums and VirtueMart are concerned but I know much about MIGS.

I'm surprise to hear that OSC caused MIGS problems. I suspect that that was a mis-communication somewhere.

asterix

Tested and working with ANZ eGATE.
For those having trouble:
Make sure you get access to the Migs anz control panel from ANZ eGATE. They'll set you up a TEST account, in which  you need to setup an 'operator' that has the correct privileges to accept gateway payments. Login as the operator to retrieve your secure HASH etc.

From there, simply:
upload the find_shortly's ps_migs files into your administrator/components/com_virtuemart/classes/payments/ directory.
Login to your virtuemart console and add a new payment method. Make sure your payment class name is ps_migs  and payment method types is usage payment processor!
Hit save, then click on the ps_migs payment method link again to open the payment method form.
Go to the configuration tab and enter all the right details.
migs.mastercard.com.au/vpcdps
1
pay
then your access code etc...

you will need to enter your administrator password to enter a new secure hash.


Once thats done, you should be able to use the dummy cc numbers supplied by ANZ eGATE to run some tests. Be sure to point to the live url when you've done testing!

I've found diners and amex aren't working. Strange.

yerg

Asterix thanks but that doesn't help me with Bendigo Bank .. does it?

MIGS ANZ
MIGS CommBank
MIGS StGeorge Bank
MIGS Bendigo Bank

... all seem to integrate with the actual MIGS system in a different way. That's my understanding of it at this point.

Shoot me down if I'm wrong ;D



asterix

No, it works the same way from what I understand. The 'front end' login to the migs system might vary from bank to bank but logically they would each have the same requirements.

toivo

Hi,

I have just integrated the ANZ eGate MIGS Virtual Payment Client with Joomla eCommerce release 1.0.15, using the Bank Hosted mode of operation.  The solution utilises the configuration functions from findshorty's ps_migs.zip module, the request and the receipt cover the essential parts of the sample code from the VPC Developers Kit.

The receipt module:
- validates the hash
- checks that the order number exists
- checks that the order number is not a duplicate
- writes the response from the bank to a transaction log
- sends the email only if the card transaction was approved

As an added bonus, the shopper details are posted as a weblead to Salesforce.com.

If anyone is interested, drop me a line  :-)

Best Regards,
toivo
-------------------------
Suzhou, China

asterix

#24
I've cleaned out some of the code, and added error code handling so it tells the user exactly why their transaction failed if it did so:

<?php
defined
'_VALID_MOS' ) or die( 'Direct Access to this location is not allowed.' );
/**
* The ps_migs class, containing the payment processing code
*  for transactions with mastercard 
*
* @package VirtueMart
* @subpackage payment
* @copyright Copyright (C) 2001-2007 Ian Young. All rights reserved.
* @license http://www.gnu.org/copyleft/gpl.html GNU/GPL, see LICENSE.php
* VirtueMart is free software. This version may have been modified pursuant
* to the GNU General Public License, and as distributed it includes or
* is derivative of works licensed under the GNU General Public License or
* other free or open source software licenses.
* See /administrator/components/com_virtuemart/COPYRIGHT.php for copyright notices and details.
*
* http://virtuemart.net
*/

class ps_migs {

var $payment_code "MIGS";
var $classname "ps_migs";

/**
    * Show all configuration parameters for this payment method
    * @returns boolean False when the Payment method has no configration
    */
function show_configuration() {

global $VM_LANG$sess;
$db =& new ps_DB;
$payment_method_id mosGetParam$_REQUEST'payment_method_id'null );
/** Read current Configuration ***/
require_once(CLASSPATH ."payment/".$this->classname.".cfg.php");
    
?>

      <table>
  <tr>
<td><strong>Virtual Payment Client URL</strong></td>
<td><input type="text" class="inputbox" name="virtualPaymentClientURL" value="<?php echo virtualPaymentClientURL ?>" size="40" /></td>
<td>Domain only, no https:// as this is required by default</td>
</tr>
        <tr>
            <td><strong>VPC Version</strong></td>
            <td><input type="text" class="inputbox" size="4" value="<?php echo vpc_Version ?>" name="vpc_Version"/></td>
<td>&nbsp;</td>
        </tr>
        <tr>
            <td><strong>Command Type</strong></td>
            <td><input type="text" name="vpc_Command" value="<?php echo vpc_Command ?>" size="20" class="inputbox" maxlength="16" /></td>
<td>&nbsp;</td>
        </tr>
        <tr>
            <td><strong>Merchant AccessCode</strong></td>
            <td><input type="text" name="vpc_AccessCode" value="<?php echo vpc_AccessCode ?>" size="20" maxlength="9" class="inputbox" /></td>
<td>&nbsp;</td>
        </tr>
        <tr>
            <td><strong>MerchantID</strong></td>
            <td><input type="text" name="vpc_Merchant" value="<?php echo vpc_Merchant ?>" size="20" maxlength="16" class="inputbox" /></td>
<td>&nbsp;</td>
        </tr>
<tr>
            <td><strong>Secure Hash</strong></td>
            <td>
                <a id="changekey" href="<?php $sess->purl($_SERVER['PHP_SELF']."?page=store.payment_method_keychange&pshop_mode=admin&payment_method_id=$payment_method_id"?>" >
                <input onclick="document.location=document.getElementById('changekey').href" type="button" name="" value="View/Change Secure Hash" /></a>
            </td>
            <td>&nbsp;</td>
        </tr>

        <tr>
            <td><strong>Payment Server Display Language Locale</strong></td>
            <td><input type="text" name="vpc_Locale" value="en" size="20" maxlength="5" class="inputbox" /></td>
<td>&nbsp;</td>
        </tr>
        <tr><td colspan="3"><hr/></td></tr>
        <tr>
            <td><strong>Order Status for successful transactions</strong></td>
            <td>
                <select name="MIGS_VERIFIED_STATUS" class="inputbox" >
                <?php
                $q 
"SELECT order_status_name,order_status_code FROM #__{vm}_order_status ORDER BY list_order";
                
$db->query($q);
                
$order_status_code = Array();
                
$order_status_name = Array();

                while (
$db->next_record()) {
                
$order_status_code[] = $db->f("order_status_code");
                
$order_status_name[] =  $db->f("order_status_name");
                }
                for (
$i 0$i sizeof($order_status_code); $i++) {
                
echo "<option value=\"" $order_status_code[$i];
                
if (MIGS_VERIFIED_STATUS == $order_status_code[$i])
                
echo "\" selected=\"selected\">";
                
else
                
echo "\">";
                
echo $order_status_name[$i] . "</option>\n";
                    }
?>

                    </select>
            </td>
            <td>Select the order status to which the actual order is set, if the MIGS Transaction was successful.
            If using download selling options: select the status which enables the download (then the customer is instantly notified about the download via e-mail).
            </td>
        </tr>
            <tr>
            <td><strong>Order Status for failed transactions</strong></td>
            <td>
                <select name="MIGS_INVALID_STATUS" class="inputbox" >
                <?php
                
for ($i 0$i sizeof($order_status_code); $i++) {
                
echo "<option value=\"" $order_status_code[$i];
                
if (MIGS_INVALID_STATUS == $order_status_code[$i])
                
echo "\" selected=\"selected\">";
                
else
                
echo "\">";
                
echo $order_status_name[$i] . "</option>\n";
                    } 
?>

                    </select>
            </td>
            <td>Select an order status for failed MIGS Transactions.</td>
        </tr>
<?
?>
      </table>
   <?php
   
// return false if there's no configuration
   
return true;
}

function has_configuration() {
// return false if there's no configuration
return true;
}

/**
* Returns the "is_writeable" status of the configuration file
* @param void
* @returns boolean True when the configuration file is writeable, false when not
*/
function configfile_writeable() {
return is_writeableCLASSPATH."payment/".$this->classname.".cfg.php" );
}

/**
* Returns the "is_readable" status of the configuration file
* @param void
* @returns boolean True when the configuration file is writeable, false when not
*/
function configfile_readable() {
return is_readableCLASSPATH."payment/".$this->classname.".cfg.php" );
}
/**
* Writes the configuration file for this payment method
* @param array An array of objects
* @returns boolean True when writing was successful
*/
function write_configuration( &$d ) {

$my_config_array = array("virtualPaymentClientURL" => $d['virtualPaymentClientURL'],
"vpc_Version" => $d['vpc_Version'],
"vpc_Command" => $d['vpc_Command'],
"vpc_AccessCode" => $d['vpc_AccessCode'],
"vpc_Merchant" => $d['vpc_Merchant'],
"vpc_Locale" => $d['vpc_Locale'],
"MIGS_VERIFIED_STATUS" => $d["MIGS_VERIFIED_STATUS"],
"MIGS_INVALID_STATUS" => $d["MIGS_INVALID_STATUS"],
//asterix
"vpc_SecureHash" => $d["vpc_SecureHash"]
);
$config "<?php\n";
$config .= "defined('_VALID_MOS') or die('Direct Access to this location is not allowed.'); \n\n";
foreach( $my_config_array as $key => $value ) {
$config .= "define ('$key', '$value');\n";
}

$config .= "?>
";

if ($fp = fopen(CLASSPATH ."payment/".$this->classname.".cfg.php", "w")) {
fputs($fp, $config, strlen($config));
                        fclose ($fp);
                        return true;
                }
                else {
                        return false;
                }
        }

        /**************************************************************************
        ** name: process_payment()
** created by: findshorty.com
** description: process transaction with MasterCard Internet Gateway Service
** parameters: $order_number, the number of the order, we're processing here
**            $order_total, the total $ of the order
** returns:
***************************************************************************/
function process_payment($order_number, $order_total, &$d) {

global $vendor_mail, $vendor_currency, $VM_LANG, $vmLogger;
$database = new ps_DB;
$ps_vendor_id = $_SESSION["ps_vendor_id"];
$auth = $_SESSION['auth'];
$ps_checkout = new ps_checkout;

/*** Get the Configuration File for MIGS ***/
require_once(CLASSPATH ."payment/".$this->classname.".cfg.php");

// Get the Transaction Key securely from the database

$database->query( "SELECT DECODE(payment_passkey,'".ENCODE_KEY."') as passkey FROM #__{vm}_payment_method WHERE payment_class='".$this->classname."' AND shopper_group_id='".$auth['shopper_group_id']."'" );
$transaction = $database->record[0];
if( empty($transaction->passkey)) {
$vmLogger->err( $VM_LANG->_PHPSHOP_PAYMENT_ERROR.'. Technical Note: The required transaction key is empty! The payment method settings must be reviewed.' );
return false;
}
$host = virtualPaymentClientURL;

// MIGS vars to send
$formdata = array (
'vpc_Version' => vpc_Version,
'vpc_Command' => vpc_Command,
'vpc_MerchTxnRef' => $order_number,
'vpc_AccessCode' => vpc_AccessCode,
'vpc_Merchant' => vpc_Merchant,
'vpc_SecureHash' => $transaction->passkey,

// Gateway Response Configuration

// Invoice Information
'vpc_OrderInfo' => $order_number,
//asterix added
'vpc_MerchantTransactionReference' => $order_number,

// Transaction Data
'vpc_Amount' => $order_total*100,
'vpc_CardNum' => $_SESSION['ccdata']['order_payment_number'],
'vpc_CardSecurityCode' => $_SESSION['ccdata']['credit_card_code'],
'vpc_CardExp' => (substr($_SESSION['ccdata']['order_payment_expire_year'],2)) . ($_SESSION['ccdata']['order_payment_expire_month']),

);
ksort($formdata);
$md5HashData = $transaction->passkey;
//build the post string
$poststring = '';
foreach($formdata as $key => $val){
$poststring .= urlencode($key) . "=" . urlencode($val) . "&";
$md5HashData .= $val;
}
// strip off trailing ampersand
$poststring = substr($poststring, 0, -1)."&vpc_SecureHash=".strtoupper(md5($md5HashData));

if( function_exists( "curl_init" )) {

$vmLogger->debug( 'Using the cURL library for communicating with '.$host );

$CR = curl_init();
curl_setopt($CR, CURLOPT_URL, "https://".$host);
curl_setopt($CR, CURLOPT_POST, 1);
curl_setopt($CR, CURLOPT_FAILONERROR, true);
curl_setopt($CR, CURLOPT_POSTFIELDS, $poststring);
//curl_setopt($CR, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($CR, CURLOPT_RETURNTRANSFER, 1);

// No PEER certificate validation...as we don't have
// a certificate file for it to authenticate the host against!
//curl_setopt($CR, CURLOPT_SSL_VERIFYPEER, 0);
//curl_setopt($CR, CURLOPT_SSLCERT , "/usr/locale/xxxx/clientcertificate.pem");

$result = curl_exec( $CR );

$error = curl_error( $CR );
if( !empty( $error )) {
$vmLogger->err( $error );
$html = "<br/><span class=\"message\">".$VM_LANG->_PHPSHOP_PAYMENT_INTERNAL_ERROR." MIGS</span>";
return false;
}
else {
//echo $result; exit();
}
curl_close( $CR );
} else {
// Not sure MIGS allows following
}
// extract array from returned string output
$responsearr = explode("&", $result);
$response = array();
foreach($responsearr as $var) {
$tarr = explode("=",$var);
$response[$tarr[0]] = $tarr[1];
}

$vmLogger->debug('Beginning to analyse the response from '.$host);

$vpc_Txn_Secure_Hash = $response["vpc_SecureHash"];
//unset($response["vpc_SecureHash"]);
// set a flag to indicate if hash has been validated
$errorExists = false;
if (strlen($transaction->passkey) > 0 && strlen($vpc_Txn_Secure_Hash) > 0 && $response["vpc_TxnResponseCode"] != "7" && $response["vpc_TxnResponseCode"] != "No Value Returned") {
$md5HashData = $transaction->passkey;
ksort($response);
    // sort all the incoming vpc response fields and leave out any with no value
    foreach($response as $key => $value) {
        if ($key != "vpc_SecureHash" or strlen($value) > 0) {
            $md5HashData .= $value;
        }
    }
   
    // Validate the Secure Hash (remember MD5 hashes are not case sensitive)
// This is just one way of displaying the result of checking the hash.
// In production, you would work out your own way of presenting the result.
// The hash check is all about detecting if the data has changed in transit.
    if (strtoupper($vpc_Txn_Secure_Hash) == strtoupper(md5($md5HashData))) {
// Secure Hash validation succeeded, add a data field to be displayed
// later.

$vmLogger->debug("Secure Hash validated");
    } else {
        // Secure Hash validation failed, add a data field to be displayed
        // later.
        $errorExists = true;
$vmLogger->err("Secure Hash validation failed");
$vmLogger->err( strtoupper(md5($md5HashData)) );
$vmLogger->err( strtoupper($vpc_Txn_Secure_Hash) );
    }
} else {
    // Secure Hash was not validated, add a data field to be displayed later.
    $vmLogger->debug("Secure Hash Not Calculated");
}

// Approved - Success!
if ($response["vpc_TxnResponseCode"] == '0' && !$errorExists) {
$d["order_payment_log"] = $VM_LANG->_PHPSHOP_PAYMENT_TRANSACTION_SUCCESS.": ";
//$d["order_payment_log"] .= $response[3];

$vmLogger->debug( $d['order_payment_log']);

// Catch Transaction Number
$d["order_payment_trans_id"] = $response["vpc_TransactionNo"];

return true;
} else {
// log errors
// Modified by Asterix - www.imagineer.net.au. Display the correct error codes for failed transactions
if ($response["vpc_TxnResponseCode"] == '1') {
$d["order_payment_log"] = "Transaction could not be processed";
$vmLogger->err("Transaction could not be processed");
$d["order_payment_trans_id"] = $response["vpc_TransactionNo"];
} else if ($response["vpc_TxnResponseCode"] == '2') {
$d["order_payment_log"] = "Transaction declined - contact issuing bank";
$vmLogger->err("Transaction declined - contact issuing bank");
$d["order_payment_trans_id"] = $response["vpc_TransactionNo"];
} else if ($response["vpc_TxnResponseCode"] == '3') {
$d["order_payment_log"] = "No reply from Processing Host. ANZ EGATE may be temporarily offline";
$d["order_payment_trans_id"] = $response["vpc_TransactionNo"];
$vmLogger->err("No reply from Processing Host. ANZ EGATE may be temporarily offline. Please try again.");
} else if ($response["vpc_TxnResponseCode"] == '4') {
$d["order_payment_log"] = "Card has expired";
$vmLogger->err("Card has expired");
$d["order_payment_trans_id"] = $response["vpc_TransactionNo"];
} else if ($response["vpc_TxnResponseCode"] == '5') {
$d["order_payment_log"] = "Insufficient credit";
$vmLogger->err("Insufficient credit");
$d["order_payment_trans_id"] = $response["vpc_TransactionNo"];
} else {

$vmLogger->err( str_replace("&","\n",$result) );

$d["order_payment_log"] = str_replace("&","<br/>",$result);
// Catch Transaction ID
$d["order_payment_trans_id"] = $response["vpc_TransactionNo"];
}

return false;
}
}

/**************************************************************************
** name: capture_payment()
** created by: Soeren
** description: Process a previous transaction with authorize.net, Capture the Payment
** parameters: $order_number, the number of the order, we're processing here
** returns:
***************************************************************************/
function capture_payment( &$d ) {

global $vendor_mail, $vendor_currency, $VM_LANG, $vmLogger;
$database = new ps_DB();


}

}

aussieute

#25
I'm having an issue with choosing the ps_migs as the Payment Method

I can add/edit any other of the payment methods and things get saved but not with the MIGS option.

The file dates are 8/May/2007 ... is there a later version?
Or is this something else?

More questions

Do we edit the contents of the ps_migs.cfg.php manually or should this be able to be completed via the VM admin interface?

toivo

You should be able to update the contents via the VM admin interface.  I am using the interface from ps_migs to support Bank Hosted mode of operation.
toivo
-------------------------
Suzhou, China

aussieute

Toivo am having all sorts of issues

The migs file doesn't like J1.5.3 + VM1.1.0
Getting some issues with some tables not installing and
Australia Post Module isn't functional on my install combo <grin>

Ya gotta love it <grin>

tez

#28
Seems I had already started on Joomla1.5 and VM, works okay. I started with e-commerce edition.

I can't work out what to use between the two URLs (server hosted / merchant hosted), is it a choice or can you only use whatever is relevant to your account?. Which one is it that sends to you the CBA site to input your details?

Also I had this error,
Error: . Technical Note: The required transaction key is empty! The payment method settings must be reviewed.
Is "transaction key" something auto generated per order, not based on any of my settings?. The bank error said it was above 34 characters.


Another error I had was that the vpc_MerchTxnRef and vpc_OrderInfo being sent were really massive numbers. See below. Whats up with that? It should be an order number, but mine are only about 000005 or so and the rest looks like a session ID.
vpc_MerchTxnRef=62_a79009c1f7414c7d72c7129f0b7206d8
vpc_Message=Field+vpc_OrderInfo+value+%5B62_a79009c1f7414c7d72c7129f0b7206d8%5D+is+too+long.+The+maximum+field+length+is+34+chars.
vpc_OrderInfo=62_a79009c1f7414c7d72c7129f0b7206d8

toivo

Hi,

The Server Hosted, also called the Bank Hosted mode of operation sends the customer to the bank's website.  This mode mode does not store the credit card numbers in your web server, in other words one less thing to worry about.

The ps_migs.php software in a previous post is meant to be used in the Merchant Hosted mode of operation.  I used that as a basis for configuring the options, included the Extra Info from the sample programs in the VPC Development Kit to send the card transaction, removed ps_migs from the settings of the payment method and cobbled together a module to receive the response from the gateway, write the details to a transaction log for later reconciliation and finally to  update the order status in VM.

I am now waiting for the bank and MIGS to confirm that it is OK to publish the integration code in this forum, to avoid possible copyright issues.
toivo
-------------------------
Suzhou, China