コード例 #1
0
        public PayPalResponse Refund(PayPalApiSettingsBase settings, PayPalSessionData session, RefundPaymentRequest request)
        {
            var data   = new Dictionary <string, object>();
            var store  = _services.StoreService.GetStoreById(request.Order.StoreId);
            var isSale = request.Order.AuthorizationTransactionResult.Contains("(sale)");

            var path = "/v1/payments/{0}/{1}/refund".FormatInvariant(isSale ? "sale" : "capture", request.Order.CaptureTransactionId);

            var amount = new Dictionary <string, object>();

            amount.Add("total", request.AmountToRefund.FormatInvariant());
            amount.Add("currency", store.PrimaryStoreCurrency.CurrencyCode);

            data.Add("amount", amount);

            var result = CallApi("POST", path, session.AccessToken, settings, data.Any() ? JsonConvert.SerializeObject(data) : null);

            if (result.Success && result.Json != null)
            {
                result.Id = (string)result.Json.id;
            }

            //Logger.InsertLog(LogLevel.Information, "PayPal Refund", JsonConvert.SerializeObject(data, Formatting.Indented) + "\r\n\r\n" + (result.Json != null ? result.Json.ToString() : ""));

            return(result);
        }
コード例 #2
0
        public PayPalResponse Capture(PayPalApiSettingsBase settings, PayPalSessionData session, CapturePaymentRequest request)
        {
            var data = new Dictionary <string, object>();
            //var isAuthorize = request.Order.AuthorizationTransactionCode.IsCaseInsensitiveEqual("authorize");

            var path = "/v1/payments/authorization/{0}/capture".FormatInvariant(request.Order.AuthorizationTransactionId);

            var store = _services.StoreService.GetStoreById(request.Order.StoreId);

            var amount = new Dictionary <string, object>();

            amount.Add("total", request.Order.OrderTotal.FormatInvariant());
            amount.Add("currency", store.PrimaryStoreCurrency.CurrencyCode);

            data.Add("amount", amount);

            var result = CallApi("POST", path, session.AccessToken, settings, JsonConvert.SerializeObject(data));

            if (result.Success && result.Json != null)
            {
                result.Id = (string)result.Json.id;
            }

            return(result);
        }
コード例 #3
0
        public PayPalResponse EnsureAccessToken(PayPalSessionData session, PayPalApiSettingsBase settings)
        {
            if (session.AccessToken.IsEmpty() || DateTime.UtcNow >= session.TokenExpiration)
            {
                var result = CallApi("POST", "/v1/oauth2/token", null, settings, "grant_type=client_credentials");

                if (result.Success)
                {
                    session.AccessToken = (string)result.Json.access_token;

                    var expireSeconds = ((string)result.Json.expires_in).ToInt(5 * 60);

                    session.TokenExpiration = DateTime.UtcNow.AddSeconds(expireSeconds);
                }
                else
                {
                    return(result);
                }
            }

            return(new PayPalResponse
            {
                Success = session.AccessToken.HasValue()
            });
        }
コード例 #4
0
        public PayPalResponse GetPayment(PayPalApiSettingsBase settings, PayPalSessionData session)
        {
            var result = CallApi("GET", "/v1/payments/payment/" + session.PaymentId, session.AccessToken, settings, null);

            if (result.Success && result.Json != null)
            {
                result.Id = (string)result.Json.id;
            }

            return(result);
        }
コード例 #5
0
        public PayPalResponse DeleteWebhook(PayPalApiSettingsBase settings, PayPalSessionData session)
        {
            var result = CallApi("DELETE", "/v1/notifications/webhooks/" + settings.WebhookId, session.AccessToken, settings, null);

            if (result.Success && result.Json != null)
            {
                result.Id = (string)result.Json.id;
            }

            return(result);
        }
コード例 #6
0
        public PayPalResponse Void(PayPalApiSettingsBase settings, PayPalSessionData session, VoidPaymentRequest request)
        {
            var path = "/v1/payments/authorization/{0}/void".FormatInvariant(request.Order.AuthorizationTransactionId);

            var result = CallApi("POST", path, session.AccessToken, settings, null);

            if (result.Success && result.Json != null)
            {
                result.Id = (string)result.Json.id;
            }

            return(result);
        }
