Current section
20 Versions
Jump to
Current section
20 Versions
Compare versions
13
files changed
+385
additions
-28
deletions
| @@ -1,3 +1,25 @@ | |
| 1 | + ## v0.12.0 2021-09-02 |
| 2 | + |
| 3 | + ### Changed |
| 4 | + |
| 5 | + - Bumped the minium Elixir version from `1.7` to `1.9` (it had been a while!) |
| 6 | + |
| 7 | + ### Added |
| 8 | + |
| 9 | + - [Braintree.Webhook] A new module that provides convenience methods for parsing |
| 10 | + Braintree webhook payloads. |
| 11 | + |
| 12 | + - [Braintree] Wrap HTTP calls in telemetry events for instrumentation. All |
| 13 | + requests are wrapped in a telemetry events, which emits standard span events: |
| 14 | + |
| 15 | + `[:braintree, :request, :start | :stop | :exception | :error]` |
| 16 | + |
| 17 | + - [Braintree.Customer] Support ApplePay and AndroidPay |
| 18 | + |
| 19 | + ### Fixed |
| 20 | + |
| 21 | + - Fix atomizing nested maps with mixed keys. |
| 22 | + |
| 1 23 | ## v0.11.0 2020-05-11 |
| 2 24 | |
| 3 25 | * [Braintree] Allow configuration of sandbox endpoint for testing |
| @@ -117,6 +117,43 @@ search_params = %{ | |
| 117 117 | |
| 118 118 | [doc]: https://developers.braintreepayments.com/ |
| 119 119 | |
| 120 | + |
| 121 | + ### Telemetry |
| 122 | + |
| 123 | + If the `telemetry` application is running, the library will emit telemetry events. |
| 124 | + |
| 125 | + Immediately before the HTTP request is fired, a start event will be fired with the following shape: |
| 126 | + |
| 127 | + ``` |
| 128 | + event name: [:braintree, :request, :start] |
| 129 | + measurements: %{system_time: System.system_time()} |
| 130 | + meta data: %{method: method, path: path} |
| 131 | + ``` |
| 132 | + |
| 133 | + Once the HTTP call completes, a stop event will be fired with the following shape: |
| 134 | + |
| 135 | + ``` |
| 136 | + event name: [:braintree, :request, :stop] |
| 137 | + measurements: %{duration: duration} |
| 138 | + meta data: %{method: method, path: path, http_status: status} |
| 139 | + ``` |
| 140 | + |
| 141 | + If Hackney returns an error, an error event will be fired with the following shape: |
| 142 | + |
| 143 | + ``` |
| 144 | + event name: [:braintree, :request, :error] |
| 145 | + measurements: %{duration: duration} |
| 146 | + meta data: %{method: method, path: path, error: error_reason} |
| 147 | + ``` |
| 148 | + |
| 149 | + If an exception is raised during the Hackney call, an exception event will be fired with the following shape: |
| 150 | + |
| 151 | + ``` |
| 152 | + event name: [:braintree, :request, :exception] |
| 153 | + measurements: %{duration: duration} |
| 154 | + meta data: %{method: method, path: path, kind: error_type, reason: error_message, stacktrace: stacktrace} |
| 155 | + ``` |
| 156 | + |
| 120 157 | ## Testing |
| 121 158 | |
| 122 159 | You'll need a Braintree sandbox account to run the integration tests. Also, be |
| @@ -148,9 +185,11 @@ testing][plp]. | |
| 148 185 | You can optionally configure the sandbox endpoint url to point towards a local url and |
| 149 186 | port for testing which does not need to call out to the Braintree sandbox API. |
| 150 187 | For example, in your `config.exs` |
| 151 | - ``` |
| 188 | + |
| 189 | + ```elixir |
| 152 190 | config :braintree, :sandbox_endpoint, "localhost:4001" |
| 153 191 | ``` |
| 192 | + |
| 154 193 | In conjuction with a libary such as [`Bypass`](https://github.com/PSPDFKit-labs/bypass) |
| 155 194 | you can use this config to define test-specific returns from `Braintree` calls without |
| 156 195 | hitting the Braintree sandbox API. |
| @@ -1,19 +1,22 @@ | |
| 1 1 | {<<"app">>,<<"braintree">>}. |
| 2 2 | {<<"build_tools">>,[<<"mix">>]}. |
| 3 3 | {<<"description">>,<<"Native Braintree client library for Elixir">>}. |
| 4 | - {<<"elixir">>,<<"~> 1.5">>}. |
| 4 | + {<<"elixir">>,<<"~> 1.9">>}. |
| 5 5 | {<<"files">>, |
| 6 | - [<<"lib">>,<<"lib/transaction.ex">>,<<"lib/credit_card_verification.ex">>, |
| 7 | - <<"lib/paypal_account.ex">>,<<"lib/construction.ex">>,<<"lib/util.ex">>, |
| 8 | - <<"lib/braintree.ex">>,<<"lib/settlement_batch_summary.ex">>, |
| 6 | + [<<"lib">>,<<"lib/webhook">>,<<"lib/webhook/digest.ex">>, |
| 7 | + <<"lib/webhook/validation.ex">>,<<"lib/transaction.ex">>, |
| 8 | + <<"lib/credit_card_verification.ex">>,<<"lib/paypal_account.ex">>, |
| 9 | + <<"lib/construction.ex">>,<<"lib/util.ex">>,<<"lib/braintree.ex">>, |
| 10 | + <<"lib/apple_pay_card.ex">>,<<"lib/settlement_batch_summary.ex">>, |
| 9 11 | <<"lib/address.ex">>,<<"lib/plan.ex">>,<<"lib/payment_method.ex">>, |
| 10 | - <<"lib/add_on.ex">>,<<"lib/credit_card.ex">>,<<"lib/subscription.ex">>, |
| 11 | - <<"lib/xml">>,<<"lib/xml/encoder.ex">>,<<"lib/xml/decoder.ex">>, |
| 12 | - <<"lib/xml/entity.ex">>,<<"lib/error_response.ex">>,<<"lib/customer.ex">>, |
| 13 | - <<"lib/testing">>,<<"lib/testing/test_transaction.ex">>, |
| 14 | - <<"lib/testing/nonces.ex">>,<<"lib/testing/credit_card_numbers.ex">>, |
| 15 | - <<"lib/transaction_line_item.ex">>,<<"lib/payment_method_nonce.ex">>, |
| 16 | - <<"lib/http.ex">>,<<"lib/client_token.ex">>,<<"lib/search.ex">>, |
| 12 | + <<"lib/add_on.ex">>,<<"lib/credit_card.ex">>,<<"lib/webhook.ex">>, |
| 13 | + <<"lib/subscription.ex">>,<<"lib/xml">>,<<"lib/xml/encoder.ex">>, |
| 14 | + <<"lib/xml/decoder.ex">>,<<"lib/xml/entity.ex">>, |
| 15 | + <<"lib/error_response.ex">>,<<"lib/customer.ex">>,<<"lib/testing">>, |
| 16 | + <<"lib/testing/test_transaction.ex">>,<<"lib/testing/nonces.ex">>, |
| 17 | + <<"lib/testing/credit_card_numbers.ex">>,<<"lib/transaction_line_item.ex">>, |
| 18 | + <<"lib/payment_method_nonce.ex">>,<<"lib/http.ex">>, |
| 19 | + <<"lib/android_pay_card.ex">>,<<"lib/client_token.ex">>,<<"lib/search.ex">>, |
| 17 20 | <<"lib/discount.ex">>,<<"lib/merchant">>,<<"lib/merchant/funding.ex">>, |
| 18 21 | <<"lib/merchant/account.ex">>,<<"lib/merchant/business.ex">>, |
| 19 22 | <<"lib/merchant/individual.ex">>,<<"priv">>,<<"priv/entities.txt">>, |
| @@ -28,5 +31,15 @@ | |
| 28 31 | {<<"name">>,<<"hackney">>}, |
| 29 32 | {<<"optional">>,false}, |
| 30 33 | {<<"repository">>,<<"hexpm">>}, |
| 31 | - {<<"requirement">>,<<"~> 1.15">>}]]}. |
| 32 | - {<<"version">>,<<"0.11.0">>}. |
| 34 | + {<<"requirement">>,<<"~> 1.15">>}], |
| 35 | + [{<<"app">>,<<"plug">>}, |
| 36 | + {<<"name">>,<<"plug">>}, |
| 37 | + {<<"optional">>,false}, |
| 38 | + {<<"repository">>,<<"hexpm">>}, |
| 39 | + {<<"requirement">>,<<"~> 1.12">>}], |
| 40 | + [{<<"app">>,<<"telemetry">>}, |
| 41 | + {<<"name">>,<<"telemetry">>}, |
| 42 | + {<<"optional">>,false}, |
| 43 | + {<<"repository">>,<<"hexpm">>}, |
| 44 | + {<<"requirement">>,<<"~> 1.0">>}]]}. |
| 45 | + {<<"version">>,<<"0.12.0">>}. |
| @@ -0,0 +1,49 @@ | |
| 1 | + defmodule Braintree.AndroidPayCard do |
| 2 | + @moduledoc """ |
| 3 | + AndroidPayCard structs are not created directly, but are built within |
| 4 | + responses from other endpoints, such as `Braintree.Customer`. |
| 5 | + |
| 6 | + For additional reference see: |
| 7 | + https://developers.braintreepayments.com/reference/response/android-pay-card/ruby |
| 8 | + """ |
| 9 | + use Braintree.Construction |
| 10 | + |
| 11 | + @type t :: %__MODULE__{ |
| 12 | + bin: String.t(), |
| 13 | + created_at: String.t(), |
| 14 | + customer_id: String.t(), |
| 15 | + default: boolean, |
| 16 | + expiration_month: String.t(), |
| 17 | + expiration_year: String.t(), |
| 18 | + google_transaction_id: String.t(), |
| 19 | + image_url: String.t(), |
| 20 | + is_network_tokenized: boolean, |
| 21 | + source_card_last_4: String.t(), |
| 22 | + source_card_type: String.t(), |
| 23 | + source_description: String.t(), |
| 24 | + subscriptions: [any], |
| 25 | + token: String.t(), |
| 26 | + updated_at: String.t(), |
| 27 | + virtual_card_last_4: String.t(), |
| 28 | + virtual_card_type: String.t() |
| 29 | + } |
| 30 | + |
| 31 | + defstruct bin: nil, |
| 32 | + billing_address: nil, |
| 33 | + created_at: nil, |
| 34 | + customer_id: nil, |
| 35 | + default: false, |
| 36 | + expiration_month: nil, |
| 37 | + expiration_year: nil, |
| 38 | + google_transaction_id: nil, |
| 39 | + image_url: nil, |
| 40 | + is_network_tokenized: false, |
| 41 | + source_card_last_4: nil, |
| 42 | + source_card_type: nil, |
| 43 | + source_description: nil, |
| 44 | + subscriptions: [], |
| 45 | + token: nil, |
| 46 | + updated_at: nil, |
| 47 | + virtual_card_last_4: nil, |
| 48 | + virtual_card_type: nil |
| 49 | + end |
| @@ -0,0 +1,47 @@ | |
| 1 | + defmodule Braintree.ApplePayCard do |
| 2 | + @moduledoc """ |
| 3 | + ApplePayCard structs are not created directly, but are built within |
| 4 | + responsees from other endpoints, such as `Braintree.Customer`. |
| 5 | + """ |
| 6 | + |
| 7 | + use Braintree.Construction |
| 8 | + alias Braintree.Address |
| 9 | + |
| 10 | + @type t :: %__MODULE__{ |
| 11 | + billing_address: Address.t(), |
| 12 | + bin: String.t(), |
| 13 | + card_type: String.t(), |
| 14 | + cardholder_name: String.t(), |
| 15 | + created_at: String.t(), |
| 16 | + customer_id: String.t(), |
| 17 | + default: String.t(), |
| 18 | + expiration_month: String.t(), |
| 19 | + expiration_year: String.t(), |
| 20 | + expired: String.t(), |
| 21 | + image_url: String.t(), |
| 22 | + last_4: String.t(), |
| 23 | + payment_instrument_name: String.t(), |
| 24 | + source_description: String.t(), |
| 25 | + subscriptions: [any], |
| 26 | + token: String.t(), |
| 27 | + updated_at: String.t() |
| 28 | + } |
| 29 | + |
| 30 | + defstruct billing_address: nil, |
| 31 | + bin: nil, |
| 32 | + card_type: nil, |
| 33 | + cardholder_name: nil, |
| 34 | + created_at: nil, |
| 35 | + customer_id: nil, |
| 36 | + default: false, |
| 37 | + expiration_month: nil, |
| 38 | + expiration_year: nil, |
| 39 | + expired: nil, |
| 40 | + image_url: nil, |
| 41 | + last_4: nil, |
| 42 | + payment_instrument_name: nil, |
| 43 | + source_description: nil, |
| 44 | + subscriptions: [], |
| 45 | + token: nil, |
| 46 | + updated_at: nil |
| 47 | + end |
Loading more files…