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; }
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"; } } } } } } } } } }