コード例 #7
0
        public PayPalResponse CreateWebhook(PayPalApiSettingsBase settings, PayPalSessionData session, string url)
        {
            var data   = new Dictionary <string, object>();
            var events = new List <Dictionary <string, object> >();

            events.Add(new Dictionary <string, object> {
                { "name", "PAYMENT.AUTHORIZATION.VOIDED" }
            });
            events.Add(new Dictionary <string, object> {
                { "name", "PAYMENT.CAPTURE.COMPLETED" }
            });
            events.Add(new Dictionary <string, object> {
                { "name", "PAYMENT.CAPTURE.DENIED" }
            });
            events.Add(new Dictionary <string, object> {
                { "name", "PAYMENT.CAPTURE.PENDING" }
            });
            events.Add(new Dictionary <string, object> {
                { "name", "PAYMENT.CAPTURE.REFUNDED" }
            });
            events.Add(new Dictionary <string, object> {
                { "name", "PAYMENT.CAPTURE.REVERSED" }
            });
            events.Add(new Dictionary <string, object> {
                { "name", "PAYMENT.SALE.COMPLETED" }
            });
            events.Add(new Dictionary <string, object> {
                { "name", "PAYMENT.SALE.DENIED" }
            });
            events.Add(new Dictionary <string, object> {
                { "name", "PAYMENT.SALE.PENDING" }
            });
            events.Add(new Dictionary <string, object> {
                { "name", "PAYMENT.SALE.REFUNDED" }
            });
            events.Add(new Dictionary <string, object> {
                { "name", "PAYMENT.SALE.REVERSED" }
            });

            data.Add("url", url);
            data.Add("event_types", events);

            var result = CallApi("POST", "/v1/notifications/webhooks", session.AccessToken, settings, JsonConvert.SerializeObject(data));

            if (result.Success && result.Json != null)
            {
                result.Id = (string)result.Json.id;
            }

            return(result);
        }
コード例 #8
0
        public PayPalResponse ExecutePayment(PayPalApiSettingsBase settings, PayPalSessionData session)
        {
            var data = new Dictionary <string, object>();

            data.Add("payer_id", session.PayerId);

            var result = CallApi("POST", "/v1/payments/payment/{0}/execute".FormatInvariant(session.PaymentId), session.AccessToken, settings, JsonConvert.SerializeObject(data));

            if (result.Success && result.Json != null)
            {
                result.Id = (string)result.Json.id;

                //Logger.InsertLog(LogLevel.Information, "PayPal PLUS", JsonConvert.SerializeObject(data, Formatting.Indented) + "\r\n\r\n" + result.Json.ToString());
            }

            return(result);
        }
コード例 #9
0
        public PayPalResponse DeleteCheckoutExperience(PayPalApiSettingsBase settings, PayPalSessionData session)
        {
            var result = CallApi("DELETE", "/v1/payment-experience/web-profiles/" + settings.ExperienceProfileId, session.AccessToken, settings, null);

            if (result.Success && result.Json != null)
            {
                result.Id = (string)result.Json.id;
            }

            return(result);
        }
