public List<ResponseDetails> ProcessBCPTransactionPro(
            TransactionType _TT //Required
            , BankcardTransactionPro _BCtransaction //Conditional : Only used for an AuthorizeAndCapture, Authorize and ReturnUnlinked. Otherwise null
            , BankcardCapturePro _BCDifferenceData //Conditional : Only used for a Capture. Otherwise null
            , List<String> _BatchIds //Conditional : A list of one or more batch Ids to capture.
            , BankcardReturn _RDifferenceData //Conditional : Only used for a ReturnById. Otherwise null
            , Adjust _ADifferenceData //Conditional : Only used for an Adjust. Otherwise null
            , BankcardUndo _UDifferenceData //Conditional : Only used for an Undo. Otherwise null
            , List<string> _TransactionIds //Conditional : Only used for a CaptureSelective. Otherwise null
            , List<Capture> _CaptureDifferenceData //Conditional : Only used for CaptureAll and CaptureSelective. Otherwise null
            , bool _SendAcknowledge
            , bool _UseWorkflowId)
        {
            List<Response> _Response = new List<Response>();
            try
            {
                CheckTokenExpire();//Make sure the current token is valid

                string _serviceIdOrWorkflowId = _serviceId;
                if (_UseWorkflowId)
                    _serviceIdOrWorkflowId = _workflowId;

                if (_TT == TransactionType.AuthorizeAndCapture)
                {
                    if (CredentialRequired())
                        _BCtransaction.Addendum = CredentialsRequired(_serviceId, _credUserName, _credPassword);
                    _Response.Add(Cwsbc.AuthorizeAndCapture(_sessionToken, _BCtransaction, _applicationProfileId, _merchantProfileId, _serviceIdOrWorkflowId));
                    //Always Verify that the requested amount and approved amount are the same.
                    BankcardTransactionResponsePro BCR = new BankcardTransactionResponsePro();
                    BCR = (BankcardTransactionResponsePro)_Response[0];
                    if (_BCtransaction.TransactionData.Amount != BCR.Amount)
                        MessageBox.Show("The transaction was approved for " + BCR.Amount
                            + " which is an amount not equal to the requested amount of " + _BCtransaction.TransactionData.Amount
                            + ". Please provide alternate payment to complete transaction");
                }

                if (_TT == TransactionType.Authorize)
                {
                    if (CredentialRequired())
                        _BCtransaction.Addendum = CredentialsRequired(_serviceId, _credUserName, _credPassword);
                    _Response.Add(Cwsbc.Authorize(_sessionToken, _BCtransaction, _applicationProfileId, _merchantProfileId, _serviceIdOrWorkflowId));
                    //Always Verify that the requested amount and approved amount are the same.
                    BankcardTransactionResponsePro BCR = new BankcardTransactionResponsePro();
                    BCR = (BankcardTransactionResponsePro)_Response[0];
                    if (_BCtransaction.TransactionData.Amount != BCR.Amount)
                        MessageBox.Show("The transaction was approved for " + BCR.Amount
                            + " which is an amount not equal to than the requested amount of " + _BCtransaction.TransactionData.Amount
                            + ". Please provide alternate payment to complete transaction");
                }
                if (_TT == TransactionType.Capture)
                {
                    if (CredentialRequired())
                        _BCDifferenceData.Addendum = CredentialsRequired(_serviceId, _credUserName, _credPassword);
                    _Response.Add(Cwsbc.Capture(_sessionToken, _BCDifferenceData, _applicationProfileId, _serviceId));
                }
                if (_TT == TransactionType.CaptureAll)
                {
                    if (CredentialRequired())
                        _BCDifferenceData.Addendum = CredentialsRequired(_serviceId, _credUserName, _credPassword);
                    _Response = Cwsbc.CaptureAll(_sessionToken, _CaptureDifferenceData, _BatchIds, _applicationProfileId,
                                                 _merchantProfileId, _serviceId);
                }
                if (_TT == TransactionType.CaptureAllAsync)
                {
                    if (CredentialRequired())
                        _BCDifferenceData.Addendum = CredentialsRequired(_serviceId, _credUserName, _credPassword);
                    _Response.Add(Cwsbc.CaptureAllAsync(_sessionToken, _CaptureDifferenceData, _BatchIds,
                                                        _applicationProfileId, _merchantProfileId, _serviceId));
                }
                if (_TT == TransactionType.CaptureSelective)
                {
                    if (CredentialRequired())
                        _BCDifferenceData.Addendum = CredentialsRequired(_serviceId, _credUserName, _credPassword);
                    _Response = Cwsbc.CaptureSelective(_sessionToken, _TransactionIds, _CaptureDifferenceData,
                                                       _applicationProfileId, _serviceId);
                }
                if (_TT == TransactionType.CaptureSelectiveAsync)
                {
                    if (CredentialRequired())
                        _BCDifferenceData.Addendum = CredentialsRequired(_serviceId, _credUserName, _credPassword);
                    _Response.Add(Cwsbc.CaptureSelectiveAsync(_sessionToken, _TransactionIds, _CaptureDifferenceData,
                                                              _applicationProfileId, _serviceId));
                }
                if (_TT == TransactionType.ReturnById)
                {
                    if (CredentialRequired())
                        _RDifferenceData.Addendum = CredentialsRequired(_serviceId, _credUserName, _credPassword);
                    _Response.Add(Cwsbc.ReturnById(_sessionToken, _RDifferenceData, _applicationProfileId, _serviceId));
                }
                if (_TT == TransactionType.Return)
                {
                    if (CredentialRequired())
                        _BCtransaction.Addendum = CredentialsRequired(_serviceId, _credUserName, _credPassword);
                    _Response.Add(Cwsbc.ReturnUnlinked(_sessionToken, _BCtransaction, _applicationProfileId, _merchantProfileId, _serviceId));
                }
                if (_TT == TransactionType.Adjust)
                {
                    if (CredentialRequired())
                        _ADifferenceData.Addendum = CredentialsRequired(_serviceId, _credUserName, _credPassword);
                    _Response.Add(Cwsbc.Adjust(_sessionToken, _ADifferenceData, _applicationProfileId, _serviceId));
                }
                if (_TT == TransactionType.Undo)
                {
                    if (CredentialRequired())
                        _UDifferenceData.Addendum = CredentialsRequired(_serviceId, _credUserName, _credPassword);
                    _Response.Add(Cwsbc.Undo(_sessionToken, _UDifferenceData, _applicationProfileId, _serviceId));
                }
                if (_TT == TransactionType.QueryAccount)
                {
                    if (CredentialRequired())
                        _BCtransaction.Addendum = CredentialsRequired(_serviceId, _credUserName, _credPassword);
                    _Response.Add(Cwsbc.QueryAccount(_sessionToken, _BCtransaction, _applicationProfileId,
                                                     _merchantProfileId, _serviceId));
                }
                if (_TT == TransactionType.Verify)
                    _Response.Add(Cwsbc.Verify(_sessionToken, _BCtransaction, _applicationProfileId, _merchantProfileId, _serviceId));

                List<ResponseDetails> RD = new List<ResponseDetails>();//Convert the response to response details so that we can report on the UI
                if (_Response != null)
                {
                    foreach (Response r in _Response)
                    {
                        if (_SendAcknowledge && r.TransactionId.Length > 0)
                            Cwsbc.Acknowledge(_sessionToken, r.TransactionId, _applicationProfileId, _serviceId);

                        ResponseDetails RDN = new ResponseDetails(0.00M, r, _TT.ToString(), _serviceIdOrWorkflowId, _merchantProfileId, true, TypeCardType.NotSet, "");
                        MessageBox.Show(ProcessResponse(ref RDN));//Pass as reference so we can extract more values from the response
                        RD.Add(RDN);
                    }
                }

                return RD;
            }
            catch (EndpointNotFoundException)
            {
                //In this case the SvcEndpoint was not available. Try the same logic again with the alternate Endpoint
                try
                {
                    SetTxnEndpoint();//Change the endpoint to use the backup.

                    //TODO : Add a copy of the code above once fully tested out.

                    return null;

                }
                catch (EndpointNotFoundException)
                {
                    MessageBox.Show("Neither the primary or secondary endpoints are available. Unable to process.");
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Unable to AuthorizeAndCapture\r\nError Message : " + ex.Message, "AuthorizeAndCapture Failed", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                }
            }
            catch (System.TimeoutException te)
            {
                //A timeout has occured. Prompt the user if they'd like to query for the last transaction submitted
                if(_BCtransaction != null)
                {
                    DialogResult Result;
                    Result = MessageBox.Show("A timeout has occured. Would you like to query 'RequestTransaction' to obtain transactions with the exact same TenderData? To avoid duplicate charges your code will need to reconcile transactions.",
                                "Request Transaction", MessageBoxButtons.YesNo);
                    if (Result == DialogResult.Yes)
                    {
                        RequestTransaction(_BCtransaction.TenderData);
                    }
                    else { throw te; }
                }
                else{throw te;}
            }
            catch (Exception ex)
            {
                string strErrorId;
                string strErrorMessage;
                if (_FaultHandler.handleTxnFault(ex, out strErrorId, out strErrorMessage))
                { MessageBox.Show(strErrorId + " : " + strErrorMessage); }
                else { MessageBox.Show(ex.Message); }
            }

            return null;
        }
        private void cmdPurchaseCardL3_Click(object sender, EventArgs e)
        {
            Cursor = Cursors.WaitCursor;
            //NOTE: The first step with purchase card level 2 is to submit a Authorize to verify that the card is a valid purchase card
            //Check to see if this transaction type is supported
            if (!SupportedTxnTypes.Authorize | !SupportedTxnTypes.Capture) { MessageBox.Show("Purchase card requires support for Authorize as well as Capture"); Cursor = Cursors.Default; return; }

            List<ResponseDetails> response = new List<ResponseDetails>();
            if (_bcs != null) //Process a BankCard Transaction
            {
                try
                {
                    BankcardTransactionPro BCtransaction = new BankcardTransactionPro();
                    
                    //First Check to see if this work flow is an "AuthorizeAndCapture" or an "Authorize" followed by a "Capture".
                    if (chkL3AuthAndCapture.Checked)
                    {//In this case the work flow is a "AuthorizeAndCapture"
                        BankCardProProcessingOptions BCPO = new BankCardProProcessingOptions(PurchaseCardLevel.Level3, false, true);
                        BCtransaction = SetBankCardTxnData(BCPO);
                        response = Helper.ProcessBCPTransaction(TransactionType.AuthorizeAndCapture, BCtransaction, null, null, null, null, null, null, null, ChkAcknowledge.Checked, ChkUserWorkflowId.Checked);
                        if (response.Count < 1) { return; }
                        ChkLstTransactionsProcessed.Items.Add(response[0]);
                    }
                    else
                    {//In this case the work flow is an "Authorize" followed by a "Capture"
                        BankCardProProcessingOptions BCPO = new BankCardProProcessingOptions(PurchaseCardLevel.Level3, false, false);
                        BCtransaction = SetBankCardTxnData(BCPO);

                        response = Helper.ProcessBCPTransaction(TransactionType.Authorize, BCtransaction, null, null, null, null, null, null, null, ChkAcknowledge.Checked, ChkUserWorkflowId.Checked);
                        if (response.Count < 1) { return; }
                        ChkLstTransactionsProcessed.Items.Add(response[0]);
                        BankcardTransactionResponsePro BCR = (BankcardTransactionResponsePro)response[0].Response;

                        //Note : Now let's send the capture for the level 3 transaction. 
                        //First verify that the card is a valid Purchase Card. 
                        if (BCR.CommercialCardResponse == CommercialCardResponse.BusinessCard | BCR.CommercialCardResponse == CommercialCardResponse.CorporateCard | BCR.CommercialCardResponse == CommercialCardResponse.PurchaseCard)
                        {
                            BankcardCapturePro BCP = new BankcardCapturePro();
                            BCP.Level2Data = SetLevel2Data(); //Level 3 purchase card is always inclusive of Level 1 and Level 2 data.

                            List<LineItemDetail> LIDS = new List<LineItemDetail>();
                            //For each line on the receipt the following needs to be called. 
                            for (int i = 0; i < 3; i++)//Add three line items
                            {
                                LIDS.Add(SetLevel3Data());
                            }
                            BCP.LineItemDetails = LIDS;
                            BCP.TransactionId = BCR.TransactionId;//Set the transactionId to the original Authorize
                            response = Helper.ProcessBCPTransaction(TransactionType.Capture, null, BCP, null, null, null, null, null, null, ChkAcknowledge.Checked, false);
                            if (response.Count < 1) { return; }
                            ChkLstTransactionsProcessed.Items.Add(response[0]);
                        }
                        else
                        {
                            MessageBox.Show("Capture failed as Card PAN was not a valid Level 2 or Level 3 purchase Card");
                        }
                    }
                }
                catch (Exception ex) { MessageBox.Show(ex.Message); }
                finally { Cursor = Cursors.Default; }
            }
            else if (_ecks != null) //Process as a Check transaction
            {
                try
                {
                    MessageBox.Show(@"Placeholder for ECK code. Please ask your solution consultant for an example");
                }
                catch (Exception ex) { MessageBox.Show(ex.Message); }
                finally { Cursor = Cursors.Default; }
            }
        }
        private void cmdCapture_Click(object sender, EventArgs e)
        {//The Capture() operation is used to capture a single transaction after it has been successfully authorized.
            if (ChkLstTransactionsProcessed.CheckedItems.Count == 0) { MessageBox.Show("Please Select (Check) transactions for Capture"); return; }
            //Check to see if this transaction type is supported
            if (!SupportedTxnTypes.Capture) { MessageBox.Show("Capture Not Supported"); return; }

            Cursor = Cursors.WaitCursor;
            
            //First verify if all transactions selected are "Authorize" transactions
            List<ResponseDetails> txnsToProcess = new List<ResponseDetails>();
            foreach (object itemChecked in ChkLstTransactionsProcessed.CheckedItems)
            {
                if (((ResponseDetails)(itemChecked)).TransactionType != TransactionType.Authorize.ToString())
                {
                    MessageBox.Show("All selected messages must be of type Authorize");
                    Cursor = Cursors.Default; 
                    return;
                }
                txnsToProcess.Add(((ResponseDetails)(itemChecked)));
            }

            //Now process each Authorize message selected
            foreach (ResponseDetails _RD in txnsToProcess)
            {
                if (_bcs != null) //Process a BankCard Transaction
                {
                    try
                    {
                        BankcardCapturePro BCDifferenceData = new BankcardCapturePro();
                        BCDifferenceData.TransactionId = _RD.Response.TransactionId;

                        if (ChkMultiplePartialCapture.Checked)
                        {
                            //Let's demonstrate capturing two multipartialCaptures. Note that multipartialCapture requries the BankcarCapturePro() object
                            BCDifferenceData.Amount = 5.00M;
                            BCDifferenceData.MultiplePartialCapture = true;

                            processResponse(Helper.ProcessBCPTransaction(TransactionType.Capture, null, BCDifferenceData, null, null, null, null, null, null, ChkAcknowledge.Checked, false));
                            processResponse(Helper.ProcessBCPTransaction(TransactionType.Capture, null, BCDifferenceData, null, null, null, null, null, null, ChkAcknowledge.Checked, false));
                        }
                        else
                        {
                            //For demonstrations let's show adding a two dollar tip
                            BCDifferenceData.Amount = 12.00M;
                            BCDifferenceData.TipAmount = 2.00M;

                            BCDifferenceData.MultiplePartialCapture = false;
                            processResponse(Helper.ProcessBCPTransaction(TransactionType.Capture, null, BCDifferenceData, null, null, null, null, null, null, ChkAcknowledge.Checked, false));
                        }
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message);
                    }
                    finally
                    {
                        Cursor = Cursors.Default;
                    }
                }
                else if (_svas != null) //Process a BankCard Transaction
                {
                    try
                    {
                        StoredValueCapture SVDifferenceData = new StoredValueCapture();
                        string strAuthTxn = _authorizeTxn;
                        _authorizeTxn = ""; //Reset so that a new Authorize will be required            
                        SVDifferenceData.TransactionId = strAuthTxn;


                        SVDifferenceData.Amount = 12.00M;
                        //SVDifferenceData.TipAmount = 2.00M;

                        processResponse(Helper.ProcessSVATransaction(TransactionType.Capture, null, null, SVDifferenceData, null, null, ChkAcknowledge.Checked));
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message);
                    }
                    finally
                    {
                        Cursor = Cursors.Default;
                    }
                }
                else if (_ecks != null) //Process as a Check transaction
                {
                    try
                    {
                        MessageBox.Show(@"Placeholder for ECK code. Please ask your solution consultant for an example");
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message);
                    }
                    finally
                    {
                        Cursor = Cursors.Default;
                    }
                }
            }

        }
        private void cmdPurchaseCardL2_Click(object sender, EventArgs e)
        {
            Cursor = Cursors.WaitCursor;

            if (_bcs != null) //Process a BankCard Transaction
            {
                //NOTE: The first step with purchase card level 2 is to submit a Authorize to verify that the card is a valid purchase card
                //Check to see if this the service is a host capture or terminal capture solution. This will drive logice in terms of useing an AuthorizeAndCapture Versus Authorize to Capture
                if (_bcs.Tenders.CreditAuthorizeSupport == CreditAuthorizeSupportType.AuthorizeOnly)//In this case it's a Host capture so either an Authorize followed by capture or AuthorizeAndCapture should be used.
                    if (!SupportedTxnTypes.Authorize && !SupportedTxnTypes.AuthAndCapture) { MessageBox.Show("Purchase card requires support for Authorize or AuthorizeAndCapture"); Cursor = Cursors.Default; return; }
                    else//In this case its a terminal capture service which requires an Authorize followed by a captureall or capture selective
                        if (!SupportedTxnTypes.Authorize | !SupportedTxnTypes.CaptureAll) { MessageBox.Show("Purchase card requires support for Authorize as well as CaptureAll or CaptureSelective"); Cursor = Cursors.Default; return; }

                List<ResponseDetails> response = new List<ResponseDetails>();
                try
                {
                    BankcardTransactionPro BCtransaction = new BankcardTransactionPro();
                    //First Check to see if this work flow is an "AuthorizeAndCapture" or an "Authorize" followed by a "Capture".
                    if (chkL2AuthAndCapture.Checked && _bcs.Tenders.CreditAuthorizeSupport == CreditAuthorizeSupportType.AuthorizeOnly)
                    {//In this case the work flow is a "AuthorizeAndCapture"
                        BankCardProProcessingOptions BCPO = new BankCardProProcessingOptions(PurchaseCardLevel.Level2, false, true);
                        BCtransaction = SetBankCardTxnData(BCPO);
                        response = Helper.ProcessBCPTransaction(TransactionType.AuthorizeAndCapture, BCtransaction, null, null, null, null, null, null, null, ChkAcknowledge.Checked, ChkUserWorkflowId.Checked);
                        if (response.Count < 1) { return; }
                        ChkLstTransactionsProcessed.Items.Add(response[0]);
                    }
                    else if (!chkL2AuthAndCapture.Checked)
                    {//In this case the work flow is an "Authorize" followed by a "Capture"
                        BankCardProProcessingOptions BCPO = new BankCardProProcessingOptions(PurchaseCardLevel.Level2, false, false);
                        BCtransaction = SetBankCardTxnData(BCPO);

                        response = Helper.ProcessBCPTransaction(TransactionType.Authorize, BCtransaction, null, null, null, null, null, null, null, ChkAcknowledge.Checked, ChkUserWorkflowId.Checked);
                        if (response.Count < 1) { return; }
                        ChkLstTransactionsProcessed.Items.Add(response[0]);
                        BankcardTransactionResponsePro BCR = (BankcardTransactionResponsePro)response[0].Response;

                        //Note : Now let's send the capture for the level 2 transaction. 
                        //First verify that the card is a valid Purchase Card. 
                        if (BCR.CommercialCardResponse == CommercialCardResponse.BusinessCard | BCR.CommercialCardResponse == CommercialCardResponse.CorporateCard | BCR.CommercialCardResponse == CommercialCardResponse.PurchaseCard)
                        {
                            BankcardCapturePro BCP = new BankcardCapturePro();
                            BCP.Level2Data = SetLevel2Data();
                            BCP.TransactionId = BCR.TransactionId;//Set the transactionId to the original Authorize

                            response = Helper.ProcessBCPTransaction(TransactionType.Capture, null, BCP, null, null, null, null, null, null, ChkAcknowledge.Checked, false);
                            if (response.Count < 1) { return; }
                            ChkLstTransactionsProcessed.Items.Add(response[0]);
                        }
                        else
                        {
                            MessageBox.Show("Capture failed as Card PAN was not a valid Level 2 or Level 3 purchase Card");
                        }
                    }
                    else
                    {
                        MessageBox.Show("Unable to process purchase Card as the transaction types requested are not supported. Specifically AuthorizeAndCapture");
                    }
                }
                catch (Exception ex) { MessageBox.Show(ex.Message); }
                finally { Cursor = Cursors.Default; }

            }
            else if (_ecks != null) //Process as a Check transaction
            {
                try
                {
                    MessageBox.Show(@"Placeholder for ECK code. Please ask your solution consultant for an example");
                }
                catch (Exception ex) { MessageBox.Show(ex.Message); }
                finally { Cursor = Cursors.Default; }
            }
        }