/// <summary>
        /// Executes Task.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <returns>The response.</returns>
        private ExecuteTaskPaymentTerminalDeviceResponse ExecuteTask(ExecuteTaskPaymentTerminalDeviceRequest request)
        {
            ThrowIf.Null(request, nameof(request));

            List <CommerceProperty> commerceProperties = new List <CommerceProperty>();

            ExtensionTransaction transaction;

            // Add/substitute 'case' matching your task and put there the business logic you need for your specific task.
            switch (request.Task)
            {
            case "Echo":
                // 1. Copying original properties into the response.
                commerceProperties.AddRange(request.ExtensionTransactionProperties.ExtensionProperties);

                // 2. Adding some new properties
                commerceProperties.AddRange(new CommerceProperty[]
                {
                    new CommerceProperty("Key" + Guid.NewGuid(), "Value1"),
                    new CommerceProperty("Key" + Guid.NewGuid(), "Value2")
                });

                transaction = new ExtensionTransaction
                {
                    EntityName          = request.ExtensionTransactionProperties.EntityName,
                    ExtensionProperties = commerceProperties
                };
                break;

            default:
                throw new NotSupportedException($"The task{request.Task} is not supported");
            }

            return(new ExecuteTaskPaymentTerminalDeviceResponse(transaction));
        }
Beispiel #2
0
            /// <summary>
            /// Fetch token for credit card.
            /// </summary>
            /// <param name="isManualEntry">The value indicating whether credit card should be entered manually.</param>
            /// <param name="extensionTransactionProperties">Optional extension transaction properties.</param>
            /// <returns>A task that can await until the token generation has completed.</returns>
            public async Task <PaymentInfo> FetchTokenAsync(bool isManualEntry, ExtensionTransaction extensionTransactionProperties)
            {
                PaymentInfo paymentInfo = new PaymentInfo();

                // Get tender
                TenderInfo maskedTenderInfo = await this.GetTenderAsync(false);

                if (maskedTenderInfo == null)
                {
                    return(paymentInfo);
                }

                if (this.processor == null)
                {
                    this.processor = CardPaymentManager.GetPaymentProcessor(this.merchantProperties, this.paymentConnectorName);
                }

                paymentInfo.CardNumberMasked = maskedTenderInfo.CardNumber;
                paymentInfo.CashbackAmount   = maskedTenderInfo.CashBackAmount;
                paymentInfo.CardType         = (Microsoft.Dynamics.Commerce.HardwareStation.CardPayment.CardType)maskedTenderInfo.CardTypeId;

                PaymentProperty[] defaultMerchantProperties = this.merchantProperties;

                if (this.merchantProperties[0].Namespace.Equals(GenericNamespace.Connector) && this.merchantProperties[0].Name.Equals(ConnectorProperties.Properties))
                {
                    defaultMerchantProperties = this.merchantProperties[0].PropertyList;
                }

                // Generate card token
                Request  request  = CardPaymentManager.GetTokenRequest(defaultMerchantProperties, this.tenderInfo, this.terminalSettings.Locale, extensionTransactionProperties);
                Response response = this.processor.GenerateCardToken(request, null);

                CardPaymentManager.MapTokenResponse(response, paymentInfo);

                return(paymentInfo);
            }
