Skip to content

Commit 7fa48e6

Browse files
committed
Resolves smartstore#141 Payment methods by customer roles
Resolves smartstore#67 Restrict payment methods to certain countries Resolves smartstore#94 Restrict payment methods to certain shipping methods
1 parent 2548956 commit 7fa48e6

17 files changed

Lines changed: 192 additions & 36 deletions

File tree

changelog.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44

55
### New Features
66
* #210 Implement multi-store support for import/export
7+
* #141 Payment methods by customer roles
8+
* #67 Restrict payment methods to certain countries
9+
* #94 Restrict payment methods to certain shipping methods
710

811
### Improvements
912
* License checker now supports IDN mapping for domain names

src/Libraries/SmartStore.Core/Domain/Payments/PaymentMethod.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public partial class PaymentMethod : BaseEntity
2727
public string ExcludedCountryIds { get; set; }
2828

2929
/// <summary>
30-
/// Gets or sets identifiers of shipping methods (comma separated) to be excluded in checkout
30+
/// Gets or sets shipping methods (comma separated) to be excluded in checkout
3131
/// </summary>
3232
[DataMember]
3333
public string ExcludedShippingMethodIds { get; set; }

src/Libraries/SmartStore.Core/Domain/Shipping/ShippingOption.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ namespace SmartStore.Core.Domain.Shipping
1313
/// </summary>
1414
public partial class ShippingOption
1515
{
16+
/// <summary>
17+
/// Shipping method identifier
18+
/// </summary>
19+
public int ShippingMethodId { get; set; }
20+
1621
/// <summary>
1722
/// Gets or sets the system name of shipping rate computation method
1823
/// </summary>

src/Libraries/SmartStore.Services/Payments/IPaymentService.cs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Collections.Generic;
2+
using SmartStore.Core.Domain.Customers;
23
using SmartStore.Core.Domain.Orders;
34
using SmartStore.Core.Domain.Payments;
45
using SmartStore.Core.Plugins;
@@ -13,10 +14,10 @@ public partial interface IPaymentService
1314
/// <summary>
1415
/// Load active payment methods
1516
/// </summary>
16-
/// <param name="filterByCustomerId">Filter payment methods by customer; null to load all records</param>
17-
/// <param name="storeId">Load records allows only in specified store; pass 0 to load all records</param>
17+
/// <param name="customer">Filter payment methods by customer and apply payment method restrictions; null to load all records</param>
18+
/// <param name="storeId">Filter payment methods by store identifier; pass 0 to load all records</param>
1819
/// <returns>Payment methods</returns>
19-
IEnumerable<Provider<IPaymentMethod>> LoadActivePaymentMethods(int? filterByCustomerId = null, int storeId = 0);
20+
IEnumerable<Provider<IPaymentMethod>> LoadActivePaymentMethods(Customer customer = null, int storeId = 0);
2021

2122
/// <summary>
2223
/// Determines whether a payment method is active\enabled for a shop
@@ -39,24 +40,35 @@ public partial interface IPaymentService
3940

4041

4142
/// <summary>
42-
/// Gets a payment method by system name
43+
/// Gets all payment method extra data
44+
/// </summary>
45+
/// <returns>List of payment method objects</returns>
46+
IList<PaymentMethod> GetAllPaymentMethods();
47+
48+
/// <summary>
49+
/// Gets payment method extra data by system name
4350
/// </summary>
4451
/// <param name="systemName">Provider system name</param>
4552
/// <returns>Payment method entity</returns>
4653
PaymentMethod GetPaymentMethodBySystemName(string systemName);
4754

4855
/// <summary>
49-
/// Insert a payment method
56+
/// Insert payment method extra data
5057
/// </summary>
5158
/// <param name="paymentMethod">Payment method</param>
5259
void InsertPaymentMethod(PaymentMethod paymentMethod);
5360

5461
/// <summary>
55-
/// Updates a payment method
62+
/// Updates payment method extra data
5663
/// </summary>
5764
/// <param name="paymentMethod">Payment method</param>
5865
void UpdatePaymentMethod(PaymentMethod paymentMethod);
5966

67+
/// <summary>
68+
/// Delete payment method extra data
69+
/// </summary>
70+
/// <param name="paymentMethod">Payment method</param>
71+
void DeletePaymentMethod(PaymentMethod paymentMethod);
6072

6173

6274
/// <summary>

src/Libraries/SmartStore.Services/Payments/PaymentService.cs

Lines changed: 115 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Linq;
4+
using SmartStore.Core.Caching;
45
using SmartStore.Core.Data;
6+
using SmartStore.Core.Domain.Customers;
57
using SmartStore.Core.Domain.Orders;
68
using SmartStore.Core.Domain.Payments;
9+
using SmartStore.Core.Domain.Shipping;
710
using SmartStore.Core.Events;
811
using SmartStore.Core.Plugins;
12+
using SmartStore.Services.Common;
913
using SmartStore.Services.Configuration;
1014
using SmartStore.Services.Localization;
1115

@@ -16,6 +20,12 @@ namespace SmartStore.Services.Payments
1620
/// </summary>
1721
public partial class PaymentService : IPaymentService
1822
{
23+
#region Constants
24+
25+
private const string PAYMENTMETHOD_ALL_KEY = "SmartStore.paymentmethod.all";
26+
27+
#endregion
28+
1929
#region Fields
2030

2131
private readonly IRepository<PaymentMethod> _paymentMethodRepository;
@@ -26,6 +36,7 @@ public partial class PaymentService : IPaymentService
2636
private readonly ILocalizationService _localizationService;
2737
private readonly IProviderManager _providerManager;
2838
private readonly IEventPublisher _eventPublisher;
39+
private readonly ICacheManager _cacheManager;
2940

3041
#endregion
3142

@@ -46,7 +57,8 @@ public PaymentService(
4657
ISettingService settingService,
4758
ILocalizationService localizationService,
4859
IProviderManager providerManager,
49-
IEventPublisher eventPublisher)
60+
IEventPublisher eventPublisher,
61+
ICacheManager cacheManager)
5062
{
5163
this._paymentMethodRepository = paymentMethodRepository;
5264
this._paymentSettings = paymentSettings;
@@ -56,32 +68,83 @@ public PaymentService(
5668
this._localizationService = localizationService;
5769
this._providerManager = providerManager;
5870
this._eventPublisher = eventPublisher;
71+
this._cacheManager = cacheManager;
5972
}
6073

6174
#endregion
6275

63-
#region Methods
76+
#region Methods
6477

65-
/// <summary>
78+
/// <summary>
6679
/// Load active payment methods
6780
/// </summary>
68-
/// <param name="filterByCustomerId">Filter payment methods by customer; null to load all records</param>
69-
/// <param name="storeId">Load records allows only in specified store; pass 0 to load all records</param>
81+
/// <param name="customer">Filter payment methods by customer and apply payment method restrictions; null to load all records</param>
82+
/// <param name="storeId">Filter payment methods by store identifier; pass 0 to load all records</param>
7083
/// <returns>Payment methods</returns>
71-
public virtual IEnumerable<Provider<IPaymentMethod>> LoadActivePaymentMethods(int? filterByCustomerId = null, int storeId = 0)
84+
public virtual IEnumerable<Provider<IPaymentMethod>> LoadActivePaymentMethods(Customer customer = null, int storeId = 0)
7285
{
73-
var allMethods = LoadAllPaymentMethods(storeId);
74-
var activeMethods = allMethods
75-
.Where(p => p.Value.IsActive && _paymentSettings.ActivePaymentMethodSystemNames.Contains(p.Metadata.SystemName, StringComparer.InvariantCultureIgnoreCase));
86+
List<int> customerRoleIds = null;
87+
int? selectedShippingMethodId = null;
7688

77-
if (!activeMethods.Any())
89+
var allProviders = LoadAllPaymentMethods(storeId);
90+
91+
var activeProviders = allProviders
92+
.Where(p =>
93+
{
94+
if (!p.Value.IsActive || !_paymentSettings.ActivePaymentMethodSystemNames.Contains(p.Metadata.SystemName, StringComparer.InvariantCultureIgnoreCase))
95+
return false;
96+
97+
if (customer != null)
98+
{
99+
var method = GetPaymentMethodBySystemName(p.Metadata.SystemName);
100+
if (method != null)
101+
{
102+
// method restricted by customer role id?
103+
var excludedRoleIds = method.ExcludedCustomerRoleIds.ToIntArray();
104+
if (excludedRoleIds.Any())
105+
{
106+
if (customerRoleIds == null)
107+
customerRoleIds = customer.CustomerRoles.Where(r => r.Active).Select(r => r.Id).ToList();
108+
109+
if (customerRoleIds != null && !customerRoleIds.Except(excludedRoleIds).Any())
110+
return false;
111+
}
112+
113+
// method restricted by selected shipping method?
114+
var excludedShippingMethodIds = method.ExcludedShippingMethodIds.ToIntArray();
115+
if (excludedShippingMethodIds.Any())
116+
{
117+
if (!selectedShippingMethodId.HasValue)
118+
{
119+
var selectedShipping = customer.GetAttribute<ShippingOption>(SystemCustomerAttributeNames.SelectedShippingOption, storeId);
120+
selectedShippingMethodId = (selectedShipping == null ? 0 : selectedShipping.ShippingMethodId);
121+
}
122+
123+
if ((selectedShippingMethodId ?? 0) != 0 && excludedShippingMethodIds.Contains(selectedShippingMethodId.Value))
124+
return false;
125+
}
126+
127+
// method restricted by country of selected billing address?
128+
var excludedCountryIds = method.ExcludedCountryIds.ToIntArray();
129+
if (excludedCountryIds.Any() && customer.BillingAddress != null && (customer.BillingAddress.CountryId ?? 0) != 0)
130+
{
131+
if (excludedCountryIds.Contains(customer.BillingAddress.CountryId.Value))
132+
return false;
133+
}
134+
}
135+
}
136+
return true;
137+
});
138+
139+
if (!activeProviders.Any())
78140
{
79-
var fallbackMethod = allMethods.FirstOrDefault();
141+
var fallbackMethod = allProviders.FirstOrDefault();
80142
if (fallbackMethod != null)
81143
{
82144
_paymentSettings.ActivePaymentMethodSystemNames.Clear();
83145
_paymentSettings.ActivePaymentMethodSystemNames.Add(fallbackMethod.Metadata.SystemName);
84146
_settingService.SaveSetting(_paymentSettings);
147+
85148
return new Provider<IPaymentMethod>[] { fallbackMethod };
86149
}
87150
else
@@ -91,7 +154,7 @@ public virtual IEnumerable<Provider<IPaymentMethod>> LoadActivePaymentMethods(in
91154
}
92155
}
93156

94-
return activeMethods;
157+
return activeProviders;
95158
}
96159

97160
/// <summary>
@@ -130,21 +193,37 @@ public virtual IEnumerable<Provider<IPaymentMethod>> LoadAllPaymentMethods(int s
130193

131194

132195
/// <summary>
133-
/// Gets a payment method by system name
196+
/// Gets all payment method extra data
197+
/// </summary>
198+
/// <returns>List of payment method objects</returns>
199+
public virtual IList<PaymentMethod> GetAllPaymentMethods()
200+
{
201+
var paymentMethods = _cacheManager.Get(PAYMENTMETHOD_ALL_KEY, () =>
202+
{
203+
return _paymentMethodRepository.Table.ToList();
204+
});
205+
206+
return paymentMethods;
207+
}
208+
209+
/// <summary>
210+
/// Gets payment method extra data by system name
134211
/// </summary>
135212
/// <param name="systemName">Provider system name</param>
136213
/// <returns>Payment method entity</returns>
137214
public virtual PaymentMethod GetPaymentMethodBySystemName(string systemName)
138215
{
139216
if (systemName.HasValue())
140217
{
141-
return _paymentMethodRepository.Table.FirstOrDefault(x => x.PaymentMethodSystemName == systemName);
218+
var allPaymentMethods = GetAllPaymentMethods();
219+
220+
return allPaymentMethods.FirstOrDefault(x => x.PaymentMethodSystemName.IsCaseInsensitiveEqual(systemName));
142221
}
143222
return null;
144223
}
145224

146225
/// <summary>
147-
/// Insert a payment method
226+
/// Insert payment method extra data
148227
/// </summary>
149228
/// <param name="paymentMethod">Payment method</param>
150229
public virtual void InsertPaymentMethod(PaymentMethod paymentMethod)
@@ -154,11 +233,13 @@ public virtual void InsertPaymentMethod(PaymentMethod paymentMethod)
154233

155234
_paymentMethodRepository.Insert(paymentMethod);
156235

236+
_cacheManager.RemoveByPattern(PAYMENTMETHOD_ALL_KEY);
237+
157238
_eventPublisher.EntityInserted(paymentMethod);
158239
}
159240

160241
/// <summary>
161-
/// Updates a payment method
242+
/// Updates payment method extra data
162243
/// </summary>
163244
/// <param name="paymentMethod">Payment method</param>
164245
public virtual void UpdatePaymentMethod(PaymentMethod paymentMethod)
@@ -168,9 +249,27 @@ public virtual void UpdatePaymentMethod(PaymentMethod paymentMethod)
168249

169250
_paymentMethodRepository.Update(paymentMethod);
170251

252+
_cacheManager.RemoveByPattern(PAYMENTMETHOD_ALL_KEY);
253+
171254
_eventPublisher.EntityUpdated(paymentMethod);
172255
}
173256

257+
/// <summary>
258+
/// Delete payment method extra data
259+
/// </summary>
260+
/// <param name="paymentMethod">Payment method</param>
261+
public virtual void DeletePaymentMethod(PaymentMethod paymentMethod)
262+
{
263+
if (paymentMethod == null)
264+
throw new ArgumentNullException("paymentMethod");
265+
266+
_paymentMethodRepository.Delete(paymentMethod);
267+
268+
_cacheManager.RemoveByPattern(PAYMENTMETHOD_ALL_KEY);
269+
270+
_eventPublisher.EntityDeleted(paymentMethod);
271+
}
272+
174273

175274
/// <summary>
176275
/// Pre process a payment

src/Plugins/SmartStore.Shipping/Providers/ByTotalProvider.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ public GetShippingOptionResponse GetShippingOptions(GetShippingOptionRequest get
200200
}
201201

202202
var shippingOption = new ShippingOption();
203+
shippingOption.ShippingMethodId = shippingMethod.Id;
203204
shippingOption.Name = shippingMethod.Name;
204205
shippingOption.Description = shippingMethod.Description;
205206
shippingOption.Rate = rate.Value;

src/Plugins/SmartStore.Shipping/Providers/FixedRateProvider.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ public GetShippingOptionResponse GetShippingOptions(GetShippingOptionRequest get
6060
foreach (var shippingMethod in shippingMethods)
6161
{
6262
var shippingOption = new ShippingOption();
63+
shippingOption.ShippingMethodId = shippingMethod.Id;
6364
shippingOption.Name = shippingMethod.GetLocalized(x => x.Name);
6465
shippingOption.Description = shippingMethod.GetLocalized(x => x.Description);
6566
shippingOption.Rate = GetRate(shippingMethod.Id);

src/Plugins/SmartStore.ShippingByWeight/ByWeightShippingComputationMethod.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ public GetShippingOptionResponse GetShippingOptions(GetShippingOptionRequest get
150150
if (rate.HasValue)
151151
{
152152
var shippingOption = new ShippingOption();
153+
shippingOption.ShippingMethodId = shippingMethod.Id;
153154
shippingOption.Name = shippingMethod.GetLocalized(x => x.Name);
154155

155156
if (record != null && record.SmallQuantityThreshold > subTotal)

0 commit comments

Comments
 (0)