expressly 2.0.32.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
 - data/.document +5 -0
 - data/.gitignore +51 -0
 - data/.rspec +1 -0
 - data/Gemfile +10 -0
 - data/Gemfile.lock +65 -0
 - data/Guardfile +8 -0
 - data/LICENSE.txt +20 -0
 - data/README.rdoc +5 -0
 - data/Rakefile +2 -0
 - data/app/controllers/expressly/api_controller.rb +79 -0
 - data/config/routes.rb +11 -0
 - data/expressly.gemspec +29 -0
 - data/lib/expressly.rb +49 -0
 - data/lib/expressly/api.rb +126 -0
 - data/lib/expressly/domain.rb +480 -0
 - data/lib/expressly/engine.rb +3 -0
 - data/lib/expressly/plugin_provider.rb +60 -0
 - data/lib/expressly/util.rb +98 -0
 - data/lib/expressly/version.rb +10 -0
 - data/spec/expressly/domain_spec.rb +597 -0
 - data/spec/expressly_spec.rb +11 -0
 - data/spec/spec_helper.rb +13 -0
 - metadata +125 -0
 
    
        checksums.yaml
    ADDED
    
    | 
         @@ -0,0 +1,7 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ---
         
     | 
| 
      
 2 
     | 
    
         
            +
            SHA1:
         
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 765092a460c3705f8841d13a0a39acfaa5d69304
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 274eed1b540c881777a709ad7c26267d40630dee
         
     | 
| 
      
 5 
     | 
    
         
            +
            SHA512:
         
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 8c56a2753464a13dcd47c858b99fa2cbac90554a366a8da766af141a26bc2703b75f8c8a3e1f8bc2a27d22c31c84275721b0a96941da2cb138a669bb81bb2dc2
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 493cbaa6101ddfda59fb10469affca648d59ca74afe0dea7645208fed21a5cf18ab3c63c32369f2ad0e8ab2486e2c21c2269b294d2d2d121c0c05976fa68719a
         
     | 
    
        data/.document
    ADDED
    
    
    
        data/.gitignore
    ADDED
    
    | 
         @@ -0,0 +1,51 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # rcov generated
         
     | 
| 
      
 2 
     | 
    
         
            +
            coverage
         
     | 
| 
      
 3 
     | 
    
         
            +
            coverage.data
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            # rdoc generated
         
     | 
| 
      
 6 
     | 
    
         
            +
            rdoc
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            # yard generated
         
     | 
| 
      
 9 
     | 
    
         
            +
            .yardoc
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            # bundler
         
     | 
| 
      
 12 
     | 
    
         
            +
            .bundle
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            # jeweler generated
         
     | 
| 
      
 15 
     | 
    
         
            +
            pkg
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            # Have editor/IDE/OS specific files you need to ignore? Consider using a global gitignore: 
         
     | 
| 
      
 18 
     | 
    
         
            +
            #
         
     | 
| 
      
 19 
     | 
    
         
            +
            # * Create a file at ~/.gitignore
         
     | 
| 
      
 20 
     | 
    
         
            +
            # * Include files you want ignored
         
     | 
| 
      
 21 
     | 
    
         
            +
            # * Run: git config --global core.excludesfile ~/.gitignore
         
     | 
| 
      
 22 
     | 
    
         
            +
            #
         
     | 
| 
      
 23 
     | 
    
         
            +
            # After doing this, these files will be ignored in all your git projects,
         
     | 
| 
      
 24 
     | 
    
         
            +
            # saving you from having to 'pollute' every project you touch with them
         
     | 
| 
      
 25 
     | 
    
         
            +
            #
         
     | 
| 
      
 26 
     | 
    
         
            +
            # Not sure what to needs to be ignored for particular editors/OSes? Here's some ideas to get you started. (Remember, remove the leading # of the line)
         
     | 
| 
      
 27 
     | 
    
         
            +
            #
         
     | 
| 
      
 28 
     | 
    
         
            +
            # For MacOS:
         
     | 
| 
      
 29 
     | 
    
         
            +
            #
         
     | 
| 
      
 30 
     | 
    
         
            +
            #.DS_Store
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
            # For TextMate
         
     | 
| 
      
 33 
     | 
    
         
            +
            #*.tmproj
         
     | 
| 
      
 34 
     | 
    
         
            +
            #tmtags
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
            # For emacs:
         
     | 
| 
      
 37 
     | 
    
         
            +
            #*~
         
     | 