Beispiel #3
0
            /// <summary>
            /// Make reversal/void a payment.
            /// </summary>
            /// <param name="amount">The amount.</param>
            /// <param name="currency">The currency.</param>
            /// <param name="paymentProperties">The payment properties of the authorization response.</param>
            /// <param name="extensionTransactionProperties">Optional extension transaction properties.</param>
            /// <returns>A task that can await until the void has completed.</returns>
            public Task <PaymentInfo> VoidPaymentAsync(decimal amount, string currency, PaymentProperty[] paymentProperties, ExtensionTransaction extensionTransactionProperties)
            {
                if (amount < this.terminalSettings.MinimumAmountAllowed)
                {
                    throw new CardPaymentException(CardPaymentException.AmountLessThanMinimumLimit, "Amount does not meet minimum amount allowed.");
                }

                if (this.processor == null)
                {
                    this.processor = CardPaymentManager.GetPaymentProcessor(this.merchantProperties, this.paymentConnectorName);
                }

                if (this.terminalSettings.MaximumAmountAllowed > 0 && amount > this.terminalSettings.MaximumAmountAllowed)
                {
                    throw new CardPaymentException(CardPaymentException.AmountExceedsMaximumLimit, "Amount exceeds the maximum amount allowed.");
                }

                PaymentInfo paymentInfo = new PaymentInfo();

                // Handle multiple chain connectors by returning single instance used in capture.
                IPaymentProcessor currentProcessor = null;

                PaymentProperty[] currentMerchantProperties = null;
                CardPaymentManager.GetRequiredConnector(this.merchantProperties, paymentProperties, this.processor, out currentProcessor, out currentMerchantProperties);

                Request  request  = CardPaymentManager.GetCaptureRequest(currentMerchantProperties, paymentProperties, amount, currency, this.terminalSettings.Locale, this.isTestMode, this.terminalSettings.TerminalId, cardCache, extensionTransactionProperties);
                Response response = currentProcessor.Void(request);

                CardPaymentManager.MapVoidResponse(response, paymentInfo);

                return(Task.FromResult(paymentInfo));
            }
