Skip to content

Commit

Permalink
Merge pull request #7 from nozzlegear/ShopifyChargeService
Browse files Browse the repository at this point in the history
ShopifyChargeService: Create, get, list and activate one-time app charges.
  • Loading branch information
nozzlegear committed Sep 25, 2015
2 parents 118b3e1 + a8db1a3 commit 738ae5e
Show file tree
Hide file tree
Showing 23 changed files with 554 additions and 25 deletions.
2 changes: 1 addition & 1 deletion ShopifySharp.Tests/Playlists/Charges.playlist
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<Playlist Version="1.0"><Add Test="ShopifySharp.Tests.ShopifyBillingService_Tests.When_creating_a_charge_with_trial::should_create_a_charge_with_trial" /><Add Test="ShopifySharp.Tests.ShopifyBillingService_Tests.When_listing_charges::should_retrieve_a_charge" /><Add Test="ShopifySharp.Tests.ShopifyBillingService_Tests.When_activating_a_charge::should_activate_a_charge" /><Add Test="ShopifySharp.Tests.ShopifyBillingService_Tests.When_deleting_a_charge::should_delete_a_charge" /><Add Test="ShopifySharp.Tests.ShopifyBillingService_Tests.When_retrieving_a_charge::should_retrieve_a_charge" /><Add Test="ShopifySharp.Tests.ShopifyBillingService_Tests.When_creating_a_charge_with_no_trial::should_create_a_charge_with_no_trial" /><Add Test="ShopifySharp.Tests.ShopifyBillingService_Tests.When_listing_charges::should_retrieve_a_list_of_charges" /><Add Test="ShopifySharp.Tests.ShopifyBillingService_Tests.When_creating_a_charge::should_create_a_charge" /><Add Test="ShopifySharp.Tests.ShopifyRecurringChargeService_Tests.When_deleting_a_charge::should_delete_a_charge" /><Add Test="ShopifySharp.Tests.ShopifyRecurringChargeService_Tests.When_listing_charges::should_retrieve_a_list_of_charges" /><Add Test="ShopifySharp.Tests.ShopifyRecurringChargeService_Tests.When_creating_a_charge::should_create_a_charge" /><Add Test="ShopifySharp.Tests.ShopifyRecurringChargeService_Tests.When_retrieving_a_charge::should_retrieve_a_charge" /><Add Test="ShopifySharp.Tests.ShopifyRecurringChargeService_Tests.When_activating_a_charge::should_activate_a_charge" /></Playlist>
<Playlist Version="1.0"><Add Test="ShopifySharp.Tests.ShopifyChargeService_Tests.When_listing_charges::should_retrieve_a_list_of_charges" /><Add Test="ShopifySharp.Tests.ShopifyChargeService_Tests.When_activating_a_charge::should_activate_a_charge" /><Add Test="ShopifySharp.Tests.ShopifyChargeService_Tests.When_retrieving_a_charge::should_retrieve_a_charge" /><Add Test="ShopifySharp.Tests.ShopifyChargeService_Tests.When_creating_a_charge::should_create_a_charge" /></Playlist>
1 change: 1 addition & 0 deletions ShopifySharp.Tests/Playlists/RecurringCharges.playlist
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<Playlist Version="1.0"><Add Test="ShopifySharp.Tests.ShopifyBillingService_Tests.When_creating_a_charge_with_trial::should_create_a_charge_with_trial" /><Add Test="ShopifySharp.Tests.ShopifyBillingService_Tests.When_listing_charges::should_retrieve_a_charge" /><Add Test="ShopifySharp.Tests.ShopifyBillingService_Tests.When_activating_a_charge::should_activate_a_charge" /><Add Test="ShopifySharp.Tests.ShopifyBillingService_Tests.When_deleting_a_charge::should_delete_a_charge" /><Add Test="ShopifySharp.Tests.ShopifyBillingService_Tests.When_retrieving_a_charge::should_retrieve_a_charge" /><Add Test="ShopifySharp.Tests.ShopifyBillingService_Tests.When_creating_a_charge_with_no_trial::should_create_a_charge_with_no_trial" /><Add Test="ShopifySharp.Tests.ShopifyBillingService_Tests.When_listing_charges::should_retrieve_a_list_of_charges" /><Add Test="ShopifySharp.Tests.ShopifyBillingService_Tests.When_creating_a_charge::should_create_a_charge" /><Add Test="ShopifySharp.Tests.ShopifyRecurringChargeService_Tests.When_deleting_a_charge::should_delete_a_charge" /><Add Test="ShopifySharp.Tests.ShopifyRecurringChargeService_Tests.When_listing_charges::should_retrieve_a_list_of_charges" /><Add Test="ShopifySharp.Tests.ShopifyRecurringChargeService_Tests.When_creating_a_charge::should_create_a_charge" /><Add Test="ShopifySharp.Tests.ShopifyRecurringChargeService_Tests.When_retrieving_a_charge::should_retrieve_a_charge" /><Add Test="ShopifySharp.Tests.ShopifyRecurringChargeService_Tests.When_activating_a_charge::should_activate_a_charge" /><Add Test="ShopifySharp.Tests.ShopifyRecurringChargeService_Tests.When_activating_a_recurring_charge::should_activate_a_recurring_charge" /><Add Test="ShopifySharp.Tests.ShopifyRecurringChargeService_Tests.When_retrieving_a_recurring_charge::should_retrieve_a_recurring_charge" /><Add Test="ShopifySharp.Tests.ShopifyRecurringChargeService_Tests.When_deleting_a_recurring_charge::should_delete_a_recurring_charge" /><Add Test="ShopifySharp.Tests.ShopifyRecurringChargeService_Tests.When_listing_recurring_charges::should_retrieve_a_list_of_recurring_charges" /><Add Test="ShopifySharp.Tests.ShopifyRecurringChargeService_Tests.When_creating_a_recurring_charge::should_create_a_recurring_charge" /></Playlist>
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using Machine.Specifications;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ShopifySharp.Tests.ShopifyChargeService_Tests
{
[Subject(typeof(ShopifyChargeService))]
class When_activating_a_charge
{
Establish context = () =>
{
// NOTE: Creating a charge will fail if the access token used is for a private app.
// Only real apps can use the Shopify billing API.
Service = new ShopifyChargeService(Utils.BillingMyShopifyUrl, Utils.BillingAccessToken);
Charge = Service.CreateAsync(new ShopifyCharge()
{
Name = "Lorem Ipsum Single Charge",
Price = 123.45,
Test = true,
ReturnUrl = "http://localhost:5445/shopify/chargeresult/?attemptedChargeId=" + Guid.NewGuid().ToString()
}).Await().AsTask.Result;
};

Because of = () =>
{
Service.ActivateAsync(Charge.Id.Value).Await();
Charge = Service.GetAsync(Charge.Id.Value).Await().AsTask.Result;
};

It should_activate_a_charge = () =>
{
// NOTE: This test will require you to set a break point after creating the charge but before activating it,
// grab the confirmation url and manually accept it, then continue the test.
Charge.Status.ShouldEqual(Enums.ShopifyChargeStatus.Active);
};

Cleanup after = () =>
{
//Charges cannot be deleted.
};

static ShopifyChargeService Service;

static ShopifyCharge Charge;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using Machine.Specifications;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ShopifySharp.Tests.ShopifyChargeService_Tests
{
[Subject(typeof(ShopifyChargeService))]
class When_creating_a_charge
{
Establish context = () =>
{
Service = new ShopifyChargeService(Utils.BillingMyShopifyUrl, Utils.BillingAccessToken);
Charge = new ShopifyCharge()
{
Name = "Lorem Ipsum Single Charge",
Price = 123.45,
Test = true
};
};

Because of = () =>
{
// NOTE: Creating a charge will fail if the access token used is for a private app.
// Only real apps can use the Shopify billing API.
Charge = Service.CreateAsync(Charge).Await().AsTask.Result;
};

It should_create_a_charge = () =>
{
Charge.ConfirmationUrl.ShouldNotBeNull();
Charge.Price.ShouldEqual(123.45);
Charge.Test.ShouldBeTrue();
};

Cleanup after = () =>
{
//Charges cannot be deleted.
};

static ShopifyChargeService Service;

static ShopifyCharge Charge;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using Machine.Specifications;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ShopifySharp.Tests.ShopifyChargeService_Tests
{
[Subject(typeof(ShopifyChargeService))]
class When_listing_charges
{
Establish context = () =>
{
// NOTE: Creating a charge will fail if the access token used is for a private app.
// Only real apps can use the Shopify billing API.
Service = new ShopifyChargeService(Utils.BillingMyShopifyUrl, Utils.BillingAccessToken);
ChargeId = Service.CreateAsync(new ShopifyCharge()
{
Name = "Lorem Ipsum Single Charge",
Price = 123.45,
Test = true,
}).Await().AsTask.Result.Id.Value;
};

Because of = () =>
{
Charges = Service.ListAsync().Await().AsTask.Result;
};

It should_retrieve_a_list_of_charges = () =>
{
Charges.ShouldNotBeNull();
Charges.Count().ShouldBeGreaterThanOrEqualTo(1);
};

Cleanup after = () =>
{
//Charges cannot be deleted.
};

static ShopifyChargeService Service;

static IEnumerable<ShopifyCharge> Charges;

static long ChargeId;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using Machine.Specifications;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ShopifySharp.Tests.ShopifyChargeService_Tests
{
[Subject(typeof(ShopifyChargeService))]
class When_retrieving_a_charge
{
Establish context = () =>
{
// NOTE: Creating a charge will fail if the access token used is for a private app.
// Only real apps can use the Shopify billing API.
Service = new ShopifyChargeService(Utils.BillingMyShopifyUrl, Utils.BillingAccessToken);
ChargeId = Service.CreateAsync(new ShopifyCharge()
{
Name = "Lorem Ipsum Single Charge",
Price = 123.45,
Test = true,
}).Await().AsTask.Result.Id.Value;
};

Because of = () =>
{
Charge = Service.GetAsync(ChargeId).Await().AsTask.Result;
};

It should_retrieve_a_charge = () =>
{
Charge.ShouldNotBeNull();
};

Cleanup after = () =>
{
//Charges cannot be deleted.
};

static ShopifyChargeService Service;

static ShopifyCharge Charge;

static long ChargeId;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
namespace ShopifySharp.Tests.ShopifyRecurringChargeService_Tests
{
[Subject(typeof(ShopifyRecurringChargeService))]
class When_activating_a_charge
class When_activating_a_recurring_charge
{
Establish context = () =>
{
Expand All @@ -22,6 +22,7 @@ class When_activating_a_charge
Price = 123.45,
Test = true,
TrialDays = 21,
ReturnUrl = "http://localhost:5445/shopify/chargeresult/?attemptedChargeId=" + Guid.NewGuid().ToString()
}).Await().AsTask.Result;
};

Expand All @@ -31,7 +32,7 @@ class When_activating_a_charge
Charge = Service.GetAsync(Charge.Id.Value).Await().AsTask.Result;
};

It should_activate_a_charge = () =>
It should_activate_a_recurring_charge = () =>
{
// NOTE: This test will require you to set a break point after creating the charge but before activating it,
// grab the confirmation url and manually accept it, then continue the test.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
namespace ShopifySharp.Tests.ShopifyRecurringChargeService_Tests
{
[Subject(typeof(ShopifyRecurringChargeService))]
class When_creating_a_charge
class When_creating_a_recurring_charge
{
Establish context = () =>
{
Expand All @@ -30,7 +30,7 @@ class When_creating_a_charge
Charge = Service.CreateAsync(Charge).Await().AsTask.Result;
};

It should_create_a_charge = () =>
It should_create_a_recurring_charge = () =>
{
Charge.ConfirmationUrl.ShouldNotBeNull();
Charge.Price.ShouldEqual(123.45);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
namespace ShopifySharp.Tests.ShopifyRecurringChargeService_Tests
{
[Subject(typeof(ShopifyRecurringChargeService))]
class When_deleting_a_charge
class When_deleting_a_recurring_charge
{
Establish context = () =>
{
Expand Down Expand Up @@ -37,7 +37,7 @@ class When_deleting_a_charge
}
};

It should_delete_a_charge = () =>
It should_delete_a_recurring_charge = () =>
{
// A charge cannot be deleted unless it has been activated. This test will fail unless you manually
// accept the charge, then activate it, then let the test delete it.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
namespace ShopifySharp.Tests.ShopifyRecurringChargeService_Tests
{
[Subject(typeof(ShopifyRecurringChargeService))]
class When_listing_charges
class When_listing_recurring_charges
{
Establish context = () =>
{
Expand All @@ -29,7 +29,7 @@ class When_listing_charges
Charges = Service.ListAsync().Await().AsTask.Result;
};

It should_retrieve_a_list_of_charges = () =>
It should_retrieve_a_list_of_recurring_charges = () =>
{
Charges.ShouldNotBeNull();
Charges.Count().ShouldBeGreaterThanOrEqualTo(1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
namespace ShopifySharp.Tests.ShopifyRecurringChargeService_Tests
{
[Subject(typeof(ShopifyRecurringChargeService))]
class When_retrieving_a_charge
class When_retrieving_a_recurring_charge
{
Establish context = () =>
{
Expand All @@ -29,7 +29,7 @@ class When_retrieving_a_charge
Charge = Service.GetAsync(ChargeId).Await().AsTask.Result;
};

It should_retrieve_a_charge = () =>
It should_retrieve_a_recurring_charge = () =>
{
Charge.ShouldNotBeNull();
};
Expand Down
14 changes: 9 additions & 5 deletions ShopifySharp.Tests/ShopifySharp.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,15 @@
<Compile Include="FalseToNullConverter Tests\When_serialzing_false.cs" />
<Compile Include="GlobalSuppressions.cs" />
<Compile Include="ShopifyAuthorizationService Tests\When_building_an_authorization_url.cs" />
<Compile Include="ShopifyRecurringChargeService Tests\When_activating_a_charge.cs" />
<Compile Include="ShopifyRecurringChargeService Tests\When_creating_a_charge.cs" />
<Compile Include="ShopifyRecurringChargeService Tests\When_deleting_a_charge.cs" />
<Compile Include="ShopifyRecurringChargeService Tests\When_listing_charges.cs" />
<Compile Include="ShopifyRecurringChargeService Tests\When_retrieving_a_charge.cs" />
<Compile Include="ShopifyChargeService Tests\When_activating_a_charge.cs" />
<Compile Include="ShopifyChargeService Tests\When_creating_a_charge.cs" />
<Compile Include="ShopifyChargeService Tests\When_listing_charges.cs" />
<Compile Include="ShopifyChargeService Tests\When_retrieving_a_charge.cs" />
<Compile Include="ShopifyRecurringChargeService Tests\When_activating_a_recurring_charge.cs" />
<Compile Include="ShopifyRecurringChargeService Tests\When_creating_a_recurring_charge.cs" />
<Compile Include="ShopifyRecurringChargeService Tests\When_deleting_a_recurring_charge.cs" />
<Compile Include="ShopifyRecurringChargeService Tests\When_listing_recurring_charges.cs" />
<Compile Include="ShopifyRecurringChargeService Tests\When_retrieving_a_recurring_charge.cs" />
<Compile Include="ShopifyCustomerService Tests\Test_Data\CustomerCreation.cs" />
<Compile Include="ShopifyCustomerService Tests\When_counting_customers.cs" />
<Compile Include="ShopifyCustomerService Tests\When_creating_a_customer.cs" />
Expand Down
44 changes: 44 additions & 0 deletions ShopifySharp/Converters/ShopifyChargeConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using Newtonsoft.Json.Converters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using ShopifySharp.Enums;

namespace ShopifySharp.Converters
{
/// <summary>
/// A custom enum converter for <see cref="ShopifyChargeStatus"/> enums which sets the default value
/// to <see cref="ShopifyChargeStatus.Unknown"/> when the value is null or does not exist.
/// </summary>
public class ShopifyChargeConverter : StringEnumConverter
{
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
ShopifyChargeStatus parsed;

if (!Enum.TryParse(reader.Value?.ToString() ?? "", true, out parsed))
{
return ShopifyChargeStatus.Unknown;
}

return parsed;
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
if (value == null ||
!Enum.IsDefined(typeof(ShopifyChargeStatus), value) ||
(Enum.IsDefined(typeof(ShopifyChargeStatus), value) && ((ShopifyChargeStatus)value) == ShopifyChargeStatus.Unknown))
{
writer.WriteNull();
}
else
{
base.WriteJson(writer, value, serializer);
}
}
}
}
10 changes: 8 additions & 2 deletions ShopifySharp/Converters/ShopifyRecurringChargeConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

namespace ShopifySharp.Converters
{
// TODO: Merge this converter with ShopifyChargeConverter in v2.0

/// <summary>
/// A custom enum converter for <see cref="ShopifyRecurringChargeStatus"/> enums which sets the default value
/// to <see cref="ShopifyRecurringChargeStatus.Unknown"/> when the value is null or does not exist.
Expand All @@ -17,10 +19,14 @@ public class ShopifyRecurringChargeConverter : StringEnumConverter
{
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (string.IsNullOrEmpty(reader.Value?.ToString()))
ShopifyRecurringChargeStatus parsed;

if (!Enum.TryParse(reader.Value?.ToString() ?? "", true, out parsed))
{
return ShopifyRecurringChargeStatus.Unknown;
}

return base.ReadJson(reader, objectType, existingValue, serializer);
return parsed;
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
Expand Down
Loading

0 comments on commit 738ae5e

Please sign in to comment.