Skip to content

Commit

Permalink
Add subscription preview #61
Browse files Browse the repository at this point in the history
  • Loading branch information
kfrancis committed Mar 28, 2018
1 parent 33e21b8 commit 5f2fb1b
Show file tree
Hide file tree
Showing 6 changed files with 404 additions and 5 deletions.
34 changes: 34 additions & 0 deletions Source/ChargifyDotNet.Tests/SubscriptionPreviewTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using System;
using ChargifyNET;
using ChargifyDotNetTests.Base;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace ChargifyDotNetTests
{
[TestClass]
public class SubscriptionPreviewTests : ChargifyTestBase
{
[TestMethod]
public void SubscriptionPreview_CanCreate()
{
// Arrange
var subscription = Chargify.GetSubscriptionList().FirstOrDefault(s => s.Value.State == SubscriptionState.Active).Value as Subscription;
Assert.IsNotNull(subscription, "No suitable subscription could be found.");
var options = new SubscriptionCreateOptions()
{
ProductHandle = subscription.Product.Handle,
CustomerAttributes = subscription.Customer.ToCustomerAttributes() as CustomerAttributes,
CreditCardAttributes = new CreditCardAttributes() { FullNumber = "1", ExpirationMonth = 1, ExpirationYear = DateTime.Now.Year+1 }
};

// Act
var result = Chargify.CreateSubscriptionPreview(options);

// Assert
Assert.IsNotNull(result);
Assert.IsInstanceOfType(result, typeof(ISubscriptionPreview));
Assert.AreEqual(1, result.SubscriptionPreviewResult.CurrentBillingManifest.LineItems.Count);
}
}
}
84 changes: 83 additions & 1 deletion Source/ChargifyDotNet/ChargifyConnect.cs
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,32 @@ public HttpWebResponse LastResponse

#endregion

#region Metafield
/// <summary>
/// Returns a list of all metadata for a resource.
/// </summary>
/// <typeparam name="T">The type of resource. Currently either Subscription or Customer</typeparam>
/// <returns>The metadata result containing the response</returns>
public IMetafield GetMetafields<T>() where T : ChargifyBase
{
string response;
switch (typeof(T).Name.ToLowerInvariant())
{
case "customer":
response = DoRequest(string.Format("customers/metafields.{0}", GetMethodExtension()), HttpRequestMethod.Get, null);
break;
case "subscription":
response = DoRequest(string.Format("subscriptions/metafields.{0}", GetMethodExtension()), HttpRequestMethod.Get, null);
break;
default:
throw new Exception(string.Format("Must be of type '{0}'", string.Join(", ", _metafieldTypes.ToArray())));
}
// change the response to the object
return response.ConvertResponseTo<Metafield>("metafield");
}
private static List<string> _metafieldTypes = new List<string> { "Customer", "Subscription" };
#endregion

#region Metadata
/// <summary>
/// Allows you to set a group of metadata for a specific resource
Expand Down Expand Up @@ -1989,7 +2015,8 @@ private ISubscription CreateSubscription(string productHandle, string newSystemI
/// <param name="couponCode">The coupon to use</param>
/// <param name="componentsWithQuantity">Components to set on the subscription initially</param>
/// <returns>Details about the subscription</returns>
public ISubscription CreateSubscriptionUsingCoupon(string productHandle, ICustomerAttributes customerAttributes, ICreditCardAttributes creditCardAttributes, string couponCode, Dictionary<int, string> componentsWithQuantity)
public ISubscription CreateSubscriptionUsingCoupon
(string productHandle, ICustomerAttributes customerAttributes, ICreditCardAttributes creditCardAttributes, string couponCode, Dictionary<int, string> componentsWithQuantity)
{
// make sure data is valid
if (creditCardAttributes == null) throw new ArgumentNullException("creditCardAttributes");
Expand Down Expand Up @@ -3392,6 +3419,61 @@ public ISubscription ResumeSubscription(int subscriptionId)
}
}

