diff --git a/.github/mergify.yml b/.github/mergify.yml index 76a4b024de..034eec9685 100644 --- a/.github/mergify.yml +++ b/.github/mergify.yml @@ -2,7 +2,7 @@ queue_rules: - name: default conditions: # Conditions to get out of the queue (= merged) - - check-success=build + - check-success=Run Unit and UI tests - check-success=license/cla pull_request_rules: diff --git a/.github/workflows/deploy_pro_package_samplesite.yml b/.github/workflows/deploy_pro_package_samplesite.yml index be5b0f2347..6d327e2a24 100644 --- a/.github/workflows/deploy_pro_package_samplesite.yml +++ b/.github/workflows/deploy_pro_package_samplesite.yml @@ -20,6 +20,8 @@ jobs: with: workflow_conclusion: success run_id: ${{ github.event.workflow_run.id }} + name: packages + path: packages - name: Publish to nuget run: dotnet nuget push packages/*.nupkg --source https://api.nuget.org/v3/index.json --api-key ${{ secrets.NUGET_API_KEY }} --skip-duplicate diff --git a/.github/workflows/template_build.yml b/.github/workflows/template_build.yml index 1499f6258a..c84f3b986d 100644 --- a/.github/workflows/template_build.yml +++ b/.github/workflows/template_build.yml @@ -43,7 +43,7 @@ jobs: - uses: actions/checkout@v3 - name: Setup .NET - uses: actions/setup-dotnet@v3.0.0 + uses: actions/setup-dotnet@v3.0.3 with: dotnet-version: ${{ env.dotnetVersion }} @@ -83,7 +83,7 @@ jobs: ./src/Samples/Sample.AspNetCore.SystemTests/chrome-driver-udpate.ps1 - name: Publish Sdk Sample site system test - run: dotnet publish --configuration ${{ inputs.Configuration }} -p:Version=${{ inputs.nuGetVersionV2 }} --no-restore ${{ inputs.SystemTestsCsprojPath }} --output '${{ env.AZURE_WEBAPP_PACKAGE_PATH }}/systemtests' --os win + run: dotnet publish --configuration ${{ inputs.Configuration }} -p:Version=${{ inputs.nuGetVersionV2 }} ${{ inputs.SystemTestsCsprojPath }} --output '${{ env.AZURE_WEBAPP_PACKAGE_PATH }}/systemtests' --os win - name: Copy wwwroot to publish directory shell: pwsh @@ -96,8 +96,11 @@ jobs: name: Sample.AspNetCore.SystemTests path: ${{ env.AZURE_WEBAPP_PACKAGE_PATH }}/systemtests - - name: Nuget pack - run: dotnet pack ${{ inputs.SlnPath }} -p:PackageVersion=${{ inputs.NUGETVERSIONV2 }} -p:Version=${{ inputs.NUGETVERSIONV2 }} --no-restore --configuration=${{ inputs.Configuration }} --output=artifacts + - name: Nuget pack SwedbankPay.Sdk + run: dotnet pack ./src/SwedbankPay.Sdk.Infrastructure/SwedbankPay.Sdk.Infrastructure.csproj -p:PackageVersion=${{ inputs.NUGETVERSIONV2 }} -p:Version=${{ inputs.NUGETVERSIONV2 }} --no-restore --configuration=${{ inputs.Configuration }} --output=artifacts + + - name: Nuget pack SwedbankPay.Sdk.Extensions + run: dotnet pack ./src/SwedbankPay.Sdk.Extensions/SwedbankPay.Sdk.Extensions.csproj -p:PackageVersion=${{ inputs.NUGETVERSIONV2 }} -p:Version=${{ inputs.NUGETVERSIONV2 }} --no-restore --configuration=${{ inputs.Configuration }} --output=artifacts - name: Archive nuget packages artifacts uses: actions/upload-artifact@v3 diff --git a/.github/workflows/template_version.yml b/.github/workflows/template_version.yml index f43ebe1d48..4c16c88883 100644 --- a/.github/workflows/template_version.yml +++ b/.github/workflows/template_version.yml @@ -17,7 +17,7 @@ jobs: - uses: actions/checkout@v3 - name: Install GitVersion - uses: gittools/actions/gitversion/setup@v0.9.13 + uses: gittools/actions/gitversion/setup@v0.9.15 with: versionSpec: '5.x.x' @@ -26,4 +26,4 @@ jobs: - name: Use GitVersion id: gitversion # step id used as reference for output values - uses: gittools/actions/gitversion/execute@v0.9.13 \ No newline at end of file + uses: gittools/actions/gitversion/execute@v0.9.15 \ No newline at end of file diff --git a/.github/workflows/test_deploy_samplesite.yml b/.github/workflows/test_deploy_samplesite.yml index b7f3f771c7..6978ae3d76 100644 --- a/.github/workflows/test_deploy_samplesite.yml +++ b/.github/workflows/test_deploy_samplesite.yml @@ -42,7 +42,7 @@ jobs: run_id: ${{ github.event.workflow_run.id }} - name: Setup .NET - uses: actions/setup-dotnet@v3.0.0 + uses: actions/setup-dotnet@v3.0.3 with: dotnet-version: ${{ env.dotnetVersion }} @@ -66,7 +66,7 @@ jobs: - name: Commit Action Status if: ${{ always() }} - uses: LouisBrunner/checks-action@v1.3.1 + uses: LouisBrunner/checks-action@v1.5.0 with: sha: ${{ steps.source-run-info.outputs.sourceHeadSha }} token: ${{ secrets.GITHUB_TOKEN }} @@ -91,7 +91,7 @@ jobs: path: packages - name: Publish test package to GitHub Package Registry - run: dotnet nuget push "packages/*.nupkg" --api-key ${{secrets.GITHUB_TOKEN}} --source https://nuget.pkg.github.com/sveawebpay/index.json --skip-duplicate + run: dotnet nuget push "packages/*.nupkg" --api-key ${{secrets.GITHUB_TOKEN}} --source https://nuget.pkg.github.com/swedbankpay/index.json --skip-duplicate publish_sample_site: needs: [test-unit-ui] diff --git a/src/Samples/Sample.AspNetCore.SystemTests/PageObjectModels/Orders/OrdersPage.cs b/src/Samples/Sample.AspNetCore.SystemTests/PageObjectModels/Orders/OrdersPage.cs index 41d8e3b4b6..3021dd8f53 100644 --- a/src/Samples/Sample.AspNetCore.SystemTests/PageObjectModels/Orders/OrdersPage.cs +++ b/src/Samples/Sample.AspNetCore.SystemTests/PageObjectModels/Orders/OrdersPage.cs @@ -38,5 +38,8 @@ public class ActionRow : TableRow<_> [FindByAutomation("div", "div-orders")] public ItemsControl Orders { get; set; } + + [FindByClass("alert-success")] + public Text<_> SuccessMessage { get; set; } } } \ No newline at end of file diff --git a/src/Samples/Sample.AspNetCore.SystemTests/PageObjectModels/Payment/LocalPaymentMenuPage.cs b/src/Samples/Sample.AspNetCore.SystemTests/PageObjectModels/Payment/LocalPaymentMenuPage.cs index e09b4b5bc7..8c6af7c1f2 100644 --- a/src/Samples/Sample.AspNetCore.SystemTests/PageObjectModels/Payment/LocalPaymentMenuPage.cs +++ b/src/Samples/Sample.AspNetCore.SystemTests/PageObjectModels/Payment/LocalPaymentMenuPage.cs @@ -18,6 +18,9 @@ public class LocalPaymentMenuPage : Page<_> [FindById("trustly")] public Button<_> Trustly { get; private set; } + [FindById("recurring")] + public Button<_> Recurring { get; private set; } + [WaitFor(Until.Visible, TriggerEvents.BeforeAccess)] public Frame<_> PaymentFrame { get; private set; } } diff --git a/src/Samples/Sample.AspNetCore.SystemTests/Sample.AspNetCore.SystemTests.csproj b/src/Samples/Sample.AspNetCore.SystemTests/Sample.AspNetCore.SystemTests.csproj index 78002c1353..0e88bd37d4 100644 --- a/src/Samples/Sample.AspNetCore.SystemTests/Sample.AspNetCore.SystemTests.csproj +++ b/src/Samples/Sample.AspNetCore.SystemTests/Sample.AspNetCore.SystemTests.csproj @@ -12,23 +12,23 @@ - + - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + diff --git a/src/Samples/Sample.AspNetCore.SystemTests/Services/FluentExtensions.cs b/src/Samples/Sample.AspNetCore.SystemTests/Services/FluentExtensions.cs index 9979294962..854c88fa9f 100644 --- a/src/Samples/Sample.AspNetCore.SystemTests/Services/FluentExtensions.cs +++ b/src/Samples/Sample.AspNetCore.SystemTests/Services/FluentExtensions.cs @@ -60,6 +60,15 @@ public static TOwner StoreValueAsUri(this UIComponent component, return component.Owner; } + public static string StorePaymentUri(this UIComponent component) + where TOwner : PageObject + { + var val = component.Content.Value; + var limit = val.IndexOf("/transactions"); + var value = val.Substring(0, limit); + return value; + } + public static TOwner StoreValue(this UIComponent component, out string value) where TOwner : PageObject { diff --git a/src/Samples/Sample.AspNetCore.SystemTests/Test/Helpers/Checkout.cs b/src/Samples/Sample.AspNetCore.SystemTests/Test/Helpers/Checkout.cs index b2b2010b93..5f9d751bd5 100644 --- a/src/Samples/Sample.AspNetCore.SystemTests/Test/Helpers/Checkout.cs +++ b/src/Samples/Sample.AspNetCore.SystemTests/Test/Helpers/Checkout.cs @@ -6,7 +6,8 @@ public enum Option { Anonymous, Standard, - LocalPaymentMenu + LocalPaymentMenu, + LocalPaymentMenuVerification, } } } diff --git a/src/Samples/Sample.AspNetCore.SystemTests/Test/Helpers/PayexCardInfo.cs b/src/Samples/Sample.AspNetCore.SystemTests/Test/Helpers/PayexCardInfo.cs index d64b73d844..49088aa273 100644 --- a/src/Samples/Sample.AspNetCore.SystemTests/Test/Helpers/PayexCardInfo.cs +++ b/src/Samples/Sample.AspNetCore.SystemTests/Test/Helpers/PayexCardInfo.cs @@ -2,16 +2,18 @@ { public class PayexCardInfo : PayexInfo { - public PayexCardInfo(string creditCardNumber, string expiryDate, string cvc) + public PayexCardInfo(string creditCardNumber, string expiryDate, string cvc, bool isVerification) { CreditCardNumber = creditCardNumber; ExpiryDate = expiryDate; Cvc = cvc; + IsVerification = isVerification; } public string CreditCardNumber { get; } public string Cvc { get; } + public bool IsVerification { get; } public string ExpiryDate { get; } } } \ No newline at end of file diff --git a/src/Samples/Sample.AspNetCore.SystemTests/Test/Helpers/PaymentMethods.cs b/src/Samples/Sample.AspNetCore.SystemTests/Test/Helpers/PaymentMethods.cs index cd1abfb6eb..b0f4b89147 100644 --- a/src/Samples/Sample.AspNetCore.SystemTests/Test/Helpers/PaymentMethods.cs +++ b/src/Samples/Sample.AspNetCore.SystemTests/Test/Helpers/PaymentMethods.cs @@ -3,6 +3,7 @@ public class PaymentMethods { public const string Card = "Kort"; + public const string Recurring = "Recurring"; public const string Swish = "Swish"; public const string Invoice = "Faktura"; public const string Trustly = "Bankbetalning"; diff --git a/src/Samples/Sample.AspNetCore.SystemTests/Test/PaymentTests/Base/PaymentTests.cs b/src/Samples/Sample.AspNetCore.SystemTests/Test/PaymentTests/Base/PaymentTests.cs index bb97c37e13..770969f669 100644 --- a/src/Samples/Sample.AspNetCore.SystemTests/Test/PaymentTests/Base/PaymentTests.cs +++ b/src/Samples/Sample.AspNetCore.SystemTests/Test/PaymentTests/Base/PaymentTests.cs @@ -40,6 +40,7 @@ public void Setup() .SetBasePath(Environment.CurrentDirectory) .AddJsonFile("appsettings.json", true) .AddJsonFile("appsettings.local.json", true) + .AddUserSecrets("e6f89439-1a88-4120-92cf-be2d9fe6457d", true) .AddEnvironmentVariables() .Build(); @@ -86,7 +87,7 @@ protected OrdersPage GoToOrdersPage(Product[] products, PayexInfo payexInfo, Che }); } - protected PayexCardFramePage GoToPayexCardPaymentFrame(Product[] products, Checkout.Option checkout = Checkout.Option.Anonymous) + protected PayexCardFramePage GoToPayexCardPaymentFrame(Product[] products, PayexCardInfo payexCardInfo, Checkout.Option checkout = Checkout.Option.Anonymous) { PayexCardFramePage frame = null; @@ -94,8 +95,21 @@ protected PayexCardFramePage GoToPayexCardPaymentFrame(Product[] products, Check { case Checkout.Option.LocalPaymentMenu: frame = GoToLocalPaymentPage(products, checkout) - .CreditCard.IsVisible.WaitTo.BeTrue() - .CreditCard.Click() + .Do(x => + { + if(payexCardInfo.IsVerification) + { + x + .Recurring.IsVisible.WaitTo.BeTrue() + .Recurring.Click(); + } + else + { + x + .CreditCard.IsVisible.WaitTo.BeTrue() + .CreditCard.Click(); + } + }) .PaymentFrame.IsVisible.WaitTo.BeTrue() .PaymentFrame.SwitchTo() .PageSource.WaitTo.WithinSeconds(15).Contain("/psp/"); @@ -219,6 +233,7 @@ protected PaymentFramePage GoToPaymentFramePage(Product[] products, Checkout.Opt .Email.SetWithSpeed(TestDataService.Email, interval: 0.1) .PhoneNumber.SetWithSpeed(TestDataService.SwedishPhoneNumber, interval: 0.1) .Next.Click() + .Next.IsVisible.WaitTo.WithinSeconds(10).BeFalse() .WaitSeconds(1) .Do(x => { if(x.SaveMyInformation.IsVisible) @@ -299,7 +314,7 @@ protected ThankYouPage PayWithPayexCard(Product[] products, PayexCardInfo info, { return checkout switch { - Checkout.Option.Standard => GoToPayexCardPaymentFrame(products, checkout) + Checkout.Option.Standard => GoToPayexCardPaymentFrame(products, info, checkout) .Do(x => { if (x.PreFilledCards.Exists(new SearchOptions { IsSafely = true, Timeout = TimeSpan.FromSeconds(3) })) @@ -332,12 +347,11 @@ protected ThankYouPage PayWithPayexCard(Product[] products, PayexCardInfo info, }) .Pay.Content.Should.BeEquivalent($"Betala {string.Format("{0:N2}", Convert.ToDecimal(products.Sum(x => x.UnitPrice / 100 * x.Quantity)))} kr") .Pay.ClickAndGo(), - _ => GoToPayexCardPaymentFrame(products, checkout) + _ => GoToPayexCardPaymentFrame(products, info, checkout) .CreditCardNumber.IsVisible.WaitTo.BeTrue() .CreditCardNumber.SetWithSpeed(info.CreditCardNumber, interval: 0.1) .ExpiryDate.SetWithSpeed(info.ExpiryDate, interval: 0.1) .Cvc.SetWithSpeed(info.Cvc, interval: 0.1) - .Pay.Content.Should.BeEquivalent($"Betala {string.Format("{0:N2}", Convert.ToDecimal(products.Sum(x => x.UnitPrice / 100 * x.Quantity)))} kr") .Pay.ClickAndGo(), }; } @@ -429,7 +443,12 @@ protected static IEnumerable TestData(bool singleProduct = true, string paymentM { case PaymentMethods.Card: data.Add(new PayexCardInfo(TestDataService.CreditCardNumber, TestDataService.CreditCardExpirationDate, - TestDataService.CreditCardCvc)); + TestDataService.CreditCardCvc, false)); + break; + + case PaymentMethods.Recurring: + data.Add(new PayexCardInfo(TestDataService.CreditCardNumber, TestDataService.CreditCardExpirationDate, + TestDataService.CreditCardCvc, true)); break; case PaymentMethods.Swish: diff --git a/src/Samples/Sample.AspNetCore.SystemTests/Test/PaymentTests/Payment/PaymentVerificationTests.cs b/src/Samples/Sample.AspNetCore.SystemTests/Test/PaymentTests/Payment/PaymentVerificationTests.cs new file mode 100644 index 0000000000..91bccbdcc6 --- /dev/null +++ b/src/Samples/Sample.AspNetCore.SystemTests/Test/PaymentTests/Payment/PaymentVerificationTests.cs @@ -0,0 +1,93 @@ +using Atata; +using NUnit.Framework; +using Sample.AspNetCore.SystemTests.Services; +using Sample.AspNetCore.SystemTests.Test.Helpers; +using SwedbankPay.Sdk; +using SwedbankPay.Sdk.PaymentInstruments; +using SwedbankPay.Sdk.PaymentOrders; +using System; +using System.Linq; +using System.Threading.Tasks; + +namespace Sample.AspNetCore.SystemTests.Test.PaymentTests.Payment +{ + public class PaymentVerificationTests : Base.PaymentTests + { + public PaymentVerificationTests(string driverAlias) + : base(driverAlias) + { + } + + + [Test] + [Retry(2)] + [TestCaseSource(nameof(TestData), new object[] { false, PaymentMethods.Recurring })] + public async Task Payment_Card_Verification(Product[] products, PayexInfo payexInfo) + { + GoToOrdersPage(products, payexInfo, Checkout.Option.LocalPaymentMenu) + .RefreshPageUntil(x => x.Orders[y => y.Attributes["data-paymentlink"] == _referenceLink].IsVisible, 60, 10); + + var cardPayment = await SwedbankPayClient.Payments.CardPayments.Get(new Uri(_referenceLink, UriKind.RelativeOrAbsolute), PaymentExpand.All); + + // Global Order + Assert.That(cardPayment.Payment.Amount.InLowestMonetaryUnit, Is.EqualTo(0)); + Assert.That(cardPayment.Payment.Currency.ToString(), Is.EqualTo("SEK")); + Assert.That(cardPayment.Payment.State, Is.EqualTo(State.Ready)); + + // Operations + Assert.That(cardPayment.Operations.Count, Is.EqualTo(2)); + Assert.That(cardPayment.Operations[LinkRelation.ViewPayment], Is.Not.Null); + Assert.That(cardPayment.Operations[LinkRelation.PaidPayment], Is.Not.Null); + + Assert.That(cardPayment.Payment.RecurrenceToken, Is.Not.Null); + + // Transactions + Assert.That(cardPayment.Payment.Transactions.TransactionList.Count, Is.EqualTo(1)); + Assert.That(cardPayment.Payment.Transactions.TransactionList.First(x => x.Type == TransactionType.Verification).State, + Is.EqualTo(State.Completed)); + } + + [Test] + [Retry(2)] + [TestCaseSource(nameof(TestData), new object[] { false, PaymentMethods.Recurring })] + public async Task Payment_Card_Recurring(Product[] products, PayexInfo payexInfo) + { + var page = GoToOrdersPage(products, payexInfo, Checkout.Option.LocalPaymentMenu) + .RefreshPageUntil(x => x.Orders[y => y.Attributes["data-paymentlink"] == _referenceLink].IsVisible, 60, 10) + .Orders[y => y.Attributes["data-paymentlink"] == _referenceLink].Actions.Rows[y => y.Name.Value.Contains("create-recurring")].ExecuteAction.ClickAndGo(); + + var paymentUriLink1 = page.SuccessMessage.StorePaymentUri(); + + await VerifyPayment(paymentUriLink1, products); + + + page = page.Orders[y => y.Attributes["data-paymentlink"] == _referenceLink].Actions.Rows[y => y.Name.Value.Contains("create-recurring")].ExecuteAction.ClickAndGo(); + + var paymentUriLink2 = page.SuccessMessage.StorePaymentUri(); + + await VerifyPayment(paymentUriLink2, products); + } + + private async Task VerifyPayment(string paymentLink, Product[] products) + { + var cardPayment = await SwedbankPayClient.Payments.CardPayments.Get(new Uri(paymentLink, UriKind.RelativeOrAbsolute), PaymentExpand.All); + + // Global Order + Assert.That(cardPayment.Payment.Amount.InLowestMonetaryUnit, Is.EqualTo(products.Select(x => x.UnitPrice * x.Quantity).Sum())); + Assert.That(cardPayment.Payment.Currency.ToString(), Is.EqualTo("SEK")); + Assert.That(cardPayment.Payment.State, Is.EqualTo(State.Ready)); + + // Operations + Assert.That(cardPayment.Operations.Count, Is.EqualTo(2)); + Assert.That(cardPayment.Operations[LinkRelation.CreateReversal], Is.Not.Null); + Assert.That(cardPayment.Operations[LinkRelation.PaidPayment], Is.Not.Null); + + // Transactions + Assert.That(cardPayment.Payment.Transactions.TransactionList.Count, Is.EqualTo(2)); + Assert.That(cardPayment.Payment.Transactions.TransactionList.First(x => x.Type == TransactionType.Authorization).State, + Is.EqualTo(State.Completed)); + Assert.That(cardPayment.Payment.Transactions.TransactionList.First(x => x.Type == TransactionType.Capture).State, + Is.EqualTo(State.Completed)); + } + } +} \ No newline at end of file diff --git a/src/Samples/Sample.AspNetCore.SystemTests/Test/PaymentTests/Validation/ValidationTests.cs b/src/Samples/Sample.AspNetCore.SystemTests/Test/PaymentTests/Validation/ValidationTests.cs index 4c1e7c833a..c04f290bfb 100644 --- a/src/Samples/Sample.AspNetCore.SystemTests/Test/PaymentTests/Validation/ValidationTests.cs +++ b/src/Samples/Sample.AspNetCore.SystemTests/Test/PaymentTests/Validation/ValidationTests.cs @@ -30,7 +30,7 @@ public void FieldValidationCard(Product[] products) { Assert.DoesNotThrow(() => { - GoToPayexCardPaymentFrame(products) + GoToPayexCardPaymentFrame(products, null) .CreditCardNumber.Set("abc") .ExpiryDate.Set("abcd") .Cvc.Set("abc") diff --git a/src/Samples/Sample.AspNetCore/Controllers/CheckOutController.cs b/src/Samples/Sample.AspNetCore/Controllers/CheckOutController.cs index b13860fc8f..a4588c7eee 100644 --- a/src/Samples/Sample.AspNetCore/Controllers/CheckOutController.cs +++ b/src/Samples/Sample.AspNetCore/Controllers/CheckOutController.cs @@ -205,6 +205,49 @@ public async Task CreateCardPayment() } } + + public async Task CreateVerifyRecurringPayment() + { + try + { + var cardRequest = new CardPaymentVerifyRequest(PaymentIntent.Authorization, new Currency("SEK"), + "Test Purchase", "useragent", + new Language("sv-SE"), + new Urls( + this.urls.HostUrls.ToList(), + this.urls.CompleteUrl, + this.urls.TermsOfServiceUrl) + { + CancelUrl = this.urls.CancelUrl, + PaymentUrl = this.urls.PaymentUrl, + CallbackUrl = this.urls.CallbackUrl, + LogoUrl = this.urls.LogoUrl + }, + new PayeeInfo(this.payeeInfoOptions.PayeeId, + this.payeeInfoOptions.PayeeReference) + ); + foreach (var url in urls.HostUrls) + { + cardRequest.Payment.Urls.HostUrls.Add(url); + } + + cardRequest.Payment.GenerateRecurrenceToken = true; + + var cardPayment = await this.swedbankPayClient.Payments.CardPayments.Create(cardRequest); + this.cartService.PaymentLink = cardPayment.Payment.Id.OriginalString; + this.cartService.Instrument = PaymentInstrument.CreditCard; + this.cartService.PaymentOrderLink = null; + this.cartService.Update(); + return cardPayment; + } + catch (Exception ex) + { + Debug.Write(ex.Message); + return null; + } + } + + public async Task CreateTrustlyPayment() { var totalAmount = this.cartService.CalculateTotal(); @@ -397,15 +440,22 @@ public async Task LoadSwishPaymentMenu() } [HttpPost] - public async Task GetPaymentJsSource(PaymentInstrument instrument) + public async Task GetPaymentJsSource(PaymentInstrument instrument, bool recurring = false) { switch (instrument) { case PaymentInstrument.CreditCard: - var cardPayment = await CreateCardPayment().ConfigureAwait(false); - return new JsonResult(cardPayment.Operations.ViewAuthorization.Href); - - case PaymentInstrument.Swish: + if (recurring) + { + var recurringPayment = await CreateVerifyRecurringPayment().ConfigureAwait(false); + return new JsonResult(recurringPayment.Operations.ViewVerification.Href); + } + else + { + var cardPayment = await CreateCardPayment().ConfigureAwait(false); + return new JsonResult(cardPayment.Operations.ViewAuthorization.Href); + } + case PaymentInstrument.Swish: var swishPayment = await CreateSwishPayment().ConfigureAwait(false); return new JsonResult(swishPayment.Operations.ViewSales.Href); diff --git a/src/Samples/Sample.AspNetCore/Controllers/OrdersController.cs b/src/Samples/Sample.AspNetCore/Controllers/OrdersController.cs index 12efe2904e..bbe8a98e2e 100644 --- a/src/Samples/Sample.AspNetCore/Controllers/OrdersController.cs +++ b/src/Samples/Sample.AspNetCore/Controllers/OrdersController.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; @@ -96,12 +97,12 @@ public async Task Details(int? _) foreach (var order in orders) { - IEnumerable operations = Enumerable.Empty(); + List operations = new List(); if (order.PaymentOrderLink != null) { var paymentOrder = await this.swedbankPayClient.PaymentOrders.Get(order.PaymentOrderLink); var paymentOrderOperations = paymentOrder.Operations.Where(r => r.Key.Value.Contains("paymentorder")).Select(x => x.Value); - operations = paymentOrderOperations; + operations = paymentOrderOperations.ToList(); } else { @@ -110,17 +111,24 @@ public async Task Details(int? _) case PaymentInstrument.Swish: var swishPayment = await this.swedbankPayClient.Payments.SwishPayments.Get(order.PaymentLink, PaymentExpand.All); var swishOperations = swishPayment.Operations; - operations = swishOperations.Values; + operations = swishOperations.Values.ToList(); break; case PaymentInstrument.CreditCard: - var cardPayment = await this.swedbankPayClient.Payments.SwishPayments.Get(order.PaymentLink, PaymentExpand.All); + var cardPayment = await this.swedbankPayClient.Payments.CardPayments.Get(order.PaymentLink, PaymentExpand.All); var cardOperations = cardPayment.Operations; - operations = cardOperations.Values; + operations = cardOperations.Values.ToList(); + + if (!string.IsNullOrWhiteSpace(cardPayment.Payment.RecurrenceToken) + && cardPayment.Payment.Operation.Equals(Operation.Verify)) + { + operations.Add(new HttpOperation(new Uri("https://localhost:5001"), new LinkRelation("create-recurring", "create-recurring"), "GET", "text/html")); + } + break; case PaymentInstrument.Trustly: var trustlyPayment = await this.swedbankPayClient.Payments.TrustlyPayments.Get(order.PaymentLink, PaymentExpand.All); var trustlyOperations = trustlyPayment.Operations; - operations = trustlyOperations.Values; + operations = trustlyOperations.Values.ToList(); break; } } diff --git a/src/Samples/Sample.AspNetCore/Controllers/PaymentController.cs b/src/Samples/Sample.AspNetCore/Controllers/PaymentController.cs index a2a73c6168..46d9e71618 100644 --- a/src/Samples/Sample.AspNetCore/Controllers/PaymentController.cs +++ b/src/Samples/Sample.AspNetCore/Controllers/PaymentController.cs @@ -19,14 +19,21 @@ public class PaymentController : Controller private readonly StoreDbContext context; private readonly PayeeInfoConfig payeeInfoOptions; private readonly ISwedbankPayClient swedbankPayClient; + private readonly UrlsOptions urls; - public PaymentController(IOptionsSnapshot payeeInfoOptionsAccessor, Cart cart, StoreDbContext dbContext, ISwedbankPayClient payClient) + public PaymentController( + IOptionsSnapshot payeeInfoOptionsAccessor, + Cart cart, + StoreDbContext dbContext, + ISwedbankPayClient payClient, + IOptionsSnapshot urlsAccessor) { this.payeeInfoOptions = payeeInfoOptionsAccessor.Value; this.cartService = cart; this.context = dbContext; this.swedbankPayClient = payClient; + this.urls = urlsAccessor.Value; } @@ -133,6 +140,36 @@ public async Task PaymentOrderCapture(string paymentOrderId) TempData["ErrorMessage"] = $"Something unexpected happened. {e.Message}"; return RedirectToAction("Details", "Orders"); } + } + + [HttpGet] + public async Task Recurring(string paymentId, PaymentInstrument instrument) + { + try + { + var description = "Recurring the authorized payment"; + + switch (instrument) + { + case PaymentInstrument.CreditCard: + var cardPayment = await this.swedbankPayClient.Payments.CardPayments.Get(new Uri(paymentId, UriKind.RelativeOrAbsolute)); + + var recurringRequest = await GetRecurringRequest(description, cardPayment.Payment.RecurrenceToken); + + var response = await this.swedbankPayClient.Payments.CardPayments.Create(recurringRequest, PaymentExpand.All); + var transaction = response.Payment.Transactions.TransactionList.LastOrDefault(); + TempData["CaptureMessage"] = $"{transaction.Id}, {transaction.State}, {transaction.Type}"; + break; + } + + this.cartService.PaymentLink = null; + return RedirectToAction("Details", "Orders"); + } + catch (Exception e) + { + TempData["ErrorMessage"] = $"Something unexpected happened. {e.Message}"; + return RedirectToAction("Details", "Orders"); + } } @@ -256,6 +293,23 @@ public async Task Reversal(string paymentId, PaymentInstrument in } + private async Task GetRecurringRequest(string description, string reccurenceToken) + { + var order = await this.context.Orders.Include(l => l.Lines).ThenInclude(p => p.Product).FirstOrDefaultAsync(); + + var request = new SwedbankPay.Sdk.PaymentInstruments.Card.CardPaymentRecurRequest(PaymentIntent.AutoCapture, reccurenceToken, new Currency("SEK"), new Amount(order.Lines.Sum(e => e.Quantity * e.Product.Price)), + new Amount(0), description, "useragent", new Language("sv-SE"), + new Urls(this.urls.HostUrls.ToList(), this.urls.CompleteUrl, + this.urls.TermsOfServiceUrl) + { + CancelUrl = this.urls.CancelUrl, + PaymentUrl = this.urls.PaymentUrl, + CallbackUrl = this.urls.CallbackUrl, + LogoUrl = this.urls.LogoUrl + }, new PayeeInfo(this.payeeInfoOptions.PayeeId, this.payeeInfoOptions.PayeeReference)); + return request; + } + private async Task GetCaptureRequest(string description) { var order = await this.context.Orders.Include(l => l.Lines).ThenInclude(p => p.Product).FirstOrDefaultAsync(); diff --git a/src/Samples/Sample.AspNetCore/Sample.AspNetCore.csproj b/src/Samples/Sample.AspNetCore/Sample.AspNetCore.csproj index f97617c6b5..1106b8ce07 100644 --- a/src/Samples/Sample.AspNetCore/Sample.AspNetCore.csproj +++ b/src/Samples/Sample.AspNetCore/Sample.AspNetCore.csproj @@ -15,7 +15,7 @@ - + diff --git a/src/Samples/Sample.AspNetCore/Views/Checkout/Payment.cshtml b/src/Samples/Sample.AspNetCore/Views/Checkout/Payment.cshtml index 749e89c7fc..b863fef3c8 100644 --- a/src/Samples/Sample.AspNetCore/Views/Checkout/Payment.cshtml +++ b/src/Samples/Sample.AspNetCore/Views/Checkout/Payment.cshtml @@ -3,17 +3,20 @@