Beispiel #4
0
            /// <summary>
            /// Make authorization payment.
            /// </summary>
            /// <param name="amount">The amount.</param>
            /// <param name="currency">The currency.</param>
            /// <param name="voiceAuthorization">The voice approval code (optional).</param>
            /// <param name="isManualEntry">If manual credit card entry is required.</param>
            /// <param name="extensionTransactionProperties">Optional extension transaction properties.</param>
            /// <returns>A task that can await until the authorization has completed.</returns>
            public async Task <PaymentInfo> AuthorizePaymentAsync(decimal amount, string currency, string voiceAuthorization, bool isManualEntry, ExtensionTransaction extensionTransactionProperties)
            {
                if (amount < this.terminalSettings.MinimumAmountAllowed)
                {
                    throw new CardPaymentException(CardPaymentException.AmountLessThanMinimumLimit, "Amount does not meet minimum amount allowed.");
                }

                if (this.terminalSettings.MaximumAmountAllowed > 0 && amount > this.terminalSettings.MaximumAmountAllowed)
                {
                    throw new CardPaymentException(CardPaymentException.AmountExceedsMaximumLimit, "Amount exceeds the maximum amount allowed.");
                }

                if (this.processor == null)
                {
                    this.processor = CardPaymentManager.GetPaymentProcessor(this.merchantProperties, this.paymentConnectorName);
                }

                PaymentInfo paymentInfo = new PaymentInfo();

                // Get tender
                TenderInfo maskedTenderInfo = await this.GetTenderAsync(true);

                if (maskedTenderInfo == null)
                {
                    return(paymentInfo);
                }

                paymentInfo.CardNumberMasked = maskedTenderInfo.CardNumber;
                paymentInfo.CashbackAmount   = maskedTenderInfo.CashBackAmount;
                paymentInfo.CardType         = (Microsoft.Dynamics.Commerce.HardwareStation.CardPayment.CardType)maskedTenderInfo.CardTypeId;

                if (paymentInfo.CashbackAmount > this.terminalSettings.DebitCashbackLimit)
                {
                    throw new CardPaymentException(CardPaymentException.CashbackAmountExceedsLimit, "Cashback amount exceeds the maximum amount allowed.");
                }

                // Authorize
                Response response = CardPaymentManager.ChainedAuthorizationCall(this.processor, this.merchantProperties, this.tenderInfo, amount, currency, this.terminalSettings.Locale, this.isTestMode, this.terminalSettings.TerminalId, extensionTransactionProperties);

                Guid cardStorageKey = Guid.NewGuid();

                CardPaymentManager.MapAuthorizeResponse(response, paymentInfo, cardStorageKey, this.terminalSettings.TerminalId);

                if (paymentInfo.IsApproved)
                {
                    // Backup credit card number
                    TemporaryCardMemoryStorage <string> cardStorage = new TemporaryCardMemoryStorage <string>(DateTime.UtcNow, this.tenderInfo.CardNumber);
                    cardStorage.StorageInfo = paymentInfo.PaymentSdkData;
                    cardCache.Add(cardStorageKey, cardStorage);

                    // need signature?
                    if (this.terminalSettings.SignatureCaptureMinimumAmount < paymentInfo.ApprovedAmount)
                    {
                        paymentInfo.SignatureData = await this.RequestTenderApprovalAsync(paymentInfo.ApprovedAmount);
                    }
                }

                return(paymentInfo);
            }
        private async Task <PaymentInfo> GetGiftCardBalanceAsync(string paymentConnectorName, string currencyCode, TenderInfo tenderInfo, ExtensionTransaction extensionTransactionProperties)
        {
            await Task.Delay(10).ConfigureAwait(false);

            throw new PeripheralException(PeripheralException.PaymentTerminalError, "Operation is not supported by payment terminal.", inner: null);
        }
        private async Task <PaymentInfo> FetchTokenAsync(bool isManualEntry, ExtensionTransaction extensionTransactionProperties)
        {
            await Task.Delay(10).ConfigureAwait(false);

            throw new PeripheralException(PeripheralException.PaymentTerminalError, "Operation is not supported by payment terminal.", inner: null);
        }
 private async Task <PaymentInfo> RefundPaymentAsync(decimal amount, string currency, bool isManualEntry, ExtensionTransaction extensionTransactionProperties)
 {
     return(await Task.FromResult(CreateAuthorizationSuccessPaymentInfo(amount)).ConfigureAwait(false));
 }
        private async Task <PaymentInfo> VoidPaymentAsync(string paymentConnectorName, decimal amount, string currency, TenderInfo tenderInfo, string paymentPropertiesXml, ExtensionTransaction extensionTransactionProperties)
        {
            ThrowIf.Null(this.merchantProperties, nameof(this.merchantProperties));

            PaySdk.PaymentProperty[] properties = GetPaymentPropertiesWithInitialList(paymentConnectorName, this.merchantProperties);

            // Several below values are hardcoded, real implementations should take this data from real device.
            return(await Task.FromResult(new PaymentInfo()
            {
                CardNumberMasked = string.Empty,
                CardType = Microsoft.Dynamics.Commerce.HardwareStation.CardPayment.CardType.Unknown,
                SignatureData = string.Empty,
                PaymentSdkData = PaySdk.PaymentProperty.ConvertPropertyArrayToXML(properties),
                CashbackAmount = 0.0m,
                ApprovedAmount = amount,
                IsApproved = false,
                Errors = null
            }).ConfigureAwait(false));
        }
 /// <summary>
 /// Make refund payment.
 /// </summary>
 /// <param name="amount">The amount.</param>
 /// <param name="currency">The currency.</param>
 /// <param name="isManualEntry">If manual credit card entry is required.</param>
 /// <param name="extensionTransactionProperties">Optional extension transaction properties.</param>
 /// <returns>A task that can await until the refund has completed.</returns>
 public virtual async Task <PaymentInfo> RefundPaymentAsync(decimal amount, string currency, bool isManualEntry, ExtensionTransaction extensionTransactionProperties)
 {
     return(await this.Execute(async() =>
     {
         return await this.paymentDevice.RefundPaymentAsync(amount, currency, isManualEntry, extensionTransactionProperties);
     }));
 }
            /// <summary>
            /// Fetch token for credit card.
            /// </summary>
            /// <param name="isManualEntry">The value indicating whether credit card should be entered manually.</param>
            /// <param name="extensionTransactionProperties">Optional extension transaction properties.</param>
            /// <returns>A task that can await until the token generation has completed.</returns>
            public async Task <PaymentInfo> FetchTokenAsync(bool isManualEntry, ExtensionTransaction extensionTransactionProperties)
            {
                await Task.Delay(10);

                throw new System.NotImplementedException();
            }
 /// <summary>
 /// Make refund payment.
 /// </summary>
 /// <param name="amount">The amount.</param>
 /// <param name="currency">The currency.</param>
 /// <param name="isManualEntry">If manual credit card entry is required.</param>
 /// <param name="extensionTransactionProperties">Optional extension transaction properties.</param>
 /// <returns>A task that can await until the refund has completed.</returns>
 public async Task <PaymentInfo> RefundPaymentAsync(decimal amount, string currency, bool isManualEntry, ExtensionTransaction extensionTransactionProperties)
 {
     return(await Task.FromResult <PaymentInfo>(new PaymentInfo()
     {
         CardNumberMasked = "411111******1111",
         CardType = Microsoft.Dynamics.Commerce.HardwareStation.CardPayment.CardType.InternationalCreditCard,
         SignatureData = "AAgEAAQALP4hvpJrK/UfKvlX7ABkIfJFnxoZbaXC2vmnzYB8ItM1rBYwzRrw0IdLF3Qv89lwBfgGn5gBwKkFSoguAft6w8ZAJATwSYNMGJTlqmorxYYyN2BZvtGmroCuKygDAJoBkAyDAr46bUZ4kOFG7P9GmjcA",
         PaymentSdkData = "<!--- payment sdk connector payment properties for refund response -->",
         CashbackAmount = 0.0m,
         ApprovedAmount = amount,
         IsApproved = true,
         Errors = null
     }));
 }
 /// <summary>
 /// Make reversal/void a payment.
 /// </summary>
 /// <param name="amount">The amount.</param>
 /// <param name="currency">The currency.</param>
 /// <param name="paymentProperties">The payment properties of the authorization response.</param>
 /// <param name="extensionTransactionProperties">Optional extension transaction properties.</param>
 /// <returns>A task that can await until the void has completed.</returns>
 public async Task <PaymentInfo> VoidPaymentAsync(decimal amount, string currency, PaymentProperty[] paymentProperties, ExtensionTransaction extensionTransactionProperties)
 {
     return(await Task.FromResult <PaymentInfo>(new PaymentInfo()
     {
         CardNumberMasked = string.Empty,
         CardType = Microsoft.Dynamics.Commerce.HardwareStation.CardPayment.CardType.Unknown,
         SignatureData = string.Empty,
         PaymentSdkData = "<!--- payment sdk connector payment properties for void response -->",
         CashbackAmount = 0.0m,
         ApprovedAmount = amount,
         IsApproved = true,
         Errors = null
     }));
 }
            /// <summary>
            /// Extensibility execute method.
            /// </summary>
            /// <param name="task">The task to execute.</param>
            /// <param name="extensionTransactionProperties">Optional extension transaction properties.</param>
            /// <returns>The result of executing the task.</returns>
            public virtual async Task <ExtensionTransaction> ExecuteTaskAsync(string task, ExtensionTransaction extensionTransactionProperties)
            {
                IPaymentTerminalExtension extension = this.paymentDevice as IPaymentTerminalExtension;

                if (extension != null)
                {
                    return(await extension.ExecuteTaskAsync(task, extensionTransactionProperties));
                }
                else
                {
                    return(await Task.FromResult <ExtensionTransaction>(null));
                }
            }
 /// <summary>
 /// Fetch token for credit card.
 /// </summary>
 /// <param name="isManualEntry">The value indicating whether credit card should be entered manually.</param>
 /// <param name="extensionTransactionProperties">Optional extension transaction properties.</param>
 /// <returns>A task that can await until the token generation has completed.</returns>
 public virtual async Task <PaymentInfo> FetchTokenAsync(bool isManualEntry, ExtensionTransaction extensionTransactionProperties)
 {
     return(await this.Execute(async() =>
     {
         return await this.paymentDevice.FetchTokenAsync(isManualEntry, extensionTransactionProperties);
     }));
 }