/// <summary>
/// Return a preview of charges for a subscription creation
/// </summary>
/// <param name="options"></param>
/// <returns></returns>
public ISubscriptionPreview CreateSubscriptionPreview(ISubscriptionCreateOptions options)
{
if (options == null) throw new ArgumentNullException(nameof(options));

// Customer
bool customerSpecifiedAlready = options.CustomerID.HasValue;

if (!string.IsNullOrEmpty(options.CustomerReference))
{
if (customerSpecifiedAlready) { throw new ArgumentException("Customer information should only be specified once", nameof(options)); }
customerSpecifiedAlready = true;
}
if (options.CustomerAttributes != null)
{
if (customerSpecifiedAlready) throw new ArgumentException("Customer information should only be specified once", nameof(options));
customerSpecifiedAlready = true;
}
if (!customerSpecifiedAlready) { throw new ArgumentException("No customer information was specified. Please specify either the CustomerID, CustomerReference or CustomerAttributes and try again.", "options"); }

// Product
bool productSpecifiedAlready = options.ProductID.HasValue;
if (!string.IsNullOrEmpty(options.ProductHandle))
{
if (productSpecifiedAlready) { throw new ArgumentException("Product information should only be specified once", nameof(options)); }
productSpecifiedAlready = true;
}
if (!productSpecifiedAlready) { throw new ArgumentException("No product information was specified. Please specify either the ProductID or ProductHandle and try again.", "options"); }

var subscriptionXml = new StringBuilder();
var serializer = new System.Xml.Serialization.XmlSerializer(options.GetType());
using (StringWriter textWriter = new Utf8StringWriter())
{
serializer.Serialize(textWriter, options);
subscriptionXml.Append(textWriter);
}

try
{
// now make the request
string response = DoRequest(string.Format("subscriptions/preview.{0}", GetMethodExtension()), HttpRequestMethod.Post, subscriptionXml.ToString());
// change the response to the object
return response.ConvertResponseTo<SubscriptionPreview>("subscription_preview");
}
catch (ChargifyException cex)
{
if (cex.StatusCode == HttpStatusCode.NotFound) throw new InvalidOperationException("Migration not found");
throw;
}
}

#endregion

#region Subscription Override
Expand Down
8 changes: 4 additions & 4 deletions Source/ChargifyDotNet/ChargifyDotNet.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@
<Company>Clinical Support Systems</Company>
<Product>Chargify.NET</Product>
<Description>Chargify.NET is a comprehensive .NET API wrapper library for accessing Chargify.com, using XML or JSON to read/write.</Description>
<AssemblyVersion>1.2.3</AssemblyVersion>
<FileVersion>1.2.3</FileVersion>
<VersionPrefix>1.2.1</VersionPrefix>
<AssemblyVersion>1.2.5</AssemblyVersion>
<FileVersion>1.2.5</FileVersion>
<VersionPrefix>1.2.5</VersionPrefix>
<!--<VersionSuffix>beta1</VersionSuffix>-->
<IncludeSource>true</IncludeSource>
<IncludeSymbols>true</IncludeSymbols>
<Version>1.2.3</Version>
<Version>1.2.5</Version>
</PropertyGroup>

<ItemGroup>
Expand Down
7 changes: 7 additions & 0 deletions Source/ChargifyDotNet/Interfaces/IChargifyConnect.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1187,6 +1187,13 @@ public interface IChargifyConnect
/// <returns>The subscription data, if successful</returns>
/// <remarks>https://reference.chargify.com/v1/subscriptions/hold-subscription</remarks>
ISubscription PauseSubscription(int subscriptionId, DateTime? automaticResumeDate = null);

/// <summary>
/// Return a preview of charges for a subscription creation
/// </summary>
/// <param name="options"></param>
/// <returns></returns>
ISubscriptionPreview CreateSubscriptionPreview(ISubscriptionCreateOptions options);
#endregion

#region Transactions
Expand Down
85 changes: 85 additions & 0 deletions Source/ChargifyDotNet/Interfaces/ISubscriptionPreview.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@

#region License, Terms and Conditions
//
// ISubscriptionPreview.cs
//
// Authors: Kori Francis <twitter.com/djbyter>, David Ball
// Copyright (C) 2010 Clinical Support Systems, Inc. All rights reserved.
//
// THIS FILE IS LICENSED UNDER THE MIT LICENSE AS OUTLINED IMMEDIATELY BELOW:
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#endregion

namespace ChargifyNET
{
#region Imports
using System;
using System.Collections.Generic;
#endregion

public interface ISubscriptionPreview
{
SubscriptionPreviewResult SubscriptionPreviewResult { get; set; }
}

public interface ISubscriptionPreviewResult
{
SubscriptionPreviewBillingManifest CurrentBillingManifest { get; set; }

SubscriptionPreviewBillingManifest NextBillingManifest { get; set; }
}

public interface ISubscriptionPreviewBillingManifest
{
List<SubscriptionPreviewLineItem> LineItems { get; set; }

long TotalInCents { get; set; }

long TotalDiscountInCents { get; set; }

long TotalTaxInCents { get; set; }

long SubtotalInCents { get; set; }

DateTime StartDate { get; set; }

DateTime EndDate { get; set; }

string PeriodType { get; set; }

long ExistingBalanceInCents { get; set; }
}

public interface ISubscriptionPreviewLineItem
{
string TransactionType { get; set; }

string Kind { get; set; }

long AmountInCents { get; set; }

string Memo { get; set; }

long DiscountAmountInCents { get; set; }

long TaxableAmountInCents { get; set; }
}
}
Loading

0 comments on commit 5f2fb1b

Please sign in to comment.