ソースを参照

#1326 Update all plugins: Recurly from 2.7.1 to 2.10.3

Alex Trofimov 8 年 前
親
コミット
4dd9c9f0ad
34 ファイル変更、690 行追加、102 行削除
  1. 8 11
      plugins/recurly/LICENSE
  2. 10 0
      plugins/recurly/recurly.php
  3. 11 1
      plugins/recurly/recurly/account.php
  4. 11 0
      plugins/recurly/recurly/account_acquisition.php
  5. 8 2
      plugins/recurly/recurly/account_balance.php
  6. 23 3
      plugins/recurly/recurly/account_list.php
  7. 10 1
      plugins/recurly/recurly/addon_list.php
  8. 19 2
      plugins/recurly/recurly/adjustment.php
  9. 43 5
      plugins/recurly/recurly/adjustment_list.php
  10. 5 1
      plugins/recurly/recurly/billing_info.php
  11. 7 2
      plugins/recurly/recurly/client.php
  12. 32 2
      plugins/recurly/recurly/coupon.php
  13. 20 0
      plugins/recurly/recurly/coupon_list.php
  14. 18 0
      plugins/recurly/recurly/credit_payment_list.php
  15. 39 0
      plugins/recurly/recurly/currency.php
  16. 47 0
      plugins/recurly/recurly/custom_field_list.php
  17. 12 1
      plugins/recurly/recurly/delivery.php
  18. 20 1
      plugins/recurly/recurly/error_list.php
  19. 60 16
      plugins/recurly/recurly/gift_card_list.php
  20. 16 0
      plugins/recurly/recurly/invoice_collection.php
  21. 4 4
      plugins/recurly/recurly/invoice_list.php
  22. 7 0
      plugins/recurly/recurly/link.php
  23. 15 29
      plugins/recurly/recurly/measured_unit_list.php
  24. 6 3
      plugins/recurly/recurly/plan.php
  25. 87 0
      plugins/recurly/recurly/plan_list.php
  26. 14 0
      plugins/recurly/recurly/push_notification.php
  27. 9 1
      plugins/recurly/recurly/redemption_list.php
  28. 9 1
      plugins/recurly/recurly/response.php
  29. 3 9
      plugins/recurly/recurly/shipping_address.php
  30. 86 1
      plugins/recurly/recurly/shipping_address_list.php
  31. 12 4
      plugins/recurly/recurly/subscription_addon.php
  32. 5 2
      plugins/recurly/recurly/subscription_list.php
  33. 14 0
      plugins/recurly/recurly/transaction_error.php
  34. 0 0
      plugins/recurly/recurly/usage_list.php

+ 8 - 11
plugins/recurly/LICENSE

@@ -12,16 +12,18 @@ be careful when upgrading.
 
 ## Requirements
 
-###cURL and OpenSSL
+### cURL and OpenSSL
 
-The PHP library depends on PHP 5.3.0 (or higher) and libcurl compiled with
+The PHP library depends on PHP 5.4.0 (or higher) and libcurl compiled with
 OpenSSL support. Open up a `phpinfo();` page and verify that under the curl
 section, there's a line that says something like:
 
 ```
-libcurl/7.19.5 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.15
+libcurl/7.19.5 OpenSSL/1.0.1g zlib/1.2.3.3 libidn/1.15
 ```
 
+Please ensure that your OpenSSL version supports TLS v1.1 or higher. At a minimum use v1.0.1g, however we recommend v1.1.0 and up.
+
 ### Timezone
 You will need to specify your server's timezone before using the Recurly PHP client. This is necessary for the library to properly handle datetime conversions. You can do this in your `php.ini` file:
 
@@ -41,12 +43,12 @@ date_default_timezone_set('America/Los_Angeles');
 
 If you're using [Composer](http://getcomposer.org/), you can simply add a
 dependency on `recurly/recurly-client` to your project's `composer.json` file.
-Here's an example of a dependency on 2.5:
+Here's an example of a dependency on 2.10:
 
 ```json
 {
     "require": {
-        "recurly/recurly-client": "2.5.*"
+        "recurly/recurly-client": "2.10.*"
     }
 }
 ```
@@ -104,7 +106,7 @@ You can run our unit tests by using Composer to install PHPUnit:
 ```
 $ curl -s https://getcomposer.org/installer | php
 $ php composer.phar install --dev
-$ vendor/phpunit/phpunit/phpunit Tests/
+$ vendor/bin/phpunit
 ```
 
 ## Support
