├── .gitignore ├── LICENSE ├── README.md ├── lib ├── stripe.ex └── stripe │ ├── charge.ex │ ├── charges.ex │ ├── customer.ex │ ├── customers.ex │ ├── invoice_item.ex │ ├── invoice_items.ex │ ├── plan.ex │ ├── plans.ex │ ├── subscription.ex │ ├── subscriptions.ex │ ├── supervisor.ex │ └── util.ex ├── mix.exs ├── mix.lock └── test ├── stripe_test.exs └── test_helper.exs /.gitignore: -------------------------------------------------------------------------------- 1 | /_build 2 | /deps 3 | erl_crash.dump 4 | *.ez 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Shane Logsdon 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # stripe-elixir 2 | 3 | a Stripe wrapper for Elixir 4 | 5 | ## Usage 6 | 7 | Add the following to your dependencies in your mix file: 8 | 9 | ```elixir 10 | { :stripe, github: "slogsdon/stripe-elixir" } 11 | ``` 12 | 13 | > ##### Note 14 | > stripe-elixir requires the `STRIPE_SECRET_KEY` environment variable set to a 15 | > valid API key associated with your Stripe account. 16 | 17 | ```elixir 18 | iex> Stripe.start 19 | :ok 20 | iex> Stripe.InvoiceItems.list 21 | [Stripe.InvoiceItem[id: "ii_103lSZ2eZvKYlo2C6Zz1aFHv", object: "invoiceitem", 22 | livemode: false, amount: 1000, currency: "usd", 23 | customer: "cus_3lPWbj9wX1KqP6", date: {{2014, 3, 30}, {3, 0, 11}}, 24 | proration: false, description: "One-time setup fee", invoice: nil, 25 | metadata: [{}], subscription: nil], 26 | Stripe.InvoiceItem[id: "ii_103kXf2eZvKYlo2CkRlaXEN6", object: "invoiceitem", 27 | livemode: false, amount: 350, currency: "usd", customer: "cus_3kXfWSyHPMZOan", 28 | date: {{2014, 3, 27}, {16, 11, 35}}, proration: false, description: nil, 29 | invoice: "in_103kXf2eZvKYlo2CgUV8Vctw", metadata: [{}], subscription: nil], 30 | ...] 31 | ``` 32 | 33 | ## Reference 34 | 35 | See [Stripe's API docs](https://stripe.com/docs/api/). 36 | 37 | ## Dependencies 38 | 39 | - [HTTPoison](https://github.com/edgurgel/httpoison) 40 | - [JSEX](https://github.com/talentdeficit/jsex) 41 | 42 | ## License 43 | 44 | See [LICENSE](https://github.com/slogsdon/stripe-elixir/blob/master/LICENSE) 45 | -------------------------------------------------------------------------------- /lib/stripe.ex: -------------------------------------------------------------------------------- 1 | defmodule Stripe do 2 | @moduledoc """ 3 | A HTTP client for Stripe. 4 | """ 5 | 6 | # Let's build on top of HTTPoison 7 | use Application 8 | use HTTPoison.Base 9 | 10 | def start(_type, _args) do 11 | Stripe.Supervisor.start_link 12 | end 13 | 14 | @doc """ 15 | Creates the URL for our endpoint. 16 | Args: 17 | * endpoint - part of the API we're hitting 18 | Returns string 19 | """ 20 | def process_url(endpoint) do 21 | "https://api.stripe.com/v1/" <> endpoint 22 | end 23 | 24 | @doc """ 25 | Set our request headers for every request. 26 | """ 27 | def req_headers do 28 | HashDict.new 29 | |> Dict.put("Authorization", "Bearer #{key}") 30 | |> Dict.put("User-Agent", "Stripe/v1 stripe-elixir/0.1.0") 31 | |> Dict.put("Content-Type", "application/x-www-form-urlencoded") 32 | end 33 | 34 | @doc """ 35 | Converts the binary keys in our response to atoms. 36 | Args: 37 | * body - string binary response 38 | Returns Record or ArgumentError 39 | """ 40 | def process_response_body(body) do 41 | JSEX.decode! body, [{:labels, :atom}] 42 | end 43 | 44 | @doc """ 45 | Boilerplate code to make requests. 46 | Args: 47 | * endpoint - string requested API endpoint 48 | * body - request body 49 | Returns dict 50 | """ 51 | def make_request(method, endpoint, body \\ [], headers \\ [], options \\ []) do 52 | rb = Enum.map(body, &url_encode_keyvalue(&1)) 53 | |> Enum.join("&") 54 | rh = req_headers 55 | |> Dict.merge(headers) 56 | |> Dict.to_list 57 | 58 | response = case method do 59 | :get -> get( endpoint, rh, options) 60 | :put -> put( endpoint, rb, rh, options) 61 | :head -> head( endpoint, rh, options) 62 | :post -> post( endpoint, rb, rh, options) 63 | :patch -> patch( endpoint, rb, rh, options) 64 | :delete -> delete( endpoint, rh, options) 65 | :options -> options( endpoint, rh, options) 66 | end 67 | 68 | response.body 69 | end 70 | 71 | @doc """ 72 | Grabs STRIPE_SECRET_KEY from system ENV 73 | Returns binary 74 | """ 75 | def key do 76 | Application.get_env(:stripe, :secret_key) || 77 | System.get_env "STRIPE_SECRET_KEY" 78 | end 79 | 80 | defp url_encode_keyvalue({k, v}) do 81 | key = Atom.to_string(k) 82 | "#{key}=#{v}" 83 | end 84 | end 85 | -------------------------------------------------------------------------------- /lib/stripe/charge.ex: -------------------------------------------------------------------------------- 1 | defmodule Stripe.Charge do 2 | @moduledoc """ 3 | ## Attributes 4 | 5 | - `id` - `String` 6 | - `object` - `String` - value is "charge" 7 | - `livemode` - `Boolean` 8 | - `amount` - `Integer` - Amount charged in cents 9 | - `captured` - `Boolean` - If the charge was created without capturing, 10 | this boolean represents whether or not it is still uncaptured or has 11 | since been captured. 12 | - `card` - `Keyword` -, card object Hash describing the card used to make 13 | the charge 14 | - `created` - `Tuple` 15 | - `currency` - `String` - Three-letter ISO currency code representing the 16 | currency in which the charge was made. 17 | - `paid` - `Boolean` 18 | - `refunded` - `Boolean` - Whether or not the charge has been fully 19 | refunded. If the charge is only partially refunded, this attribute 20 | will still be false. 21 | - `refunds` - `Keyword` - A list of refunds that have been applied to the 22 | charge. 23 | - `amount_refunded` - `Integer` - Amount in cents refunded (can be less 24 | than the amount attribute on the charge if a partial refund was 25 | issued) 26 | - `balance_transaction` - `String` - Balance transaction that describes 27 | the impact of this charge on your account balance (not including 28 | refunds or disputes). 29 | - `customer` - `String` - ID of the customer this charge is for if one 30 | exists 31 | - `description` - `String` 32 | - `dispute` - `Keyword` -, dispute object Details about the dispute if the 33 | charge has been disputed 34 | - `failure_code` - `String` - Error code explaining reason for charge 35 | failure if available (see https://stripe.com/docs/api#errors for a 36 | list of codes) 37 | - `failure_message` - `String` - Message to user further explaining reason 38 | for charge failure if available 39 | - `invoice` - `String` - ID of the invoice this charge is for if one exists 40 | - `metadata` - `Keyword` - Keyword A set of key/value pairs that you can 41 | attach to a charge object. It can be useful for storing additional 42 | information about the charge in a structured format. 43 | - `statement_description` - `String` - Extra information about a charge for 44 | the customer’s credit card statement. 45 | """ 46 | 47 | defstruct id: nil, 48 | object: "charge", 49 | livemode: nil, 50 | amount: nil, 51 | captured: nil, 52 | card: nil, 53 | created: nil, 54 | currency: nil, 55 | paid: nil, 56 | refunded: nil, 57 | refunds: nil, 58 | amount_refunded: nil, 59 | balance_transaction: nil, 60 | customer: nil, 61 | description: nil, 62 | dispute: nil, 63 | failure_code: nil, 64 | failure_message: nil, 65 | invoice: nil, 66 | metadata: nil, 67 | statement_description: nil 68 | 69 | @type id :: binary 70 | @type object :: binary 71 | @type livemode :: boolean 72 | @type amount :: pos_integer 73 | @type captured :: boolean 74 | @type card :: binary 75 | @type created :: {{1970..10000, 1..12, 1..31}, {0..23, 0..59, 0..59}} 76 | @type currency :: binary 77 | @type paid :: boolean 78 | @type refunded :: boolean 79 | @type refunds :: Keyword.t 80 | @type amount_refunded :: pos_integer 81 | @type balance_transaction :: binary 82 | @type customer :: binary 83 | @type description :: binary 84 | @type dispute :: Keyword.t 85 | @type failure_code :: binary 86 | @type failure_message :: binary 87 | @type invoice :: binary 88 | @type metadata :: Keyword.t 89 | @type statement_description :: binary 90 | 91 | @type t :: %Stripe.Charge{ 92 | id: id, 93 | object: object, 94 | livemode: livemode, 95 | amount: amount, 96 | captured: captured, 97 | card: card, 98 | created: created, 99 | currency: currency, 100 | paid: paid, 101 | refunded: refunded, 102 | refunds: refunds, 103 | amount_refunded: amount_refunded, 104 | balance_transaction: balance_transaction, 105 | customer: customer, 106 | description: description, 107 | dispute: dispute, 108 | failure_code: failure_code, 109 | failure_message: failure_message, 110 | invoice: invoice, 111 | metadata: metadata, 112 | statement_description: statement_description 113 | } 114 | end -------------------------------------------------------------------------------- /lib/stripe/charges.ex: -------------------------------------------------------------------------------- 1 | defmodule Stripe.Charges do 2 | @moduledoc """ 3 | To charge a credit or a debit card, you create a new charge object. You can 4 | retrieve and refund individual charges as well as list all charges. Charges 5 | are identified by a unique random ID. 6 | """ 7 | 8 | @endpoint "charges" 9 | 10 | @doc """ 11 | To charge a credit card, you create a new charge object. If your API key is 12 | in test mode, the supplied card won't actually be charged, though 13 | everything else will occur as if in live mode. (Stripe assumes that the 14 | charge would have completed successfully). 15 | 16 | ## Arguments 17 | 18 | - `amount` - required - A positive integer in the smallest currency unit 19 | (e.g 100 cents to charge $1.00, or 1 to charge ¥1, a 0-decimal currency) 20 | representing how much to charge the card. The minimum amount is $0.50 21 | (or equivalent in charge currency). 22 | - `currency` - required - 3-letter ISO code for currency. 23 | - `customer` - optional, either customer or card is required - The ID of an 24 | existing customer that will be charged in this request. 25 | - `card` - optional, either card or customer is required - A card to be 26 | charged. If you also pass a customer ID, the card must be the ID of a 27 | card belonging to the customer. Otherwise, if you do not pass a customer 28 | ID, the card you provide must either be a token, like the ones returned 29 | by Stripe.js, or a dictionary containing a user's credit card details, 30 | with the options described below. Although not all information is 31 | required, the extra info helps prevent fraud. 32 | - `number` - required - The card number, as a string without any 33 | separators. 34 | - `exp_month` - required - Two digit number representing the card's 35 | expiration month. 36 | - `exp_year` - required - Two or four digit number representing the 37 | card's expiration year. 38 | - `cvc` - optional, highly recommended - Card security code. 39 | - `name` - optional - Cardholder's full name. 40 | - `address_line1` - optional 41 | - `address_line2` - optional 42 | - `address_city` - optional 43 | - `address_zip` - optional 44 | - `address_state` - optional 45 | - `address_country` - optional 46 | - `description` - optional, default is null - An arbitrary string which you 47 | can attach to a charge object. It is displayed when in the web interface 48 | alongside the charge. Note that if you use Stripe to send automatic email 49 | receipts to your customers, your receipt emails will include the 50 | description of the charge(s) that they are describing. 51 | - `metadata` - optional, default is { } - A set of key/value pairs that you 52 | can attach to a customer object. It can be useful for storing additional 53 | information about the customer in a structured format. It's often a good 54 | idea to store an email address in metadata for tracking later. 55 | - `capture` - optional, default is true - Whether or not to immediately 56 | capture the charge. When false, the charge issues an authorization (or 57 | pre-authorization), and will need to be captured later. Uncaptured 58 | charges expire in 7 days. For more information, see authorizing charges 59 | and settling later. 60 | - `statement_description` - optional, default is null - An arbitrary string 61 | to be displayed alongside your company name on your customer's credit 62 | card statement. This may be up to 15 characters. As an example, if your 63 | website is RunClub and you specify 5K Race Ticket, the user will see 64 | RUNCLUB 5K RACE TICKET. The statement description may not include `<>"'` 65 | characters. While most banks display this information consistently, some 66 | may display it incorrectly or not at all. 67 | - `application_fee` - optional - A fee in cents that will be applied to the 68 | charge and transferred to the application owner's Stripe account. The 69 | request must be made with an OAuth key in order to take an application 70 | fee. For more information, see the application fees documentation. 71 | 72 | ## Returns 73 | 74 | Returns a charge object if the charge succeeded. Returns an error if something 75 | goes wrong. A common source of error is an invalid or expired card, or a valid 76 | card with insufficient available balance. 77 | 78 | If the cvc parameter is provided, Stripe will attempt to check the CVC's 79 | correctness, and the check's result will be returned. Similarly, If 80 | address_line1 or address_zip are provided, Stripe will similarly try to check 81 | the validity of those parameters. Some banks do not support checking one or 82 | more of these parameters, in which case Stripe will return an 'unchecked' 83 | result. Also note that, depending on the bank, charges can succeed even when 84 | passed incorrect CVC and address information. 85 | """ 86 | def create(params) do 87 | Stripe.make_request :post, @endpoint, params 88 | end 89 | end -------------------------------------------------------------------------------- /lib/stripe/customer.ex: -------------------------------------------------------------------------------- 1 | defmodule Stripe.Customer do 2 | @moduledoc """ 3 | ## Attributes 4 | 5 | - `id` - `String` 6 | - `object` - `String` - value is "customer" 7 | - `livemode` - `Boolean` 8 | - `cards` - `List` 9 | - `created` - `Tuple` 10 | - `account_balance` - `Integer` - Current balance, if any, being stored on the 11 | customer’s account. If negative, the customer has credit to apply to the 12 | next invoice. If positive, the customer has an amount owed that will be 13 | added to the next invoice. The balance does not refer to any unpaid 14 | invoices; it solely takes into account amounts that have yet to be 15 | successfully applied to any invoice. This balance is only taken into 16 | account for recurring charges. 17 | - `currency` - `String` - The currency the customer can be charged in for 18 | recurring billing purposes (subscriptions, invoices, invoice items). 19 | - `default_card` - `String` - ID of the default credit card attached to the 20 | customer 21 | - `delinquent` - `Boolean` - Whether or not the latest charge for the 22 | customer’s latest invoice has failed 23 | - `description` - `String` 24 | - `discount` - `Stripe.Discount` - Describes the current discount active on 25 | the customer, if there is one. 26 | - `email` - `String` 27 | - `metadata` - `Keyword` - Keyword A set of key/value pairs that you can 28 | attach to a charge object. It can be useful for storing additional 29 | information about the charge in a structured format. 30 | - `subscriptions` - `List` - The customer’s current subscriptions, if any 31 | """ 32 | 33 | defstruct id: nil, 34 | object: "customer", 35 | livemode: nil, 36 | cards: nil, 37 | created: nil, 38 | account_balance: nil, 39 | currency: nil, 40 | default_card: nil, 41 | delinquent: nil, 42 | description: nil, 43 | discount: nil, 44 | email: nil, 45 | metadata: nil, 46 | subscriptions: nil 47 | 48 | @type id :: binary 49 | @type object :: binary 50 | @type livemode :: boolean 51 | @type cards :: [] #[Stripe.Card.t] 52 | @type created :: {{1970..10000, 1..12, 1..31}, {0..23, 0..59, 0..59}} 53 | @type account_balance :: integer 54 | @type currency :: binary 55 | @type default_card :: binary 56 | @type delinquent :: boolean 57 | @type description :: binary 58 | @type discount :: binary # Stripe.Discount.t 59 | @type email :: binary 60 | @type metadata :: Keyword.t 61 | @type subscriptions :: [Stripe.Subscripton.t] 62 | 63 | @type t :: %Stripe.Customer{ 64 | id: id, 65 | object: object, 66 | livemode: livemode, 67 | cards: cards, 68 | created: created, 69 | account_balance: account_balance, 70 | currency: currency, 71 | default_card: default_card, 72 | delinquent: delinquent, 73 | description: description, 74 | discount: discount, 75 | email: email, 76 | metadata: metadata, 77 | subscriptions: subscriptions 78 | } 79 | 80 | def from_keyword(data) do 81 | datetime = Stripe.Util.datetime_from_timestamp data[:created] 82 | %Stripe.Customer{ 83 | id: data[:id], 84 | object: data[:object], 85 | cards: data[:cards], 86 | created: datetime, 87 | account_balance: data[:account_balance], 88 | currency: data[:currency], 89 | default_card: data[:default_card], 90 | delinquent: data[:delinquent], 91 | description: data[:description], 92 | discount: data[:discount], 93 | email: data[:email], 94 | metadata: data[:metadata], 95 | subscriptions: data[:subscriptions] 96 | } 97 | end 98 | end -------------------------------------------------------------------------------- /lib/stripe/customers.ex: -------------------------------------------------------------------------------- 1 | defmodule Stripe.Customers do 2 | @moduledoc """ 3 | Customer objects allow you to perform recurring charges and track multiple 4 | charges that are associated with the same customer. The API allows you to 5 | create, delete, and update your customers. You can retrieve individual 6 | customers as well as a list of all your customers. 7 | """ 8 | 9 | @endpoint "customers" 10 | 11 | @doc """ 12 | Creates a new customer object. 13 | 14 | ## Arguments 15 | 16 | - `account_balance` - `optional` - An integer amount in cents that is the 17 | starting account balance for your customer. A negative amount represents a 18 | credit that will be used before attempting any charges to the customer’s 19 | card; a positive amount will be added to the next invoice. 20 | - `card` - `optional` - The card can either be a token, like the ones returned 21 | by our Stripe.js, or a dictionary containing a user’s credit card details 22 | (with the options shown below). Passing card will create a new card, make 23 | it the new customer default card, and delete the old customer default if 24 | one exists. If you want to add additional cards instead of replacing the 25 | existing default, use the card creation API. Whenever you attach a card to 26 | a customer, Stripe will automatically validate the card. 27 | - `number` - required - The card number, as a string without any 28 | separators. 29 | - `exp_month` - required - Two digit number representing the card's 30 | expiration month. 31 | - `exp_year` - required - Two or four digit number representing the 32 | card's expiration year. 33 | - `cvc` - optional, highly recommended - Card security code. 34 | - `name` - optional - Cardholder's full name. 35 | - `address_line1` - optional 36 | - `address_line2` - optional 37 | - `address_city` - optional 38 | - `address_zip` - optional 39 | - `address_state` - optional 40 | - `address_country` - optional 41 | - `coupon` - `optional` - If you provide a coupon code, the customer will have 42 | a discount applied on all recurring charges. Charges you create through 43 | the API will not have the discount. 44 | - `description` - `optional` - An arbitrary string that you can attach to a 45 | customer object. It is displayed alongside the customer in the dashboard. 46 | This will be unset if you POST an empty value. 47 | - `email` - `optional` - Customer’s email address. It’s displayed alongside 48 | the customer in your dashboard and can be useful for searching and 49 | tracking. This will be unset if you POST an empty value. 50 | - `metadata` - `optional` - A set of key/value pairs that you can attach to a 51 | customer object. It can be useful for storing additional information about 52 | the customer in a structured format. This will be unset if you POST an 53 | empty value. 54 | - `plan` - `optional` - The identifier of the plan to subscribe the customer 55 | to. If provided, the returned customer object will have a list of 56 | subscriptions that the customer is currently subscribed to. If you 57 | subscribe a customer to a plan without a free trial, the customer must 58 | have a valid card as well. 59 | - `quantity` - `optional` - The quantity you’d like to apply to the 60 | subscription you’re creating (if you pass in a plan). For example, if your 61 | plan is 10 cents/user/month, and your customer has 5 users, you could pass 62 | 5 as the quantity to have the customer charged 50 cents (5 x 10 cents) 63 | monthly. Defaults to 1 if not set. Only applies when the plan parameter is 64 | also provided. 65 | - `trial_end` - `optional` - Unix timestamp representing the end of the trial 66 | period the customer will get before being charged for the first time. If 67 | set, trial_end will override the default trial period of the plan the 68 | customer is being subscribed to. The special value now can be provided to 69 | end the customer’s trial immediately. Only applies when the plan parameter 70 | is also provided. 71 | 72 | ## Returns 73 | 74 | Returns a customer object if the call succeeded. The returned object will have 75 | information about subscriptions, discount, and cards, if that information has 76 | been provided. If a non-free plan is specified and a card is not provided 77 | (unless the plan has a trial period), the call will return an error. If a 78 | non-existent plan or a non-existent or expired coupon is provided, the call 79 | will return an error. 80 | 81 | If a card has been attached to the customer, the returned customer object will 82 | have a default_card attribute, which is an ID that can be expanded into the 83 | full card details when retrieving the customer. 84 | """ 85 | def create(params) do 86 | obj = Stripe.make_request :post, @endpoint, params 87 | if obj[:object] do 88 | Stripe.Customer.from_keyword obj 89 | else 90 | [] 91 | end 92 | end 93 | end -------------------------------------------------------------------------------- /lib/stripe/invoice_item.ex: -------------------------------------------------------------------------------- 1 | defmodule Stripe.InvoiceItem do 2 | @moduledoc """ 3 | ## Attributes 4 | 5 | - `id` - `String` 6 | - `object` - `String`, value is "invoiceitem" 7 | - `livemode` - `Boolean` 8 | - `amount` - `Integer` 9 | - `currency` - `String` 10 | - `customer` - `String` 11 | - `date` - `Tuple` 12 | - `proration` - `Boolean` - Whether or not the invoice item was created 13 | automatically as a proration adjustment when the customer 14 | switched plans 15 | - `description` - `String` 16 | - `invoice` - `String` 17 | - `metadata` - `Keyword` - A set of key/value pairs that you can 18 | attach to an invoice item object. It can be useful for storing 19 | additional information about the invoice item in a structured format. 20 | - `subscription` - `String` - The subscription that this invoice item 21 | has been created for, if any. 22 | """ 23 | 24 | defstruct id: nil, 25 | object: "invoiceitem", 26 | livemode: nil, 27 | amount: nil, 28 | currency: nil, 29 | customer: nil, 30 | date: nil, 31 | proration: nil, 32 | description: nil, 33 | invoice: nil, 34 | metadata: nil, 35 | subscription: nil 36 | 37 | @type id :: binary 38 | @type object :: binary 39 | @type livemode :: boolean 40 | @type amount :: pos_integer 41 | @type currency :: binary 42 | @type customer :: binary 43 | @type date :: {{1970..10000, 1..12, 1..31}, {0..23, 0..59, 0..59}} 44 | @type proration :: boolean 45 | @type description :: binary 46 | @type invoice :: binary 47 | @type metadata :: Keyword.t 48 | @type subscription :: binary 49 | 50 | @type t :: %Stripe.InvoiceItem{ 51 | id: id, 52 | object: object, 53 | livemode: livemode, 54 | amount: amount, 55 | currency: currency, 56 | customer: customer, 57 | date: date, 58 | proration: proration, 59 | description: description, 60 | invoice: invoice, 61 | metadata: metadata, 62 | subscription: subscription 63 | } 64 | 65 | def from_keyword(data) do 66 | datetime = Stripe.Util.datetime_from_timestamp data[:date] 67 | %Stripe.InvoiceItem{ 68 | id: data[:id], 69 | object: data[:object], 70 | livemode: data[:livemode], 71 | amount: data[:amount], 72 | currency: data[:currency], 73 | customer: data[:customer], 74 | date: datetime, 75 | proration: data[:proration], 76 | description: data[:description], 77 | invoice: data[:invoice], 78 | metadata: data[:metadata], 79 | subscription: data[:subscription] 80 | } 81 | end 82 | end -------------------------------------------------------------------------------- /lib/stripe/invoice_items.ex: -------------------------------------------------------------------------------- 1 | defmodule Stripe.InvoiceItems do 2 | @moduledoc """ 3 | Invoice Items 4 | 5 | Sometimes you want to add a charge or credit to a customer but only 6 | actually charge the customer's card at the end of a regular billing 7 | cycle. This is useful for combining several charges to minimize 8 | per-transaction fees or having Stripe tabulate your usage-based 9 | billing totals. 10 | """ 11 | 12 | @endpoint "invoiceitems" 13 | 14 | @doc """ 15 | Returns a list of your invoice items. Invoice Items are returned sorted 16 | by creation date, with the most recently created invoice items appearing 17 | first. 18 | 19 | ## Arguments 20 | 21 | - `created` - `String` | `Keyword` - (optional) - A filter on the list 22 | based on the object created field. The value can be a string with 23 | an exact UTC timestamp, or it can be a dictionary with the 24 | following options: 25 | - `gt` - `String` - (optional) - Return values where the created 26 | field is after this timestamp. 27 | - `gte` - `String` - (optional) - Return values where the created 28 | field is after or equal to this timestamp. 29 | - `lt` - `String` - (optional) - Return values where the created 30 | field is before this timestamp. 31 | - `lte` - `String` - (optional) - Return values where the created 32 | field is before or equal to this timestamp. 33 | - `customer` - `String` - (optional) - The identifier of the customer 34 | whose invoice items to return. If none is provided, all invoice 35 | items will be returned. 36 | - `limit` - `Integer` - (optional), default is 10 - A limit on the number 37 | of objects to be returned. Limit can range between 1 and 100 items. 38 | - `offset` - `Integer` - (optional), default is 0 - An offset into the 39 | list of returned items. The API will return the requested number of 40 | items starting at that offset. 41 | - `starting_after` - `String` - (optional) - A "cursor" for use in 42 | pagination. starting_after is an object id that defines your place 43 | in the list. For instance, if you make a list request and receive 44 | 100 objects, ending with obj_foo, your subsequent call can include 45 | `starting_after=obj_foo` in order to fetch the next page of the list. 46 | 47 | ## Returns 48 | 49 | A dictionary with a data property that contains an array of up to limit 50 | invoice items, starting after invoice item starting_after. Each entry in 51 | the array is a separate invoice item object. If no more invoice items 52 | are available, the resulting array will be empty. This request should 53 | never return an error. 54 | 55 | You can optionally request that the response include the total count of 56 | all invoice items that match your filters. To do so, specify 57 | `include[]=total_count` in your request. 58 | """ 59 | def list do 60 | obj = Stripe.make_request :get, @endpoint 61 | if obj[:data] do 62 | Enum.map obj[:data], &Stripe.InvoiceItem.from_keyword(&1) 63 | else 64 | [] 65 | end 66 | end 67 | 68 | @doc """ 69 | Adds an arbitrary charge or credit to the customer's upcoming invoice. 70 | 71 | ## Arguments 72 | 73 | - `customer` - `String` - (required) - The ID of the customer who will 74 | be billed when this invoice item is billed. 75 | - `amount` - `Integer` - (required) - The integer amount in cents of 76 | the charge to be applied to the upcoming invoice. If you want to 77 | apply a credit to the customer's account, pass a negative amount. 78 | - `currency` - `String` - (required) - 3-letter ISO code for currency. 79 | - `invoice` - `String` - (optional) - The ID of an existing invoice to 80 | add this invoice item to. When left blank, the invoice item will be 81 | added to the next upcoming scheduled invoice. Use this when adding 82 | invoice items in response to an invoice.created webhook. You 83 | cannot add an invoice item to an invoice that has already been 84 | paid or closed. 85 | - `subscription` - `String` - (optional) - The ID of a subscription to 86 | add this invoice item to. When left blank, the invoice item will be 87 | added to the next upcoming scheduled invoice. When set, scheduled 88 | invoices for subscriptions other than the specified subscription 89 | will ignore the invoice item. Use this when you want to express 90 | that an invoice item has been accrued within the context of a 91 | particular subscription. 92 | - `description` - `String` - (optional), default is `null` - An arbitrary 93 | string which you can attach to the invoice item. The description is 94 | displayed in the invoice for easy tracking. 95 | - `metadata` - `Keyword` - (optional), default is `[]` - A set of 96 | key/value pairs that you can attach to an invoice item object. It can 97 | be useful for storing additional information about the invoice item in 98 | a structured format. 99 | 100 | ## Returns 101 | 102 | The created invoice item object is returned if successful. Otherwise, 103 | this call returns an error. 104 | """ 105 | def create(params) do 106 | obj = Stripe.make_request :post, @endpoint, params 107 | Stripe.InvoiceItem.from_keyword obj 108 | end 109 | 110 | @doc """ 111 | Retrieves the invoice item with the given ID. 112 | 113 | ## Arguments 114 | 115 | - `id` - `String` - (required) - The ID of the desired invoice item. 116 | 117 | ## Returns 118 | 119 | Returns an invoice item if a valid invoice item ID was provided. Returns 120 | an error otherwise. 121 | """ 122 | def retrieve(id) do 123 | obj = Stripe.make_request :get, @endpoint <> "/#{id}" 124 | Stripe.InvoiceItem.from_keyword obj 125 | end 126 | 127 | @doc """ 128 | Updates the amount or description of an invoice item on an upcoming invoice. 129 | Updating an invoice item is only possible before the invoice it's attached 130 | to is closed. 131 | 132 | ## Arguments 133 | 134 | - `amount` - `Integer` - (required) - The integer amount in cents of 135 | the charge to be applied to the upcoming invoice. If you want to 136 | apply a credit to the customer's account, pass a negative amount. 137 | - `description` - `String` - (optional), default is `null` - An arbitrary 138 | string which you can attach to the invoice item. The description is 139 | displayed in the invoice for easy tracking. 140 | - `metadata` - `Keyword` - (optional), default is `[]` - A set of 141 | key/value pairs that you can attach to an invoice item object. It can 142 | be useful for storing additional information about the invoice item in 143 | a structured format. 144 | 145 | ## Returns 146 | 147 | The updated invoice item object is returned upon success. Otherwise, this 148 | call returns an error. 149 | """ 150 | def update(params) do 151 | obj = Stripe.make_request :post, @endpoint <> "/#{params[:id]}", params 152 | Stripe.InvoiceItem.from_keyword obj 153 | end 154 | 155 | @doc """ 156 | Removes an invoice item from the upcoming invoice. Removing an invoice 157 | item is only possible before the invoice it's attached to is closed. 158 | 159 | ## Arguments 160 | 161 | - `id` - `String` - (required) - The ID of the desired invoice item. 162 | 163 | ## Returns 164 | 165 | An object with the deleted invoice item's ID and a deleted flag upon 166 | success. This call returns an error otherwise, such as when the invoice 167 | item has already been deleted. 168 | """ 169 | def delete(id) do 170 | Stripe.make_request :delete, @endpoint <> "/#{id}" 171 | end 172 | end 173 | -------------------------------------------------------------------------------- /lib/stripe/plan.ex: -------------------------------------------------------------------------------- 1 | defmodule Stripe.Plan do 2 | @doc """ 3 | ## Attributes 4 | 5 | - `id` - `string` 6 | - `object` - `string`, value is "plan" 7 | - `livemode` - `boolean` 8 | - `amount` - `Integer` - The amount in cents to be charged on the interval specified 9 | - `created` - `timestamp` 10 | - `currency` - `String` - Currency in which subscription will be charged 11 | - `interval` - `String` - One of week, month or year. The frequency with which a subscription should be billed. 12 | - `interval_count` - `Integer` - The number of intervals (specified in the interval property) between each subscription billing. For example, interval=month and interval_count=3 bills every 3 months. 13 | - `name` - `string` - Display name of the plan 14 | - `metadata` - `Keyword` - A set of key/value pairs that you can attach to a plan object. It can be useful for storing additional information about the plan in a structured format. 15 | - `trial_period_days` - `Integer` - Number of trial period days granted when subscribing a customer to this plan. Null if the plan has no trial period. 16 | - `statement_description` - `String` - Extra information about a charge for the customer’s credit card statement. 17 | """ 18 | 19 | defstruct id: nil, 20 | object: "plan", 21 | livemode: nil, 22 | amount: nil, 23 | created: nil, 24 | currency: nil, 25 | interval: nil, 26 | interval_count: nil, 27 | name: nil, 28 | metadata: nil, 29 | trial_period_days: nil, 30 | statement_description: nil 31 | 32 | @type id :: binary 33 | @type object :: binary 34 | @type livemode :: boolean 35 | @type amount :: pos_integer 36 | @type created :: {{1970..10000, 1..12, 1..31}, {0..23, 0..59, 0..59}} 37 | @type currency :: binary 38 | @type interval :: binary 39 | @type interval_count :: pos_integer 40 | @type name :: binary 41 | @type metadata :: Keyword.t 42 | @type trial_period_days :: pos_integer 43 | @type statement_description :: binary 44 | 45 | @type t :: %Stripe.Plan{ 46 | id: id, 47 | object: object, 48 | livemode: livemode, 49 | amount: amount, 50 | created: created, 51 | currency: currency, 52 | interval: interval, 53 | interval_count: interval_count, 54 | name: name, 55 | metadata: metadata, 56 | trial_period_days: trial_period_days, 57 | statement_description: statement_description 58 | } 59 | 60 | def from_keyword(data) do 61 | created = Stripe.Util.datetime_from_timestamp data[:created] 62 | %Stripe.Plan{ 63 | id: data[:id], 64 | object: data[:object], 65 | livemode: data[:livemode], 66 | amount: data[:amount], 67 | created: created, 68 | currency: data[:currency], 69 | interval: data[:interval], 70 | interval_count: data[:interval_count], 71 | name: data[:name], 72 | metadata: data[:metadata], 73 | trial_period_days: data[:trial_period_days], 74 | statement_description: data[:statement_description] 75 | } 76 | end 77 | end -------------------------------------------------------------------------------- /lib/stripe/plans.ex: -------------------------------------------------------------------------------- 1 | defmodule Stripe.Plans do 2 | @moduledoc """ 3 | A subscription plan contains the pricing information for different products 4 | and feature levels on your site. For example, you might have a $10/month 5 | plan for basic features and a different $20/month plan for premium features. 6 | """ 7 | 8 | @endpoint "plans" 9 | 10 | @doc """ 11 | You can create plans easily via the plan management page of the Stripe 12 | dashboard. Plan creation is also accessible via the API if you need to 13 | create plans on the fly. 14 | 15 | ## Arguments 16 | 17 | - `id` - required - Unique string of your choice that will be used to 18 | identify this plan when subscribing a customer. This could be an 19 | identifier like "gold" or a primary key from your own database. 20 | - `amount` - required - A positive integer in cents (or 0 for a free plan) 21 | representing how much to charge (on a recurring basis). 22 | - `currency` - required - 3-letter ISO code for currency. 23 | - `interval` - required - Specifies billing frequency. Either week, month 24 | or year. 25 | - `interval_count` - optional - default is 1 - The number of intervals 26 | between each subscription billing. For example, interval=month and 27 | interval_count=3 bills every 3 months. Maximum of one year 28 | - `interval` - allowed - (1 year, 12 months, or 52 weeks). 29 | - `name` - required - Name of the plan, to be displayed on invoices and in 30 | the web interface. 31 | - `trial_period_days` - optional - Specifies a trial period in (an integer 32 | number of) days. If you include a trial period, the customer won't be 33 | billed for the first time until the trial period ends. If the customer 34 | cancels before the trial period is over, she'll never be billed at all. 35 | - `metadata` - optional - default is { } - A set of key/value pairs that 36 | you can attach to a plan object. It can be useful for storing 37 | additional information about the plan in a structured format. 38 | - `statement_description` - optional - default is null - An arbitrary 39 | string to be displayed on your customers' credit card statements 40 | (alongside your company name) for charges created by this plan. This 41 | may be up to 15 characters. As an example, if your website is RunClub 42 | and you specify Silver Plan, the user will see RUNCLUB SILVER PLAN. 43 | The statement description may not include `<>"'` characters. While 44 | most banks display this information consistently, some may display 45 | it incorrectly or not at all. 46 | """ 47 | def create(params) do 48 | obj = Stripe.make_request :post, @endpoint, params 49 | Stripe.Plan.from_keyword obj 50 | end 51 | end -------------------------------------------------------------------------------- /lib/stripe/subscription.ex: -------------------------------------------------------------------------------- 1 | defmodule Stripe.Subscription do 2 | @moduledoc """ 3 | ## Attributes 4 | 5 | - `id` - string 6 | - `object` - string, value is "subscription" 7 | - `cancel_at_period_end` - boolean - If the subscription has been 8 | canceled with the at_period_end flag set to true, 9 | cancel_at_period_end on the subscription will be true. You can use 10 | this attribute to determine whether a subscription that has a 11 | status of active is scheduled to be canceled at the end of the 12 | current period. 13 | - `customer` - string 14 | - `plan` - hash, plan object - Hash describing the plan the customer 15 | is subscribed to 16 | - `quantity` - integer 17 | - `start` - timestamp - Date the subscription started 18 | - `status` - string - Possible values are trialing, active, past_due, 19 | canceled, or unpaid. A subscription still in its trial period is 20 | trialing and moves to active when the trial period is over. When 21 | payment to renew the subscription fails, the subscription becomes 22 | past_due. After Stripe has exhausted all payment retry attempts, 23 | the subscription ends up with a status of either canceled or 24 | unpaid depending on your retry settings. Note that when a 25 | subscription has a status of unpaid, no subsequent invoices will 26 | be attempted (invoices will be created, but then immediately 27 | automatically closed). After receiving updated card details from a 28 | customer, you may choose to reopen and pay their closed invoices. 29 | - `application_fee_percent` - decimal - A positive decimal that 30 | represents the fee percentage of the subscription invoice amount 31 | that will be transferred to the application owner’s Stripe account 32 | each billing period. 33 | - `canceled_at` - timestamp - If the subscription has been canceled, 34 | the date of that cancellation. If the subscription was canceled 35 | with cancel_at_period_end, canceled_at will still reflect the date 36 | of the initial cancellation request, not the end of the 37 | subscription period when the subscription is automatically moved 38 | to a canceled state. 39 | - `current_period_end` - timestamp - End of the current period that the 40 | subscription has been invoiced for. At the end of this period, a 41 | new invoice will be created. 42 | - `current_period_start` - timestamp - Start of the current period that 43 | the subscription has been invoiced for 44 | - `discount` - hash, discount object - Describes the current discount 45 | applied to this subscription, if there is one. When billing, a 46 | discount applied to a subscription overrides a discount applied on 47 | a customer-wide basis. 48 | - `ended_at` - timestamp - If the subscription has ended (either 49 | because it was canceled or because the customer was switched to a 50 | subscription to a new plan), the date the subscription ended 51 | - `trial_end` - timestamp - If the subscription has a trial, the end of 52 | that trial. 53 | - `trial_start` - timestamp - If the subscription has a trial, the 54 | beginning of that trial. 55 | """ 56 | 57 | defstruct id: nil, 58 | object: "subscription", 59 | cancel_at_period_end: nil, 60 | customer: nil, 61 | plan: nil, 62 | quantity: nil, 63 | start: nil, 64 | status: nil, 65 | application_fee_percent: nil, 66 | canceled_at: nil, 67 | current_period_end: nil, 68 | current_period_start: nil, 69 | discount: nil, 70 | ended_at: nil, 71 | trial_end: nil, 72 | trial_start: nil 73 | 74 | @type id :: binary 75 | @type object :: binary 76 | @type cancel_at_period_end :: boolean 77 | @type customer :: binary 78 | @type plan :: Keyword.t #| Stripe.Plan.t 79 | @type quantity :: pos_integer 80 | @type start :: {{1970..10000, 1..12, 1..31}, {0..23, 0..59, 0..59}} 81 | @type status :: binary 82 | @type application_fee_percent :: float 83 | @type canceled_at :: {{1970..10000, 1..12, 1..31}, {0..23, 0..59, 0..59}} 84 | @type current_period_end :: {{1970..10000, 1..12, 1..31}, {0..23, 0..59, 0..59}} 85 | @type current_period_start :: {{1970..10000, 1..12, 1..31}, {0..23, 0..59, 0..59}} 86 | @type discount :: Keyword.t #| Stripe.Discount.t 87 | @type ended_at :: {{1970..10000, 1..12, 1..31}, {0..23, 0..59, 0..59}} 88 | @type trial_end :: {{1970..10000, 1..12, 1..31}, {0..23, 0..59, 0..59}} 89 | @type trial_start :: {{1970..10000, 1..12, 1..31}, {0..23, 0..59, 0..59}} 90 | 91 | @type t :: %Stripe.Subscription{ 92 | id: id, 93 | object: object, 94 | cancel_at_period_end: cancel_at_period_end, 95 | customer: customer, 96 | plan: plan, 97 | quantity: quantity, 98 | start: start, 99 | status: status, 100 | application_fee_percent: application_fee_percent, 101 | canceled_at: canceled_at, 102 | current_period_end: current_period_end, 103 | current_period_start: current_period_start, 104 | discount: discount, 105 | ended_at: ended_at, 106 | trial_end: trial_end, 107 | trial_start: trial_start 108 | } 109 | 110 | def from_keyword(data) do 111 | start = Stripe.Util.datetime_from_timestamp data[:start] 112 | canceled_at = Stripe.Util.datetime_from_timestamp data[:canceled_at] 113 | current_period_end = Stripe.Util.datetime_from_timestamp data[:current_period_end] 114 | current_period_start = Stripe.Util.datetime_from_timestamp data[:current_period_start] 115 | ended_at = Stripe.Util.datetime_from_timestamp data[:ended_at] 116 | trial_end = Stripe.Util.datetime_from_timestamp data[:trial_end] 117 | trial_start = Stripe.Util.datetime_from_timestamp data[:trial_start] 118 | %Stripe.Subscription{ 119 | id: data[:id], 120 | object: data[:object], 121 | cancel_at_period_end: data[:cancel_at_period_end], 122 | customer: data[:customer], 123 | plan: data[:plan], 124 | quantity: data[:quantity], 125 | start: start, 126 | status: data[:status], 127 | application_fee_percent: data[:application_fee_percent], 128 | canceled_at: canceled_at, 129 | current_period_end: current_period_end, 130 | current_period_start: current_period_start, 131 | discount: data[:discount], 132 | ended_at: ended_at, 133 | trial_end: trial_end, 134 | trial_start: trial_start 135 | } 136 | end 137 | end -------------------------------------------------------------------------------- /lib/stripe/subscriptions.ex: -------------------------------------------------------------------------------- 1 | defmodule Stripe.Subscriptions do 2 | @moduledoc """ 3 | To charge a credit or a debit card, you create a new charge object. You can 4 | retrieve and refund individual charges as well as list all charges. Charges 5 | are identified by a unique random ID. 6 | """ 7 | 8 | @doc """ 9 | You can see a list of the customer's active subscriptions. Note that the 10 10 | most recent active subscriptions are always available by default on the 11 | customer object. If you need more than those 10, you can use the limit and 12 | starting_after parameters to page through additional subscriptions. 13 | 14 | ## Arguments 15 | 16 | - `id` - required - The ID of the customer whose subscriptions will be 17 | retrieved 18 | - `limit` - optional — default is 10 - A limit on the number of objects to 19 | be returned. Limit can range between 1 and 100 items. 20 | - `starting_after` - optional - A "cursor" for use in pagination. 21 | starting_after is an object id that defines your place in the list. For 22 | instance, if you make a list request and receive 100 objects, ending 23 | with obj_foo, your subsequent call can include starting_after=obj_foo 24 | in order to fetch the next page of the list. 25 | 26 | ## Returns 27 | 28 | Returns a list of the customer's active subscriptions. 29 | 30 | You can optionally request that the response include the total count of all 31 | subscriptions for the customer. To do so, specify `include[]=total_count` 32 | in your request. 33 | """ 34 | def list(params) do 35 | obj = Stripe.make_request :get, "customers/#{params[:customer_id]}/subscriptions" 36 | if obj[:data] do 37 | Enum.map obj[:data], &Stripe.Subscription.from_keyword(&1) 38 | else 39 | [] 40 | end 41 | end 42 | 43 | @doc """ 44 | Updates an existing subscription on a customer to match the specified 45 | parameters. When changing plans or quantities, we will optionally prorate 46 | the price we charge next month to make up for any price changes. 47 | 48 | ## Arguments 49 | 50 | - `plan` - optional - The identifier of the plan to update the subscription 51 | to. If omitted, the subscription will not change plans. 52 | - `coupon` - optional - default is null - The code of the coupon to apply 53 | to the customer if you would like to apply it at the same time as 54 | creating the subscription. 55 | - `prorate` - optional - default is true - Flag telling us whether to 56 | prorate switching plans during a billing cycle. 57 | - `trial_end` - optional - default is null - UTC integer timestamp 58 | representing the end of the trial period the customer will get before 59 | being charged for the first time. If set, trial_end will override the 60 | default trial period of the plan the customer is being subscribed to. 61 | The special value now can be provided to end the customer's trial 62 | immediately. 63 | - `card` - optional - default is null - The card can either be a token, like 64 | the ones returned by our Stripe.js, or a dictionary containing a user's 65 | credit card details (with the options shown below). You must provide a 66 | card if the customer does not already have a valid card attached, and 67 | you are subscribing the customer for a plan that is not free. Passing 68 | card will create a new card, make it the customer default card, and 69 | delete the old customer default if one exists. If you want to add an 70 | additional card to use with subscriptions, instead use the card creation 71 | API to add the card and then the customer update API to set it as the 72 | default. Whenever you attach a card to a customer, Stripe will 73 | automatically validate the card. 74 | - `quantity` - optional - default is 1 - The quantity you'd like to apply to 75 | the subscription you're updating. For example, if your plan is 76 | $10/user/month, and your customer has 5 users, you could pass 5 as the 77 | quantity to have the customer charged $50 (5 x $10) monthly. If you 78 | update a subscription but don't change the plan ID (e.g. changing only 79 | the trial_end), the subscription will inherit the old subscription's 80 | quantity attribute unless you pass a new quantity parameter. If you 81 | update a subscription and change the plan ID, the new subscription will 82 | not inherit the quantity attribute and will default to 1 unless you pass 83 | a quantity parameter. 84 | - `application_fee_percent` - optional - default is null - A positive 85 | decimal (with at most two decimal places) between 1 and 100 that 86 | represents the percentage of the subscription invoice amount due each 87 | billing period (including any bundled invoice items) that will be 88 | transferred to the application owner’s Stripe account. The request must 89 | be made with an OAuth key in order to set an application fee percentage. 90 | For more information, see the application fees documentation. 91 | 92 | By default, we prorate subscription changes. For example, if a customer signs 93 | up on May 1 for a $10 plan, she'll be billed $10 immediately. If she then 94 | switches to a $20 plan on May 15, on June 1 she'll be billed $25 ($20 for a 95 | renewal of her subscription and a $5 prorating adjustment for the previous 96 | month). Similarly, a downgrade will generate a credit to be applied to the 97 | next invoice. We also prorate when you make quantity changes. Switching plans 98 | does not change the billing date or generate an immediate charge unless 99 | you're switching between different intervals (e.g. monthly to yearly), in 100 | which case we apply a credit for the time unused on the old plan and charge 101 | for the new plan starting right away, resetting the billing date. 102 | 103 | If you'd like to charge for an upgrade immediately, just pass prorate as true 104 | as usual, and then invoice the customer as soon as you make the subscription 105 | change. That'll collect the proration adjustments into a new invoice, and 106 | Stripe will automatically attempt to pay the invoice. 107 | 108 | If you don't want to prorate at all, set the prorate option to false and the 109 | customer would be billed $10 on May 1 and $20 on June 1. Similarly, if you 110 | set prorate to false when switching between different billing intervals 111 | (monthly to yearly, for example), we won't generate any credits for the old 112 | subscription's unused time, although we will still reset the billing date 113 | and bill immediately for the new subscription. 114 | 115 | ## Returns 116 | 117 | The newly created subscription object if the call succeeded. 118 | 119 | If the customer has no card or the attempted charge fails, this call returns 120 | an error (unless the specified plan is free or has a trial period). 121 | """ 122 | def update(params) do 123 | customer_id = params[:customer_id] 124 | subscription_id = params[:subscription_id] 125 | params = Keyword.drop params, [:customer_id, :subscription_id] 126 | obj = Stripe.make_request :post, "customers/#{customer_id}/subscriptions/#{subscription_id}", params 127 | Stripe.Subscription.from_keyword obj 128 | end 129 | end -------------------------------------------------------------------------------- /lib/stripe/supervisor.ex: -------------------------------------------------------------------------------- 1 | defmodule Stripe.Supervisor do 2 | use Supervisor 3 | 4 | def start_link do 5 | :supervisor.start_link(__MODULE__, []) 6 | end 7 | 8 | def init([]) do 9 | children = [ 10 | # Define workers and child supervisors to be supervised 11 | # worker(Stripe.Worker, []) 12 | ] 13 | 14 | # See http://elixir-lang.org/docs/stable/Supervisor.Behaviour.html 15 | # for other strategies and supported options 16 | supervise(children, strategy: :one_for_one) 17 | end 18 | end -------------------------------------------------------------------------------- /lib/stripe/util.ex: -------------------------------------------------------------------------------- 1 | defmodule Stripe.Util do 2 | def datetime_from_timestamp(ts) when is_binary ts do 3 | ts = case Integer.parse ts do 4 | :error -> 0 5 | {i, _r} -> i 6 | end 7 | datetime_from_timestamp ts 8 | end 9 | def datetime_from_timestamp(ts) when is_number ts do 10 | {{year, month, day}, {hour, minutes, seconds}} = :calendar.gregorian_seconds_to_datetime ts 11 | {{year + 1970, month, day}, {hour, minutes, seconds}} 12 | end 13 | def datetime_from_timestamp(nil) do 14 | datetime_from_timestamp 0 15 | end 16 | end -------------------------------------------------------------------------------- /mix.exs: -------------------------------------------------------------------------------- 1 | defmodule Stripe.Mixfile do 2 | use Mix.Project 3 | 4 | def project do 5 | [ app: :stripe, 6 | version: "0.2.0", 7 | elixir: "~> 0.15.0", 8 | deps: deps ] 9 | end 10 | 11 | # Configuration for the OTP application 12 | def application do 13 | [mod: { Stripe, [] }] 14 | end 15 | 16 | # Returns the list of dependencies in the format: 17 | # { :foobar, git: "https://github.com/elixir-lang/foobar.git", tag: "0.1" } 18 | # 19 | # To specify particular versions, regardless of the tag, do: 20 | # { :barbat, "~> 0.1", github: "elixir-lang/barbat" } 21 | defp deps do 22 | [ 23 | { :httpoison, "~> 0.3" }, 24 | { :hackney, "~> 0.13.1" }, # not included in hex version of httpoison :( 25 | { :jsex, "~> 2.0.0" } 26 | ] 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /mix.lock: -------------------------------------------------------------------------------- 1 | %{"hackney": {:package, "0.13.1"}, 2 | "httpoison": {:package, "0.3.2"}, 3 | "idna": {:package, "1.0.1"}, 4 | "jsex": {:package, "2.0.0"}, 5 | "jsx": {:package, "2.0.4"}} 6 | -------------------------------------------------------------------------------- /test/stripe_test.exs: -------------------------------------------------------------------------------- 1 | defmodule StripeTest do 2 | use ExUnit.Case 3 | 4 | test "the truth" do 5 | assert(true) 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /test/test_helper.exs: -------------------------------------------------------------------------------- 1 | ExUnit.start 2 | --------------------------------------------------------------------------------