Skip to content

Commit 254c2d4

Browse files
Merge branch 'release/15.0.0'
2 parents affacc6 + 920cc37 commit 254c2d4

File tree

8 files changed

+65
-66
lines changed

8 files changed

+65
-66
lines changed

Directory.Build.props

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<Project>
22
<PropertyGroup>
3-
<TargetFramework>net8.0</TargetFramework>
3+
<TargetFramework>net9.0</TargetFramework>
44
<Company>Umbraco HQ</Company>
55
<Authors>Umbraco</Authors>
66
<Copyright>Copyright © Umbraco $([System.DateTime]::Today.ToString('yyyy'))</Copyright>
@@ -33,7 +33,7 @@
3333
<!-- Package validation -->
3434
<PropertyGroup>
3535
<EnablePackageValidation>false</EnablePackageValidation>
36-
<PackageValidationBaselineVersion>12.0.0</PackageValidationBaselineVersion>
36+
<PackageValidationBaselineVersion>14.0.0</PackageValidationBaselineVersion>
3737
<EnableStrictModeForCompatibleFrameworksInPackage>true</EnableStrictModeForCompatibleFrameworksInPackage>
3838
<EnableStrictModeForCompatibleTfms>true</EnableStrictModeForCompatibleTfms>
3939
</PropertyGroup>

Directory.Packages.props

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,13 @@
44
</PropertyGroup>
55
<ItemGroup>
66
<GlobalPackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" />
7-
<GlobalPackageReference Include="Nerdbank.GitVersioning" Version="3.5.119" />
7+
<GlobalPackageReference Include="Nerdbank.GitVersioning" Version="3.6.133" />
88
<GlobalPackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" />
9-
<GlobalPackageReference Include="Umbraco.Code" Version="2.1.0" />
9+
<GlobalPackageReference Include="Umbraco.Code" Version="2.2.0" />
1010
<GlobalPackageReference Include="Umbraco.GitVersioning.Extensions" Version="0.2.0" />
1111
</ItemGroup>
1212
<ItemGroup>
13-
<PackageVersion Include="Flurl.Http" Version="[4.0.0, 5)" />
14-
<PackageVersion Include="Flurl.Http.Newtonsoft" Version="[0.9.0, 1)" />
15-
<PackageVersion Include="Umbraco.Commerce.Core" Version="[14.0.0, 15)" />
16-
<PackageVersion Include="Microsoft.AspNet.WebApi.Client" Version="[6, 7)" />
13+
<PackageVersion Include="Flurl.Http" Version="[4.0.2, 5)" />
14+
<PackageVersion Include="Umbraco.Commerce.Core" Version="[15.0.0, 15.999.999)" />
1715
</ItemGroup>
1816
</Project>

global.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"sdk": {
3-
"version": "8.0.100",
3+
"version": "9.0.100",
44
"rollForward": "latestFeature"
55
}
66
}

src/Umbraco.Commerce.PaymentProviders.Quickpay/QuickpayCheckoutPaymentProvider.cs