| 
      
 38 
     | 
    
         
            +
            #\#*
         
     | 
| 
      
 39 
     | 
    
         
            +
            #.\#*
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
            # For vim:
         
     | 
| 
      
 42 
     | 
    
         
            +
            #*.swp
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
            # For redcar:
         
     | 
| 
      
 45 
     | 
    
         
            +
            #.redcar
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
            # For rubinius / eclipse:
         
     | 
| 
      
 48 
     | 
    
         
            +
            #*.rbc
         
     | 
| 
      
 49 
     | 
    
         
            +
            /tmp
         
     | 
| 
      
 50 
     | 
    
         
            +
            /.buildpath
         
     | 
| 
      
 51 
     | 
    
         
            +
            /.project
         
     | 
    
        data/.rspec
    ADDED
    
    | 
         @@ -0,0 +1 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            --color
         
     | 
    
        data/Gemfile
    ADDED
    
    
    
        data/Gemfile.lock
    ADDED
    
    | 
         @@ -0,0 +1,65 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            GEM
         
     | 
| 
      
 2 
     | 
    
         
            +
              remote: http://rubygems.org/
         
     | 
| 
      
 3 
     | 
    
         
            +
              specs:
         
     | 
| 
      
 4 
     | 
    
         
            +
                celluloid (0.15.2)
         
     | 
| 
      
 5 
     | 
    
         
            +
                  timers (~> 1.1.0)
         
     | 
| 
      
 6 
     | 
    
         
            +
                coderay (1.1.0)
         
     | 
| 
      
 7 
     | 
    
         
            +
                diff-lcs (1.2.5)
         
     | 
| 
      
 8 
     | 
    
         
            +
                ffi (1.9.3)
         
     | 
| 
      
 9 
     | 
    
         
            +
                ffi (1.9.3-x64-mingw32)
         
     | 
| 
      
 10 
     | 
    
         
            +
                formatador (0.2.4)
         
     | 
| 
      
 11 
     | 
    
         
            +
                guard (2.2.4)
         
     | 
| 
      
 12 
     | 
    
         
            +
                  formatador (>= 0.2.4)
         
     | 
| 
      
 13 
     | 
    
         
            +
                  listen (~> 2.1)
         
     | 
| 
      
 14 
     | 
    
         
            +
                  lumberjack (~> 1.0)
         
     | 
| 
      
 15 
     | 
    
         
            +
                  pry (>= 0.9.12)
         
     | 
| 
      
 16 
     | 
    
         
            +
                  thor (>= 0.18.1)
         
     | 
| 
      
 17 
     | 
    
         
            +
                guard-rspec (4.0.4)
         
     | 
| 
      
 18 
     | 
    
         
            +
                  guard (>= 2.1.1)
         
     | 
| 
      
 19 
     | 
    
         
            +
                  rspec (~> 2.14)
         
     | 
| 
      
 20 
     | 
    
         
            +
                httpclient (2.7.0.1)
         
     | 
| 
      
 21 
     | 
    
         
            +
                json (1.8.1)
         
     | 
| 
      
 22 
     | 
    
         
            +
                listen (2.2.0)
         
     | 
| 
      
 23 
     | 
    
         
            +
                  celluloid (>= 0.15.2)
         
     | 
| 
      
 24 
     | 
    
         
            +
                  rb-fsevent (>= 0.9.3)
         
     | 
| 
      
 25 
     | 
    
         
            +
                  rb-inotify (>= 0.9)
         
     | 
| 
      
 26 
     | 
    
         
            +
                lumberjack (1.0.4)
         
     | 
| 
      
 27 
     | 
    
         
            +
                method_source (0.8.2)
         
     | 
| 
      
 28 
     | 
    
         
            +
                pry (0.9.12.3)
         
     | 
| 
      
 29 
     | 
    
         
            +
                  coderay (~> 1.0)
         
     | 
| 
      
 30 
     | 
    
         
            +
                  method_source (~> 0.8)
         
     | 
| 
      
 31 
     | 
    
         
            +
                  slop (~> 3.4)
         
     | 
| 
      
 32 
     | 
    
         
            +
                rb-fsevent (0.9.3)
         
     | 
| 
      
 33 
     | 
    
         
            +
                rb-inotify (0.9.2)
         
     | 
| 
      
 34 
     | 
    
         
            +
                  ffi (>= 0.5.0)
         
     | 
| 
      
 35 
     | 
    
         
            +
                rdoc (3.12.2)
         
     | 
