private FindPaymentRequest PrepareFindPaymentRequest(CodeActivityContext executionContext, LocalWorkflowContext crmWorkflowContext, ITracingService tracingService)
        {
            string paymentId = LookupPaymentId.Get(executionContext);

            tracingService.Trace("PrepareFindPaymentRequest trying paymentId: {0}", paymentId);

            if (string.IsNullOrWhiteSpace(paymentId))
            {
                string paymentRefNum = LookupPaymentReferenceNumber.Get(executionContext);
                tracingService.Trace("PrepareFindPaymentRequest trying paymentRefNum: {0}", paymentRefNum);

                // Try to get the payment id from the Payment reference number
                paymentId = crmWorkflowContext.OrganizationService.GetPaymentIdFromPaymentReferenceNumber(paymentRefNum, tracingService);
            }

            if (string.IsNullOrWhiteSpace(paymentId))
            {
                tracingService.Trace("PrepareFindPaymentRequest Could not find payment id, returning {0}", paymentId);
                throw new ArgumentException("paymentRefNum");
            }

            tracingService.Trace("PrepareFindPaymentRequest using paymentId: {0}", paymentId);


            FindPaymentRequest apiRequest = new FindPaymentRequest
            {
                PaymentId = paymentId
            };

            return(apiRequest);
        }
        /// <summary>
        /// Executes the WorkFlow.
        /// </summary>
        /// <param name="crmWorkflowContext">The <see cref="WorkFlowActivityBase.LocalWorkflowContext"/> which contains the
        /// <param name="executionContext" > <see cref="CodeActivityContext"/>
        /// </param>
        /// <remarks>
        /// For improved performance, Microsoft Dynamics 365 caches WorkFlow instances.
        /// The WorkFlow's Execute method should be written to be stateless as the constructor
        /// is not called for every invocation of the WorkFlow. Also, multiple system threads
        /// could execute the WorkFlow at the same time. All per invocation state information
        /// is stored in the context. This means that you should not use global variables in WorkFlows.
        /// </remarks>
        public override void ExecuteCRMWorkFlowActivity(CodeActivityContext executionContext, LocalWorkflowContext crmWorkflowContext)
        {
            var tracingService = executionContext.GetExtension <ITracingService>();

            tracingService.Trace("FindPayment starting...");

            try
            {
                // 1. Validation
                ValidateNotNull(crmWorkflowContext);

                // 2. Prepare API Request
                tracingService.Trace("Calling PrepareFindPaymentRequest...");
                FindPaymentRequest apiRequest = this.PrepareFindPaymentRequest(executionContext, crmWorkflowContext, tracingService);

                // 3. Retrieve Configuration
                tracingService.Trace("Calling RetrieveCardPaymentServiceConfiguration...");
                RestServiceConfiguration cardServiceConfiguration = this.RetrieveCardPaymentServiceConfiguration(executionContext, ConfigurationPrefix.Get(executionContext));

                // 4. Set-up the Api Service
                tracingService.Trace("Instantiating CardPaymentService...");
                CardPaymentService cardPaymentService = new CardPaymentService(cardServiceConfiguration);

                // 5. Call the API
                tracingService.Trace("Calling GovPay FindPayment...");
                FindPaymentResponse apiResponse = cardPaymentService.FindPayment(apiRequest);

                // 6. Return the response
                tracingService.Trace("Calling PrepareOutputParameters...");
                this.PrepareOutputParameters(executionContext, apiResponse, tracingService);
            }
            catch (Exception ex)
            {
                // Todo: Log the Error
                tracingService.Trace("Exception: " + ex);
                throw ex;
            }
        }
        public FindPaymentResponse FindPayment(FindPaymentRequest request)
        {
            using (this.Httpclient)
            {
                // 1. Call API
                // Todo: Implement retry orchestration
                HttpResponseMessage result;
                try
                {
                    result = Get(CardServiceConstants.FindPaymentCommand + "/" + request.PaymentId);
                }
                catch (Exception ex)
                {
                    return(new FindPaymentResponse
                    {
                        error_message = ex.Message,
                        state = new State
                        {
                            status = ErrorState
                        }
                    });
                }

                // 2. Check Request Status
                if (result.IsSuccessStatusCode)
                {
                    // 3. Parse Response
                    return(ParseResponse <FindPaymentResponse>(result.Content));
                }
                else
                {
                    //4. Handle Errors
                    throw new ApplicationException($"There was an error calling the api {CardServiceConstants.FindPaymentCommand}: {result.StatusCode} - {result.StatusCode}");
                }
            }
        }