function create_paypal_AutoBill($account, $paymentmethod)
{
    $ipAddress = '127.0.0.1';
    $uniqueValue = get_unique_value();
    $merchantAutoBillId = 'ab-' . $uniqueValue;
    $merchantProductId = 'mm_1_day_recurring';
    //'Video';
    $merchantBillingPlanId = 'Daily';
    //'OneMonthSubOneMonthRecurring';
    $autobill = new AutoBill();
    $autobill->setMerchantAutoBillId($merchantAutoBillId);
    $autobill->setAccount($account);
    $product = new Product();
    $product->setMerchantProductId($merchantProductId);
    $billingplan = new BillingPlan();
    $billingplan->setMerchantBillingPlanId($merchantBillingPlanId);
    $item = new AutoBillItem();
    $item->setIndex(0);
    $item->setProduct($product);
    $autobill->setItems(array($item));
    $autobill->setSourceIp($ipAddress);
    $autobill->setBillingPlan($billingplan);
    $autobill->setCurrency('USD');
    $autobill->setPaymentMethod($paymentmethod);
    // Set PaymentMethod used by AutoBill
    //$duplicateBehavior = 'Fail'; //removed in 9.0
    //$validatePaymentMethod = true; //removed in 9.0
    $immediateAuthFailurePolicy = 'doNotSaveAutoBill';
    //added in 9.0
    $validateForFuturePayment = true;
    //added in 9.0
    $minChargebackProbability = 100;
    $ignoreAvsPolicy = true;
    $ignoreCvnPolicy = true;
    $campaignCode = null;
    $dryrun = false;
    $response = $autobill->update($immediateAuthFailurePolicy, $validateForFuturePayment, $minChargebackProbability, $ignoreAvsPolicy, $ignoreCvnPolicy, $campaignCode, $dryrun);
    if ($response['returnCode'] != '200') {
        print 'Error creating 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 {
        $response_object = $response['data'];
        $auth_status = $response_object->authStatus;
        if ($auth_status->status == 'AuthorizationPending') {
            $redirection_url = $auth_status->payPalStatus->redirectUrl;
            echo "To authorize, please visit: <a href=\"" . $redirection_url . "\">Continue to Paypal</a>" . PHP_EOL;
        } else {
            if ($auth_status->status == 'Cancelled') {
                echo "Autobill not accepted by PayPal";
            } else {
                echo "Status = " . $auth_status->status;
            }
        }
    }
    return $redirection_url;
}
function create_ecp_AutoBill($account)
{
    $ipAddress = '127.0.0.1';
    $uniqueValue = get_unique_value();
    $merchantAutoBillId = 'ab-' . $uniqueValue;
    $merchantProductId = 'git_hub_product';
    $merchantBillingPlanId = 'git_hub_example';
    $autobill = new AutoBill();
    $autobill->setMerchantAutoBillId($merchantAutoBillId);
    $autobill->setAccount($account);
    $product = new Product();
    $product->setMerchantProductId($merchantProductId);
    $billingplan = new BillingPlan();
    $billingplan->setMerchantBillingPlanId($merchantBillingPlanId);
    $item = new AutoBillItem();
    $item->setIndex(0);
    $item->setProduct($product);
    $autobill->setItems(array($item));
    $autobill->setSourceIp($ipAddress);
    $autobill->setBillingPlan($billingplan);
    $autobill->setCurrency('USD');
    //$duplicateBehavior = 'Fail'; //removed in 9.0
    //$validatePaymentMethod = true; //removed in 9.0
    $immediateAuthFailurePolicy = 'doNotSaveAutoBill';
    //added in 9.0
    $validateForFuturePayment = true;
    //added in 9.0
    $minChargebackProbability = 100;
    $ignoreAvsPolicy = true;
    $ignoreCvnPolicy = true;
    $campaignCode = null;
    $dryrun = false;
    $response = $autobill->update($immediateAuthFailurePolicy, $validateForFuturePayment, $minChargebackProbability, $ignoreAvsPolicy, $ignoreCvnPolicy, $campaignCode, $dryrun);
    if ($response['returnCode'] != '200') {
        print 'Error creating 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 {
        $response_object = $response['data'];
        $auth_status = $response_object->authStatus;
        if ($auth_status->status == 'AuthorizedForValidation') {
            echo "ECP payment in AuthorizedForValidation status, this is a successful test of ECP." . PHP_EOL;
        } else {
            if ($auth_status->status == 'Cancelled') {
                echo "Validation of ECP failed.";
            } else {
                echo "Status = " . $auth_status->status;
            }
        }
    }
    return $auth_status->status;
}
function Step3MigrateVideoMember($merchantAccountId)
{
    $uniqueValue = $merchantAccountId;
    //Step 3
    //Assume that this subscription is for Video access for one year, and was paid in full 6 months ago.
    //As such it will be up for renewal in 6 months.
    //Generally, these dates are retrieved from your datastore.
    $sixmonthsagoPT = new \DateTime('-6 months', new \DateTimeZone('America/Los_Angeles'));
    $sixmonthsfromnowPT = new \DateTime('6 months', new \DateTimeZone('America/Los_Angeles'));
    $dateActiveSubscriptionPeriodPaidInFull = $sixmonthsagoPT->format(DateTime::ATOM);
    $dateActiveSubscriptionPeriodUpForRenewal = $sixmonthsfromnowPT->format(DateTime::ATOM);
    $billPlan = new BillingPlan();
    $product = new Product();
    // Generally, the billing plan and productid will be provided in your datastore.
    // These objects need to exist in CashBox prior to migration.
    $merchantBillingPlanId = 'OneYearSubOneYearRecurring';
    $merchantProductId = 'Video';
    $billPlan->setMerchantBillingPlanId($merchantBillingPlanId);
    $product->setMerchantProductId($merchantProductId);
    //To save a soap call, you can use sparse objects.
    $account = new Account();
    $account->merchantAccountId = $merchantAccountId;
    // Assuming merchantPaymentMethodId is the same value as the merchantAccountId.
    $merchantPaymentMethodId = $merchantAccountId;
    $paymentMethod = new PaymentMethod();
    $paymentMethod->merchantPaymentMethodId = $merchantPaymentMethodId;
    //If you don't have the address VID, then set migrationtransaction shippingaddress to null.
    $address = null;
    //    // If you want to fetch the account by making a soap call to CashBox...
    //    // This is a soap call to CashBox.
    //    $fetchedAccount = get_account_by_merchantAccountId($merchantAccountId);
    //
    //    // Only use sparse object, so all data members are not over-written.
    //    $account->merchantAccountId = $fetchedAccount->merchantAccountId;
    //    $fetchedPaymentMethod = $account->paymentMethods[0];
    //
    //    // Only use sparse object, so all data members are not over-written.
    //    $paymentMethod->merchantPaymentMethodId = $fetchedPaymentMethod->merchantPaymentMethodId;
    $paymentMethodType = 'CreditCard';
    $currency = 'USD';
    $lastPaidPrice = '10.00';
    $useZeroUnlessYouKnowDifferent = 0;
    $paymentProcessor = 'Paymentech';
    $transactionType = 'Recurring';
    $authCode = '000';
    $capturedStatus = 'Captured';
    $txItemType = 'RecurringCharge';
    $txItemName = $merchantProductId . ':' . $merchantBillingPlanId;
    // This paymentProcessorTransactionId makes the transaction refundable if migrating from Litle (Vantiv) into Litle.
    $paymentProcessorTransactionId = 'RetrievedIdFromLegacyBillingPaymentProcessor';
    // Assume campaigns were not used when creating this Autobill.
    // Alternatively, consider specifying campaign on the AutoBillItem if necessary.
    $item = new AutoBillItem();
    $item->setIndex(0);
    $item->setAddedDate($dateActiveSubscriptionPeriodPaidInFull);
    $item->setMerchantAutoBillItemId(get_unique_value());
    $item->setProduct($product);
    $autobill = new AutoBill();
    // No need to set payment method on Autobill as it will be inherited from the Account.
    $autobill->setAccount($account);
    $autobill->setItems(array($item));
    $autobill->setBillingPlan($billPlan);
    $autobill->setCurrency($currency);
    $autobill->setCustomerAutoBillName($uniqueValue);
    $autobill->setMerchantAutoBillId($uniqueValue);
    $autobill->setStartTimestamp($dateActiveSubscriptionPeriodPaidInFull);
    // For this example, we assume one transaction item with a price equal to the entire migration transaction amount.
    $txItemA = new MigrationTransactionItem();
    $txItemA->setItemType($txItemType);
    $txItemA->setName($txItemName);
    $txItemA->setPrice($lastPaidPrice);
    $txItemA->setServicePeriodStartDate($dateActiveSubscriptionPeriodPaidInFull);
    $txItemA->setServicePeriodEndDate($dateActiveSubscriptionPeriodUpForRenewal);
    // It is recommended Sku equals the merchantProductId of the Product set on the Autobill.
    $txItemA->setSku($merchantProductId);
    $creditCardStatusA = new TransactionStatusCreditCard();
    $statusLogA = new TransactionStatus();
    // AuthCode is the code for a transaction successfully run through the payment processor.
    $creditCardStatusA->setAuthCode($authCode);
    $statusLogA->setCreditCardStatus($creditCardStatusA);
    $statusLogA->setPaymentMethodType($paymentMethodType);
    $statusLogA->setStatus($capturedStatus);
    $statusLogA->setTimestamp($dateActiveSubscriptionPeriodPaidInFull);
    $merchantTransactionId = $uniqueValue;
    fail_if_merchant_transaction_id_too_long($merchantTransactionId);
    // Assume sales tax calculated refunds not in scope in this example.
    // If they were, consider setting salesTaxAddress and tax migration transaction items.
    // Assume we are only migrating the last transaction used to pay for the Autobill.
    // If in scope, you have the option to migrate more than one.
    $migrationTransaction = new MigrationTransaction();
    $migrationTransaction->setAccount($account);
    // Set to 21 characters or less, or you will not be able to refund against this.
    $migrationTransaction->setMerchantTransactionId($merchantTransactionId);
    // Total migration transaction amount must equal sum of tx items.
    $migrationTransaction->setAmount($lastPaidPrice);
    // It is recommended that AutoBillCycle is set to the number of times the Autobill has renewed.
    // Make a best effort guess if exact number is unknown.
    // This will help with CashBox Reviews to determine metrics such as Lifetime Value (LTV).
    $migrationTransaction->setAutoBillCycle($useZeroUnlessYouKnowDifferent);
    $migrationTransaction->setBillingDate($dateActiveSubscriptionPeriodPaidInFull);
    // If the billing plan is modified, then the billing plan cycle resets to 0.
    // In general, if the billing has not been modified, this value will be the same as the AutoBill Cycle.
    $migrationTransaction->setBillingPlanCycle($useZeroUnlessYouKnowDifferent);
    $migrationTransaction->setCurrency($currency);
    $migrationTransaction->setPaymentProcessor($paymentProcessor);
    $migrationTransaction->setMerchantBillingPlanId($merchantBillingPlanId);
    $migrationTransaction->setMigrationTransactionItems(array($txItemA));
    $migrationTransaction->setPaymentMethod($paymentMethod);
    $migrationTransaction->setShippingAddress($address);
    $migrationTransaction->setStatusLog(array($statusLogA));
    $migrationTransaction->setType($transactionType);
    $migrationTransaction->setPaymentProcessorTransactionId($paymentProcessorTransactionId);
    //    Division ID mapping:
    //    123456 - Standard Subscription  [Default]
    //    123457 - Premium Subscription
    // CashBox merchant configuration will be configured to route automatically based on a name value pair.
    // Confirm with your Deployment Consultant the values matching the merchant configuration.
    $divisionId = new NameValuePair();
    $divisionId->setName('vin:Division');
    $divisionId->setValue('Premium Subscription');
    $migrationTransaction->setNameValues(array($divisionId));
    //$divisionNumber='123456';
    //$migrationTransaction->setDivisionNumber($divisionNumber);
    $srd = '';
    $response = $autobill->migrate($srd, $dateActiveSubscriptionPeriodUpForRenewal, array($migrationTransaction));
    // Log soap id for each API call.
    //    $log->addDebug('Method = Autobill.migrate' . 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;
    }
    return $response;
}
// This example uses an existing Account
$accountID = $argv[1];
print "accountID is {$accountID} \n";
$account = new Account();
$account->setMerchantAccountId($accountID);
// must be an existing Product
$productID = $argv[2];
print "productID is {$productID} \n";
$product = new Product();
$product->setMerchantProductId($productID);
// AutoBills may have multiple products (AutoBill Items)
$item = new AutoBillItem();
// You can apply a Campaign Code to the product here:
$item->setCampaignCode('1MonthBonusPromo');
// set the Product in the AutoBillItem
$item->setProduct($product);
// must be an existing BillingPlan
$billingplanID = $argv[3];
print "billingplanID is {$billingplanID} \n";
$billingplan = new BillingPlan();
$billingplan->setMerchantBillingPlanId($billingplanID);
// Create a random ID for our testing - This should be much more unique in a production env.
$autobillID = 'ab-random' . rand(1000, 9999999);
print "autobillID is {$autobillID} \n";
$autobill = new AutoBill();
$autobill->setItems(array($item));
$autobill->setAccount($account);
$autobill->setBillingPlan($billingplan);
$autobill->setMerchantAutoBillId($autobillID);
// You can apply a Campaign Code to the Billing Plan here:
//$autobill->setBillingPlanCampaignCode('1MonthBonusPromo');
function createAutoBill($account, $merchantPaymentMethodId, $merchantAutoBillId, $merchantBillingPlanId, $merchantProductId, $currency)
{
    $autobill = new AutoBill();
    $autobill->setAccount($account);
    # same Account
    # AutoBills can have multiple products each in an AutoBillItem as an array:
    $item = new AutoBillItem();
    $item->setIndex(0);
    # set product to an existing product
    $product = new Product();
    $product->setMerchantProductId($merchantProductId);
    $item->setProduct($product);
    # set the Product in the AutoBillItem
    # WSDL AutoBill.items data member is set using PHP method AutoBill.setItems()
    $response = $autobill->setItems(array($item));
    # print_r ($response);
    $autobill->setMerchantAutoBillId($merchantAutoBillId);
    $autobill->setCustomerAutoBillName($merchantAutoBillId);
    # use same PaymentMethod that just validated successfully
    $pm = new PaymentMethod();
    $pm->setMerchantPaymentMethodId($merchantPaymentMethodId);
    $autobill->setPaymentMethod($pm);
    $autobill->setCurrency($currency);
    # set billing plan to existing billing plan
    $billingplan = new BillingPlan();
    $billingplan->setMerchantBillingPlanId($merchantBillingPlanId);
    $autobill->setBillingPlan($billingplan);
    # AutoBill.update() method parameters:
    $validate = false;
    // through 8.0
    $fraudScore = 100;
    // Use this to accept cards involved in chargeback (i.e. Fraud Score=100)
    $minChargebackProbability = $fraudScore;
    $ignoreAvsPolicy = true;
    $ignoreCvnPolicy = true;
    $campaignCode = "";
    $dryrun = false;
    # 9.0 parameters
    $immediateAuthFailurePolicy = 'doNotSaveAutoBill';
    $validateForFuturePayment = $validate;
    print "\nmerchantAccountId=" . $account->getMerchantAccountId() . "\n";
    print "\tmerchantAutoBillId={$merchantAutoBillId}\n";
    print "\t\tmerchantProductId={$product->merchantProductId},";
    print "\tmerchantBillingPlanId={$merchantBillingPlanId}\n";
    print "\tminChargeBackProbability={$minChargebackProbability}\n\n";
    $response = $autobill->update('SucceedIgnore', $validate, $minChargebackProbability, $ignoreAvsPolicy, $ignoreCvnPolicy, $campaignCode, $dryrun);
    // 5.0+
    # $response = $autobill->update($immediateAuthFailurePolicy, $validateForFuturePayment,
    #					$minChargebackProbability,
    # 					$ignoreAvsPolicy, $ignoreCvnPolicy,
    #					$campaignCode, $dryrun);	// 9.0
    echo "\n";
    # print_r ($response);
    $createAutoBill_soapId = $response['data']->return->soapId;
    print "createAutoBill(): soapId = " . $createAutoBill_soapId;
}
    $changeBillingPlanTo->setMerchantBillingPlanId($newBillingPlanId);
}
$autobill = new AutoBill();
$return = $autobill->fetchByMerchantAutoBillId('', $abID);
$autobillVID = $return['data']->autobill->VID;
print "VID is {$autobillVID} \n";
$modAutoBill = new AutoBill();
$modAutoBill->setVID($autobillVID);
$remProduct = new Product();
$remProduct->setMerchantProductId($remID);
$remItem = new AutoBillItem();
$remItem->setProduct($remProduct);
$addProduct = new Product();
$addProduct->setMerchantProductId($addID);
$addItem = new AutoBillItem();
$addItem->setProduct($addProduct);
//$addItem->setCampaignCode('promo10');
$replaceModification = new AutoBillItemModification();
$replaceModification->setRemoveAutoBillItem($remItem);
$replaceModification->setAddAutoBillItem($addItem);
$response = $modAutoBill->modify('', $prorate, $effectiveDate, $changeBillingPlanTo, $replaceModification, $dryrun);
print_r($response);
if ($response['returnCode'] == 200) {
    // Now we can force this autobill to show up in autobill.fetchDeltaSince for this time block
    print "Forcing FDS return by resetting nextBilling date";
    $autobill = new AutoBill();
    $autobillVID = $response['data']->autobill->VID;
    $autobillNextBillDate = $response['data']->autobill->nextBilling->timestamp;
    echo "VID is {$autobillVID} \n";
    echo "nextBill is {$autobillNextBillDate} \n";
    $autobill = new AutoBill();
$addID = $argv[2];
$bpID = $argv[3];
$dryrun = $argv[4];
print "Adding product {$addID} to autobill {$abID} \n";
print "BillingPlan is {$bpID} \n";
print "dryrun is {$dryrun} \n";
$autobill = new AutoBill();
$return = $autobill->fetchByMerchantAutoBillId('', $abID);
$remID = $return['data']->autobill->items[0]->product->merchantProductId;
$autobillVID = $return['data']->autobill->VID;
print "VID is {$autobillVID} \n";
print "item to remove is {$remID} \n";
$modAutoBill = new AutoBill();
$modAutoBill->setVID($autobillVID);
$addProduct = new Product();
$addProduct->setMerchantProductId($addID);
$remProduct = new Product();
$remProduct->setMerchantProductId($remID);
$addItem = new AutoBillItem();
$addItem->setProduct($addProduct);
$remItem = new AutoBillItem();
$remItem->setProduct($remProduct);
$bp = new BillingPLan();
$bp->setMerchantBillingPlanId($bpID);
$mod = new AutoBillItemModification();
$mod->setAddAutoBillItem($addItem);
$mod->setRemoveAutoBillItem($remItem);
$effectiveDate = 'today';
$prorate = 1;
$response = $modAutoBill->modify('', $prorate, $effectiveDate, $bp, array($mod), $dryrun);
print_r($response);
function prepayNonRecurringWithNonRecurringPrice($merchantAutobillId)
{
    // Fetch the current active non-recurring autobill by fetching all autobills by merchantAccountId.
    // Pick the current active non-recurring autobill for which they are pre-paying.
    $currentActiveNonRecurringAutobill = get_current_active_nonrecurring_autobill($merchantAutobillId);
    // Pre-pay capturing a transaction for price of product on current active non-recurring autobill.
    $merchantTransactionId = prepay($currentActiveNonRecurringAutobill);
    $startTimestamp = $currentActiveNonRecurringAutobill->endTimestamp;
    $merchantAutoBillId = $currentActiveNonRecurringAutobill->merchantAutoBillId . '+';
    $merchantAccountId = $currentActiveNonRecurringAutobill->account->merchantAccountId;
    // Only use sparse object, so all data members are not over-written.
    $sparseAccount = new Account();
    $sparseAccount->merchantAccountId = $currentActiveNonRecurringAutobill->account->merchantAccountId;
    // Assume same billing plan as on current autobill.
    $billingPlan = $currentActiveNonRecurringAutobill->billingPlan;
    // Assume same product as on current autobill.
    $product = $currentActiveNonRecurringAutobill->items[0]->product;
    $itemNonRecurring = new AutoBillItem();
    $itemNonRecurring->setIndex(1);
    // Override price of product to 0 USD, since payment is taken up front as one-time transaction.
    $itemNonRecurring->setAmount(0);
    $itemNonRecurring->setProduct($product);
    $autobill = new AutoBill();
    $autobill->setMerchantAutoBillId($merchantAutoBillId);
    $autobill->setAccount($sparseAccount);
    $autobill->setItems(array($itemNonRecurring));
    $autobill->setBillingPlan($billingPlan);
    // Future dated autobill will start when the current active autobill ends.
    // Price is overrided as 0 USD, so no transaction will occur and the user will be entitled for the next non-recurring cycle.
    $autobill->setStartTimestamp($startTimestamp);
    $autobill->setWarnOnExpiration(true);
    $autobill->setCurrency('USD');
    // Add a name value pair to signify a linkage to the previous Autobill.
    // Add a name value pair to signify a linkage to the Transaction used to collect payment.
    // This will help out with revenue recognition.
    $nameVals[0] = new NameValuePair();
    $nameVals[0]->setName("PreviousNonRecurringAutobillId");
    $nameVals[0]->setValue($currentActiveNonRecurringAutobill->merchantAutoBillId);
    $nameVals[1] = new NameValuePair();
    $nameVals[1]->setName("PaidForByMerchantTransactionId");
    $nameVals[1]->setValue($merchantTransactionId);
    $autobill->setNameValues($nameVals);
    $immediateAuthFailurePolicy = 'doNotSaveAutoBill';
    $validateForFuturePayment = false;
    $minChargebackProbability = 100;
    $ignoreAvsPolicy = true;
    $ignoreCvnPolicy = true;
    $campaignCode = null;
    $dryrun = false;
    $response = $autobill->update($immediateAuthFailurePolicy, $validateForFuturePayment, $minChargebackProbability, $ignoreAvsPolicy, $ignoreCvnPolicy, $campaignCode, $dryrun);
    logCall($response, 'Autobill::Update', $merchantAccountId);
}
function Combining_Subscription_And_Non_Subscription_Items_To_Checkout_With_Single_Transaction()
{
    $autobill = new AutoBill();
    $productSubscription = new Product();
    $productSubscription->setMerchantProductId('Video Subscription');
    //Must be defined in CashBox portal
    $productNonRecurring = new Product();
    $productNonRecurring->setMerchantProductId('Golf Clubs');
    //Must be defined in CashBox portal
    $itemSubscription = new AutoBillItem();
    $itemSubscription->setIndex(0);
    $itemSubscription->setProduct($productSubscription);
    $itemNonRecurring = new AutoBillItem();
    $itemNonRecurring->setCycles(1);
    //Only bill first time
    $itemNonRecurring->setIndex(1);
    //If you want to minimize the number of Products defined in CashBox,
    //you have the option to re-use Products by overriding the price by setting the autobill item amount.
    $itemNonRecurring->setAmount(100);
    $itemNonRecurring->setProduct($productNonRecurring);
    $autobill->setItems(array($itemSubscription, $itemNonRecurring));
    // Finish setting up autobill and then call autobill.update.
}