├── .github
└── stale.yml
├── .rspec
├── .github_changelog_generator
├── spec
├── support
│ ├── views.rb
│ ├── capybara.rb
│ ├── gateway_helpers.rb
│ ├── order_ready_for_payment.rb
│ └── vcr.rb
├── models
│ ├── spree
│ │ └── store_spec.rb
│ └── solidus_paypal_braintree
│ │ ├── address_spec.rb
│ │ ├── transaction_spec.rb
│ │ ├── transaction_address_spec.rb
│ │ ├── response_spec.rb
│ │ └── transaction_import_spec.rb
├── helpers
│ └── solidus_paypal_braintree
│ │ ├── braintree_admin_helper_spec.rb
│ │ └── braintree_checkout_helper_spec.rb
├── features
│ ├── backend
│ │ ├── configuration_spec.rb
│ │ └── new_payment_spec.rb
│ └── frontend
│ │ ├── paypal_checkout_spec.rb
│ │ ├── venmo_checkout_spec.rb
│ │ └── braintree_credit_card_checkout_spec.rb
├── requests
│ └── spree
│ │ └── api
│ │ └── orders_controller_spec.rb
├── spec_helper.rb
├── fixtures
│ ├── cassettes
│ │ ├── gateway
│ │ │ ├── cancel
│ │ │ │ └── missing.yml
│ │ │ ├── customer.yml
│ │ │ ├── authorized_transaction.yml
│ │ │ ├── authorize.yml
│ │ │ ├── authorize
│ │ │ │ ├── credit_card
│ │ │ │ │ └── address.yml
│ │ │ │ ├── paypal
│ │ │ │ │ ├── EUR.yml
│ │ │ │ │ └── address.yml
│ │ │ │ └── merchant_account
│ │ │ │ │ └── EUR.yml
│ │ │ ├── purchase.yml
│ │ │ ├── void.yml
│ │ │ ├── capture.yml
│ │ │ ├── settled_transaction.yml
│ │ │ └── complete.yml
│ │ ├── checkout
│ │ │ ├── update.yml
│ │ │ ├── invalid_credit_card.yml
│ │ │ └── valid_credit_card.yml
│ │ ├── braintree
│ │ │ ├── create_profile.yml
│ │ │ ├── token.yml
│ │ │ └── generate_token.yml
│ │ ├── transaction
│ │ │ └── import
│ │ │ │ └── valid.yml
│ │ ├── admin
│ │ │ └── invalid_credit_card.yml
│ │ └── source
│ │ │ └── card_type.yml
│ └── views
│ │ └── spree
│ │ └── orders
│ │ └── edit.html.erb
└── controllers
│ └── solidus_paypal_braintree
│ ├── client_tokens_controller_spec.rb
│ ├── configurations_controller_spec.rb
│ ├── checkouts_controller_spec.rb
│ └── transactions_controller_spec.rb
├── lib
├── solidus_paypal_braintree
│ ├── version.rb
│ └── engine.rb
├── solidus_paypal_braintree.rb
└── generators
│ └── solidus_paypal_braintree
│ └── install
│ └── install_generator.rb
├── bin
├── rake
├── setup
├── rails
├── rails-sandbox
├── console
├── rails-engine
└── sandbox
├── .gem_release.yml
├── Rakefile
├── .gitignore
├── .circleci
└── config.yml
├── LICENSE
├── Gemfile
├── solidus_paypal_braintree.gemspec
└── .rubocop.yml
/.github/stale.yml:
--------------------------------------------------------------------------------
1 | _extends: .github
2 |
--------------------------------------------------------------------------------
/.rspec:
--------------------------------------------------------------------------------
1 | --color
2 | --require spec_helper
3 |
--------------------------------------------------------------------------------
/.github_changelog_generator:
--------------------------------------------------------------------------------
1 | issues=false
2 | exclude-labels=infrastructure
3 |
--------------------------------------------------------------------------------
/spec/support/views.rb:
--------------------------------------------------------------------------------
1 | ApplicationController.prepend_view_path "spec/fixtures/views"
2 |
--------------------------------------------------------------------------------
/lib/solidus_paypal_braintree/version.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module SolidusPaypalBraintree
4 | VERSION = '2.0.0'
5 | end
6 |
--------------------------------------------------------------------------------
/bin/rake:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # frozen_string_literal: true
3 |
4 | require "rubygems"
5 | require "bundler/setup"
6 |
7 | load Gem.bin_path("rake", "rake")
8 |
--------------------------------------------------------------------------------
/bin/setup:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | set -euo pipefail
3 | IFS=$'\n\t'
4 | set -vx
5 |
6 | gem install bundler --conservative
7 | bundle update
8 | bin/rake clobber
9 |
--------------------------------------------------------------------------------
/.gem_release.yml:
--------------------------------------------------------------------------------
1 | bump:
2 | recurse: false
3 | file: 'lib/solidus_paypal_braintree/version.rb'
4 | message: Bump SolidusPaypalBraintree to %{version}
5 | tag: true
6 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'solidus_dev_support/rake_tasks'
4 | SolidusDevSupport::RakeTasks.install
5 |
6 | task default: 'extension:specs'
7 |
--------------------------------------------------------------------------------
/bin/rails:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 |
3 | if %w[g generate].include? ARGV.first
4 | exec "#{__dir__}/rails-engine", *ARGV
5 | else
6 | exec "#{__dir__}/rails-sandbox", *ARGV
7 | end
8 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.gem
2 | \#*
3 | *~
4 | .#*
5 | .DS_Store
6 | .idea
7 | .project
8 | .sass-cache
9 | coverage
10 | Gemfile.lock
11 | tmp
12 | nbproject
13 | pkg
14 | *.swp
15 | spec/dummy
16 | spec/examples.txt
17 | /sandbox
18 | .rvmrc
19 | .ruby-version
20 | .ruby-gemset
21 |
--------------------------------------------------------------------------------
/spec/support/capybara.rb:
--------------------------------------------------------------------------------
1 | RSpec.configure do |config|
2 | config.before(:each, type: :feature, js: true) do
3 | page.driver.browser.manage.window.resize_to(1600, 1024)
4 | end
5 | end
6 |
7 | Capybara.javascript_driver = (ENV['CAPYBARA_DRIVER'] || :selenium_chrome_headless).to_sym
8 |
--------------------------------------------------------------------------------
/lib/solidus_paypal_braintree.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'solidus_braintree'
4 | require 'solidus_paypal_braintree/version'
5 | require 'solidus_paypal_braintree/engine'
6 |
7 | module SolidusPaypalBraintree
8 | def self.table_name_prefix
9 | 'solidus_paypal_braintree_'
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/lib/generators/solidus_paypal_braintree/install/install_generator.rb:
--------------------------------------------------------------------------------
1 | module SolidusPaypalBraintree
2 | module Generators
3 | class InstallGenerator < Rails::Generators::Base
4 | def install_braintree
5 | run 'bin/rails g solidus_braintree:install --auto_run_migrations=true'
6 | end
7 | end
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/lib/solidus_paypal_braintree/engine.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'solidus_core'
4 | require 'solidus_support'
5 |
6 | module SolidusPaypalBraintree
7 | class Engine < Rails::Engine
8 | include SolidusSupport::EngineExtensions
9 |
10 | isolate_namespace SolidusPaypalBraintree
11 | engine_name 'solidus_paypal_braintree'
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/bin/rails-sandbox:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 |
3 | app_root = 'sandbox'
4 |
5 | unless File.exist? "#{app_root}/bin/rails"
6 | warn 'Creating the sandbox app...'
7 | Dir.chdir "#{__dir__}/.." do
8 | system "#{__dir__}/sandbox" or begin
9 | warn 'Automatic creation of the sandbox app failed'
10 | exit 1
11 | end
12 | end
13 | end
14 |
15 | Dir.chdir app_root
16 | exec 'bin/rails', *ARGV
17 |
--------------------------------------------------------------------------------
/bin/console:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 |
3 | # frozen_string_literal: true
4 |
5 | require "bundler/setup"
6 | require "solidus_paypal_braintree"
7 |
8 | # You can add fixtures and/or initialization code here to make experimenting
9 | # with your gem easier. You can also use a different console, if you like.
10 | $LOAD_PATH.unshift(*Dir["#{__dir__}/../app/*"])
11 |
12 | # (If you use this, don't forget to add pry to your Gemfile!)
13 | # require "pry"
14 | # Pry.start
15 |
16 | require "irb"
17 | IRB.start(__FILE__)
18 |
--------------------------------------------------------------------------------
/spec/models/spree/store_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe Spree::Store do
4 | describe 'before_create :build_default_configuration' do
5 | context 'when a braintree_configuration record already exists' do
6 | it 'does not overwrite it' do
7 | store = build(:store)
8 | custom_braintree_configuration = store.build_braintree_configuration
9 | store.save!
10 | expect(store.braintree_configuration).to be custom_braintree_configuration
11 | end
12 | end
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/bin/rails-engine:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # This command will automatically be run when you run "rails" with Rails gems
3 | # installed from the root of your application.
4 |
5 | ENGINE_ROOT = File.expand_path('..', __dir__)
6 | ENGINE_PATH = File.expand_path('../lib/solidus_paypal_braintree/engine', __dir__)
7 |
8 | # Set up gems listed in the Gemfile.
9 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
10 | require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
11 |
12 | require 'rails/all'
13 | require 'rails/engine/commands'
14 |
--------------------------------------------------------------------------------
/spec/helpers/solidus_paypal_braintree/braintree_admin_helper_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | RSpec.describe SolidusBraintree::BraintreeAdminHelper do
4 | describe '#braintree_transaction_link' do
5 | subject { helper.braintree_transaction_link(payment) }
6 |
7 | let(:payment_method) { create_gateway }
8 | let(:payment) do
9 | instance_double(Spree::Payment, payment_method: payment_method, response_code: 'abcde')
10 | end
11 | let(:merchant_id) { payment_method.preferences[:merchant_id] }
12 |
13 | it 'generates a link to Braintree admin' do
14 | expect(subject).to eq "abcde" # rubocop:disable Layout/LineLength
15 | end
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | version: 2.1
2 |
3 | orbs:
4 | # Required for feature specs.
5 | browser-tools: circleci/browser-tools@1.1
6 |
7 | # Always take the latest version of the orb, this allows us to
8 | # run specs against Solidus supported versions only without the need
9 | # to change this configuration every time a Solidus version is released
10 | # or goes EOL.
11 | solidusio_extensions: solidusio/extensions@volatile
12 |
13 | jobs:
14 | run-specs-with-postgres:
15 | executor: solidusio_extensions/postgres
16 | steps:
17 | - browser-tools/install-browser-tools
18 | - solidusio_extensions/run-tests
19 | run-specs-with-mysql:
20 | executor: solidusio_extensions/mysql
21 | steps:
22 | - browser-tools/install-browser-tools
23 | - solidusio_extensions/run-tests
24 |
25 | workflows:
26 | "Run specs on supported Solidus versions":
27 | jobs:
28 | - run-specs-with-postgres
29 | - run-specs-with-mysql
30 |
--------------------------------------------------------------------------------
/spec/features/backend/configuration_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | RSpec.describe "viewing the configuration interface" do
4 | stub_authorization!
5 |
6 | # Regression to ensure this page still renders on old versions of solidus
7 | it "doesn't raise any errors due to unavailable route helpers" do
8 | visit "/solidus_braintree/configurations/list"
9 | expect(page).to have_content("Braintree Configurations")
10 | end
11 |
12 | # Regression to ensure this page renders on Solidus 2.4
13 | it "doesn't raise any errors due to unavailable preference field partial" do
14 | Rails.application.config.spree.payment_methods << SolidusBraintree::Gateway
15 | Spree::PaymentMethod.create!(
16 | type: 'SolidusBraintree::Gateway',
17 | name: 'Braintree Payments'
18 | )
19 | visit '/admin/payment_methods'
20 | page.find('a[title="Edit"]').click
21 | expect(page).to have_field 'Name', with: 'Braintree Payments'
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/spec/support/gateway_helpers.rb:
--------------------------------------------------------------------------------
1 | module SolidusBraintree
2 | module GatewayHelpers
3 | def new_gateway(opts = {})
4 | SolidusBraintree::Gateway.new({
5 | name: "Braintree",
6 | preferences: {
7 | environment: 'sandbox',
8 | public_key: ENV.fetch('BRAINTREE_PUBLIC_KEY', 'dummy_public_key'),
9 | private_key: ENV.fetch('BRAINTREE_PRIVATE_KEY', 'dummy_private_key'),
10 | merchant_id: ENV.fetch('BRAINTREE_MERCHANT_ID', 'dummy_merchant_id'),
11 | merchant_currency_map: {
12 | 'EUR' => 'stembolt_EUR'
13 | },
14 | paypal_payee_email_map: {
15 | 'EUR' => ENV.fetch('BRAINTREE_PAYPAL_PAYEE_EMAIL', 'paypal+europe@example.com')
16 | }
17 | }
18 | }.merge(opts))
19 | end
20 |
21 | def create_gateway(opts = {})
22 | new_gateway(opts).tap(&:save!)
23 | end
24 | end
25 | end
26 |
27 | RSpec.configure do |config|
28 | config.include SolidusBraintree::GatewayHelpers
29 | end
30 |
--------------------------------------------------------------------------------
/spec/support/order_ready_for_payment.rb:
--------------------------------------------------------------------------------
1 | shared_context 'when order is ready for payment' do
2 | let!(:country) { create :country }
3 |
4 | let(:user) { create :user }
5 | let(:address) { create :address, zipcode: "90210", lastname: "Doe", country: country }
6 |
7 | before do
8 | create :shipping_method, cost: 5
9 | end
10 |
11 | let(:gateway) do
12 | new_gateway(auto_capture: true)
13 | end
14 |
15 | let(:order) do
16 | order = Spree::Order.create!(
17 | line_items: [create(:line_item, price: 50)],
18 | email: 'test@example.com',
19 | bill_address: address,
20 | ship_address: address,
21 | user: user
22 | )
23 | order.recalculate
24 |
25 | expect(order.state).to eq "cart"
26 |
27 | # push through cart, address and delivery
28 | # its sadly unsafe to use any reasonable factory here accross
29 | # supported solidus versions
30 | order.next!
31 | order.next!
32 | order.next!
33 |
34 | expect(order.state).to eq "payment"
35 | order
36 | end
37 | end
38 |
--------------------------------------------------------------------------------
/spec/requests/spree/api/orders_controller_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe Spree::Api::OrdersController, type: :request do
4 | stub_authorization!
5 |
6 | describe 'get show' do
7 | let(:gateway) { create_gateway }
8 | let(:order) { create(:order_with_line_items) }
9 | let(:source) do
10 | SolidusBraintree::Source.new(
11 | nonce: 'fake-valid-nonce',
12 | user: order.user,
13 | payment_type: SolidusBraintree::Source::PAYPAL,
14 | payment_method: gateway
15 | )
16 | end
17 |
18 | context 'when using braintree as the payment' do
19 | before do
20 | allow_any_instance_of(Spree::Payment).to receive(:create_payment_profile).and_return(true)
21 |
22 | order.payments.create!(
23 | payment_method: gateway,
24 | source: source,
25 | amount: 55
26 | )
27 | end
28 |
29 | it "can be rendered correctly" do
30 | get "/api/orders/#{order.number}"
31 |
32 | expect(response).to have_http_status :ok
33 | end
34 | end
35 | end
36 | end
37 |
--------------------------------------------------------------------------------
/spec/spec_helper.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | # Configure Rails Environment
4 | ENV['RAILS_ENV'] = 'test'
5 |
6 | # Run Coverage report
7 | require 'solidus_dev_support/rspec/coverage'
8 | require 'rails-controller-testing'
9 |
10 | # Create the dummy app if it's still missing.
11 | dummy_env = "#{__dir__}/dummy/config/environment.rb"
12 | system 'bin/rake extension:test_app' unless File.exist? dummy_env
13 | require dummy_env
14 |
15 | # Requires factories and other useful helpers defined in spree_core.
16 | require 'solidus_dev_support/rspec/feature_helper'
17 |
18 | # Requires supporting ruby files with custom matchers and macros, etc,
19 | # in spec/support/ and its subdirectories.
20 | Dir["#{__dir__}/support/**/*.rb"].sort.each { |f| require f }
21 |
22 | # Requires factories defined in lib/solidus_braintree/testing_support/factories.rb
23 | SolidusDevSupport::TestingSupport::Factories.load_for(SolidusBraintree::Engine)
24 |
25 | RSpec.configure do |config|
26 | config.infer_spec_type_from_file_location!
27 | config.use_transactional_fixtures = false
28 |
29 | if Spree.solidus_gem_version < Gem::Version.new('2.11')
30 | config.extend Spree::TestingSupport::AuthorizationHelpers::Request, type: :system
31 | end
32 | end
33 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2016-2020 Stembolt and other contributors
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without modification,
5 | are permitted provided that the following conditions are met:
6 |
7 | * Redistributions of source code must retain the above copyright notice,
8 | this list of conditions and the following disclaimer.
9 | * Redistributions in binary form must reproduce the above copyright notice,
10 | this list of conditions and the following disclaimer in the documentation
11 | and/or other materials provided with the distribution.
12 | * Neither the name Solidus nor the names of its contributors may be used to
13 | endorse or promote products derived from this software without specific
14 | prior written permission.
15 |
16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 |
--------------------------------------------------------------------------------
/spec/support/vcr.rb:
--------------------------------------------------------------------------------
1 | require 'vcr'
2 | require 'webmock'
3 |
4 | VCR.configure do |c|
5 | c.cassette_library_dir = "spec/fixtures/cassettes"
6 | c.hook_into :webmock
7 | c.configure_rspec_metadata!
8 | c.default_cassette_options = {
9 | match_requests_on: [:method, :uri, :body]
10 | }
11 | c.allow_http_connections_when_no_cassette = false
12 | c.ignore_localhost = true
13 | c.ignore_hosts 'chromedriver.storage.googleapis.com'
14 |
15 | # client token used for the fronted JS lib cannot be mocked:
16 | # it contains a cryptographically signed string containing the merchant id
17 | # that's sent back to braintree's server by the JS lib
18 | c.ignore_request do |request|
19 | !(request.uri =~ %r{/merchants/\w+/client_token\z}).nil?
20 | end
21 |
22 | # match a request to Braintree sandbox APIs by ignoring the merchant ID
23 | # in the request URI
24 | c.register_request_matcher :braintree_uri do |request1, request2|
25 | extract_url_resource = lambda do |uri|
26 | uri_match_pattern =
27 | %r{\Ahttps://api\.sandbox\.braintreegateway\.com/merchants/\w+(/.*)\z}
28 |
29 | if match = uri.match(uri_match_pattern)
30 | match.captures.first
31 | end
32 | end
33 | r1_resource = extract_url_resource.call(request1.uri)
34 | r2_resource = extract_url_resource.call(request2.uri)
35 |
36 | !r1_resource.nil? && r1_resource == r2_resource
37 | end
38 |
39 | # https://github.com/titusfortner/webdrivers/wiki/Using-with-VCR-or-WebMock
40 | driver_hosts = Webdrivers::Common.subclasses.map { |driver| URI(driver.base_url).host }
41 | c.ignore_hosts(*driver_hosts)
42 | end
43 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | source 'https://rubygems.org'
4 | git_source(:github) { |repo| "https://github.com/#{repo}.git" }
5 |
6 | branch = ENV.fetch('SOLIDUS_BRANCH', 'master')
7 | gem 'solidus', github: 'solidusio/solidus', branch: branch
8 |
9 | # The solidus_frontend gem has been pulled out since v3.2
10 | gem 'solidus_frontend', github: 'solidusio/solidus_frontend' if branch == 'master'
11 | gem 'solidus_frontend' if branch >= 'v3.2' # rubocop:disable Bundler/DuplicatedGem
12 |
13 | # Needed to help Bundler figure out how to resolve dependencies,
14 | # otherwise it takes forever to resolve them.
15 | # See https://github.com/bundler/bundler/issues/6677
16 | gem 'rails', '>0.a'
17 |
18 | # Provides basic authentication functionality for testing parts of your engine
19 | gem 'solidus_auth_devise'
20 |
21 | case ENV.fetch('DB', nil)
22 | when 'mysql'
23 | gem 'mysql2'
24 | when 'postgresql'
25 | gem 'pg'
26 | else
27 | gem 'sqlite3'
28 | end
29 |
30 | # While we still support Ruby < 3 we need to workaround a limitation in
31 | # the 'async' gem that relies on the latest ruby, since RubyGems doesn't
32 | # resolve gems based on the required ruby version.
33 | gem 'async', '< 3' if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('3')
34 |
35 | gemspec
36 |
37 | # Use a local Gemfile to include development dependencies that might not be
38 | # relevant for the project or for other contributors, e.g. pry-byebug.
39 | #
40 | # We use `send` instead of calling `eval_gemfile` to work around an issue with
41 | # how Dependabot parses projects: https://github.com/dependabot/dependabot-core/issues/1658.
42 | send(:eval_gemfile, 'Gemfile-local') if File.exist? 'Gemfile-local'
43 |
--------------------------------------------------------------------------------
/spec/fixtures/cassettes/gateway/cancel/missing.yml:
--------------------------------------------------------------------------------
1 | ---
2 | http_interactions:
3 | - request:
4 | method: get
5 | uri: https://api.sandbox.braintreegateway.com/merchants/7rdg92j7bm7fk5h3/transactions/fake_transaction_id
6 | body:
7 | encoding: US-ASCII
8 | string: ''
9 | headers:
10 | Accept-Encoding:
11 | - gzip
12 | Accept:
13 | - application/xml
14 | User-Agent:
15 | - Braintree Ruby Gem 2.98.0
16 | X-Apiversion:
17 | - '5'
18 | Content-Type:
19 | - application/xml
20 | Authorization:
21 | - Basic bXdqa2t4d2NwMzJja2huZjphOTI5OGY0M2IzMGM2OTlkYjMwNzJjYzRhMDBmN2Y0OQ==
22 | response:
23 | status:
24 | code: 404
25 | message: Not Found
26 | headers:
27 | Date:
28 | - Fri, 13 Sep 2019 14:27:48 GMT
29 | Content-Type:
30 | - application/xml; charset=utf-8
31 | Transfer-Encoding:
32 | - chunked
33 | X-Frame-Options:
34 | - SAMEORIGIN
35 | X-Xss-Protection:
36 | - 1; mode=block
37 | X-Content-Type-Options:
38 | - nosniff
39 | X-Authentication:
40 | - basic_auth
41 | Vary:
42 | - Accept-Encoding
43 | Content-Encoding:
44 | - gzip
45 | Cache-Control:
46 | - no-cache
47 | X-Runtime:
48 | - '0.030577'
49 | X-Request-Id:
50 | - 01-1568384868.074-92.223.152.178-12971830
51 | Content-Security-Policy:
52 | - frame-ancestors 'self'
53 | X-Broxyid:
54 | - 01-1568384868.074-92.223.152.178-12971830
55 | Strict-Transport-Security:
56 | - max-age=31536000; includeSubDomains
57 | body:
58 | encoding: ASCII-8BIT
59 | string: !binary |-
60 | H4sIAGSne10AAwAAAP//AwAAAAAAAAAAAA==
61 | http_version:
62 | recorded_at: Fri, 13 Sep 2019 14:27:48 GMT
63 | recorded_with: VCR 5.0.0
64 |
--------------------------------------------------------------------------------
/spec/fixtures/views/spree/orders/edit.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 | <% @body_id = 'cart' %>
4 |
5 |
<%= t('spree.shopping_cart') %>
6 |
7 | <% if @order.line_items.empty? %>
8 |
9 |
10 |
<%= t('spree.your_cart_is_empty') %>
11 |
<%= link_to t('spree.continue_shopping'), products_path, class: 'button continue' %>
12 |
13 |
14 | <% else %>
15 |
16 |
17 | <%= form_for @order, url: update_cart_path, html: {id: 'update-cart'} do |order_form| %>
18 |
19 |
20 |
21 | <%= render 'form', order_form: order_form %>
22 |
23 |
24 |
25 | <%= order_form.text_field :coupon_code, size: 10, placeholder: t('spree.coupon_code') %>
26 | <%= button_tag class: 'primary', id: 'update-button' do %>
27 | <%= t('spree.update') %>
28 | <% end %>
29 | <%= button_tag class: 'button checkout primary', id: 'checkout-link', name: 'checkout' do %>
30 | <%= t('spree.checkout') %>
31 | <% end %>
32 |
33 |
34 |
35 | <% end %>
36 |
37 |
38 |
39 | <%= form_tag empty_cart_path, method: :put do %>
40 |
41 | <%= submit_tag t('spree.empty_cart'), class: 'button gray' %>
42 | <%= t('spree.or') %>
43 | <%= link_to t('spree.continue_shopping'), products_path, class: 'continue button gray' %>
44 |
45 | <% end %>
46 |
47 |
48 | <%= render "spree/shared/paypal_cart_button" %>
49 | <% end %>
50 |
51 |
--------------------------------------------------------------------------------
/solidus_paypal_braintree.gemspec:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'lib/solidus_paypal_braintree/version'
4 |
5 | Gem::Specification.new do |spec|
6 | spec.name = 'solidus_paypal_braintree'
7 | spec.version = SolidusPaypalBraintree::VERSION
8 | spec.authors = ['Stembolt']
9 | spec.email = 'braintree+gemfile@stembolt.com'
10 |
11 | spec.summary = 'Officially supported Paypal/Braintree extension'
12 | spec.description = 'Uses the javascript API for seamless braintree payments'
13 | spec.homepage = 'https://github.com/solidusio/solidus_paypal_braintree'
14 | spec.license = 'BSD-3-Clause'
15 |
16 | spec.metadata['homepage_uri'] = spec.homepage
17 | spec.metadata['source_code_uri'] = 'https://github.com/solidusio/solidus_paypal_braintree'
18 | spec.metadata['changelog_uri'] = 'https://github.com/solidusio/solidus_paypal_braintree/blob/master/CHANGELOG.md'
19 |
20 | spec.required_ruby_version = Gem::Requirement.new('>= 2.5', '< 4')
21 |
22 | # Specify which files should be added to the gem when it is released.
23 | # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
24 | files = Dir.chdir(__dir__) { `git ls-files -z`.split("\x0") }
25 |
26 | spec.files = files.grep_v(%r{^(test|spec|features)/})
27 | spec.test_files = files.grep(%r{^(test|spec|features)/})
28 | spec.bindir = "exe"
29 | spec.executables = files.grep(%r{^exe/}) { |f| File.basename(f) }
30 | spec.require_paths = ["lib"]
31 |
32 | spec.add_dependency 'solidus_braintree', '~> 2.0'
33 | spec.post_install_message = %q{
34 | ACTION REQUIRED: This extension has been renamed to solidus_braintree.
35 |
36 | To upgrade to the new name, follow the instructions here:
37 | https://github.com/solidusio/solidus_braintree/wiki/Upgrading-from-SolidusPaypalBraintree-To-SolidusBraintree
38 | }
39 |
40 | spec.add_development_dependency 'rails-controller-testing'
41 | spec.add_development_dependency 'solidus_dev_support', '~> 2.5'
42 | spec.add_development_dependency 'vcr'
43 | spec.add_development_dependency 'webmock'
44 | end
45 |
--------------------------------------------------------------------------------
/.rubocop.yml:
--------------------------------------------------------------------------------
1 | require:
2 | - solidus_dev_support/rubocop
3 |
4 | AllCops:
5 | NewCops: disable
6 |
7 | Layout/FirstArgumentIndentation:
8 | EnforcedStyle: consistent
9 |
10 | Layout/FirstArrayElementIndentation:
11 | EnforcedStyle: consistent
12 |
13 | Layout/FirstHashElementIndentation:
14 | EnforcedStyle: consistent
15 |
16 | Layout/MultilineMethodCallIndentation:
17 | EnforcedStyle: indented
18 |
19 | Naming/VariableNumber:
20 | Enabled: false
21 |
22 | # We use this extensively, the alternatives are not viable or desirable.
23 | RSpec/AnyInstance:
24 | Enabled: false
25 |
26 | # No need to make the code more complex for no real gain.
27 | RSpec/MessageSpies:
28 | Enabled: false
29 |
30 | # Let's consider legitimate to have multiple expectations within an example.
31 | RSpec/MultipleExpectations:
32 | Enabled: false
33 |
34 | # Allow to use subject as is, no big deal.
35 | RSpec/NamedSubject:
36 | Enabled: false
37 |
38 | # Let's set this to some really exagerate value.
39 | RSpec/NestedGroups:
40 | Max: 8
41 |
42 | # We don't use the FactoryBot mixin
43 | RSpec/FactoryBot/SyntaxMethods:
44 | Enabled: false
45 |
46 | RSpec/VerifiedDoubles:
47 | # Sometimes you really need an "anything" double
48 | IgnoreSymbolicNames: true
49 |
50 | Style/FrozenStringLiteralComment:
51 | Exclude:
52 | - spec/**/*
53 | - db/migrate/**/*
54 | - bin/**/*
55 |
56 | Style/ExplicitBlockArgument:
57 | Exclude:
58 | - lib/solidus_paypal_braintree/request_protection.rb
59 |
60 | Rails/SkipsModelValidations:
61 | Exclude:
62 | - db/migrate/**/*
63 |
64 | Rails/ReflectionClassName:
65 | Exclude:
66 | - app/models/solidus_paypal_braintree/customer.rb
67 | - app/models/solidus_paypal_braintree/source.rb
68 |
69 | RSpec/MultipleMemoizedHelpers:
70 | Exclude:
71 | - spec/models/solidus_paypal_braintree/transaction_import_spec.rb
72 | - spec/models/solidus_paypal_braintree/response_spec.rb
73 | - spec/models/solidus_paypal_braintree/gateway_spec.rb
74 | - spec/controllers/solidus_paypal_braintree/client_tokens_controller_spec.rb
75 | - spec/features/frontend/braintree_credit_card_checkout_spec.rb
76 |
--------------------------------------------------------------------------------
/spec/models/solidus_paypal_braintree/address_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | RSpec.describe SolidusBraintree::Address do
4 | describe "::split_name" do
5 | subject { described_class.split_name(name) }
6 |
7 | context "with a one word name" do
8 | let(:name) { "Bruce" }
9 |
10 | it "correctly splits" do
11 | expect(subject).to eq ["Bruce"]
12 | end
13 | end
14 |
15 | context "with a multi word name" do
16 | let(:name) { "Bruce Wayne The Batman" }
17 |
18 | it "correctly splits" do
19 | expect(subject).to eq ["Bruce", "Wayne The Batman"]
20 | end
21 | end
22 | end
23 |
24 | describe '#to_json' do
25 | subject(:address_json) { JSON.parse(described_class.new(spree_address).to_json) }
26 |
27 | let(:german_address) { create(:address, country_iso: 'DE', state: nil) } # Does not require states
28 | let(:us_address) { create(:address, country_iso: 'US') } # Requires states
29 | let(:spree_address) { us_address }
30 |
31 | before do
32 | create(:country, iso: 'DE', states_required: false)
33 | create(:country, iso: 'US', states_required: true)
34 | end
35 |
36 | it 'has all the required keys' do
37 | expect(address_json.keys).to contain_exactly(
38 | 'line1',
39 | 'line2',
40 | 'city',
41 | 'postalCode',
42 | 'countryCode',
43 | 'recipientName',
44 | 'state',
45 | 'phone'
46 | )
47 | end
48 |
49 | context 'with a country that does not require state' do
50 | let(:spree_address) { german_address }
51 |
52 | it { is_expected.not_to have_key('state') }
53 | end
54 |
55 | context 'with states turned off globally' do
56 | before do
57 | allow(::Spree::Config).to receive(:address_requires_state).and_return(false)
58 | end
59 |
60 | context 'with a country that requires states' do
61 | it { is_expected.not_to have_key('state') }
62 | end
63 |
64 | context 'with a country that does not require state' do
65 | let(:spree_address) { german_address }
66 |
67 | it { is_expected.not_to have_key('state') }
68 | end
69 | end
70 | end
71 | end
72 |
--------------------------------------------------------------------------------
/spec/controllers/solidus_paypal_braintree/client_tokens_controller_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe SolidusBraintree::ClientTokensController do
4 | routes { SolidusBraintree::Engine.routes }
5 |
6 | cassette_options = { cassette_name: "braintree/token" }
7 | describe "POST create", vcr: cassette_options do
8 | let!(:gateway) { create_gateway }
9 | let(:user) { create(:user) }
10 | let(:json) { JSON.parse(response.body) }
11 |
12 | before { user.generate_spree_api_key! }
13 |
14 | context 'without a payment method id' do
15 | subject(:response) do
16 | post :create, params: { token: user.spree_api_key }
17 | end
18 |
19 | it "returns a client token", aggregate_failures: true do
20 | expect(response).to have_http_status(:success)
21 | expect(response.content_type).to include 'application/json'
22 | expect(json["client_token"]).to be_present
23 | expect(json["client_token"]).to be_a String
24 | expect(json["payment_method_id"]).to eq gateway.id
25 | end
26 |
27 | context "when there's two gateway's for different stores" do
28 | let!(:store1) { create(:store, code: 'store_1') }
29 | let!(:store2) { create(:store, code: 'store_2') }
30 | let!(:gateway_for_store1) { create_gateway.tap{ |gw| store1.payment_methods << gw } }
31 | let!(:gateway_for_store2) { create_gateway.tap{ |gw| store2.payment_methods << gw } }
32 |
33 | it "returns the correct gateway for store1" do
34 | allow_any_instance_of(described_class).to receive(:current_store).and_return store1
35 | expect(json["payment_method_id"]).to eq gateway_for_store1.id
36 | end
37 |
38 | it "returns the correct gateway for store2" do
39 | allow_any_instance_of(described_class).to receive(:current_store).and_return store2
40 | expect(json["payment_method_id"]).to eq gateway_for_store2.id
41 | end
42 | end
43 | end
44 |
45 | context 'with a payment method id' do
46 | subject(:response) do
47 | post :create, params: { token: user.spree_api_key, payment_method_id: gateway.id }
48 | end
49 |
50 | it 'uses the selected gateway' do
51 | expect(json["payment_method_id"]).to eq gateway.id
52 | end
53 | end
54 | end
55 | end
56 |
--------------------------------------------------------------------------------
/spec/controllers/solidus_paypal_braintree/configurations_controller_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe SolidusBraintree::ConfigurationsController, type: :controller do
4 | routes { SolidusBraintree::Engine.routes }
5 |
6 | let!(:store_1) { create :store }
7 | let!(:store_2) { create :store }
8 |
9 | stub_authorization!
10 |
11 | describe "GET #list" do
12 | subject { get :list }
13 |
14 | it "assigns all store's configurations as @configurations" do
15 | subject
16 | expect(assigns(:configurations)).
17 | to eq [store_1.braintree_configuration, store_2.braintree_configuration]
18 | end
19 |
20 | it "renders the correct view" do
21 | expect(subject).to render_template :list
22 | end
23 | end
24 |
25 | describe "POST #update" do
26 | subject { post :update, params: configurations_params }
27 |
28 | let(:paypal_button_color) { 'blue' }
29 | let(:configurations_params) do
30 | {
31 | configurations: {
32 | configuration_fields: {
33 | store_1.braintree_configuration.id.to_s => { paypal: true, apple_pay: true },
34 | store_2.braintree_configuration.id.to_s => {
35 | paypal: true,
36 | apple_pay: false,
37 | preferred_paypal_button_color: paypal_button_color
38 | }
39 | }
40 | }
41 | }
42 | end
43 |
44 | context "with valid parameters" do
45 | it "updates the configuration" do
46 | expect { subject }.to change { store_1.braintree_configuration.reload.paypal }.
47 | from(false).to(true)
48 | end
49 |
50 | it "displays a success message to the user" do
51 | subject
52 | expect(flash[:success]).to eq "Successfully updated Braintree configurations."
53 | end
54 |
55 | it "displays all configurations" do
56 | expect(subject).to redirect_to action: :list
57 | end
58 | end
59 |
60 | context "with invalid parameters" do
61 | let(:paypal_button_color) { 'invalid-color' }
62 |
63 | it "displays an error message to the user" do
64 | subject
65 | expect(flash[:error]).to eq "An error occurred while updating Braintree configurations."
66 | end
67 |
68 | it "returns the user to the edit page" do
69 | expect(subject).to redirect_to action: :list
70 | end
71 | end
72 | end
73 | end
74 |
--------------------------------------------------------------------------------
/spec/models/solidus_paypal_braintree/transaction_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe SolidusBraintree::Transaction do
4 | describe "#valid?" do
5 | subject { transaction.valid? }
6 |
7 | let(:valid_attributes) do
8 | {
9 | nonce: 'abcde-fghjkl-lmnop',
10 | payment_method: SolidusBraintree::Gateway.new,
11 | payment_type: 'ApplePayCard',
12 | email: "test@example.com"
13 | }
14 | end
15 | let(:valid_address_attributes) do
16 | {
17 | address_attributes: {
18 | name: "Bruce Wayne",
19 | address_line_1: "42 Spruce Lane",
20 | city: "Gotham",
21 | zip: "98201",
22 | state_code: "WA",
23 | country_code: "US"
24 | }
25 | }
26 | end
27 | let(:transaction) { described_class.new(valid_attributes) }
28 |
29 | before do
30 | create(:country, iso: "US")
31 | create(:state, state_code: "WA")
32 | end
33 |
34 | it { is_expected.to be true }
35 |
36 | context 'without nonce' do
37 | let(:valid_attributes) { super().except(:nonce) }
38 |
39 | it { is_expected.to be false }
40 | end
41 |
42 | context 'without gateway' do
43 | let(:valid_attributes) { super().except(:payment_method) }
44 |
45 | it { is_expected.to be false }
46 | end
47 |
48 | context 'with bad gateway' do
49 | let(:valid_attributes) { super().merge(payment_method: Spree::PaymentMethod.new) }
50 |
51 | it { is_expected.to be false }
52 | end
53 |
54 | context 'without payment_type' do
55 | let(:valid_attributes) { super().except(:payment_type) }
56 |
57 | it { is_expected.to be false }
58 | end
59 |
60 | context 'without email' do
61 | let(:valid_attributes) { super().except(:email) }
62 |
63 | it { is_expected.to be false }
64 | end
65 |
66 | context "with valid address" do
67 | let(:valid_attributes) { super().merge(valid_address_attributes) }
68 |
69 | it { is_expected.to be true }
70 | end
71 |
72 | context "with invalid address" do
73 | let(:valid_attributes) { super().merge(valid_address_attributes) }
74 |
75 | before { valid_address_attributes[:address_attributes][:zip] = nil }
76 |
77 | it { is_expected.to be false }
78 |
79 | it "sets useful error messages" do
80 | transaction.valid?
81 | expect(transaction.errors.full_messages).
82 | to eq ["Address Zip can't be blank"]
83 | end
84 | end
85 | end
86 | end
87 |
--------------------------------------------------------------------------------
/spec/helpers/solidus_paypal_braintree/braintree_checkout_helper_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | RSpec.describe SolidusBraintree::BraintreeCheckoutHelper do
4 | let!(:store) { create :store }
5 | let(:braintree_configuration) { {} }
6 |
7 | before do
8 | store.braintree_configuration.update(braintree_configuration)
9 | end
10 |
11 | describe '#venmo_button_style' do
12 | subject { helper.venmo_button_style(store) }
13 |
14 | context 'when the venmo button is white and has a width of 280' do
15 | let(:braintree_configuration) { { preferred_venmo_button_width: '280', preferred_venmo_button_color: 'white' } }
16 |
17 | it 'returns a hash of the width and color' do
18 | expect(subject).to eq({ width: '280', color: 'white' })
19 | end
20 | end
21 |
22 | context 'when the venmo button is blue and has a width of 375' do
23 | let(:braintree_configuration) { { preferred_venmo_button_width: '375', preferred_venmo_button_color: 'blue' } }
24 |
25 | it 'returns a hash of the width and color' do
26 | expect(subject).to eq({ width: '375', color: 'blue' })
27 | end
28 | end
29 | end
30 |
31 | describe '#venmo_button_width' do
32 | subject { helper.venmo_button_asset_url(style, active: active) }
33 |
34 | context 'when the given style color is white and width is 280, and the given active is false' do
35 | let(:style) { { width: '280', color: 'white' } }
36 | let(:active) { false }
37 |
38 | it 'returns the correct url' do
39 | expect(subject).to match(%r[\A/assets/solidus_braintree/venmo/venmo_white_button_280x48-.+\.svg])
40 | end
41 | end
42 |
43 | context 'when the given style color is white and width is 280, and the given active is true' do
44 | let(:style) { { width: '280', color: 'white' } }
45 | let(:active) { true }
46 |
47 | it 'returns the correct url' do
48 | expect(subject).to match(%r[\A/assets/solidus_braintree/venmo/venmo_active_white_button_280x48-.+\.svg])
49 | end
50 | end
51 |
52 | context 'when the given style color is blue and width is 320, and the given active is false' do
53 | let(:style) { { width: '320', color: 'blue' } }
54 | let(:active) { false }
55 |
56 | it 'returns the correct url' do
57 | expect(subject).to match(%r[\A/assets/solidus_braintree/venmo/venmo_blue_button_320x48-.+\.svg])
58 | end
59 | end
60 |
61 | context 'when the given style color is blue and width is 320, and the given active is true' do
62 | let(:style) { { width: '320', color: 'blue' } }
63 | let(:active) { true }
64 |
65 | it 'returns the correct url' do
66 | expect(subject).to match(%r[\A/assets/solidus_braintree/venmo/venmo_active_blue_button_320x48-.+\.svg])
67 | end
68 | end
69 | end
70 | end
71 |
--------------------------------------------------------------------------------
/spec/fixtures/cassettes/checkout/update.yml:
--------------------------------------------------------------------------------
1 | ---
2 | http_interactions:
3 | - request:
4 | method: post
5 | uri: https://api.sandbox.braintreegateway.com/merchants/7rdg92j7bm7fk5h3/customers
6 | body:
7 | encoding: UTF-8
8 | string: |
9 |
10 |
11 | fake-paypal-billing-agreement-nonce
12 |
13 | headers:
14 | Accept-Encoding:
15 | - gzip
16 | Accept:
17 | - application/xml
18 | User-Agent:
19 | - Braintree Ruby Gem 2.98.0
20 | X-Apiversion:
21 | - '5'
22 | Content-Type:
23 | - application/xml
24 | Authorization:
25 | - Basic bXdqa2t4d2NwMzJja2huZjphOTI5OGY0M2IzMGM2OTlkYjMwNzJjYzRhMDBmN2Y0OQ==
26 | response:
27 | status:
28 | code: 201
29 | message: Created
30 | headers:
31 | Date:
32 | - Fri, 13 Sep 2019 14:23:31 GMT
33 | Content-Type:
34 | - application/xml; charset=utf-8
35 | Transfer-Encoding:
36 | - chunked
37 | X-Frame-Options:
38 | - SAMEORIGIN
39 | X-Xss-Protection:
40 | - 1; mode=block
41 | X-Content-Type-Options:
42 | - nosniff
43 | X-Authentication:
44 | - basic_auth
45 | X-User:
46 | - 3v249hqtptsg744y
47 | Vary:
48 | - Accept-Encoding
49 | Content-Encoding:
50 | - gzip
51 | Etag:
52 | - W/"1def9e79aa7d52374b638f665c50d5ef"
53 | Cache-Control:
54 | - max-age=0, private, must-revalidate
55 | X-Runtime:
56 | - '0.296888'
57 | X-Request-Id:
58 | - 01-1568384611.188-92.223.152.178-12918506
59 | Content-Security-Policy:
60 | - frame-ancestors 'self'
61 | X-Broxyid:
62 | - 01-1568384611.188-92.223.152.178-12918506
63 | Strict-Transport-Security:
64 | - max-age=31536000; includeSubDomains
65 | body:
66 | encoding: ASCII-8BIT
67 | string: !binary |-
68 | H4sIAGOme10AA6RUTW/iMBC991eg3I0JH6JBIexKFUh7aC9sd9sLmsST4OLYke3Q0l+/TkKgJfSw6tHz3ny9mXG4eMtFb4/acCXnnt8feD2UiWJcZnPv93pJbr1FdBMmpbEqRx3d9HohZ9FtMJxMg2AwDql7VUYHJluQlrj3VLMsGL5M43ya7ibbUUg/ohU75dpYIiHHnuRi7lldokdrSMBXSKLyAuShY8ccuOhYi62S3RgpvHVsrxgbbq/k0wgWGQHbs4cC5x5zT8tz9KLhwA/IICD+aO2PZ8PRbOQ/h/TsUPuXBfs//7NDk78WnaQcBTNNSZlQMYhKxafR4ztbBfb576/04W53uF8nk4f1z0FIz5xjE4xbkoBm5lgGaA2HViU4FI4MSaJKaT8zKkKH0hidOeZCuC0hkGnEHJvZNtzNEducsA1nIb3q0Yb7pthNjOOWks8b+tHcUhmmUIo2V6yUQJBeVE0/pEfwRK4XLHoBiX2m8EfTZN+tY0gbqCWepU9Wy0n857FkK1+w1Xb/vAxek+Wtf3/H9NNIXUypduY5ZEhKLaKttYWZUQrGoDX9WAOX1mmWuYZf4VBlpq6IWtgc7VaxjVCZosfCCpktUO65VrKizA1IFqs3d6qnDG1OU8Ym0byw7vyvrEfNsWqHMpqMp7vkPaTNq8W+ueJN34ZUf4NEp4bkllf45VxSEMYN5hr1FMd1X8/48o4/gjJVV2HBc16VVRokSrOv42jcOwHqhjtwSLuncmkztREY0+iG25H8vKzRzT8AAAD//wMA+PYWapwFAAA=
69 | http_version:
70 | recorded_at: Fri, 13 Sep 2019 14:23:32 GMT
71 | recorded_with: VCR 5.0.0
72 |
--------------------------------------------------------------------------------
/bin/sandbox:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -e
4 | if [ -n "$DEBUG" ]
5 | then
6 | set -x
7 | fi
8 |
9 | case "$DB" in
10 | postgres|postgresql)
11 | RAILSDB="postgresql"
12 | ;;
13 | mysql)
14 | RAILSDB="mysql"
15 | ;;
16 | sqlite3|sqlite)
17 | RAILSDB="sqlite3"
18 | ;;
19 | '')
20 | echo "~~> Use 'export DB=[postgres|mysql|sqlite]' to control the DB adapter"
21 | RAILSDB="sqlite3"
22 | ;;
23 | *)
24 | echo "Invalid value specified for the Solidus sandbox: DB=\"$DB\"."
25 | echo "Please use 'postgres', 'mysql', or 'sqlite' instead."
26 | exit 1
27 | ;;
28 | esac
29 | echo "~~> Using $RAILSDB as the database engine"
30 |
31 | if [ -z "$SOLIDUS_BRANCH" ]
32 | then
33 | echo "~~> Use 'export SOLIDUS_BRANCH=[master|v3.2|...]' to control the Solidus branch"
34 | SOLIDUS_BRANCH="master"
35 | fi
36 | echo "~~> Using branch $SOLIDUS_BRANCH of solidus"
37 |
38 | if [ -z "$SOLIDUS_FRONTEND" ]
39 | then
40 | echo "~~> Use 'export SOLIDUS_FRONTEND=[solidus_frontend|solidus_starter_frontend]' to control the Solidus frontend"
41 | SOLIDUS_FRONTEND="solidus_frontend"
42 | fi
43 | echo "~~> Using branch $SOLIDUS_FRONTEND as the solidus frontend"
44 |
45 | extension_name="solidus_paypal_braintree"
46 |
47 | # Stay away from the bundler env of the containing extension.
48 | function unbundled {
49 | ruby -rbundler -e'b = proc {system *ARGV}; Bundler.respond_to?(:with_unbundled_env) ? Bundler.with_unbundled_env(&b) : Bundler.with_clean_env(&b)' -- $@
50 | }
51 |
52 | rm -rf ./sandbox
53 | unbundled bundle exec rails new sandbox --database="$RAILSDB" \
54 | --skip-bundle \
55 | --skip-git \
56 | --skip-keeps \
57 | --skip-rc \
58 | --skip-spring \
59 | --skip-test \
60 | --skip-javascript
61 |
62 | if [ ! -d "sandbox" ]; then
63 | echo 'sandbox rails application failed'
64 | exit 1
65 | fi
66 |
67 | cd ./sandbox
68 | cat <> Gemfile
69 | gem 'solidus', github: 'solidusio/solidus', branch: '$SOLIDUS_BRANCH'
70 | gem 'rails-i18n'
71 | gem 'solidus_i18n'
72 |
73 | # This Braintree extension contains a user decorator, so the user class must be loaded first.
74 | gem "solidus_auth_devise", "~> 2.5"
75 | gem '$extension_name', path: '..'
76 |
77 | group :test, :development do
78 | platforms :mri do
79 | gem 'pry-byebug'
80 | end
81 | end
82 | RUBY
83 |
84 | unbundled bundle install --gemfile Gemfile
85 |
86 | unbundled bundle exec rake db:drop db:create
87 |
88 | # Still request "devise". Solidus will skip installing it again but will include its seeds.
89 | unbundled bundle exec rails generate solidus:install \
90 | --auto-accept \
91 | --user_class=Spree::User \
92 | --enforce_available_locales=true \
93 | --authentication="devise" \
94 | --payment-method=none \
95 | --frontend=${SOLIDUS_FRONTEND} \
96 | $@
97 |
98 | unbundled bundle exec rails generate solidus:auth:install --auto-run-migrations
99 | unbundled bundle exec rails generate ${extension_name}:install --auto-run-migrations
100 |
101 | echo
102 | echo "🚀 Sandbox app successfully created for $extension_name!"
103 | echo "🧪 This app is intended for test purposes."
104 |
--------------------------------------------------------------------------------
/spec/controllers/solidus_paypal_braintree/checkouts_controller_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 | require 'support/order_ready_for_payment'
3 |
4 | RSpec.describe SolidusBraintree::CheckoutsController, type: :controller do
5 | routes { SolidusBraintree::Engine.routes }
6 |
7 | include_context 'when order is ready for payment'
8 |
9 | describe 'PATCH update' do
10 | subject(:patch_update) { patch :update, params: params }
11 |
12 | let(:params) do
13 | {
14 | "state" => "payment",
15 | "order" => {
16 | "payments_attributes" => [
17 | {
18 | "payment_method_id" => payment_method.id,
19 | "source_attributes" => {
20 | "nonce" => "fake-paypal-billing-agreement-nonce",
21 | "payment_type" => SolidusBraintree::Source::PAYPAL
22 | }
23 | }
24 | ],
25 | "use_billing" => "1",
26 | "use_postmates_shipping" => "0"
27 | },
28 | "reuse_credit" => "1",
29 | "order_bill_address" => "",
30 | "reuse_bill_address" => "1"
31 | }
32 | end
33 |
34 | let!(:payment_method) do
35 | create_gateway
36 | end
37 |
38 | before do
39 | allow(controller).to receive(:try_spree_current_user) { user }
40 | allow(controller).to receive(:spree_current_user) { user }
41 | allow(controller).to receive(:current_order) { order }
42 | end
43 |
44 | context "when a payment is created successfully", vcr: {
45 | cassette_name: 'checkout/update',
46 | match_requests_on: [:braintree_uri]
47 | } do
48 | it 'creates a payment' do
49 | expect { patch_update }.
50 | to change { order.payments.count }.
51 | from(0).
52 | to(1)
53 | end
54 |
55 | it 'creates a payment source' do
56 | expect { patch_update }.
57 | to change(SolidusBraintree::Source, :count).
58 | from(0).
59 | to(1)
60 | end
61 |
62 | it 'assigns @order' do
63 | patch_update
64 | expect(assigns(:order)).to eq order
65 | end
66 |
67 | it "is successful" do
68 | expect(patch_update).to be_successful
69 | end
70 |
71 | it "renders 'ok'" do
72 | expect(patch_update.body).to eql("ok")
73 | end
74 | end
75 |
76 | context "when a payment is not created successfully" do
77 | before do
78 | allow_any_instance_of(::Spree::Payment).to receive(:save).and_return(false)
79 | end
80 |
81 | # No idea why this is the case, but I'm just adding the tests here
82 | it "is successful" do
83 | expect(patch_update).to be_successful
84 | end
85 |
86 | it "renders 'not-ok'" do
87 | expect(patch_update.body).to eq('not-ok')
88 | end
89 |
90 | it "does not change the number of payments in the system" do
91 | expect{ patch_update }.not_to(change(::Spree::Payment, :count))
92 | end
93 |
94 | it "does not change the number of sources in the system" do
95 | expect{ patch_update }.not_to(change(SolidusBraintree::Source, :count))
96 | end
97 | end
98 | end
99 | end
100 |
--------------------------------------------------------------------------------
/spec/fixtures/cassettes/braintree/create_profile.yml:
--------------------------------------------------------------------------------
1 | ---
2 | http_interactions:
3 | - request:
4 | method: post
5 | uri: https://api.sandbox.braintreegateway.com/merchants/7rdg92j7bm7fk5h3/customers
6 | body:
7 | encoding: UTF-8
8 | string: |
9 |
10 |
11 | fake-valid-nonce
12 |
13 | headers:
14 | Accept-Encoding:
15 | - gzip
16 | Accept:
17 | - application/xml
18 | User-Agent:
19 | - Braintree Ruby Gem 2.98.0
20 | X-Apiversion:
21 | - '5'
22 | Content-Type:
23 | - application/xml
24 | Authorization:
25 | - Basic bXdqa2t4d2NwMzJja2huZjphOTI5OGY0M2IzMGM2OTlkYjMwNzJjYzRhMDBmN2Y0OQ==
26 | response:
27 | status:
28 | code: 201
29 | message: Created
30 | headers:
31 | Date:
32 | - Fri, 13 Sep 2019 14:27:38 GMT
33 | Content-Type:
34 | - application/xml; charset=utf-8
35 | Transfer-Encoding:
36 | - chunked
37 | X-Frame-Options:
38 | - SAMEORIGIN
39 | X-Xss-Protection:
40 | - 1; mode=block
41 | X-Content-Type-Options:
42 | - nosniff
43 | X-Authentication:
44 | - basic_auth
45 | X-User:
46 | - 3v249hqtptsg744y
47 | Vary:
48 | - Accept-Encoding
49 | Content-Encoding:
50 | - gzip
51 | Etag:
52 | - W/"e8b417e908ed25a3832f0e430535e83c"
53 | Cache-Control:
54 | - max-age=0, private, must-revalidate
55 | X-Runtime:
56 | - '0.431124'
57 | X-Request-Id:
58 | - 01-1568384857.323-92.223.152.178-12969763
59 | Content-Security-Policy:
60 | - frame-ancestors 'self'
61 | X-Broxyid:
62 | - 01-1568384857.323-92.223.152.178-12969763
63 | Strict-Transport-Security:
64 | - max-age=31536000; includeSubDomains
65 | body:
66 | encoding: ASCII-8BIT
67 | string: !binary |-
68 | H4sIAFqne10AA6xWTXOjOBC951e4uBMMtscmhUlt1W5SNYfsYZPsJpcpgRpQLCRWEo6dXz8S5ssfeJzK3NyvX0tN63W3g9tNTkdrEJJwtrTc67E1AhZzTFi6tJ4e7+yFdRteBXEpFc9BhFejUUBw+M31/PFkupgGjrYMqJ1xhpiytT0XOPW9t3mUz5PVLJsETt9r2AkRUtkM5TBihC4tJUqwnMpF0ZAn5nmB2PYIhxwReoQWGWfHZyRoc4S9QySJOnGfAKQA20iN1LaApYW1qUgOVuiNXd8e+7Y7eXSnN978ZjJ/DZwuoIovC/y5+C5gd39VdDshQLHcpZRSHiFqqvgyef7A9756/e978vD21/bvxz8+Hv5Mx4HTceqPwETZMRJY1mkgIdDWMt59/w7RWEQo1QKwEcYCpGzw3dMz1rx5jTXasPd10Yc78vDD14TB529uOy2C2iuVAFBN4gMk2Chg2NT5LI3yGFGihq4SkOqeGXAWXCr9BrqRIPSn7ngeOH2o/zklU2JbwTaiRYa8wQ8/ZE4uYbJSvwGJf0E9V/CvdUF9yhd7oTrDGdCl1isLp2PXWywMh7W4EbVtrgufiUQ6s9buMzJOsZbpUAmM4sz4IoiGT2zF+LtugB7W0Xal5IlNpCwRi6HPP3a2gV8v8Cd6sKMafSst4fDpnx6zRRs+hoio7kt2ZudMUEmbxCPOKSBmhaaChlo5O3Ip9OvYunFKaj6gd+ihpwmBTUFElY+dc6ay0PUC5wg8wd4CErp83niPXqF7bMCHuSeISqijepl0UzW+v5tF/z6X+N6l+D5bv975by+uL17fvucvE34wgKvgDBBVmRZbTxI9rKGRHKVgl4KGmVKFvHEcJCUoeR0JRJgZbamuzjvaXmv9OQXa5sDUjxxUxvEPylPurLXOrwuW3gJbE8GZISwlYjjiGz222/PbG7UYTUdFiK261PbQhloN5mnoLhZu4NRG49OpCE57/dEALUFAgXRBHnR5mt+dj+Myrv4adPEd1tBkGclYkMI85P4m61pV8RWwcJV4SfwRODur8ZWM/F9W8zCqGkJXhujVKkKUzGbzqZ/M/MRN8GSBv8VJ7Gogmc4WUaIFNxjanv0bptsaWM5tiVcDgmz9vQih09i168mKVKOiv933gGp+BvUshZN/Dg4H7dH6/8zgOb/6zy/+c2v/gqV/0co/u/DPrPsLl/2lq/7SRX/xmv/lkv8tG+jLLRA4PbW1Bmizk1N49RMAAP//AwBDGwx/sQwAAA==
69 | http_version:
70 | recorded_at: Fri, 13 Sep 2019 14:27:38 GMT
71 | recorded_with: VCR 5.0.0
72 |
--------------------------------------------------------------------------------
/spec/fixtures/cassettes/transaction/import/valid.yml:
--------------------------------------------------------------------------------
1 | ---
2 | http_interactions:
3 | - request:
4 | method: post
5 | uri: https://api.sandbox.braintreegateway.com/merchants/7rdg92j7bm7fk5h3/customers
6 | body:
7 | encoding: UTF-8
8 | string: |
9 |
10 |
11 | fake-valid-nonce
12 |
13 | headers:
14 | Accept-Encoding:
15 | - gzip
16 | Accept:
17 | - application/xml
18 | User-Agent:
19 | - Braintree Ruby Gem 2.98.0
20 | X-Apiversion:
21 | - '5'
22 | Content-Type:
23 | - application/xml
24 | Authorization:
25 | - Basic bXdqa2t4d2NwMzJja2huZjphOTI5OGY0M2IzMGM2OTlkYjMwNzJjYzRhMDBmN2Y0OQ==
26 | response:
27 | status:
28 | code: 201
29 | message: Created
30 | headers:
31 | Date:
32 | - Fri, 13 Sep 2019 14:27:57 GMT
33 | Content-Type:
34 | - application/xml; charset=utf-8
35 | Transfer-Encoding:
36 | - chunked
37 | X-Frame-Options:
38 | - SAMEORIGIN
39 | X-Xss-Protection:
40 | - 1; mode=block
41 | X-Content-Type-Options:
42 | - nosniff
43 | X-Authentication:
44 | - basic_auth
45 | X-User:
46 | - 3v249hqtptsg744y
47 | Vary:
48 | - Accept-Encoding
49 | Content-Encoding:
50 | - gzip
51 | Etag:
52 | - W/"353759854f3f20558dfdfbeff3bd4668"
53 | Cache-Control:
54 | - max-age=0, private, must-revalidate
55 | X-Runtime:
56 | - '0.384787'
57 | X-Request-Id:
58 | - 02-1568384876.677-92.223.152.178-13026259
59 | Content-Security-Policy:
60 | - frame-ancestors 'self'
61 | X-Broxyid:
62 | - 02-1568384876.677-92.223.152.178-13026259
63 | Strict-Transport-Security:
64 | - max-age=31536000; includeSubDomains
65 | body:
66 | encoding: ASCII-8BIT
67 | string: !binary |-
68 | H4sIAG2ne10AA6xWXXPaOhB9z69g/O4YAy44Y5xp506405mmD01y27x0ZGuNFWTJlWQC/fVXMv7iw5RM+saePSutV2d3CW43GR2sQUjC2dxyr4fWAFjMMWHLufX4cGfPrNvwKogLqXgGIrwaDAKCQ8+fTob+eOgHjrYMqJ1xipiytT0VeOmPXqZRNk1WXjoOnK7XsBMipLIZymDACJ1bShRgOaWLoj5PzLMcse0RDhki9AjNU86Oz0jQ5gh7hUgSdeI+AUgBtpEaqG0OcwtrU5EMrHA0dH176Nvu+MGd3IymN970OXDagDK+yPHb4tuA3f1l0e2EAMVyl9KS8ghRU8Uf46ffeOGr5++fk/uH1fj+n4/el98fvcBpOdVHYKLsGAksqzSQEGhrGe++f4doLCKUagHYCGMBUtb47ul/zeo3r7BaG/a+LrpwS+5/+IrQ+/z1badFUHmlEgCqTryHBBsFDJs6n6VRHiNKVN9VApa6Z3qcOZdKv4FuJAj9iTucBk4X6n5OwZTYlrCNaJ6iUe+HHzLHlzBZod+AxH+gniv4+7qgOuWdvVCe4fToUuuVhZOhO5rNDIc1uBG1ba4Ln4hEOrPG7jJSTrGWaV8JjOLM+CKIho9sxfgr0ye1WEvblZInNpGyQCyGLv/Y2QS+v8Bv6MGWavSttITDx28dZoPWfAwRUe2X7MzWmaCC1olHnFNAzApNBQ21dLbkQujXsXXjFNR8QOfQQ08dApuciDIfO+NMpaE7Cpwj8AR7C0jo8o2Ge/QS3WMDPsw9QVRCFdXJpJ2q8eLOi/57KvDCpXiRrp/v/Jcfrv8S//vp5etCHgzgMjgFRFWqxdaRRAeraSRDS7ALQcNUqVzeOA6SEpS8jgQizIy2pa7OK9pea/05OdpmwNTPDFTK8U/Kl9xZa51f52x5C2xNBGeGMJeI4Yhv9Nhuzm9u1GI0HRUhtmpT20NrajmYJ6E7m7mBUxm1T6ciOO30Rw00BAE50gW559pX/W59HBdx+degjW+xmiaLSMaC5OYh9zdZ26qKr4CFcZ7Hs1Xg7KzaVzDyqyjnYVQ2hK4M0atVhCjxvOnETzw/cRM8nuEPcRK7Gkgm3ixKtOB6Q5uz/8J0WwPLuC3xqkeQjb8TIXQau3Y9WZFyVHS3+x5Qzs+gmqVw8s/B4aA9Wv9vGTznV//5xX9u7V+w9C9a+WcX/pl1f+Gyv3TVX7roL17zf1zyf2UDvbsFAqejtsYAbbZyCq/+BwAA//8DAGwXsMSxDAAA
69 | http_version:
70 | recorded_at: Fri, 13 Sep 2019 14:27:57 GMT
71 | recorded_with: VCR 5.0.0
72 |
--------------------------------------------------------------------------------
/spec/fixtures/cassettes/gateway/customer.yml:
--------------------------------------------------------------------------------
1 | ---
2 | http_interactions:
3 | - request:
4 | method: post
5 | uri: https://api.sandbox.braintreegateway.com/merchants/vn32pmzn67tzbcd9/customers
6 | body:
7 | encoding: UTF-8
8 | string: |
9 |
10 |
11 | braintree@customers.com
12 | fake-valid-nonce
13 |
14 | headers:
15 | Accept-Encoding:
16 | - gzip
17 | Accept:
18 | - application/xml
19 | User-Agent:
20 | - Braintree Ruby Gem 3.4.0
21 | X-Apiversion:
22 | - '6'
23 | Content-Type:
24 | - application/xml
25 | Authorization:
26 | - Basic cTM3ZnF0eXc0cDJzN2Zidzo2M2RhYmNjOWFmMTcyNDhlZjQyMTdjZmRlYWEwM2UwMQ==
27 | response:
28 | status:
29 | code: 201
30 | message: ''
31 | headers:
32 | Date:
33 | - Fri, 10 Dec 2021 10:53:18 GMT
34 | Content-Type:
35 | - application/xml; charset=utf-8
36 | X-Frame-Options:
37 | - SAMEORIGIN
38 | X-Xss-Protection:
39 | - 1; mode=block
40 | X-Content-Type-Options:
41 | - nosniff
42 | X-Download-Options:
43 | - noopen
44 | X-Permitted-Cross-Domain-Policies:
45 | - none
46 | Referrer-Policy:
47 | - strict-origin-when-cross-origin
48 | X-Authentication:
49 | - basic_auth
50 | X-User:
51 | - mp9fm99xgbv5d7nc
52 | Vary:
53 | - Accept-Encoding, Origin
54 | Content-Encoding:
55 | - gzip
56 | Etag:
57 | - W/"435fd70a86beeb87bca285ff652a7010"
58 | Cache-Control:
59 | - max-age=0, private, must-revalidate
60 | X-Runtime:
61 | - '0.366158'
62 | X-Request-Id:
63 | - e7e1e4f3-b4cb-4f66-83d8-68956318e262
64 | Content-Security-Policy:
65 | - frame-ancestors 'self'
66 | X-Broxyid:
67 | - e7e1e4f3-b4cb-4f66-83d8-68956318e262
68 | Strict-Transport-Security:
69 | - max-age=31536000; includeSubDomains
70 | Paypal-Debug-Id:
71 | - ed5d938d152c4
72 | Transfer-Encoding:
73 | - chunked
74 | body:
75 | encoding: ASCII-8BIT
76 | string: !binary |-
77 | H4sIAJ4xs2EAA6xW23KjOBB9z1e4eCeAsR07hcnW1GxStVU7+7DjzE5epgRqG8VCIpLw7etXwtx8wXEq84ZOn241rdNSBw+blPZWICThbGp5t67VAxZzTNhias2+P9pj6yG8CeJcKp6CCG96vYDgcDwc+kN35LmBo1cG1MY4QUzZer1ifj9Ld2x0p3ZRjCeB07Ya9pwIqWyGUugxQqeWEjlYTmGiqMsS8zRDbHuCQ4oIDSOBCFMC4I8qWXmrPQJnbzbELOHsNOwcbU6wNUSSqDMpCEAKsI1UT20zmFpYLxVJwQr7bt+zvb7tud89937o33t3L4HTOBT+eYY/5t847Pcvfs2eE6BY7lNaUB4hagr703/e4aeJevnvr/k/X2fe37vZ+tvrn+vAaTjlT2Ci7BgJLMs0kBBoaxnroX2PaCwilGpN2AhjAVJWeKmGu0oGJVadgH0olTbckLu1UBI6FVHtdl4XpVUaTagq8Q4SbBQwbOp8kUZ5jChRXVsJWOg26jBmXCp9Brq3IJwMPFfXrA21fyfXOt4WsI1olqB+548fM/1rmCzXZ0Did6gXCl70kQkTgeiK8rlGKaN8sl2KGE6HdLWkWThwvf54bDisxo3ubbNd+Ewk0pnV6zYj4RRrJXdVyYjSXHoE0XDGloyvmY7UYA1tX20+t4mUOWIxtPmnxtrx8wX+QJs21GuumzPkkzimlZTulnD2b8uhRis+hoiopiL7ZWOco5xWBYg4p4CYFZqTMNTC2JBzoU/Z1j2aU1OIVtBjS+UCm4yIIh875UwlodfXz8kxeIa9BSTMMRzSC/SADfg49zmiEkqvViZNIeOnx2H04znHTx7FT8nq5XHy+tMbD7H/5S3+4W6PLvvCOwFEVaJV29JWC6toJEULsHNBw0SpTN47DpISlLytn9aFLs8abc276mRomwJTv1JQCce/KF9wZ6Ub5jZjiwdgKyI4M4SpRAxHfKOfiDp+vaNWtWnNCLFlk9oBWlGLR2AQeuOxFzjlorLpVASnrUargJogIEO6IN+4tpXfjY3jPC4mk8a/wSqazCMZC5KZkzx8NZueV3wJLJyss9e3VB/9flkZc0be8urW1JF1aYh+x4V+DEYe8gfjyO9P4iGejEcjNMSAwJ/7Aw3oW63LtY79G+7JFbCU2xIvOyRZ21seQqexb9iukhBpM1BrLpZ2UQ6y69T8OWo5kThHI8kBUNzoQXm7w9mJ5vjqP5lZPnIVXp5XLk8rl2aVKyaVq+aUi1PKhRnlygnl2vnk2unk6tnk3cnk3bnktzyan+61wGnJsV6AXjZ6C2/+BwAA//8DAM4vgB+aDQAA
78 | recorded_at: Fri, 10 Dec 2021 10:53:18 GMT
79 | recorded_with: VCR 6.0.0
80 |
--------------------------------------------------------------------------------
/spec/fixtures/cassettes/braintree/token.yml:
--------------------------------------------------------------------------------
1 | ---
2 | http_interactions:
3 | - request:
4 | method: post
5 | uri: https://api.sandbox.braintreegateway.com/merchants/7rdg92j7bm7fk5h3/client_token
6 | body:
7 | encoding: UTF-8
8 | string: |
9 |
10 |
11 | 2
12 |
13 | headers:
14 | Accept-Encoding:
15 | - gzip
16 | Accept:
17 | - application/xml
18 | User-Agent:
19 | - Braintree Ruby Gem 2.98.0
20 | X-Apiversion:
21 | - '5'
22 | Content-Type:
23 | - application/xml
24 | Authorization:
25 | - Basic bXdqa2t4d2NwMzJja2huZjphOTI5OGY0M2IzMGM2OTlkYjMwNzJjYzRhMDBmN2Y0OQ==
26 | response:
27 | status:
28 | code: 201
29 | message: Created
30 | headers:
31 | Server:
32 | - nginx
33 | Date:
34 | - Fri, 13 Sep 2019 14:27:14 GMT
35 | Content-Type:
36 | - application/xml; charset=utf-8
37 | Transfer-Encoding:
38 | - chunked
39 | X-Authentication:
40 | - server_to_server
41 | Braintree-Service-Origin:
42 | - clientauth
43 | Vary:
44 | - Accept-Encoding
45 | Content-Encoding:
46 | - gzip
47 | Etag:
48 | - W/"9594a9129759a812d3dddac3f8ab3b85"
49 | Cache-Control:
50 | - max-age=0, private, must-revalidate
51 | X-Request-Id:
52 | - 7f8e13cb-6cad-478b-a05e-af21202650d4
53 | X-Runtime:
54 | - '0.065468'
55 | Strict-Transport-Security:
56 | - max-age=31536000; includeSubDomains
57 | body:
58 | encoding: ASCII-8BIT
59 | string: !binary |-
60 | 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
61 | http_version:
62 | recorded_at: Fri, 13 Sep 2019 14:27:14 GMT
63 | recorded_with: VCR 5.0.0
64 |
--------------------------------------------------------------------------------
/spec/fixtures/cassettes/admin/invalid_credit_card.yml:
--------------------------------------------------------------------------------
1 | ---
2 | http_interactions:
3 | - request:
4 | method: post
5 | uri: https://api.sandbox.braintreegateway.com/merchants/7rdg92j7bm7fk5h3/client_token
6 | body:
7 | encoding: UTF-8
8 | string: |
9 |
10 |
11 | 2
12 |
13 | headers:
14 | Accept-Encoding:
15 | - gzip
16 | Accept:
17 | - application/xml
18 | User-Agent:
19 | - Braintree Ruby Gem 2.98.0
20 | X-Apiversion:
21 | - '5'
22 | Content-Type:
23 | - application/xml
24 | Authorization:
25 | - Basic bXdqa2t4d2NwMzJja2huZjphOTI5OGY0M2IzMGM2OTlkYjMwNzJjYzRhMDBmN2Y0OQ==
26 | response:
27 | status:
28 | code: 201
29 | message: Created
30 | headers:
31 | Server:
32 | - nginx
33 | Date:
34 | - Fri, 13 Sep 2019 14:27:11 GMT
35 | Content-Type:
36 | - application/xml; charset=utf-8
37 | Transfer-Encoding:
38 | - chunked
39 | X-Authentication:
40 | - server_to_server
41 | Braintree-Service-Origin:
42 | - clientauth
43 | Vary:
44 | - Accept-Encoding
45 | Content-Encoding:
46 | - gzip
47 | Etag:
48 | - W/"c95fd3caa086065297edd0aeeb8e6d55"
49 | Cache-Control:
50 | - max-age=0, private, must-revalidate
51 | X-Request-Id:
52 | - 51cbbac6-bce1-4f90-ab14-6d61a064e77b
53 | X-Runtime:
54 | - '0.200715'
55 | Strict-Transport-Security:
56 | - max-age=31536000; includeSubDomains
57 | body:
58 | encoding: ASCII-8BIT
59 | string: !binary |-
60 | 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
61 | http_version:
62 | recorded_at: Fri, 13 Sep 2019 14:27:11 GMT
63 | recorded_with: VCR 5.0.0
64 |
--------------------------------------------------------------------------------
/spec/fixtures/cassettes/braintree/generate_token.yml:
--------------------------------------------------------------------------------
1 | ---
2 | http_interactions:
3 | - request:
4 | method: post
5 | uri: https://api.sandbox.braintreegateway.com/merchants/7rdg92j7bm7fk5h3/client_token
6 | body:
7 | encoding: UTF-8
8 | string: |
9 |
10 |
11 | 2
12 |
13 | headers:
14 | Accept-Encoding:
15 | - gzip
16 | Accept:
17 | - application/xml
18 | User-Agent:
19 | - Braintree Ruby Gem 2.98.0
20 | X-Apiversion:
21 | - '5'
22 | Content-Type:
23 | - application/xml
24 | Authorization:
25 | - Basic bXdqa2t4d2NwMzJja2huZjphOTI5OGY0M2IzMGM2OTlkYjMwNzJjYzRhMDBmN2Y0OQ==
26 | response:
27 | status:
28 | code: 201
29 | message: Created
30 | headers:
31 | Server:
32 | - nginx
33 | Date:
34 | - Fri, 13 Sep 2019 14:27:15 GMT
35 | Content-Type:
36 | - application/xml; charset=utf-8
37 | Transfer-Encoding:
38 | - chunked
39 | X-Authentication:
40 | - server_to_server
41 | Braintree-Service-Origin:
42 | - clientauth
43 | Vary:
44 | - Accept-Encoding
45 | Content-Encoding:
46 | - gzip
47 | Etag:
48 | - W/"b13b8d459a392fd7cf8fb5e5ce004e6f"
49 | Cache-Control:
50 | - max-age=0, private, must-revalidate
51 | X-Request-Id:
52 | - 865a84cf-849f-4131-a223-b0ea218dc873
53 | X-Runtime:
54 | - '0.089979'
55 | Strict-Transport-Security:
56 | - max-age=31536000; includeSubDomains
57 | body:
58 | encoding: ASCII-8BIT
59 | string: !binary |-
60 | H4sIAEOne10AA3xW25KbOBB9z1ek8r67XMzUuCrJVjzDxYqRYxkkoTeQSMBImIyv8PXb4ElNpnZ2H1zlQq3uo+5zjvTx76vR78/l06Het58+2H9aH96Xrdyruv3x6UOaBH/cf/j787uPUtdle/zjuG/K9vO79+8/nnN9Kj+XPXIER0PO5qflbt+vHlClONkXLupKE1jjd2L0STi0lxHqinZTr2uky3R/EbRa5Om82zZHFtOgS3z8NQ9RlDn6W552IeUdilOv23KMCk4urMEIN/rnlitMQ+UmDUFxY6eMk13cCJs16qsy9HG7a06C669FSJcbBrma9JqYro19745wjUtNhy2zL3EYJNtEoNxUe2Y6HFveXZLgmFqplVCFle9FidHrzfDFSlIS5taVp1CbhGSfsA6VWvPUXL9tLA35vHVMdXfLRzzAssOpfSwGLIrky8CMPcQs8BOm443VXbIB49vZUcMCdBYUI2npY8yuuyL1zoxKO/b1T/moUNEsr4zZMxk01zVf5Burcbasa0raRdlAccHuB8asS2x3RzkEFfHtqZex7rJtu8gLczUsQSHEh2umNd3pJ6ZVnoeEl48LlLeLI6NqVkJ8HEGvm+7Cdmgfh9iD8/Ay7awRTx7se2pEU6TZNWsqktMqUY6uY2t5yaj0FJvidTz43sqofUKXF2Zmfaqr71hXM2oFOPc7d6NpRcMuTn37TjbIVmYzSK4OwhebTUrqvJU9Y0KQKEhzW89K/7jnTlUJ3e2ULR1Mu5/UoSFrpJP7R5tFAUoi0i7rS50585MwuqUcHYCPdR4RS0bx3aqfVzJsTtIJTiJE5/LBq6UJgI+kF4y2GSdaOQHgxuci2Vv4MT4XjPYZ1IWYYTWoXoTSi83ezYzlCnOwc4jJnGsnmGdxJ7jk27kTb+e7wvFMzgDpM/9HXMJFUL8iycPyDjQDa5dRB3sVkYsc9ueVu6hKZuupVourwpC6cH+cshZVOeSXhuoVG2t4kN86P+e7Fg/Lw9KQSoUp5Fv28aM/WyVfbPjNlq0Fa3ifsesBMLaCx/VaHxVoFOqITpr5Cc54UoBp+VKzhvVdEeoRy0KGmv4L63RWb8iY12RmPlsZ1GdMn1SEtGAKsFA3480JZnFc7zZW3M+P4BG7PAwgJj5jFzViaPp8p+oiUSYf6B5iftX8nvFFN82S40FwMrw5SxdryPWqP8IJLMFVVd56VP/yorf2j99XrdCFsc//1e+38hUmOJScdJkLvWwPtfp37rME/uVsdoT+VEWkgQN4WPGxxuY/+JcexzNP3Nveu9KQdp2gn9hBR+yIJ8x+DNMsW7IfcZEA68ylvUjpKWMIZgueCnkUSyEGeMQXVeH/z9qNg03O8aUIAy8xwVFsgQMaW4LZdeFcrZuWbtzessmzFzAPUwziITPZUGohWCC2RC++kqTxSlo9qAbdYbaZ5Tb5ht3FN5h/AmchMkp7Yl2/UbrsZbsQyrcfshQ82a122VA9xI1qCpf4uZF9Yn54yXY5Yu1zLqrMfc2/dX1/Fhw0yRcH8awFGX0ZZwPOQPsNU6OejyPuV3N/HHlLZxn4fhGmEzdXLjnLftQPaMmhb/F8gO+W7P/HK0as5jnOpv3Y26WpLBUthhEr+IfOnONZcZg99Bp+h5d9BDRId8r/rb7x7CK8jDkPRTh3tyN2yAnassUWfIR5Ts7RGXg7amVdWB7oQAHnDrBXAN+wflPfZm6EuXaFSadewTrsI1r4tpaTR3jWctcZ8IphrPO7DjaveQBcBZ7wXx6xGSauGA144Z63gnbcM9WNcAB6qeEebiC3JVs6YnvxAj/YwRwAC0Hi5kGv+Qcch1wn4ACSzvyxcIge50kp9m/e9oL9hm35tnYgF7wLoBf3I/6zMNmkZRkBhyhoYjvpYVBhYKnRI+GMhYOfnu+TEV9fpvgsJo9FNJ04g23ZQp8N9jbOvLnphyZk8uPfcZFxTh3cSVrW4xxe1n73HeiXVmP/XnEtPUkX9jOYd7Q55YAfcA+KLy7wvoJekTX4owv/n4DHdwzeYqDpasRdsADOM95fQS8mTKBxPnn7qPtd4QrAg9R3bn36+NftLffu41+vX3n/AAAA//8DAFkKZDAcCgAA
61 | http_version:
62 | recorded_at: Fri, 13 Sep 2019 14:27:15 GMT
63 | recorded_with: VCR 5.0.0
64 |
--------------------------------------------------------------------------------
/spec/fixtures/cassettes/checkout/invalid_credit_card.yml:
--------------------------------------------------------------------------------
1 | ---
2 | http_interactions:
3 | - request:
4 | method: post
5 | uri: https://api.sandbox.braintreegateway.com/merchants/7rdg92j7bm7fk5h3/client_token
6 | body:
7 | encoding: UTF-8
8 | string: |
9 |
10 |
11 | 2
12 |
13 | headers:
14 | Accept-Encoding:
15 | - gzip
16 | Accept:
17 | - application/xml
18 | User-Agent:
19 | - Braintree Ruby Gem 2.98.0
20 | X-Apiversion:
21 | - '5'
22 | Content-Type:
23 | - application/xml
24 | Authorization:
25 | - Basic bXdqa2t4d2NwMzJja2huZjphOTI5OGY0M2IzMGM2OTlkYjMwNzJjYzRhMDBmN2Y0OQ==
26 | response:
27 | status:
28 | code: 201
29 | message: Created
30 | headers:
31 | Server:
32 | - nginx
33 | Date:
34 | - Fri, 13 Sep 2019 14:28:19 GMT
35 | Content-Type:
36 | - application/xml; charset=utf-8
37 | Transfer-Encoding:
38 | - chunked
39 | X-Authentication:
40 | - server_to_server
41 | Braintree-Service-Origin:
42 | - clientauth
43 | Vary:
44 | - Accept-Encoding
45 | Content-Encoding:
46 | - gzip
47 | Etag:
48 | - W/"8d61b38a37820d4ee67ecf0606a04804"
49 | Cache-Control:
50 | - max-age=0, private, must-revalidate
51 | X-Request-Id:
52 | - eddeb5a6-81dd-4969-a4b7-fdd5c2eecc84
53 | X-Runtime:
54 | - '0.116279'
55 | Strict-Transport-Security:
56 | - max-age=31536000; includeSubDomains
57 | body:
58 | encoding: ASCII-8BIT
59 | string: !binary |-
60 | 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
61 | http_version:
62 | recorded_at: Fri, 13 Sep 2019 14:28:19 GMT
63 | recorded_with: VCR 5.0.0
64 |
--------------------------------------------------------------------------------
/spec/fixtures/cassettes/gateway/authorized_transaction.yml:
--------------------------------------------------------------------------------
1 | ---
2 | http_interactions:
3 | - request:
4 | method: post
5 | uri: https://api.sandbox.braintreegateway.com/merchants/7rdg92j7bm7fk5h3/transactions
6 | body:
7 | encoding: UTF-8
8 | string: |
9 |
10 |
11 | 40
12 | fake-valid-nonce
13 | sale
14 |
15 | headers:
16 | Accept-Encoding:
17 | - gzip
18 | Accept:
19 | - application/xml
20 | User-Agent:
21 | - Braintree Ruby Gem 2.98.0
22 | X-Apiversion:
23 | - '5'
24 | Content-Type:
25 | - application/xml
26 | Authorization:
27 | - Basic bXdqa2t4d2NwMzJja2huZjphOTI5OGY0M2IzMGM2OTlkYjMwNzJjYzRhMDBmN2Y0OQ==
28 | response:
29 | status:
30 | code: 201
31 | message: Created
32 | headers:
33 | Date:
34 | - Fri, 13 Sep 2019 14:27:33 GMT
35 | Content-Type:
36 | - application/xml; charset=utf-8
37 | Transfer-Encoding:
38 | - chunked
39 | X-Frame-Options:
40 | - SAMEORIGIN
41 | X-Xss-Protection:
42 | - 1; mode=block
43 | X-Content-Type-Options:
44 | - nosniff
45 | X-Authentication:
46 | - basic_auth
47 | X-User:
48 | - 3v249hqtptsg744y
49 | Vary:
50 | - Accept-Encoding
51 | Content-Encoding:
52 | - gzip
53 | Etag:
54 | - W/"9f163d0d605e2cf0f374d80596165c7f"
55 | Cache-Control:
56 | - max-age=0, private, must-revalidate
57 | X-Runtime:
58 | - '0.517267'
59 | X-Request-Id:
60 | - 02-1568384852.825-92.223.152.178-13021928
61 | Content-Security-Policy:
62 | - frame-ancestors 'self'
63 | X-Broxyid:
64 | - 02-1568384852.825-92.223.152.178-13021928
65 | Strict-Transport-Security:
66 | - max-age=31536000; includeSubDomains
67 | body:
68 | encoding: ASCII-8BIT
69 | string: !binary |-
70 | H4sIAFWne10AA+RYS4/bNhC+768wfOfKryK7gVZp0CJoCzSHJFske1lQ4thiliJVkvLa/fUdipIsWZR3eykK9GbNfBySw3l84/jdoRCzPWjDlbybL68X8xnITDEud3fz+y8fyM38XXIVW02loZlFVHI1m8WcJdvNk4QVlHGEH05mLLWVSWhlc6X5X8DiqBE5rT2WkBgqII7qn06WVVrjbkfCjSK4KST3n3+Oo7HYgWmhKmmTzeJ6sYij5sspCtBZTqUlNMuckOB5jIUiVcLGUUhbn7ZKSUA3k1zcza2uYB556xRt6VdBlWaIDCgyDdQCI9TO3N3v5gw/LS9gnqwWy1uyuCXL9Zfl5u3qzdv1+gE90C2o11cl+2frTwsaPxur8Abuo3688xOicMu1sUTSAgJKQad1mSpKKo8BDRSUi4D8GVLDbchWmSsZkm/pYeTUqH+rOOVCYMz+yzc0VgNgTDCmwZiQCw4WJHMvMQkRKqOC25B5DTtMuJCfFGaW8Llxu1ku3sRRX9QeG+NUH6dv5dVuBaGizOnqVaj1SyhZ4aPwbPxgvTfCq20ryULJ0mlME+xUa3ocKNGfvYIUMlJSbTm6w4C1AgrAhB2uCBk/Va6XzPfMptRmeRCT87L8X4bkhQD5z8Ri/3Wa+ki2HAQzTSzsDQGtlSboo1JJA8Gr1bje1Yfo5HdsVBcBrYnhq52BfvVWLmLqa+z34/3HQgfdYXt4pkfUfAcf5dhxzPhh41KrDHdDP7TZQWt4bWnz8duHn1ztuQQaWhkeZblwvXxKO7HSYgQn70vU7B3HmELUrmWMu5Og88ew0V33imfugbb48LgCYycFPfZI5ZgA7uLb/QTK0gPxHCWoggMUZdvNU6UEUDlPtlQYx486QMse8BYko5o1IW7VE4RyMOUS+dFydXPjiq3s15FNsry5WcZR89GkCpokNRv7gxuKsdJ9t6Wi5No/ZaGkzZPlKo5GwhH2CFQjMVktBuBa2uzbdG7iCk3NKe8/n/r5SXo6Za5E7exw+eAF3QGptEhya0vzNoqowRJtrlNNuXRp08T7NdbNqKRHV7kfC8BYZY9C7VS0x/tfl3L3DuSeayUd4M5QyVJ1QILb2W9qnYaSIo/8qFz4+d9ekwMVNscTI5WVT1I9yzjqyTyIQcrtSe8/G1Wl8eEwBneVcAyuhzrXdI3AUVPsdSdoT9aclx61Ej1EK2jcZ0yFpRBbmXw6YQbSYWlVW+K0VGbQ33WsbN2lWJXVzPt0gpPMg3ZCpZh0wTbZcm4XmgF1JfmfFTSZiBbw7TjW8lFSuhQHWShi2NNE6nX6hmIOU68ZcUjOMVL1cUAhuvZbIwANNW/q8hWpOiqK8pX0vcN3Fi7OVt5HE+OR95BBmtwlw4/tdOTSAYcF004G7qg94mMUljpIaMnxSGO5v3B0fuNO0njJF01Bw0SqSk2meTlJtHr6rsjVLJKU2NgVI8hliPNnsBwOkHgsbYNYPPLZPq5zEGwSAZbIuKmjMagDb0W1lW6iYE3NOVhixmcbGkUG5uZjvNdECHd63zxwaJUwtopvvnfdbgsw1afctuqZ+NccadENaaWNJ8EMLI56pi1iA1X4bXoMOrz9EDP6S+CVcDg4B2Dx1uFjuGkCIxV5X8hglWUBgowvMnF3d/OysnBpuPDNkLLv2O3c+hC26VCES+R8lZ9eXFf25ejRlaM4mgINWVPPKUNy1SdOk6CXbdVU6yVbHR+TYJ+Vfjrb5evXOAprgmtqawaro8AX9cpZx+mcMmCtO4HNsQASLAYuSwCdt1XByc2QrcaR4MJU0w14U/nTFoopfXvI4ayZLFxPWNwu18vN6s16fbrMGW6KHbsYoBfZcRslw5CsqRqYS38yrRb9LjW1vD/Fd109HOYXh/SLa4N/BExyiKnRfnpBp0nYL7/lqfyYf1t/KtPVD9uH7590WtwfH76+j6MT7GrQI5OrvwEAAP//AwDB+fqkWhUAAA==
71 | http_version:
72 | recorded_at: Fri, 13 Sep 2019 14:27:34 GMT
73 | recorded_with: VCR 5.0.0
74 |
--------------------------------------------------------------------------------
/spec/fixtures/cassettes/gateway/authorize.yml:
--------------------------------------------------------------------------------
1 | ---
2 | http_interactions:
3 | - request:
4 | method: post
5 | uri: https://api.sandbox.braintreegateway.com/merchants/7rdg92j7bm7fk5h3/transactions
6 | body:
7 | encoding: UTF-8
8 | string: |
9 |
10 |
11 | 10.00
12 | Solidus
13 |
14 | true
15 |
16 | fake-valid-nonce
17 |
18 | Bruce
19 | Wayne
20 | 42 Spruce Lane Apt 312
21 | Gotham
22 | 90210
23 | CA
24 | US
25 |
26 | sale
27 |
28 | headers:
29 | Accept-Encoding:
30 | - gzip
31 | Accept:
32 | - application/xml
33 | User-Agent:
34 | - Braintree Ruby Gem 2.98.0
35 | X-Apiversion:
36 | - '5'
37 | Content-Type:
38 | - application/xml
39 | Authorization:
40 | - Basic bXdqa2t4d2NwMzJja2huZjphOTI5OGY0M2IzMGM2OTlkYjMwNzJjYzRhMDBmN2Y0OQ==
41 | response:
42 | status:
43 | code: 201
44 | message: Created
45 | headers:
46 | Date:
47 | - Fri, 13 Sep 2019 14:27:17 GMT
48 | Content-Type:
49 | - application/xml; charset=utf-8
50 | Transfer-Encoding:
51 | - chunked
52 | X-Frame-Options:
53 | - SAMEORIGIN
54 | X-Xss-Protection:
55 | - 1; mode=block
56 | X-Content-Type-Options:
57 | - nosniff
58 | X-Authentication:
59 | - basic_auth
60 | X-User:
61 | - 3v249hqtptsg744y
62 | Vary:
63 | - Accept-Encoding
64 | Content-Encoding:
65 | - gzip
66 | Etag:
67 | - W/"d5257db6ada80984d58fcdd80b08a656"
68 | Cache-Control:
69 | - max-age=0, private, must-revalidate
70 | X-Runtime:
71 | - '0.578117'
72 | X-Request-Id:
73 | - 01-1568384836.096-92.223.152.178-12965922
74 | Content-Security-Policy:
75 | - frame-ancestors 'self'
76 | X-Broxyid:
77 | - 01-1568384836.096-92.223.152.178-12965922
78 | Strict-Transport-Security:
79 | - max-age=31536000; includeSubDomains
80 | body:
81 | encoding: ASCII-8BIT
82 | string: !binary |-
83 | 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
84 | http_version:
85 | recorded_at: Fri, 13 Sep 2019 14:27:17 GMT
86 | recorded_with: VCR 5.0.0
87 |
--------------------------------------------------------------------------------
/spec/fixtures/cassettes/gateway/authorize/credit_card/address.yml:
--------------------------------------------------------------------------------
1 | ---
2 | http_interactions:
3 | - request:
4 | method: post
5 | uri: https://api.sandbox.braintreegateway.com/merchants/7rdg92j7bm7fk5h3/transactions
6 | body:
7 | encoding: UTF-8
8 | string: |
9 |
10 |
11 | 10.00
12 | Solidus
13 |
14 | true
15 |
16 | fake-valid-nonce
17 |
18 | Dick
19 | Grayson
20 | 15 Robin Walk Apt 123
21 | Blüdhaven
22 | 90210
23 | CA
24 | US
25 |
26 | sale
27 |
28 | headers:
29 | Accept-Encoding:
30 | - gzip
31 | Accept:
32 | - application/xml
33 | User-Agent:
34 | - Braintree Ruby Gem 2.98.0
35 | X-Apiversion:
36 | - '5'
37 | Content-Type:
38 | - application/xml
39 | Authorization:
40 | - Basic bXdqa2t4d2NwMzJja2huZjphOTI5OGY0M2IzMGM2OTlkYjMwNzJjYzRhMDBmN2Y0OQ==
41 | response:
42 | status:
43 | code: 201
44 | message: Created
45 | headers:
46 | Date:
47 | - Fri, 13 Sep 2019 14:27:21 GMT
48 | Content-Type:
49 | - application/xml; charset=utf-8
50 | Transfer-Encoding:
51 | - chunked
52 | X-Frame-Options:
53 | - SAMEORIGIN
54 | X-Xss-Protection:
55 | - 1; mode=block
56 | X-Content-Type-Options:
57 | - nosniff
58 | X-Authentication:
59 | - basic_auth
60 | X-User:
61 | - 3v249hqtptsg744y
62 | Vary:
63 | - Accept-Encoding
64 | Content-Encoding:
65 | - gzip
66 | Etag:
67 | - W/"352c8901a89656457f414fe8ab578ca2"
68 | Cache-Control:
69 | - max-age=0, private, must-revalidate
70 | X-Runtime:
71 | - '0.473273'
72 | X-Request-Id:
73 | - 01-1568384840.821-92.223.152.178-12966756
74 | Content-Security-Policy:
75 | - frame-ancestors 'self'
76 | X-Broxyid:
77 | - 01-1568384840.821-92.223.152.178-12966756
78 | Strict-Transport-Security:
79 | - max-age=31536000; includeSubDomains
80 | body:
81 | encoding: ASCII-8BIT
82 | string: !binary |-
83 | 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
84 | http_version:
85 | recorded_at: Fri, 13 Sep 2019 14:27:21 GMT
86 | recorded_with: VCR 5.0.0
87 |
--------------------------------------------------------------------------------
/spec/fixtures/cassettes/gateway/purchase.yml:
--------------------------------------------------------------------------------
1 | ---
2 | http_interactions:
3 | - request:
4 | method: post
5 | uri: https://api.sandbox.braintreegateway.com/merchants/7rdg92j7bm7fk5h3/transactions
6 | body:
7 | encoding: UTF-8
8 | string: |
9 |
10 |
11 | 10.00
12 | Solidus
13 |
14 | true
15 | true
16 |
17 | fake-valid-nonce
18 |
19 | Bruce
20 | Wayne
21 | 42 Spruce Lane Apt 312
22 | Gotham
23 | 90210
24 | CA
25 | US
26 |
27 | sale
28 |
29 | headers:
30 | Accept-Encoding:
31 | - gzip
32 | Accept:
33 | - application/xml
34 | User-Agent:
35 | - Braintree Ruby Gem 2.98.0
36 | X-Apiversion:
37 | - '5'
38 | Content-Type:
39 | - application/xml
40 | Authorization:
41 | - Basic bXdqa2t4d2NwMzJja2huZjphOTI5OGY0M2IzMGM2OTlkYjMwNzJjYzRhMDBmN2Y0OQ==
42 | response:
43 | status:
44 | code: 201
45 | message: Created
46 | headers:
47 | Date:
48 | - Fri, 13 Sep 2019 14:27:49 GMT
49 | Content-Type:
50 | - application/xml; charset=utf-8
51 | Transfer-Encoding:
52 | - chunked
53 | X-Frame-Options:
54 | - SAMEORIGIN
55 | X-Xss-Protection:
56 | - 1; mode=block
57 | X-Content-Type-Options:
58 | - nosniff
59 | X-Authentication:
60 | - basic_auth
61 | X-User:
62 | - 3v249hqtptsg744y
63 | Vary:
64 | - Accept-Encoding
65 | Content-Encoding:
66 | - gzip
67 | Etag:
68 | - W/"3fcabe79853d46ebc3e84b6bafd1a249"
69 | Cache-Control:
70 | - max-age=0, private, must-revalidate
71 | X-Runtime:
72 | - '0.678478'
73 | X-Request-Id:
74 | - 02-1568384868.912-92.223.152.178-13024911
75 | Content-Security-Policy:
76 | - frame-ancestors 'self'
77 | X-Broxyid:
78 | - 02-1568384868.912-92.223.152.178-13024911
79 | Strict-Transport-Security:
80 | - max-age=31536000; includeSubDomains
81 | body:
82 | encoding: ASCII-8BIT
83 | string: !binary |-
84 | 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
85 | http_version:
86 | recorded_at: Fri, 13 Sep 2019 14:27:50 GMT
87 | recorded_with: VCR 5.0.0
88 |
--------------------------------------------------------------------------------
/spec/fixtures/cassettes/gateway/authorize/paypal/EUR.yml:
--------------------------------------------------------------------------------
1 | ---
2 | http_interactions:
3 | - request:
4 | method: post
5 | uri: https://api.sandbox.braintreegateway.com/merchants/7rdg92j7bm7fk5h3/transactions
6 | body:
7 | encoding: UTF-8
8 | string: |
9 |
10 |
11 | 10.00
12 | Solidus
13 |
14 | true
15 |
16 | paypal+europe@example.com
17 |
18 |
19 | stembolt_EUR
20 | fake-valid-nonce
21 |
22 | Bruce
23 | Wayne
24 | 42 Spruce Lane Apt 312
25 | Gotham
26 | 90210
27 | CA
28 | US
29 |
30 | sale
31 |
32 | headers:
33 | Accept-Encoding:
34 | - gzip
35 | Accept:
36 | - application/xml
37 | User-Agent:
38 | - Braintree Ruby Gem 2.98.0
39 | X-Apiversion:
40 | - '5'
41 | Content-Type:
42 | - application/xml
43 | Authorization:
44 | - Basic bXdqa2t4d2NwMzJja2huZjphOTI5OGY0M2IzMGM2OTlkYjMwNzJjYzRhMDBmN2Y0OQ==
45 | response:
46 | status:
47 | code: 201
48 | message: Created
49 | headers:
50 | Date:
51 | - Fri, 13 Sep 2019 14:27:23 GMT
52 | Content-Type:
53 | - application/xml; charset=utf-8
54 | Transfer-Encoding:
55 | - chunked
56 | X-Frame-Options:
57 | - SAMEORIGIN
58 | X-Xss-Protection:
59 | - 1; mode=block
60 | X-Content-Type-Options:
61 | - nosniff
62 | X-Authentication:
63 | - basic_auth
64 | X-User:
65 | - 3v249hqtptsg744y
66 | Vary:
67 | - Accept-Encoding
68 | Content-Encoding:
69 | - gzip
70 | Etag:
71 | - W/"77e1e2d6d635e062ee34868bb7aca21a"
72 | Cache-Control:
73 | - max-age=0, private, must-revalidate
74 | X-Runtime:
75 | - '0.511733'
76 | X-Request-Id:
77 | - 01-1568384842.114-92.223.152.178-12966962
78 | Content-Security-Policy:
79 | - frame-ancestors 'self'
80 | X-Broxyid:
81 | - 01-1568384842.114-92.223.152.178-12966962
82 | Strict-Transport-Security:
83 | - max-age=31536000; includeSubDomains
84 | body:
85 | encoding: ASCII-8BIT
86 | string: !binary |-
87 | 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
88 | http_version:
89 | recorded_at: Fri, 13 Sep 2019 14:27:23 GMT
90 | recorded_with: VCR 5.0.0
91 |
--------------------------------------------------------------------------------
/spec/fixtures/cassettes/gateway/authorize/paypal/address.yml:
--------------------------------------------------------------------------------
1 | ---
2 | http_interactions:
3 | - request:
4 | method: post
5 | uri: https://api.sandbox.braintreegateway.com/merchants/7rdg92j7bm7fk5h3/transactions
6 | body:
7 | encoding: UTF-8
8 | string: |
9 |
10 |
11 | 10.00
12 | Solidus
13 |
14 | true
15 |
16 | paypal+europe@example.com
17 |
18 |
19 | stembolt_EUR
20 | fake-valid-nonce
21 |
22 | Bruce
23 | Wayne
24 | 42 Spruce Lane Apt 312
25 | Gotham
26 | 90210
27 | CA
28 | US
29 |
30 | sale
31 |
32 | headers:
33 | Accept-Encoding:
34 | - gzip
35 | Accept:
36 | - application/xml
37 | User-Agent:
38 | - Braintree Ruby Gem 2.98.0
39 | X-Apiversion:
40 | - '5'
41 | Content-Type:
42 | - application/xml
43 | Authorization:
44 | - Basic bXdqa2t4d2NwMzJja2huZjphOTI5OGY0M2IzMGM2OTlkYjMwNzJjYzRhMDBmN2Y0OQ==
45 | response:
46 | status:
47 | code: 201
48 | message: Created
49 | headers:
50 | Date:
51 | - Fri, 13 Sep 2019 14:27:24 GMT
52 | Content-Type:
53 | - application/xml; charset=utf-8
54 | Transfer-Encoding:
55 | - chunked
56 | X-Frame-Options:
57 | - SAMEORIGIN
58 | X-Xss-Protection:
59 | - 1; mode=block
60 | X-Content-Type-Options:
61 | - nosniff
62 | X-Authentication:
63 | - basic_auth
64 | X-User:
65 | - 3v249hqtptsg744y
66 | Vary:
67 | - Accept-Encoding
68 | Content-Encoding:
69 | - gzip
70 | Etag:
71 | - W/"fdbf84ba963bfcc3556d33a5f62d0b7f"
72 | Cache-Control:
73 | - max-age=0, private, must-revalidate
74 | X-Runtime:
75 | - '0.456705'
76 | X-Request-Id:
77 | - 01-1568384843.516-92.223.152.178-12967200
78 | Content-Security-Policy:
79 | - frame-ancestors 'self'
80 | X-Broxyid:
81 | - 01-1568384843.516-92.223.152.178-12967200
82 | Strict-Transport-Security:
83 | - max-age=31536000; includeSubDomains
84 | body:
85 | encoding: ASCII-8BIT
86 | string: !binary |-
87 | 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
88 | http_version:
89 | recorded_at: Fri, 13 Sep 2019 14:27:24 GMT
90 | recorded_with: VCR 5.0.0
91 |
--------------------------------------------------------------------------------
/spec/features/backend/new_payment_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 | require 'spree/testing_support/order_walkthrough'
3 |
4 | shared_context "with backend checkout setup" do
5 | let(:braintree) { new_gateway(active: true) }
6 | let!(:gateway) { create :payment_method }
7 | let(:order) { create(:completed_order_with_totals, number: 'R9999999') }
8 | let(:pending_case_insensitive) { /pending/i }
9 | let(:expiration) { "02/#{Date.current.year.next}" }
10 |
11 | before do
12 | braintree.save!
13 | create(:store, payment_methods: [gateway, braintree]).tap do |store|
14 | store.braintree_configuration.update!(credit_card: true)
15 | end
16 |
17 | allow_any_instance_of(SolidusBraintree::Source).to receive(:nonce).and_return("fake-valid-nonce")
18 |
19 | # Order and payment numbers must be identical between runs to re-use the VCR
20 | # cassette
21 | allow_any_instance_of(Spree::Payment).to receive(:number).and_return("123ABC")
22 | end
23 |
24 | around do |example|
25 | Capybara.using_wait_time(20) { example.run }
26 | end
27 | end
28 |
29 | describe 'creating a new payment', type: :feature, js: true do
30 | stub_authorization!
31 |
32 | context "with valid credit card data", vcr: {
33 | cassette_name: 'admin/valid_credit_card',
34 | match_requests_on: [:braintree_uri]
35 | } do
36 | include_context "with backend checkout setup"
37 |
38 | it "checks out successfully" do
39 | visit "/admin/orders/#{order.number}/payments/new"
40 | choose('Braintree')
41 | expect(page).to have_selector("#payment_method_#{braintree.id}", visible: :visible)
42 | expect(page).to have_selector("iframe#braintree-hosted-field-number")
43 |
44 | within_frame("braintree-hosted-field-number") do
45 | fill_in("credit-card-number", with: "4111111111111111")
46 | end
47 | within_frame("braintree-hosted-field-expirationDate") do
48 | fill_in("expiration", with: expiration)
49 | end
50 | within_frame("braintree-hosted-field-cvv") do
51 | fill_in("cvv", with: "123")
52 | end
53 |
54 | click_button("Update")
55 |
56 | within('table#payments') do
57 | expect(page).to have_content('Braintree')
58 | expect(page).to have_content(pending_case_insensitive)
59 | end
60 |
61 | click_icon(:capture)
62 |
63 | expect(page).not_to have_content('Cannot perform requested operation')
64 | expect(page).to have_content('Payment Updated')
65 | end
66 | end
67 |
68 | context "with invalid credit card data" do
69 | include_context "with backend checkout setup"
70 |
71 | # Attempt to submit an invalid form once
72 | before do
73 | visit "/admin/orders/#{order.number}/payments/new"
74 | choose('Braintree')
75 |
76 | within_frame("braintree-hosted-field-number") do
77 | fill_in("credit-card-number", with: "1111111111111111")
78 | end
79 | within_frame("braintree-hosted-field-expirationDate") do
80 | fill_in("expiration", with: expiration)
81 | end
82 | within_frame("braintree-hosted-field-cvv") do
83 | fill_in("cvv", with: "123")
84 | end
85 |
86 | click_button "Update"
87 | end
88 |
89 | it "displays a meaningful error message" do
90 | expect(page).to have_text(
91 | "BraintreeError: Some payment input fields are invalid. Cannot tokenize invalid card fields."
92 | )
93 | end
94 |
95 | # Same error should be produced when submitting an empty form again
96 | context "when user tries to resubmit another invalid form", vcr: {
97 | cassette_name: "admin/invalid_credit_card",
98 | match_requests_on: [:braintree_uri]
99 | } do
100 | it "displays a meaningful error message" do
101 | click_button "Update"
102 | expect(page).to have_text(
103 | "BraintreeError: Some payment input fields are invalid. Cannot tokenize invalid card fields."
104 | )
105 | end
106 | end
107 |
108 | # User should be able to checkout after submit fails once
109 | context "when user enters valid data", vcr: {
110 | cassette_name: "admin/resubmit_credit_card",
111 | match_requests_on: [:braintree_uri]
112 | } do
113 | it "creates the payment successfully" do
114 | within_frame("braintree-hosted-field-number") do
115 | fill_in("credit-card-number", with: "4111111111111111")
116 | end
117 | within_frame("braintree-hosted-field-expirationDate") do
118 | fill_in("expiration", with: expiration)
119 | end
120 | within_frame("braintree-hosted-field-cvv") do
121 | fill_in("cvv", with: "123")
122 | end
123 | click_button("Update")
124 |
125 | within('table#payments') do
126 | expect(page).to have_content('Braintree')
127 | expect(page).to have_content(pending_case_insensitive)
128 | end
129 |
130 | click_icon(:capture)
131 |
132 | expect(page).not_to have_content('Cannot perform requested operation')
133 | expect(page).to have_content('Payment Updated')
134 | end
135 | end
136 | end
137 | end
138 |
--------------------------------------------------------------------------------
/spec/controllers/solidus_paypal_braintree/transactions_controller_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | RSpec.describe SolidusBraintree::TransactionsController, type: :controller do
4 | routes { SolidusBraintree::Engine.routes }
5 |
6 | let!(:country) { create :country }
7 | let(:line_item) { create :line_item, price: 50 }
8 | let(:order) do
9 | Spree::Order.create!(
10 | line_items: [line_item],
11 | email: 'test@example.com',
12 | bill_address: create(:address, country: country),
13 | ship_address: create(:address, country: country),
14 | user: create(:user)
15 | )
16 | end
17 |
18 | let(:payment_method) { create_gateway }
19 |
20 | before do
21 | allow(controller).to receive(:spree_current_user) { order.user }
22 | allow(controller).to receive(:current_order) { order }
23 | create :shipping_method, cost: 5
24 | create :state, abbr: "WA", country: country
25 | end
26 |
27 | cassette_options = {
28 | cassette_name: "transactions_controller/create",
29 | match_requests_on: [:braintree_uri]
30 | }
31 | describe "POST create", vcr: cassette_options do
32 | subject(:post_create) { post :create, params: params }
33 |
34 | let!(:country) { create :country, iso: 'US' }
35 |
36 | let(:params) do
37 | {
38 | transaction: {
39 | nonce: "fake-valid-nonce",
40 | payment_type: SolidusBraintree::Source::PAYPAL,
41 | phone: "1112223333",
42 | email: "batman@example.com",
43 | address_attributes: {
44 | name: "Wade Wilson",
45 | address_line_1: "123 Fake Street",
46 | city: "Seattle",
47 | zip: "98101",
48 | state_code: "WA",
49 | country_code: "US"
50 | }
51 | },
52 | payment_method_id: payment_method.id
53 | }
54 | end
55 |
56 | before do
57 | create :state, abbr: "WA", country: country
58 | end
59 |
60 | context "when import has invalid address" do
61 | before { params[:transaction][:address_attributes][:city] = nil }
62 |
63 | it "raises a validation error" do
64 | expect { post_create }.to raise_error(
65 | SolidusBraintree::TransactionsController::InvalidImportError,
66 | "Import invalid: " \
67 | "Address is invalid, " \
68 | "Address City can't be blank"
69 | )
70 | end
71 | end
72 |
73 | context "when the transaction is valid", vcr: {
74 | cassette_name: 'transaction/import/valid',
75 | match_requests_on: [:braintree_uri]
76 | } do
77 | it "imports the payment" do
78 | expect { post_create }.to change { order.payments.count }.by(1)
79 | expect(order.payments.first.amount).to eq 55
80 | end
81 |
82 | context "when no end state is provided" do
83 | it "advances the order to confirm" do
84 | post_create
85 | expect(order).to be_confirm
86 | end
87 | end
88 |
89 | context "when end state provided is delivery" do
90 | let(:params) { super().merge(state: 'delivery') }
91 |
92 | it "advances the order to delivery" do
93 | post_create
94 | expect(order).to be_delivery
95 | end
96 | end
97 |
98 | context "with provided address" do
99 | it "creates a new address" do
100 | # Creating the order also creates 3 addresses, we want to make sure
101 | # the transaction import only creates 1 new one
102 | order
103 | expect { post_create }.to change(Spree::Address, :count).by(1)
104 | expect(Spree::Address.last.address1).to eq "123 Fake Street"
105 | end
106 | end
107 |
108 | context "without country ISO" do
109 | before do
110 | params[:transaction][:address_attributes][:country_code] = ""
111 | params[:transaction][:address_attributes][:country_name] = "United States"
112 | end
113 |
114 | it "creates a new address, looking up the ISO by country name" do
115 | order
116 | expect { post_create }.to change(Spree::Address, :count).by(1)
117 | expect(Spree::Address.last.country.iso).to eq "US"
118 | end
119 | end
120 |
121 | context "without transaction address" do
122 | before { params[:transaction].delete(:address_attributes) }
123 |
124 | it "does not create a new address" do
125 | order
126 | expect { post_create }.not_to(change(Spree::Address, :count))
127 | end
128 | end
129 |
130 | context "when format is HTML" do
131 | context "when import! leaves the order in confirm" do
132 | it "redirects the user to the confirm page" do
133 | expect(post_create).to redirect_to spree.checkout_state_path("confirm")
134 | end
135 | end
136 |
137 | context "when import! completes the order" do
138 | before { allow(order).to receive(:complete?).and_return(true) }
139 |
140 | it "displays the order to the user" do
141 | expect(post_create).to redirect_to spree.order_path(order)
142 | end
143 | end
144 | end
145 |
146 | context "when format is JSON" do
147 | before { params[:format] = :json }
148 |
149 | it "has a successful response" do
150 | post_create
151 | expect(response).to be_successful
152 | end
153 | end
154 | end
155 |
156 | context "when the transaction is invalid" do
157 | before { params[:transaction][:email] = nil }
158 |
159 | context "when format is HTML" do
160 | it "raises an error including the validation messages" do
161 | expect { post_create }.to raise_error(
162 | SolidusBraintree::TransactionsController::InvalidImportError,
163 | "Import invalid: Email can't be blank"
164 | )
165 | end
166 | end
167 |
168 | context "when format is JSON" do
169 | before { params[:format] = :json }
170 |
171 | it "has a failed status" do
172 | post_create
173 | expect(response).to have_http_status :unprocessable_entity
174 | end
175 |
176 | it "returns the errors as JSON" do
177 | post_create
178 | expect(JSON.parse(response.body)["errors"]["email"]).to eq ["can't be blank"]
179 | end
180 | end
181 | end
182 | end
183 | end
184 |
--------------------------------------------------------------------------------
/spec/features/frontend/paypal_checkout_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe "Checkout", type: :feature, js: true do
4 | Capybara.default_max_wait_time = 60
5 |
6 | # let!(:store) do
7 | # create(:store, payment_methods: [payment_method]).tap do |s|
8 | # s.braintree_configuration.update!(braintree_preferences)
9 | # end
10 | # end
11 | let(:braintree_preferences) { { paypal: true }.merge(paypal_options) }
12 | let(:paypal_options) { {} }
13 |
14 | let!(:country) { create(:country, states_required: true) }
15 | # let!(:state) { create(:state, country: country, abbr: "CA", name: "California") }
16 | # let!(:shipping_method) { create(:shipping_method) }
17 | # let!(:stock_location) { create(:stock_location) }
18 | let!(:mug) { create(:product, name: "RoR Mug") }
19 | let!(:payment_method) { create_gateway }
20 | # let!(:zone) { create(:zone) }
21 |
22 | before do
23 | create(:store, payment_methods: [payment_method]).tap do |s|
24 | s.braintree_configuration.update!(braintree_preferences)
25 | end
26 | create(:state, country: country, abbr: "CA", name: "California")
27 | create(:shipping_method)
28 | create(:stock_location)
29 | create(:zone)
30 | end
31 |
32 | context "when going through express checkout using paypal cart button" do
33 | before do
34 | payment_method
35 | add_mug_to_cart
36 | end
37 |
38 | it "checks out successfully", skip: "Broken. To be revisited" do
39 | pend_if_paypal_slow do
40 | expect_any_instance_of(Spree::Order).to receive(:restart_checkout_flow)
41 | move_through_paypal_popup
42 | expect(page).to have_content("Shipments")
43 | click_on "Place Order"
44 | expect(page).to have_content("Your order has been processed successfully")
45 | end
46 | end
47 |
48 | context 'when using custom paypal button style' do
49 | let(:paypal_options) { { preferred_paypal_button_color: 'blue' } }
50 |
51 | it 'displays required PayPal button style' do
52 | within_frame find('#paypal-button iframe') do
53 | expect(page).to have_selector('.paypal-button-color-blue')
54 | end
55 | end
56 | end
57 | end
58 |
59 | context "when going through regular checkout using paypal payment method" do
60 | before do
61 | payment_method
62 | add_mug_to_cart
63 | click_button("Checkout")
64 | fill_in("order_email", with: "paypal_buyer@paypaltest.com")
65 | click_button("Continue")
66 | fill_in_address
67 | click_button("Save and Continue")
68 | click_button("Save and Continue")
69 | end
70 |
71 | it "formats the address variable correctly" do
72 | expect(page.evaluate_script("address['recipientName']")).to eq "Ryan Bigg"
73 | end
74 |
75 | it "checks out successfully", skip: "Broken. To be revisited" do
76 | pend_if_paypal_slow do
77 | expect_any_instance_of(Spree::Order).not_to receive(:restart_checkout_flow)
78 | move_through_paypal_popup
79 |
80 | expect(page).to have_content("Shipments")
81 | click_on "Place Order"
82 | expect(page).to have_content("Your order has been processed successfully")
83 | end
84 | end
85 | end
86 |
87 | # Selenium does not clear cookies properly between test runs, even when
88 | # using Capybara.reset_sessions!, see:
89 | # https://github.com/jnicklas/capybara/issues/535
90 | #
91 | # This causes Paypal to remain logged in and not prompt for an email on the
92 | # second test run and causes the test to fail. Adding conditional logic for
93 | # this greatly increases the test time, so it is left out since CI runs
94 | # these with poltergeist.
95 | def move_through_paypal_popup
96 | expect(page).to have_css('#paypal-button .paypal-button')
97 |
98 | sleep 2 # the PayPal button is not immediately ready
99 |
100 | popup = page.window_opened_by do
101 | within_frame find('#paypal-button iframe') do
102 | find('div.paypal-button').click
103 | end
104 | end
105 | page.switch_to_window(popup)
106 |
107 | # We don't control this popup window.
108 | # So javascript errors are not our errors.
109 | begin
110 | expect(page).not_to have_selector('body.loading')
111 | fill_in("login_email", with: "stembolt_buyer@stembolttest.com")
112 | click_on "Next"
113 | fill_in("login_password", with: "test1234")
114 |
115 | expect(page).not_to have_selector('body.loading')
116 | click_button("btnLogin")
117 |
118 | expect(page).not_to have_selector('body.loading')
119 | click_button("Continue")
120 | click_button("Agree & Continue")
121 | rescue Selenium::WebDriver::Error::JavascriptError => e
122 | pending "PayPal had javascript errors in their popup window."
123 | raise e
124 | rescue Capybara::ElementNotFound => e
125 | pending "PayPal delivered unkown HTML in their popup window."
126 | raise e
127 | rescue Selenium::WebDriver::Error::NoSuchWindowError => e
128 | pending "PayPal popup not available."
129 | raise e
130 | end
131 |
132 | page.switch_to_window(page.windows.first)
133 | end
134 |
135 | def fill_in_address
136 | address = "order_bill_address_attributes"
137 | if page.has_css?("##{address}_firstname", wait: 0)
138 | fill_in "#{address}_firstname", with: "Ryan"
139 | fill_in "#{address}_lastname", with: "Bigg"
140 | else
141 | fill_in "#{address}_name", with: "Ryan Bigg"
142 | end
143 | fill_in "#{address}_address1", with: "143 Swan Street"
144 | fill_in "#{address}_city", with: "San Jose"
145 | select "United States of America", from: "#{address}_country_id"
146 | select "California", from: "#{address}_state_id"
147 | fill_in "#{address}_zipcode", with: "95131"
148 | fill_in "#{address}_phone", with: "(555) 555-0111"
149 | end
150 |
151 | def add_mug_to_cart
152 | visit spree.root_path
153 | click_link mug.name
154 | click_button "add-to-cart-button"
155 | end
156 |
157 | def pend_if_paypal_slow
158 | yield
159 | rescue RSpec::Expectations::ExpectationNotMetError => e
160 | pending "PayPal did not answer in #{Capybara.default_max_wait_time} seconds."
161 | raise e
162 | rescue Selenium::WebDriver::Error::JavascriptError => e
163 | pending "PayPal delivered wrong payload because of errors in their popup window."
164 | raise e
165 | end
166 | end
167 |
--------------------------------------------------------------------------------
/spec/models/solidus_paypal_braintree/transaction_address_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe SolidusBraintree::TransactionAddress do
4 | describe "#valid?" do
5 | subject { address.valid? }
6 |
7 | let(:address) { described_class.new(valid_attributes) }
8 |
9 | let(:valid_attributes) do
10 | {
11 | name: "Bruce Wayne",
12 | address_line_1: "42 Spruce Lane",
13 | city: "Gotham",
14 | zip: "98201",
15 | state_code: "WA",
16 | country_code: "US"
17 | }
18 | end
19 |
20 | let(:country) { create :country, iso: 'US', states_required: true }
21 |
22 | before do
23 | create :state, abbr: "WA", country: country
24 | end
25 |
26 | it { is_expected.to be true }
27 |
28 | context 'without country matches' do
29 | let(:valid_attributes) { super().merge({ country_code: 'CA' }) }
30 |
31 | it { is_expected.to be false }
32 | end
33 |
34 | context "without name" do
35 | let(:valid_attributes) { super().except(:name) }
36 |
37 | it { is_expected.to be false }
38 | end
39 |
40 | context "without address_line_1" do
41 | let(:valid_attributes) { super().except(:address_line_1) }
42 |
43 | it { is_expected.to be false }
44 | end
45 |
46 | context "without city" do
47 | let(:valid_attributes) { super().except(:city) }
48 |
49 | it { is_expected.to be false }
50 | end
51 |
52 | context "without zip" do
53 | let(:valid_attributes) { super().except(:zip) }
54 |
55 | it { is_expected.to be false }
56 | end
57 |
58 | context "without state_code" do
59 | let(:valid_attributes) { super().except(:state_code) }
60 |
61 | it { is_expected.to be false }
62 |
63 | context "when country does not requires states" do
64 | let(:country) { create :country, iso: 'US', states_required: false }
65 |
66 | it { is_expected.to be true }
67 | end
68 | end
69 |
70 | context "without country_code" do
71 | let(:valid_attributes) { super().except(:country_code) }
72 |
73 | it { is_expected.to be true }
74 |
75 | it "defaults to the US" do
76 | subject
77 | expect(address.country_code).to eq "us"
78 | end
79 | end
80 |
81 | context "with a one word name" do
82 | let(:valid_attributes) { super().merge({ name: "Bruce" }) }
83 |
84 | it { is_expected.to be true }
85 | end
86 | end
87 |
88 | describe "#attributes=" do
89 | subject { described_class.new(attrs) }
90 |
91 | context "when an ISO code is provided" do
92 | let(:attrs) { { country_code: "US" } }
93 |
94 | it "uses the ISO code provided" do
95 | expect(subject.country_code).to eq "US"
96 | end
97 | end
98 |
99 | context "when the ISO code is blank" do
100 | context "with a valid country name provided" do
101 | before do
102 | create :country, name: "canada", iso: "CA"
103 | end
104 |
105 | let(:attrs) { { country_name: "Canada" } }
106 |
107 | it "looks up the ISO code by the country name" do
108 | expect(subject.country_code).to eq "CA"
109 | end
110 | end
111 |
112 | context "without valid country name" do
113 | let(:attrs) { { country_name: "Neverland" } }
114 |
115 | it "leaves the country code blank" do
116 | expect(subject.country_code).to be_nil
117 | end
118 | end
119 | end
120 | end
121 |
122 | describe '#spree_country' do
123 | subject { described_class.new(country_code: country_code).spree_country }
124 |
125 | before do
126 | create :country, name: 'United States', iso: 'US'
127 | end
128 |
129 | ['us', 'US'].each do |code|
130 | let(:country_code) { code }
131 |
132 | it 'looks up by iso' do
133 | expect(subject.name).to eq 'United States'
134 | end
135 | end
136 |
137 | context 'when country does not exist' do
138 | let(:country_code) { 'NA' }
139 |
140 | it { is_expected.to be_nil }
141 | end
142 | end
143 |
144 | describe '#spree_state' do
145 | subject { described_class.new(country_code: 'US', state_code: state_code).spree_state }
146 |
147 | let(:state_code) { 'newy' }
148 |
149 | it { is_expected.to be_nil }
150 |
151 | context 'when state exists' do
152 | before do
153 | us = create :country, iso: 'US'
154 | create :state, abbr: 'NY', name: 'New York', country: us
155 | end
156 |
157 | ['ny', ' ny', 'ny ', 'New York', 'new york', 'NY'].each do |code|
158 | let(:state_code) { code }
159 |
160 | it 'looks up the right state' do
161 | expect(subject.abbr).to eq "NY"
162 | end
163 | end
164 |
165 | context 'with no matching state' do
166 | let(:state_code) { 'AL' }
167 |
168 | it { is_expected.to be_nil }
169 | end
170 | end
171 | end
172 |
173 | describe '#should_match_state_model' do
174 | subject { described_class.new(country_code: 'US').should_match_state_model? }
175 |
176 | it { is_expected.to be_falsey }
177 |
178 | context 'when country does not require states' do
179 | before { create :country, iso: 'US', states_required: false }
180 |
181 | it { is_expected.to be false }
182 | end
183 |
184 | context 'when country requires states' do
185 | before { create :country, iso: 'US', states_required: true }
186 |
187 | it { is_expected.to be true }
188 | end
189 | end
190 |
191 | describe '#to_spree_address' do
192 | subject { described_class.new(address_params).to_spree_address }
193 |
194 | let(:address_params) do
195 | {
196 | country_code: 'US',
197 | state_code: 'NY',
198 | name: "Alfred"
199 | }
200 | end
201 | let!(:us) { create :country, iso: 'US' }
202 |
203 | it { is_expected.to be_a Spree::Address }
204 |
205 | context 'when country exists with states' do
206 | before do
207 | create :state, country: us, abbr: 'NY', name: 'New York'
208 | end
209 |
210 | it 'uses state model' do
211 | expect(subject.state.name).to eq 'New York'
212 | end
213 | end
214 |
215 | context 'when country exist with no states' do
216 | it 'uses state_name' do
217 | expect(subject.state).to be_nil
218 | expect(subject.state_text).to eq 'NY'
219 | end
220 | end
221 |
222 | unless SolidusSupport.combined_first_and_last_name_in_address?
223 | context 'when using first_name and last_name' do
224 | let(:address_params) { super().merge({ first_name: "Bruce", last_name: "Wayne" }) }
225 |
226 | it 'displays a deprecation warning' do
227 | expect(Spree::Deprecation).to receive(:warn).
228 | with("first_name and last_name are deprecated. Use name instead.", any_args)
229 |
230 | subject
231 | end
232 | end
233 | end
234 | end
235 | end
236 |
--------------------------------------------------------------------------------
/spec/features/frontend/venmo_checkout_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 | require 'spree/testing_support/order_walkthrough'
5 |
6 | describe "Checkout", type: :feature, js: true do
7 | let(:braintree_preferences) { { venmo: true }.merge(preferences) }
8 | let(:preferences) { {} }
9 | let(:user) { create(:user) }
10 | let!(:payment_method) { create_gateway }
11 |
12 | before do
13 | create(:store, payment_methods: [payment_method]).tap do |s|
14 | s.braintree_configuration.update!(braintree_preferences)
15 | end
16 |
17 | go_to_payment_checkout_page
18 | end
19 |
20 | context 'with Venmo checkout' do
21 | context 'when Venmo is disabled' do
22 | let(:preferences) { { venmo: false } }
23 |
24 | it 'does not load the Venmo payment button' do
25 | expect(page).not_to have_selector('#venmo-button')
26 | end
27 | end
28 |
29 | context 'when Venmo is enabled' do
30 | it 'loads the Venmo payment button' do
31 | expect(page).to have_selector('#venmo-button')
32 | end
33 | end
34 |
35 | context "when Venmo's button style is customized" do
36 | context 'when venmo_button_color is "blue" and venmo_button_width is "280"' do
37 | let(:preferences) { { preferred_venmo_button_color: 'blue', preferred_venmo_button_width: '280' } }
38 |
39 | it 'has the correct style' do
40 | venmo_button.assert_matches_style(width: '280px', 'background-image': /venmo_blue_button_280x48/)
41 | venmo_button.hover
42 | venmo_button.assert_matches_style('background-image': /venmo_active_blue_button_280x48/)
43 | end
44 | end
45 |
46 | context 'when venmo_button_color is "white" and venmo_button_width is "375"' do
47 | let(:preferences) { { preferred_venmo_button_color: 'white', preferred_venmo_button_width: '375' } }
48 |
49 | it 'has the correct style' do
50 | venmo_button.assert_matches_style(width: '375px', 'background-image': /venmo_white_button_375x48/)
51 | venmo_button.hover
52 | venmo_button.assert_matches_style('background-image': /venmo_active_white_button_375x48/)
53 | end
54 | end
55 | end
56 |
57 | context 'when the Venmo button is clicked' do
58 | before { venmo_button.click }
59 |
60 | it 'opens the QR modal which shows an error when closed' do
61 | within_frame(venmo_frame) do
62 | expect(page).to have_selector('#venmo-qr-code-view')
63 |
64 | click_button('close-icon')
65 |
66 | expect(page).not_to have_selector('#venmo-qr-code-view')
67 | end
68 |
69 | expect(page).to have_content('Venmo authorization was canceled by closing the Venmo Desktop modal.')
70 | end
71 | end
72 |
73 | # TODO: Reenable these specs once Venmo is enabled on the Braintree sandbox.
74 | xcontext 'with Venmo transactions', vcr: { cassette_name: 'checkout/valid_venmo_transaction' } do
75 | before do
76 | fake_venmo_successful_tokenization
77 | end
78 |
79 | context 'with CreditCard disabled' do
80 | it 'can checkout with Venmo' do
81 | next_checkout_step
82 | finalize_checkout
83 |
84 | expect(Spree::Order.last.complete?).to be(true)
85 | end
86 | end
87 |
88 | # To test that the hosted-fields inputs do not conflict with Venmo's
89 | context 'with CreditCard enabled' do
90 | let(:preferences) { { credit_card: true } }
91 |
92 | it 'can checkout with Venmo' do
93 | disable_hosted_fields_inputs
94 | disable_hosted_fields_form_listener
95 |
96 | next_checkout_step
97 | finalize_checkout
98 |
99 | expect(Spree::Order.last.complete?).to be(true)
100 | expect(Spree::Payment.last.source.venmo?).to be(true)
101 | end
102 | end
103 |
104 | # https://developer.paypal.com/braintree/docs/guides/venmo/client-side#custom-integration
105 | it "meet's Braintree's acceptance criteria during checkout", aggregate_failures: true do
106 | next_checkout_step
107 |
108 | expect(page).to have_content('Payment Type: Venmo')
109 |
110 | finalize_checkout
111 |
112 | expect(page).to have_content('Venmo Account: venmojoe')
113 | end
114 |
115 | # the VCR must be based on this test, so it includes HTTP requests of the second order
116 | it 'saves the used Venmo source in the wallet and can be reused' do
117 | next_checkout_step
118 | finalize_checkout
119 | go_to_payment_checkout_page(order_number: 'R300000002')
120 |
121 | expect(Spree::User.first.wallet.wallet_payment_sources).not_to be_empty
122 | expect(page).to have_selector('#existing_cards')
123 | expect(page).to have_content('venmojoe')
124 |
125 | next_checkout_step
126 | finalize_checkout
127 |
128 | expect(Spree::Order.all.all?(&:complete?)).to be(true)
129 | end
130 | end
131 | end
132 |
133 | private
134 |
135 | def go_to_payment_checkout_page(order_number: 'R300000001' )
136 | order = if Spree.solidus_gem_version >= Gem::Version.new('2.6.0')
137 | Spree::TestingSupport::OrderWalkthrough.up_to(:address)
138 | else
139 | OrderWalkthrough.up_to(:address)
140 | end
141 |
142 | order.update!(user: user, number: order_number) # constant order number for VCRs
143 |
144 | allow_any_instance_of(Spree::CheckoutController).to receive_messages(current_order: order)
145 |
146 | first_user = Spree::User.first
147 | allow_any_instance_of(Spree::CheckoutController).to receive_messages(try_spree_current_user: first_user)
148 | allow_any_instance_of(Spree::CheckoutController).to receive_messages(spree_current_user: first_user)
149 |
150 | allow_any_instance_of(Spree::Payment).to receive(:gateway_order_id).and_return(order_number)
151 |
152 | visit spree.checkout_state_path(order.state)
153 | next_checkout_step
154 | end
155 |
156 | def next_checkout_step
157 | click_button('Save and Continue')
158 | end
159 |
160 | def finalize_checkout
161 | click_button('Place Order')
162 | end
163 |
164 | def venmo_button
165 | find_button('venmo-button', disabled: false)
166 | end
167 |
168 | def venmo_frame
169 | find('#venmo-desktop-iframe')
170 | end
171 |
172 | def fake_venmo_successful_tokenization
173 | enable_venmo_inputs
174 | fake_payment_method_nonce
175 | end
176 |
177 | def enable_venmo_inputs
178 | page.execute_script("$('.venmo-fields input').each(function(_index, input){input.removeAttribute('disabled');});")
179 | end
180 |
181 | def fake_payment_method_nonce
182 | page.execute_script("$('#venmo_payment_method_nonce').val('fake-venmo-account-nonce');")
183 | end
184 |
185 | def disable_hosted_fields_inputs
186 | page.execute_script("$('.hosted-fields input').each(function(_index, input){input.disabled=true;});")
187 | end
188 |
189 | def disable_hosted_fields_form_listener
190 | # Once the submit button is enabled, the submit listener has been added
191 | find("#checkout_form_payment input[type='submit']:not(:disabled)")
192 | page.execute_script("$('#checkout_form_payment').off('submit');")
193 | end
194 | end
195 |
--------------------------------------------------------------------------------
/spec/features/frontend/braintree_credit_card_checkout_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 | require 'spree/testing_support/order_walkthrough'
3 |
4 | shared_context "with frontend checkout setup" do
5 | let(:braintree) { new_gateway(active: true) }
6 | let!(:gateway) { create :payment_method }
7 | let(:three_d_secure_enabled) { false }
8 | let(:venmo_enabled) { false }
9 | let(:card_number) { "4111111111111111" }
10 | let(:card_expiration) { "01/#{Time.now.utc.year + 3}" }
11 |
12 | before do
13 | braintree.save!
14 |
15 | create(:store, payment_methods: [gateway, braintree]).tap do |store|
16 | store.braintree_configuration.update!(
17 | credit_card: true,
18 | three_d_secure: three_d_secure_enabled,
19 | venmo: venmo_enabled
20 | )
21 |
22 | braintree.update(
23 | preferred_credit_card_fields_style: { input: { 'font-size': '30px' } },
24 | preferred_placeholder_text: { number: "Enter Your Card Number" }
25 | )
26 | end
27 |
28 | order = if Spree.solidus_gem_version >= Gem::Version.new('2.6.0')
29 | Spree::TestingSupport::OrderWalkthrough.up_to(:delivery)
30 | else
31 | OrderWalkthrough.up_to(:delivery)
32 | end
33 |
34 | user = create(:user)
35 | order.user = user
36 | order.number = "R9999999"
37 | order.recalculate
38 |
39 | allow_any_instance_of(Spree::CheckoutController).to receive_messages(current_order: order)
40 | allow_any_instance_of(Spree::CheckoutController).to receive_messages(try_spree_current_user: user)
41 | allow_any_instance_of(Spree::CheckoutController).to receive_messages(spree_current_user: user)
42 | allow_any_instance_of(Spree::Payment).to receive(:number).and_return("123ABC")
43 | allow_any_instance_of(SolidusBraintree::Source).to receive(:nonce).and_return("fake-valid-nonce")
44 |
45 | visit spree.checkout_state_path(:delivery)
46 | click_button "Save and Continue"
47 | choose("Braintree")
48 | end
49 |
50 | around do |example|
51 | Capybara.using_wait_time(20) { example.run }
52 | end
53 | end
54 |
55 | describe 'entering credit card details', type: :feature, js: true do
56 | context 'when page loads' do
57 | include_context "with frontend checkout setup"
58 |
59 | it "selectors display correctly" do
60 | expect(page).to have_selector("#payment_method_#{braintree.id}", visible: :visible)
61 | expect(page).to have_selector("iframe#braintree-hosted-field-number")
62 | expect(page).to have_selector("iframe[type='number']")
63 | end
64 |
65 | it "credit card field style variable is set" do
66 | within_frame("braintree-hosted-field-number") do
67 | expect(find("#credit-card-number").style("font-size")).to eq({ "font-size" => "30px" })
68 | end
69 | end
70 |
71 | it "sets the placeholder text correctly" do
72 | within_frame("braintree-hosted-field-number") do
73 | expect(find("#credit-card-number")['placeholder']).to eq("Enter Your Card Number")
74 | end
75 | end
76 | end
77 |
78 | context "with valid credit card data", vcr: {
79 | cassette_name: 'checkout/valid_credit_card',
80 | match_requests_on: [:braintree_uri]
81 | } do
82 | include_context "with frontend checkout setup"
83 | # To ensure Venmo inputs do not conflict with checkout
84 | let(:venmo_enabled) { true }
85 |
86 | before do
87 | within_frame("braintree-hosted-field-number") do
88 | fill_in("credit-card-number", with: card_number)
89 | end
90 | within_frame("braintree-hosted-field-expirationDate") do
91 | fill_in("expiration", with: card_expiration)
92 | end
93 | within_frame("braintree-hosted-field-cvv") do
94 | fill_in("cvv", with: "123")
95 | end
96 |
97 | click_button("Save and Continue")
98 | end
99 |
100 | it "checks out successfully" do
101 | within("#order_details") do
102 | expect(page).to have_content("CONFIRM")
103 | end
104 | click_button("Place Order")
105 | expect(page).to have_content("Your order has been processed successfully")
106 | end
107 |
108 | context 'with 3D secure enabled' do
109 | let(:three_d_secure_enabled) { true }
110 |
111 | it 'checks out successfully' do
112 | authenticate_3ds
113 |
114 | within("#order_details") do
115 | expect(page).to have_content("CONFIRM")
116 | end
117 |
118 | click_button("Place Order")
119 | expect(page).to have_content("Your order has been processed successfully")
120 | end
121 |
122 | context 'with 3ds authentication error' do
123 | let(:card_number) { "4000000000001125" }
124 |
125 | it 'shows a 3ds authentication error' do
126 | authenticate_3ds
127 | expect(page).to have_content(
128 | "3D Secure authentication failed. Please try again using a different payment method."
129 | )
130 | end
131 | end
132 | end
133 | end
134 |
135 | context "with invalid credit card data" do
136 | include_context "with frontend checkout setup"
137 |
138 | # Attempt to submit an empty form once
139 | before do
140 | click_button "Save and Continue"
141 | end
142 |
143 | it "displays an alert with a meaningful error message" do
144 | expect(page).to have_text I18n.t("solidus_braintree.errors.empty_fields")
145 | expect(page).to have_selector("input[type='submit']:enabled")
146 | end
147 |
148 | # Same error should be produced when submitting an empty form again
149 | context "when user tries to resubmit an empty form", vcr: { cassette_name: "checkout/invalid_credit_card" } do
150 | it "displays an alert with a meaningful error message" do
151 | expect(page).to have_selector("input[type='submit']:enabled")
152 |
153 | click_button "Save and Continue"
154 | expect(page).to have_text I18n.t("solidus_braintree.errors.empty_fields")
155 | end
156 | end
157 |
158 | # User should be able to checkout after submit fails once
159 | context "when user enters valid data", vcr: {
160 | cassette_name: "checkout/resubmit_credit_card",
161 | match_requests_on: [:braintree_uri]
162 | } do
163 | it "allows them to resubmit and complete the purchase" do
164 | within_frame("braintree-hosted-field-number") do
165 | fill_in("credit-card-number", with: "4111111111111111")
166 | end
167 | within_frame("braintree-hosted-field-expirationDate") do
168 | fill_in("expiration", with: card_expiration)
169 | end
170 | within_frame("braintree-hosted-field-cvv") do
171 | fill_in("cvv", with: "123")
172 | end
173 | click_button("Save and Continue")
174 | within("#order_details") do
175 | expect(page).to have_content("CONFIRM")
176 | end
177 | click_button("Place Order")
178 | expect(page).to have_content("Your order has been processed successfully")
179 | end
180 | end
181 | end
182 |
183 | def authenticate_3ds
184 | within_frame("Cardinal-CCA-IFrame") do
185 | fill_in("challengeDataEntry", with: "1234")
186 | continue_button = find_button("SUBMIT")
187 | continue_button.scroll_to(continue_button)
188 | continue_button.click
189 | end
190 | end
191 | end
192 |
--------------------------------------------------------------------------------
/spec/fixtures/cassettes/gateway/void.yml:
--------------------------------------------------------------------------------
1 | ---
2 | http_interactions:
3 | - request:
4 | method: post
5 | uri: https://api.sandbox.braintreegateway.com/merchants/7rdg92j7bm7fk5h3/transactions
6 | body:
7 | encoding: UTF-8
8 | string: |
9 |
10 |
11 | 40
12 | fake-valid-nonce
13 | sale
14 |
15 | headers:
16 | Accept-Encoding:
17 | - gzip
18 | Accept:
19 | - application/xml
20 | User-Agent:
21 | - Braintree Ruby Gem 2.98.0
22 | X-Apiversion:
23 | - '5'
24 | Content-Type:
25 | - application/xml
26 | Authorization:
27 | - Basic bXdqa2t4d2NwMzJja2huZjphOTI5OGY0M2IzMGM2OTlkYjMwNzJjYzRhMDBmN2Y0OQ==
28 | response:
29 | status:
30 | code: 201
31 | message: Created
32 | headers:
33 | Date:
34 | - Fri, 13 Sep 2019 14:27:35 GMT
35 | Content-Type:
36 | - application/xml; charset=utf-8
37 | Transfer-Encoding:
38 | - chunked
39 | X-Frame-Options:
40 | - SAMEORIGIN
41 | X-Xss-Protection:
42 | - 1; mode=block
43 | X-Content-Type-Options:
44 | - nosniff
45 | X-Authentication:
46 | - basic_auth
47 | X-User:
48 | - 3v249hqtptsg744y
49 | Vary:
50 | - Accept-Encoding
51 | Content-Encoding:
52 | - gzip
53 | Etag:
54 | - W/"f09ed2bcb5f927430d556ec2c442012d"
55 | Cache-Control:
56 | - max-age=0, private, must-revalidate
57 | X-Runtime:
58 | - '0.402901'
59 | X-Request-Id:
60 | - 02-1568384854.660-92.223.152.178-13022247
61 | Content-Security-Policy:
62 | - frame-ancestors 'self'
63 | X-Broxyid:
64 | - 02-1568384854.660-92.223.152.178-13022247
65 | Strict-Transport-Security:
66 | - max-age=31536000; includeSubDomains
67 | body:
68 | encoding: ASCII-8BIT
69 | string: !binary |-
70 | H4sIAFene10AA+RY32/bNhB+z19h+J2RbKdIUijqCgzDVqDFsLZD15eCEs8WG4rUSMqx99fvKEqyZFFO9jIM2Jt19/FIHu/Hd07eHEqx2IM2XMmH5eo6Xi5A5opxuXtYfv70E7lbvkmvEqupNDS3iEqvFouEs3Rn7W3ByjiJ8MPJjKW2NimtbaE0/wtYErUip7XHClJDBSRR89PJ8lpr3O1IuFEEN4X088cfk2gqdmBaqlra9Ca+jnHP9sspStB5QaUlNM+dkOB5jIUyU8ImUUjbnLbOSEC3kFw8LK2uYRl56xRt6RdBlWaIDChyDdQCI9Qu3N0flgw/LS9hma7j1T2J78lq82l183p9+3rz6it6oF/QrK8r9s/Wnxa0fjZW4Q3cR/N45ydE4ZZrY4mkJQSUgs7rclVWVB4DGigpFwH5E2SG25CtqlAyJN/Sw8Sp0fBWScaFwJj9l29orAbAmGBMgzEhFxwsSOZeYhYiVE4FtyHzGnaYcCE/Kcws4XPj/mYV3ybRUNQdG+NUH+dv5dVuBaGiKuj6RajNcyhZ46PwfPpggzfCq21ryULJ0mtMG+xUa3ocKdGfg4IUMlJRbTm6w4C1AkrAhB2vCBk/Va7nzA/MZtTmRRBT8Kr6X4bkhQD5z8Ti8HXa+ki2HAQzbSzsDQGtlSboo0pJA8GrNbjB1cfo9D02qouAzsT41c5Av3grFzHNNfb76f5ToYPusD080SNqvoOPcuw4ZvqwSaVVjruhH7rsoA28sXTz7tf3a2zYF0FjK+OjrGLXy+e0MystRnD6tkLN3nGMOUTjWsa4Owk6fwqb3HWveO4eaIsPjyswdjLQU4/UjgngLr7dz6AsPRDPUYIqOEBZdd08U0oAlct0S4Vx/KgHdOwBb0Fyqlkb4lY9QigHMy6RH63Wd3eu2MphHblJV3d3qyRqP9pUQZOkYWO/c0MxVvrvrlRUXPunLJW0RbpaJ9FEOMEegWokJut4BG6k7b5t5yau0DSc8vPHUz8/SU+nLJRonB0uH7ykOyC1FmlhbWVeRxE1WKLNdaYply5t2ni/xroZVfToKve3EjBW2Tehdira4/2vK7l7A3LPtZIO8GCoZJk6IMHt7be1TkNFkUd+UC78/G+vKYAKW+CJkcrKR6meZBINZB7EIOP2pPefrarW+HAYg7taOAY3QJ1r+kbgqCn2uhN0IGvPS49aiQGiE7TuM6bGUoitTD6eMCPpuLSqLXFaKnMY7jpVdu5SrM4b5n06wUnmQTuhMky6YJvsOLcLzYC6lvzPGtpMRAv4dhxr+SQpXYqDLBUx7HEm9Xp9SzHHqdeOOKTgGKn6OKIQffttEICG2jd1+YpUHRVl9UL63uN7CxdnK++jmfHIe8ggTe6T4YduOnLpgMOC6SYDd9QB8TEKSx2ktOJ4pKncXzg6v3Evab3ki6agYSJVZybXvJolWgN9X+QaFkkqbOyKEeQyxPkzWA5HSDyWtkEsHvlsH9c5CDaJAEtk3DTRGNSBt6K6SjdTsObmHCwx07ONjSIDc/Mx3msmhHu9bx44tEqYWsU337tutwWY61NuW/VE/GtOtOiGrNbGk2AGFkc90xWxkSr8NgMGHd5+jJn8JfBCOBycA7B46/Ax3DSBkYq8L2SwzvMAQcYXmbm7u3lVW7g0XPhmSNl37HZufQjbdijCJXK+2k8vriv7cvTNlaMkmgONWdPAKWNyNSROs6DnbTVU6zlbPR+TYJ+Ufjzb5cuXJAprgmsaawaro8AX9cpFz+mcMmCtP4EtsAASLAYuSwCdt1XByc2QrcaR4MJU0w94c/nTFYo5fXfI8ayZxq4nxPerzepmfbt5dbrMGW6OHbsYoBfZcRcl45BsqBqYS38yreNhl5pbPpzi+64eDvOLQ/rFtcE/AmY5xNxoP7+g16Ts53dFJj8Uf2x+q7L1q+3XzW/xh3XxmH16m0Qn2NWoR6ZXfwMAAP//AwDK0oYOWhUAAA==
71 | http_version:
72 | recorded_at: Fri, 13 Sep 2019 14:27:35 GMT
73 | - request:
74 | method: put
75 | uri: https://api.sandbox.braintreegateway.com/merchants/7rdg92j7bm7fk5h3/transactions/gtt7hdm0/void
76 | body:
77 | encoding: UTF-8
78 | string: ''
79 | headers:
80 | Accept-Encoding:
81 | - gzip
82 | Accept:
83 | - application/xml
84 | User-Agent:
85 | - Braintree Ruby Gem 2.98.0
86 | X-Apiversion:
87 | - '5'
88 | Content-Type:
89 | - application/xml
90 | Authorization:
91 | - Basic bXdqa2t4d2NwMzJja2huZjphOTI5OGY0M2IzMGM2OTlkYjMwNzJjYzRhMDBmN2Y0OQ==
92 | response:
93 | status:
94 | code: 200
95 | message: OK
96 | headers:
97 | Date:
98 | - Fri, 13 Sep 2019 14:27:36 GMT
99 | Content-Type:
100 | - application/xml; charset=utf-8
101 | Transfer-Encoding:
102 | - chunked
103 | X-Frame-Options:
104 | - SAMEORIGIN
105 | X-Xss-Protection:
106 | - 1; mode=block
107 | X-Content-Type-Options:
108 | - nosniff
109 | X-Authentication:
110 | - basic_auth
111 | X-User:
112 | - 3v249hqtptsg744y
113 | Vary:
114 | - Accept-Encoding
115 | Content-Encoding:
116 | - gzip
117 | Etag:
118 | - W/"07af645a7680e62054eb52a5c668f69d"
119 | Cache-Control:
120 | - max-age=0, private, must-revalidate
121 | X-Runtime:
122 | - '0.303758'
123 | X-Request-Id:
124 | - 02-1568384855.897-92.223.152.178-13022485
125 | Content-Security-Policy:
126 | - frame-ancestors 'self'
127 | X-Broxyid:
128 | - 02-1568384855.897-92.223.152.178-13022485
129 | Strict-Transport-Security:
130 | - max-age=31536000; includeSubDomains
131 | body:
132 | encoding: ASCII-8BIT
133 | string: !binary |-
134 | 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
135 | http_version:
136 | recorded_at: Fri, 13 Sep 2019 14:27:36 GMT
137 | recorded_with: VCR 5.0.0
138 |
--------------------------------------------------------------------------------
/spec/fixtures/cassettes/gateway/capture.yml:
--------------------------------------------------------------------------------
1 | ---
2 | http_interactions:
3 | - request:
4 | method: post
5 | uri: https://api.sandbox.braintreegateway.com/merchants/7rdg92j7bm7fk5h3/transactions
6 | body:
7 | encoding: UTF-8
8 | string: |
9 |
10 |
11 | 40
12 | fake-valid-nonce
13 | sale
14 |
15 | headers:
16 | Accept-Encoding:
17 | - gzip
18 | Accept:
19 | - application/xml
20 | User-Agent:
21 | - Braintree Ruby Gem 2.98.0
22 | X-Apiversion:
23 | - '5'
24 | Content-Type:
25 | - application/xml
26 | Authorization:
27 | - Basic bXdqa2t4d2NwMzJja2huZjphOTI5OGY0M2IzMGM2OTlkYjMwNzJjYzRhMDBmN2Y0OQ==
28 | response:
29 | status:
30 | code: 201
31 | message: Created
32 | headers:
33 | Date:
34 | - Fri, 13 Sep 2019 14:27:51 GMT
35 | Content-Type:
36 | - application/xml; charset=utf-8
37 | Transfer-Encoding:
38 | - chunked
39 | X-Frame-Options:
40 | - SAMEORIGIN
41 | X-Xss-Protection:
42 | - 1; mode=block
43 | X-Content-Type-Options:
44 | - nosniff
45 | X-Authentication:
46 | - basic_auth
47 | X-User:
48 | - 3v249hqtptsg744y
49 | Vary:
50 | - Accept-Encoding
51 | Content-Encoding:
52 | - gzip
53 | Etag:
54 | - W/"5df8feea829117d5a9605546aa3caf64"
55 | Cache-Control:
56 | - max-age=0, private, must-revalidate
57 | X-Runtime:
58 | - '0.364675'
59 | X-Request-Id:
60 | - 02-1568384870.537-92.223.152.178-13025218
61 | Content-Security-Policy:
62 | - frame-ancestors 'self'
63 | X-Broxyid:
64 | - 02-1568384870.537-92.223.152.178-13025218
65 | Strict-Transport-Security:
66 | - max-age=31536000; includeSubDomains
67 | body:
68 | encoding: ASCII-8BIT
69 | string: !binary |-
70 | H4sIAGene10AA+RYS4/bNhC+768wfOfK8m6Q3UCrtECRPtDkkFfTXAJKHFvMUqRCUl47vz5DUZIli/JuL0WB3qyZj0NyOI9vnLzcl2KxA224knfL+HK1XIDMFeNye7f88P4VuVm+TC8Sq6k0NLeISi8Wi4Sz9Bv7+rDbxN+TCD+czFhqa5PS2hZK8+/AkqgVOa09VJAaKiCJmp9Oltda424Hwo0iuCmkH979kkRTsQPTUtXSptery9UqidovpyhB5wWVltA8d0KC5zEWykwJm0QhbXPaOiMB3UJycbe0uoZl5K1TtKWfBFWaITKgyDVQC4xQu3B3v1sy/LS8hGW6XsW3ZHVL4qv38fWL9fMXz+LP6IF+QbO+rtg/W39c0PrZWIU3cB/N452eEIUbro0lkpYQUAo6r8tVWVF5CGigpFwE5A+QGW5DtqpCyZB8Q/cTp0bDWyUZFwJj9l++obEaAGOCMQ3GhFywtyCZe4lZiFA5FdyGzGvYYsKF/KQws4TPjdvrePU8iYai7tgYp/owfyuvdisIFVVB109CXT2GkjU+Cs+nDzZ4I7zappYslCy9xrTBTrWmh5ES/TkoSCEjFdWWozsMWCugBEzY8YqQ8WPlesz8wGxGbV4EMQWvqv9lSJ4JkP9MLA5fp62PZMNBMNPGws4Q0Fppgj6qlDQQvFqDG1x9jE5fY6M6C+hMjF/tBPS7t3IW01xjt5vuPxU66BbbwwM9oOYr+CjHjmOmD5tUWuW4G/qhyw7awBtL618/vvrzHdaec6CxlfFR4pXr5XPamZUWIzj9uULNznGMOUTjWsa4Owk6fwqb3HWneO4eaIMPjyswdjLQU4/UjgngLr7dz6As3RPPUYIq2ENZdd08U0oAlct0Q4Vx/KgHdOwBb0Fyqlkb4lbdQygHMy6RH8XrmxtXbOWwjlyn8c1NnETtR5sqaJI0bOwjNxRjpf/uSkXFtX/KUklbpPE6iSbCCfYAVCMxWa9G4Eba7tt2buIKTcMpP7w79vOj9HjKQonG2eHywUu6BVJrkRbWVuZFFFGDJdpcZppy6dKmjfdLrJtRRQ+ucn8pAWOVfRFqq6Id3v+yktuXIHdcK+kAd4ZKlqk9EtzeflvrNFQUeeQb5cLP//aaAqiwBZ4Yqay8l+pBJtFA5kEMMm6Pev/ZqmqND4cxuK2FY3AD1KmmbwSOmmKvO0IHsva89KCVGCA6Qes+Y2oshdjK5P0RM5KOS6vaEKelMofhrlNl5y7F6rxh3scTHGUetBUqw6QLtsmOc7vQDKhryb/V0GYiWsC341jLJ0npUhxkqYhh9zOp1+tbijlOvXbEIQXHSNWHEYXo22+DADTUvqnLV6TqqCirJ9L3Ht9bODtbeR/NjEfeQwZpcp8MP3XTkUsHHBZMNxm4ow6Ij1FY6iClFccjTeX+wtHpjXtJ6yVfNAUNE6k6M7nm1SzRGuj7ItewSFJhY1eMIJchzp/BcjhC4rG0DWLxyCf7uM5BsEkEWCLjponGoA68FdVVupmCNTfnYImZnm1sFBmYm4/xXjMh3Ot988ChVcLUKr75znW7DcBcn3LbqgfiX3OiRTdktTaeBDOwOOqZroiNVOG3GTDo8PZjzOQvgSfCYe8cgMVbh4/hpgmMVOR9IYN1ngcIMr7IzN3dzavawrnhwjdDyr5it3PrQ9i2QxEukfPVfnpxXdmXoy+uHCXRHGjMmgZOGZOrIXGaBT1uq6Faj9nq+ZgE+6D0/ckunz4lUVgTXNNYM1gdBb6oVy56TueUAWv9CWyBBZBgMXBZAui8jQpOboZsNI4EZ6aafsCby5+uUMzpu0OOZ8105XrC6ja+iq/Xz5/Fx8uc4ObYsYsBepYdd1EyDsmGqoE59yfTejXsUnPLh1N839XDYX52SD+7NvhHwCyHmBvt5xf0mpT99keRyTfF31dvq2z9bJP/9fYbu/pcvv6E7O8Iuxj1yPTiBwAAAP//AwDLzmndWhUAAA==
71 | http_version:
72 | recorded_at: Fri, 13 Sep 2019 14:27:51 GMT
73 | - request:
74 | method: put
75 | uri: https://api.sandbox.braintreegateway.com/merchants/7rdg92j7bm7fk5h3/transactions/qdjwvf1z/submit_for_settlement
76 | body:
77 | encoding: UTF-8
78 | string: |
79 |
80 |
81 | 10.00
82 |
83 | headers:
84 | Accept-Encoding:
85 | - gzip
86 | Accept:
87 | - application/xml
88 | User-Agent:
89 | - Braintree Ruby Gem 2.98.0
90 | X-Apiversion:
91 | - '5'
92 | Content-Type:
93 | - application/xml
94 | Authorization:
95 | - Basic bXdqa2t4d2NwMzJja2huZjphOTI5OGY0M2IzMGM2OTlkYjMwNzJjYzRhMDBmN2Y0OQ==
96 | response:
97 | status:
98 | code: 200
99 | message: OK
100 | headers:
101 | Date:
102 | - Fri, 13 Sep 2019 14:27:52 GMT
103 | Content-Type:
104 | - application/xml; charset=utf-8
105 | Transfer-Encoding:
106 | - chunked
107 | X-Frame-Options:
108 | - SAMEORIGIN
109 | X-Xss-Protection:
110 | - 1; mode=block
111 | X-Content-Type-Options:
112 | - nosniff
113 | X-Authentication:
114 | - basic_auth
115 | X-User:
116 | - 3v249hqtptsg744y
117 | Vary:
118 | - Accept-Encoding
119 | Content-Encoding:
120 | - gzip
121 | Etag:
122 | - W/"ed8e3283994c88be937b9355ea73f35c"
123 | Cache-Control:
124 | - max-age=0, private, must-revalidate
125 | X-Runtime:
126 | - '0.242210'
127 | X-Request-Id:
128 | - 01-1568384871.840-92.223.152.178-12972594
129 | Content-Security-Policy:
130 | - frame-ancestors 'self'
131 | X-Broxyid:
132 | - 01-1568384871.840-92.223.152.178-12972594
133 | Strict-Transport-Security:
134 | - max-age=31536000; includeSubDomains
135 | body:
136 | encoding: ASCII-8BIT
137 | string: !binary |-
138 | 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
139 | http_version:
140 | recorded_at: Fri, 13 Sep 2019 14:27:52 GMT
141 | recorded_with: VCR 5.0.0
142 |
--------------------------------------------------------------------------------
/spec/fixtures/cassettes/gateway/settled_transaction.yml:
--------------------------------------------------------------------------------
1 | ---
2 | http_interactions:
3 | - request:
4 | method: post
5 | uri: https://api.sandbox.braintreegateway.com/merchants/7rdg92j7bm7fk5h3/transactions
6 | body:
7 | encoding: UTF-8
8 | string: |
9 |
10 |
11 | 40
12 | fake-valid-nonce
13 |
14 | true
15 |
16 | sale
17 |
18 | headers:
19 | Accept-Encoding:
20 | - gzip
21 | Accept:
22 | - application/xml
23 | User-Agent:
24 | - Braintree Ruby Gem 2.98.0
25 | X-Apiversion:
26 | - '5'
27 | Content-Type:
28 | - application/xml
29 | Authorization:
30 | - Basic bXdqa2t4d2NwMzJja2huZjphOTI5OGY0M2IzMGM2OTlkYjMwNzJjYzRhMDBmN2Y0OQ==
31 | response:
32 | status:
33 | code: 201
34 | message: Created
35 | headers:
36 | Date:
37 | - Fri, 13 Sep 2019 14:27:30 GMT
38 | Content-Type:
39 | - application/xml; charset=utf-8
40 | Transfer-Encoding:
41 | - chunked
42 | X-Frame-Options:
43 | - SAMEORIGIN
44 | X-Xss-Protection:
45 | - 1; mode=block
46 | X-Content-Type-Options:
47 | - nosniff
48 | X-Authentication:
49 | - basic_auth
50 | X-User:
51 | - 3v249hqtptsg744y
52 | Vary:
53 | - Accept-Encoding
54 | Content-Encoding:
55 | - gzip
56 | Etag:
57 | - W/"55837a4ca9eedd573fb5339a11a6cf5d"
58 | Cache-Control:
59 | - max-age=0, private, must-revalidate
60 | X-Runtime:
61 | - '0.405397'
62 | X-Request-Id:
63 | - 01-1568384849.487-92.223.152.178-12968285
64 | Content-Security-Policy:
65 | - frame-ancestors 'self'
66 | X-Broxyid:
67 | - 01-1568384849.487-92.223.152.178-12968285
68 | Strict-Transport-Security:
69 | - max-age=31536000; includeSubDomains
70 | body:
71 | encoding: ASCII-8BIT
72 | string: !binary |-
73 | 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
74 | http_version:
75 | recorded_at: Fri, 13 Sep 2019 14:27:30 GMT
76 | - request:
77 | method: put
78 | uri: https://api.sandbox.braintreegateway.com/merchants/7rdg92j7bm7fk5h3/transactions/kkket563/settle
79 | body:
80 | encoding: UTF-8
81 | string: ''
82 | headers:
83 | Accept-Encoding:
84 | - gzip
85 | Accept:
86 | - application/xml
87 | User-Agent:
88 | - Braintree Ruby Gem 2.98.0
89 | X-Apiversion:
90 | - '5'
91 | Content-Type:
92 | - application/xml
93 | Authorization:
94 | - Basic bXdqa2t4d2NwMzJja2huZjphOTI5OGY0M2IzMGM2OTlkYjMwNzJjYzRhMDBmN2Y0OQ==
95 | response:
96 | status:
97 | code: 200
98 | message: OK
99 | headers:
100 | Date:
101 | - Fri, 13 Sep 2019 14:27:32 GMT
102 | Content-Type:
103 | - application/xml; charset=utf-8
104 | Transfer-Encoding:
105 | - chunked
106 | X-Frame-Options:
107 | - SAMEORIGIN
108 | X-Xss-Protection:
109 | - 1; mode=block
110 | X-Content-Type-Options:
111 | - nosniff
112 | X-Authentication:
113 | - basic_auth
114 | X-User:
115 | - 3v249hqtptsg744y
116 | Vary:
117 | - Accept-Encoding
118 | Content-Encoding:
119 | - gzip
120 | Etag:
121 | - W/"6be7b4df5675b6e4e620434661e759e6"
122 | Cache-Control:
123 | - max-age=0, private, must-revalidate
124 | X-Runtime:
125 | - '0.839189'
126 | X-Request-Id:
127 | - 01-1568384850.887-92.223.152.178-12968568
128 | Content-Security-Policy:
129 | - frame-ancestors 'self'
130 | X-Broxyid:
131 | - 01-1568384850.887-92.223.152.178-12968568
132 | Strict-Transport-Security:
133 | - max-age=31536000; includeSubDomains
134 | body:
135 | encoding: ASCII-8BIT
136 | string: !binary |-
137 | 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
138 | http_version:
139 | recorded_at: Fri, 13 Sep 2019 14:27:32 GMT
140 | recorded_with: VCR 5.0.0
141 |
--------------------------------------------------------------------------------
/spec/fixtures/cassettes/gateway/complete.yml:
--------------------------------------------------------------------------------
1 | ---
2 | http_interactions:
3 | - request:
4 | method: post
5 | uri: https://api.sandbox.braintreegateway.com/merchants/7rdg92j7bm7fk5h3/customers
6 | body:
7 | encoding: UTF-8
8 | string: |
9 |
10 |
11 | fake-valid-nonce
12 |
13 | headers:
14 | Accept-Encoding:
15 | - gzip
16 | Accept:
17 | - application/xml
18 | User-Agent:
19 | - Braintree Ruby Gem 2.98.0
20 | X-Apiversion:
21 | - '5'
22 | Content-Type:
23 | - application/xml
24 | Authorization:
25 | - Basic bXdqa2t4d2NwMzJja2huZjphOTI5OGY0M2IzMGM2OTlkYjMwNzJjYzRhMDBmN2Y0OQ==
26 | response:
27 | status:
28 | code: 201
29 | message: Created
30 | headers:
31 | Date:
32 | - Fri, 13 Sep 2019 14:27:54 GMT
33 | Content-Type:
34 | - application/xml; charset=utf-8
35 | Transfer-Encoding:
36 | - chunked
37 | X-Frame-Options:
38 | - SAMEORIGIN
39 | X-Xss-Protection:
40 | - 1; mode=block
41 | X-Content-Type-Options:
42 | - nosniff
43 | X-Authentication:
44 | - basic_auth
45 | X-User:
46 | - 3v249hqtptsg744y
47 | Vary:
48 | - Accept-Encoding
49 | Content-Encoding:
50 | - gzip
51 | Etag:
52 | - W/"7cd94d9571863581960bf3200d7f3f29"
53 | Cache-Control:
54 | - max-age=0, private, must-revalidate
55 | X-Runtime:
56 | - '0.354179'
57 | X-Request-Id:
58 | - 01-1568384873.711-92.223.152.178-12972849
59 | Content-Security-Policy:
60 | - frame-ancestors 'self'
61 | X-Broxyid:
62 | - 01-1568384873.711-92.223.152.178-12972849
63 | Strict-Transport-Security:
64 | - max-age=31536000; includeSubDomains
65 | body:
66 | encoding: ASCII-8BIT
67 | string: !binary |-
68 | H4sIAGqne10AA6xWy3KjOhDd5ytc7AkG49ikMNlMJVVTNdncSe5NNlMCNUaxkBhJOHa+/kqYlx94nMrs3KdPS03rdLfDu01OR2sQknC2sNzrsTUClnBM2HJhPf28t+fWXXQVJqVUPAcRXY1GIcGRN5tPbgJ/dhM62jKgdiYZYsrW9kzgZeC9zeJ8lq6m2SR0+l7DTomQymYohxEjdGEpUYLlVC6KhjwJzwvEtkc45IjQI7TIODs+I0WbI+wdYknUifsEIAXYRmqktgUsLKxNRXKwIm/sBvY4sN3JT9e/9Wa3U/81dLqAKr4s8Ofiu4Dd/VXR7ZQAxXKX0pLyGFFTxZfJ8wd+CNTrf9/TH2+J/+PjZfr4LfFCp+PUH4GJshMksKzTQEKgrWW8+/4dorGYUKoFYCOMBUjZ4LunX/1u3rzGGm3Y+7rowx15+OFrwuDzN7edFkHtlUoAqCbxARJsFDBs6nyWRnmCKFFDVwlY6p4ZcBZcKv0GupEgCnx3PAudPtT/nJIpsa1gG9EiQ97ghx8yJ5cwWanfgCR/oJ4r+Ne6oD7li71QneEM6FLrlUX+2PXmc8NhLW5EbZvromcikc6stfuMjFOsZTpUAqM4M74IotETWzH+zvRJHdbRdqXkqU2kLBFLoM8/draBXy/wJ3qwoxp9Ky3h6OmfHrNFGz6GmKjuS3Zm50xRSZvEY84pIGZFpoKGWjk7cin069i6cUpqPqB36KGnCYFNQUSVj51zprLI1QPuCDzB3gISunzeeI9eoXtswIe5p4hKqKN6mXRTNXm4n8b/Ppf4waX4IVu/3gdvL24gko/V9pG9HAzgKjgDRFWmxdaTRA9raCRHS7BLQaNMqULeOg6SEpS8jgUizIy2pa7OO9pea/05BdrmwNSvHFTG8S/Kl9xZa51fF2x5B2xNBGeGsJCI4Zhv9Nhuz29v1GI0HRUjtupS20MbajWY/cidz93QqY3Gp1MRnPb6owFagoAC6YI8cu2rf3c+jsuk+mvQxXdYQ5NlLBNBCvOQ+5usa1XFV8CilQy8m3Xo7KzGVzLyu6zmYVw1hK4M0atVRCidTmd+kE6D1E3xZI5vkjRxNZD603mcasENhrZn/4XptgaWc1vi1YAgW38vQug0du16siLVqOhv9z2gmp9hPUvh5J+Dw0F7tP4/M3jOr/7zi//c2r9g6V+08s8u/DPr/sJlf+mqv3TRX7zm/7jk/8oG+nILhE5Pba0B2uzkFF39DwAA//8DABlnXNuxDAAA
69 | http_version:
70 | recorded_at: Fri, 13 Sep 2019 14:27:54 GMT
71 | - request:
72 | method: post
73 | uri: https://api.sandbox.braintreegateway.com/merchants/7rdg92j7bm7fk5h3/transactions
74 | body:
75 | encoding: UTF-8
76 | string: |
77 |
78 |
79 | 55.00
80 | ORDER0-PAYMENT0
81 | Solidus
82 |
83 | true
84 | true
85 |
86 | ks926v
87 |
88 | John
89 | Doe
90 | 10 Lovely Street Northwest
91 | Herndon
92 | 90210
93 | AL
94 | US
95 |
96 | 278369476
97 | sale
98 |
99 | headers:
100 | Accept-Encoding:
101 | - gzip
102 | Accept:
103 | - application/xml
104 | User-Agent:
105 | - Braintree Ruby Gem 2.98.0
106 | X-Apiversion:
107 | - '5'
108 | Content-Type:
109 | - application/xml
110 | Authorization:
111 | - Basic bXdqa2t4d2NwMzJja2huZjphOTI5OGY0M2IzMGM2OTlkYjMwNzJjYzRhMDBmN2Y0OQ==
112 | response:
113 | status:
114 | code: 201
115 | message: Created
116 | headers:
117 | Date:
118 | - Fri, 13 Sep 2019 14:27:55 GMT
119 | Content-Type:
120 | - application/xml; charset=utf-8
121 | Transfer-Encoding:
122 | - chunked
123 | X-Frame-Options:
124 | - SAMEORIGIN
125 | X-Xss-Protection:
126 | - 1; mode=block
127 | X-Content-Type-Options:
128 | - nosniff
129 | X-Authentication:
130 | - basic_auth
131 | X-User:
132 | - 3v249hqtptsg744y
133 | Vary:
134 | - Accept-Encoding
135 | Content-Encoding:
136 | - gzip
137 | Etag:
138 | - W/"d0ee0d4a2ad63634a4bb74a0bdfb8ee3"
139 | Cache-Control:
140 | - max-age=0, private, must-revalidate
141 | X-Runtime:
142 | - '0.437647'
143 | X-Request-Id:
144 | - 01-1568384875.006-92.223.152.178-12973110
145 | Content-Security-Policy:
146 | - frame-ancestors 'self'
147 | X-Broxyid:
148 | - 01-1568384875.006-92.223.152.178-12973110
149 | Strict-Transport-Security:
150 | - max-age=31536000; includeSubDomains
151 | body:
152 | encoding: ASCII-8BIT
153 | string: !binary |-
154 | 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
155 | http_version:
156 | recorded_at: Fri, 13 Sep 2019 14:27:55 GMT
157 | recorded_with: VCR 5.0.0
158 |
--------------------------------------------------------------------------------
/spec/models/solidus_paypal_braintree/response_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | RSpec.describe SolidusBraintree::Response do
4 | let(:failed_transaction) { nil }
5 | let(:error) do
6 | instance_double(
7 | Braintree::ValidationError,
8 | code: '12345',
9 | message: "Cannot refund a transaction unless it is settled."
10 | )
11 | end
12 |
13 | let(:error_result) do
14 | instance_double(
15 | Braintree::ErrorResult,
16 | success?: false,
17 | errors: [error],
18 | transaction: failed_transaction,
19 | params: { some: 'error' }
20 | )
21 | end
22 |
23 | let(:error_response) do
24 | described_class.build(error_result)
25 | end
26 |
27 | let(:successful_result) do
28 | transaction = instance_double(
29 | Braintree::Transaction,
30 | status: 'ok',
31 | id: 'abcdef',
32 | avs_error_response_code: nil,
33 | avs_street_address_response_code: 'M',
34 | avs_postal_code_response_code: 'M',
35 | cvv_response_code: 'I'
36 | )
37 |
38 | instance_double(
39 | Braintree::SuccessfulResult,
40 | success?: true,
41 | transaction: transaction
42 | )
43 | end
44 |
45 | let(:successful_response) do
46 | described_class.build(successful_result)
47 | end
48 |
49 | describe '.new' do
50 | it 'is private' do
51 | expect { described_class.new }.to raise_error(/private method/)
52 | end
53 | end
54 |
55 | describe '.build' do
56 | it { expect(error_response).to be_a ActiveMerchant::Billing::Response }
57 | it { expect(successful_response).to be_a ActiveMerchant::Billing::Response }
58 | end
59 |
60 | describe '#success?' do
61 | it { expect(error_response.success?).to be false }
62 | it { expect(successful_response.success?).to be true }
63 | end
64 |
65 | describe "#message" do
66 | context "with a success response" do
67 | subject { successful_response.message }
68 |
69 | it { is_expected.to eq "ok" }
70 | end
71 |
72 | context "with an error response" do
73 | subject { error_response.message }
74 |
75 | context "with a Braintree error" do
76 | it { is_expected.to eq "Cannot refund a transaction unless it is settled. (12345)" }
77 | end
78 |
79 | context "with a settlement_declined status" do
80 | let(:error) { nil }
81 | let(:failed_transaction) do
82 | instance_double(
83 | Braintree::Transaction,
84 | id: 'abcdef',
85 | status: "settlement_declined",
86 | processor_settlement_response_code: "4001",
87 | processor_settlement_response_text: "Settlement Declined",
88 | avs_error_response_code: nil,
89 | avs_street_address_response_code: nil,
90 | avs_postal_code_response_code: nil,
91 | cvv_response_code: nil
92 | )
93 | end
94 |
95 | it { is_expected.to eq "Settlement Declined (4001)" }
96 | end
97 |
98 | context "with a gateway_rejected status" do
99 | let(:error) { nil }
100 | let(:failed_transaction) do
101 | instance_double(
102 | Braintree::Transaction,
103 | id: 'abcdef',
104 | status: "gateway_rejected",
105 | gateway_rejection_reason: "cvv",
106 | avs_error_response_code: nil,
107 | avs_street_address_response_code: nil,
108 | avs_postal_code_response_code: nil,
109 | cvv_response_code: nil
110 | )
111 | end
112 |
113 | it { is_expected.to eq "CVV check failed." }
114 | end
115 |
116 | context "with a processor_declined status" do
117 | let(:error) { nil }
118 | let(:failed_transaction) do
119 | instance_double(
120 | Braintree::Transaction,
121 | id: 'abcdef',
122 | status: "processor_declined",
123 | processor_response_code: '2001',
124 | processor_response_text: 'Insufficient Funds',
125 | avs_error_response_code: nil,
126 | avs_street_address_response_code: nil,
127 | avs_postal_code_response_code: nil,
128 | cvv_response_code: nil
129 | )
130 | end
131 |
132 | it { is_expected.to eq "Insufficient Funds (2001)" }
133 | end
134 |
135 | context 'with other transaction status' do
136 | let(:error) { nil }
137 | let(:failed_transaction) do
138 | instance_double(
139 | Braintree::Transaction,
140 | id: 'abcdef',
141 | status: "authorization_expired",
142 | avs_error_response_code: nil,
143 | avs_street_address_response_code: nil,
144 | avs_postal_code_response_code: nil,
145 | cvv_response_code: nil
146 | )
147 | end
148 |
149 | it { is_expected.to eq 'Payment authorization has expired.' }
150 | end
151 |
152 | context 'with other transaction status that is not translated' do
153 | let(:error) { nil }
154 | let(:failed_transaction) do
155 | instance_double(
156 | Braintree::Transaction,
157 | id: 'abcdef',
158 | status: "something_bad_happened",
159 | avs_error_response_code: nil,
160 | avs_street_address_response_code: nil,
161 | avs_postal_code_response_code: nil,
162 | cvv_response_code: nil
163 | )
164 | end
165 |
166 | it { is_expected.to eq 'Something bad happened' }
167 | end
168 | end
169 | end
170 |
171 | describe '#avs_result' do
172 | context 'with a successful result' do
173 | subject { described_class.build(successful_result).avs_result }
174 |
175 | it 'includes AVS response code' do
176 | expect(subject['code']).to eq 'M'
177 | end
178 |
179 | it 'includes AVS response message' do
180 | expect(subject['message']).to eq 'Street address and postal code match.'
181 | end
182 | end
183 |
184 | context 'with an error result' do
185 | subject { described_class.build(error_result).avs_result }
186 |
187 | let(:failed_transaction) do
188 | instance_double(
189 | Braintree::Transaction,
190 | id: 'abcdef',
191 | avs_error_response_code: 'E',
192 | avs_street_address_response_code: nil,
193 | avs_postal_code_response_code: nil,
194 | cvv_response_code: nil
195 | )
196 | end
197 |
198 | it 'includes AVS response code' do
199 | expect(subject['code']).to eq 'E'
200 | end
201 |
202 | it 'includes AVS response message' do
203 | expect(subject['message']).to eq 'AVS data is invalid or AVS is not allowed for this card type.'
204 | end
205 |
206 | context 'without transaction' do
207 | let(:failed_transaction) { nil }
208 |
209 | it 'includes no AVS response' do
210 | expect(subject['message']).to be_nil
211 | expect(subject['code']).to be_nil
212 | end
213 | end
214 | end
215 | end
216 |
217 | describe '#cvv_result' do
218 | context 'with a successful result' do
219 | subject { described_class.build(successful_result).cvv_result }
220 |
221 | it 'does not include CVV response code' do
222 | expect(subject['code']).to be_nil
223 | end
224 |
225 | it 'does not include CVV response message' do
226 | expect(subject['message']).to be_nil
227 | end
228 | end
229 |
230 | context 'with an error result' do
231 | subject { described_class.build(error_result).cvv_result }
232 |
233 | let(:failed_transaction) do
234 | instance_double(
235 | Braintree::Transaction,
236 | id: 'abcdef',
237 | avs_error_response_code: nil,
238 | avs_street_address_response_code: nil,
239 | avs_postal_code_response_code: nil,
240 | cvv_response_code: 'N'
241 | )
242 | end
243 |
244 | it 'includes CVV response code' do
245 | expect(subject['code']).to eq 'N'
246 | end
247 |
248 | it 'includes CVV response message' do
249 | expect(subject['message']).to eq 'CVV does not match'
250 | end
251 |
252 | context 'without transaction' do
253 | let(:failed_transaction) { nil }
254 |
255 | it 'includes no CVV response' do
256 | expect(subject['message']).to be_nil
257 | expect(subject['code']).to be_nil
258 | end
259 | end
260 | end
261 | end
262 |
263 | describe '#params' do
264 | context "with an error response" do
265 | subject { error_response.params }
266 |
267 | it 'includes request params' do
268 | expect(subject).to eq({ 'some' => 'error' })
269 | end
270 | end
271 | end
272 |
273 | describe '#authorization' do
274 | it 'is whatever the b.t. transaction id was' do
275 | expect(successful_response.authorization).to eq 'abcdef'
276 | end
277 |
278 | it { expect(error_response.authorization).to be_nil }
279 | end
280 | end
281 |
--------------------------------------------------------------------------------
/spec/fixtures/cassettes/gateway/authorize/merchant_account/EUR.yml:
--------------------------------------------------------------------------------
1 | ---
2 | http_interactions:
3 | - request:
4 | method: post
5 | uri: https://api.sandbox.braintreegateway.com/merchants/7rdg92j7bm7fk5h3/transactions
6 | body:
7 | encoding: UTF-8
8 | string: |
9 |
10 |
11 | 10.00
12 | Solidus
13 |
14 | true
15 |
16 | paypal+europe@example.com
17 |
18 |
19 | stembolt_EUR
20 | fake-valid-nonce
21 |
22 | Bruce
23 | Wayne
24 | 42 Spruce Lane Apt 312
25 | Gotham
26 | 90210
27 | CA
28 | US
29 |
30 | sale
31 |
32 | headers:
33 | Accept-Encoding:
34 | - gzip
35 | Accept:
36 | - application/xml
37 | User-Agent:
38 | - Braintree Ruby Gem 2.98.0
39 | X-Apiversion:
40 | - '5'
41 | Content-Type:
42 | - application/xml
43 | Authorization:
44 | - Basic bXdqa2t4d2NwMzJja2huZjphOTI5OGY0M2IzMGM2OTlkYjMwNzJjYzRhMDBmN2Y0OQ==
45 | response:
46 | status:
47 | code: 201
48 | message: Created
49 | headers:
50 | Date:
51 | - Fri, 13 Sep 2019 14:27:18 GMT
52 | Content-Type:
53 | - application/xml; charset=utf-8
54 | Transfer-Encoding:
55 | - chunked
56 | X-Frame-Options:
57 | - SAMEORIGIN
58 | X-Xss-Protection:
59 | - 1; mode=block
60 | X-Content-Type-Options:
61 | - nosniff
62 | X-Authentication:
63 | - basic_auth
64 | X-User:
65 | - 3v249hqtptsg744y
66 | Vary:
67 | - Accept-Encoding
68 | Content-Encoding:
69 | - gzip
70 | Etag:
71 | - W/"b7263541ccba70a329264729c82af05d"
72 | Cache-Control:
73 | - max-age=0, private, must-revalidate
74 | X-Runtime:
75 | - '0.529816'
76 | X-Request-Id:
77 | - 02-1568384837.829-92.223.152.178-13019098
78 | Content-Security-Policy:
79 | - frame-ancestors 'self'
80 | X-Broxyid:
81 | - 02-1568384837.829-92.223.152.178-13019098
82 | Strict-Transport-Security:
83 | - max-age=31536000; includeSubDomains
84 | body:
85 | encoding: ASCII-8BIT
86 | string: !binary |-
87 | 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
88 | http_version:
89 | recorded_at: Fri, 13 Sep 2019 14:27:19 GMT
90 | - request:
91 | method: get
92 | uri: https://api.sandbox.braintreegateway.com/merchants/7rdg92j7bm7fk5h3/transactions/5vh40nwq
93 | body:
94 | encoding: US-ASCII
95 | string: ''
96 | headers:
97 | Accept-Encoding:
98 | - gzip
99 | Accept:
100 | - application/xml
101 | User-Agent:
102 | - Braintree Ruby Gem 2.98.0
103 | X-Apiversion:
104 | - '5'
105 | Content-Type:
106 | - application/xml
107 | Authorization:
108 | - Basic bXdqa2t4d2NwMzJja2huZjphOTI5OGY0M2IzMGM2OTlkYjMwNzJjYzRhMDBmN2Y0OQ==
109 | response:
110 | status:
111 | code: 200
112 | message: OK
113 | headers:
114 | Date:
115 | - Fri, 13 Sep 2019 14:27:20 GMT
116 | Content-Type:
117 | - application/xml; charset=utf-8
118 | Transfer-Encoding:
119 | - chunked
120 | X-Frame-Options:
121 | - SAMEORIGIN
122 | X-Xss-Protection:
123 | - 1; mode=block
124 | X-Content-Type-Options:
125 | - nosniff
126 | X-Authentication:
127 | - basic_auth
128 | X-User:
129 | - 3v249hqtptsg744y
130 | Vary:
131 | - Accept-Encoding
132 | Content-Encoding:
133 | - gzip
134 | Etag:
135 | - W/"e52a19fc2edb6c5b72a8c0125098607b"
136 | Cache-Control:
137 | - max-age=0, private, must-revalidate
138 | X-Runtime:
139 | - '0.162793'
140 | X-Request-Id:
141 | - 01-1568384839.628-92.223.152.178-12966562
142 | Content-Security-Policy:
143 | - frame-ancestors 'self'
144 | X-Broxyid:
145 | - 01-1568384839.628-92.223.152.178-12966562
146 | Strict-Transport-Security:
147 | - max-age=31536000; includeSubDomains
148 | body:
149 | encoding: ASCII-8BIT
150 | string: !binary |-
151 | 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
152 | http_version:
153 | recorded_at: Fri, 13 Sep 2019 14:27:20 GMT
154 | recorded_with: VCR 5.0.0
155 |
--------------------------------------------------------------------------------
/spec/fixtures/cassettes/checkout/valid_credit_card.yml:
--------------------------------------------------------------------------------
1 | ---
2 | http_interactions:
3 | - request:
4 | method: post
5 | uri: https://api.sandbox.braintreegateway.com/merchants/652zwb86tqk9v5wz/customers
6 | body:
7 | encoding: UTF-8
8 | string: |
9 |
10 |
11 | solidus@example.com
12 | fake-valid-nonce
13 |
14 | headers:
15 | Accept-Encoding:
16 | - gzip
17 | Accept:
18 | - application/xml
19 | User-Agent:
20 | - Braintree Ruby Gem 3.4.0
21 | X-Apiversion:
22 | - '6'
23 | Content-Type:
24 | - application/xml
25 | Authorization:
26 | - Basic bnk4c2MzYjY0OHE3eDVoNjpmM2VjZWNlNTI5MTIwMjAzMGU1MDQwMWY1MGMwZWNhNw==
27 | response:
28 | status:
29 | code: 201
30 | message: ''
31 | headers:
32 | Date:
33 | - Fri, 28 Oct 2022 11:48:35 GMT
34 | Content-Type:
35 | - application/xml; charset=utf-8
36 | X-Frame-Options:
37 | - SAMEORIGIN
38 | X-Xss-Protection:
39 | - 1; mode=block
40 | X-Content-Type-Options:
41 | - nosniff
42 | X-Download-Options:
43 | - noopen
44 | X-Permitted-Cross-Domain-Policies:
45 | - none
46 | Referrer-Policy:
47 | - strict-origin-when-cross-origin
48 | X-Authentication:
49 | - basic_auth
50 | X-User:
51 | - 4b9yb8scv4785hg6
52 | Vary:
53 | - Accept-Encoding, Origin
54 | Content-Encoding:
55 | - gzip
56 | Etag:
57 | - W/"fc78821a32ceefb0bb66822d19642e82"
58 | Cache-Control:
59 | - max-age=0, private, must-revalidate
60 | X-Runtime:
61 | - '0.359927'
62 | X-Request-Id:
63 | - 2bde7385-30c6-4e06-b694-ea49ffdab2ff
64 | Content-Security-Policy:
65 | - frame-ancestors 'self'
66 | X-Broxyid:
67 | - 2bde7385-30c6-4e06-b694-ea49ffdab2ff
68 | Strict-Transport-Security:
69 | - max-age=31536000; includeSubDomains
70 | Paypal-Debug-Id:
71 | - 83f2d6168bcf4
72 | Transfer-Encoding:
73 | - chunked
74 | body:
75 | encoding: ASCII-8BIT
76 | string: !binary |-
77 | H4sIAJPBW2MAA6xWy3KjOhDd5ytc7AkG7AlOYXIXU0nVVCWbO8ncyWZKoMbWWEiMJGyTr78S5uUHjlOZHTp9Wmpap1sd3m0zOlqDkISzueVej60RsIRjwhZz6/n7vR1Yd9FVmBRS8QxEdDUahQRHX4Kb8exm4o9DR68MqI3JEjFlG+vUe9vEwRf1ZzVbTzdvodO3GnZKhFQ2QxmMGKFzS4kCLKcyUTRkSXiWI1Ye4ZAhQiPJKcGF/Ae2KMspXGt26OxMhpQvOTveMkXbI2wDsSTqxPECkAJsIzVSZQ5zC+ulIhlYkTf2PNsd217w3XVvJ8GtP30Nnc6h8i9y/DH/zmF3fnUHdkqAYrkLaUF5jKhJ6k//5Q0/zNTrf9/Sp98L//Hryn/6+rgJnY5T/wQmyk6QwLIOAwmBSstY9+07RGMxoVTrwUYYC5CywXdKKFkjgRprpGLvy6QPd+RhHdSEQTU0p53WRG2VSgCoJvABEmwVMGzyfJZGeYIoUUNHCVjoEhow5lwqfQe6riCaTdzxTej0of7vFEyJsoJtRPMl8gZ//JDpX8Jkhb4DkrxDPZPwqo7MNjGIoV0+Vyj1Lp8sl2oPZ0C6WtIsmoxdLwgMh7W40b1tjoteiEQ6snbdZyw5xVrJQ1kyojQNjyAaPbMV4xtdIz2so+2yzVObSFkglkCff2xsHT+f4A+UaUe9pN2cIB/tY0pJ6WqJnv/tObRow8cQE9VlZLfsjCkqaJOAmHMKiFmRuQlDrYwduRD6lm1dowU1iehtemhpXGCbE1HFY2ecqWXkevo5OQRPsEtAwlyDv0ev0D024MPYU0Ql1F69SLpEJg/30/jHS4EfXIofluvX+9nvn+6sfPRkGf/4xl4P233lvwRE1VLrtqeuHtbQSIYWYBeCRkulcnnrOEhKUPI6Fogw00gXOkEbVJqX1clRmQFTvzJQS45/Ub7gzlqXzHXOFnfA1kRwZghziRiO+VY/Eu3+7Yla16Y4Y8RWXWh7aEOtnoFJ5AaBGzr1orHpUASnvVJrgJYgIEc6IU9c2+rvzsZxkVRzSeffYQ1NFrFMBMnNXe6/m13VK74CFgl/5WXxYhE6u3VjLRj5UzSNU2+tc0P0U66lgv3pdIpT8HEwvYGJG7hp4qVwo6FkPJnpxjbk2u79F1rlGljGbYlXA6ps7T0PocPY1exQToi0GagNFyu7Sgd5G5T9KWo9lDgHU8keUDX1sG7wcHKoOez+R2PLR7rh+ZHl/MBybly5YFi5aFQ5O6icGVMuHFIuHVEuHVAuHk/eHU7eHU3+yrv56VoLnZ4c2wXoZae36Op/AAAA//8DAOjCcKiZDQAA
78 | recorded_at: Fri, 28 Oct 2022 11:48:35 GMT
79 | - request:
80 | method: post
81 | uri: https://api.sandbox.braintreegateway.com/merchants/652zwb86tqk9v5wz/transactions
82 | body:
83 | encoding: UTF-8
84 | string: |
85 |
86 |
87 | 20.00
88 | R9999999-123ABC
89 | Solidus
90 |
91 | true
92 |
93 | r3k2mbgg
94 |
95 | John
96 | Doe
97 | 10 Lovely Street Northwest
98 | Herndon
99 | 21088-0255
100 | AL
101 | US
102 |
103 | 687097430
104 | sale
105 |
106 | headers:
107 | Accept-Encoding:
108 | - gzip
109 | Accept:
110 | - application/xml
111 | User-Agent:
112 | - Braintree Ruby Gem 3.4.0
113 | X-Apiversion:
114 | - '6'
115 | Content-Type:
116 | - application/xml
117 | Authorization:
118 | - Basic bnk4c2MzYjY0OHE3eDVoNjpmM2VjZWNlNTI5MTIwMjAzMGU1MDQwMWY1MGMwZWNhNw==
119 | response:
120 | status:
121 | code: 201
122 | message: ''
123 | headers:
124 | Date:
125 | - Fri, 28 Oct 2022 11:48:36 GMT
126 | Content-Type:
127 | - application/xml; charset=utf-8
128 | X-Frame-Options:
129 | - SAMEORIGIN
130 | X-Xss-Protection:
131 | - 1; mode=block
132 | X-Content-Type-Options:
133 | - nosniff
134 | X-Download-Options:
135 | - noopen
136 | X-Permitted-Cross-Domain-Policies:
137 | - none
138 | Referrer-Policy:
139 | - strict-origin-when-cross-origin
140 | X-Authentication:
141 | - basic_auth
142 | X-User:
143 | - 4b9yb8scv4785hg6
144 | Vary:
145 | - Accept-Encoding, Origin
146 | Content-Encoding:
147 | - gzip
148 | Etag:
149 | - W/"b235108105829caa5ec570cef992b0d5"
150 | Cache-Control:
151 | - max-age=0, private, must-revalidate
152 | X-Runtime:
153 | - '0.458590'
154 | X-Request-Id:
155 | - 75cd5459-a138-42d3-a41b-85fcd3baf633
156 | Content-Security-Policy:
157 | - frame-ancestors 'self'
158 | X-Broxyid:
159 | - 75cd5459-a138-42d3-a41b-85fcd3baf633
160 | Strict-Transport-Security:
161 | - max-age=31536000; includeSubDomains
162 | Paypal-Debug-Id:
163 | - 6370d1ef7ffe4
164 | Transfer-Encoding:
165 | - chunked
166 | body:
167 | encoding: ASCII-8BIT
168 | string: !binary |-
169 | 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
170 | recorded_at: Fri, 28 Oct 2022 11:48:36 GMT
171 | recorded_with: VCR 6.1.0
172 |
--------------------------------------------------------------------------------
/spec/models/solidus_paypal_braintree/transaction_import_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe SolidusBraintree::TransactionImport do
4 | let(:order) { Spree::Order.new }
5 | let!(:country) { create :country, iso: "US" }
6 | let(:braintree_gateway) { SolidusBraintree::Gateway.new }
7 | let(:transaction_address) { nil }
8 | let(:transaction) do
9 | SolidusBraintree::Transaction.new(
10 | nonce: 'abcd1234',
11 | payment_type: "ApplePayCard",
12 | address: transaction_address,
13 | payment_method: braintree_gateway,
14 | email: "test@example.com",
15 | phone: "123-456-6789"
16 | )
17 | end
18 | let(:transaction_import) { described_class.new(order, transaction) }
19 |
20 | describe "#valid?" do
21 | subject { transaction_import.valid? }
22 |
23 | it { is_expected.to be true }
24 |
25 | context "with invalid transaction" do
26 | let(:transaction) { SolidusBraintree::Transaction.new }
27 |
28 | it { is_expected.to be false }
29 | end
30 |
31 | context "with invalid address" do
32 | let(:transaction_address) do
33 | SolidusBraintree::TransactionAddress.new(
34 | name: "Bruce Wayne",
35 | address_line_1: "42 Spruce Lane",
36 | city: "Gotham",
37 | state_code: "WA",
38 | country_code: "US"
39 | )
40 | end
41 |
42 | before do
43 | create(:state, state_code: "WA")
44 | end
45 |
46 | it { is_expected.to be false }
47 |
48 | it "sets useful error messages" do
49 | transaction_import.valid?
50 | expect(transaction_import.errors.full_messages).
51 | to eq ["Address is invalid", "Address Zip can't be blank"]
52 | end
53 | end
54 | end
55 |
56 | describe '#source' do
57 | subject { described_class.new(order, transaction).source }
58 |
59 | it { is_expected.to be_a SolidusBraintree::Source }
60 |
61 | it 'takes the nonce from the transaction' do
62 | expect(subject.nonce).to eq 'abcd1234'
63 | end
64 |
65 | it 'takes the payment type from the transaction' do
66 | expect(subject.payment_type).to eq 'ApplePayCard'
67 | end
68 |
69 | it 'takes the payment method from the transaction' do
70 | expect(subject.payment_method).to eq braintree_gateway
71 | end
72 |
73 | it 'takes the paypal funding source from the transaction' do
74 | transaction.paypal_funding_source = 'paypal'
75 |
76 | expect(subject.paypal_funding_source).to eq('paypal')
77 | end
78 |
79 | context 'when order has a user' do
80 | let(:user) { Spree.user_class.new }
81 | let(:order) { Spree::Order.new user: user }
82 |
83 | it 'associates user to the source' do
84 | expect(subject.user).to eq user
85 | end
86 | end
87 | end
88 |
89 | describe '#user' do
90 | subject { described_class.new(order, transaction).user }
91 |
92 | it { is_expected.to be_nil }
93 |
94 | context 'when order has a user' do
95 | let(:user) { Spree.user_class.new }
96 | let(:order) { Spree::Order.new user: user }
97 |
98 | it { is_expected.to eq user }
99 | end
100 | end
101 |
102 | describe '#import!' do
103 | subject { described_class.new(order, transaction).import!(end_state) }
104 |
105 | let(:store) { create :store }
106 | let(:variant) { create :variant }
107 | let(:line_item) { Spree::LineItem.new(variant: variant, quantity: 1, price: 10) }
108 | let(:address) { create :address, country: country }
109 | let(:order) {
110 | Spree::Order.create(
111 | number: "R999999999",
112 | store: store,
113 | line_items: [line_item],
114 | ship_address: address,
115 | currency: 'USD',
116 | total: 10,
117 | email: 'test@example.com'
118 | )
119 | }
120 | let(:payment_method) { create_gateway }
121 |
122 | let(:transaction_address) { nil }
123 | let(:end_state) { 'confirm' }
124 |
125 | let(:transaction) do
126 | SolidusBraintree::Transaction.new(
127 | nonce: 'fake-valid-nonce',
128 | payment_method: payment_method,
129 | address: transaction_address,
130 | payment_type: SolidusBraintree::Source::PAYPAL,
131 | phone: '123-456-7890',
132 | email: 'user@example.com'
133 | )
134 | end
135 |
136 | before do
137 | # create a shipping method so we can push through to the end
138 | create :shipping_method, cost: 5
139 |
140 | # ensure payments have the same number so VCR matches the request body
141 | allow_any_instance_of(Spree::Payment).
142 | to receive(:generate_identifier).
143 | and_return("ABCD1234")
144 | end
145 |
146 | context "with passing validation", vcr: {
147 | cassette_name: 'transaction/import/valid',
148 | match_requests_on: [:braintree_uri]
149 | } do
150 | context "when order end state is confirm" do
151 | it 'advances order to confirm state' do
152 | subject
153 | expect(order.state).to eq 'confirm'
154 | end
155 |
156 | it 'has a payment for the cost of line items + shipment' do
157 | subject
158 | expect(order.payments.first.amount).to eq 15
159 | end
160 |
161 | it 'is complete and capturable', aggregate_failures: true, vcr: {
162 | cassette_name: 'transaction/import/valid/capture',
163 | match_requests_on: [:braintree_uri]
164 | } do
165 | subject
166 | order.complete
167 |
168 | expect(order).to be_complete
169 | expect(order.payments.first).to be_pending
170 |
171 | order.payments.first.capture!
172 | # need to reload, as capture will update the order
173 | expect(order.reload).to be_paid
174 | end
175 | end
176 |
177 | context "when order end state is delivery" do
178 | let(:end_state) { 'delivery' }
179 |
180 | it "advances the order to delivery" do
181 | subject
182 | expect(order.state).to eq 'delivery'
183 | end
184 |
185 | it "has a payment for the cost of line items" do
186 | subject
187 | expect(order.payments.first.amount).to eq 10
188 | end
189 | end
190 |
191 | context 'when transaction has address' do
192 | let!(:new_york) { create :state, country: country, abbr: 'NY' }
193 |
194 | let(:transaction_address) do
195 | SolidusBraintree::TransactionAddress.new(
196 | country_code: 'US',
197 | name: 'Thaddeus Venture',
198 | city: 'New York',
199 | state_code: 'NY',
200 | address_line_1: '350 5th Ave',
201 | zip: '10118'
202 | )
203 | end
204 |
205 | it 'uses the new address', aggregate_failures: true do
206 | subject
207 | expect(order.shipping_address.address1).to eq '350 5th Ave'
208 | expect(order.shipping_address.country).to eq country
209 | expect(order.shipping_address.state).to eq new_york
210 | end
211 |
212 | context 'when transaction has paypal funding source' do
213 | it 'saves it to the payment source' do
214 | transaction.paypal_funding_source = 'paypal'
215 |
216 | subject
217 |
218 | source = SolidusBraintree::Source.last
219 | expect(source.paypal_funding_source).to eq('paypal')
220 | end
221 | end
222 |
223 | context 'with a tax category' do
224 | before do
225 | zone = Spree::Zone.create name: 'nyc tax'
226 | zone.members << Spree::ZoneMember.new(zoneable: new_york)
227 | create :tax_rate, zone: zone
228 | end
229 |
230 | it 'includes the tax in the payment' do
231 | subject
232 | expect(order.payments.first.amount).to eq 16
233 | end
234 | end
235 |
236 | context 'with a less expensive tax category' do
237 | before do
238 | original_zone = Spree::Zone.create name: 'first address tax'
239 | original_zone.members << Spree::ZoneMember.new(zoneable: address.state)
240 | original_tax_rate = create :tax_rate, zone: original_zone, amount: 0.2
241 |
242 | # new address is NY
243 | ny_zone = Spree::Zone.create name: 'nyc tax'
244 | ny_zone.members << Spree::ZoneMember.new(zoneable: new_york)
245 | create :tax_rate, tax_categories: [original_tax_rate.tax_categories.first], zone: ny_zone, amount: 0.1
246 | end
247 |
248 | it 'includes the lower tax in the payment' do
249 | # so shipments and shipment cost is calculated before transaction import
250 | order.next!; order.next!
251 | # precondition
252 | expect(order.additional_tax_total).to eq 2
253 | expect(order.total).to eq 17
254 |
255 | subject
256 | expect(order.additional_tax_total).to eq 1
257 | expect(order.payments.first.amount).to eq 16
258 | end
259 | end
260 | end
261 | end
262 |
263 | context "when validation fails" do
264 | let(:transaction_address) do
265 | SolidusBraintree::TransactionAddress.new(
266 | country_code: 'US',
267 | name: 'Thaddeus Venture',
268 | city: 'New York',
269 | state_code: 'NY',
270 | address_line_1: '350 5th Ave'
271 | )
272 | end
273 |
274 | it "raises an error with the validation messages" do
275 | expect { subject }.to raise_error(
276 | SolidusBraintree::TransactionImport::InvalidImportError
277 | )
278 | end
279 | end
280 |
281 | context "with checkout flow", vcr: {
282 | cassette_name: 'transaction/import/valid',
283 | match_requests_on: [:braintree_uri]
284 | } do
285 | it "is not restarted by default" do
286 | expect(order).not_to receive(:restart_checkout_flow)
287 | subject
288 | end
289 |
290 | context "with restart_checkout: true" do
291 | subject do
292 | described_class.new(order, transaction).import!(end_state, restart_checkout: true)
293 | end
294 |
295 | it "is restarted" do
296 | expect(order).to receive(:restart_checkout_flow)
297 | subject
298 | end
299 | end
300 | end
301 | end
302 | end
303 |
--------------------------------------------------------------------------------
/spec/fixtures/cassettes/source/card_type.yml:
--------------------------------------------------------------------------------
1 | ---
2 | http_interactions:
3 | - request:
4 | method: post
5 | uri: https://api.sandbox.braintreegateway.com/merchants/7rdg92j7bm7fk5h3/customers
6 | body:
7 | encoding: UTF-8
8 | string: |
9 |
10 |
11 |
12 | headers:
13 | Accept-Encoding:
14 | - gzip
15 | Accept:
16 | - application/xml
17 | User-Agent:
18 | - Braintree Ruby Gem 2.98.0
19 | X-Apiversion:
20 | - '5'
21 | Content-Type:
22 | - application/xml
23 | Authorization:
24 | - Basic bXdqa2t4d2NwMzJja2huZjphOTI5OGY0M2IzMGM2OTlkYjMwNzJjYzRhMDBmN2Y0OQ==
25 | response:
26 | status:
27 | code: 201
28 | message: Created
29 | headers:
30 | Date:
31 | - Fri, 13 Sep 2019 14:26:31 GMT
32 | Content-Type:
33 | - application/xml; charset=utf-8
34 | Transfer-Encoding:
35 | - chunked
36 | X-Frame-Options:
37 | - SAMEORIGIN
38 | X-Xss-Protection:
39 | - 1; mode=block
40 | X-Content-Type-Options:
41 | - nosniff
42 | X-Authentication:
43 | - basic_auth
44 | X-User:
45 | - 3v249hqtptsg744y
46 | Vary:
47 | - Accept-Encoding
48 | Content-Encoding:
49 | - gzip
50 | Etag:
51 | - W/"a8e61a976412f48ed3e7b4d6aae9bf48"
52 | Cache-Control:
53 | - max-age=0, private, must-revalidate
54 | X-Runtime:
55 | - '0.132308'
56 | X-Request-Id:
57 | - 02-1568384790.635-92.223.152.178-13010244
58 | Content-Security-Policy:
59 | - frame-ancestors 'self'
60 | X-Broxyid:
61 | - 02-1568384790.635-92.223.152.178-13010244
62 | Strict-Transport-Security:
63 | - max-age=31536000; includeSubDomains
64 | body:
65 | encoding: ASCII-8BIT
66 | string: !binary |-
67 | H4sIABene10AA5RRz0+DMBS+768gvVcG1QELsIvRxGTxMo3u9kYfUG0LaYtu/PXCtjgT9ODx+9X3vtd0tVfS+0BjRaMzElzNiYe6aLjQVUaeNnc0Jqt8lhaddY1Ck888LxU8j+OIxQvGWOoPaCQHsahBOzrgyPAqCd+inYrK95t6MP1UR3cpjHVUg0JPC5kRZzok/lGS8JdSNKoFfZjwqEDICdvWjZ6+UcJ+wn3izgr3yzyD4JBTcJ47tJgRPkAnFJI8nAcJnSc0YJvgehkulizYpv4lcMx3Lf9f/hI4zT8enZYCJbenlSrZ7ECOV3xlzz2/T9z25aF8vK3Yuq/Cdb/uU//iOZfgwtECDLfnNcAYOJw7AucGrcWJNrT5/vMvAAAA//8DAGGcIVomAgAA
68 | http_version:
69 | recorded_at: Fri, 13 Sep 2019 14:26:31 GMT
70 | - request:
71 | method: post
72 | uri: https://api.sandbox.braintreegateway.com/merchants/7rdg92j7bm7fk5h3/payment_methods
73 | body:
74 | encoding: UTF-8
75 | string: |
76 |
77 |
78 | fake-valid-country-of-issuance-usa-nonce
79 | 887386333
80 |
81 | headers:
82 | Accept-Encoding:
83 | - gzip
84 | Accept:
85 | - application/xml
86 | User-Agent:
87 | - Braintree Ruby Gem 2.98.0
88 | X-Apiversion:
89 | - '5'
90 | Content-Type:
91 | - application/xml
92 | Authorization:
93 | - Basic bXdqa2t4d2NwMzJja2huZjphOTI5OGY0M2IzMGM2OTlkYjMwNzJjYzRhMDBmN2Y0OQ==
94 | response:
95 | status:
96 | code: 201
97 | message: Created
98 | headers:
99 | Date:
100 | - Fri, 13 Sep 2019 14:26:32 GMT
101 | Content-Type:
102 | - application/xml; charset=utf-8
103 | Transfer-Encoding:
104 | - chunked
105 | X-Frame-Options:
106 | - SAMEORIGIN
107 | X-Xss-Protection:
108 | - 1; mode=block
109 | X-Content-Type-Options:
110 | - nosniff
111 | X-Authentication:
112 | - basic_auth
113 | X-User:
114 | - 3v249hqtptsg744y
115 | Vary:
116 | - Accept-Encoding
117 | Content-Encoding:
118 | - gzip
119 | Etag:
120 | - W/"542e7d55e2ec7398658887008e4c4a7e"
121 | Cache-Control:
122 | - max-age=0, private, must-revalidate
123 | X-Runtime:
124 | - '0.241721'
125 | X-Request-Id:
126 | - 02-1568384791.617-92.223.152.178-13010465
127 | Content-Security-Policy:
128 | - frame-ancestors 'self'
129 | X-Broxyid:
130 | - 02-1568384791.617-92.223.152.178-13010465
131 | Strict-Transport-Security:
132 | - max-age=31536000; includeSubDomains
133 | body:
134 | encoding: ASCII-8BIT
135 | string: !binary |-
136 | H4sIABine10AA6xVwXLaMBC98xWM78Y2dgnOGGd6SW49tEk7zSWzthasIkuuJJPw910ZgwmBtJ32ht6+Xe0+vxXZzUstxhvUhiu58KJJ6I1RlopxuVp4D/e3/ty7yUdZqZFx65egWT4aj7OCC0EUHxjTaIzDCOUsb+ZZwFl/LltjVY3aJ2Q+v4rnsziOs+AY3hGXXBvrS6hxLLlYeFa36AV9UMDlWKnqBuT2TMRYjWj3DZ4h4ItFyZC9QxGqBMHtufIaV6TYmUCjjAXhk4SYp0kUXmXBMbRvu5VWbzvIB9FUMD073Ckr/h1LtqQrL9+hXRJSI1gnhh3bbYMLj9HR8hq9fBpGqR+mfhTfR8n1dHYdTx/pIx4S+gptw/6uwpDQWSo44ynymcyTMJqGoYvLDnMm9N0V+VdugDo5nPfRSglG9jo3qnMMSVRyEPmDXEv1LKnCgI2OpFJLnxvTgiwxf/jy0fHeBkb/Lt4f7slAc760ZD/q6oh1QB2XYcHtMOHuuAssoRX7RgulBIL0cqeQo3XBHbHVpLhPRm+Fa/ao2Glk1K1Tw3V3v18raas8mmbBG/CEuUXQJNE0fEXt0AMT2WmvSxAG+4z+9pVQBa0YCVXe3X4ovn1t2V0k2F21ebxNf3yPUs3k5+fHO5MFA9UlVgjCVmQaHOY7whyF17BCv9Uir6xtzHUQgDFozaTQwKV7ZlakwjNsJ+SjoIFtjdI+1WgrxZ6EWqlgQz6dNHJ1g3LDtZKOsDAgWaFe6Lk81O9uI2O5LShAroeWXqGj/aOY5OHMadcfHE7XayWOvL0HuqDGBmjwT4rw/vcOV6wtrdNkyBswRzFtYUrNG/eBTP9BQGvY9mtl1Rplvt7Yhq2zYHdyeCv5z7Z7l4rOyDQ5X3LUeVhEkDA2S3EWz1iaxgnE0RUDiJMIkySh9+FS6ug/vDYblLXyDVtfMNch3rM1Xb1brzfTd+s8/Dv+AgAA//8DADBA2i1TBwAA
137 | http_version:
138 | recorded_at: Fri, 13 Sep 2019 14:26:32 GMT
139 | - request:
140 | method: get
141 | uri: https://api.sandbox.braintreegateway.com/merchants/7rdg92j7bm7fk5h3/payment_methods/any/kvtpdk
142 | body:
143 | encoding: US-ASCII
144 | string: ''
145 | headers:
146 | Accept-Encoding:
147 | - gzip
148 | Accept:
149 | - application/xml
150 | User-Agent:
151 | - Braintree Ruby Gem 2.98.0
152 | X-Apiversion:
153 | - '5'
154 | Content-Type:
155 | - application/xml
156 | Authorization:
157 | - Basic bXdqa2t4d2NwMzJja2huZjphOTI5OGY0M2IzMGM2OTlkYjMwNzJjYzRhMDBmN2Y0OQ==
158 | response:
159 | status:
160 | code: 200
161 | message: OK
162 | headers:
163 | Date:
164 | - Fri, 13 Sep 2019 14:26:33 GMT
165 | Content-Type:
166 | - application/xml; charset=utf-8
167 | Transfer-Encoding:
168 | - chunked
169 | X-Frame-Options:
170 | - SAMEORIGIN
171 | X-Xss-Protection:
172 | - 1; mode=block
173 | X-Content-Type-Options:
174 | - nosniff
175 | X-Authentication:
176 | - basic_auth
177 | X-User:
178 | - 3v249hqtptsg744y
179 | Vary:
180 | - Accept-Encoding
181 | Content-Encoding:
182 | - gzip
183 | Etag:
184 | - W/"1d1dc0ec90596e65e546f301db422d7f"
185 | Cache-Control:
186 | - max-age=0, private, must-revalidate
187 | X-Runtime:
188 | - '0.099681'
189 | X-Request-Id:
190 | - 02-1568384792.728-92.223.152.178-13010638
191 | Content-Security-Policy:
192 | - frame-ancestors 'self'
193 | X-Broxyid:
194 | - 02-1568384792.728-92.223.152.178-13010638
195 | Strict-Transport-Security:
196 | - max-age=31536000; includeSubDomains
197 | body:
198 | encoding: ASCII-8BIT
199 | string: !binary |-
200 | H4sIABmne10AA6xVwXLaMBC98xWM78Y2dgnOGGd6SW49tEk7zSWzthasIkuuJJPw910ZgwmBtJ32ht6+Xe0+vxXZzUstxhvUhiu58KJJ6I1RlopxuVp4D/e3/ty7yUdZqZFx65egWT4aj7OCC0EUHxjTaIzDCOUsb+ZZwFl/LltjVY3aJ2Q+v4rnsziOs+AY3hGXXBvrS6hxLLlYeFa36AV9UMDlWKnqBuT2TMRYjWj3DZ4h4ItFyZC9QxGqBMHtufIaV6TYmUCjjAXhk4SYp0kUXmXBMbRvu5VWbzvIB9FUMD073Ckr/h1LtqQrL9+hXRJSI1gnhh3bbYMLj9HR8hq9fBpGqR+mfhTfR8n1dHYdTx/pIx4S+gptw/6uwpDQWSo44ynymcyTMJqGoYvLDnMm9N0V+VdugDo5nPfRSglG9jo3qnMMSVRyEPmDXEv1LKnCgI2OpFJLnxvTgiwxf/jy0fHeBkb/Lt4f7slAc760ZD/q6oh1QB2XYcHtMOHuuAssoRX7RgulBIL0cqeQo3XBHbHVpLhPRm+Fa/ao2Glk1K1Tw3V3v18raas8mmbBG/CEuUXQJNE0fEXt0AMT2WmvSxAG+4z+9pVQBa0YCVXe3X4ovn1t2V0k2F21ebxNf3yPUs3k5+fHO5MFA9UlVgjCVmQaHOY7whyF17BCv9Uir6xtzHUQgDFozaTQwKV7ZlakwjNsJ+SjoIFtjdI+1WgrxZ6EWqlgQz6dNHJ1g3LDtZKOsDAgWaFe6Lk81O9uI2O5LShAroeWXqGj/aOY5OHMadcfHE7XayWOvL0HuqDGBmjwT4rw/vcOV6wtrdNkyBswRzFtYUrNG/eBTP9BQGvY9mtl1Rplvt7Yhq2zYHdyeCv5z7Z7l4rOyDQ5X3LUeVhEkDA2S3EWz1iaxgnE0RUDiJMIkySh9+FS6ug/vDYblLXyDVtfMNch3rM1Xb1brzfTd+s8/Dv+AgAA//8DADBA2i1TBwAA
201 | http_version:
202 | recorded_at: Fri, 13 Sep 2019 14:26:33 GMT
203 | - request:
204 | method: get
205 | uri: https://api.sandbox.braintreegateway.com/merchants/7rdg92j7bm7fk5h3/payment_methods/any/kvtpdk
206 | body:
207 | encoding: US-ASCII
208 | string: ''
209 | headers:
210 | Accept-Encoding:
211 | - gzip
212 | Accept:
213 | - application/xml
214 | User-Agent:
215 | - Braintree Ruby Gem 2.98.0
216 | X-Apiversion:
217 | - '5'
218 | Content-Type:
219 | - application/xml
220 | Authorization:
221 | - Basic bXdqa2t4d2NwMzJja2huZjphOTI5OGY0M2IzMGM2OTlkYjMwNzJjYzRhMDBmN2Y0OQ==
222 | response:
223 | status:
224 | code: 200
225 | message: OK
226 | headers:
227 | Date:
228 | - Fri, 13 Sep 2019 14:26:34 GMT
229 | Content-Type:
230 | - application/xml; charset=utf-8
231 | Transfer-Encoding:
232 | - chunked
233 | X-Frame-Options:
234 | - SAMEORIGIN
235 | X-Xss-Protection:
236 | - 1; mode=block
237 | X-Content-Type-Options:
238 | - nosniff
239 | X-Authentication:
240 | - basic_auth
241 | X-User:
242 | - 3v249hqtptsg744y
243 | Vary:
244 | - Accept-Encoding
245 | Content-Encoding:
246 | - gzip
247 | Etag:
248 | - W/"0d1d13944d385fc31fa7c4fcf23f72ef"
249 | Cache-Control:
250 | - max-age=0, private, must-revalidate
251 | X-Runtime:
252 | - '0.097855'
253 | X-Request-Id:
254 | - 02-1568384793.685-92.223.152.178-13010819
255 | Content-Security-Policy:
256 | - frame-ancestors 'self'
257 | X-Broxyid:
258 | - 02-1568384793.685-92.223.152.178-13010819
259 | Strict-Transport-Security:
260 | - max-age=31536000; includeSubDomains
261 | body:
262 | encoding: ASCII-8BIT
263 | string: !binary |-
264 | H4sIABqne10AA6xVwXLaMBC98xWM78Y2dgnOGGd6SW49tEk7zSWzthasIkuuJJPw910ZgwmBtJ32ht6+Xe0+vxXZzUstxhvUhiu58KJJ6I1RlopxuVp4D/e3/ty7yUdZqZFx65egWT4aj7OCC0EUHxjTaIzDCOUsb+ZZwFl/LltjVY3aJ2Q+v4rnsziOs+AY3hGXXBvrS6hxLLlYeFa36AV9UMDlWKnqBuT2TMRYjWj3DZ4h4ItFyZC9QxGqBMHtufIaV6TYmUCjjAXhk4SYp0kUXmXBMbRvu5VWbzvIB9FUMD073Ckr/h1LtqQrL9+hXRJSI1gnhh3bbYMLj9HR8hq9fBpGqR+mfhTfR8n1dHYdTx/pIx4S+gptw/6uwpDQWSo44ynymcyTMJqGoYvLDnMm9N0V+VdugDo5nPfRSglG9jo3qnMMSVRyEPmDXEv1LKnCgI2OpFJLnxvTgiwxf/jy0fHeBkb/Lt4f7slAc760ZD/q6oh1QB2XYcHtMOHuuAssoRX7RgulBIL0cqeQo3XBHbHVpLhPRm+Fa/ao2Glk1K1Tw3V3v18raas8mmbBG/CEuUXQJNE0fEXt0AMT2WmvSxAG+4z+9pVQBa0YCVXe3X4ovn1t2V0k2F21ebxNf3yPUs3k5+fHO5MFA9UlVgjCVmQaHOY7whyF17BCv9Uir6xtzHUQgDFozaTQwKV7ZlakwjNsJ+SjoIFtjdI+1WgrxZ6EWqlgQz6dNHJ1g3LDtZKOsDAgWaFe6Lk81O9uI2O5LShAroeWXqGj/aOY5OHMadcfHE7XayWOvL0HuqDGBmjwT4rw/vcOV6wtrdNkyBswRzFtYUrNG/eBTP9BQGvY9mtl1Rplvt7Yhq2zYHdyeCv5z7Z7l4rOyDQ5X3LUeVhEkDA2S3EWz1iaxgnE0RUDiJMIkySh9+FS6ug/vDYblLXyDVtfMNch3rM1Xb1brzfTd+s8/Dv+AgAA//8DADBA2i1TBwAA
265 | http_version:
266 | recorded_at: Fri, 13 Sep 2019 14:26:34 GMT
267 | recorded_with: VCR 5.0.0
268 |
--------------------------------------------------------------------------------