| 
      
 36 
     | 
    
         
            +
                  json (~> 1.4)
         
     | 
| 
      
 37 
     | 
    
         
            +
                rspec (2.14.1)
         
     | 
| 
      
 38 
     | 
    
         
            +
                  rspec-core (~> 2.14.0)
         
     | 
| 
      
 39 
     | 
    
         
            +
                  rspec-expectations (~> 2.14.0)
         
     | 
| 
      
 40 
     | 
    
         
            +
                  rspec-mocks (~> 2.14.0)
         
     | 
| 
      
 41 
     | 
    
         
            +
                rspec-core (2.14.7)
         
     | 
| 
      
 42 
     | 
    
         
            +
                rspec-expectations (2.14.4)
         
     | 
| 
      
 43 
     | 
    
         
            +
                  diff-lcs (>= 1.1.3, < 2.0)
         
     | 
| 
      
 44 
     | 
    
         
            +
                rspec-mocks (2.14.4)
         
     | 
| 
      
 45 
     | 
    
         
            +
                slop (3.4.7)
         
     | 
| 
      
 46 
     | 
    
         
            +
                thor (0.18.1)
         
     | 
| 
      
 47 
     | 
    
         
            +
                timers (1.1.0)
         
     | 
| 
      
 48 
     | 
    
         
            +
                tzinfo (0.3.37)
         
     | 
| 
      
 49 
     | 
    
         
            +
                wdm (0.1.1)
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
            PLATFORMS
         
     | 
| 
      
 52 
     | 
    
         
            +
              ruby
         
     | 
| 
      
 53 
     | 
    
         
            +
              x64-mingw32
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
            DEPENDENCIES
         
     | 
| 
      
 56 
     | 
    
         
            +
              bundler
         
     | 
| 
      
 57 
     | 
    
         
            +
              guard
         
     | 
| 
      
 58 
     | 
    
         
            +
              guard-rspec
         
     | 
| 
      
 59 
     | 
    
         
            +
              httpclient
         
     | 
| 
      
 60 
     | 
    
         
            +
              rdoc (~> 3.12)
         
     | 
| 
      
 61 
     | 
    
         
            +
              tzinfo (= 0.3.37)
         
     | 
| 
      
 62 
     | 
    
         
            +
              wdm (>= 0.1.0)
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
            BUNDLED WITH
         
     | 
| 
      
 65 
     | 
    
         
            +
               1.10.6
         
     | 
    
        data/Guardfile
    ADDED
    
    
    
        data/LICENSE.txt
    ADDED
    
    | 
         @@ -0,0 +1,20 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            Copyright (c) 2015 Marc G. Smith
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            Permission is hereby granted, free of charge, to any person obtaining
         
     | 
| 
      
 4 
     | 
    
         
            +
            a copy of this software and associated documentation files (the
         
     | 
| 
      
 5 
     | 
    
         
            +
            "Software"), to deal in the Software without restriction, including
         
     | 
| 
      
 6 
     | 
    
         
            +
            without limitation the rights to use, copy, modify, merge, publish,
         
     | 
| 
      
 7 
     | 
    
         
            +
            distribute, sublicense, and/or sell copies of the Software, and to
         
     | 
| 
      
 8 
     | 
    
         
            +
            permit persons to whom the Software is furnished to do so, subject to
         
     | 
| 
      
 9 
     | 
    
         
            +
            the following conditions:
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            The above copyright notice and this permission notice shall be
         
     | 
| 
      
 12 
     | 
    
         
            +
            included in all copies or substantial portions of the Software.
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
         
     | 
| 
      
 15 
     | 
    
         
            +
            EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
         
     | 
| 
      
 16 
     | 
    
         
            +
            MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
         
     | 
| 
      
 17 
     | 
    
         
            +
            NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
         
     | 
| 
      
 18 
     | 
    
         
            +
            LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
         
     | 
| 
      
 19 
     | 
    
         
            +
            OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
         
     | 
| 
      
 20 
     | 
    
         
            +
            WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
         
     | 
    
        data/README.rdoc
    ADDED
    
    
    
        data/Rakefile
    ADDED
    
    
| 
         @@ -0,0 +1,79 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Expressly
         
     | 
| 
      
 2 
     | 
    
         
            +
              class ApiController < ApplicationController
         
     | 
| 
      
 3 
     | 
    
         
            +
                skip_before_action :verify_authenticity_token
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                before_action :authenticate
         
     | 