@@ -112,11 +114,6 @@ $ vendor/phpunit/phpunit/phpunit Tests/
 - [https://support.recurly.com](https://support.recurly.com)
 - [stackoverflow](http://stackoverflow.com/questions/tagged/recurly)
 
-## Announcements
-
-- [@recurly](https://twitter.com/recurly)
-- [Google Group Announcements](https://groups.google.com/group/recurly-api)
-
 ## Contributing Guidelines
 
 Please refer to [CONTRIBUTING.md](CONTRIBUTING.md)

+ 10 - 0
plugins/recurly/recurly.php

@@ -26,8 +26,17 @@ require_once(dirname(__FILE__) . '/recurly/adjustment_list.php');
 require_once(dirname(__FILE__) . '/recurly/billing_info.php');
 require_once(dirname(__FILE__) . '/recurly/coupon.php');
 require_once(dirname(__FILE__) . '/recurly/coupon_list.php');
+require_once(dirname(__FILE__) . '/recurly/credit_payment.php');
+require_once(dirname(__FILE__) . '/recurly/credit_payment_list.php');
+require_once(dirname(__FILE__) . '/recurly/custom_field.php');
+require_once(dirname(__FILE__) . '/recurly/custom_field_list.php');
 require_once(dirname(__FILE__) . '/recurly/unique_coupon_code_list.php');
+require_once(dirname(__FILE__) . '/recurly/export_date.php');
+require_once(dirname(__FILE__) . '/recurly/export_date_list.php');
+require_once(dirname(__FILE__) . '/recurly/export_file.php');
+require_once(dirname(__FILE__) . '/recurly/export_file_list.php');
 require_once(dirname(__FILE__) . '/recurly/invoice.php');
+require_once(dirname(__FILE__) . '/recurly/invoice_collection.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');
@@ -35,6 +44,7 @@ require_once(dirname(__FILE__) . '/recurly/note.php');
 require_once(dirname(__FILE__) . '/recurly/note_list.php');
 require_once(dirname(__FILE__) . '/recurly/plan.php');
 require_once(dirname(__FILE__) . '/recurly/plan_list.php');
+require_once(dirname(__FILE__) . '/recurly/purchase.php');
 require_once(dirname(__FILE__) . '/recurly/redemption.php');
 require_once(dirname(__FILE__) . '/recurly/redemption_list.php');
 require_once(dirname(__FILE__) . '/recurly/shipping_address.php');

+ 11 - 1
plugins/recurly/recurly/account.php

@@ -1,4 +1,5 @@
 <?php
+
 /**
  * Class Recurly_Account
  * @property Recurly_Stub $adjustments The URL of adjustments for the specified account.
@@ -21,6 +22,13 @@
  * @property Recurly_Address $address The nested address information of the account: address1, address2, city, state, zip, country, phone.
  * @property string $accept_language The ISO 639-1 language code from the user's browser, indicating their preferred language and locale.
  * @property string $hosted_login_token The unique token for automatically logging the account in to the hosted management pages. You may automatically log the user into their hosted management pages by directing the user to: https://:subdomain.recurly.com/account/:hosted_login_token.
+ * @property string $preferred_locale The locale for the emails
+ * @property string $has_live_subscription True if the account has at least one live subscription.
+ * @property string $has_active_subscription True if the account has at least one active subscription.
+ * @property string $has_future_subscription True if the account has at least one future subscription.
+ * @property string $has_canceled_subscription True if the account has at least one canceled subscription.
+ * @property string $has_paused_subscription True if the account has at least one paised subscription.
+ * @property string $has_past_due_invoice True if the account has at least one past due invoice.
  * @property DateTime $created_at The date and time the account was created in Recurly.
  * @property DateTime $updated_at The date and time the account or its billing info was last updated.
  * @property DateTime $closed_at For closed accounts, the date and time it was closed.
@@ -32,6 +40,7 @@ class Recurly_Account extends Recurly_Resource
     if (!is_null($accountCode))
       $this->account_code = $accountCode;
     $this->address = new Recurly_Address();
+    $this->custom_fields = new Recurly_CustomFieldList();
   }
 
   public function &__get($key)
@@ -94,7 +103,8 @@ class Recurly_Account extends Recurly_Resource
     return array(
       'account_code', 'username', 'first_name', 'last_name', 'vat_number',
       'email', 'company_name', 'accept_language', 'billing_info', 'address',
-      'tax_exempt', 'entity_use_code', 'cc_emails', 'shipping_addresses'
+      'tax_exempt', 'entity_use_code', 'cc_emails', 'shipping_addresses',
+      'preferred_locale', 'custom_fields'
     );
   }
   protected function getRequiredAttributes() {

+ 11 - 0
plugins/recurly/recurly/account_acquisition.php

@@ -1,5 +1,16 @@
 <?php
 
+/**
+ * Class Recurly_AccountAcquisition
+ * @property Recurly_Stub $account The associated Recurly_Account for this account acquisition.
+ * @property int $cost_in_cents Total cost of marketing activities to acquire the customer.
+ * @property string $currency_code Currency, 3-letter ISO code.
+ * @property string $channel The method by which the customer was acquired. Allowed values: [referral, social_media, email, paid_search, organic_search, direct_traffic, marketing_content, blog, events, outbound_sales, advertising, public_relations, other].
+ * @property string $subchannel A free-form field to provide additional detail on the acquisition channel.
+ * @property string $campaign Identifier for the marketing campaign used to convert this account.
+ * @property DateTime $created_at The date and time the account acquisition was created.
+ * @property DateTime $updated_at The date and time the account acquisition was last updated.
+ */
 class Recurly_AccountAcquisition extends Recurly_Resource
 {
   public static function get($accountCode, $client = null) {

+ 8 - 2
plugins/recurly/recurly/account_balance.php

@@ -1,13 +1,19 @@
 <?php
 
+/**
+ * Class Recurly_AccountBalance
+ * @property Recurly_Stub $account The associated Recurly_Account for this balance.
+ * @property boolean $past_due The account's past due status.
+ * @property Recurly_CurrencyList $balance_in_cents The account balance in cents for each currency.
+ */
 class Recurly_AccountBalance extends Recurly_Resource
 {
   public static function get($accountCode, $client = null) {
     return Recurly_Base::_get(Recurly_Client::PATH_ACCOUNTS . '/' . rawurlencode($accountCode) . Recurly_Client::PATH_BALANCE, $client);
   }
 
-  function __construct() {
-    parent::__construct();
+  function __construct($href = null, $client = null) {
+    parent::__construct($href, $client);
     $this->balance_in_cents = new Recurly_CurrencyList('balance_in_cents');
   }
 

+ 23 - 3
plugins/recurly/recurly/account_list.php

@@ -1,9 +1,28 @@
 <?php
 
+/**
+ * class Recurly_Addon
+ * @property Recurly_Stub $plan The URL of the associated Recurly_Plan for this add-on.
+ * @property Recurly_Stub $measured_unit The URL of the associated Recurly_MeasuredUnit for this add-on.
+ * @property string $add_on_code The add-on code. Max of 50 characters.
+ * @property string $name The add-on name. Max of 255 characters.
+ * @property int $default_quantity Default quantity for the hosted pages, defaults to 1.
+ * @property int $default_quantity_on_hosted_page If true, displays a quantity field on the hosted pages for the add-on.
+ * @property string $tax_code Optional field for EU VAT merchants and Avalara AvaTax Pro merchants. If you are using Recurly's EU VAT feature, you can use values of: [unknown, physical, digital]. If you have your own AvaTax account configured, you can use Avalara's tax codes to assign custom tax rules.
+ * @property Recurly_CurrencyList $unit_amount_in_cents Array of unit amounts with their currency code. Max 10000000. Ex. $5.00 USD would be <USD>500</USD>.
+ * @property string $accounting_code Accounting code for invoice line items for the add-on. Max of 20 characters.
+ * @property string $add_on_type Whether the add-on is Fixed-Price or Usage-Based. Allowed values: [fixed, usage].
+ * @property boolean $optional Whether the add-on is optional for the customer to include in their purchase on the hosted payment page.
+ * @property string $usage_type string If add_on_type = usage, you will see usage_type, which can be price or percentage. If price, the price is defined in unit_amount_in_cents. If percentage, the percentage is defined in usage_percentage.
+ * @property float $usage_percentage If add_on_type = usage, you will see usage_percentage, which can have a value if usage_type = percentage. Must be between 0.0000 and 100.0000.
+ * @property string $revenue_schedule_type Optional field for setting a revenue schedule type. This will determine how revenue for the associated Plan should be recognized. When creating a Plan, if you supply an end_date and end_date available schedule types are never, evenly, at_range_start, or at_range_end.
+ * @property DateTime $created_at The date and time the add-on was created.
+ * @property DateTime $updated_at The date and time the add-on was last updated.
+ */
 class Recurly_Addon extends Recurly_Resource
 {
-  function __construct() {
-    parent::__construct();
+  function __construct($href = null, $client = null) {
+    parent::__construct($href, $client);
     $this->unit_amount_in_cents = new Recurly_CurrencyList('unit_amount_in_cents');
   }
 
@@ -41,7 +60,8 @@ class Recurly_Addon extends Recurly_Resource
     return array(
       'add_on_code', 'name', 'display_quantity', 'default_quantity',
       'unit_amount_in_cents', 'accounting_code', 'tax_code',
-      'measured_unit_id', 'usage_type', 'add_on_type', 'revenue_schedule_type'
+      'measured_unit_id', 'usage_type', 'add_on_type', 'revenue_schedule_type',
+      'optional', 'display_quantity_on_hosted_page'
     );
   }
 }

+ 10 - 1
plugins/recurly/recurly/addon_list.php

@@ -1,7 +1,16 @@
 <?php
 
+/**
+ * Class Recurly_Address
+ * @property string $address1 The first street address line.
+ * @property string $address2 The second street address line.
+ * @property string $city The city.
+ * @property string $state The state/province. Required if country = US, CA, IT or NL.
+ * @property string $zip The zip/postal code.
+ * @property string $country The 2 character country code.
+ * @property string $phone The phone number.
+ */
 class Recurly_Address extends Recurly_Resource {
-
   protected function getNodeName() {
     return 'address';
   }

+ 19 - 2
plugins/recurly/recurly/adjustment.php

@@ -1,4 +1,5 @@
 <?php
+
 /**
  * class Recurly_Adjustment
  * @property string $type The type of adjustment to return: charge or credit.
@@ -23,6 +24,10 @@
  * @property boolean $tax_exempt true exempts tax on the charge, false applies tax on the charge. If not defined, then defaults to the Plan and Site settings. This attribute does not work for credits (negative adjustments). Credits are always post-tax. Pre-tax discounts should use the Coupons feature.
  * @property mixed[] $tax_details The nested address information of the adjustment: name, type, tax_rate, tax_in_cents.
  * @property string $tax_code Optional field for EU VAT merchants and Avalara AvaTax Pro merchants. If you are using Recurly's EU VAT feature, you can use values of unknown, physical, or digital. If you have your own AvaTax account configured, you can use Avalara tax codes to assign custom tax rules.
+ * @property string $product_code Merchant defined product code
+ * @property string $credit_reason_code Can be set if adjustment is a credit (unit_amount_in_cents < 0). Allowed values: [general, service, promotional, refund, gift_card, write_off]. Defaults to "general".
+ * @property Recurly_ShippingAddress $shipping_address The Recurly_ShippingAddress object associated with this adjustment.
+ * @property string $shipping_address_id The id of Recurly_ShippingAddress object associated with this adjustment.
  * @property DateTime $start_date A timestamp associated with when the adjustment began.
  * @property DateTime $end_date A timestamp associated with when the adjustment ended.
  * @property DateTime $created_at A timestamp associated with when the adjustment was created.
@@ -36,6 +41,7 @@ class Recurly_Adjustment extends Recurly_Resource
   public function create() {
     $this->_save(Recurly_Client::POST, $this->createUriForAccount());
   }
+
   public function delete() {
     return Recurly_Base::_delete($this->getHref(), $this->_client);
   }
@@ -77,17 +83,28 @@ class Recurly_Adjustment extends Recurly_Resource
       throw new Recurly_Error("'account_code' is not specified");
 
     return (Recurly_Client::PATH_ACCOUNTS . '/' . rawurlencode($this->account_code) .
-            Recurly_Client::PATH_ADJUSTMENTS);
+        Recurly_Client::PATH_ADJUSTMENTS);
+  }
+
+  protected function populateXmlDoc(&$doc, &$node, &$obj, $nested = false) {
+    if ($this->isEmbedded($node, 'adjustments')) {
+      $adjustmentNode = $node->appendChild($doc->createElement($this->getNodeName()));
+      parent::populateXmlDoc($doc, $adjustmentNode, $obj, $nested);
+    } else {
+      parent::populateXmlDoc($doc, $node, $obj, $nested);
+    }
   }
 
   protected function getNodeName() {
     return 'adjustment';
   }
+
   protected function getWriteableAttributes() {
     return array(
       'currency', 'unit_amount_in_cents', 'quantity', 'description',
       'accounting_code', 'tax_exempt', 'tax_code', 'start_date', 'end_date',
-      'revenue_schedule_type', 'origin'
+      'revenue_schedule_type', 'origin', 'product_code', 'credit_reason_code',
+      'shipping_address', 'shipping_address_id'
     );
   }
 }

+ 43 - 5
plugins/recurly/recurly/adjustment_list.php

@@ -3,6 +3,7 @@
 abstract class Recurly_Base
 {
   protected $_href;
+  protected $_type;
   protected $_client;
   protected $_links;
 
@@ -15,7 +16,7 @@ abstract class Recurly_Base
 
   /**
    * Request the URI, validate the response and return the object.
-   * @param string Resource URI, if not fully qualified, the base URL will be appended
+   * @param string Resource URI, if not fully qualified, the base URL will be prepended
    * @param string Optional client for the request, useful for mocking the client
    */
   public static function _get($uri, $client = null)
@@ -28,9 +29,24 @@ abstract class Recurly_Base
     return Recurly_Base::__parseResponseToNewObject($response, $uri, $client);
   }
 
+  /**
+   * Send a HEAD request to the URI, validate the response and return the headers.
+   * @param string Resource URI, if not fully qualified, the base URL will be prepended
+   * @param string Optional client for the request, useful for mocking the client
+   */
+  public static function _head($uri, $client = null)
+  {
+    if (is_null($client)) {
+      $client = new Recurly_Client();
+    }
+    $response = $client->request(Recurly_Client::HEAD, $uri);
+    $response->assertValidResponse();
+    return $response->headers;
+  }
+
   /**
    * Post to the URI, validate the response and return the object.
-   * @param string Resource URI, if not fully qualified, the base URL will be appended
+   * @param string Resource URI, if not fully qualified, the base URL will be prepended
    * @param string Data to post to the URI
    * @param string Optional client for the request, useful for mocking the client
    */
@@ -48,7 +64,7 @@ abstract class Recurly_Base
 
   /**
    * Put to the URI, validate the response and return the object.
-   * @param string Resource URI, if not fully qualified, the base URL will be appended
+   * @param string Resource URI, if not fully qualified, the base URL will be prepended
    * @param string Optional client for the request, useful for mocking the client
    */
   protected static function _put($uri, $client = null)
@@ -149,6 +165,11 @@ abstract class Recurly_Base
     $this->_href = $href;
   }
 
+  /** Refers to the `type` root xml attribute **/
+  public function getType() {
+    return $this->_type;
+  }
+
   private function addLink($name, $href, $method){
     $this->_links[$name] = new Recurly_Link($name, $href, $method);
   }
@@ -177,7 +198,14 @@ abstract class Recurly_Base
     'billing_info' => 'Recurly_BillingInfo',
     'coupon' => 'Recurly_Coupon',
     'unique_coupon_codes' => 'Recurly_UniqueCouponCodeList',
+    'charge_invoice' => 'Recurly_Invoice',
+    'credit_invoice' => 'Recurly_Invoice',
     'currency' => 'Recurly_Currency',
+    'custom_fields' => 'Recurly_CustomFieldList',
+    'custom_field' => 'Recurly_CustomField',
+    'credit_invoices' => 'array',
+    'credit_payment' => 'Recurly_CreditPayment',
+    'credit_payments' => 'Recurly_CreditPaymentList',
     'details' => 'array',
     'discount_in_cents' => 'Recurly_CurrencyList',
     'delivery' => 'Recurly_Delivery',
@@ -193,6 +221,7 @@ abstract class Recurly_Base
     'gifter_account' => 'Recurly_Account',
     'invoice' => 'Recurly_Invoice',
     'invoices' => 'Recurly_InvoiceList',
+    'invoice_collection' => 'Recurly_InvoiceCollection',
     'line_items' => 'array',
     'measured_unit' => 'Recurly_MeasuredUnit',
     'measured_units' => 'Recurly_MeasuredUnitList',
@@ -291,7 +320,9 @@ abstract class Recurly_Base
             $node = $node->nextSibling;
             continue;
           }
-        } else if (is_array($object)) {
+        // Would prefer to do `$object instanceof ArrayAccess` but Recurly_CurrencyList
+        // implements that and expects to have its children assigned like `$list->USD = 123`.
+        } else if (is_array($object) || $object instanceof Recurly_CustomFieldList) {
           if ($nodeName == 'error') {
             $object[] = Recurly_Resource::parseErrorNode($node);
             $node = $node->nextSibling;
@@ -400,8 +431,15 @@ abstract class Recurly_Base
     else {
       if ($node_class == 'Recurly_CurrencyList') {
         $new_obj = new $node_class($nodeName);
-      } else
+      } else {
         $new_obj = new $node_class();
+      }
+
+      // It may have a type attribute we wish to capture
+      $typeAttribute = $node->getAttribute('type');
+      if (!empty($typeAttribute)) {
+        $new_obj->_type = $typeAttribute;
+      }
 
       $href = $node->getAttribute('href');
       if (!empty($href)) {

+ 5 - 1
plugins/recurly/recurly/billing_info.php

@@ -1,4 +1,5 @@
 <?php
+
 /**
  * class Recurly_BillingInfo
  * @property string $account_code Account's unique code.
@@ -21,6 +22,9 @@
  * @property string $currency Currency in which invoices will be posted. Only applicable if this account is enrolled in a plan has a different currency than your site's default.
  * @property string $verification_value Security code or CVV, 3-4 digits STRONGLY RECOMMENDED
  * @property string $ip_address Customer's IP address when updating their Billing Information STRONGLY RECOMMENDED
+ * @property string $external_hpp_type Used to indicate payment made out of band via an external service (e.g. Adyen HPP).
+ * @property string $gateway_token The token generated by the payment gateway (Vantiv for example). When using this attribute you must set gateway_code. Also, billing_info.month will be the month of the token's expiration instead of the card's expiration month, and billing_info.year will be the year of the token's expiration instead of the card's expiration year.
+ * @property string $gateway_code The identifier for the gateway to use. This code can be found on the payment gateways page in the admin UI.
  */
 class Recurly_BillingInfo extends Recurly_Resource
 {
@@ -64,7 +68,7 @@ class Recurly_BillingInfo extends Recurly_Resource
       'vat_number', 'number', 'month', 'year', 'verification_value',
       'account_number', 'routing_number', 'account_type',
       'paypal_billing_agreement_id', 'amazon_billing_agreement_id', 'currency',
-      'token_id'
+      'token_id', 'external_hpp_type', 'gateway_token', 'gateway_code'
     );
   }
 }

+ 7 - 2
plugins/recurly/recurly/client.php

@@ -27,7 +27,7 @@ class Recurly_Client
   /**
    * API Version
    */
-  public static $apiVersion = '2.4';
+  public static $apiVersion = '2.13';
 
   /**
    * The path to your CA certs. Use only if needed (if you can't fix libcurl/php).
@@ -44,7 +44,7 @@ class Recurly_Client
    */
   private $_acceptLanguage = 'en-US';
 
-  const API_CLIENT_VERSION = '2.7.1';
+  const API_CLIENT_VERSION = '2.10.3';
   const DEFAULT_ENCODING = 'UTF-8';
 
   const GET = 'GET';
@@ -62,6 +62,7 @@ class Recurly_Client
   const PATH_COUPON_REDEMPTION = '/redemption';
   const PATH_COUPON_REDEMPTIONS = '/redemptions';
   const PATH_COUPONS = '/coupons';
+  const PATH_CREDIT_PAYMENTS = '/credit_payments';
   const PATH_GIFT_CARDS = '/gift_cards';
   const PATH_UNIQUE_COUPONS = '/unique_coupon_codes';
   const PATH_INVOICES = '/invoices';
@@ -150,6 +151,10 @@ class Recurly_Client
       curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
       curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
     }
+    else if ('HEAD' == $method)
+    {
+      curl_setopt($ch, CURLOPT_NOBODY, TRUE);
+    }
     else if('GET' != $method)
     {
       curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);

+ 32 - 2
plugins/recurly/recurly/coupon.php

@@ -1,5 +1,34 @@
 <?php
 
+/**
+ * Class Recurly_Coupon
+ * @property Recurly_Stub $redemptions The URL of Recurly_CouponRedemptions for this coupon.
+ * @property int $id The unique integer identifier of the coupon.
+ * @property string $coupon_code Unique code to identify and redeem the coupon. This code may only contain the following characters: [a-z A-Z 0-9 + - _ ]. Max of 50 characters.
+ * @property string $name Coupon name.
+ * @property string $description Description of the coupon shown on the hosted payment pages.
+ * @property string $discount_type The type of discount. Allowed values: [percent, dollars, free_trial].
+ * @property int $discount_in_cents Mapping of discount amounts by currency if discount_type is dollars. Max 10000000.
+ * @property int $discount_percent Discount percentage if discount_type is percent. Example `coupon->discount_percent = 10; // 10%`
+ * @property string $invoice_description Description of the coupon on the invoice.
+ * @property int $max_redemptions Maximum number of accounts that may use the coupon before it can no longer be redeemed.
+ * @property boolean $applies_to_all_plans The coupon is valid for all plans if true, defaults to true.
+ * @property string $duration Allowed values: [forever, single_use, temporal].  If single_use, the coupon applies to the first invoice only. If temporal the coupon will apply to invoices for the duration determined by the temporal_unit and temporal_amount attributes.
+ * @property string $temporal_unit Allowed values: [day, week, month, year]. If duration is temporal then temporal_unit is multiplied by temporal_amount to define the duration that the coupon will be applied to invoices for.
+ * @property integer $temporal_amount If duration is temporal then temporal_amount is an integer which is multiplied by temporal_unit to define the duration that the coupon will be applied to invoices for.
+ * @property boolean $applies_to_non_plan_charges The coupon is valid for one-time, non-plan charges if true, defaults to false.
+ * @property string $redemption_resource Whether the discount is for all eligible charges on the account, or only a specific subscription. Allowed values: [account, subscription].
+ * @property int $max_redemptions_per_account The number of times the coupon can be redeemed on a specific account. null is the default and means unlimited.
+ * @property string $coupon_type Allowed values: [single_code, bulk]. Bulk coupons will require a unique_code_template and will generate unique codes through the generate endpoint.
+ * @property string $unique_code_template The template for generating unique codes. See rules in the coupon docs: https://dev.recurly.com/docs/create-coupon
+ * @property string[] $plan_codes Array of plan_codes the coupon applies to, if applies_to_all_plans is false.
+ * @property int $free_trial_amount Only relevant when the coupon type is free_trial. The free_trial_amount is used together with free_trial_unit to define the length of a free trial coupon. For example, a 2 week free trial would be defined as free_trial_amount = 2 and free_trial_unit = Week.
+ * @property string $free_trial_unit Only relevant when the coupon type is free_trial. Allowed values are day or week or month. free_trial_unit is used together with free_trial_unit to define the length of a free trial coupon. For example, a 2 week free trial would be defined as free_trial_amount = 2 and free_trial_unit = Week.
+ * @property DateTime $redeem_by_date Last date to redeem the coupon, defaults to no date.
+ * @property DateTime $created_at The date and time the coupon was created.
+ * @property DateTime $updated_at The date and time the coupon was last updated.
+ * @property DateTime $deleted_at The date and time the coupon was deleted.
+ */
 class Recurly_Coupon extends Recurly_Resource
 {
   protected $_redeemUrl;
@@ -110,13 +139,14 @@ class Recurly_Coupon extends Recurly_Resource
       'invoice_description', 'applies_to_non_plan_charges', 'redemption_resource',
       'max_redemptions_per_account', 'coupon_type', 'unique_code_template',
       'unique_coupon_codes', 'discount_type', 'free_trial_amount',
-      'free_trial_unit'
+      'free_trial_unit', 'description'
     );
   }
   protected function getUpdatableAttributes() {
     return array(
       'name', 'max_redemptions', 'max_redemptions_per_account',
-      'hosted_description', 'invoice_description', 'redeem_by_date'
+      'hosted_description', 'invoice_description', 'redeem_by_date',
+      'description'
     );
   }
 }

+ 20 - 0
plugins/recurly/recurly/coupon_list.php

@@ -0,0 +1,20 @@
+<?php
+/**
+ * class Recurly_CreditPayment
+ * @property string $uuid The uuid of the credit payment.
+ * @property string $currency The currency of the amount_in_cents.
+ * @property int $amount_in_cents The amount of the credit payment.
+ * @property DateTime $created_at
+ * @property DateTime $updated_at
+ * @property DateTime $voided_at
+ */
+class Recurly_CreditPayment extends Recurly_Resource
+{
+  protected function getNodeName() {
+    return 'credit_payment';
+  }
+
+  protected function getWriteableAttributes() {
+   return array();
+  }
+}

+ 18 - 0
plugins/recurly/recurly/credit_payment_list.php

@@ -0,0 +1,18 @@
+<?php
+
+class Recurly_CreditPaymentList extends Recurly_Pager
+{
+  public static function get($params = null, $client = null) {
+    $uri = self::_uriWithParams(Recurly_Client::PATH_CREDIT_PAYMENTS, $params);
+    return new self($uri, $client);
+  }
+
+  public static function getForAccount($accountCode, $params = null, $client = null) {
+    $uri = self::_uriWithParams(Recurly_Client::PATH_ACCOUNTS . '/' . rawurlencode($accountCode) . Recurly_Client::PATH_CREDIT_PAYMENTS, $params);
+    return new self($uri, $client);
+  }
+
+  protected function getNodeName() {
+    return 'credit_payments';
+  }
+}

+ 39 - 0
plugins/recurly/recurly/currency.php

@@ -0,0 +1,39 @@
+<?php
+
+/**
+ * An name/value pair.
+ */
+class Recurly_CustomField extends Recurly_Resource
+{
+  function __construct($name = null, $value = null, $client = null) {
+    parent::__construct(null, $client);
+    if (!is_null($name)) $this->name = $name;
+    $this->value = $value;
+  }
+
+  public function has_changed() {
+    return in_array('value', $this->_unsavedKeys);
+  }
+
+  // Need to make this public since Recurly_CustomFieldList doesn't inherit from
+  // Recurly_Resource.
+  public function populateXmlDoc(&$doc, &$node, &$obj, $nested = false) {
+    if ($this->has_changed()) {
+      $childNode = $node->appendChild($doc->createElement($this->getNodeName()));
+      parent::populateXmlDoc($doc, $childNode, $obj, $nested);
+    }
+  }
+
+  protected function getNodeName() {
+    return 'custom_field';
+  }
+
+  protected function getRequiredAttributes() {
+    return array('name');
+  }
+
+  protected function getWriteableAttributes() {
+    return array('name', 'value');
+  }
+}
+

+ 47 - 0
plugins/recurly/recurly/custom_field_list.php

@@ -0,0 +1,47 @@
+<?php
+
+// Recurly only stores string values so if you have other data types you should
+// explicitly handle the casting/conversion yourself. Null or empty string
+// values are used to clear a value.
+class Recurly_CustomFieldList extends ArrayObject
+{
+  public function offsetSet($index, $value) {
+    if (!$value instanceof Recurly_CustomField) {
+      throw new Exception("value must be an instance of Recurly_CustomField");
+    }
+
+    if (is_null($index)) {
+      $index = $value->name;
+    }
+    else if ($index != $value->name) {
+      throw new Exception("key: '{$index}' does not match fields's name: '{$value->name}'");
+    }
+
+    parent::offsetSet($index, $value);
+  }
+
+  public function offsetUnset($index) {
+    parent::offsetSet($index, new Recurly_CustomField($index, null));
+  }
+
+  public function populateXmlDoc(&$doc, &$node) {
+    $customFieldsNode = $doc->createElement('custom_fields');
+
+    foreach($this->getIterator() as $field) {
+      $field->populateXmlDoc($doc, $customFieldsNode, $field);
+    }
+    // Don't emit anything if there are no children.
+    if ($customFieldsNode->hasChildNodes()) {
+      $node->appendChild($customFieldsNode);
+    }
+  }
+
+  public function __toString() {
+    $values = array();
+    foreach($this->getIterator() as $field) {
+      $values[] = "{$field->name}={$field->value}";
+    }
+    $values = implode($values, ', ');
+    return "<Recurly_CustomFieldList [$values]>";
+  }
+}

+ 12 - 1
plugins/recurly/recurly/delivery.php

@@ -1,5 +1,16 @@
 <?php
 
+/**
+ * Class Recurly_Delivery
+ * @property string $method The delivery method. Allowed values: [email, post].
+ * @property string $email_address The email address of the recipient.
+ * @property string $first_name The first name of the recipient.
+ * @property string $last_name The last name of the recipient.
+ * @property string $gifter_name The name of the gifter for the purpose of message displays to the recipient.
+ * @property string $personal_message The personal message from the gifter to the recipient. 255 characters.
+ * @property Recurly_Address $address The address of the recipient. Required if method = post.
+ * @property DateTime $deliver_at When the gift card should be delivered to the recipient. If null, the gift card will be delivered immediately. If a datetime is provided, the delivery will be in an hourly window, rounding down. For example, 6:23 pm will be in the 6:00 pm hourly batch.
+ */
 class Recurly_Delivery extends Recurly_Resource
 {
   protected function getNodeName() {
@@ -8,7 +19,7 @@ class Recurly_Delivery extends Recurly_Resource
   protected function getWriteableAttributes() {
     return array(
       'method','email_address','first_name','last_name',
-      'address','gifter_name','personal_message'
+      'address','gifter_name','personal_message','deliver_at'
     );
   }
 }

+ 20 - 1
plugins/recurly/recurly/error_list.php

@@ -1,5 +1,24 @@
 <?php
 
+/**
+ * Class Recurly_GiftCard
+ * @property Recurly_Stub $gifter_account The URL of the Recurly_Account for the giver of the gift.
+ * @property Recurly_Stub $recipient_account The URL of the Recurly_Account for the recipient of the gift.
+ * @property Recurly_Stub $invoice The URL of the Recurly_Invoice for the invoice of the gift card.
+ * @property Recurly_Stub $purchase_invoice The URL of the charge invoice for the gift card redemption.
+ * @property Recurly_Stub $redemption_invoice The URL of the credit invoice for the gift card purchase.
+ * @property int $id The unique identifier of the gift card.
+ * @property string $redemption_code The unique redemption code for the gift card, generated by Recurly. Will be 16 characters, alphanumeric, displayed uppercase, but accepted in any case at redemption. Used by the recipient_account to create a credit in the amount of the unit_amount_in_cents on their account.
+ * @property int $balance_in_cents The remaining credit on the recipient_account associated with this gift card. Only shows once the gift card has been redeemed. Can be used to create gift card balance displays for your customers.
+ * @property string $currency The currency of the unit_amount_in_cents and balance_in_cents.
+ * @property string $product_code The product code or SKU of the gift card product.
+ * @property int $unit_amount_in_cents The amount of the gift card, which is the amount of the charge to the gifter_account and the amount of credit that is applied to the recipient_account upon successful redemption.
+ * @property Recurly_Delivery $delivery Block of delivery information.
+ * @property DateTime $created_at The date and time the gift card was created in Recurly.
+ * @property DateTime $updated_at The date and time the gift card was last updated.
+ * @property DateTime $delivered_at When the gift card was sent to the recipient by Recurly via email, if method was email and the "Gift Card Delivery" email template was enabled. This will be empty for post delivery or email delivery where the email template was disabled.
+ * @property DateTime $redeemed_at When the gift card was redeemed by the recipient.
+ */
 class Recurly_GiftCard extends Recurly_Resource
 {
   /**
@@ -55,7 +74,7 @@ class Recurly_GiftCard extends Recurly_Resource
     } else {
       return array(
         'product_code','unit_amount_in_cents','delivery',
-        'gifter_account','currency','delivery'
+        'gifter_account','currency'
       );
     }
   }

+ 60 - 16
plugins/recurly/recurly/gift_card_list.php

@@ -1,5 +1,30 @@
 <?php
-
+/**
+ * class Recurly_Invoice
+ * @property Recurly_Stub $account
+ * @property Recurly_Address $address
+ * @property Recurly_Stub $subscriptions
+ * @property Recurly_String $all_transactions A link to all transactions on the invoice. Only present if there are more than 500 transactions
+ * @property string $uuid
+ * @property string $state
+ * @property int $invoice_number
+ * @property int $tax_in_cents
+ * @property int $total_in_cents
+ * @property DateTime $created_at
+ * @property DateTime $closed_at
+ * @property int $net_terms
+ * @property string $collection_method
+ * @property int $subtotal_before_discount_in_cents The total of all adjustments on the invoice before discounts or taxes are applied.
+ * @property int $subtotal_in_cents The total of all adjustments on the invoice after discounts are applied, but before taxes.
+ * @property int $discount_in_cents The total of all discounts applied to adjustments on the invoice.
+ * @property int $balance_in_cents The total_in_cents minus all successful transactions and credit payments for the invoice.
+ * @property DateTime $due_on If type = charge, will have a value that is the created_at plus the terms. If type = credit, will be null.
+ * @property int $type Whether the invoice is a credit invoice or charge invoice.
+ * @property int $origin The event that created the invoice.
+ * @property int $credit_customer_notes Allows merchant to set customer notes on a credit invoice. Will only be rejected if type is set to "charge", otherwise will be ignored if no credit invoice is created.
+ * @property Recurly_Adjustment[] $line_items
+ * @property Recurly_TransactionList $transactions
+ */
 class Recurly_Invoice extends Recurly_Resource
 {
   /**
@@ -34,31 +59,40 @@ class Recurly_Invoice extends Recurly_Resource
    * Creates an invoice for an account using its pending charges
    * @param string Unique account code
    * @param array additional invoice attributes (see writeableAttributes)
-   * @return Recurly_Invoice invoice on success
-   */
+   * @return Recurly_InvoiceCollection collection of invoices on success
+   **/
   public static function invoicePendingCharges($accountCode, $attributes = array(), $client = null) {
     $uri = Recurly_Client::PATH_ACCOUNTS . '/' . rawurlencode($accountCode) . Recurly_Client::PATH_INVOICES;
     $invoice = new self();
-    return self::_post($uri, $invoice->setValues($attributes)->xml(), $client);
+    return Recurly_InvoiceCollection::_post($uri, $invoice->setValues($attributes)->xml(), $client);
   }
 
   /**
    * Previews an invoice for an account using its pending charges
    * @param string Unique account code
    * @param array additional invoice attributes (see writeableAttributes)
-   * @return Recurly_Invoice invoice on success
+   * @return Recurly_InvoiceCollection collection of invoices on success
    */
   public static function previewPendingCharges($accountCode, $attributes = array(), $client = null) {
     $uri = Recurly_Client::PATH_ACCOUNTS . '/' . rawurlencode($accountCode) . Recurly_Client::PATH_INVOICES . '/preview';
     $invoice = new self();
-    return self::_post($uri, $invoice->setValues($attributes)->xml(), $client);
+    return Recurly_InvoiceCollection::_post($uri, $invoice->setValues($attributes)->xml(), $client);
   }
 
   public function markSuccessful() {
     $this->_save(Recurly_Client::PUT, $this->uri() . '/mark_successful');
   }
+
+  public function forceCollect() {
+    $this->_save(Recurly_Client::PUT, $this->uri() . '/collect');
+  }
+
+  public function void() {
+    $this->_save(Recurly_Client::PUT, $this->uri() . '/void');
+  }
+
   public function markFailed() {
-    $this->_save(Recurly_Client::PUT, $this->uri() . '/mark_failed');
+    return Recurly_InvoiceCollection::_put($this->uri() . '/mark_failed', $this->_client);
   }
 
   public function invoiceNumberWithPrefix() {
@@ -66,16 +100,26 @@ class Recurly_Invoice extends Recurly_Resource
   }
 
   /**
-   * Refunds an open amount from the invoice and returns a new refund invoice
+   * Enters an offline payment for an invoice
+   * @param Recurly_Transaction additional transaction attributes. The attributes available to set are (payment_method, collected_at, amount_in_cents, description)
+   * @return Recurly_Transaction transaction on success
+   */
+  public function enterOfflinePayment($transaction) {
+    $uri = $this->uri() . '/transactions';
+    return Recurly_Transaction::_post($uri, $transaction->xml(), $this->_client);
+  }
+
+  /**
+   * Refunds an open amount from the invoice and returns a collection of refund invoices
    * @param Integer amount in cents to refund from this invoice
-   * @param String indicates the refund order to apply, valid options: {'credit','transaction'}, defaults to 'credit'
+   * @param String indicates the refund order to apply, valid options: {'credit_first','transaction_first'}, defaults to 'credit_first'
    * @return Recurly_Invoice a new refund invoice
    */
-  public function refundAmount($amount_in_cents, $refund_apply_order = 'credit') {
+  public function refundAmount($amount_in_cents, $refund_method = 'credit_first') {
     $doc = $this->createDocument();
 
     $root = $doc->appendChild($doc->createElement($this->getNodeName()));
-    $root->appendChild($doc->createElement('refund_apply_order', $refund_apply_order));
+    $root->appendChild($doc->createElement('refund_method', $refund_method));
     $root->appendChild($doc->createElement('amount_in_cents', $amount_in_cents));
 
     return $this->createRefundInvoice($this->renderXML($doc));
@@ -84,16 +128,16 @@ class Recurly_Invoice extends Recurly_Resource
   /**
    * Refunds given line items from an invoice and returns new refund invoice
    * @param Array refund attributes or Array of refund attributes to refund (see 'REFUND ATTRIBUTES' in docs or Recurly_Adjustment#toRefundAttributes)
-   * @param String indicates the refund order to apply, valid options: {'credit','transaction'}, defaults to 'credit'
+   * @param String indicates the refund order to apply, valid options: {'credit_first','transaction_first'}, defaults to 'credit_first'
    * @return Recurly_Invoice a new refund invoice
    */
-  public function refund($line_items, $refund_apply_order = 'credit') {
+  public function refund($line_items, $refund_method = 'credit_first') {
     if (isset($line_items['uuid'])) { $line_items = array($line_items); }
 
     $doc = $this->createDocument();
 
     $root = $doc->appendChild($doc->createElement($this->getNodeName()));
-    $root->appendChild($doc->createElement('refund_apply_order', $refund_apply_order));
+    $root->appendChild($doc->createElement('refund_method', $refund_method));
     $line_items_node = $root->appendChild($doc->createElement('line_items'));
 
     foreach ($line_items as $line_item) {
@@ -107,7 +151,7 @@ class Recurly_Invoice extends Recurly_Resource
   }
 
   protected function createRefundInvoice($xml_string) {
-    return self::_post($this->uri() . '/refund', $xml_string, $this->_client);
+    return Recurly_Invoice::_post($this->uri() . '/refund', $xml_string, $this->_client);
   }
 
   protected function getNodeName() {
@@ -116,7 +160,7 @@ class Recurly_Invoice extends Recurly_Resource
   protected function getWriteableAttributes() {
     return array(
       'terms_and_conditions', 'customer_notes', 'vat_reverse_charge_notes',
-      'collection_method', 'net_terms', 'po_number'
+      'collection_method', 'net_terms', 'po_number', 'currency', 'credit_customer_notes'
     );
   }
   protected function uri() {

+ 16 - 0
plugins/recurly/recurly/invoice_collection.php

@@ -0,0 +1,16 @@
+<?php
+/**
+ * class Recurly_InvoiceCollection
+ * @property Recurly_Invoice $charge_invoice The invoice with any charges from the collection.
+ * @property Recurly_Invoice[] $credit_invoices The array of any credit invoices created from the collection.
+ */
+class Recurly_InvoiceCollection extends Recurly_Resource
+{
+  protected function getNodeName() {
+    return 'invoice_collection';
+  }
+
+  protected function getWriteableAttributes() {
+   return array();
+  }
+}

+ 4 - 4
plugins/recurly/recurly/invoice_list.php

@@ -2,12 +2,12 @@
 
 class Recurly_InvoiceList extends Recurly_Pager
 {
-  public static function getOpen($params = null, $client = null) {
-    return Recurly_InvoiceList::get(Recurly_Pager::_setState($params, 'open'), $client);
+  public static function getPending($params = null, $client = null) {
+    return Recurly_InvoiceList::get(Recurly_Pager::_setState($params, 'pending'), $client);
   }
 
-  public static function getCollected($params = null, $client = null) {
-    return Recurly_InvoiceList::get(Recurly_Pager::_setState($params, 'collected'), $client);
+  public static function getPaid($params = null, $client = null) {
+    return Recurly_InvoiceList::get(Recurly_Pager::_setState($params, 'paid'), $client);
   }
 
   public static function getFailed($params = null, $client = null) {

+ 7 - 0
plugins/recurly/recurly/link.php

@@ -1,5 +1,12 @@
 <?php
 
+/**
+ * Class Recurly_MeasuredUnit
+ * @property int $id The unique identifier of the account.
+ * @property string $name Unique internal name of the measured unit on your site.
+ * @property string $display_name Display name for the measured unit. We recommend the singular version. (e.g. - GB, API Call, Email).
+ * @property string $description Optional internal description.
+ */
 class Recurly_MeasuredUnit extends Recurly_Resource
 {
   public function create() {

+ 15 - 29
plugins/recurly/recurly/measured_unit_list.php

@@ -6,28 +6,28 @@
  *
  * The pager moves forward only and can rewind to the first item.
  */
-abstract class Recurly_Pager extends Recurly_Base implements Iterator
+abstract class Recurly_Pager extends Recurly_Base implements Iterator, Countable
 {
   private $_position = 0;    // position within the current page
-  protected $_count = null;  // total number of records
   protected $_objects;       // current page of records
 
   /**
-   * Number of records in this list.
+   * If the pager has a URL this will send a HEAD request to get the count of
+   * all records. Otherwise it'll return the count of the cached _objects.
+   *
    * @return integer number of records in list
    */
   public function count() {
-    if (!isset($this->_count)) {
-      if (isset($this->_objects)) {
-        $this->_count = count($this->_objects);
-      } elseif (isset($this->_href)) {
-        // Don't bother with the HEAD request the server takes the same amount
-        // of time to generate them so, might as well just get the results at
-        // the same time.
-        $this->_loadFrom($this->_href);
+    if (isset($this->_href)) {
+      $headers = Recurly_Base::_head($this->_href, $this->_client);
+      if (isset($headers['X-Records'])) {
+        return intval($headers['X-Records']);
       }
+    } elseif (isset($this->_objects) && is_array($this->_objects)) {
+      return count($this->_objects);
     }
-    return $this->_count;
+
+    return null;
   }
 
   /**
@@ -45,8 +45,8 @@ abstract class Recurly_Pager extends Recurly_Base implements Iterator
   public function current()
   {
     // Work around pre-PHP 5.5 issue that prevents `empty($this->count())`:
-    if ($this->count() == 0) {
-      return null;
+    if (!isset($this->_objects)) {
+      $this->_loadFrom($this->_href);
     }
 
     if ($this->_position >= sizeof($this->_objects)) {
@@ -100,7 +100,6 @@ abstract class Recurly_Pager extends Recurly_Base implements Iterator
   }
 
   protected function _afterParseResponse($response, $uri) {
-    $this->_loadRecordCount($response);
     $this->_loadLinks($response);
     $this->_href = isset($this->_links['start']) ? $this->_links['start'] : $uri;
   }
@@ -131,24 +130,11 @@ abstract class Recurly_Pager extends Recurly_Base implements Iterator
     }
   }
 
-  /**
-   * Find the total number of results in the collection from the 'X-Records' header.
-   */
-  private function _loadRecordCount($response)
-  {
-    if (isset($response->headers['X-Records'])) {
-      $this->_count = intval($response->headers['X-Records']);
-    }
-  }
-
   protected function updateErrorAttributes() {}
 
-
   public function __toString()
   {
     $class = get_class($this);
-    $count = (!empty($this->_count) ? "count={$this->_count}" : '');
-
-    return "<{$class}[href={$this->getHref()}] $count>";
+    return "<{$class}[href={$this->getHref()}]>";
   }
 }

+ 6 - 3
plugins/recurly/recurly/plan.php

@@ -1,4 +1,5 @@
 <?php
+
 /**
  * class Recurly_Plan
  * @property string $plan_code Unique code to identify the plan. This code may only contain the following characters: [a-z 0-9 @ - _ .]. Max of 50 characters.
@@ -32,11 +33,13 @@
  * @property string $measured_unit_id The id of the measured unit on your site associated with the add-on.
  * @property string $usage_type If add_on_type = usage, you must set a usage_type, which can be price or percentage. If price, the price is defined in unit_amount_in_cents. If percentage, the percentage is defined in usage_percentage.
  * @property string $usage_percentage If add_on_type = usage and usage_type = percentage, you must set a usage_percentage. Must be between 0.0000 and 100.0000.
+ * @property boolean $trial_requires_billing_info Setting to determine if subscriptions to this plan will always require billing info or will only require it when either not in a trial or when money is due, defaults to true.
+ * @property boolean $auto_renew Determines whether subscriptions to this plan should auto-renew term at the end of the current term or expire. Defaults to true.
  */
 class Recurly_Plan extends Recurly_Resource
 {
-  function __construct() {
-    parent::__construct();
+  function __construct($href = null, $client = null) {
+    parent::__construct($href, $client);
     $this->setup_fee_in_cents = new Recurly_CurrencyList('setup_fee_in_cents');
     $this->unit_amount_in_cents = new Recurly_CurrencyList('unit_amount_in_cents');
   }
@@ -81,7 +84,7 @@ class Recurly_Plan extends Recurly_Resource
       'trial_interval_unit', 'unit_amount_in_cents', 'setup_fee_in_cents',
       'total_billing_cycles', 'accounting_code', 'setup_fee_accounting_code',
       'revenue_schedule_type', 'setup_fee_revenue_schedule_type',
-      'tax_exempt', 'tax_code'
+      'tax_exempt', 'tax_code', 'trial_requires_billing_info', 'auto_renew'
     );
   }
 }

+ 87 - 0
plugins/recurly/recurly/plan_list.php

@@ -0,0 +1,87 @@
+<?php
+/**
+ * Class Recurly_Purchase
+ * @property Recurly_Account $account The account for the purchase. Can create an account or use existing.
+ * @property Recurly_Adjustment[] $adjustments The array of adjustments for the purchase
+ * @property string $collection_method The invoice collection method ('automatic' or 'manual')
+ * @property string $currency The currency to use in this invoice
+ * @property string $po_number The po number for the invoice
+ * @property integer $net_terms The net terms of the invoice
+ * @property string[] $coupon_codes An array of coupon codes to apply to the purchase
+ * @property Recurly_Subscription[] $subscriptions An array of subscriptions to apply to the purchase
+ * @property Recurly_GiftCard $gift_card A gift card to apply to the purchase
+ * @property string $customer_notes Optional notes field. This will default to the Customer Notes text specified on the Invoice Settings page in your Recurly admin. Custom notes made on an invoice for a one time charge will not carry over to subsequent invoices.
+ * @property string $terms_and_conditions Optional Terms and Conditions field. This will default to the Terms and Conditions text specified on the Invoice Settings page in your Recurly admin. Custom notes will stay with a subscription on all renewals.
+ * @property string $vat_reverse_charge_notes Optional VAT Reverse Charge Notes only appear if you have EU VAT enabled or are using your own Avalara AvaTax account and the customer is in the EU, has a VAT number, and is in a different country than your own. This will default to the VAT Reverse Charge Notes text specified on the Tax Settings page in your Recurly admin, unless custom notes were created with the original subscription. Custom notes will stay with a subscription on all renewals.
+ * @property integer $shipping_address_id Optional id of an existing ShippingAddress to be applied to all subscriptions and adjustments in purchase.
+ * @property string $gateway_code Optional base36 encoded id for the gateway you wish to use for this transaction.
+ */
+class Recurly_Purchase extends Recurly_Resource
+{
+  /**
+   * Send the purchase data to the server and creates an invoice.
+   *
+   * @param Recurly_Purchase Our purchase data.
+   * @param RecurlyClient Optional client for the request, useful for mocking the client
+   * @return Recurly_InvoiceCollection
+   */
+  public static function invoice($purchase, $client = null) {
+    return Recurly_Base::_post('/purchases', $purchase->xml(), $client);
+  }
+
+  /**
+   * Send the purchase data to the server and create a preview invoice. This runs
+   * the validations but not the transactions.
+   *
+   * @param Recurly_Purchase Our purchase data.
+   * @param RecurlyClient Optional client for the request, useful for mocking the client
+   * @return Recurly_InvoiceCollection
+   */
+  public static function preview($purchase, $client = null) {
+    return Recurly_Base::_post('/purchases/preview', $purchase->xml(), $client);
+  }
+
+  /**
+   * Send the purchase data to the server and create an authorized purchase. This runs
+   * the validations but not the transactions. This endpoint will create a
+   * pending purchase that can be activated at a later time once payment
+   * has been completed on an external source (e.g. Adyen's Hosted
+   * Payment Pages).
+   *
+   * @param Recurly_Purchase Our purchase data.
+   * @param RecurlyClient Optional client for the request, useful for mocking the client
+   * @return Recurly_InvoiceCollection
+   */
+  public static function authorize($purchase, $client = null) {
+    return Recurly_Base::_post('/purchases/authorize', $purchase->xml(), $client);
+  }
+
+  /**
+   * Use for Adyen HPP transaction requests. This runs
+   * the validations but not the transactions.
+   *
+   * @param Recurly_Purchase Our purchase data.
+   * @param RecurlyClient Optional client for the request, useful for mocking the client
+   * @return Recurly_InvoiceCollection
+   */
+  public static function pending($purchase, $client = null) {
+    return Recurly_Base::_post('/purchases/pending', $purchase->xml(), $client);
+  }
+
+  public function __construct($href = null, $client = null) {
+    parent::__construct($href, $client);
+    $this->adjustments = array();
+  }
+
+  protected function getNodeName() {
+    return 'purchase';
+  }
+  protected function getWriteableAttributes() {
+    return array(
+      'account', 'adjustments', 'collection_method', 'currency', 'po_number',
+      'net_terms', 'subscriptions', 'gift_card', 'coupon_codes', 'customer_notes',
+      'terms_and_conditions', 'vat_reverse_charge_notes', 'shipping_address_id',
+      'gateway_code'
+    );
+  }
+}

+ 14 - 0
plugins/recurly/recurly/push_notification.php

@@ -1,5 +1,19 @@
 <?php
 
+/**
+ * Class Recurly_CouponRedemption
+ * @property Recurly_Stub $coupon The URL of coupon used for this redemption.
+ * @property Recurly_Stub $account The URL of account belonging to this redemption.
+ * @property Recurly_Stub $subscription The URL of subscription belonging to this redemption.
+ * @property string $uuid The unique UUID referencing this redemption.
+ * @property boolean $single_use True if this is a single use coupon.
+ * @property integer $total_discounted_in_cents Total in cents for the discount issued with this redemption.
+ * @property string $currency The currency used at the time of purchase.
+ * @property string $state The state of the redemption. Allowed values: [active, inactive].
+ * @property string $coupon_code The coupon code of the coupon used.
+ * @property DateTime $created_at The date and time the redemption was created in Recurly.
+ * @property DateTime $updated_at The date and time the redemption was last updated.
+ */
 class Recurly_CouponRedemption extends Recurly_Resource
 {
   protected static $_redeemUrl;

+ 9 - 1
plugins/recurly/recurly/redemption_list.php

@@ -111,12 +111,20 @@ abstract class Recurly_Resource extends Recurly_Base
     return $doc->saveXML(null, LIBXML_NOEMPTYTAG);
   }
 
+  protected function isEmbedded($node, $xmlKey) {
+    $path = explode('/', $node->getNodePath());
+    $last = $path[count($path)-1];
+    return $last == $xmlKey;
+  }
+
   protected function populateXmlDoc(&$doc, &$node, &$obj, $nested = false)
   {
     $attributes = $obj->getChangedAttributes($nested);
 
     foreach ($attributes as $key => $val) {
-      if ($val instanceof Recurly_CurrencyList) {
+      // If we get another object that handles its own XML serialization but
+      // doesn't extend Recurly_Resource we should add an interface for this.
+      if ($val instanceof Recurly_CurrencyList || $val instanceof Recurly_CustomFieldList) {
         $val->populateXmlDoc($doc, $node);
       } else if ($val instanceof Recurly_Resource) {
         $attribute_node = $node->appendChild($doc->createElement($key));

+ 9 - 1
plugins/recurly/recurly/response.php

@@ -26,8 +26,16 @@ class Recurly_ClientResponse
         if ($trans_error instanceof Recurly_TransactionError && $transaction instanceof Recurly_Transaction)
           throw new Recurly_ValidationError($trans_error->customer_message, $transaction, array($trans_error));
       }
-      else
+      else {
+        // Here we are making sure that this isn't a ValidationError in the shape of a FieldError
+        // If it is, we will reshape it into a ValidationError
+        $error = @$this->parseErrorXml($this->body);
+        if (isset($error)) {
+          throw new Recurly_ValidationError('Validation error', $object, array($error));
+        }
         throw new Recurly_ValidationError('Validation error', $object, $object->getErrors());
+      }
+
     }
   }
 

+ 3 - 9
plugins/recurly/recurly/shipping_address.php

@@ -17,17 +17,11 @@ class Recurly_ShippingAddress extends Recurly_Resource
     );
   }
   protected function populateXmlDoc(&$doc, &$node, &$obj, $nested = false) {
-    if ($this->isEmbedded($node)) {
+    if ($this->isEmbedded($node, 'shipping_addresses')) {
       $shippingAddressNode = $node->appendChild($doc->createElement($this->getNodeName()));
-      parent::populateXmlDoc($doc, $shippingAddressNode, $obj);
+      parent::populateXmlDoc($doc, $shippingAddressNode, $obj, $nested);
     } else {
-      parent::populateXmlDoc($doc, $node, $obj);
+      parent::populateXmlDoc($doc, $node, $obj, $nested);
     }
   }
-
-  private function isEmbedded($node) {
-    $path = explode('/', $node->getNodePath());
-    $last = $path[count($path)-1];
-    return $last == 'shipping_addresses';
-  }
 }

+ 86 - 1
plugins/recurly/recurly/shipping_address_list.php

@@ -1,10 +1,51 @@
 <?php
 
+/**
+ * Class Recurly_Subscription
+ * @property Recurly_Stub $gift_card The gift card object is required in order to redeem a redemption code.
+ * @property string $redemption_code The redemption code for the gift card being redeemed.
+ * @property string $plan_code plan_code for the subscription.
+ * @property Recurly_Stub $account Nested account attributes.
+ * @property string $currency Currency for the subscription.
+ * @property mixed[] $subscription_add_ons Nested add-ons.
+ * @property string $coupon_code Optional coupon code to redeem on the account and discount the subscription. Please note, the subscription request will fail if the coupon is invalid.
+ * @property integer $unit_amount_in_cents Override the unit amount of the subscription plan by setting this value in cents. If not provided, the subscription will inherit the price from the subscription plan for the provided currency. Max 10000000.
+ * @property integer $quantity Optionally override the default quantity of 1.
+ * @property DateTime $trial_ends_at If set, overrides the default trial behavior for the subscription. This must be a date and time, preferably in UTC. The date must be in the future.
+ * @property DateTime $starts_at If set, the subscription will begin in the future on this date. The subscription will apply the setup fee and trial period, unless the plan has no trial.
+ * @property integer $total_billing_cycles Determines the length of the subscription’s initial term. Defaults to plan’s total billing cycles value unless overwritten when creating the subscription or editing subscription.
+ * @property DateTime $first_renewal_date Indicates a date at which the first renewal should occur. Subsequent renewals will be offset from this date. The first invoice will be prorated appropriately so that the customer only pays for the portion of the first billing period for which the subscription applies. Useful for forcing a subscription to renew on the first of the month.
+ * @property string $collection_method Optional field to set the collection for an invoice as automatic or manual. The default is automatic if it's not set.
+ * @property integer $net_terms Integer representing the number of days after an invoice's creation that the invoice will become past due. If an invoice's net terms are set to 0, it is due 'On Receipt' and will become past due 24 hours after it’s created. If an invoice is due net 30, it will become past due at 31 days exactly. Defaults to 0.
+ * @property string $po_number Optional notes field. Attach a PO number to the invoice.
+ * @property boolean $bulk Optional field to be used only when needing to bypass the 60 second limit on creating subscriptions. Should only be used when creating subscriptions in bulk from the API. Set to 'true' or 'false'. Defaults to 'false'.
+ * @property string $terms_and_conditions Optional notes field. This will default to the Terms and Conditions text specified on the Invoice Settings page in your Recurly admin. Specify custom notes with this tag to add or override Terms and Conditions. Custom notes will stay with a subscription on all renewals.
+ * @property string $customer_notes Optional notes field. This will default to the Customer Notes text specified on the Invoice Settings page in your Recurly admin. Specify custom notes with this tag to add or override Customer Notes. Custom notes will stay with a subscription on all renewals.
+ * @property string $vat_reverse_charge_notes VAT Reverse Charge Notes only appear if you have EU VAT enabled or are using your own Avalara AvaTax account and the customer is in the EU, has a VAT number, and is in a different country than your own. This will default to the VAT Reverse Charge Notes text specified on the Tax Settings page in your Recurly admin, unless custom notes were created with the original subscription. Specify custom notes with this tag to add or override VAT Reverse Charge Notes. Custom notes will stay with a subscription on all renewals.
+ * @property DateTime $bank_account_authorized_at Merchants importing recurring subscriptions paid with ACH into Recurly can backdate the subscription's authorization with this attribute using an ISO 8601 timestamp. This timestamp is used for alerting customers to reauthorize in 3 years in accordance with NACHA rules. If a subscription becomes inactive or the billing info is no longer a bank account, this timestamp is cleared.
+ * @property string $add_on_code The code for the Add-On.
+ * @property string $usage_percentage If add_on_type = usage and usage_type = percentage, you can set a custom usage_percentage for the subscription add-on. Must be between 0.0000 and 100.0000.
+ * @property string $revenue_schedule_type Optional field for setting a revenue schedule type. This will determine how revenue for the associated Subscription Add-On should be recognized. When creating a Subscription Add-On, available schedule types are never, evenly, at_range_start, or at_range_end. If no revenue_schedule_type is set, the Subscription Add-On will inherit the revenue_schedule_type from its Plan Add-On.
+ * @property boolean $imported_trial Optionally set true to denote that this subscription was imported from a trial.
+ * @property string $credit_customer_notes Allows merchant to set customer notes on a credit invoice. Will be ignored if no credit invoice is created.
+ * @property DateTime $paused_at The datetime when the subscription will be (or was) paused.
+ * @property integer $remaining_pause_cycles The number of billing cycles that the subscription will be paused.
+ * @property boolean $auto_renew Determines whether subscription will auto renew for another term at the end of current term. Defaults to plan value unless overwritten when creating subscription or editing subscription.
+ * @property integer $remaining_billing_cycles Remaining billing periods in the current subscription term. Decrements from the total number of billing periods in the current term. Will always be 0 if total billing cycles is 1.
+ * @property integer $renewal_billing_cycles Determines the renewal subscription term Defaults to plan’s total billing cycles value unless overwritten when creating the subscription or editing subscription.
+ * @property DateTime $current_period_started_at Start date of the subscription’s current billing period.
+ * @property DateTime $current_period_ends_at End date of the subscription’s current billing period.
+ * @property DateTime $first_bill_date Previously named first_renewal_date. Forces the subscription’s next billing period start date. Subsequent billing period start dates will be offset from this date. The first invoice will be prorated appropriately so that the customer pays for the portion of the first billing period for which the subscription applies.
+ * @property DateTime $next_bill_date Previously named next_renewal_date. Specifies a future date that the subscription’s next  billing period should be billed.
+ * @property DateTime $current_term_started_at Start date of the subscription’s current term. Will equal the future start date if subscription was created in the future state.
+ * @property DateTime $current_term_ends_at End date of the subscription’s current term. Will be null if subscription has future start date.
+ */
 class Recurly_Subscription extends Recurly_Resource
 {
   public function __construct($href = null, $client = null) {
     parent::__construct($href, $client);
     $this->subscription_add_ons = array();
+    $this->custom_fields = new Recurly_CustomFieldList();
   }
 
   public static function get($uuid, $client = null) {
@@ -101,6 +142,40 @@ class Recurly_Subscription extends Recurly_Resource
     $this->setValues($notes)->_save(Recurly_Client::PUT, $this->uri() . '/notes');
   }
 
+  /**
+    * Pauses a subscription or cancels a scheduled pause.
+    *
+    * - For an active subscription without a pause scheduled already,
+    * this will schedule a pause period to begin at the next renewal
+    * date for the specified number of billing cycles (remaining_pause_cycles).
+    * - For an active subscription with a scheduled pause, this will update the remaining
+    * pause cycles with the new value sent. When zero (0) remaining_pause_cycles
+    * is sent for a subscription with a scheduled pause, the pause will be canceled.
+    * - For a paused subscription, the remaining_pause_cycles will adjust the
+    * length of the current pause period. Sending zero (0) in the remaining_pause_cycles
+    * field will cause the subscription to be resumed at the next renewal date.
+    *
+    * @param integer remaining_pause_cycles The number of billing cycles that the subscription will be paused.
+    **/
+  public function pause($remaining_pause_cycles) {
+    $doc = $this->createDocument();
+    $root = $doc->appendChild($doc->createElement($this->getNodeName()));
+    $root->appendChild($doc->createElement('remaining_pause_cycles', $remaining_pause_cycles));
+    $this->_save(Recurly_Client::PUT, $this->uri() . '/pause', $this->renderXML($doc));
+  }
+
+  /**
+   * Resumes a paused subscription.
+   *
+   * For a paused subscription, this will immediately resume the subscription
+   * from the pause, produce an invoice, and return the newly resumed subscription.
+   * Any at-renewal subscription changes will be immediately applied
+   * when the subscription resumes.
+   **/
+  public function resume() {
+    $this->_save(Recurly_Client::PUT, $this->uri() . '/resume');
+  }
+
   public function buildUsage($addOnCode, $client = null) {
     return Recurly_Usage::build($this->uuid, $addOnCode, $client);
   }
@@ -121,6 +196,14 @@ class Recurly_Subscription extends Recurly_Resource
     return Recurly_Client::PATH_SUBSCRIPTIONS . '/' . rawurlencode($uuid);
   }
 
+  protected function populateXmlDoc(&$doc, &$node, &$obj, $nested = false) {
+    if ($this->isEmbedded($node, 'subscriptions')) {
+      $subscriptionNode = $node->appendChild($doc->createElement($this->getNodeName()));
+      parent::populateXmlDoc($doc, $subscriptionNode, $obj, $nested);
+    } else {
+      parent::populateXmlDoc($doc, $node, $obj, $nested);
+    }
+  }
   protected function getNodeName() {
     return 'subscription';
   }
@@ -133,7 +216,9 @@ class Recurly_Subscription extends Recurly_Resource
       'collection_method', 'cost_in_cents', 'remaining_billing_cycles', 'bulk',
       'terms_and_conditions', 'customer_notes', 'vat_reverse_charge_notes',
       'bank_account_authorized_at', 'revenue_schedule_type', 'gift_card',
-      'shipping_address', 'shipping_address_id'
+      'shipping_address', 'shipping_address_id', 'imported_trial',
+      'remaining_pause_cycles', 'custom_fields', 'auto_renew',
+      'renewal_billing_cycles'
     );
   }
 }

+ 12 - 4
plugins/recurly/recurly/subscription_addon.php

@@ -1,6 +1,15 @@
 <?php
 
-class Recurly_SubscriptionAddOn extends Recurly_Resource {
+/**
+ * Class Recurly_SubscriptionAddOn
+ * @property string $add_on_code The code for the Add-On.
+ * @property int $unit_amount_in_cents Price of 1 unit of the add-on in cents. Max 10000000.
+ * @property int $quantity Optionally override the default quantity of 1.
+ * @property float $usage_percentage If add_on_type = usage and usage_type = percentage, you can set a custom usage_percentage for the subscription add-on. Must be between 0.0000 and 100.0000.
+ * @property string $revenue_schedule_type Optional field for setting a revenue schedule type. This will determine how revenue for the associated Subscription Add-On should be recognized. When creating a Subscription Add-On, available schedule types are: [never, evenly, at_range_start, at_range_end]. If no revenue_schedule_type is set, the Subscription Add-On will inherit the revenue_schedule_type from its Plan Add-On.
+ */
+class Recurly_SubscriptionAddOn extends Recurly_Resource
+{
 
   protected function getNodeName() {
     return 'subscription_add_on';
@@ -20,7 +29,7 @@ class Recurly_SubscriptionAddOn extends Recurly_Resource {
 
   protected function populateXmlDoc(&$doc, &$node, &$obj, $nested = false) {
     $addonNode = $node->appendChild($doc->createElement($this->getNodeName()));
-    parent::populateXmlDoc($doc, $addonNode, $obj);
+    parent::populateXmlDoc($doc, $addonNode, $obj, $nested);
   }
 
   protected function getChangedAttributes($nested = false) {
@@ -38,8 +47,7 @@ class Recurly_SubscriptionAddOn extends Recurly_Resource {
   /**
    * Pretty string version of the object
    */
-  public function __toString()
-  {
+  public function __toString() {
     $class = get_class($this);
     $values = $this->__valuesString();
     return "<$class $values>";

+ 5 - 2
plugins/recurly/recurly/subscription_list.php

@@ -4,7 +4,7 @@
  * @property string $uuid Transaction's unique identifier.
  * @property Recurly_Stub $account The URL of the account associated with the transaction.  Run get() to pull back a Recurly_Account
  * @property Recurly_Stub $invoice The URL of the invoice associated with the transaction.  Run get() to pull back a Recurly_Invoice
- * @property Recurly_Stub $subscription The URL of the subscription associated with the transaction.  Run get() to pull back a Recurly_Subscription
+ * @property Recurly_Stub $subscriptions The URL of the subscriptions associated with the transaction.
  * @property string $original_transaction For refund transactions, the URL of the original transaction.  Run get() to pull back a Recurly_Transaction
  * @property string $action purchase, verify or refund.
  * @property integer $amount_in_cents Total transaction amount in cents.
@@ -31,6 +31,9 @@
  * @property string $merchant_message For declined transactions, the message displayed to the merchant (if applicable).
  * @property string $customer_message For declined transactions, the message displayed to the customer (if applicable).
  * @property string $gateway_error_code For declined transactions, this field lists the gateway error code sent to us from the gateway (if applicable).
+ * @property string $payment_method The method of payment: The method of payment: (credit_card, paypal, eft, wire_transfer, money_order, check, or other).
+ * @property DateTime $collected_at Date payment was collected
+ * @property string $product_code Merchant defined product code
  */
 class Recurly_Transaction extends Recurly_Resource
 {
@@ -86,7 +89,7 @@ class Recurly_Transaction extends Recurly_Resource
   protected function getWriteableAttributes() {
     return array(
       'account', 'amount_in_cents', 'currency', 'description', 'accounting_code',
-      'tax_exempt', 'tax_code'
+      'tax_exempt', 'tax_code', 'product_code', 'payment_method', 'collected_at'
     );
   }
 }

+ 14 - 0
plugins/recurly/recurly/transaction_error.php

@@ -1,5 +1,19 @@
 <?php
 
+/**
+ * Class Recurly_Usage
+ * @property Recurly_Stub $measured_unit The URL to the Recurly_MeasuredUnit associated with this usage.
+ * @property integer $amount The amount of usage. Can be positive, negative, or 0. No decimals allowed, we will strip them. If the usage-based add-on is billed with a percentage, your usage will be a monetary amount you will want to format in cents. (e.g. - $5.00 is "500").
+ * @property string $merchant_tag Custom field great for recording the id in your own system associated with the usage, so you can provide auditable usage displays to your customers using a GET on this endpoint.
+ * @property string $usage_type Whether the associated add-on has a pricing model of "price per unit" (price) or "percentage of an amount" (percentage).
+ * @property integer $unit_amount_in_cents If usage_type = price, this is the price of the add-on at the usage_timestamp time and the price at which the usage will be billed on the invoice.
+ * @property float $usage_percentage If usage_type = percentage, this is the percentage for the add-on at the usage_timestamp time and the percentage at which the usage will be billed on the invoice.
+ * @property DateTime $recording_timestamp When the usage was recorded in your system.
+ * @property DateTime $usage_timestamp When the usage actually happened. This will define the line item dates this usage is billed under and is important for revenue recognition.
+ * @property DateTime $created_at When the usage record was created in Recurly.
+ * @property DateTime $updated_at When the usage record was updated. Will be null after creation.
+ * @property DateTime $billed_at When the usage record was billed on an invoice.
+ */
 class Recurly_Usage extends Recurly_Resource
 {
   var $subUuid;

+ 0 - 0
plugins/recurly/recurly/usage_list.php