Skip to content

Commit b2e260f

Browse files
authored
Merge pull request #38 from umbraco/feature/payment-provider-integration
Feature/payment provider integration
2 parents 28473a3 + 8d87d67 commit b2e260f

File tree

12 files changed

+132
-45
lines changed

12 files changed

+132
-45
lines changed

src/Umbraco.Forms.Integrations.Commerce.EMerchantPay/App_Plugins/UmbracoForms.Integrations/Commerce/eMerchantPay/customer-details-mapper.controller.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,16 @@
3232

3333
function init() {
3434

35-
umbracoFormsIntegrationsCommerceEMerchantPayResource.getMappingFields().then(function (response) {
35+
umbracoFormsIntegrationsCommerceEMerchantPayResource.getAvailableMappingFields().then(function (response) {
3636
vm.customerProperties = response;
3737
});
3838

3939
vm.fields = [];
4040

41+
umbracoFormsIntegrationsCommerceEMerchantPayResource.getRequiredMappingFields().then(function (response) {
42+
vm.requiredFields = response.join();
43+
});
44+
4145
emerchantpayService.getFormFields(function (response) {
4246
vm.fields = response;
4347
});

src/Umbraco.Forms.Integrations.Commerce.EMerchantPay/App_Plugins/UmbracoForms.Integrations/Commerce/eMerchantPay/customer-details-mapper.html

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,19 @@
1010
<option ng-repeat="field in vm.fields" value="{{ field.id }}">{{ field.value }}</option>
1111
</select>
1212
</div>
13-
13+
14+
<div ng-if="vm.requiredFields.length > 0" class="alert alert-info mt2 mr3" role="alert">
15+
<span>Mandatory fields: {{ vm.requiredFields }}</span>
16+
</div>
17+
1418
<div class="mt2">
1519
<umb-button type="button" class="mt2"
1620
action="vm.addMapping()"
1721
label="Add mapping"
1822
disabled="vm.selectedCustomerProperty.length === 0 || vm.selectedField.length === 0">
1923
</umb-button>
2024
</div>
21-
25+
2226
<div class="umb-forms-mappings mt2" ng-if="vm.mappings.length > 0">
2327

2428
<div class="umb-forms-mapping-header">

src/Umbraco.Forms.Integrations.Commerce.EMerchantPay/App_Plugins/UmbracoForms.Integrations/Commerce/eMerchantPay/emerchantpay.resource.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,14 @@
88
$http.get(`${apiEndpoint}/GetCurrencies`),
99
"Failed to get resource");
1010
},
11-
getMappingFields: function () {
11+
getAvailableMappingFields: function () {
1212
return umbRequestHelper.resourcePromise(
13-
$http.get(`${apiEndpoint}/GetMappingFields`),
13+
$http.get(`${apiEndpoint}/GetAvailableMappingFields`),
14+
"Failed to get resource");
15+
},
16+
getRequiredMappingFields: function () {
17+
return umbRequestHelper.resourcePromise(
18+
$http.get(`${apiEndpoint}/GetRequiredMappingFields`),
1419
"Failed to get resource");
1520
}
1621
};
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System.IO;
2+
using System.Text;
3+
4+
namespace Umbraco.Forms.Integrations.Commerce.EMerchantPay.Configuration
5+
{
6+
/// <summary>
7+
/// Override encoding to ensure request object is utf-8 encoded.
8+
/// </summary>
9+
public class PaymentProviderStringWriter : StringWriter
10+
{
11+
public override Encoding Encoding => Encoding.UTF8;
12+
}
13+
}

src/Umbraco.Forms.Integrations.Commerce.EMerchantPay/Constants.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,5 +60,10 @@ public static class NotificationProperty
6060

6161
public const string Status = "wpf_status";
6262
}
63+
64+
public static class PaymentStatus
65+
{
66+
public const string Approved = "approved";
67+
}
6368
}
6469
}