| 
      
 6 
     | 
    
         
            +
                skip_before_action :authenticate, only: [:display_popup, :migrate]
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                def ping
         
     | 
| 
      
 9 
     | 
    
         
            +
                  render content_type: "application/json", json: { "expressly" => "Stuff is happening!" }
         
     | 
| 
      
 10 
     | 
    
         
            +
                end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                def ping_registered
         
     | 
| 
      
 13 
     | 
    
         
            +
                  render content_type: "application/json", json: { "registered" => true }
         
     | 
| 
      
 14 
     | 
    
         
            +
                end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                def customer_export
         
     | 
| 
      
 17 
     | 
    
         
            +
                  result = Expressly::CustomerExport.new({
         
     | 
| 
      
 18 
     | 
    
         
            +
                    :metadata => config.merchant_metadata,
         
     | 
| 
      
 19 
     | 
    
         
            +
                    :primary_email => params[:email],
         
     | 
| 
      
 20 
     | 
    
         
            +
                    :customer => provider.get_customer(params[:email])
         
     | 
| 
      
 21 
     | 
    
         
            +
                  })
         
     | 
| 
      
 22 
     | 
    
         
            +
                  render content_type: "application/json", json: JSON.parse(result.to_json)
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                def invoices
         
     | 
| 
      
 26 
     | 
    
         
            +
                  result = provider.get_customer_invoices(Expressly::CustomerInvoiceRequest.from_json_list(params[:customers]))
         
     | 
| 
      
 27 
     | 
    
         
            +
                  render content_type: "application/json", json: JSON.parse(Expressly::CustomerInvoice.to_json_from_list(result))
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                def check_emails
         
     | 
| 
      
 31 
     | 
    
         
            +
                  result = provider.check_customer_statuses(params[:emails])
         
     | 
| 
      
 32 
     | 
    
         
            +
                  render content_type: "application/json", json: result
         
     | 
| 
      
 33 
     | 
    
         
            +
                end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                def display_popup
         
     | 
| 
      
 36 
     | 
    
         
            +
                  campaign_customer_uuid = params[:campaign_customer_uuid]
         
     | 
| 
      
 37 
     | 
    
         
            +
                  provider.popup_handler(self, params[:campaign_customer_uuid])
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                def migrate
         
     | 
| 
      
 41 
     | 
    
         
            +
                  campaign_customer_uuid = params[:campaign_customer_uuid]
         
     | 
| 
      
 42 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                    import = config.expressly_provider.fetch_customer_data(campaign_customer_uuid)
         
     | 
| 
      
 45 
     | 
    
         
            +
                    customer_reference = provider.customer_register(import.primary_email, import.customer)
         
     | 
| 
      
 46 
     | 
    
         
            +
                    provider.customer_send_password_reset_email(customer_reference)
         
     | 
| 
      
 47 
     | 
    
         
            +
                    provider.customer_update_cart(customer_reference, import.cart)
         
     | 
| 
      
 48 
     | 
    
         
            +
                    provider.customer_login(customer_reference)
         
     | 
| 
      
 49 
     | 
    
         
            +
                    redirect_to provider.customer_migrated_redirect_url(true, customer_reference)
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 52 
     | 
    
         
            +
                      config.expressly_provider.confirm_migration_success?(campaign_customer_uuid)
         
     | 
| 
      
 53 
     | 
    
         
            +
                    rescue Exception => e
         
     | 
| 
      
 54 
     | 
    
         
            +
                      Expressly::logger.warn(self) {
         
     | 
| 
      
 55 
     | 
    
         
            +
                        "couldn't finalise migration campaign_customer_uuid=[#{campaign_customer_uuid}], email=[#{import.primary_email}], error=[#{e.message}]"
         
     | 
| 
      
 56 
     | 
    
         
            +
                      }
         
     | 
| 
      
 57 
     | 
    
         
            +
                    end
         
     | 
| 
      
 58 
     | 
    
         
            +
                  rescue Expressly::ExpresslyError
         
     | 
| 
      
 59 
     | 
    
         
            +
                    # already migrated or invalid uuid so just redirect
         
     | 
| 
      
 60 
     | 
    
         
            +
                    redirect_to provider.customer_migrated_redirect_url(false)
         
     | 
| 
      
 61 
     | 
    
         
            +
                  end
         
     | 
| 
      
 62 
     | 
    
         
            +
                end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                def authenticate
         
     | 
