Klicken Sie unter Verkäufer/Händler auf API-Zugriff.
+
Klicken Sie auf API-Berechtigung anfordern.
+
Wählen Sie die Option Fordern Sie eine API-Signature an.
+
Klicken Sie auf Zustimmen und senden.
+
+
Aktivieren Sie optional den PayPal-Service zum Empfang von IPN-Nachrichten (Instant Payment Notification):
+
+
In Ihr Premier- oder Business-Konto einloggen.
+
Auf den Register Mein Profil klicken.
+
Unter Sprach-Kodierung > Weitere Einstellungen wählen Sie bitte UTF-8.
+
Sofortige Zahlungsbestätigung klicken.
+
Einstellungen für sofortige Zahlungsbestätigungen wählen klicken.
+
Bei Benachrichtigungs-URL die URL Ihres IPN-Handlers (https://www.yourStore.com/Plugins/SmartStore.PayPal/PayPalPlus/IPNHandler) eingeben.
+
Speichern klicken. Danach sollten Sie eine Nachricht über die erfolgreiche Aktivierung von IPN erhalten.
+ ]]>
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Plugins/SmartStore.PayPal/Localization/resources.en-us.xml b/src/Plugins/SmartStore.PayPal/Localization/resources.en-us.xml
index 9dbfca9abc..24db661f71 100644
--- a/src/Plugins/SmartStore.PayPal/Localization/resources.en-us.xml
+++ b/src/Plugins/SmartStore.PayPal/Localization/resources.en-us.xml
@@ -4,7 +4,23 @@
PayPal Payment Methods
- Provides the PayPal payment methods PayPal Express, PayPal Standard and PayPal Direct.
+ Provides the PayPal payment methods PayPal Standard, PayPal Direct, PayPal Express and PayPal Plus.
+
+
+
+ API access;Data exchange;Miscellaneous
+
+
+ Authorize immediately, debit later
+
+
+ Immediately debit
+
+
+ Show button in mini shopping cart
+
+
+ Soecifies to show the checkout button in the mini shopping cart.
@@ -334,4 +350,37 @@ Payment fee: {10}]]>
+
+
+ PayPal Plus
+
+
+
+
+
+ If you're using PayPal ensure that your primary store currency is supported by Paypal.
+
+
Log into your PayPal account.
+
Click on Profile from the Home Menu.
+
Under Account Information choose API Access.
+
Choose Request API credentials.
+
Choose API Signature as the credential type.
+
Enable the checkbox and agree to the license Terms-I agree to the API Certificate Terms of Use and terms incorporated therein and press the Submit button.
+
+
Before being able to receive IPN (Instant Payment Notification) messages (optional), you'll need to activate this service; follow these steps:
+
+
Log in to your Premier or Business account.
+
Click the Profile subtab.
+
Click Language Encoding and More options and select UTF-8.
+
Click Instant Payment Notification in the Selling Preferences column.
+
Click the Edit IPN Settings button to update your settings.
+
Select Receive IPN messages (enabled) and enter the URL of your IPN handler (https://www.yourStore.com/Plugins/SmartStore.PayPal/PayPalPlus/IPNHandler).
+
Click Save, and you should get a message that you have successfully activated IPN.
+ ]]>
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Plugins/SmartStore.PayPal/Models/ApiConfigurationModels.cs b/src/Plugins/SmartStore.PayPal/Models/ApiConfigurationModels.cs
index ed2526fbc4..9d697dd85d 100644
--- a/src/Plugins/SmartStore.PayPal/Models/ApiConfigurationModels.cs
+++ b/src/Plugins/SmartStore.PayPal/Models/ApiConfigurationModels.cs
@@ -130,4 +130,41 @@ public void Copy(PayPalExpressPaymentSettings settings, bool fromSettings)
}
}
}
+
+
+ public class PayPalPlusConfigurationModel : ApiConfigurationModel
+ {
+ [SmartResourceDisplayName("Plugins.SmartStore.PayPal.ShowButtonInMiniShoppingCart")]
+ public bool ShowButtonInMiniShoppingCart { get; set; }
+
+ public void Copy(PayPalPlusPaymentSettings settings, bool fromSettings)
+ {
+ if (fromSettings)
+ {
+ SecurityProtocol = settings.SecurityProtocol;
+ UseSandbox = settings.UseSandbox;
+ IpnChangesPaymentStatus = settings.IpnChangesPaymentStatus;
+ TransactMode = Convert.ToInt32(settings.TransactMode);
+ ApiAccountName = settings.ApiAccountName;
+ ApiAccountPassword = settings.ApiAccountPassword;
+ Signature = settings.Signature;
+ AdditionalFee = settings.AdditionalFee;
+ AdditionalFeePercentage = settings.AdditionalFeePercentage;
+ ShowButtonInMiniShoppingCart = settings.ShowButtonInMiniShoppingCart;
+ }
+ else
+ {
+ settings.SecurityProtocol = SecurityProtocol;
+ settings.UseSandbox = UseSandbox;
+ settings.IpnChangesPaymentStatus = IpnChangesPaymentStatus;
+ settings.TransactMode = (TransactMode)TransactMode;
+ settings.ApiAccountName = ApiAccountName;
+ settings.ApiAccountPassword = ApiAccountPassword;
+ settings.Signature = Signature;
+ settings.AdditionalFee = AdditionalFee;
+ settings.AdditionalFeePercentage = AdditionalFeePercentage;
+ settings.ShowButtonInMiniShoppingCart = ShowButtonInMiniShoppingCart;
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/src/Plugins/SmartStore.PayPal/Plugin.cs b/src/Plugins/SmartStore.PayPal/Plugin.cs
index 0883d41784..336c38f253 100644
--- a/src/Plugins/SmartStore.PayPal/Plugin.cs
+++ b/src/Plugins/SmartStore.PayPal/Plugin.cs
@@ -28,6 +28,7 @@ public override void Install()
_settingService.SaveSetting(new PayPalExpressPaymentSettings());
_settingService.SaveSetting(new PayPalDirectPaymentSettings());
_settingService.SaveSetting(new PayPalStandardPaymentSettings());
+ _settingService.SaveSetting(new PayPalPlusPaymentSettings());
_localizationService.ImportPluginResourcesFromXml(this.PluginDescriptor);
@@ -39,6 +40,7 @@ public override void Uninstall()
_settingService.DeleteSetting();
_settingService.DeleteSetting();
_settingService.DeleteSetting();
+ _settingService.DeleteSetting();
_localizationService.DeleteLocaleStringResources(PluginDescriptor.ResourceRootKey);
diff --git a/src/Plugins/SmartStore.PayPal/Providers/PayPalPlusProvider.cs b/src/Plugins/SmartStore.PayPal/Providers/PayPalPlusProvider.cs
new file mode 100644
index 0000000000..d18f0759dc
--- /dev/null
+++ b/src/Plugins/SmartStore.PayPal/Providers/PayPalPlusProvider.cs
@@ -0,0 +1,62 @@
+using System;
+using SmartStore.Core.Domain.Payments;
+using SmartStore.Core.Plugins;
+using SmartStore.PayPal.Controllers;
+using SmartStore.PayPal.Settings;
+using SmartStore.Services.Payments;
+
+namespace SmartStore.PayPal
+{
+ [SystemName("Payments.PayPalPlus")]
+ [FriendlyName("PayPal Plus")]
+ [DisplayOrder(1)]
+ public partial class PayPalPlusProvider : PayPalProviderBase
+ {
+ public PayPalPlusProvider()
+ {
+ }
+
+ public static string SystemName
+ {
+ get { return "Payments.PayPalPlus"; }
+ }
+
+ public override PaymentMethodType PaymentMethodType
+ {
+ get
+ {
+ return PaymentMethodType.StandardAndRedirection;
+ }
+ }
+
+ protected override string GetResourceRootKey()
+ {
+ return "Plugins.Payments.PayPalPlus";
+ }
+
+ protected override string GetControllerName()
+ {
+ return "PayPalPlus";
+ }
+
+ ///
+ /// Process a payment
+ ///
+ /// Payment info required for an order processing
+ /// Process payment result
+ public override ProcessPaymentResult ProcessPayment(ProcessPaymentRequest processPaymentRequest)
+ {
+ var result = new ProcessPaymentResult
+ {
+ NewPaymentStatus = PaymentStatus.Pending
+ };
+
+ return result;
+ }
+
+ public override Type GetControllerType()
+ {
+ return typeof(PayPalPlusController);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Plugins/SmartStore.PayPal/Settings/PayPalSettings.cs b/src/Plugins/SmartStore.PayPal/Settings/PayPalSettings.cs
index 9e728d3e40..2b48ebc678 100644
--- a/src/Plugins/SmartStore.PayPal/Settings/PayPalSettings.cs
+++ b/src/Plugins/SmartStore.PayPal/Settings/PayPalSettings.cs
@@ -36,6 +36,7 @@ public abstract class PayPalApiSettingsBase : PayPalSettingsBase
public string Signature { get; set; }
}
+
public class PayPalDirectPaymentSettings : PayPalApiSettingsBase, ISettings
{
public PayPalDirectPaymentSettings()
@@ -84,7 +85,20 @@ public PayPalExpressPaymentSettings()
public decimal DefaultShippingPrice { get; set; }
}
- public class PayPalStandardPaymentSettings : PayPalSettingsBase, ISettings
+ public class PayPalPlusPaymentSettings : PayPalApiSettingsBase, ISettings
+ {
+ public PayPalPlusPaymentSettings()
+ {
+ UseSandbox = true;
+ }
+
+ ///
+ /// Specifies whether to display the checkout button in mini shopping cart
+ ///
+ public bool ShowButtonInMiniShoppingCart { get; set; }
+ }
+
+ public class PayPalStandardPaymentSettings : PayPalSettingsBase, ISettings
{
public PayPalStandardPaymentSettings()
{
@@ -101,18 +115,13 @@ public PayPalStandardPaymentSettings()
public string IpnUrl { get; set; }
}
- ///
- /// Represents payment processor transaction mode
- ///
- public enum TransactMode : int
+
+ ///
+ /// Represents payment processor transaction mode
+ ///
+ public enum TransactMode
{
- ///
- /// Authorize
- ///
Authorize = 1,
- ///
- /// Authorize and capture
- ///
AuthorizeAndCapture = 2
}
}
diff --git a/src/Plugins/SmartStore.PayPal/SmartStore.PayPal.csproj b/src/Plugins/SmartStore.PayPal/SmartStore.PayPal.csproj
index 57974e8e71..4e90e87d49 100644
--- a/src/Plugins/SmartStore.PayPal/SmartStore.PayPal.csproj
+++ b/src/Plugins/SmartStore.PayPal/SmartStore.PayPal.csproj
@@ -115,6 +115,7 @@
Properties\AssemblyVersionInfo.cs
+
@@ -127,6 +128,7 @@
+
@@ -172,6 +174,9 @@
+
+ PreserveNewest
+ PreserveNewest
@@ -183,9 +188,6 @@
PreserveNewest
-
- Always
- Always
@@ -271,6 +273,9 @@
PreserveNewest
+
+ PreserveNewest
+ Designer
diff --git a/src/Plugins/SmartStore.PayPal/Views/PayPalDirect/Configure.cshtml b/src/Plugins/SmartStore.PayPal/Views/PayPalDirect/Configure.cshtml
index 2a07a8326d..128ae981b6 100644
--- a/src/Plugins/SmartStore.PayPal/Views/PayPalDirect/Configure.cshtml
+++ b/src/Plugins/SmartStore.PayPal/Views/PayPalDirect/Configure.cshtml
@@ -15,7 +15,7 @@
+}
\ No newline at end of file
diff --git a/src/Plugins/SmartStore.PayPal/Views/PayPalStandard/Configure.cshtml b/src/Plugins/SmartStore.PayPal/Views/PayPalStandard/Configure.cshtml
index fdd6911358..5846c1ed43 100644
--- a/src/Plugins/SmartStore.PayPal/Views/PayPalStandard/Configure.cshtml
+++ b/src/Plugins/SmartStore.PayPal/Views/PayPalStandard/Configure.cshtml
@@ -14,7 +14,7 @@
\ No newline at end of file
diff --git a/src/Plugins/SmartStore.PayPal/Views/PayPalPlus/PaymentWallScripting.cshtml b/src/Plugins/SmartStore.PayPal/Views/PayPalPlus/PaymentWallScripting.cshtml
new file mode 100644
index 0000000000..c66219b54f
--- /dev/null
+++ b/src/Plugins/SmartStore.PayPal/Views/PayPalPlus/PaymentWallScripting.cshtml
@@ -0,0 +1,43 @@
+@using SmartStore.PayPal.Models;
+@model PayPalPlusCheckoutModel
+
+
\ No newline at end of file
From 2ff963ab4280f059ae3e5ed8e93a94a6266cc97b Mon Sep 17 00:00:00 2001
From: Marcus Gesing
Date: Sat, 16 Apr 2016 17:19:47 +0200
Subject: [PATCH 006/251] PayPal Plus: Rendering payment wall
---
.../Controllers/PayPalPlusController.cs | 43 +++---
.../Localization/resources.de-de.xml | 27 ++--
.../Localization/resources.en-us.xml | 28 ++--
.../Models/PayPalPlusCheckoutModel.cs | 1 +
.../Services/IPayPalService.cs | 7 +-
.../Services/PayPalService.cs | 135 +++++++++++++++---
.../Views/PayPalPlus/Configure.cshtml | 2 +-
.../Views/PayPalPlus/PaymentWall.cshtml | 14 +-
.../PayPalPlus/PaymentWallScripting.cshtml | 69 ++++-----
9 files changed, 207 insertions(+), 119 deletions(-)
diff --git a/src/Plugins/SmartStore.PayPal/Controllers/PayPalPlusController.cs b/src/Plugins/SmartStore.PayPal/Controllers/PayPalPlusController.cs
index bdb302b649..49bb7304da 100644
--- a/src/Plugins/SmartStore.PayPal/Controllers/PayPalPlusController.cs
+++ b/src/Plugins/SmartStore.PayPal/Controllers/PayPalPlusController.cs
@@ -162,35 +162,40 @@ public ActionResult PaymentWall()
model.BillingAddressCountryCode = customer.BillingAddress.Country.TwoLetterIsoCode;
}
- var protocol = (store.SslEnabled ? "https" : "http");
- var returnUrl = Url.Action("CheckoutReturn", "PayPalPlus", new { area = Plugin.SystemName }, protocol);
- var cancelUrl = Url.Action("CheckoutCancel", "PayPalPlus", new { area = Plugin.SystemName }, protocol);
-
-
- var result = _payPalService.EnsureAccessToken(session, settings);
- if (result.Success)
+ if (session.PaymentId.IsEmpty() || session.ApprovalUrl.IsEmpty())
{
- result = _payPalService.UpsertPayment(settings, session, null, returnUrl, cancelUrl);
- if (result.Success && result.Json != null)
+ var result = _payPalService.EnsureAccessToken(session, settings);
+ if (result.Success)
{
- foreach (var link in result.Json.links)
+ var protocol = (store.SslEnabled ? "https" : "http");
+ var returnUrl = Url.Action("CheckoutReturn", "PayPalPlus", new { area = Plugin.SystemName }, protocol);
+ var cancelUrl = Url.Action("CheckoutCancel", "PayPalPlus", new { area = Plugin.SystemName }, protocol);
+
+ result = _payPalService.CreatePayment(settings, session, PayPalPlusProvider.SystemName, returnUrl, cancelUrl);
+ if (result.Success && result.Json != null)
{
- if (((string)link.rel).IsCaseInsensitiveEqual("approval_url"))
+ foreach (var link in result.Json.links)
{
- model.ApprovalUrl = link.href;
- break;
+ if (((string)link.rel).IsCaseInsensitiveEqual("approval_url"))
+ {
+ session.PaymentId = result.Id;
+ session.ApprovalUrl = link.href;
+ break;
+ }
}
}
+ else
+ {
+ model.ErrorMessage = result.ErrorMessage;
+ }
}
- else if (result.ErrorMessage.HasValue())
+ else
{
- ModelState.AddModelError("", result.ErrorMessage);
+ model.ErrorMessage = result.ErrorMessage;
}
}
- else if (result.ErrorMessage.HasValue())
- {
- ModelState.AddModelError("", result.ErrorMessage);
- }
+
+ model.ApprovalUrl = session.ApprovalUrl;
return View(model);
}
diff --git a/src/Plugins/SmartStore.PayPal/Localization/resources.de-de.xml b/src/Plugins/SmartStore.PayPal/Localization/resources.de-de.xml
index 43419425fe..d4abb7441e 100644
--- a/src/Plugins/SmartStore.PayPal/Localization/resources.de-de.xml
+++ b/src/Plugins/SmartStore.PayPal/Localization/resources.de-de.xml
@@ -25,6 +25,9 @@
Jetzt aktualisieren
+
+ Sonstiges
+ Client-ID
@@ -379,27 +382,13 @@ Zahlungsgebühr: {10}]]>
- Stellen Sie bitte sicher, dass PayPal die Primärwährung Ihres Shops unterstützt.
-
-
Loggen Sie sich in Ihr PayPal-Konto ein.
-
Klicken Sie auf den Register Mein Profil.
-
Klicken Sie unter Verkäufer/Händler auf API-Zugriff.
-
Klicken Sie auf API-Berechtigung anfordern.
-
Wählen Sie die Option Fordern Sie eine API-Signature an.
-
Klicken Sie auf Zustimmen und senden.
-
-
Aktivieren Sie optional den PayPal-Service zum Empfang von IPN-Nachrichten (Instant Payment Notification):
-
-
In Ihr Premier- oder Business-Konto einloggen.
-
Auf den Register Mein Profil klicken.
-
Unter Sprach-Kodierung > Weitere Einstellungen wählen Sie bitte UTF-8.
-
Sofortige Zahlungsbestätigung klicken.
-
Einstellungen für sofortige Zahlungsbestätigungen wählen klicken.
-
Bei Benachrichtigungs-URL die URL Ihres IPN-Handlers (https://www.yourStore.com/Plugins/SmartStore.PayPal/PayPalPlus/IPNHandler) eingeben.
-
Speichern klicken. Danach sollten Sie eine Nachricht über die erfolgreiche Aktivierung von IPN erhalten.
- ]]>
+ PayPal PLUS bietet die Möglichkeit per PayPal, Kreditkarte, Lastschriftverfahren und per Rechnung zu bezahlen.
+Die Bezahlung auf Rechnung steht möglicherweise nicht allen Händlern zur Verfügung. PayPal PLUS ist im Moment nur in Deutschland verfügbar.]]>
+
+ Wir können Ihnen leider keine PayPal PLUS Zahlungsart anbieten. Bitte versuchen Sie er später erneut.
+
diff --git a/src/Plugins/SmartStore.PayPal/Localization/resources.en-us.xml b/src/Plugins/SmartStore.PayPal/Localization/resources.en-us.xml
index 392835a2b9..8661213392 100644
--- a/src/Plugins/SmartStore.PayPal/Localization/resources.en-us.xml
+++ b/src/Plugins/SmartStore.PayPal/Localization/resources.en-us.xml
@@ -25,6 +25,9 @@
Update now
+
+ Miscellaneous
+ Client ID
@@ -379,28 +382,13 @@ Payment fee: {10}]]>
- If you're using PayPal ensure that your primary store currency is supported by Paypal.
-
-
Log into your PayPal account.
-
Click on Profile from the Home Menu.
-
Under Account Information choose API Access.
-
Choose Request API credentials.
-
Choose API Signature as the credential type.
-
Enable the checkbox and agree to the license Terms-I agree to the API Certificate Terms of Use and terms incorporated therein and press the Submit button.
-
-
Before being able to receive IPN (Instant Payment Notification) messages (optional), you'll need to activate this service; follow these steps:
-
-
Log in to your Premier or Business account.
-
Click the Profile subtab.
-
Click Language Encoding and More options and select UTF-8.
-
Click Instant Payment Notification in the Selling Preferences column.
-
Click the Edit IPN Settings button to update your settings.
-
Select Receive IPN messages (enabled) and enter the URL of your IPN handler (https://www.yourStore.com/Plugins/SmartStore.PayPal/PayPalPlus/IPNHandler).
-
Click Save, and you should get a message that you have successfully activated IPN.
- ]]>
+ PayPal PLUS is a solution where PayPal offers PayPal, Credit Card, Direct Debit (ELV) and pay upon invoice as individual payment options on the payment selection page.
+Pay upon invoice may not be available for all merchants. PayPal PLUS is only available in Germany at the moment.]]>
+
+ Unfortunately we cannot offer you a PayPal PLUS payment method. Please try again later.
+
diff --git a/src/Plugins/SmartStore.PayPal/Models/PayPalPlusCheckoutModel.cs b/src/Plugins/SmartStore.PayPal/Models/PayPalPlusCheckoutModel.cs
index f9fec802a2..dcb5b83bb2 100644
--- a/src/Plugins/SmartStore.PayPal/Models/PayPalPlusCheckoutModel.cs
+++ b/src/Plugins/SmartStore.PayPal/Models/PayPalPlusCheckoutModel.cs
@@ -9,5 +9,6 @@ public class PayPalPlusCheckoutModel : ModelBase
public string BillingAddressCountryCode { get; set; }
public string LanguageCulture { get; set; }
public string ApprovalUrl { get; set; }
+ public string ErrorMessage { get; set; }
}
}
\ No newline at end of file
diff --git a/src/Plugins/SmartStore.PayPal/Services/IPayPalService.cs b/src/Plugins/SmartStore.PayPal/Services/IPayPalService.cs
index 1dedce8e88..7305762d68 100644
--- a/src/Plugins/SmartStore.PayPal/Services/IPayPalService.cs
+++ b/src/Plugins/SmartStore.PayPal/Services/IPayPalService.cs
@@ -18,11 +18,6 @@ public interface IPayPalService
PayPalResponse UpsertCheckoutExperience(PayPalApiSettingsBase settings, PayPalSessionData session, Store store, string profileId);
- PayPalResponse UpsertPayment(
- PayPalApiSettingsBase settings,
- PayPalSessionData session,
- string paymentId,
- string returnUrl,
- string cancelUrl);
+ PayPalResponse CreatePayment(PayPalApiSettingsBase settings, PayPalSessionData session, string providerSystemName, string returnUrl, string cancelUrl);
}
}
\ No newline at end of file
diff --git a/src/Plugins/SmartStore.PayPal/Services/PayPalService.cs b/src/Plugins/SmartStore.PayPal/Services/PayPalService.cs
index 33a4d0d78a..5718a77bab 100644
--- a/src/Plugins/SmartStore.PayPal/Services/PayPalService.cs
+++ b/src/Plugins/SmartStore.PayPal/Services/PayPalService.cs
@@ -7,15 +7,22 @@
using System.Web;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
+using SmartStore.Core.Domain.Discounts;
using SmartStore.Core.Domain.Logging;
using SmartStore.Core.Domain.Orders;
using SmartStore.Core.Domain.Stores;
+using SmartStore.Core.Domain.Tax;
using SmartStore.Core.Localization;
using SmartStore.Core.Logging;
using SmartStore.PayPal.Settings;
using SmartStore.Services;
+using SmartStore.Services.Catalog;
+using SmartStore.Services.Customers;
+using SmartStore.Services.Localization;
using SmartStore.Services.Media;
using SmartStore.Services.Orders;
+using SmartStore.Services.Payments;
+using SmartStore.Services.Tax;
namespace SmartStore.PayPal.Services
{
@@ -23,15 +30,27 @@ public class PayPalService : IPayPalService
{
private readonly ICommonServices _services;
private readonly IOrderService _orderService;
+ private readonly IOrderTotalCalculationService _orderTotalCalculationService;
+ private readonly IPaymentService _paymentService;
+ private readonly IPriceCalculationService _priceCalculationService;
+ private readonly ITaxService _taxService;
private readonly Lazy _pictureService;
public PayPalService(
ICommonServices services,
IOrderService orderService,
+ IOrderTotalCalculationService orderTotalCalculationService,
+ IPaymentService paymentService,
+ IPriceCalculationService priceCalculationService,
+ ITaxService taxService,
Lazy pictureService)
{
_services = services;
_orderService = orderService;
+ _orderTotalCalculationService = orderTotalCalculationService;
+ _paymentService = paymentService;
+ _priceCalculationService = priceCalculationService;
+ _taxService = taxService;
_pictureService = pictureService;
T = NullLocalizer.Instance;
@@ -322,25 +341,48 @@ public PayPalResponse UpsertCheckoutExperience(PayPalApiSettingsBase settings, P
return result;
}
- public PayPalResponse UpsertPayment(
- PayPalApiSettingsBase settings,
- PayPalSessionData session,
- string paymentId,
- string returnUrl,
- string cancelUrl)
+ public PayPalResponse CreatePayment(PayPalApiSettingsBase settings, PayPalSessionData session, string providerSystemName, string returnUrl, string cancelUrl)
{
+ var store = _services.StoreContext.CurrentStore;
+ var customer = _services.WorkContext.CurrentCustomer;
+ var language = _services.WorkContext.WorkingLanguage;
+ var cart = customer.GetCartItems(ShoppingCartType.ShoppingCart, store.Id);
+ var currencyCode = store.PrimaryStoreCurrency.CurrencyCode;
+
+ Discount orderAppliedDiscount;
+ List 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 path = "/v1/payments/payment";
var data = new Dictionary();
var redirectUrls = new Dictionary();
+ var payer = new Dictionary();
+ var transaction = new Dictionary();
+ var amount = new Dictionary();
+ var amountDetails = new Dictionary();
+ var items = new List>();
- if (paymentId.HasValue())
- path = string.Concat(path, "/", HttpUtility.UrlPathEncode(paymentId));
+ if (session.PaymentId.HasValue())
+ path = string.Concat(path, "/", HttpUtility.UrlPathEncode(session.PaymentId));
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);
@@ -350,19 +392,78 @@ public PayPalResponse UpsertPayment(
if (redirectUrls.Any())
data.Add("redirect_urls", redirectUrls);
- if (paymentId.IsEmpty())
+ // payer
+ payer.Add("payment_method", "paypal");
+ data.Add("payer", payer);
+
+ // line items
+ foreach (var item in cart)
{
- // TODO: add line items
+ 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();
+ 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", Math.Round(productPrice, 2));
+ line.Add("currency", currencyCode);
+ line.Add("sku", item.Item.Product.Sku.Truncate(50));
+ items.Add(line);
+
+ totalOrderItems += (productPrice * item.Item.Quantity);
}
- var result = CallApi(paymentId.HasValue() ? "PATCH" : "POST", path, session.AccessToken, settings, JsonConvert.SerializeObject(data));
+ var itemsPlusMisc = (totalOrderItems + shipping + paymentFee);
- if (result.Success)
+ if (total != itemsPlusMisc)
{
- if (result.Json != null)
- result.Id = (string)result.Json.id;
- else
- result.Id = paymentId;
+ var line = new Dictionary();
+ line.Add("quantity", "1");
+ line.Add("name", T("Plugins.SmartStore.PayPal.Other").Text.Truncate(127));
+ line.Add("price", Math.Round(total - itemsPlusMisc, 2));
+ line.Add("currency", currencyCode);
+ items.Add(line);
+
+ totalOrderItems += (total - itemsPlusMisc);
+ }
+
+ // transactions
+ amountDetails.Add("shipping", Math.Round(shipping, 2));
+ amountDetails.Add("subtotal", Math.Round(totalOrderItems, 2));
+ 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 taxRates = null;
+ var taxTotal = _orderTotalCalculationService.GetTaxTotal(cart, out taxRates);
+
+ amountDetails.Add("tax", Math.Round(taxTotal, 2));
+ }
+ if (paymentFee != decimal.Zero)
+ {
+ amountDetails.Add("handling_fee", Math.Round(paymentFee, 2));
+ }
+
+ amount.Add("total", Math.Round(total, 2));
+ amount.Add("currency", currencyCode);
+ amount.Add("details", amountDetails);
+
+ transaction.Add("amount", amount);
+ transaction.Add("item_list", new Dictionary { { "items" , items } });
+
+ data.Add("transactions", new List> { transaction });
+
+ var result = CallApi("POST", path, 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;
@@ -382,5 +483,7 @@ public class PayPalSessionData
{
public string AccessToken { get; set; }
public DateTime TokenExpiration { get; set; }
+ public string PaymentId { get; set; }
+ public string ApprovalUrl { get; set; }
}
}
\ No newline at end of file
diff --git a/src/Plugins/SmartStore.PayPal/Views/PayPalPlus/Configure.cshtml b/src/Plugins/SmartStore.PayPal/Views/PayPalPlus/Configure.cshtml
index 45c7a157f3..6b32a76ada 100644
--- a/src/Plugins/SmartStore.PayPal/Views/PayPalPlus/Configure.cshtml
+++ b/src/Plugins/SmartStore.PayPal/Views/PayPalPlus/Configure.cshtml
@@ -43,7 +43,6 @@
@Html.SmartLabelFor(model => model.UseSandbox)
- @*multistore context not possible, see IPN handling*@
@Html.EditorFor(model => model.UseSandbox)
@Html.ValidationMessageFor(model => model.UseSandbox)