コード例 #10
0
        public PayPalResponse UpsertCheckoutExperience(PayPalApiSettingsBase settings, PayPalSessionData session, Store store)
        {
            PayPalResponse result;
            var            name = store.Name;
            var            logo = _pictureService.Value.GetPictureById(store.LogoPictureId);
            var            path = "/v1/payment-experience/web-profiles";

            var data         = new Dictionary <string, object>();
            var presentation = new Dictionary <string, object>();
            var inpuFields   = new Dictionary <string, object>();

            // find existing profile id, only one profile per profile name possible
            if (settings.ExperienceProfileId.IsEmpty())
            {
                result = CallApi("GET", path, session.AccessToken, settings, null);
                if (result.Success && result.Json != null)
                {
                    foreach (var profile in result.Json)
                    {
                        var profileName = (string)profile.name;
                        if (profileName.IsCaseInsensitiveEqual(name))
                        {
                            settings.ExperienceProfileId = (string)profile.id;
                            break;
                        }
                    }
                }
            }

            presentation.Add("brand_name", name);
            presentation.Add("locale_code", _services.WorkContext.WorkingLanguage.UniqueSeoCode.EmptyNull().ToUpper());

            if (logo != null)
            {
                presentation.Add("logo_image", _pictureService.Value.GetPictureUrl(logo, showDefaultPicture: false, storeLocation: store.Url));
            }

            inpuFields.Add("allow_note", false);
            inpuFields.Add("no_shipping", 0);
            inpuFields.Add("address_override", 1);

            data.Add("name", name);
            data.Add("presentation", presentation);
            data.Add("input_fields", inpuFields);

            if (settings.ExperienceProfileId.HasValue())
            {
                path = string.Concat(path, "/", HttpUtility.UrlPathEncode(settings.ExperienceProfileId));
            }

            result = CallApi(settings.ExperienceProfileId.HasValue() ? "PUT" : "POST", path, session.AccessToken, settings, JsonConvert.SerializeObject(data));

            if (result.Success)
            {
                if (result.Json != null)
                {
                    result.Id = (string)result.Json.id;
                }
                else
                {
                    result.Id = settings.ExperienceProfileId;
                }
            }

            return(result);
        }