| 
      
 65 
     | 
    
         
            +
                  partitionedApiKey = config.api_key.partition(':')
         
     | 
| 
      
 66 
     | 
    
         
            +
                  authenticate_or_request_with_http_basic('expressly') do |username, password|
         
     | 
| 
      
 67 
     | 
    
         
            +
                    username == partitionedApiKey[0] && password == partitionedApiKey[2]
         
     | 
| 
      
 68 
     | 
    
         
            +
                  end
         
     | 
| 
      
 69 
     | 
    
         
            +
                end
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                def config
         
     | 
| 
      
 72 
     | 
    
         
            +
                  Expressly::default_configuration
         
     | 
| 
      
 73 
     | 
    
         
            +
                end
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
                def provider
         
     | 
| 
      
 76 
     | 
    
         
            +
                  config.merchant_plugin_provider
         
     | 
| 
      
 77 
     | 
    
         
            +
                end
         
     | 
| 
      
 78 
     | 
    
         
            +
              end
         
     | 
| 
      
 79 
     | 
    
         
            +
            end
         
     | 
    
        data/config/routes.rb
    ADDED
    
    | 
         @@ -0,0 +1,11 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            Rails.application.routes.draw do
         
     | 
| 
      
 2 
     | 
    
         
            +
              get 'expressly/api/ping'
         
     | 
| 
      
 3 
     | 
    
         
            +
              get 'expressly/api/ping_registered'
         
     | 
| 
      
 4 
     | 
    
         
            +
              get 'expressly/api/user/:email' => 'expressly/api#customer_export'
         
     | 
| 
      
 5 
     | 
    
         
            +
              
         
     | 
| 
      
 6 
     | 
    
         
            +
              post 'expressly/api/batch/invoice' => 'expressly/api#invoices'  
         
     | 
| 
      
 7 
     | 
    
         
            +
              post 'expressly/api/batch/customer' => 'expressly/api#check_emails'  
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
              get 'expressly/api/:campaign_customer_uuid/migrate' => 'expressly/api#migrate'
         
     | 
| 
      
 10 
     | 
    
         
            +
              get 'expressly/api/:campaign_customer_uuid' => 'expressly/api#display_popup'
         
     | 
| 
      
 11 
     | 
    
         
            +
            end
         
     | 
    
        data/expressly.gemspec
    ADDED
    
    | 
         @@ -0,0 +1,29 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # -*- encoding: utf-8 -*-
         
     | 
| 
      
 2 
     | 
    
         
            +
            $:.push File.expand_path("../lib", __FILE__)
         
     | 
| 
      
 3 
     | 
    
         
            +
            require "expressly/version"
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            Gem::Specification.new do |s|
         
     | 
| 
      
 6 
     | 
    
         
            +
              s.name = "expressly"
         
     | 
| 
      
 7 
     | 
    
         
            +
              s.version = Expressly::Version::STRING
         
     | 
| 
      
 8 
     | 
    
         
            +
              s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
         
     | 
| 
      
 9 
     | 
    
         
            +
              s.authors = ["Marc G. Smith"]
         
     | 
| 
      
 10 
     | 
    
         
            +
              s.date = "2015-12-01"
         
     | 
| 
      
 11 
     | 
    
         
            +
              s.description = "Expressly sdk to help with implementing the expressly e-commerce plug-in / module API"
         
     | 
| 
      
 12 
     | 
    
         
            +
              s.email = "marc@buyexpressly.com"
         
     | 
| 
      
 13 
     | 
    
         
            +
              s.extra_rdoc_files = [
         
     | 
| 
      
 14 
     | 
    
         
            +
                "LICENSE.txt",
         
     | 
| 
      
 15 
     | 
    
         
            +
                "README.rdoc"
         
     | 
| 
      
 16 
     | 
    
         
            +
              ]
         
     | 
| 
      
 17 
     | 
    
         
            +
              s.files         = `git ls-files`.split("\n")
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
              s.homepage = "http://developer.buyexpressly.com"
         
     | 
| 
      
 20 
     | 
    
         
            +
              s.licenses = ["MIT"]
         
     | 
| 
      
 21 
     | 
    
         
            +
              s.require_paths = ["lib"]
         
     | 
| 
      
 22 
     | 
    
         
            +
              s.rubygems_version = "2.0.2"
         
     | 
| 
      
 23 
     | 
    
         
            +
              s.summary = "Expressly plug-in sdk"
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
              s.add_development_dependency(%q<bundler>, ["~> 0"])
         
     | 
