<?php

require_once "Vindicia/Soap/Vindicia.php";
require_once "Vindicia/Soap/Const.php";
// This example uses an existing account
$accountId = $argv[1];
$dryrun = $argv[2];
print "accountId is {$accountId} \n";
print "dryrun is {$dryrun} \n";
$account = new Account();
$return = $account->fetchByMerchantAccountId($accountId);
$customer = $return['data']->account;
// This example is assuming we already know it's the default PM and type is Credit Card
$pm = $customer->paymentMethods[0];
$nv = new NameValuePair();
$nv->setName('CVN');
$nv->setValue('123');
$pm->setNameValues(array($nv));
$transaction = new Transaction();
$transaction->setCurrency('USD');
$transaction->setMerchantTransactionId('testTrx-' . rand(10000, 99999));
$transaction->setAccount($customer);
$transaction_lineItem0 = new TransactionItem();
$transaction_lineItem0->setSku('RMMTEST002');
$transaction_lineItem0->setName('LineItem 1');
$transaction_lineItem0->setMerchantAutoBillItemId('foobar');
$transaction_lineItem0->setPrice('99.99');
$transaction_lineItem0->setQuantity('1');
// Campaign Code can be assigned to each individual line item:
$transaction_lineItem0->setCampaignCode('promo2');
$lineitems = array($transaction_lineItem0);
function CreateAccount($merchantAccountId, $email)
{
    $account = new Account();
    $account->setName('Migrated Customer');
    $account->setMerchantAccountId($merchantAccountId);
    // Be conscious that using real email addresses in ProdTest depending on configuration will
    // have live emails triggered and sent on billing events for the Account.
    // It is recommended that when testing in ProdTest be certain to mask real email addresses.
    $account->setEmailAddress($email);
    $account->setEmailTypePreference('html');
    $account->setWarnBeforeAutoBilling(true);
    $anyOtherHelpfulDataForCSRsWhenLookingUpAccount = new NameValuePair();
    $anyOtherHelpfulDataForCSRsWhenLookingUpAccount->setName('HelpfulData');
    $anyOtherHelpfulDataForCSRsWhenLookingUpAccount->setValue('BestCustomerEver');
    $account->setNameValues(array($anyOtherHelpfulDataForCSRsWhenLookingUpAccount));
    $address = new Address();
    $address->setAddr1('303 Twin Dolphin Drive');
    $address->setAddr2('Suite 200');
    $address->setCity('Redwood City');
    $address->setDistrict('CA');
    $address->setPostalCode('94065');
    $address->setCountry('US');
    $address->setPhone('123-456-7890');
    $srd = '';
    $account->setShippingAddress($address);
    $response = $account->update($srd);
    // Log soap id for each API call.
    //    $log->addDebug('Method = Account.update' . PHP_EOL);
    //    $log->addDebug('Soap Id = ' . $response['data']->return->soapId . PHP_EOL);
    //    $log->addDebug('Return Code = ' . $response['returnCode'] . PHP_EOL);
    //    $log->addDebug('Return String = ' . $response['returnString'] . PHP_EOL);
    if ($response['returnCode'] == 200) {
        print "Call succeeded" . PHP_EOL;
    } else {
        print "Call failed" . PHP_EOL;
        print_r($response);
    }
}
function hoaAccountUpdatePaymentMethod($merchantAccountId = null, $merchantPaymentMethodId = null)
{
    $creditCardAccount = '5454541111111111';
    $paymentType = 'CreditCard';
    $cvn = '111';
    $exp = '201805';
    $email = get_unique_value() . '@nomail.com';
    $successUrl = 'http://good.com';
    $errorUrl = 'http://bad.com';
    $HOAmethod = 'Account_UpdatePaymentMethod';
    $HOAurl = str_replace("soap", "secure", VIN_SOAP_HOST) . "/vws.html";
    $HOAversion = '5.0';
    // VIN_SOAP_CLIENT_VERSION
    $ipAddress = '127.0.0.1';
    $name = 'John Vindicia';
    $addr1 = '303 Twin Dolphin Drive';
    $city = 'Redwood City';
    $district = 'CA';
    $postalCode = '94065';
    $country = 'US';
    # Create a new WebSession object
    $webSession = new WebSession();
    # Set the WebSession parameters
    $webSession->setReturnURL($successUrl);
    $webSession->setErrorURL($errorUrl);
    $webSession->setIpAddress($ipAddress);
    $webSession->setMethod($HOAmethod);
    $webSession->setVersion($HOAversion);
    if (is_null($merchantAccountId)) {
        $merchantAccountId = 'account-2015-02-10_02_55_50';
    }
    if (is_null($merchantPaymentMethodId)) {
        $merchantPaymentMethodId = 'pm-2015-02-10_02_55_50';
    }
    // Step 2: start configuring the WebSession with the parameters we want to have
    $nvp1 = new NameValuePair();
    $nvp1->setName('vin_Account_merchantAccountId');
    $nvp1->setValue($merchantAccountId);
    // so that we can use the existing account
    $nvp2 = new NameValuePair();
    $nvp2->setName('vin_PaymentMethod_merchantPaymentMethodId');
    $nvp2->setValue($merchantPaymentMethodId);
    $nvp3 = new NameValuePair();
    $nvp3->setName('vin_PaymentMethod_type');
    $nvp3->setValue($paymentType);
    $webSession->setPrivateFormValues(array($nvp1, $nvp2, $nvp3));
    $nvp7 = new NameValuePair();
    $nvp7->setName('Account_updatePaymentMethod_updateBehavior');
    $nvp7->setValue('CatchUp');
    $nvp8 = new NameValuePair();
    $nvp8->setName('Account_updatePaymentMethod_replaceOnAllAutoBills');
    $nvp8->setValue('false');
    $nvp9 = new NameValuePair();
    $nvp9->setName('Account_updatePaymentMethod_ignoreAvsPolicy');
    $nvp9->setValue('false');
    $nvp10 = new NameValuePair();
    $nvp10->setName('Account_updatePaymentMethod_ignoreCvnPolicy');
    $nvp10->setValue('false');
    $webSession->setMethodParamValues(array($nvp7, $nvp8, $nvp9, $nvp10));
    // now, create the session and generate it's session ID
    $response = $webSession->initialize();
    print_r($response);
    # Check to see that the initialize succeeded
    #
    if ($response['returnCode'] == 200) {
        # The VID of the WebSession object serves as session id
        #
        $vin_WebSession_vid = $response['data']->session->getVID();
    } else {
        print_r($response);
        return;
    }
    # populate accountHolderName with same value as on billingAddress:
    $post['vin_PaymentMethod_accountHolderName'] = $post['vin_PaymentMethod_billingAddress_name'] = $name;
    $post['vin_PaymentMethod_billingAddress_addr1'] = $addr1;
    $post['vin_PaymentMethod_billingAddress_city'] = $city;
    $post['vin_PaymentMethod_billingAddress_district'] = $district;
    $post['vin_PaymentMethod_billingAddress_postalCode'] = $postalCode;
    $post['vin_PaymentMethod_billingAddress_country'] = $country;
    $post['vin_Account_emailAddress'] = $email;
    $post['vin_PaymentMethod_creditCard_account'] = $creditCardAccount;
    $post['vin_PaymentMethod_creditCard_expirationDate'] = $exp;
    $post['vin_PaymentMethod_nameValues_cvn'] = $cvn;
    $post['vin_WebSession_vid'] = $vin_WebSession_vid;
    # Copy the BillingAddress to the ShippingAddress to improve
    # Chargeback dispute success. Visa will deny disputed Chargeback
    # for many reasons. A missing ShippingAddress, even though there
    # is nothing being shipped, is commonly one of those reasons.
    # This can be done with JavaScript on the checkout form.
    #
    $post['vin_Account_name'] = $post['vin_PaymentMethod_billingAddress_name'];
    $post['vin_Account_shippingAddress_name'] = $post['vin_PaymentMethod_billingAddress_name'];
    $post['vin_Account_shippingAddress_addr1'] = $post['vin_PaymentMethod_billingAddress_addr1'];
    $post['vin_Account_shippingAddress_city'] = $post['vin_PaymentMethod_billingAddress_city'];
    $post['vin_Account_shippingAddress_district'] = $post['vin_PaymentMethod_billingAddress_district'];
    $post['vin_Account_shippingAddress_county'] = $post['vin_PaymentMethod_billingAddress_county'];
    $post['vin_Account_shippingAddress_postalCode'] = $post['vin_PaymentMethod_billingAddress_postalCode'];
    $post['vin_Account_shippingAddress_country'] = $post['vin_PaymentMethod_billingAddress_country'];
    $post['vin_Account_shippingAddress_phone'] = $post['vin_PaymentMethod_billingAddress_phone'];
    # Create the curl command line for exec by looping through the
    # $post array
    #
    $curlopts = "";
    foreach ($post as $name => $value) {
        $curlopts .= " --data-urlencode {$name}=\"{$value}\"";
    }
    print "<b><i>SOAP URL</i></b>: " . VIN_SOAP_HOST . PHP_EOL;
    # Do the POST
    #
    print "Posting to <b>HOA URL</b>: " . $HOAurl . PHP_EOL;
    print PHP_EOL;
    exec("curl -s {$curlopts} " . $HOAurl, $curlout, $curlret);
    # this line is only here to support testing with a single PHP file:
    $_GET = simulate_get($curlout);
    # the above function established the $_GET array to be the same as
    # what PHP by default populates in the $_GET array when the returnURL
    # page is a separate PHP file, and is here to support testing with
    # a single PHP file.
    #---------------------------------------------------------------------------
    #
    #	PHP specific code handling of HOA WebSession Method finalize processing
    #	------------------------------------------------------------------------
    #
    # The finalize call returns an updated WebSession object.  This
    # is correct in that it refers to the WebSession.finalize soap request and the
    # WebSession.finalizeResponse soap response as defined in the WSDL and Online
    # Soap Documentation at:
    #
    #	http://developer.vindicia.com/docs/soap/index.html?ver=9.0
    #
    # However, specific to the CashBox PHP Client library, this translates into
    # the mapping into the PHP API method to invoke the WebSession.finalize soap
    # request, and the WebSession.finalizeResponse object containing the returned
    # WebSession object may be accessed from the response:
    #
    # 1) PHP API method to invoke the WebSession.finalize soap request:
    #
    #	$response = WebSession->finalize()
    #
    # 2) WebSession.finalizeResponse soap response object containing WebSession:
    #
    #	Following a successful call to finalize(), the values from $response, the
    #	WebSession.finalizeResponse soap response, are then accessible by referencing
    #	the nested objects in the response corresponding to the hierarchy in the WSDL.
    #
    # Note that the WebSession data members from the WSDL are documented in the
    # Online Soap documentation for the WebSession datatype below:
    #
    #	http://developer.vindicia.com/docs/soap/AllDataTypes.html?pf=1&ver=9.0&type=WebSession
    #
    # ---
    #
    # HOA uses the following 3 steps:
    #		1. WebSession.initialize (initialize & obtain a sessionId for the WebSession)
    #		2. HOA Form Post (Present Form to buyer with hidden sessionId, buyer posts to HOA)
    #		3. Redirect to HOA success page (sessionId from redirect for WebSession.finalize)
    #
    # Below describes the handling of Step 3, HOA success page,
    # where the sessionId from the redirect URL is passed to the finalize() method below:
    #
    # 6.	Upon payment form submission if customer’s browser is redirected to the Return URL
    #      hosted by you and specified in the WebSession object. On this page finalize the
    #      WebSession object as follows:
    #
    # 		a.	The redirect URL string contains WebSession’s VID as the value associated with
    #			name ‘session_id’.  Use the VID to make the finalize() call below:
    #
    # ---
    #
    #	HOA WebSession Method: Account_UpdatePaymentMethod
    #
    #---------------------------------------------------------------------------
    #
    # HOA Success Page:  Need to call WebSession.finalize() to invoke internal
    # soap call to Account.updatePaymentMethod() as indicated by the value of
    # WebSession Method (Account_UpdatePaymentMethod), using the parameters already
    # contained in the WebSession object stored in the database (on the HOA/CashBox server).
    #
    #
    # Documentation of Soap Objects returned in PHP code (displayed by print_r($response)):
    #
    # To see the data members in the WebSession (& all other CashBox Soap objects),
    # please review the Online Soap Documentation at the link below:
    #
    #	http://developer.vindicia.com/docs/soap/index.html?ver=9.0
    #
    #	Within the Online Soap Documentation, the following links are pertinent:
    #
    #	All Data Types that are returned by PHP (as seen by print_r($response) are found at:
    #		http://developer.vindicia.com/docs/soap/AllDataTypes.html?ver=9.0
    #
    #	The WebSession methods (including WebSession.initialize() & WebSession.finalize():
    #		http://developer.vindicia.com/docs/soap/WebSession.html?ver=9.0
    #
    #	Specifically for the code below, the WebSession Data Type definition:
    #		http://developer.vindicia.com/docs/soap/AllDataTypes.html?pf=1&ver=9.0&type=WebSession
    #
    # With the above Documentation of the CashBox Soap Objects in mind, the source code
    # of the PHP library itself reveals the actual syntax of the PHP methods involved in
    # setting data members on the CashBox Soap Objects represented in PHP Objects created
    # & used in this sample code.
    #
    # The source code for the WebSession Object in the PHP library is found under
    # 		Vindicia/Soap/WebSession.php within the PHP library for example.
    #
    #-Step 3-----------------------------------------------------
    #-Step 3-
    #-Step 3- This code should be on the returnURL page
    #-Step 3-
    #-Step 3- Nothing has been committed until the WebSession gets
    #-Step 3- finalized. This is done in the returnURL page code. For
    #-Step 3- example, the returnURL is a confirmation page and when
    #-Step 3- the user clicks a confirmation button the form action
    #-Step 3- is a page that performs all the actual finalize steps.
    #-Step 3-
    print "Parameters from redirect URL:" . PHP_EOL;
    print_r($_GET);
    $session_id = $_GET['session_id'];
    $webSession = new WebSession();
    $webSession->setVid($session_id);
    # initialize call timestamp in case of error for support information below:
    date_default_timezone_set("America/Los_Angeles");
    $call_timestamp = date("c");
    // c - The ISO-8601 date (e.g. 2015-06-17T16:34:42+00:00)
    $response = $webSession->finalize();
    print_r($response);
    $session = $response['data']->session;
    # WebSession.finalizeResponse.return.returnCode
    $returnCode = $response['returnCode'];
    # WebSession.finalizeResponse.return.returnString
    $returnString = $response['returnString'];
    # WebSession.finalizeResponse.return.soapId
    $finalize_soapId = $response['data']->return->soapId;
    print $call_timestamp . " WebSession.finalize soapId: " . $finalize_soapId . "\n";
    # log soap id if available in the return values of this call
    # WebSession.apiReturn.returnCode
    $apiReturnCode = $session->apiReturn->returnCode;
    # WebSession.apiReturn.returnString
    $apiReturnString = $session->apiReturn->returnString;
    # WebSession.apiReturnValues
    $apiReturnValues = $session->apiReturnValues;
    # WebSession.apiReturnValues.accountUpdatePaymentMethod
    $accountUpdatePaymentMethod = $apiReturnValues->accountUpdatePaymentMethod;
    # WebSession.apiReturnValues.accountUpdatePaymentMethod.validated
    $validated = $accountUpdatePaymentMethod->validated;
    if ($response['returnCode'] != '200') {
        print $response['returnCode'] . PHP_EOL;
        print $returnString . PHP_EOL;
        print $apiReturnCode . PHP_EOL;
        print $apiReturnString . PHP_EOL;
    } else {
        print $apiReturnCode . PHP_EOL;
        print $apiReturnString . PHP_EOL;
        if ($apiReturnCode == "200") {
            print PHP_EOL . 'Updated Credit Card. Account=' . $merchantAccountId . ' PaymentMethod=' . $merchantPaymentMethodId . PHP_EOL;
        } else {
            if ($apiReturnCode = "261") {
                print "All active AutoBills were updated. AutoBills which are both expired and Suspended cannot be updated.\n";
            } else {
                if ($apiReturnCode == "400") {
                    print "One of the following:\n• Invalid Payment Method Type. (You cannot change the Payment Method Type on an existing Payment Method.)\n• No PaymentMethod specified in arguments.\n• Data validation error Failed to create Payment-Type-Specific Payment Record: Credit Card conversion failed: Credit Card failed Luhn check.\n";
                } else {
                    if ($apiReturnCode == "402") {
                        print "One of the following:\n• PaymentMethod failed validation.\n• Error attempting to authorize card.\n• Unable to authorize card.\n";
                    } else {
                        if ($apiReturnCode = "404") {
                            print "No match found error-description.\n Returned if CashBox cannot find an account that matches the input in the Vindicia database.\n";
                        } else {
                            if ($apiReturnCode = "407") {
                                print "Transaction cannot be processed due to Failed AVS policy evaluation\n";
                            } else {
                                if ($apiReturnCode = "408") {
                                    print "Transaction cannot be processed due to Failed CVN policy evaluation\n";
                                } else {
                                    if ($apiReturnCode = "409") {
                                        print "AutoBill creation failed: due to AVS and CVV Check Failed\n";
                                    } else {
                                        if ($apiReturnCode = "410") {
                                            print "AutoBill creation failed: due to AVS and CVV Check not being able to be performed\n";
                                        } else {
                                            print "Error while making call to Vindicia CashBox\n";
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    return array('apiReturnCode' => $apiReturnCode, 'validated' => $validated);
}
    $webSession->setPrivateFormValues(array($acct_id, $paym_id, $pmt_type));
    #------------------------------------------------------------
    # Set any parameters specific for the Method we are
    # calling in the WebSession.
    #
    $nvp7 = new NameValuePair();
    $nvp7->setName('Account_updatePaymentMethod_updateBehavior');
    $nvp7->setValue('CatchUp');
    $nvp8 = new NameValuePair();
    $nvp8->setName('Account_updatePaymentMethod_replaceOnAllAutoBills');
    $nvp8->setValue('true');
    $nvp9 = new NameValuePair();
    $nvp9->setName('Account_updatePaymentMethod_ignoreAvsPolicy');
    $nvp9->setValue('false');
    $nvp10 = new NameValuePair();
    $nvp10->setName('Account_updatePaymentMethod_ignoreCvnPolicy');
    $nvp10->setValue('false');
    $webSession->setMethodParamValues(array($nvp7, $nvp8, $nvp9, $nvp10));
    $response = $webSession->initialize();
    if ($response['returnCode'] == 200) {
        $sessionId = $response['data']->session->getVID();
        return $sessionId;
    }
    // Add error checking and logging of soap ids
});
//Example Method for WebSession Finalize
$app->get('/wsfinalizeaccountupdatepaymentmethod', function (Request $request) use($app) {
    $webSession = new WebSession();
    $websession_id = $request->query->get('vin_WebSession_VID');
    $webSession->setVID($websession_id);
    $response = $webSession->finalize();
function hoaTransactionAuthThenCapture()
{
    $uniqueValue = get_unique_value();
    $merchantAccountId = 'account-' . $uniqueValue;
    $merchantTransactionId = 't-' . $uniqueValue;
    if (fail_if_merchant_transaction_id_too_long($merchantTransactionId)) {
        return;
    }
    $merchantPaymentMethodId = 'pm-' . $uniqueValue;
    $creditCardAccount = '5454541111111111';
    $paymentType = 'CreditCard';
    $cvn = '111';
    $exp = '201801';
    $email = get_unique_value() . '@nomail.com';
    $successUrl = 'http://good.com';
    $errorUrl = 'http://bad.com';
    $HOAmethod = 'Transaction_Auth';
    $HOAurl = 'https://secure.prodtest.sj.vindicia.com/vws';
    $HOAversion = '5.0';
    $ipAddress = '127.0.0.1';
    $name = 'John Vindicia';
    $addr1 = '303 Twin Dolphin Drive';
    $city = 'Redwood City';
    $district = 'CA';
    $postalCode = '94065';
    $country = 'US';
    #------------------------------------------------------------
    #-Step 1-
    #-Step 1- Initialize the WebSession before the PaymentMethod
    #-Step 1- form is displayed to the user
    #-Step 1-
    #
    # Create a new WebSession object
    $webSession = new WebSession();
    # Set the WebSession parameters
    $webSession->setReturnURL($successUrl);
    $webSession->setErrorURL($errorUrl);
    $webSession->setIpAddress($ipAddress);
    $webSession->setMethod($HOAmethod);
    $webSession->setVersion($HOAversion);
    #------------------------------------------------------------
    # Set PrivateFormValues. These are hidden fields in the POST
    # that we want to protect from hacking. If the value in the
    # POST does not match the value set during initialization,
    # the WebSession.finalize will fail
    //    $account_VID = $account->VID;
    //
    //    $nameVals[0] = new NameValuePair();
    //    $nameVals[0]->setName('Account_VID');
    //    $nameVals[0]->setValue($account_VID); // so that we can use the existing account
    $tx_id = new NameValuePair();
    $tx_id->setName('vin_Transaction_merchantTransactionId');
    $tx_id->setValue($merchantTransactionId);
    // so that we can use the existing account
    # Your ID for this user
    $acct_id = new NameValuePair();
    $acct_id->setName("vin_Account_merchantAccountId");
    $acct_id->setValue($merchantAccountId);
    # Your ID for this PaymentMethod
    $paym_id = new NameValuePair();
    $paym_id->setName("vin_PaymentMethod_merchantPaymentMethodId");
    $paym_id->setValue($merchantPaymentMethodId);
    $pmt_type = new NameValuePair();
    $pmt_type->setName("vin_PaymentMethod_type");
    $pmt_type->setValue($paymentType);
    # Add the PrivateFormValues to the WebSession
    $webSession->setPrivateFormValues(array($tx_id, $acct_id, $paym_id, $pmt_type));
    #------------------------------------------------------------
    # Set any parameters specific for the Method we are
    # calling in the WebSession.
    #
    $minChargebackProbability = new NameValuePair();
    $minChargebackProbability->setName("Transaction_Auth_minChargebackProbability");
    $minChargebackProbability->setValue("70");
    $dryRun = new NameValuePair();
    $dryRun->setName("Transaction_Auth_dryRun");
    $dryRun->setValue("false");
    $sendEmailNotification = new NameValuePair();
    $sendEmailNotification->setName("Transaction_Auth_sendEmailNotification");
    $sendEmailNotification->setValue("true");
    // Transaction_Auth takes in one more parameter - campaignCode
    // We can collect campaign code from the payment form and set
    // prior to WebSession.Finalize, or pass it in here prior to WebSession.Initialize.
    $campaign = 'CampaignXYZ';
    //    $campaignCodeNVP = new NameValuePair();
    //    $campaignCodeNVP->setName("Transaction_Auth_campaignCode");
    //    $campaignCodeNVP->setValue($campaign);
    $webSession->setMethodParamValues(array($sendEmailNotification, $minChargebackProbability, $dryRun));
    # Initialize the WebSession
    #
    $response = $webSession->initialize();
    # Check to see that the initialize succeeded
    #
    if ($response['returnCode'] == 200) {
        # The VID of the WebSession object serves as session id
        #
        $vin_WebSession_vid = $response['data']->session->getVID();
    } else {
        print $response;
        return;
    }
    #------------------------------------------------------------
    #-Step 2-
    #-Step 2- This is the payment method FORM and the HOA POST
    #-Step 2-
    # Fields on the checkout FORM
    # User supplied input
    //    $post['vin_PaymentMethod_merchantPaymentMethodId'] =
    //                $merchantPaymentMethodId;
    $post['vin_PaymentMethod_accountHolderName'] = $post['vin_PaymentMethod_billingAddress_name'] = $name;
    $post['vin_PaymentMethod_billingAddress_addr1'] = $addr1;
    $post['vin_PaymentMethod_billingAddress_city'] = $city;
    $post['vin_PaymentMethod_billingAddress_district'] = $district;
    $post['vin_PaymentMethod_billingAddress_postalCode'] = $postalCode;
    $post['vin_PaymentMethod_billingAddress_country'] = $country;
    $post['vin_Account_emailAddress'] = $email;
    $post['vin_PaymentMethod_creditCard_account'] = $creditCardAccount;
    $post['vin_PaymentMethod_creditCard_expirationDate'] = $exp;
    $post['vin_PaymentMethod_nameValues_cvn'] = $cvn;
    $post['vin_Transaction_transactionItems_0_sku'] = 'Item 1';
    $post['vin_Transaction_transactionItems_0_name'] = 'Item 1 Description';
    $post['vin_Transaction_transactionItems_0_price'] = '99';
    $post['vin_Transaction_transactionItems_0_quantity'] = '1';
    # Hidden fields in the checkout FORM
    #
    $post['vin_WebSession_vid'] = $vin_WebSession_vid;
    # Copy the BillingAddress to the ShippingAddress to improve
    # Chargeback dispute success. Visa will deny disputed Chargeback
    # for many reasons. A missing ShippingAddress, even though there
    # is nothing being shipped, is commonly one of those reasons.
    # This can be done with JavaScript on the checkout form.
    #
    $post['vin_Account_name'] = $post['vin_PaymentMethod_billingAddress_name'];
    $post['vin_Account_shippingAddress_name'] = $post['vin_PaymentMethod_billingAddress_name'];
    $post['vin_Account_shippingAddress_addr1'] = $post['vin_PaymentMethod_billingAddress_addr1'];
    $post['vin_Account_shippingAddress_city'] = $post['vin_PaymentMethod_billingAddress_city'];
    $post['vin_Account_shippingAddress_district'] = $post['vin_PaymentMethod_billingAddress_district'];
    $post['vin_Account_shippingAddress_county'] = $post['vin_PaymentMethod_billingAddress_county'];
    $post['vin_Account_shippingAddress_postalCode'] = $post['vin_PaymentMethod_billingAddress_postalCode'];
    $post['vin_Account_shippingAddress_country'] = $post['vin_PaymentMethod_billingAddress_country'];
    $post['vin_Account_shippingAddress_phone'] = $post['vin_PaymentMethod_billingAddress_phone'];
    // If you have a Campaign Code form value...
    //$post['Transaction_Auth_campaignCode'] = $campaign;
    # Create the curl command line for exec by looping through the
    # $post array
    #
    $curlopts = "";
    foreach ($post as $name => $value) {
        $curlopts .= " --data-urlencode {$name}=\"{$value}\"";
    }
    # Do the POST
    #
    exec("curl -s {$curlopts} " . $HOAurl, $curlout, $curlret);
    #-Step 3-----------------------------------------------------
    #-Step 3-
    #-Step 3- This code should be on the returnURL page
    #-Step 3-
    #-Step 3- Nothing has been committed until the WebSession gets
    #-Step 3- finalized. This is done in the returnURL page code. For
    #-Step 3- example, the returnURL is a confirmation page and when
    #-Step 3- the user clicks a confirmation button the form action
    #-Step 3- is a page that performs all the actual finalize steps.
    #-Step 3-
    #------------------------------------------------------------
    # This is only necessary for this CLI implementation.
    #
    # Flatten the output from exec so we can search it. The response
    # from a successful HOA POST should be a 302 page that contains
    # our returnURL with the WebSessionVID as the query string.
    #
    if (php_sapi_name() == "cli") {
        $curlresp = implode("\n", $curlout);
    }
    #
    #------------------------------------------------------------
    # For CLI, use the WebSessionId we stored in the POST values
    # for curl. For everything else, retrieve the WebSessionId
    # from the URL query string on the redirect to the returnURL
    #
    if (php_sapi_name() == "cli") {
        $session_id = $post['vin_WebSession_vid'];
    } else {
        $session_id = $_GET['session_id'];
    }
    $campaignCode = $post['Transaction_Auth_campaignCode'];
    if ($campaignCode != null) {
        $fetchedWebSession = new WebSession();
        $response = $fetchedWebSession->fetchByVid($session_id);
        $response_object = $response['data'];
        $return_code = $response['returnCode'];
        $websession = $response_object->session;
        if ($return_code != "200" || $websession->apiReturn->returnCode != "200") {
            print $response;
        }
    }
    $webSession = new WebSession();
    $webSession->setVid($session_id);
    if ($campaignCode != null) {
        $campaignCodeNVP = new NameValuePair();
        $campaignCodeNVP->setName("Transaction_Auth_campaignCode");
        $campaignCodeNVP->setValue($campaignCode);
        $webSession->setMethodParamValues(array($campaignCodeNVP));
    }
    $response = $webSession->finalize();
    if ($response['returnCode'] != '200') {
        print $response['data']->session->apiReturn->returnCode . PHP_EOL;
        print $response['data']->session->apiReturn->returnString . PHP_EOL;
    } else {
        print "returnCode=" . $response['data']->session->apiReturn->returnCode . PHP_EOL;
        print "returnString=" . $response['data']->session->apiReturn->returnString . PHP_EOL;
        if ($response['data']->session->apiReturn->returnCode == "200") {
            $returnTransaction = $response['data']->session->apiReturnValues->transactionAuth->transaction;
            if ($returnTransaction->statusLog[0]->status == 'Authorized') {
                print "Transaction approved\n";
                $captureTransaction = new Transaction();
                $response = $captureTransaction->capture(array($returnTransaction));
                print "returnCode=" . $response['returnCode'] . PHP_EOL;
                print "returnString=" . $response['returnString'] . PHP_EOL;
                if ($response['returnCode'] == 200) {
                    $captureResults = $response['data']->results;
                    foreach ($captureResults as $captureResult) {
                        if ($captureResult->returnCode == 200) {
                            print "Transaction with id " . $captureResult->merchantTransactionId . " was successfully captured";
                        } else {
                            print "Transaction was not successfully captured. ReturnCode=" . $captureResult->returnCode;
                        }
                    }
                } else {
                    print "Transactions were not successfully captured. ReturnCode=" . $response['returnCode'];
                }
            } else {
                if ($returnTransaction->statusLog[0]->status == 'Cancelled') {
                    print "Transaction not approved \n";
                    print "Reason code is: ";
                    print $returnTransaction->statusLog[0]->creditCardStatus->authCode;
                    print "\n";
                } else {
                    print "Error: Unexpected transaction status\n";
                }
            }
        } else {
            if ($response['data']->session->apiReturn->returnCode = "202") {
                print "Transaction cannot be processed due to taxes being temporarily unavailable\n";
            } else {
                if ($response['data']->session->apiReturn->returnCode == "400") {
                    print "Transaction cannot be processed due to data validation error\n";
                } else {
                    if ($response['data']->session->apiReturn->returnCode == "402") {
                        print "Transaction cannot be processed due to transaction error\n";
                    } else {
                        if ($response['data']->session->apiReturn->returnCode = "403") {
                            print "Transaction cannot be processed due to high fraud potential\n";
                        } else {
                            if ($response['data']->session->apiReturn->returnCode = "406") {
                                print "Transaction cannot be processed due to Chargeback risk score being higher than minChargebackProbability\n";
                            } else {
                                if ($response['data']->session->apiReturn->returnCode = "407") {
                                    print "Transaction cannot be processed due to Failed AVS policy evaluation\n";
                                } else {
                                    if ($response['data']->session->apiReturn->returnCode = "408") {
                                        print "Transaction cannot be processed due to Failed CVN policy evaluation\n";
                                    } else {
                                        print "Error while making call to Vindicia CashBox\n";
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
function hoaAutoBill()
{
    # Set the data members from the arg values
    #
    $uniqueValue = get_unique_value();
    $merchantAutoBillId = 'ab-' . $uniqueValue;
    $merchantAccountId = 'account-' . $uniqueValue;
    $merchantPaymentMethodId = 'pm-' . $uniqueValue;
    $merchantProductId = 'Video';
    $merchantBillingPlanId = 'OneMonthSubOneMonthRecurring';
    $creditCardAccount = '5454541111111111';
    $paymentType = 'CreditCard';
    $cvn = '111';
    $exp = '201501';
    $email = get_unique_value() . '@nomail.com';
    $successUrl = 'http://good.com';
    $errorUrl = 'http://bad.com';
    $HOAmethod = 'AutoBill_Update';
    $HOAurl = 'https://secure.prodtest.sj.vindicia.com/vws';
    $HOAversion = '5.0';
    $ipAddress = '127.0.0.1';
    $name = 'John Vindicia';
    $addr1 = '303 Twin Dolphin Drive';
    $city = 'Redwood City';
    $district = 'CA';
    $postalCode = '94065';
    $country = 'US';
    #------------------------------------------------------------
    #-Step 1-
    #-Step 1- Initialize the WebSession before the PaymentMethod
    #-Step 1- form is displayed to the user
    #-Step 1-
    #
    # Create a new WebSession object
    $webSession = new WebSession();
    # Set the WebSession parameters
    $webSession->setReturnURL($successUrl);
    $webSession->setErrorURL($errorUrl);
    $webSession->setIpAddress($ipAddress);
    $webSession->setMethod($HOAmethod);
    $webSession->setVersion($HOAversion);
    #------------------------------------------------------------
    # Set PrivateFormValues. These are hidden fields in the POST
    # that we want to protect from hacking. If the value in the
    # POST does not match the value set during initialization,
    # the WebSession.finalize will fail
    # Your ID for this AutoBill
    $ab_id = new NameValuePair();
    $ab_id->setName("vin_AutoBill_merchantAutoBillId");
    $ab_id->setValue($merchantAutoBillId);
    # Your ID for this user
    $acct_id = new NameValuePair();
    $acct_id->setName("vin_Account_merchantAccountId");
    $acct_id->setValue($merchantAccountId);
    # Permissible values for the Product that is going to be purchased
    //    $prod_id = new NameValuePair();
    //    $prod_id->setName("vin_Product_merchantProductId");
    //    $prod_id->setValue($merchantProductId);
    # Permissible values for the Product that is going to be purchased
    $prod_id = new NameValuePair();
    $prod_id->setName("vin_AutoBill_items_0_Product_merchantProductId");
    $prod_id->setValue($merchantProductId);
    # Permissible values for BillingPlan to be used
    $plan_id = new NameValuePair();
    $plan_id->setName("vin_BillingPlan_merchantBillingPlanId");
    $plan_id->setValue($merchantBillingPlanId);
    # Your ID for this PaymentMethod
    $paym_id = new NameValuePair();
    $paym_id->setName("vin_PaymentMethod_merchantPaymentMethodId");
    $paym_id->setValue($merchantPaymentMethodId);
    $pmt_type = new NameValuePair();
    $pmt_type->setName("vin_PaymentMethod_type");
    $pmt_type->setValue($paymentType);
    # Add the PrivateFormValues to the WebSession
    $webSession->setPrivateFormValues(array($ab_id, $acct_id, $prod_id, $plan_id, $paym_id, $pmt_type));
    #------------------------------------------------------------
    # Set any parameters specific for the Method we are
    # calling in the WebSession.
    #
    $validate = new NameValuePair();
    $validate->setName("AutoBill_Update_validatePaymentMethod");
    //    $validate->setName("AutoBill_Update_validate");
    $validate->setValue("true");
    $minChargebackProbability = new NameValuePair();
    $minChargebackProbability->setName("AutoBill_Update_minChargebackProbability");
    // Value of 100 turns off fraud checking.
    $minChargebackProbability->setValue("100");
    $ignoreCvnPolicy = new NameValuePair();
    $ignoreCvnPolicy->setName("AutoBill_Update_ignoreCvnPolicy");
    $ignoreCvnPolicy->setValue("false");
    $ignoreAvsPolicy = new NameValuePair();
    $ignoreAvsPolicy->setName("AutoBill_Update_ignoreAvsPolicy");
    $ignoreAvsPolicy->setValue("false");
    $dryRun = new NameValuePair();
    $dryRun->setName("AutoBill_Update_dryRun");
    $dryRun->setValue("false");
    // AutoBill_Update takes in one more parameter - campaignCode
    // We will collect campaign code from the payment form
    $webSession->setMethodParamValues(array($validate, $minChargebackProbability, $ignoreCvnPolicy, $ignoreAvsPolicy, $dryRun));
    # Initialize the WebSession
    #
    $response = $webSession->initialize();
    # Check to see that the initialize succeeded
    #
    if ($response['returnCode'] == 200) {
        # The VID of the WebSession object serves as session id
        #
        $vin_WebSession_vid = $response['data']->session->getVID();
    } else {
        print $response;
        return;
    }
    #------------------------------------------------------------
    #-Step 2-
    #-Step 2- This is the payment method FORM and the HOA POST
    #-Step 2-
    # TODO: Parameterize these from $_POST or $argv
    # Fields on the checkout FORM
    # User supplied input
    //    $post['vin_PaymentMethod_merchantPaymentMethodId'] =
    //                $merchantPaymentMethodId;
    $post['vin_PaymentMethod_accountHolderName'] = $post['vin_PaymentMethod_billingAddress_name'] = $name;
    $post['vin_PaymentMethod_billingAddress_addr1'] = $addr1;
    $post['vin_PaymentMethod_billingAddress_city'] = $city;
    $post['vin_PaymentMethod_billingAddress_district'] = $district;
    $post['vin_PaymentMethod_billingAddress_postalCode'] = $postalCode;
    $post['vin_PaymentMethod_billingAddress_country'] = $country;
    $post['vin_Account_emailAddress'] = $email;
    $post['vin_PaymentMethod_creditCard_account'] = $creditCardAccount;
    $post['vin_PaymentMethod_creditCard_expirationDate'] = $exp;
    $post['vin_PaymentMethod_nameValues_cvn'] = $cvn;
    # Hidden fields in the checkout FORM
    #
    $post['vin_WebSession_vid'] = $vin_WebSession_vid;
    // If you have a Campaign Code form value...
    //$post['AutoBill_Update_campaignCode'] = 'XYZ';
    # Copy the BillingAddress to the ShippingAddress to improve
    # Chargeback dispute success. Visa will deny disputed Chargeback
    # for many reasons. A missing ShippingAddress, even though there
    # is nothing being shipped, is commonly one of those reasons.
    # This can be done with JavaScript on the checkout form.
    #
    $post['vin_Account_name'] = $post['vin_PaymentMethod_billingAddress_name'];
    $post['vin_Account_shippingAddress_name'] = $post['vin_PaymentMethod_billingAddress_name'];
    $post['vin_Account_shippingAddress_addr1'] = $post['vin_PaymentMethod_billingAddress_addr1'];
    $post['vin_Account_shippingAddress_city'] = $post['vin_PaymentMethod_billingAddress_city'];
    $post['vin_Account_shippingAddress_district'] = $post['vin_PaymentMethod_billingAddress_district'];
    $post['vin_Account_shippingAddress_county'] = $post['vin_PaymentMethod_billingAddress_county'];
    $post['vin_Account_shippingAddress_postalCode'] = $post['vin_PaymentMethod_billingAddress_postalCode'];
    $post['vin_Account_shippingAddress_country'] = $post['vin_PaymentMethod_billingAddress_country'];
    $post['vin_Account_shippingAddress_phone'] = $post['vin_PaymentMethod_billingAddress_phone'];
    # Create the curl command line for exec by looping through the
    # $post array
    #
    $curlopts = "";
    foreach ($post as $name => $value) {
        $curlopts .= " --data-urlencode {$name}=\"{$value}\"";
    }
    # Do the POST
    #
    exec("curl -s {$curlopts} " . $HOAurl, $curlout, $curlret);
    #-Step 3-----------------------------------------------------
    #-Step 3-
    #-Step 3- This code should be on the returnURL page
    #-Step 3-
    #-Step 3- Nothing has been committed until the WebSession gets
    #-Step 3- finalized. This is done in the returnURL page code. For
    #-Step 3- example, the returnURL is a confirmation page and when
    #-Step 3- the user clicks a confirmation button the form action
    #-Step 3- is a page that performs all the actual finalize steps.
    #-Step 3-
    #------------------------------------------------------------
    # This is only necessary for this CLI implementation.
    #
    # Flatten the output from exec so we can search it. The response
    # from a successful HOA POST should be a 302 page that contains
    # our returnURL with the WebSessionVID as the query string.
    #
    if (php_sapi_name() == "cli") {
        $curlresp = implode("\n", $curlout);
    }
    #
    #------------------------------------------------------------
    # For CLI, use the WebSessionId we stored in the POST values
    # for curl. For everything else, retrieve the WebSessionId
    # from the URL query string on the redirect to the returnURL
    #
    if (php_sapi_name() == "cli") {
        $session_id = $post['vin_WebSession_vid'];
    } else {
        $session_id = $_GET['session_id'];
    }
    $webSession = new WebSession();
    $webSession->setVid($session_id);
    $response = $webSession->finalize();
    if ($response['returnCode'] != '200') {
        print $response;
    }
    # Note, finalize almost always returns a 200 returnCode. The real
    # test for success of the underlying API call is inspection of
    # the apiReturn and apiReturnValues objects
    # Parse out the return object from the method call
    #
    $apiReturnValues = $response['data']->session->apiReturnValues;
    # Check the returnCode of the method called.
    # See Returns for update method of AutoBill object in the API
    # Reference for possible returnCodes.
    #
    if ($response['data']->session->apiReturn->returnCode != "200") {
        //408 - AutoBill creation failed: CVV check failed
        //407 - AutoBill creation failed: AVS Check Failed
        //409 - AutoBill creation failed: AVS and CVV Check Failed
        //410 - AutoBill creation failed: AVS and CVV check could not be performed
        //402 - AutoBill creation failed: Card authorization failed
        //400 - AutoBill creation failed
        print $apiReturnValues;
    }
    print 'success';
    print $response['data']->session->apiReturn->soapId . " AutoBill >" . $merchantAutoBillId . "< created for Account >" . $merchantAccountId . "< using PaymentMethod >" . $merchantPaymentMethodId . "<  AuthCode->" . $response['data']->session->apiReturnValues->autoBillUpdate->authStatus->creditCardStatus->getAuthCode() . "<  AVS->" . $response['data']->session->apiReturnValues->autoBillUpdate->authStatus->creditCardStatus->getAvsCode() . "<  CVN->" . $response['data']->session->apiReturnValues->autoBillUpdate->authStatus->creditCardStatus->getCvnCode() . "<";
}
<?php

require_once 'Vindicia/Soap/Vindicia.php';
require_once 'Vindicia/Soap/Const.php';
$parentID = $argv[1];
$child1ID = $argv[2];
$child2ID = $argv[3];
print "parent: {$parentID} \n";
print "child1: {$child1ID} \n";
print "child2: {$child2ID} \n";
$parent = new Account();
$parent->setMerchantAccountId($parentID);
$parentNvp = new NameValuePair();
$parentNvp->setName('parentAccountId');
$parentNvp->setValue($parentID);
$child1 = new Account();
$child1->setMerchantAccountId($child1ID);
$child1->setNameValues(array($parentNvp));
$child2 = new Account();
$child2->setMerchantAccountId($child2ID);
$child2->setNameValues(array($parentNvp));
// use the force flag to remove these children from a previous parent
// and assign them to this new one
//$force=true;
$force = false;
// use payerReplacementBehavior to determine if any existing autobills of these children
// should use the parents payment method, or only autobills created from here in should.
//$payerReplacementBehavior='ReplaceOnAllAutoBills';
$payerReplacementBehavior = 'ReplaceOnlyFutureAutoBills';
$response = $parent->addChildren(array($child1, $child2), $force, $payerReplacementBehavior);
print_r($response);
function finalize_paypal_AutoBill_then_transaction_auth_capture_Transaction_Items($vid)
{
    $autobill = new Autobill();
    $response = $autobill->finalizePayPalAuth($vid, true);
    if ($response['returnCode'] != '200') {
        print 'Error finalizing autobill' . PHP_EOL;
        print 'Soap Id = ' . $response['data']->return->soapId . PHP_EOL;
        print 'Return Code = ' . $response['returnCode'] . PHP_EOL;
        print 'Return String = ' . $response['returnString'] . PHP_EOL;
    } else {
        // You can obtain the paypal payer email address from the return object if you desire to persist this.
        $response_object = $response['data'];
        $auth_status = $response_object->authStatus;
        $payPalEmail = $auth_status->payPalStatus->paypalEmail;
        print 'Successfully paid for by ' . $payPalEmail;
        //Get info from autobill transaction for use processing remaining cart items
        $autobill = $response['data']->autobill;
        $account = $autobill->account;
        $paymentMethod = $autobill->paymentMethod;
        $transaction = new Transaction();
        $transaction->setCurrency('USD');
        $transaction->setSourcePaymentMethod($paymentMethod);
        $transaction->setAccount($account);
        $transaction->setShippingAddress($account->shippingAddress);
        // loop through the cart on server side to add items.
        $transaction_lineitem1 = new TransactionItem();
        $transaction_lineitem1->setSku('club cover');
        $transaction_lineitem1->setName('club cover');
        $transaction_lineitem1->setPrice('4.99');
        $transaction_lineitem1->setQuantity('1');
        $transaction_lineitem2 = new TransactionItem();
        $transaction_lineitem2->setSku('shipping');
        $transaction_lineitem2->setName('shipping');
        $transaction_lineitem2->setPrice('5.00');
        $transaction_lineitem2->setQuantity('1');
        $transaction_lineitem2->setTaxClassification('NT');
        $lineitems = array($transaction_lineitem1, $transaction_lineitem2);
        $transaction->setTransactionItems($lineitems);
        $billPayPalImmediately = new NameValuePair();
        $billPayPalImmediately->setName('vin:BillPayPalImmediately');
        $billPayPalImmediately->setValue('true');
        $autobillVID = new NameValuePair();
        $autobillVID->setName('vin:AutoBillVID');
        $autobillVID->setValue('none');
        $transaction->setNameValues(array($billPayPalImmediately, $autobillVID));
        $sendEmailNotification = false;
        $ignoreAvsPolicy = true;
        $ignoreCvnPolicy = true;
        $campaign = NULL;
        $dryrun = false;
        $response = $transaction->authCapture($sendEmailNotification, $ignoreAvsPolicy, $ignoreCvnPolicy, $campaign, $dryrun);
        if ($response['returnCode'] != '200') {
            print $response['returnCode'] . PHP_EOL;
            print $response['returnString'] . PHP_EOL;
        } else {
            print "returnCode=" . $response['returnCode'] . PHP_EOL;
            print "returnString=" . $response['returnString'] . PHP_EOL;
            if ($response['returnCode'] == "200") {
                $returnTransaction = $response['data']->transaction;
                if ($returnTransaction->statusLog[0]->status == 'Authorized') {
                    print "Transaction approved\n";
                    print "Transaction with id " . $returnTransaction->merchantTransactionId . " was successfully captured";
                    return $returnTransaction->merchantTransactionId;
                } else {
                    if ($returnTransaction->statusLog[0]->status == 'Cancelled') {
                        print "Transaction not approved \n";
                        print "Reason code is: ";
                        print $returnTransaction->statusLog[0]->creditCardStatus->authCode;
                        print "\n";
                    } else {
                        print "Error: Unexpected transaction status\n";
                    }
                }
            } else {
                if ($response['returnCode'] == "202") {
                    print "Transaction cannot be processed due to taxes being temporarily unavailable\n";
                } else {
                    if ($response['returnCode'] == "400") {
                        print "Transaction cannot be processed due to data validation error\n";
                    } else {
                        if ($response['returnCode'] == "402") {
                            print "Transaction cannot be processed due to transaction error\n";
                        } else {
                            if ($response['returnCode'] == "409") {
                                print "Transaction cannot be processed due to Failed AVS and CVN policy evaluation\n";
                            } else {
                                if ($response['returnCode'] == "410") {
                                    print "Transaction cannot be processed due to not being able to perform AVS and CVN policy evaluation\n";
                                } else {
                                    print "Error while making call to Vindicia CashBox\n";
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
$nvp7->setName('PaymentMethod_Update_minchargebackprobability');
$nvp7->setValue('99');
$nvp8 = new NameValuePair();
$nvp8->setName('PaymentMethod_Update_replaceOnAllAutoBills');
$nvp8->setValue(1);
$nvp9 = new NameValuePair();
$nvp9->setName('PaymentMethod_Update_sourceIp');
$nvp9->setValue(IP_ADDRESS);
$nvp10 = new NameValuePair();
$nvp10->setName('PaymentMethod_Update_replaceOnAllChildAutoBills');
$nvp10->setValue(1);
$nvp11 = new NameValuePair();
$nvp11->setName('PaymentMethod_Update_ignoreAvsPolicy');
$nvp11->setValue(0);
$nvp12 = new NameValuePair();
$nvp12->setName('PaymentMethod_Update_ignoreCvnPolicy');
$nvp12->setValue(0);
$websession->setMethodParamValues(array($nvp6, $nvp7, $nvp8, $nvp9, $nvp10, $nvp11, $nvp12));
// now, create the session and generate it's session ID
$rc = $websession->initialize();
// print_r($rc);
$response_object = $rc['data'];
$return_code = $rc['returnCode'];
$return_object = $response_object->session;
$session_id = $return_object->VID;
?>

Merchant PM ID is <?php 
echo $merchantPmId;
?>
<br>