コード例 #11
0
        public PayPalResponse CreatePayment(
            PayPalApiSettingsBase settings,
            PayPalSessionData session,
            List <OrganizedShoppingCartItem> cart,
            string providerSystemName,
            string returnUrl,
            string cancelUrl)
        {
            var store        = _services.StoreContext.CurrentStore;
            var customer     = _services.WorkContext.CurrentCustomer;
            var language     = _services.WorkContext.WorkingLanguage;
            var currencyCode = store.PrimaryStoreCurrency.CurrencyCode;

            var dateOfBirth = customer.GetAttribute <DateTime?>(SystemCustomerAttributeNames.DateOfBirth);

            Discount orderAppliedDiscount;
            List <AppliedGiftCard> appliedGiftCards;
            int     redeemedRewardPoints = 0;
            decimal redeemedRewardPointsAmount;
            decimal orderDiscountInclTax;
            decimal totalOrderItems = decimal.Zero;

            var includingTax = (_services.WorkContext.GetTaxDisplayTypeFor(customer, store.Id) == TaxDisplayType.IncludingTax);

            var shipping = (_orderTotalCalculationService.GetShoppingCartShippingTotal(cart) ?? decimal.Zero);

            var paymentFee = _paymentService.GetAdditionalHandlingFee(cart, providerSystemName);

            var total = (_orderTotalCalculationService.GetShoppingCartTotal(cart, out orderDiscountInclTax, out orderAppliedDiscount, out appliedGiftCards,
                                                                            out redeemedRewardPoints, out redeemedRewardPointsAmount) ?? decimal.Zero);

            var data          = new Dictionary <string, object>();
            var redirectUrls  = new Dictionary <string, object>();
            var payer         = new Dictionary <string, object>();
            var payerInfo     = new Dictionary <string, object>();
            var transaction   = new Dictionary <string, object>();
            var amount        = new Dictionary <string, object>();
            var amountDetails = new Dictionary <string, object>();
            var items         = new List <Dictionary <string, object> >();
            var itemList      = new Dictionary <string, object>();

            // "PayPal PLUS only supports transaction type “Sale” (instant settlement)"
            if (providerSystemName == PayPalPlusProvider.SystemName)
            {
                data.Add("intent", "sale");
            }
            else
            {
                data.Add("intent", settings.TransactMode == TransactMode.AuthorizeAndCapture ? "sale" : "authorize");
            }

            if (settings.ExperienceProfileId.HasValue())
            {
                data.Add("experience_profile_id", settings.ExperienceProfileId);
            }

            // redirect urls
            if (returnUrl.HasValue())
            {
                redirectUrls.Add("return_url", returnUrl);
            }

            if (cancelUrl.HasValue())
            {
                redirectUrls.Add("cancel_url", cancelUrl);
            }

            if (redirectUrls.Any())
            {
                data.Add("redirect_urls", redirectUrls);
            }

            // payer, payer_info
            if (dateOfBirth.HasValue)
            {
                payerInfo.Add("birth_date", dateOfBirth.Value.ToString("yyyy-MM-dd"));
            }
            if (customer.BillingAddress != null)
            {
                payerInfo.Add("billing_address", CreateAddress(customer.BillingAddress, false));
            }

            payer.Add("payment_method", "paypal");
            payer.Add("payer_info", payerInfo);
            data.Add("payer", payer);

            // line items
            foreach (var item in cart)
            {
                decimal unitPriceTaxRate = decimal.Zero;
                decimal unitPrice        = _priceCalculationService.GetUnitPrice(item, true);
                decimal productPrice     = _taxService.GetProductPrice(item.Item.Product, unitPrice, includingTax, customer, out unitPriceTaxRate);

                var line = new Dictionary <string, object>();
                line.Add("quantity", item.Item.Quantity);
                line.Add("name", item.Item.Product.GetLocalized(x => x.Name, language.Id, true, false).Truncate(127));
                line.Add("price", productPrice.FormatInvariant());
                line.Add("currency", currencyCode);
                line.Add("sku", item.Item.Product.Sku.Truncate(50));
                items.Add(line);

                totalOrderItems += (productPrice * item.Item.Quantity);
            }

            var itemsPlusMisc = (totalOrderItems + shipping + paymentFee);

            if (total != itemsPlusMisc)
            {
                var line = new Dictionary <string, object>();
                line.Add("quantity", "1");
                line.Add("name", T("Plugins.cloudCommerce.PayPal.Other").Text.Truncate(127));
                line.Add("price", (total - itemsPlusMisc).FormatInvariant());
                line.Add("currency", currencyCode);
                items.Add(line);

                totalOrderItems += (total - itemsPlusMisc);
            }

            itemList.Add("items", items);
            if (customer.ShippingAddress != null)
            {
                itemList.Add("shipping_address", CreateAddress(customer.ShippingAddress, true));
            }

            // transactions
            amountDetails.Add("shipping", shipping.FormatInvariant());
            amountDetails.Add("subtotal", totalOrderItems.FormatInvariant());
            if (!includingTax)
            {
                // "To avoid rounding errors we recommend not submitting tax amounts on line item basis.
                // Calculated tax amounts for the entire shopping basket may be submitted in the amount objects.
                // In this case the item amounts will be treated as amounts excluding tax.
                // In a B2C scenario, where taxes are included, no taxes should be submitted to PayPal."

                SortedDictionary <decimal, decimal> taxRates = null;
                var taxTotal = _orderTotalCalculationService.GetTaxTotal(cart, out taxRates);

                amountDetails.Add("tax", taxTotal.FormatInvariant());
            }
            if (paymentFee != decimal.Zero)
            {
                amountDetails.Add("handling_fee", paymentFee.FormatInvariant());
            }

            amount.Add("total", total.FormatInvariant());
            amount.Add("currency", currencyCode);
            amount.Add("details", amountDetails);

            transaction.Add("amount", amount);
            transaction.Add("item_list", itemList);
            transaction.Add("invoice_number", session.OrderGuid.ToString());

            data.Add("transactions", new List <Dictionary <string, object> > {
                transaction
            });

            var result = CallApi("POST", "/v1/payments/payment", session.AccessToken, settings, JsonConvert.SerializeObject(data));

            if (result.Success && result.Json != null)
            {
                result.Id = (string)result.Json.id;
            }

            //Logger.InsertLog(LogLevel.Information, "PayPal PLUS", JsonConvert.SerializeObject(data, Formatting.Indented) + "\r\n\r\n" + (result.Json != null ? result.Json.ToString() : ""));

            return(result);
        }