| 
      
 26 
     | 
    
         
            +
              s.add_development_dependency(%q<guard-rspec>, ["~> 0"])
         
     | 
| 
      
 27 
     | 
    
         
            +
              s.add_development_dependency(%q<guard>, ["~> 0"])
         
     | 
| 
      
 28 
     | 
    
         
            +
              s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
         
     | 
| 
      
 29 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/expressly.rb
    ADDED
    
    | 
         @@ -0,0 +1,49 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Expressly
         
     | 
| 
      
 2 
     | 
    
         
            +
              @@logger = Logger.new(STDERR)
         
     | 
| 
      
 3 
     | 
    
         
            +
              @@logger.level= Logger::Severity::INFO
         
     | 
| 
      
 4 
     | 
    
         
            +
              
         
     | 
| 
      
 5 
     | 
    
         
            +
              def self.logger() @@logger end
         
     | 
| 
      
 6 
     | 
    
         
            +
              def self.logger=(logger) @@logger = logger end
         
     | 
| 
      
 7 
     | 
    
         
            +
                
         
     | 
| 
      
 8 
     | 
    
         
            +
              def self.default_configuration() 
         
     | 
| 
      
 9 
     | 
    
         
            +
                @@default_configuration 
         
     | 
| 
      
 10 
     | 
    
         
            +
              end
         
     | 
| 
      
 11 
     | 
    
         
            +
              
         
     | 
| 
      
 12 
     | 
    
         
            +
              def self.default_configuration?() 
         
     | 
| 
      
 13 
     | 
    
         
            +
                !@@default_configuration.nil?
         
     | 
| 
      
 14 
     | 
    
         
            +
              end
         
     | 
| 
      
 15 
     | 
    
         
            +
              
         
     | 
| 
      
 16 
     | 
    
         
            +
              def self.default_configuration=(default_configuration) 
         
     | 
| 
      
 17 
     | 
    
         
            +
                @@default_configuration = default_configuration 
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
              
         
     | 
| 
      
 20 
     | 
    
         
            +
              class Configuration
         
     | 
| 
      
 21 
     | 
    
         
            +
                attr_reader :api_key, 
         
     | 
| 
      
 22 
     | 
    
         
            +
                  :merchant_plugin_provider, :merchant_plugin_endpoint, :merchant_metadata,
         
     | 
| 
      
 23 
     | 
    
         
            +
                  :expressly_provider, :expressly_endpoint
         
     | 
| 
      
 24 
     | 
    
         
            +
                
         
     | 
| 
      
 25 
     | 
    
         
            +
                def initialize(api_key, merchant_plugin_provider, merchant_plugin_endpoint, merchant_metadata = {}, expressly_endpoint = 'https://prod.expresslyapp.com/api')
         
     | 
| 
      
 26 
     | 
    
         
            +
                  @api_key = api_key
         
     | 
| 
      
 27 
     | 
    
         
            +
                  @merchant_plugin_provider = merchant_plugin_provider
         
     | 
| 
      
 28 
     | 
    
         
            +
                  @merchant_plugin_endpoint = merchant_plugin_endpoint
         
     | 
| 
      
 29 
     | 
    
         
            +
                  @expressly_endpoint = expressly_endpoint
         
     | 
| 
      
 30 
     | 
    
         
            +
                  @expressly_provider = Api.new(api_key, expressly_endpoint)
         
     | 
| 
      
 31 
     | 
    
         
            +
                  @merchant_metadata = merchant_metadata
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
              end
         
     | 
| 
      
 34 
     | 
    
         
            +
            end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
            require 'logger'
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
            require 'expressly/version'
         
     | 
| 
      
 39 
     | 
    
         
            +
            require 'expressly/util'
         
     | 
| 
      
 40 
     | 
    
         
            +
            require 'expressly/domain'
         
     | 
| 
      
 41 
     | 
    
         
            +
            require 'expressly/api'
         
     | 
| 
      
 42 
     | 
    
         
            +
            require 'expressly/plugin_provider'
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
            begin
         
     | 
| 
      
 45 
     | 
    
         
            +
              require 'expressly/engine'
         
     | 
| 
      
 46 
     | 
    
         
            +
            rescue NameError
         
     | 
| 
      
 47 
     | 
    
         
            +
              Expressly.logger.warn('expressly') { 
         
     | 
| 
      
 48 
     | 
    
         
            +
                "skipping loading of the expressly rails engine" }
         
     | 