Betala med

- - - - +
@@ -102,12 +105,15 @@ } - function startPayment(instrument) { + function startPayment(instrument, recurring) { resetPaymentFrame(); currentInstrument = instrument; $.post("/checkout/GetPaymentJsSource", - { instrument: instrument }, + { + instrument: instrument, + recurring: recurring + }, function (paymentPageUrl) { setFrameHostedView(paymentPageUrl, instrument); removeError(); diff --git a/src/Samples/Sample.AspNetCore/Views/Orders/Details.cshtml b/src/Samples/Sample.AspNetCore/Views/Orders/Details.cshtml index 8fc4d5459c..ac4c13d99b 100644 --- a/src/Samples/Sample.AspNetCore/Views/Orders/Details.cshtml +++ b/src/Samples/Sample.AspNetCore/Views/Orders/Details.cshtml @@ -118,6 +118,9 @@ else if (TempData["ErrorMessage"] != null) case PaymentResourceOperations.CreateCancellation: actionName = "Cancel"; break; + case "create-recurring": + actionName = "Recurring"; + break; } @if (!string.IsNullOrEmpty(actionName)) diff --git a/src/SwedbankPay.Sdk.Extensions/SwedbankPay.Sdk.Extensions.csproj b/src/SwedbankPay.Sdk.Extensions/SwedbankPay.Sdk.Extensions.csproj index c4efaa74eb..076af91458 100644 --- a/src/SwedbankPay.Sdk.Extensions/SwedbankPay.Sdk.Extensions.csproj +++ b/src/SwedbankPay.Sdk.Extensions/SwedbankPay.Sdk.Extensions.csproj @@ -27,7 +27,7 @@ - + diff --git a/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/Card/CardPayment.cs b/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/Card/CardPayment.cs index 218c48fbad..3e379f1eb1 100644 --- a/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/Card/CardPayment.cs +++ b/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/Card/CardPayment.cs @@ -26,10 +26,10 @@ public CardPayment(CardPaymentDto payment) Language = new Language(payment.Language); Number = payment.Number; Operation = payment.Operation; - PayeeInfo = payment.PayeeInfo.Map(); + PayeeInfo = payment.PayeeInfo?.Map(); PayerReference = payment.PayerReference; InitiatingSystemUserAgent = payment.InitiatingSystemUserAgent; - Prices = payment.Prices.Map(); + Prices = payment.Prices?.Map(); State = payment.State; Urls = new UrlsResponse(payment.Urls); UserAgent = payment.UserAgent; @@ -41,6 +41,7 @@ public CardPayment(CardPaymentDto payment) Captures = payment.Captures?.Map(); Reversals = payment.Reversals?.Map(); Transactions = payment.Transactions?.Map(); + Verifications = payment.Verifications?.Map(); if (!string.IsNullOrEmpty(payment.Intent)) { Intent = payment.Intent.ParseTo(); @@ -95,6 +96,8 @@ public CardPayment(CardPaymentDto payment) public ITransactionListResponse Transactions { get; } + public IVerificationListResponse Verifications { get; } + public IUrls Urls { get; } public string UserAgent { get; } diff --git a/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/Card/CardPaymentOperations.cs b/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/Card/CardPaymentOperations.cs index 6f60946d28..7eebcffbc5 100644 --- a/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/Card/CardPaymentOperations.cs +++ b/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/Card/CardPaymentOperations.cs @@ -75,6 +75,10 @@ internal CardPaymentOperations(IOperationList operations, HttpClient client) case PaymentResourceOperations.PaidPayment: PaidPayment = httpOperation; break; + + case PaymentResourceOperations.ViewPayment: + ViewPayment = httpOperation; + break; } Add(httpOperation.Rel, httpOperation); } @@ -91,5 +95,6 @@ internal CardPaymentOperations(IOperationList operations, HttpClient client) public HttpOperation RedirectVerification { get; } public HttpOperation ViewAuthorization { get; } public HttpOperation ViewVerification { get; } + public HttpOperation ViewPayment { get; } } } \ No newline at end of file diff --git a/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/Card/CardPaymentVerification.cs b/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/Card/CardPaymentVerification.cs index 08f08c0178..231a3fa3cd 100644 --- a/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/Card/CardPaymentVerification.cs +++ b/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/Card/CardPaymentVerification.cs @@ -1,17 +1,30 @@ namespace SwedbankPay.Sdk.PaymentInstruments.Card { + using System; + internal class CardPaymentVerification : Identifiable, ICardPaymentVerification { - public CardPaymentVerification(CardPaymentVerificationDto dto) + public CardPaymentVerification(VerificationDto dto) : base(dto.Id) { - PaymentToken = dto.PaymentToken; + Direct = dto.Direct; + CardBrand = dto.CardBrand; + CardType = dto.CardType; + IssuingBank = dto.IssuingBank; RecurrenceToken = dto.RecurrenceToken; MaskedPan = dto.MaskedPan; ExpiryDate = dto.ExpiryDate; PanToken = dto.PanToken; - CardBrand = dto.CardBrand; - CardType = dto.CardType; + PanEnrolled = dto.PanEnrolled; + IssuerAuthorizationApprovalCode = dto.IssuerAuthorizationApprovalCode; + AcquirerTransactionType = dto.AcquirerTransactionType; + AcquirerStan = dto.AcquirerStan; + AcquirerTerminalId = dto.AcquirerTerminalId; + AcquirerTransactionTime = dto.AcquirerTransactionTime; + NonPaymentToken = dto.NonPaymentToken; + TransactionInitiator = dto.TransactionInitiator; + + PaymentToken = dto.PaymentToken; IsOperational = dto.IsOperational; if(dto.Transaction != null) @@ -22,13 +35,25 @@ public CardPaymentVerification(CardPaymentVerificationDto dto) Problem = dto.Problem?.Map(); } + public bool Direct { get; } public string CardBrand { get; } public string CardType { get; } + public string IssuingBank { get; } public string PaymentToken { get; } public string RecurrenceToken { get; } public string MaskedPan { get; } public string ExpiryDate { get; } public string PanToken { get; } + public bool PanEnrolled { get; } + public string IssuerAuthorizationApprovalCode { get; } + public string AcquirerTransactionType { get; set; } + public string AcquirerStan { get; set; } + public string AcquirerTerminalId { get; set; } + public DateTime AcquirerTransactionTime { get; set; } + public string NonPaymentToken { get; set; } + public string TransactionInitiator { get; set; } + + public IVerifyTransaction Transaction { get; } public bool IsOperational { get; } public IProblem Problem { get; } diff --git a/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/Card/CardPaymentVerificationDto.cs b/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/Card/CardPaymentVerificationDto.cs deleted file mode 100644 index e9cbdcd92a..0000000000 --- a/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/Card/CardPaymentVerificationDto.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace SwedbankPay.Sdk.PaymentInstruments.Card -{ - internal class CardPaymentVerificationDto - { - public string Id { get; set; } - public string CardBrand { get; set; } - public string CardType { get; set; } - public string PaymentToken { get; set; } - public string RecurrenceToken { get; set; } - public string MaskedPan { get; set; } - public string ExpiryDate { get; set; } - public string PanToken { get; set; } - public VerifyTransactionDto Transaction { get; set; } - public bool IsOperational { get; set; } - public ProblemDto Problem { get; set; } - } -} \ No newline at end of file diff --git a/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/Card/CardPaymentVerifyRequestDetailsDto.cs b/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/Card/CardPaymentVerifyRequestDetailsDto.cs index 444042a429..ef19c1ebbe 100644 --- a/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/Card/CardPaymentVerifyRequestDetailsDto.cs +++ b/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/Card/CardPaymentVerifyRequestDetailsDto.cs @@ -8,13 +8,13 @@ public CardPaymentVerifyRequestDetailsDto(CardPaymentVerifyRequestDetails paymen Intent = payment.Intent.ToString(); RecurrenceToken = payment.RecurrenceToken; Currency = payment.Currency.ToString(); - Amount = payment.Amount.InLowestMonetaryUnit; - VatAmount = payment.VatAmount.InLowestMonetaryUnit; Description = payment.Description; UserAgent = payment.UserAgent; Language = payment.Language.ToString(); Urls = new UrlsDto(payment.Urls); PayeeInfo = new PayeeInfoResponseDto(payment.PayeeInfo); + GenerateRecurrenceToken = payment.GenerateRecurrenceToken; + GeneratePaymentToken = payment.GeneratePaymentToken; if (payment.Metadata != null) { @@ -30,12 +30,21 @@ public CardPaymentVerifyRequestDetailsDto(CardPaymentVerifyRequestDetails paymen public string Currency { get; } - public long Amount { get; } - - public long VatAmount { get; } - public string Description { get; } + /// + /// When making the initial purchase request, you need to generate a paymentToken. + /// You can do this either by by setting the GeneratePaymentToken field to true, + /// or set the initial operation to Verify. + /// + public bool GeneratePaymentToken { get; set; } + + /// + /// Set this to true if you want to create a recurrenceToken for future use Recurring purchases (subscription + /// payments). + /// + public bool GenerateRecurrenceToken { get; set; } + public string UserAgent { get; } public string Language { get; } diff --git a/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/Card/CardPaymentVerifyResponse.cs b/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/Card/CardPaymentVerifyResponse.cs index 7c2c4d51ee..465f4d2e47 100644 --- a/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/Card/CardPaymentVerifyResponse.cs +++ b/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/Card/CardPaymentVerifyResponse.cs @@ -8,6 +8,6 @@ public CardPaymentVerifyResponse(CardPaymentVerifyResponseDto dto) Verifications = dto.Verifications.Map(); } - public ICardPaymentVerifyResponseDetails Verifications { get; } + public IVerificationListResponse Verifications { get; } } } diff --git a/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/Card/CardPaymentVerifyResponseDetailsDto.cs b/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/Card/CardPaymentVerifyResponseDetailsDto.cs deleted file mode 100644 index 262151f852..0000000000 --- a/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/Card/CardPaymentVerifyResponseDetailsDto.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace SwedbankPay.Sdk.PaymentInstruments.Card -{ - internal class CardPaymentVerifyResponseDetailsDto - { - public Uri Id { get; set; } - public IList VerificationList { get; set; } - - internal ICardPaymentVerifyResponseDetails Map() - { - return new CardPaymentVerifyResponseDetails(Id, VerificationList); - } - } -} \ No newline at end of file diff --git a/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/Card/CardPaymentVerifyResponseDto.cs b/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/Card/CardPaymentVerifyResponseDto.cs index 8677c20b57..3f28db15fd 100644 --- a/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/Card/CardPaymentVerifyResponseDto.cs +++ b/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/Card/CardPaymentVerifyResponseDto.cs @@ -1,9 +1,11 @@ -namespace SwedbankPay.Sdk.PaymentInstruments.Card +using System; + +namespace SwedbankPay.Sdk.PaymentInstruments.Card { internal class CardPaymentVerifyResponseDto { public string Payment { get; set; } - public CardPaymentVerifyResponseDetailsDto Verifications { get; set; } + public VerificationListResponseDto Verifications { get; set; } } } \ No newline at end of file diff --git a/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/Card/CardPaymentsResource.cs b/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/Card/CardPaymentsResource.cs index 2cd286bc18..28396fdae8 100644 --- a/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/Card/CardPaymentsResource.cs +++ b/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/Card/CardPaymentsResource.cs @@ -45,15 +45,14 @@ public async Task Create(CardPaymentRecurRequest paym return new CardPaymentRecurResponse(cardPaymentResponseDto, HttpClient); } - public async Task Create(CardPaymentVerifyRequest paymentRequest, PaymentExpand paymentExpand = PaymentExpand.All) + public async Task Create(CardPaymentVerifyRequest paymentRequest, PaymentExpand paymentExpand = PaymentExpand.All) { var url = new Uri("/psp/creditcard/payments", UriKind.Relative).GetUrlWithQueryString(paymentExpand); var requestDto = new CardPaymentVerifyRequestDto(paymentRequest); - var cardPaymentResponseDto = await HttpClient.PostAsJsonAsync(url.GetUrlWithQueryString(paymentExpand), requestDto); - return new CardPaymentVerifyResponse(cardPaymentResponseDto); - + var cardPaymentResponseDto = await HttpClient.PostAsJsonAsync(url.GetUrlWithQueryString(paymentExpand), requestDto); + return new CardPaymentResponse(cardPaymentResponseDto, HttpClient); } } } diff --git a/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/Card/VerificationDto.cs b/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/Card/VerificationDto.cs new file mode 100644 index 0000000000..421e306b18 --- /dev/null +++ b/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/Card/VerificationDto.cs @@ -0,0 +1,32 @@ +using System; + +namespace SwedbankPay.Sdk.PaymentInstruments.Card +{ + internal class VerificationDto + { + public bool Direct { get; set; } + public string CardBrand { get; set; } + public string CardType { get; set; } + public string IssuingBank { get; set; } + public string RecurrenceToken { get; set; } + public string MaskedPan { get; set; } + public string ExpiryDate { get; set; } + public string PanToken { get; set; } + public bool PanEnrolled { get; set; } + public string IssuerAuthorizationApprovalCode { get; set; } + public string AcquirerTransactionType { get; set; } + public string AcquirerStan { get; set; } + public string AcquirerTerminalId { get; set; } + public DateTime AcquirerTransactionTime { get; set; } + public string NonPaymentToken { get; set; } + public string TransactionInitiator { get; set; } + public string Id { get; set; } + public VerifyTransactionDto Transaction { get; set; } + + + + public string PaymentToken { get; set; } + public bool IsOperational { get; set; } + public ProblemDto Problem { get; set; } + } +} \ No newline at end of file diff --git a/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/Card/CardPaymentVerifyResponseDetails.cs b/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/Card/VerificationListResponse.cs similarity index 65% rename from src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/Card/CardPaymentVerifyResponseDetails.cs rename to src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/Card/VerificationListResponse.cs index 9026482af8..4f93330708 100644 --- a/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/Card/CardPaymentVerifyResponseDetails.cs +++ b/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/Card/VerificationListResponse.cs @@ -1,19 +1,19 @@ -using System; -using System.Collections.Generic; - -namespace SwedbankPay.Sdk.PaymentInstruments.Card -{ - internal class CardPaymentVerifyResponseDetails : Identifiable, ICardPaymentVerifyResponseDetails - { - public CardPaymentVerifyResponseDetails(Uri id, IList verificationList) - :base(id) - { - foreach (var item in verificationList) - { - VerificationList.Add(new CardPaymentVerification(item)); - } - } - - public IList VerificationList { get; } = new List(); - } +using System; +using System.Collections.Generic; + +namespace SwedbankPay.Sdk.PaymentInstruments.Card +{ + internal class VerificationListResponse : Identifiable, IVerificationListResponse + { + public VerificationListResponse(Uri id, IList verificationList) + :base(id) + { + foreach (var item in verificationList) + { + VerificationList.Add(new CardPaymentVerification(item)); + } + } + + public IList VerificationList { get; } = new List(); + } } \ No newline at end of file diff --git a/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/Card/VerificationListResponseDto.cs b/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/Card/VerificationListResponseDto.cs new file mode 100644 index 0000000000..dd9d766d6d --- /dev/null +++ b/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/Card/VerificationListResponseDto.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; + +namespace SwedbankPay.Sdk.PaymentInstruments.Card +{ + internal class VerificationListResponseDto + { + public Uri Id { get; set; } + public IList VerificationList { get; set; } = new List(); + + internal IVerificationListResponse Map() + { + return new VerificationListResponse(Id, VerificationList); + } + } +} \ No newline at end of file diff --git a/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/CardPaymentDto.cs b/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/CardPaymentDto.cs index ba37f935e0..378b2e55a6 100644 --- a/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/CardPaymentDto.cs +++ b/src/SwedbankPay.Sdk.Infrastructure/PaymentInstruments/CardPaymentDto.cs @@ -1,5 +1,7 @@ using System; +using SwedbankPay.Sdk.PaymentInstruments.Card; + namespace SwedbankPay.Sdk.PaymentInstruments { internal class CardPaymentDto @@ -54,6 +56,8 @@ internal class CardPaymentDto public TransactionListResponseDto Transactions { get; set; } + public VerificationListResponseDto Verifications { get; set; } + public UrlsDto Urls { get; set; } public string UserAgent { get; set; } diff --git a/src/SwedbankPay.Sdk.IntegrationTests/PaymentOrderTests.cs b/src/SwedbankPay.Sdk.IntegrationTests/PaymentOrderTests.cs index aa50026e3c..94644a5777 100644 --- a/src/SwedbankPay.Sdk.IntegrationTests/PaymentOrderTests.cs +++ b/src/SwedbankPay.Sdk.IntegrationTests/PaymentOrderTests.cs @@ -163,23 +163,23 @@ public async Task CreatePaymentOrder_With_RestrictedToInstruments_ShouldMapCorre - [Fact] - public async Task GetPaymentOrder_WithPayment_ShouldReturnCurrentPaymentIfExpanded() - { - //ARRANGE - _ = this.paymentOrderRequestBuilder.WithTestValues(this.payeeId) - .WithOrderItems() - .Build(); - - //ACT - var paymentOrder = await this.Sut.PaymentOrders.Get(new Uri("/psp/paymentorders/472e6f26-a9b5-4e91-1b70-08d756b9b7d8", UriKind.Relative), - PaymentOrderExpand.CurrentPayment); - - //ASSERT - Assert.NotNull(paymentOrder); - Assert.NotNull(paymentOrder.PaymentOrder.CurrentPayment); - Assert.NotNull(paymentOrder.PaymentOrder.CurrentPayment.Payment); - } + //[Fact] + //public async Task GetPaymentOrder_WithPayment_ShouldReturnCurrentPaymentIfExpanded() + //{ + // //ARRANGE + // _ = this.paymentOrderRequestBuilder.WithTestValues(this.payeeId) + // .WithOrderItems() + // .Build(); + + // //ACT + // var paymentOrder = await this.Sut.PaymentOrders.Get(new Uri("/psp/paymentorders/7737d790-dcbe-40e9-6441-08db13e1be83", UriKind.Relative), + // PaymentOrderExpand.CurrentPayment); + + // //ASSERT + // Assert.NotNull(paymentOrder); + // Assert.NotNull(paymentOrder.PaymentOrder.CurrentPayment); + // Assert.NotNull(paymentOrder.PaymentOrder.CurrentPayment.Payment); + //} [Fact] public async Task GetUnknownPaymentOrder_ShouldThrowHttpResponseException() diff --git a/src/SwedbankPay.Sdk.IntegrationTests/PaymentTests/CardPaymentTests.cs b/src/SwedbankPay.Sdk.IntegrationTests/PaymentTests/CardPaymentTests.cs index 347b2d23a7..621f665cd0 100644 --- a/src/SwedbankPay.Sdk.IntegrationTests/PaymentTests/CardPaymentTests.cs +++ b/src/SwedbankPay.Sdk.IntegrationTests/PaymentTests/CardPaymentTests.cs @@ -15,7 +15,7 @@ public class CardPaymentTests : ResourceTestsBase public async Task GetPayment() { var creditCardPayment = await this.Sut.Payments.CardPayments.Get( - new Uri("/psp/creditcard/payments/a46d809a-8d6b-4ade-4b2c-08d88169daef", UriKind.Relative), PaymentExpand.All); + new Uri("/psp/creditcard/payments/08bb7e22-167b-43e5-94f6-08dabd8f424e", UriKind.Relative), PaymentExpand.All); Assert.NotNull(creditCardPayment); } @@ -24,17 +24,33 @@ public async Task GetPayment() [Fact] public async Task CreateVerifyPayment_ShouldReturnPayment() { - var paymentRequest = this.paymentRequestBuilder.WithCreditcardTestValues(this.payeeId, Operation.Verify).BuildCreditardPaymentRequest(); + var paymentRequest = this.paymentRequestBuilder.WithCreditcardTestValues(this.payeeId, Operation.Verify).BuildCreditCardPaymentRequest(); var creditCardPayment = await this.Sut.Payments.CardPayments.Create(paymentRequest, PaymentExpand.All); Assert.Equal(UserAgent.Default, creditCardPayment.Payment.InitiatingSystemUserAgent); Assert.NotNull(creditCardPayment); } + [Fact] + public async Task CreateVerifyRecurringPayment_ShouldReturnPayment() + { + var paymentRequest = this.paymentRequestBuilder.WithCreditcardTestValues(this.payeeId, Operation.Verify, generateRecurrenceToken: true).BuildCreditCardVerifyPaymentRequest(); + var cardPayment = await this.Sut.Payments.CardPayments.Create(paymentRequest, PaymentExpand.All); + Assert.NotNull(cardPayment); + } + + [Fact] + public async Task CreateRecurringPayment_ShouldReturnPayment() + { + var recurPaymentRequest = this.paymentRequestBuilder.WithCreditcardTestValues(this.payeeId, Operation.Verify, recurrenceToken: "fb813868-1491-4854-a71d-e3b9878b342d").BuildCreditCardRecurPaymentRequest(); + var cardPayment = await this.Sut.Payments.CardPayments.Create(recurPaymentRequest, PaymentExpand.All); + Assert.NotNull(cardPayment); + } + [Fact] public async Task CreatePayment_ShouldReturnPayment() { - var paymentRequest = this.paymentRequestBuilder.WithCreditcardTestValues(this.payeeId).BuildCreditardPaymentRequest(); + var paymentRequest = this.paymentRequestBuilder.WithCreditcardTestValues(this.payeeId).BuildCreditCardPaymentRequest(); var creditCardPayment = await this.Sut.Payments.CardPayments.Create(paymentRequest, PaymentExpand.All); Assert.NotNull(creditCardPayment); diff --git a/src/SwedbankPay.Sdk.IntegrationTests/PaymentTests/SwishPaymentTests.cs b/src/SwedbankPay.Sdk.IntegrationTests/PaymentTests/SwishPaymentTests.cs index efa69b2264..a195adab63 100644 --- a/src/SwedbankPay.Sdk.IntegrationTests/PaymentTests/SwishPaymentTests.cs +++ b/src/SwedbankPay.Sdk.IntegrationTests/PaymentTests/SwishPaymentTests.cs @@ -74,7 +74,7 @@ public async Task CreateSwishPayment_ShouldReturnPayment() public async Task GetPayment() { var payment = await this.Sut.Payments.SwishPayments.Get( - new Uri("/psp/swish/payments/dda2cbde-117a-4742-cbc9-08d7942e23d8", UriKind.Relative), PaymentExpand.All); + new Uri("/psp/swish/payments/9ffb0e41-d126-4bc4-0543-08db13d23495", UriKind.Relative), PaymentExpand.All); Assert.NotNull(payment); } } diff --git a/src/SwedbankPay.Sdk.IntegrationTests/SwedbankPay.Sdk.IntegrationTests.csproj b/src/SwedbankPay.Sdk.IntegrationTests/SwedbankPay.Sdk.IntegrationTests.csproj index ce73cc524b..83c47dfd01 100644 --- a/src/SwedbankPay.Sdk.IntegrationTests/SwedbankPay.Sdk.IntegrationTests.csproj +++ b/src/SwedbankPay.Sdk.IntegrationTests/SwedbankPay.Sdk.IntegrationTests.csproj @@ -12,7 +12,7 @@
- + diff --git a/src/SwedbankPay.Sdk.Tests/SwedbankPay.Sdk.Tests.csproj b/src/SwedbankPay.Sdk.Tests/SwedbankPay.Sdk.Tests.csproj index e0d4d1073a..df8e8b7ead 100644 --- a/src/SwedbankPay.Sdk.Tests/SwedbankPay.Sdk.Tests.csproj +++ b/src/SwedbankPay.Sdk.Tests/SwedbankPay.Sdk.Tests.csproj @@ -41,12 +41,12 @@ - - - - + + + + - + diff --git a/src/SwedbankPay.Sdk.Tests/TestBuilders/PaymentRequestBuilder.cs b/src/SwedbankPay.Sdk.Tests/TestBuilders/PaymentRequestBuilder.cs index 28aa87c3a5..cfdd71ca12 100644 --- a/src/SwedbankPay.Sdk.Tests/TestBuilders/PaymentRequestBuilder.cs +++ b/src/SwedbankPay.Sdk.Tests/TestBuilders/PaymentRequestBuilder.cs @@ -22,6 +22,7 @@ public class PaymentRequestBuilder private IPayeeInfo payeeInfo; private PrefillInfo prefillInfo; private TrustlyPrefillInfo trustlyPrefillInfo; + private bool generateRecurrenceToken; private bool generatePaymentToken; private Amount amount; private Amount vatAmount; @@ -30,9 +31,10 @@ public class PaymentRequestBuilder private Metadata metadata; private InvoiceType invoiceType; private Uri shopslogoUrl; + private string recurrenceToken; - public CardPaymentRequest BuildCreditardPaymentRequest() + public CardPaymentRequest BuildCreditCardPaymentRequest() { var req = new CardPaymentRequest(this.operation, this.intent, this.currency, this.description, this.userAgent, this.language, this.urls, this.payeeInfo); @@ -48,6 +50,35 @@ public CardPaymentRequest BuildCreditardPaymentRequest() return req; } + public CardPaymentVerifyRequest BuildCreditCardVerifyPaymentRequest() + { + var req = new CardPaymentVerifyRequest(this.intent, this.currency, this.description, this.userAgent, this.language, this.urls, this.payeeInfo) + { + Payment = + { + GenerateRecurrenceToken = this.generateRecurrenceToken, + GeneratePaymentToken = this.generatePaymentToken, + Metadata = this.metadata + } + }; + + return req; + } + + public CardPaymentRecurRequest BuildCreditCardRecurPaymentRequest() + { + var req = new CardPaymentRecurRequest(this.intent, this.recurrenceToken, this.currency, this.amount, this.vatAmount, this.description, this.userAgent, this.language, this.urls, this.payeeInfo) + { + Payment = + { + Metadata = this.metadata + } + }; + + return req; + } + + public SwishPaymentRequest BuildSwishPaymentRequest() { var req = new SwishPaymentRequest(this.prices, this.description, this.payerReference, this.userAgent, this.language, this.urls, this.payeeInfo, this.prefillInfo); @@ -87,7 +118,7 @@ public TrustlyPaymentRequest BuildTrustlyRequest() return req; } - public PaymentRequestBuilder WithCreditcardTestValues(string payeeId, Operation testOperation = null, PaymentIntent paymentIntent = PaymentIntent.Authorization) + public PaymentRequestBuilder WithCreditcardTestValues(string payeeId, Operation testOperation = null, PaymentIntent paymentIntent = PaymentIntent.Authorization, bool generateRecurrenceToken = false, string recurrenceToken = null) { this.operation = testOperation ?? Operation.Purchase; this.intent = paymentIntent; @@ -99,6 +130,8 @@ public PaymentRequestBuilder WithCreditcardTestValues(string payeeId, Operation SetUrls(); this.payeeInfo = new PayeeInfo(payeeId, DateTime.Now.Ticks.ToString()); this.generatePaymentToken = false; + this.generateRecurrenceToken = generateRecurrenceToken; + this.recurrenceToken = recurrenceToken; this.amount = new Amount(1600); this.vatAmount = new Amount(0); this.metadata = new Metadata { { "key1", "value1" }, { "key2", 2 }, { "key3", 3.1 }, { "key4", false } }; diff --git a/src/SwedbankPay.Sdk.Tests/UnitTests/DtoTests.cs b/src/SwedbankPay.Sdk.Tests/UnitTests/DtoTests.cs index 6ab857eed1..3958dcceca 100644 --- a/src/SwedbankPay.Sdk.Tests/UnitTests/DtoTests.cs +++ b/src/SwedbankPay.Sdk.Tests/UnitTests/DtoTests.cs @@ -69,7 +69,7 @@ public void ProblemResponse_IsCorrectlyMapped_ToProblemType() ""operations"": [] } ]}"; - var dto = JsonSerializer.Deserialize(problemResponse, JsonSerialization.JsonSerialization.Settings); + var dto = JsonSerializer.Deserialize(problemResponse, JsonSerialization.JsonSerialization.Settings); var result = dto.Map(); diff --git a/src/SwedbankPay.Sdk.Tests/UnitTests/HttpClientExtensionsTests.cs b/src/SwedbankPay.Sdk.Tests/UnitTests/HttpClientExtensionsTests.cs index e4c537dab2..a355c1594d 100644 --- a/src/SwedbankPay.Sdk.Tests/UnitTests/HttpClientExtensionsTests.cs +++ b/src/SwedbankPay.Sdk.Tests/UnitTests/HttpClientExtensionsTests.cs @@ -78,7 +78,7 @@ private static PaymentOrderCaptureRequest GetPaymentOrderCaptureRequest() public async Task ApiError_AreCorrectlySerialized_WithCorrectAmountOfDataAdded() { var client = new HttpClient(); - var paymentRequest = new PaymentRequestBuilder().WithCreditcardTestValues(this.payeeId, Operation.Verify).BuildCreditardPaymentRequest(); + var paymentRequest = new PaymentRequestBuilder().WithCreditcardTestValues(this.payeeId, Operation.Verify).BuildCreditCardPaymentRequest(); var uri = new Uri("https://api.externalintegration.payex.com/psp/paymentorders/2d35afaa-4e5a-4930-0de5-08d7da0988bc"); var error = await Assert.ThrowsAsync(() => client.SendAndProcessAsync(HttpMethod.Post, uri, paymentRequest)); diff --git a/src/SwedbankPay.Sdk/Operation.cs b/src/SwedbankPay.Sdk/Operation.cs index d281333b65..cf2f8378ce 100644 --- a/src/SwedbankPay.Sdk/Operation.cs +++ b/src/SwedbankPay.Sdk/Operation.cs @@ -28,7 +28,7 @@ public sealed class Operation : TypeSafeEnum /// /// The for Recur. /// - public static readonly Operation Recur = new Operation(nameof(Initiate), "Recur"); + public static readonly Operation Recur = new Operation(nameof(Recur), "Recur"); /// /// The for FinancingConsumer. diff --git a/src/SwedbankPay.Sdk/PaymentInstruments/Card/CardPaymentDetails.cs b/src/SwedbankPay.Sdk/PaymentInstruments/Card/CardPaymentDetails.cs index 8c9b60b309..78018cd364 100644 --- a/src/SwedbankPay.Sdk/PaymentInstruments/Card/CardPaymentDetails.cs +++ b/src/SwedbankPay.Sdk/PaymentInstruments/Card/CardPaymentDetails.cs @@ -78,7 +78,7 @@ public CardPaymentDetails(Operation operation, public PaymentIntent Intent { get; } /// - /// The payers prefered language. + /// The payers preferred language. /// public Language Language { get; } diff --git a/src/SwedbankPay.Sdk/PaymentInstruments/Card/CardPaymentRecurDetails.cs b/src/SwedbankPay.Sdk/PaymentInstruments/Card/CardPaymentRecurDetails.cs index e80eeebedc..3bcd550218 100644 --- a/src/SwedbankPay.Sdk/PaymentInstruments/Card/CardPaymentRecurDetails.cs +++ b/src/SwedbankPay.Sdk/PaymentInstruments/Card/CardPaymentRecurDetails.cs @@ -85,7 +85,7 @@ public CardPaymentRecurDetails(Operation operation, public string UserAgent { get; } /// - /// The payers prefered . + /// The payers preferred . /// public Language Language { get; } diff --git a/src/SwedbankPay.Sdk/PaymentInstruments/Card/CardPaymentVerifyRequest.cs b/src/SwedbankPay.Sdk/PaymentInstruments/Card/CardPaymentVerifyRequest.cs index ee3f0e0f3f..bb6f6a4940 100644 --- a/src/SwedbankPay.Sdk/PaymentInstruments/Card/CardPaymentVerifyRequest.cs +++ b/src/SwedbankPay.Sdk/PaymentInstruments/Card/CardPaymentVerifyRequest.cs @@ -12,7 +12,7 @@ public class CardPaymentVerifyRequest /// The wanted for the payment to be paid in. /// A textual description of the payment. /// The payers UserAgent. - /// The prefered of the payer. + /// The preferred of the payer. /// Object holding relevant for the payment. /// Object identifying the payee. public CardPaymentVerifyRequest(PaymentIntent intent, diff --git a/src/SwedbankPay.Sdk/PaymentInstruments/Card/CardPaymentVerifyRequestDetails.cs b/src/SwedbankPay.Sdk/PaymentInstruments/Card/CardPaymentVerifyRequestDetails.cs index 8ec225e772..b7649d1b47 100644 --- a/src/SwedbankPay.Sdk/PaymentInstruments/Card/CardPaymentVerifyRequestDetails.cs +++ b/src/SwedbankPay.Sdk/PaymentInstruments/Card/CardPaymentVerifyRequestDetails.cs @@ -27,12 +27,12 @@ public CardPaymentVerifyRequestDetails(PaymentIntent intent, Currency currency, } /// - /// The initial of the payment. + /// The initial of the payment. /// public Operation Operation { get; } = Operation.Verify; /// - /// The initial of the payment. + /// The initial of the payment. /// public PaymentIntent Intent { get; } @@ -42,20 +42,10 @@ public CardPaymentVerifyRequestDetails(PaymentIntent intent, Currency currency, public string RecurrenceToken { get; } /// - /// The to be paid. + /// The to be paid. /// public Currency Currency { get; } - /// - /// The to be paid. - /// - public Amount Amount { get; } - - /// - /// Any VAT to be paid. - /// - public Amount VatAmount { get; } - /// /// A textual description of the payment. /// @@ -67,7 +57,7 @@ public CardPaymentVerifyRequestDetails(PaymentIntent intent, Currency currency, public string UserAgent { get; } /// - /// The payers prefered . + /// The payers preferred . /// public Language Language { get; } @@ -81,6 +71,19 @@ public CardPaymentVerifyRequestDetails(PaymentIntent intent, Currency currency, /// public IPayeeInfo PayeeInfo { get; } + /// + /// When making the initial purchase request, you need to generate a paymentToken. + /// You can do this either by by setting the GeneratePaymentToken field to true, + /// or set the initial operation to Verify. + /// + public bool GeneratePaymentToken { get; set; } + + /// + /// Set this to true if you want to create a recurrenceToken for future use Recurring purchases (subscription + /// payments). + /// + public bool GenerateRecurrenceToken { get; set; } + /// /// Metadata can be used to store data associated to a payment that can be /// retrieved later by performing a GET on the payment. diff --git a/src/SwedbankPay.Sdk/PaymentInstruments/Card/ICardPaymentOperations.cs b/src/SwedbankPay.Sdk/PaymentInstruments/Card/ICardPaymentOperations.cs index 462b94e40b..3002d99c99 100644 --- a/src/SwedbankPay.Sdk/PaymentInstruments/Card/ICardPaymentOperations.cs +++ b/src/SwedbankPay.Sdk/PaymentInstruments/Card/ICardPaymentOperations.cs @@ -64,5 +64,10 @@ public interface ICardPaymentOperations : IDictionary HttpOperation ViewVerification { get; } + + /// + /// View the payment if available. + /// + HttpOperation ViewPayment { get; } } } \ No newline at end of file diff --git a/src/SwedbankPay.Sdk/PaymentInstruments/Card/ICardPaymentVerifyResponse.cs b/src/SwedbankPay.Sdk/PaymentInstruments/Card/ICardPaymentVerifyResponse.cs index e16e7afb47..4d56d9d9b8 100644 --- a/src/SwedbankPay.Sdk/PaymentInstruments/Card/ICardPaymentVerifyResponse.cs +++ b/src/SwedbankPay.Sdk/PaymentInstruments/Card/ICardPaymentVerifyResponse.cs @@ -8,6 +8,6 @@ public interface ICardPaymentVerifyResponse : IIdentifiable /// /// Available list of verifications. /// - ICardPaymentVerifyResponseDetails Verifications { get; } + IVerificationListResponse Verifications { get; } } } \ No newline at end of file diff --git a/src/SwedbankPay.Sdk/PaymentInstruments/Card/ICardResource.cs b/src/SwedbankPay.Sdk/PaymentInstruments/Card/ICardResource.cs index cffda39b58..4af7543c1a 100644 --- a/src/SwedbankPay.Sdk/PaymentInstruments/Card/ICardResource.cs +++ b/src/SwedbankPay.Sdk/PaymentInstruments/Card/ICardResource.cs @@ -4,7 +4,7 @@ namespace SwedbankPay.Sdk.PaymentInstruments.Card { /// - /// The entrypoint for talkig with the creditcard APIs. + /// The entry point for talking with the creditcard APIs. /// public interface ICardResource { @@ -39,6 +39,6 @@ public interface ICardResource /// /// /// - Task Create(CardPaymentVerifyRequest paymentRequest, PaymentExpand paymentExpand = PaymentExpand.All); + Task Create(CardPaymentVerifyRequest paymentRequest, PaymentExpand paymentExpand = PaymentExpand.All); } } diff --git a/src/SwedbankPay.Sdk/PaymentInstruments/Card/ICardPaymentVerifyResponseDetails.cs b/src/SwedbankPay.Sdk/PaymentInstruments/Card/IVerificationListResponse.cs similarity index 80% rename from src/SwedbankPay.Sdk/PaymentInstruments/Card/ICardPaymentVerifyResponseDetails.cs rename to src/SwedbankPay.Sdk/PaymentInstruments/Card/IVerificationListResponse.cs index a32f43c3f5..37b88a6419 100644 --- a/src/SwedbankPay.Sdk/PaymentInstruments/Card/ICardPaymentVerifyResponseDetails.cs +++ b/src/SwedbankPay.Sdk/PaymentInstruments/Card/IVerificationListResponse.cs @@ -1,15 +1,15 @@ -using System.Collections.Generic; - -namespace SwedbankPay.Sdk.PaymentInstruments.Card -{ - /// - /// Detailed information about verified card payments. - /// - public interface ICardPaymentVerifyResponseDetails: IIdentifiable - { - /// - /// List of available verifications. - /// - IList VerificationList { get; } - } +using System.Collections.Generic; + +namespace SwedbankPay.Sdk.PaymentInstruments.Card +{ + /// + /// Detailed information about verified card payments. + /// + public interface IVerificationListResponse: IIdentifiable + { + /// + /// List of available verifications. + /// + IList VerificationList { get; } + } } \ No newline at end of file diff --git a/src/SwedbankPay.Sdk/PaymentInstruments/PaymentExpand.cs b/src/SwedbankPay.Sdk/PaymentInstruments/PaymentExpand.cs index 8c538ac2c2..5f28f37aa8 100644 --- a/src/SwedbankPay.Sdk/PaymentInstruments/PaymentExpand.cs +++ b/src/SwedbankPay.Sdk/PaymentInstruments/PaymentExpand.cs @@ -53,8 +53,12 @@ public enum PaymentExpand /// Metadata = 512, /// + /// Expand the Verifications sub-resource. + /// + Verifications = 1024, + /// /// Expand all sub-resources. /// - All = 1023 + All = 2047 } } \ No newline at end of file diff --git a/src/SwedbankPay.Sdk/SwedbankPay.Sdk.xml b/src/SwedbankPay.Sdk/SwedbankPay.Sdk.xml index 8c378f3d14..54e55b560e 100644 --- a/src/SwedbankPay.Sdk/SwedbankPay.Sdk.xml +++ b/src/SwedbankPay.Sdk/SwedbankPay.Sdk.xml @@ -2431,7 +2431,7 @@ - The payers prefered language. + The payers preferred language. @@ -2549,7 +2549,7 @@ - The payers prefered . + The payers preferred . @@ -2692,7 +2692,7 @@ The wanted for the payment to be paid in. A textual description of the payment. The payers UserAgent. - The prefered of the payer. + The preferred of the payer. Object holding relevant for the payment. Object identifying the payee. @@ -2703,12 +2703,12 @@ - Object to hold details for verifying a card payment + Object to hold details for verifying a card payment - Instantiates a new Verify request for a card payment. + Instantiates a new Verify request for a card payment. @@ -2720,71 +2720,74 @@ - The initial of the payment. + The initial of the payment. - The initial of the payment. + The initial of the payment. - The provided reccurence token. + The provided reccurence token. - The to be paid. + The to be paid. - + - The to be paid. + A textual description of the payment. - + - Any VAT to be paid. + The payers user agent. - + - A textual description of the payment. + The payers preferred . - + - The payers user agent. + Urls relevant for the payment. - + - The payers prefered . + The merchant information. - + - Urls relevant for the payment. + When making the initial purchase request, you need to generate a paymentToken. + You can do this either by by setting the GeneratePaymentToken field to true, + or set the initial operation to Verify. - + - The merchant information. + Set this to true if you want to create a recurrenceToken for future use Recurring purchases (subscription + payments). - Metadata can be used to store data associated to a payment that can be - retrieved later by performing a GET on the payment. - Swedbank Pay does not use or process metadata, - it is only stored on the payment so it can be retrieved later alongside the payment. - An example where metadata might be useful is when several internal systems - are involved in the payment process and the payment creation is done in one system - and post-purchases take place in another. - In order to transmit data between these two internal systems, - the data can be stored in metadata on the payment so the internal - systems do not need to communicate with each other directly. + Metadata can be used to store data associated to a payment that can be + retrieved later by performing a GET on the payment. + Swedbank Pay does not use or process metadata, + it is only stored on the payment so it can be retrieved later alongside the payment. + An example where metadata might be useful is when several internal systems + are involved in the payment process and the payment creation is done in one system + and post-purchases take place in another. + In order to transmit data between these two internal systems, + the data can be stored in metadata on the payment so the internal + systems do not need to communicate with each other directly. @@ -2978,6 +2981,11 @@ View the verification if available. + + + View the payment if available. + + Transactional details about a response for a credit card @@ -3228,19 +3236,9 @@ Available list of verifications. - - - Detailed information about verified card payments. - - - - - List of available verifications. - - - The entrypoint for talkig with the creditcard APIs. + The entry point for talking with the creditcard APIs. @@ -3275,6 +3273,16 @@ + + + Detailed information about verified card payments. + + + + + List of available verifications. + + Transaction for a verified payment. @@ -5203,6 +5211,11 @@ Expand the MetaData sub-resource. + + + Expand the Verifications sub-resource. + + Expand all sub-resources.