Lines changed: 51 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using System.Text.Json;
99
using System.Threading;
1010
using System.Threading.Tasks;
11+
using Microsoft.AspNetCore.Http;
1112
using Umbraco.Commerce.Common.Logging;
1213
using Umbraco.Commerce.Core.Api;
1314
using Umbraco.Commerce.Core.Models;
@@ -36,14 +37,14 @@ public QuickpayCheckoutPaymentProvider(UmbracoCommerceContext ctx, ILogger<Quick
3637

3738
public override IEnumerable<TransactionMetaDataDefinition> TransactionMetaDataDefinitions => new[]
3839
{
39-
new TransactionMetaDataDefinition("quickPayOrderId", "Quickpay Order ID"),
40-
new TransactionMetaDataDefinition("quickPayPaymentId", "Quickpay Payment ID"),
41-
new TransactionMetaDataDefinition("quickPayPaymentHash", "Quickpay Payment Hash")
40+
new TransactionMetaDataDefinition("quickpayOrderId", "Quickpay Order ID"),
41+
new TransactionMetaDataDefinition("quickpayPaymentId", "Quickpay Payment ID"),
42+
new TransactionMetaDataDefinition("quickpayPaymentHash", "Quickpay Payment Hash")
4243
};
4344

4445
public override async Task<PaymentFormResult> GenerateFormAsync(PaymentProviderContext<QuickpayCheckoutSettings> ctx, CancellationToken cancellationToken = default)
4546
{
46-
var currency = Context.Services.CurrencyService.GetCurrency(ctx.Order.CurrencyId);
47+
var currency = await Context.Services.CurrencyService.GetCurrencyAsync(ctx.Order.CurrencyId);
4748
var currencyCode = currency.Code.ToUpperInvariant();
4849

4950
// Ensure currency has valid ISO 4217 code
@@ -63,12 +64,12 @@ public override async Task<PaymentFormResult> GenerateFormAsync(PaymentProviderC
6364
// Parse language - default language is English.
6465
Enum.TryParse(ctx.Settings.Lang, true, out QuickpayLang lang);
6566

66-
var quickPayOrderId = ctx.Order.Properties["quickPayOrderId"]?.Value;
67-
var quickPayPaymentId = ctx.Order.Properties["quickPayPaymentId"]?.Value;
68-
var quickPayPaymentHash = ctx.Order.Properties["quickPayPaymentHash"]?.Value ?? string.Empty;
69-
var quickPayPaymentLinkHash = ctx.Order.Properties["quickPayPaymentLinkHash"]?.Value ?? string.Empty;
67+
var quickpayOrderId = ctx.Order.Properties["quickpayOrderId"]?.Value;
68+
var quickpayPaymentId = ctx.Order.Properties["quickpayPaymentId"]?.Value;
69+
var quickpayPaymentHash = ctx.Order.Properties["quickpayPaymentHash"]?.Value ?? string.Empty;
70+
var quickpayPaymentLinkHash = ctx.Order.Properties["quickpayPaymentLinkHash"]?.Value ?? string.Empty;
7071

71-
if (quickPayPaymentHash != GetPaymentHash(quickPayPaymentId, ctx.Order.OrderNumber, currencyCode, orderAmount))
72+
if (quickpayPaymentHash != GetPaymentHash(quickpayPaymentId, ctx.Order.OrderNumber, currencyCode, orderAmount))
7273
{
7374
try
7475
{
@@ -82,7 +83,7 @@ public override async Task<PaymentFormResult> GenerateFormAsync(PaymentProviderC
8283
// Quickpay has a limit of order id between 4-20 characters.
8384
if (reference.Length > 20)
8485
{
85-
var store = Context.Services.StoreService.GetStore(ctx.Order.StoreId);
86+
var store = await Context.Services.StoreService.GetStoreAsync(ctx.Order.StoreId);
8687
var orderNumberTemplate = store.OrderNumberTemplate;
8788

8889
// If the order number template is not equals Vendr generated order number, we need to decide whether to trim prefix, suffix or both.
@@ -117,18 +118,18 @@ public override async Task<PaymentFormResult> GenerateFormAsync(PaymentProviderC
117118
{ "orderNumber", ctx.Order.OrderNumber }
118119
};
119120

120-
quickPayOrderId = reference;
121+
quickpayOrderId = reference;
121122

122123
var payment = await client.CreatePaymentAsync(
123124
new QuickpayPaymentRequest
124125
{
125-
OrderId = quickPayOrderId,
126+
OrderId = quickpayOrderId,
126127
Currency = currencyCode,
127128
Variables = metaData
128129
},
129-
cancellationToken).ConfigureAwait(false);
130+
cancellationToken);
130131

131-
quickPayPaymentId = GetTransactionId(payment);
132+
quickpayPaymentId = GetTransactionId(payment);
132133

133134
var paymentLink = await client.CreatePaymentLinkAsync(payment.Id.ToString(), new QuickpayPaymentLinkRequest
134135
{
@@ -143,12 +144,12 @@ public override async Task<PaymentFormResult> GenerateFormAsync(PaymentProviderC
143144
Framed = ctx.Settings.Framed
144145

145146
},
146-
cancellationToken).ConfigureAwait(false);
147+
cancellationToken);
147148

148149
paymentFormLink = paymentLink.Url;
149150

150-
quickPayPaymentHash = GetPaymentHash(payment.Id.ToString(), ctx.Order.OrderNumber, currencyCode, orderAmount);
151-
quickPayPaymentLinkHash = Base64Encode(paymentFormLink);
151+
quickpayPaymentHash = GetPaymentHash(payment.Id.ToString(), ctx.Order.OrderNumber, currencyCode, orderAmount);
152+
quickpayPaymentLinkHash = Base64Encode(paymentFormLink);
152153
}
153154
catch (Exception ex)
154155
{
@@ -158,17 +159,17 @@ public override async Task<PaymentFormResult> GenerateFormAsync(PaymentProviderC
158159
else
159160
{
160161
// Get payment link from order properties.
161-
paymentFormLink = Base64Decode(quickPayPaymentLinkHash);
162+
paymentFormLink = Base64Decode(quickpayPaymentLinkHash);
162163
}
163164

164165
return new PaymentFormResult()
165166
{
166167
MetaData = new Dictionary<string, string>
167168
{
168-
{ "quickPayOrderId", quickPayOrderId },
169-
{ "quickPayPaymentId", quickPayPaymentId },
170-
{ "quickPayPaymentHash", quickPayPaymentHash },
171-
{ "quickPayPaymentLinkHash", quickPayPaymentLinkHash }
169+
{ "quickpayOrderId", quickpayOrderId },
170+
{ "quickpayPaymentId", quickpayPaymentId },
171+
{ "quickpayPaymentHash", quickpayPaymentHash },
172+
{ "quickpayPaymentLinkHash", quickpayPaymentLinkHash }
172173
},
173174
Form = new PaymentForm(paymentFormLink, PaymentFormMethod.Get)
174175
};
@@ -179,15 +180,22 @@ public override async Task<CallbackResult> ProcessCallbackAsync(PaymentProviderC
179180
try
180181
{
181182
ArgumentNullException.ThrowIfNull(context);
182-
if (!await ValidateChecksumAsync(context.Request, context.Settings.PrivateKey, cancellationToken).ConfigureAwait(false))
183+
184+
var webhookBody = await GetJsonBodyAsync(context.HttpContext.Request, cancellationToken);
185+
186+
if (!await ValidateChecksumAsync(
187+
context.HttpContext.Request.Headers["Quickpay-Checksum-Sha256"],
188+
webhookBody,
189+
context.Settings.PrivateKey,
190+
cancellationToken))
183191
{
184192
Logger.Warn($"Quickpay [{context.Order.OrderNumber}] - Checksum validation failed");
185193
return CallbackResult.BadRequest();
186194
}
187195

188196
QuickpayPayment payment = await ParseCallbackAsync(
189-
context.Request,
190-
cancellationToken).ConfigureAwait(false);
197+
webhookBody,
198+
cancellationToken);
191199

192200
if (!VerifyOrder(context.Order, payment))
193201
{
@@ -251,7 +259,7 @@ private static bool VerifyOrder(OrderReadOnly order, QuickpayPayment payment)
251259
}
252260
else
253261
{
254-
if (order.Properties["quickPayOrderId"]?.Value == payment.OrderId)
262+
if (order.Properties["quickpayOrderId"]?.Value == payment.OrderId)
255263
{
256264
return true;
257265
}
@@ -271,7 +279,7 @@ public override async Task<ApiResult> FetchPaymentStatusAsync(PaymentProviderCon
271279
var clientConfig = GetQuickpayClientConfig(ctx.Settings);
272280
var client = new QuickpayClient(clientConfig);
273281

274-
var payment = await client.GetPaymentAsync(id, cancellationToken).ConfigureAwait(false);
282+
var payment = await client.GetPaymentAsync(id, cancellationToken);
275283

276284
Operation lastCompletedOperation = payment.Operations.LastOrDefault(o => !o.Pending && o.QuickpayStatusCode == "20000");
277285

@@ -308,7 +316,7 @@ public override async Task<ApiResult> CancelPaymentAsync(PaymentProviderContext<
308316
var clientConfig = GetQuickpayClientConfig(ctx.Settings);
309317
var client = new QuickpayClient(clientConfig);
310318

311-
var payment = await client.CancelPaymentAsync(id, cancellationToken).ConfigureAwait(false);
319+
var payment = await client.CancelPaymentAsync(id, cancellationToken);
312320

313321
Operation lastCompletedOperation = payment.Operations.LastOrDefault(o => !o.Pending && o.QuickpayStatusCode == "20000");
314322

@@ -349,7 +357,7 @@ public override async Task<ApiResult> CapturePaymentAsync(PaymentProviderContext
349357
{
350358
amount = AmountToMinorUnits(ctx.Order.TransactionInfo.AmountAuthorized.Value)
351359
},
352-
cancellationToken).ConfigureAwait(false);
360+
cancellationToken);
353361

354362
Operation lastCompletedOperation = payment.Operations.LastOrDefault(o => !o.Pending && o.QuickpayStatusCode == "20000");
355363

@@ -390,7 +398,7 @@ public override async Task<ApiResult> RefundPaymentAsync(PaymentProviderContext<
390398
{
391399
amount = AmountToMinorUnits(ctx.Order.TransactionInfo.AmountAuthorized.Value)
392400
},
393-
cancellationToken).ConfigureAwait(false);
401+
cancellationToken);
394402

395403
Operation lastCompletedOperation = payment.Operations.LastOrDefault(o => !o.Pending && o.QuickpayStatusCode == "20000");
396404

@@ -416,38 +424,28 @@ public override async Task<ApiResult> RefundPaymentAsync(PaymentProviderContext<
416424
return ApiResult.Empty;
417425
}
418426

419-
public async Task<QuickpayPayment> ParseCallbackAsync(HttpRequestMessage request, CancellationToken cancellationToken = default)
427+
private async Task<string> GetJsonBodyAsync(HttpRequest request, CancellationToken cancellationToken = default)
420428
{
421-
using (var stream = await request.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false))
429+
if (request.Body.CanSeek)
422430
{
423-
if (stream.CanSeek)
424-
{
425-
stream.Seek(0, SeekOrigin.Begin);
426-
}
427-
428-
// Get quickpay callback body text - See parameters: https://learn.quickpay.net/tech-talk/api/callback/
429-
430-
using (var reader = new StreamReader(stream))
431-
{
432-
var json = await reader.ReadToEndAsync(cancellationToken).ConfigureAwait(false);
433-
434-
// Deserialize json body text
435-
return JsonSerializer.Deserialize<QuickpayPayment>(json);
436-
}
431+
request.Body.Seek(0, SeekOrigin.Begin);
437432
}
433+
434+
using var reader = new StreamReader(request.Body);
435+
return await reader.ReadToEndAsync(cancellationToken);
438436
}
439437

440-
private async Task<bool> ValidateChecksumAsync(HttpRequestMessage request, string privateAccountKey, CancellationToken cancellationToken = default)
441-
{
442-
var json = await request.Content.ReadAsStringAsync(cancellationToken).ConfigureAwait(false);
443-
var checkSum = request.Headers.GetValues("Quickpay-Checksum-Sha256").FirstOrDefault();
438+
private Task<QuickpayPayment> ParseCallbackAsync(string webhookBody, CancellationToken cancellationToken = default)
439+
=> Task.FromResult(JsonSerializer.Deserialize<QuickpayPayment>(webhookBody));
444440

445-
if (string.IsNullOrEmpty(checkSum))
441+
private async Task<bool> ValidateChecksumAsync(string checksum, string webhookBody, string privateAccountKey, CancellationToken cancellationToken = default)
442+
{
443+
if (string.IsNullOrEmpty(checksum))
446444
return false;
447445

448-
var calculatedChecksum = Checksum(json, privateAccountKey);
446+
var calculatedChecksum = Checksum(webhookBody, privateAccountKey);
449447

450-
return checkSum.Equals(calculatedChecksum);
448+
return checksum.Equals(calculatedChecksum);
451449
}
452450

453451
private string Checksum(string content, string privateKey)

src/Umbraco.Commerce.PaymentProviders.Quickpay/Umbraco.Commerce.PaymentProviders.Quickpay.csproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88

99
<ItemGroup>
1010
<PackageReference Include="Flurl.Http" />
11-
<PackageReference Include="Microsoft.AspNet.WebApi.Client" />
1211
<PackageReference Include="Umbraco.Commerce.Core" />
1312
</ItemGroup>
1413

src/Umbraco.Commerce.PaymentProviders.Quickpay/wwwroot/lang/en.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,5 +35,9 @@ export default {
3535

3636
'quickpayV10CheckoutSettingsFramedLabel': 'Framed',
3737
'quickpayV10CheckoutSettingsFramedDescription': 'Flag indicating whether to allow opening payment page in iframe',
38+
39+
'quickpayV10CheckoutMetaDataQuickpayOrderIdLabel': 'Order ID',
40+
'quickpayV10CheckoutMetaDataQuickpayPaymentIdLabel': 'Payment ID',
41+
'quickpayV10CheckoutMetaDataQuickpayPaymentHashLabel': 'Payment Hash',
3842
},
39-
};
43+
};

tests/Umbraco.Commerce.PaymentProviders.Quickpay.UnitTests/Umbraco.Commerce.PaymentProviders.Quickpay.UnitTests.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>net8.0</TargetFramework>
4+
<TargetFramework>net9.0</TargetFramework>
55
<ImplicitUsings>enable</ImplicitUsings>
66
<Nullable>enable</Nullable>
77

version.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json",
3-
"version": "14.0.0",
3+
"version": "15.0.0",
44
"assemblyVersion": {
55
"precision": "build"
66
},

0 commit comments

Comments
 (0)