src/Umbraco.Forms.Integrations.Commerce.EMerchantPay/Controllers/EmerchantPayController.cs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,21 @@ public EmerchantPayController(CurrencyHelper currencyHelper, MappingFieldHelper
4242
public IEnumerable<CurrencyDto> GetCurrencies() => _currencyHelper.GetCurrencies();
4343

4444
[HttpGet]
45-
public IEnumerable<string> GetMappingFields() => _mappingFieldHelper.GetMappings();
45+
public IEnumerable<string> GetAvailableMappingFields() => new[]
46+
{
47+
"Email",
48+
"FirstName",
49+
"LastName",
50+
"Address1",
51+
"Address2",
52+
"ZipCode",
53+
"City",
54+
"State",
55+
"Country",
56+
"Phone"
57+
};
58+
59+
[HttpGet]
60+
public IEnumerable<string> GetRequiredMappingFields() => _mappingFieldHelper.GetMappings();
4661
}
4762
}

src/Umbraco.Forms.Integrations.Commerce.EMerchantPay/Controllers/PaymentProviderController.cs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
using Microsoft.AspNetCore.Mvc;
33

44
using Umbraco.Cms.Web.Common.Controllers;
5-
using Umbraco.Forms.Core.Services;
65
#else
76
using System.Web.Http;
87

@@ -18,6 +17,7 @@
1817
using Umbraco.Forms.Core.Data.Storage;
1918
using Umbraco.Forms.Integrations.Commerce.EMerchantPay.Models.Dtos;
2019
using Umbraco.Forms.Integrations.Commerce.EMerchantPay.Services;
20+
using Umbraco.Forms.Core.Services;
2121

