Skip to content

Commit

Permalink
Usage Based Billing
Browse files Browse the repository at this point in the history
  • Loading branch information
bhelx committed Jun 6, 2016
1 parent a9a2f5a commit 5a7ec34
Show file tree
Hide file tree
Showing 23 changed files with 341 additions and 13 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

* Added support for parsing `fraud` attribute on the `Transaction` class [#228](https://github.com/recurly/recurly-client-php/pull/228)
* Added support for setting`start_date` and `end_date` when creating an `Adjustment` (thanks to [imsagar](https://github.com/imsagar)) [#229](https://github.com/recurly/recurly-client-php/pull/229)
* Added support for Usage Based Billing [#227](https://github.com/recurly/recurly-client-php/pull/227)

## Version 2.5.1 (February 19th, 2016)

Expand Down
2 changes: 1 addition & 1 deletion Tests/Recurly/Addon_Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ public function testDelete() {
$this->assertInstanceOf('Recurly_Addon', $addon);
$addon->delete();
}
}
}
15 changes: 15 additions & 0 deletions Tests/Recurly/MeasuredUnit_List_Test.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

require_once(__DIR__ . '/../test_helpers.php');

class Recurly_MeasuredUnitListTest extends Recurly_TestCase
{
public function testGetMeasuredUnits() {
$this->client->addResponse('GET', '/measured_units', 'measured_units/index-200.xml');

$measured_units = Recurly_MeasuredUnitList::get(null, $this->client);

$this->assertInstanceOf('Recurly_MeasuredUnitList', $measured_units);
$this->assertEquals(2, $measured_units->count());
}
}
33 changes: 33 additions & 0 deletions Tests/Recurly/MeasuredUnit_Test.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

require_once(__DIR__ . '/../test_helpers.php');

class Recurly_MeasuredUnitTest extends Recurly_TestCase
{
public function testGetMeasuredUnit() {
$this->client->addResponse('GET', '/measured_units/123456', 'measured_units/show-200.xml');

$measured_unit = Recurly_MeasuredUnit::get(123456, $this->client);

$this->assertInstanceOf('Recurly_MeasuredUnit', $measured_unit);
$this->assertEquals(123456, $measured_unit->id);
$this->assertEquals('Marketing Emails', $measured_unit->name);
$this->assertEquals('Email', $measured_unit->display_name);
$this->assertEquals('A Marketing Email', $measured_unit->description);
}

public function testCreateMeasuredUnit() {
$this->client->addResponse('POST', '/measured_units', 'measured_units/create-201.xml');

$measured_unit = new Recurly_MeasuredUnit(null, $this->client);

$measured_unit->name = 'Marketing Emails';
$measured_unit->display_name = 'Emails';
$measured_unit->description = 'A Marketing Email';

$measured_unit->create();

$this->assertInstanceOf('Recurly_MeasuredUnit', $measured_unit);
$this->assertEquals(123456, $measured_unit->id);
}
}
10 changes: 6 additions & 4 deletions Tests/Recurly/Subscription_Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@ public function testGetSubscription() {

$add_on = $subscription->subscription_add_ons[0];
$this->assertInstanceOf('Recurly_SubscriptionAddOn', $add_on);
$this->assertEquals('IP Addresses', $add_on->name);
$this->assertEquals('ipaddresses', $add_on->add_on_code);
$this->assertEquals(200, $add_on->unit_amount_in_cents);
$this->assertEquals(2, $add_on->quantity);
$this->assertEquals('Marketing Emails', $add_on->name);
$this->assertEquals('marketing_emails', $add_on->add_on_code);
$this->assertEquals(5, $add_on->unit_amount_in_cents);
$this->assertEquals(1, $add_on->quantity);
$this->assertEquals('price', $add_on->usage_type);
$this->assertEquals('usage', $add_on->add_on_type);
$this->assertEquals('manual', $subscription->collection_method);
$this->assertEquals('1000', $subscription->po_number);
$this->assertEquals(10, $subscription->net_terms);
Expand Down
44 changes: 44 additions & 0 deletions Tests/Recurly/Usage_Test.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

require_once(__DIR__ . '/../test_helpers.php');

class Recurly_UsageTest extends Recurly_TestCase
{
public function testGetUsage() {
$this->client->addResponse('GET', '/subscriptions/012345678901234567890123456789ab/add_ons/marketing_emails/usage/123456', 'usage/show-200.xml');

$usage = Recurly_Usage::get('012345678901234567890123456789ab', 'marketing_emails', 123456, $this->client);

$this->assertInstanceOf('Recurly_Usage', $usage);
$this->assertInstanceOf('Recurly_Stub', $usage->measured_unit);
$this->assertEquals(6, $usage->amount);
$this->assertEquals('Order Number: #198349243975', $usage->merchant_tag);
$this->assertEquals('PERCENTAGE', $usage->usage_type);
$this->assertEquals(1.25, $usage->usage_percentage);
}

public function testCreateUsage() {
$this->client->addResponse('POST', '/subscriptions/012345678901234567890123456789ab/add_ons/marketing_emails/usage', 'usage/create-201.xml');

$usage = Recurly_Usage::build('012345678901234567890123456789ab', 'marketing_emails', $this->client);

$usage->create();

$this->assertInstanceOf('Recurly_Usage', $usage);
$this->assertInstanceOf('Recurly_Stub', $usage->measured_unit);
}

public function testCreateUsageFromSubscription() {
$this->client->addResponse('GET', '/subscriptions/012345678901234567890123456789ab', 'subscriptions/show-200.xml');
$this->client->addResponse('POST', '/subscriptions/012345678901234567890123456789ab/add_ons/marketing_emails/usage', 'usage/create-201.xml');

$subscription = Recurly_Subscription::get('012345678901234567890123456789ab', $this->client);
$usage = $subscription->buildUsage('marketing_emails', $this->client);

$usage->create();

$this->assertInstanceOf('Recurly_Usage', $usage);
$this->assertInstanceOf('Recurly_Stub', $usage->measured_unit);
}

}
5 changes: 4 additions & 1 deletion Tests/fixtures/addons/show-200.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,8 @@ ETag: "a81253e90a4f16089b951028675c58d2"
<unit_amount_in_cents>
<USD type="integer">200</USD>
</unit_amount_in_cents>
<measured_unit_id>123456</measured_unit_id>
<add_on_type>usage</add_on_type>
<usage_type>price</usage_type>
<created_at type="datetime">2011-06-28T12:34:56Z</created_at>
</add_on>
</add_on>
10 changes: 10 additions & 0 deletions Tests/fixtures/measured_units/create-201.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
HTTP/1.1 201 Created
Content-Type: application/xml; charset=utf-8

<?xml version="1.0" encoding="UTF-8"?>
<measured_unit href="https://api.recurly.com/v2/measured_units/123456">
<id type="integer">123456</id>
<name>Marketing Emails</name>
<display_name>Email</display_name>
<description>A Marketing Email</description>
</measured_unit>
19 changes: 19 additions & 0 deletions Tests/fixtures/measured_units/index-200.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
HTTP/1.1 200 OK
Content-Type: application/xml; charset=utf-8
X-Records: 2

<?xml version="1.0" encoding="UTF-8"?>
<measured_units>
<measured_unit href="https://api.recurly.com/v2/measured_units/123456">
<id type="integer">123456</id>
<name>Marketing Emails</name>
<display_name>Email</display_name>
<description>A Marketing Email</description>
</measured_unit>
<measured_unit href="https://api.recurly.com/v2/measured_units/654321">
<id type="integer">654321</id>
<name>Another Unit</name>
<display_name>Another</display_name>
<description>Another Measured Unit</description>
</measured_unit>
</measured_units>
10 changes: 10 additions & 0 deletions Tests/fixtures/measured_units/show-200.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
HTTP/1.1 200 OK
Content-Type: application/xml; charset=utf-8

<?xml version="1.0" encoding="UTF-8"?>
<measured_unit href="https://api.recurly.com/v2/measured_units/123456">
<id type="integer">123456</id>
<name>Marketing Emails</name>
<display_name>Email</display_name>
<description>A Marketing Email</description>
</measured_unit>
13 changes: 9 additions & 4 deletions Tests/fixtures/subscriptions/show-200.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,15 @@ Content-Type: application/xml; charset=utf-8
<vat_reverse_charge_notes>Some VAT Notes</vat_reverse_charge_notes>
<subscription_add_ons type="array">
<subscription_add_on>
<name>IP Addresses</name>
<add_on_code>ipaddresses</add_on_code>
<unit_amount_in_cents type="integer">200</unit_amount_in_cents>
<quantity type="integer">2</quantity>
<add_on_type>usage</add_on_type>
<measured_unit href="https://api.recurly.com/v2/measured_units/123456"/>
<usage href="https://api.recurly.com/v2/subscriptions/012345678901234567890123456789ab/add_ons/marketing_emails/usage"/>
<add_on_code>marketing_emails</add_on_code>
<name>Marketing Emails</name>
<unit_amount_in_cents type="integer">5</unit_amount_in_cents>
<quantity type="integer">1</quantity>
<usage_type>price</usage_type>
<usage_percentage nil="nil"/>
</subscription_add_on>
</subscription_add_ons>
<a name="cancel" href="https://api.recurly.com/v2/subscriptions/012345678901234567890123456789ab/cancel" method="put"/>
Expand Down
17 changes: 17 additions & 0 deletions Tests/fixtures/usage/create-201.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
HTTP/1.1 201 Created
Content-Type: application/xml; charset=utf-8

<?xml version="1.0" encoding="UTF-8"?>
<usage href="https://api.recurly.com/v2/subscriptions/012345678901234567890123456789ab/add_ons/marketing_emails/usage/123456">
<measured_unit href="https://yoursubdomain.recurly.com/v2/measured_units/7610" />
<amount type="integer">6</amount>
<merchant_tag>Order Number: #198349243975</merchant_tag>
<recording_timestamp type="date">2016-03-15T23:17:15+00:00</recording_timestamp>
<usage_timestamp type="date">2016-03-15T23:17:14+00:00</usage_timestamp>
<created_at type="date">2016-03-15T23:18:12+00:00</created_at>
<updated_at nil="nil"></updated_at>
<billed_at nil="nil"></billed_at>
<usage_type>percentage</usage_type>
<unit_amount_in_cents nil="nil"></unit_amount_in_cents>
<usage_percentage type="float">1.25</usage_percentage>
</usage>
17 changes: 17 additions & 0 deletions Tests/fixtures/usage/show-200.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
HTTP/1.1 200 OK
Content-Type: application/xml; charset=utf-8

<?xml version="1.0" encoding="UTF-8"?>
<usage href="https://api.recurly.com/v2/subscriptions/012345678901234567890123456789ab/add_ons/marketing_emails/usage/123456">
<measured_unit href="https://yoursubdomain.recurly.com/v2/measured_units/7610" />
<amount type="integer">6</amount>
<merchant_tag>Order Number: #198349243975</merchant_tag>
<recording_timestamp type="date">2016-03-15T23:17:15+00:00</recording_timestamp>
<usage_timestamp type="date">2016-03-15T23:17:14+00:00</usage_timestamp>
<created_at type="date">2016-03-15T23:18:12+00:00</created_at>
<updated_at nil="nil"></updated_at>
<billed_at nil="nil"></billed_at>
<usage_type>PERCENTAGE</usage_type>
<unit_amount_in_cents nil="nil"></unit_amount_in_cents>
<usage_percentage type="float">1.25</usage_percentage>
</usage>
4 changes: 4 additions & 0 deletions lib/recurly.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
require_once(dirname(__FILE__) . '/recurly/unique_coupon_code_list.php');
require_once(dirname(__FILE__) . '/recurly/invoice.php');
require_once(dirname(__FILE__) . '/recurly/invoice_list.php');
require_once(dirname(__FILE__) . '/recurly/measured_unit.php');
require_once(dirname(__FILE__) . '/recurly/measured_unit_list.php');
require_once(dirname(__FILE__) . '/recurly/note.php');
require_once(dirname(__FILE__) . '/recurly/note_list.php');
require_once(dirname(__FILE__) . '/recurly/plan.php');
Expand All @@ -40,6 +42,8 @@
require_once(dirname(__FILE__) . '/recurly/transaction.php');
require_once(dirname(__FILE__) . '/recurly/transaction_error.php');
require_once(dirname(__FILE__) . '/recurly/transaction_list.php');
require_once(dirname(__FILE__) . '/recurly/usage.php');
require_once(dirname(__FILE__) . '/recurly/usage_list.php');

require_once(dirname(__FILE__) . '/recurly/push_notification.php');
require_once(dirname(__FILE__) . '/recurly/recurly_js.php');
Expand Down
3 changes: 2 additions & 1 deletion lib/recurly/addon.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ public static function init()
{
Recurly_Addon::$_writeableAttributes = array(
'add_on_code','name','display_quantity','default_quantity',
'unit_amount_in_cents','accounting_code','tax_code'
'unit_amount_in_cents','accounting_code','tax_code',
'measured_unit_id','usage_type','add_on_type'
);
}

Expand Down
4 changes: 4 additions & 0 deletions lib/recurly/base.php
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,8 @@ public function getLinks() {
'invoice' => 'Recurly_Invoice',
'invoices' => 'Recurly_InvoiceList',
'line_items' => 'array',
'measured_unit' => 'Recurly_MeasuredUnit',
'measured_units' => 'Recurly_MeasuredUnitList',
'note' => 'Recurly_Note',
'notes' => 'Recurly_NoteList',
'plan' => 'Recurly_Plan',
Expand All @@ -203,6 +205,8 @@ public function getLinks() {
'transactions' => 'Recurly_TransactionList',
'transaction_error' => 'Recurly_TransactionError',
'unit_amount_in_cents' => 'Recurly_CurrencyList',
'usage' => 'Recurly_Usage',
'usages' => 'Recurly_UsageList'
);

// Use a valid Recurly_Response to populate a new object.
Expand Down
4 changes: 3 additions & 1 deletion lib/recurly/client.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class Recurly_Client
/**
* API Version
*/
public static $apiVersion = '2.1';
public static $apiVersion = '2.2';

/**
* The path to your CA certs. Use only if needed (if you can't fix libcurl/php).
Expand Down Expand Up @@ -67,6 +67,8 @@ class Recurly_Client
const PATH_PLANS = '/plans';
const PATH_SUBSCRIPTIONS = '/subscriptions';
const PATH_TRANSACTIONS = '/transactions';
const PATH_MEASURED_UNITS = '/measured_units';
const PATH_USAGE = '/usage';

const PATH_RECURLY_JS_RESULT = '/recurly_js/result';

Expand Down
43 changes: 43 additions & 0 deletions lib/recurly/measured_unit.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

class Recurly_MeasuredUnit extends Recurly_Resource
{
protected static $_writeableAttributes;

public static function init()
{
Recurly_MeasuredUnit::$_writeableAttributes = array(
'name','display_name','description'
);
}

public function create() {
$this->_save(Recurly_Client::POST, Recurly_Client::PATH_MEASURED_UNITS);
}

public static function get($id, $client = null) {
return Recurly_Base::_get(Recurly_MeasuredUnit::uriForMeasuredUnit($id), $client);
}

protected function uri() {
if (!empty($this->_href))
return $this->getHref();
else
return Recurly_Addon::uriForMeasuredUnit($this->id);
}
protected static function uriForMeasuredUnit($id) {
return Recurly_Client::PATH_MEASURED_UNITS . '/' . rawurlencode($id);
}

protected function getNodeName() {
return 'measured_unit';
}
protected function getWriteableAttributes() {
return Recurly_MeasuredUnit::$_writeableAttributes;
}
protected function getRequiredAttributes() {
return array();
}
}

Recurly_MeasuredUnit::init();
13 changes: 13 additions & 0 deletions lib/recurly/measured_unit_list.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

class Recurly_MeasuredUnitList extends Recurly_Pager
{
public static function get($params = null, $client = null) {
$uri = self::_uriWithParams(Recurly_Client::PATH_MEASURED_UNITS, $params);
return new self($uri, $client);
}

protected function getNodeName() {
return 'measured_units';
}
}
8 changes: 8 additions & 0 deletions lib/recurly/subscription.php
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,14 @@ public function updateNotes($notes) {
$this->setValues($notes)->_save(Recurly_Client::PUT, $this->uri() . '/notes');
}

public function buildUsage($addOnCode, $client = null) {
return Recurly_Usage::build($this->uuid, $addOnCode, $client);
}

public function usages($addOnCode, $params = null) {
return Recurly_UsageList::get($this->uuid, $addOnCode, $params);
}

protected function uri() {
if (!empty($this->_href))
return $this->getHref();
Expand Down
5 changes: 4 additions & 1 deletion lib/recurly/subscription_addon.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ public static function init() {
Recurly_SubscriptionAddOn::$_writeableAttributes = array(
'add_on_code',
'quantity',
'unit_amount_in_cents'
'unit_amount_in_cents',
'add_on_type',
'usage_type',
'usage_percentage'
);
}

Expand Down
Loading

0 comments on commit 5a7ec34

Please sign in to comment.