| 
      
 49 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,126 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Expressly
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Api
         
     | 
| 
      
 3 
     | 
    
         
            +
                
         
     | 
| 
      
 4 
     | 
    
         
            +
                def initialize(apikey, endpoint = 'https://prod.expresslyapp.com/api')
         
     | 
| 
      
 5 
     | 
    
         
            +
                  partitionedApiKey = apikey.partition(':')
         
     | 
| 
      
 6 
     | 
    
         
            +
                  @merchantUuid = partitionedApiKey[0]
         
     | 
| 
      
 7 
     | 
    
         
            +
                  @secretKey = partitionedApiKey[2]
         
     | 
| 
      
 8 
     | 
    
         
            +
                  @endpoint = endpoint
         
     | 
| 
      
 9 
     | 
    
         
            +
                end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                def ping?
         
     | 
| 
      
 12 
     | 
    
         
            +
                  response = execute('/v1/merchant/ping', 'GET')
         
     | 
| 
      
 13 
     | 
    
         
            +
                  return JSON.parse(response.body)['success']
         
     | 
| 
      
 14 
     | 
    
         
            +
                end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                def install(baseUrl)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  apiKey = Base64.strict_encode64("#{@merchantUuid}:#{@secretKey}")
         
     | 
| 
      
 18 
     | 
    
         
            +
                  response = execute(
         
     | 
| 
      
 19 
     | 
    
         
            +
                    '/v2/plugin/merchant', 
         
     | 
| 
      
 20 
     | 
    
         
            +
                    'POST', 
         
     | 
| 
      
 21 
     | 
    
         
            +
                    "{\"apiBaseUrl\":\"#{baseUrl}\", \"apiKey\":\"#{apiKey}\"}")
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                def uninstall?
         
     | 
| 
      
 25 
     | 
    
         
            +
                  response = execute(
         
     | 
| 
      
 26 
     | 
    
         
            +
                    "/v2/plugin/merchant/#{@merchantUuid}", 
         
     | 
| 
      
 27 
     | 
    
         
            +
                    'DELETE')
         
     | 
| 
      
 28 
     | 
    
         
            +
                  return JSON.parse(response.body)['success']
         
     | 
| 
      
 29 
     | 
    
         
            +
                end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                def fetch_migration_confirmation_html(campaign_customer_uuid)
         
     | 
| 
      
 32 
     | 
    
         
            +
                  response = execute(
         
     | 
| 
      
 33 
     | 
    
         
            +
                    "/v2/migration/#{campaign_customer_uuid}", 
         
     | 
| 
      
 34 
     | 
    
         
            +
                    'GET')
         
     | 
| 
      
 35 
     | 
    
         
            +
                  return response.body
         
     | 
| 
      
 36 
     | 
    
         
            +
                end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                def fetch_customer_data(campaign_customer_uuid)
         
     | 
| 
      
 39 
     | 
    
         
            +
                  response = execute(
         
     | 
| 
      
 40 
     | 
    
         
            +
                    "/v2/migration/#{campaign_customer_uuid}/user", 
         
     | 
| 
      
 41 
     | 
    
         
            +
                    'GET')
         
     | 
| 
      
 42 
     | 
    
         
            +
                  return CustomerImport.from_json(JSON.parse(response.body))
         
     | 
| 
      
 43 
     | 
    
         
            +
                end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                def confirm_migration_success?(campaign_customer_uuid)
         
     | 
| 
      
 46 
     | 
    
         
            +
                  response = execute(
         
     | 
| 
      
 47 
     | 
    
         
            +
                    "/v2/migration/#{campaign_customer_uuid}/success", 
         
     | 
| 
      
 48 
     | 
    
         
            +
                    'POST')
         
     | 
| 
      
 49 
     | 
    
         
            +
                  return JSON.parse(response.body)['success']
         
     | 
| 
      
 50 
     | 
    
         
            +
                end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                def execute(methodUri, httpVerb, body = nil)
         
     | 
| 
      
 53 
     | 
    
         
            +
                  uri = URI.parse("#{@endpoint}#{methodUri}")
         
     | 
| 
      
 54 
     | 
    
         
            +
                  http = Net::HTTP.new(uri.host, uri.port)
         
     | 
| 
      
 55 
     | 
    
         
            +
                  http.use_ssl = @endpoint.start_with?('https')
         
     | 
| 
      
 56 
     | 
    
         
            +
                  http.verify_mode = OpenSSL::SSL::VERIFY_NONE
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                  request =
         
     | 