2222
namespace Umbraco.Forms.Integrations.Commerce.EMerchantPay.Controllers
2323
{
@@ -27,20 +27,24 @@ public class PaymentProviderController : UmbracoApiController
2727

2828
private readonly IRecordStorage _recordStorage;
2929

30+
private readonly IRecordService _recordService;
31+
3032
#if NETCOREAPP
3133
private readonly IFormService _formService;
3234

33-
public PaymentProviderController(PaymentService paymentService, IRecordStorage recordStorage, IFormService formService)
35+
public PaymentProviderController(PaymentService paymentService, IRecordStorage recordStorage, IRecordService recordService, IFormService formService)
3436
#else
3537
private readonly IFormStorage _formStorage;
3638

37-
public PaymentProviderController(PaymentService paymentService, IRecordStorage recordStorage, IFormStorage formStorage)
39+
public PaymentProviderController(PaymentService paymentService, IRecordStorage recordStorage, IRecordService recordService, IFormStorage formStorage)
3840
#endif
3941
{
4042
_paymentService = paymentService;
4143

4244
_recordStorage = recordStorage;
4345

46+
_recordService = recordService;
47+
4448
#if NETCOREAPP
4549
_formService = formService;
4650
#else
@@ -50,9 +54,9 @@ public PaymentProviderController(PaymentService paymentService, IRecordStorage r
5054

5155
[HttpPost]
5256
#if NETCOREAPP
53-
public HttpResponseMessage NotifyPayment(string formId, string recordUniqueId, string statusFieldId, [FromForm] NotificationDto notificationDto)
57+
public HttpResponseMessage NotifyPayment(string formId, string recordUniqueId, string statusFieldId, bool approve, [FromForm] NotificationDto notificationDto)
5458
#else
55-
public HttpResponseMessage NotifyPayment(string formId, string recordUniqueId, string statusFieldId, [FromBody] NotificationDto notificationDto)
59+
public HttpResponseMessage NotifyPayment(string formId, string recordUniqueId, string statusFieldId, bool approve, [FromBody] NotificationDto notificationDto)
5660
#endif
5761
{
5862
try
@@ -71,11 +75,18 @@ public HttpResponseMessage NotifyPayment(string formId, string recordUniqueId, s
7175
#endif
7276

7377
var record = _recordStorage.GetRecordByUniqueId(Guid.Parse(recordUniqueId), form);
78+
7479
var paymentStatusField = record.GetRecordField(Guid.Parse(statusFieldId));
80+
paymentStatusField.Values.Clear();
7581
paymentStatusField.Values.Add(reconcileResponse.Status);
7682

7783
_recordStorage.UpdateRecord(record, form);
7884

85+
if (approve && notificationDto.Status == Constants.PaymentStatus.Approved)
86+
{
87+
_recordService.Approve(record, form);
88+
}
89+
7990
if (reconcileResponse.Status == Constants.ErrorCode.WorkflowError)
8091
return new HttpResponseMessage(HttpStatusCode.BadRequest);
8192

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using System;
2+
3+
using Umbraco.Forms.Core.Persistence.Dtos;
4+
5+
namespace Umbraco.Forms.Integrations.Commerce.EMerchantPay.Helpers
6+
{
7+
public class FormHelper
8+
{
9+
protected Record Record { get; set; }
10+
11+
public FormHelper(Record record)
12+
{
13+
Record = record;
14+
}
15+
16+
public Guid GetFormId() => Record.Form;
17+
18+
public Guid GetRecordUniqueId() => Record.UniqueId;
19+
20+
public string GetRecordFieldValue(string key) => Record.RecordFields[Guid.Parse(key)].ValuesAsString();
21+
22+
public void UpdateRecordFieldValue(string key, string value)
23+
{
24+
Record.RecordFields[Guid.Parse(key)].Values.Clear();
25+
26+
Record.RecordFields[Guid.Parse(key)].Values.Add(value);
27+
}
28+
}
29+
}

src/Umbraco.Forms.Integrations.Commerce.EMerchantPay/PaymentProviderWorkflow.cs

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
using Umbraco.Forms.Core;
77
using Umbraco.Forms.Core.Enums;
8-
using Umbraco.Forms.Core.Models;
98
using Umbraco.Forms.Integrations.Commerce.EMerchantPay.Builders;
109
using Umbraco.Forms.Integrations.Commerce.EMerchantPay.Configuration;
1110
using Umbraco.Forms.Integrations.Commerce.EMerchantPay.ExtensionMethods;
@@ -87,6 +86,11 @@ public class PaymentProviderWorkflow : WorkflowType
8786
View = "Pickers.Content")]
8887
public string CancelUrl { get; set; }
8988

89+
[Core.Attributes.Setting("Approve Record",
90+
Description = "Approve record when payment is confirmed.",
91+
View = "Checkbox")]
92+
public string Approve { get; set; }
93+
9094
#endregion
9195

9296
#if NETCOREAPP
@@ -153,35 +157,37 @@ public override WorkflowExecutionStatus Execute(Record record, RecordEventArgs e
153157
var retrieveConsumerTask = Task.Run(async () => await _consumerService.Retrieve(consumer));
154158
consumer = retrieveConsumerTask.Result;
155159
}
160+
else
161+
{
162+
consumer.Id = result.Id;
163+
}
156164

157165
// step 2. Create Payment
158166
var random = new Random();
159167
var transactionId = $"uc-{random.Next(1000000, 999999999)}";
160168

161169
#if NETCOREAPP
162-
var formId = context.Record.Form;
163-
var recordUniqueId = context.Record.UniqueId;
170+
var formHelper = new FormHelper(context.Record);
164171
#else
165-
var formId = record.Form;
166-
var recordUniqueId = record.UniqueId;
172+
var formHelper = new FormHelper(record);
167173
#endif
174+
175+
var formId = formHelper.GetFormId();
176+
var recordUniqueId = formHelper.GetRecordUniqueId();
177+
168178
var uniqueIdKey = UniqueId;
169179
var statusKey = RecordStatus;
170180

171-
172181
var numberOfItems = string.IsNullOrEmpty(NumberOfItems)
173182
? 0
174-
#if NETCOREAPP
175-
: int.Parse(context.Record.RecordFields[Guid.Parse(NumberOfItems)].ValuesAsString());
176-
#else
177-
: int.Parse(record.RecordFields[Guid.Parse(NumberOfItems)].ValuesAsString());
178-
#endif
183+
: int.Parse(formHelper.GetRecordFieldValue(NumberOfItems));
184+
179185
var payment = new PaymentDto
180186
{
181187
TransactionId = transactionId.ToString(),
182188
Usage = _paymentProviderSettings.Usage,
183189
NotificationUrl = $"{_paymentProviderSettings.UmbracoBaseUrl}umbraco/api/paymentprovider/notifypayment" +
184-
$"?formId={formId}&recordUniqueId={recordUniqueId}&statusFieldId={statusKey}",
190+
$"?formId={formId}&recordUniqueId={recordUniqueId}&statusFieldId={statusKey}&approve={bool.Parse(Approve)}",
185191
ReturnSuccessUrl = _urlHelper.GetPageUrl(int.Parse(SuccessUrl)),
186192
ReturnFailureUrl = _urlHelper.GetPageUrl(int.Parse(FailureUrl)),
187193
ReturnCancelUrl = _urlHelper.GetPageUrl(int.Parse(CancelUrl)),
@@ -219,24 +225,15 @@ public override WorkflowExecutionStatus Execute(Record record, RecordEventArgs e
219225
if (createPaymentResult.Status != "error")
220226
{
221227
// add unique ID and status to record
222-
#if NETCOREAPP
223-
context.Record.RecordFields[Guid.Parse(uniqueIdKey)].Values.Add(createPaymentResult.UniqueId);
224-
context.Record.RecordFields[Guid.Parse(statusKey)].Values.Add(createPaymentResult.Status);
225-
#else
226-
record.RecordFields[Guid.Parse(uniqueIdKey)].Values.Add(createPaymentResult.UniqueId);
227-
record.RecordFields[Guid.Parse(statusKey)].Values.Add(createPaymentResult.Status);
228-
#endif
228+
formHelper.UpdateRecordFieldValue(uniqueIdKey, createPaymentResult.UniqueId);
229+
formHelper.UpdateRecordFieldValue(statusKey, createPaymentResult.Status);
229230

230231
_httpContextAccessor.HttpContext.Items[Core.Constants.ItemKeys.RedirectAfterFormSubmitUrl] = createPaymentResult.RedirectUrl;
231232

232233
return WorkflowExecutionStatus.Completed;
233234
}
234235

235-
#if NETCOREAPP
236-
context.Record.RecordFields[Guid.Parse(statusKey)].Values.Add("error");
237-
#else
238-
record.RecordFields[Guid.Parse(statusKey)].Values.Add("error");
239-
#endif
236+
formHelper.UpdateRecordFieldValue(statusKey, "error");
240237

241238
return WorkflowExecutionStatus.Failed;
242239
}
@@ -255,7 +252,7 @@ public override List<Exception> ValidateSettings()
255252
if (string.IsNullOrEmpty(UniqueId)) list.Add(new Exception("Payment Unique ID field is required."));
256253

257254
if (!_mappingService.TryParse(CustomerDetailsMappings, out _))
258-
list.Add(new Exception("Invalid mappings. Email at least is required."));
255+
list.Add(new Exception("Invalid mappings. Please make sure that mandatory fields are mapped."));
259256

260257
if (!SuccessUrl.IsContentValid(nameof(SuccessUrl), out var successError))
261258
list.Add(new Exception(successError));

src/Umbraco.Forms.Integrations.Commerce.EMerchantPay/Services/BaseService.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
using System.Xml;
55
using System.Xml.Serialization;
66

7+
using Umbraco.Forms.Integrations.Commerce.EMerchantPay.Configuration;
8+
79
namespace Umbraco.Forms.Integrations.Commerce.EMerchantPay.Services
810
{
911
public abstract class BaseService<T> where T : class
@@ -12,7 +14,7 @@ protected StringContent Serialize(T input, string root)
1214
{
1315
var serializer = new XmlSerializer(typeof(T), new XmlRootAttribute(root));
1416

15-
using (var stringWriter = new StringWriter())
17+
using (var stringWriter = new PaymentProviderStringWriter())
1618
{
1719
using (XmlWriter writer = XmlWriter.Create(stringWriter))
1820
{
@@ -32,5 +34,6 @@ protected T Deserialize(string response, string root)
3234
return (T)serializer.Deserialize(stringReader);
3335
}
3436
}
37+
3538
}
3639
}

0 commit comments

Comments
 (0)