Exemplo n.º 1
0
    /// <summary>
    /// Request an immediate transaction for the booking cancellation fee, if any
    /// (cancellation must be previously calculated on the booking, with amounts at pricing totalPrice and serviceFeeAmount, as usual).
    /// It manages when there is no price to charge, and just skip the step without error.
    /// The removal of a temporary card is performed after all (doesn't matter if a transaction was needed or not).
    /// The transaction is "immediate" because is asked to be submitted and released now (the flow
    /// for a normal booking payment is to authorize, later settle, later release, but on this case
    /// we require to Braintree to do all that steps at the moment).
    ///
    /// REVIEWED #771
    /// </summary>
    /// <param name="booking"></param>
    /// <returns>It returns the transactionID generated, original booking object is not updated.
    /// Errors in the process are throwed.</returns>
    public static string BookingCancellationPaymentFromCard(LcRest.Booking booking)
    {
        string cancellationTransactionID = null;
        var    gateway = NewBraintreeGateway();

        if (booking.pricingSummary.totalPrice.HasValue && booking.pricingSummary.totalPrice > 0)
        {
            if (String.IsNullOrEmpty(booking.paymentMethodID))
            {
                throw new ConstraintException("Cannot charge booking cancellation fee because there is no payment method.");
            }

            TransactionRequest request = new TransactionRequest
            {
                Amount = booking.pricingSummary.totalPrice.Value,
                // Marketplace #408: since provider receive the money directly, Braintree must discount
                // the next amount in concept of fees and pay that to the Marketplace Owner (us, Loconomics)
                ServiceFeeAmount   = booking.pricingSummary.serviceFeeAmount,
                CustomerId         = GetCustomerId(booking.clientUserID),
                PaymentMethodToken = booking.paymentMethodID,
                // Now, with Marketplace #408, the receiver of the money for each transaction is
                // the provider through account at Braintree, and not the Loconomics account:
                //MerchantAccountId = LcPayment.BraintreeMerchantAccountId,
                MerchantAccountId = GetProviderPaymentAccountId(booking.serviceProfessionalUserID),
                // We explicitely ask for an immediate transaction (it's the default, but let's being explicit):
                Options = new TransactionOptionsRequest
                {
                    // Marketplace #408: we normally hold it, but this is a cancellation so don't hold, pay at the moment
                    HoldInEscrow = false,
                    // Submit now for charge
                    SubmitForSettlement = true
                }
            };

            var r = gateway.Transaction.Sale(request);

            if (!r.IsSuccess())
            {
                throw new Exception(r.Message);
            }
            // Get the transactionID
            else if (r.Target != null &&
                     !String.IsNullOrEmpty(r.Target.Id))
            {
                cancellationTransactionID = r.Target.Id;
            }
        }

        // Remove temporary card: It's a complementary task, so we avoid exceptions (if possible) to interrupt the process
        try
        {
            // If the card is a TEMPorarly card (just to perform this transaction)
            // it must be removed now since was successful used
            if (booking.paymentMethodID.StartsWith(TempSavedCardPrefix))
            {
                gateway.CreditCard.Delete(booking.paymentMethodID);
            }
        }
        catch { }

        return(cancellationTransactionID);
    }
Exemplo n.º 2
0
    /// <summary>
    /// Performs a transaction to authorize the payment on the client payment method, but
    /// not charging still, using the data from the given booking and the saved paymentMethodID.
    /// Booking is NOT checked before perform the task, use the LcRest.Booking API to securely run pre-condition
    /// checks before authorize transaction. The booking must have the data loaded for the pricingSummary.
    ///
    /// REVIEWED #771
    /// </summary>
    /// <param name="booking"></param>
    /// <param name="paymentMethodID">AKA creditCardToken</param>
    /// <returns>It returns the transactionID generated, original booking object is not updated.
    /// Errors in the process are throwed.</returns>
    public static string AuthorizeBookingTransaction(LcRest.Booking booking)
    {
        if (booking.pricingSummary == null ||
            !booking.pricingSummary.totalPrice.HasValue ||
            booking.pricingSummary.totalPrice.Value <= 0)
        {
            throw new ConstraintException("To authorize a booking payment is required a price to charge.");
        }

        var gateway = NewBraintreeGateway();

        TransactionRequest request = new TransactionRequest
        {
            Amount = booking.pricingSummary.totalPrice.Value,
            // Marketplace #408: since provider receive the money directly, Braintree must discount
            // the next amount in concept of fees and pay that to the Marketplace Owner (us, Loconomics ;-)
            ServiceFeeAmount   = booking.pricingSummary.serviceFeeAmount,
            CustomerId         = GetCustomerId(booking.clientUserID),
            PaymentMethodToken = booking.paymentMethodID,
            // Now, with Marketplace #408, the receiver of the money for each transaction is
            // the provider through account at Braintree, and not the Loconomics account:
            //MerchantAccountId = LcPayment.BraintreeMerchantAccountId,
            MerchantAccountId = GetProviderPaymentAccountId(booking.serviceProfessionalUserID),
            Options           = new TransactionOptionsRequest
            {
                // Marketplace #408: don't pay provider still, wait for the final confirmation 'release scrow'
                HoldInEscrow = true,
                // Do not submit, just authorize:
                SubmitForSettlement = false
            }
        };

        var r = gateway.Transaction.Sale(request);

        // Everything goes fine
        if (r.IsSuccess())
        {
            // Get the transactionID
            if (r.Target != null &&
                !String.IsNullOrEmpty(r.Target.Id))
            {
                // If the card is a TEMPorarly card (just to perform this transaction)
                // it must be removed now since was successful used
                // IMPORTANT: Since an error on this subtask is not important to the
                // user and will break a success process creating a new problem if throwed (because transactionID
                // gets lost),
                // is catched and managed internally by Loconomics stuff that can check and fix transparentely
                // this minor error.
                try
                {
                    if (booking.paymentMethodID.StartsWith(TempSavedCardPrefix))
                    {
                        gateway.CreditCard.Delete(booking.paymentMethodID);
                    }
                }
                catch (Exception ex)
                {
                    try
                    {
                        LcMessaging.NotifyError(String.Format("LcPayment.AuthorizeBookingTransaction..DeleteBraintreeTempCard({0});bookingID={1}", booking.paymentMethodID, booking.bookingID), "", ex.Message);
                        LcLogger.LogAspnetError(ex);
                    }
                    catch { }
                }

                // r.Target.Id => transactionID
                return(r.Target.Id);
            }
            else
            {
                // Transaction worked but impossible to know the transactionID (weird, is even possible?),
                // notify error
                throw new Exception("Impossible to know transaction details, please contact support. BookingID #" + booking.bookingID.ToString());
            }
        }
        else
        {
            throw new Exception(r.Message);
        }
    }