| 
      
 59 
     | 
    
         
            +
                    if httpVerb == 'GET' then Net::HTTP::Get.new(uri.request_uri)
         
     | 
| 
      
 60 
     | 
    
         
            +
                    elsif httpVerb == 'POST' then Net::HTTP::Post.new(uri.request_uri)
         
     | 
| 
      
 61 
     | 
    
         
            +
                    elsif httpVerb == 'DELETE' then Net::HTTP::Delete.new(uri.request_uri)
         
     | 
| 
      
 62 
     | 
    
         
            +
                    else raise "unexpected http verb [#{httpVerb}]"
         
     | 
| 
      
 63 
     | 
    
         
            +
                    end
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                  request.basic_auth(@merchantUuid, @secretKey)
         
     | 
| 
      
 66 
     | 
    
         
            +
                  if body != nil then
         
     | 
| 
      
 67 
     | 
    
         
            +
                    request["Content-Type"] = 'application/json'
         
     | 
| 
      
 68 
     | 
    
         
            +
                    request.body = body
         
     | 
| 
      
 69 
     | 
    
         
            +
                  end
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                  response = http.request(request)
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                  if response.code.to_i >= 300
         
     | 
| 
      
 74 
     | 
    
         
            +
                    handle_error(response)
         
     | 
| 
      
 75 
     | 
    
         
            +
                  end
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                  return response
         
     | 
| 
      
 78 
     | 
    
         
            +
                end
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                def handle_error(response)
         
     | 
| 
      
 81 
     | 
    
         
            +
                  is_json = response.content_type == "application/json"
         
     | 
| 
      
 82 
     | 
    
         
            +
                  body = is_json ? JSON.parse(response.body) : response.body
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                  raise (if is_json && !body['id'].nil? then
         
     | 
| 
      
 85 
     | 
    
         
            +
                    ExpresslyError.new(body) else
         
     | 
| 
      
 86 
     | 
    
         
            +
                    HttpError.new(response)  end)
         
     | 
| 
      
 87 
     | 
    
         
            +
                end
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                private :execute, :handle_error
         
     | 
| 
      
 90 
     | 
    
         
            +
              end
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
              class HttpError < StandardError
         
     | 
| 
      
 93 
     | 
    
         
            +
                attr_accessor   :code, :body
         
     | 
| 
      
 94 
     | 
    
         
            +
                def initialize(response)
         
     | 
| 
      
 95 
     | 
    
         
            +
                  super(response.message)
         
     | 
| 
      
 96 
     | 
    
         
            +
                  @code = response.code
         
     | 
| 
      
 97 
     | 
    
         
            +
                  @body = response.body
         
     | 
| 
      
 98 
     | 
    
         
            +
                  self.freeze
         
     | 
| 
      
 99 
     | 
    
         
            +
                end
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
                private :initialize
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
              end
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
              class ExpresslyError < StandardError
         
     | 
| 
      
 106 
     | 
    
         
            +
                attr_accessor   :id, :code, :description, :causes, :actions
         
     | 
| 
      
 107 
     | 
    
         
            +
                def initialize(response)
         
     | 
| 
      
 108 
     | 
    
         
            +
                  super(response['message'])
         
     | 
| 
      
 109 
     | 
    
         
            +
                  @id = response['id']
         
     | 
| 
      
 110 
     | 
    
         
            +
                  @code = response['code']
         
     | 
| 
      
 111 
     | 
    
         
            +
                  @description = response['description']
         
     | 
| 
      
 112 
     | 
    
         
            +
                  @causes = response['causes']
         
     | 
| 
      
 113 
     | 
    
         
            +
                  @actions = response['actions']
         
     | 
| 
      
 114 
     | 
    
         
            +
                  self.freeze
         
     | 
| 
      
 115 
     | 
    
         
            +
                end
         
     | 
| 
      
 116 
     | 
    
         
            +
              end
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
              private :initialize
         
     | 
| 
      
 119 
     | 
    
         
            +
             
     | 
| 
      
 120 
     | 
    
         
            +
            end
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
            require "net/http"
         
     | 
| 
      
 123 
     | 
    
         
            +
            require "net/https"
         
     | 
| 
      
 124 
     | 
    
         
            +
            require "uri"
         
     | 
| 
      
 125 
     | 
    
         
            +
            require 'json'
         
     | 
| 
      
 126 
     | 
    
         
            +
            require 'base64'
         
     |