Beispiel #15
0
            /// <summary>
            /// Make refund payment.
            /// </summary>
            /// <param name="amount">The amount.</param>
            /// <param name="currency">The currency.</param>
            /// <param name="isManualEntry">If manual credit card entry is required.</param>
            /// <param name="extensionTransactionProperties">Optional extension transaction properties.</param>
            /// <returns>A task that can await until the refund has completed.</returns>
            public async Task <PaymentInfo> RefundPaymentAsync(decimal amount, string currency, bool isManualEntry, ExtensionTransaction extensionTransactionProperties)
            {
                if (amount < this.terminalSettings.MinimumAmountAllowed)
                {
                    throw new CardPaymentException(CardPaymentException.AmountLessThanMinimumLimit, "Amount does not meet minimum amount allowed.");
                }

                if (this.terminalSettings.MaximumAmountAllowed > 0 && amount > this.terminalSettings.MaximumAmountAllowed)
                {
                    throw new CardPaymentException(CardPaymentException.AmountExceedsMaximumLimit, "Amount exceeds the maximum amount allowed.");
                }

                if (this.processor == null)
                {
                    this.processor = CardPaymentManager.GetPaymentProcessor(this.merchantProperties, this.paymentConnectorName);
                }

                PaymentInfo paymentInfo = new PaymentInfo();

                // Get tender
                TenderInfo maskedTenderInfo = await this.GetTenderAsync(false);

                if (maskedTenderInfo == null)
                {
                    return(paymentInfo);
                }

                paymentInfo.CardNumberMasked = maskedTenderInfo.CardNumber;
                paymentInfo.CashbackAmount   = maskedTenderInfo.CashBackAmount;
                paymentInfo.CardType         = (Microsoft.Dynamics.Commerce.HardwareStation.CardPayment.CardType)maskedTenderInfo.CardTypeId;

                if (paymentInfo.CashbackAmount > this.terminalSettings.DebitCashbackLimit)
                {
                    throw new CardPaymentException(CardPaymentException.CashbackAmountExceedsLimit, "Cashback amount exceeds the maximum amount allowed.");
                }

                // Refund
                Response response = CardPaymentManager.ChainedRefundCall(this.processor, this.merchantProperties, this.tenderInfo, amount, currency, this.terminalSettings.Locale, this.isTestMode, this.terminalSettings.TerminalId, extensionTransactionProperties);

                CardPaymentManager.MapRefundResponse(response, paymentInfo);

                if (paymentInfo.IsApproved)
                {
                    // need signature?
                    if (this.terminalSettings.SignatureCaptureMinimumAmount < paymentInfo.ApprovedAmount)
                    {
                        paymentInfo.SignatureData = await this.RequestTenderApprovalAsync(paymentInfo.ApprovedAmount);
                    }
                }

                return(paymentInfo);
            }
        private async Task <PaymentInfo> AuthorizePaymentAsync(string paymentConnectorName, decimal amount, string currency, TenderInfo tenderInfo, ExtensionTransaction extensionTransactionProperties)
        {
            // Several below values are hardcoded, real implementations should take this data from real device.
            var paymentInfo = CreateAuthorizationSuccessPaymentInfo(amount);

            return(await Task.FromResult(paymentInfo).ConfigureAwait(false));
        }
            /// <summary>
            /// Make reversal/void a payment.
            /// </summary>
            /// <param name="amount">The amount.</param>
            /// <param name="currency">The currency.</param>
            /// <param name="paymentPropertiesXml">The payment properties of the authorization response.</param>
            /// <param name="extensionTransactionProperties">Optional extension transaction properties.</param>
            /// <returns>A task that can await until the void has completed.</returns>
            public virtual async Task <PaymentInfo> VoidPaymentAsync(decimal amount, string currency, string paymentPropertiesXml, ExtensionTransaction extensionTransactionProperties)
            {
                PaymentProperty[] properties = CardPaymentManager.ToLocalProperties(paymentPropertiesXml);

                try
                {
                    return(await this.paymentDevice.VoidPaymentAsync(amount, currency, properties, extensionTransactionProperties));
                }
                catch (PaymentException paymentException)
                {
                    // When payment is already voided, treat it as success.
                    if (paymentException.PaymentSdkErrors != null &&
                        paymentException.PaymentSdkErrors.Count == 1 &&
                        paymentException.PaymentSdkErrors[0].Code == ErrorCode.AuthorizationIsVoided)
                    {
                        PaymentInfo paymentInfo = new PaymentInfo();
                        paymentInfo.IsApproved = true;

                        return(await Task.FromResult <PaymentInfo>(paymentInfo));
                    }
                    else
                    {
                        throw paymentException;
                    }
                }
            }