Skip to content

Commit

Permalink
Add support for the Wallet API (#327)
Browse files Browse the repository at this point in the history
* #326 Implement wallet client

* #326 Create a custom json converter so the epoch and expires at are returned as a datetime instead of a long

* #326 Update version

* Add documentation on Wallet Client

* #326 Add language to Wallet API example
  • Loading branch information
Viincenttt authored Sep 22, 2023
1 parent e5d86f7 commit b1a98be
Show file tree
Hide file tree
Showing 9 changed files with 146 additions and 6 deletions.
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Have you spotted a bug or want to add a missing feature? All pull requests are w
[15. Balances Api](#15-balances-api)
[16. Terminal Api](#16-terminal-api)
[17. Client Link Api](#17-client-link-api)
[18. Wallet Api](#18-wallet-api)

## 1. Getting started

Expand Down Expand Up @@ -76,6 +77,7 @@ This library currently supports the following API's:
- Balances API
- Terminal API
- ClientLink API
- Wallet API

### Supported .NET versions
This library is built using .NET standard 2.0. This means that the package supports the following .NET implementations:
Expand Down Expand Up @@ -1037,3 +1039,14 @@ var clientLinkUrl = response.Links.ClientLink;
string result = clientLinkClient.GenerateClientLinkWithParameters(clientLinkUrl, {yourState}, {yourScope}, {forceApprovalPrompt});
```

## 18. Wallet Api
## Request Apple Pay Payment Session
For integrating Apple Pay in your own checkout on the web, you need to provide merchant validation. For more information on this topic, read the [Mollie documentation on Apple Pay Payment sessions](https://docs.mollie.com/reference/v2/wallets-api/request-apple-pay-payment-session).
```C#
var request = new ApplePayPaymentSessionRequest() {
Domain = "pay.mywebshop.com",
ValidationUrl = "https://apple-pay-gateway-cert.apple.com/paymentservices/paymentSession"
};
using var walletClient = new WalletClient({yourApiClient});
ApplePayPaymentSessionResponse response = await walletClient.RequestApplePayPaymentSessionAsync(request);
```
9 changes: 9 additions & 0 deletions src/Mollie.Api/Client/Abstract/IWalletClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System.Threading.Tasks;
using Mollie.Api.Models.Wallet.Request;
using Mollie.Api.Models.Wallet.Response;

namespace Mollie.Api.Client.Abstract {
public interface IWalletClient {
Task<ApplePayPaymentSessionResponse> RequestApplePayPaymentSessionAsync(ApplePayPaymentSessionRequest request);
}
}
16 changes: 16 additions & 0 deletions src/Mollie.Api/Client/WalletClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System.Net.Http;
using System.Threading.Tasks;
using Mollie.Api.Client.Abstract;
using Mollie.Api.Models.Wallet.Request;
using Mollie.Api.Models.Wallet.Response;

namespace Mollie.Api.Client {
public class WalletClient : BaseMollieClient, IWalletClient {
public WalletClient(string apiKey, HttpClient httpClient = null) : base(apiKey, httpClient) {
}

public async Task<ApplePayPaymentSessionResponse> RequestApplePayPaymentSessionAsync(ApplePayPaymentSessionRequest request) {
return await this.PostAsync<ApplePayPaymentSessionResponse>("wallets/applepay/sessions", request).ConfigureAwait(false);
}
}
}
2 changes: 2 additions & 0 deletions src/Mollie.Api/DependencyInjection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ public static IServiceCollection AddMollieApi(
new TerminalClient(mollieOptions.ApiKey, httpClient), retryPolicy);
RegisterMollieApiClient<IClientLinkClient, ClientLinkClient>(services, httpClient =>
new ClientLinkClient(mollieOptions.ClientId, mollieOptions.ApiKey, httpClient), retryPolicy);
RegisterMollieApiClient<IWalletClient, WalletClient>(services, httpClient =>
new WalletClient(mollieOptions.ApiKey, httpClient), retryPolicy);

return services;
}
Expand Down
18 changes: 18 additions & 0 deletions src/Mollie.Api/JsonConverters/MicrosecondEpochConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

namespace Mollie.Api.JsonConverters {
public class MicrosecondEpochConverter : DateTimeConverterBase
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {
var longValue = long.Parse(reader.Value.ToString());
return DateTimeOffset.FromUnixTimeMilliseconds(longValue).UtcDateTime;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace Mollie.Api.Models.Wallet.Request {
public class ApplePayPaymentSessionRequest {
/// <summary>
/// The validationUrl you got from the ApplePayValidateMerchant event.
/// A list of all valid host names for merchant validation is available. You should white list these in your
/// application and reject any validationUrl that have a host name not in the list.
/// </summary>
public string ValidationUrl { get; set; }

/// <summary>
/// The domain of your web shop, that is visible in the browser’s location bar. For example pay.myshop.com.
/// </summary>
public string Domain { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System;
using Mollie.Api.JsonConverters;
using Newtonsoft.Json;

namespace Mollie.Api.Models.Wallet.Response {
public class ApplePayPaymentSessionResponse {
[JsonConverter(typeof(MicrosecondEpochConverter))]
public DateTime EpochTimestamp { get; set; }
[JsonConverter(typeof(MicrosecondEpochConverter))]
public DateTime ExpiresAt { get; set; }
public string MerchantSessionIdentifier { get; set; }
public string Nonce { get; set; }
public string MerchantIdentifier { get; set; }
public string DomainName { get; set; }
public string DisplayName { get; set; }
public string Signature { get; set; }
}
}
12 changes: 6 additions & 6 deletions src/Mollie.Api/Mollie.Api.csproj
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<Version>3.2.0.0</Version>
<Version>3.3.0.0</Version>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<Authors>Vincent Kok</Authors>
<Description>This is a wrapper for the Mollie REST webservice. All payment methods and webservice calls are supported.</Description>
<Company>Vincent Kok</Company>
<Product>Mollie Payment API</Product>
<PackageProjectUrl>https://github.com/Viincenttt/MollieApi</PackageProjectUrl>
<PackageTags>Mollie</PackageTags>
<AssemblyVersion>3.2.0.0</AssemblyVersion>
<FileVersion>3.2.0.0</FileVersion>
<PackageVersion>3.2.0.0</PackageVersion>
<AssemblyVersion>3.3.0.0</AssemblyVersion>
<FileVersion>3.3.0.0</FileVersion>
<PackageVersion>3.3.0.0</PackageVersion>
<TargetFramework>netstandard2.0</TargetFramework>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
Expand All @@ -25,8 +25,8 @@
</ItemGroup>

<ItemGroup>
<None Include="..\..\README.md" Pack="true" PackagePath="\"/>
<None Include="..\..\LICENSE" Pack="true" PackagePath="\"/>
<None Include="..\..\README.md" Pack="true" PackagePath="\" />
<None Include="..\..\LICENSE" Pack="true" PackagePath="\" />
</ItemGroup>

</Project>
49 changes: 49 additions & 0 deletions tests/Mollie.Tests.Unit/Client/WalletClientTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using System;
using System.Net.Http;
using System.Threading.Tasks;
using FluentAssertions;
using Mollie.Api.Client;
using Mollie.Api.Models.Wallet.Request;
using Xunit;

namespace Mollie.Tests.Unit.Client;

public class WalletClientTest : BaseClientTests {
private const string defaultApplePayPaymentSessionResponse = @"{
""epochTimestamp"": 1555507053169,
""expiresAt"": 1555510653169,
""merchantSessionIdentifier"": ""SSH2EAF8AFAEAA94DEEA898162A5DAFD36E_916523AAED1343F5BC5815E12BEE9250AFFDC1A17C46B0DE5A943F0F94927C24"",
""nonce"": ""0206b8db"",
""merchantIdentifier"": ""BD62FEB196874511C22DB28A9E14A89E3534C93194F73EA417EC566368D391EB"",
""domainName"": ""pay.example.org"",
""displayName"": ""Chuck Norris's Store"",
""signature"": ""308006092a864886f7...8cc030ad3000000000000""
}";

[Fact]
public async Task RequestApplePayPaymentSessionAsync_ResponseIsDeserializedInExpectedFormat() {
// Arrange
var request = new ApplePayPaymentSessionRequest() {
Domain = "pay.mywebshop.com",
ValidationUrl = "https://apple-pay-gateway-cert.apple.com/paymentservices/paymentSession"
};
var mockHttp = this.CreateMockHttpMessageHandler(
HttpMethod.Post,
$"{BaseMollieClient.ApiEndPoint}wallets/applepay/sessions",
defaultApplePayPaymentSessionResponse);
using var walletClient = new WalletClient("abcde", mockHttp.ToHttpClient());

// Act
var response = await walletClient.RequestApplePayPaymentSessionAsync(request);

// Assert
response.EpochTimestamp.Should().Be(DateTimeOffset.FromUnixTimeMilliseconds(1555507053169).UtcDateTime);
response.ExpiresAt.Should().Be(DateTimeOffset.FromUnixTimeMilliseconds(1555510653169).UtcDateTime);
response.MerchantSessionIdentifier.Should().Be("SSH2EAF8AFAEAA94DEEA898162A5DAFD36E_916523AAED1343F5BC5815E12BEE9250AFFDC1A17C46B0DE5A943F0F94927C24");
response.Nonce.Should().Be("0206b8db");
response.MerchantIdentifier.Should().Be("BD62FEB196874511C22DB28A9E14A89E3534C93194F73EA417EC566368D391EB");
response.DomainName.Should().Be("pay.example.org");
response.DisplayName.Should().Be("Chuck Norris's Store");
response.Signature.Should().Be("308006092a864886f7...8cc030ad3000000000000");
}
}

0 comments on commit b1a98be

Please sign in to comment.