spree_komoju 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +14 -0
  3. data/.rspec +1 -0
  4. data/.travis.yml +16 -0
  5. data/Gemfile +8 -0
  6. data/LICENSE +26 -0
  7. data/README.md +39 -0
  8. data/Rakefile +21 -0
  9. data/app/assets/javascripts/spree/backend/spree_komoju.js +2 -0
  10. data/app/assets/javascripts/spree/frontend/spree_komoju.js +2 -0
  11. data/app/assets/stylesheets/spree/backend/spree_komoju.css +4 -0
  12. data/app/assets/stylesheets/spree/frontend/spree_komoju.css +4 -0
  13. data/app/controllers/spree/checkout_controller_decorator.rb +18 -0
  14. data/app/models/spree/bank_transfer.rb +26 -0
  15. data/app/models/spree/gateway/komoju_bank_transfer.rb +25 -0
  16. data/app/models/spree/gateway/komoju_credit_card.rb +40 -0
  17. data/app/models/spree/gateway/komoju_konbini.rb +23 -0
  18. data/app/models/spree/komoju_gateway.rb +51 -0
  19. data/app/models/spree/konbini.rb +32 -0
  20. data/app/overrides/add_instruction_to_order_show.rb +8 -0
  21. data/app/views/spree/admin/payments/source_views/_komoju_credit_card.html.erb +1 -0
  22. data/app/views/spree/admin/payments/source_views/_komoju_konbini.html.erb +25 -0
  23. data/app/views/spree/checkout/payment/_komoju_bank_transfer.html.erb +35 -0
  24. data/app/views/spree/checkout/payment/_komoju_credit_card.html.erb +1 -0
  25. data/app/views/spree/checkout/payment/_komoju_konbini.html.erb +11 -0
  26. data/app/views/spree/orders/_bank_transfer.html.erb +10 -0
  27. data/app/views/spree/orders/_konbini.html.erb +17 -0
  28. data/bin/rails +7 -0
  29. data/config/locales/en.yml +16 -0
  30. data/config/routes.rb +2 -0
  31. data/db/migrate/20150331051027_create_spree_konbinis.rb +18 -0
  32. data/db/migrate/20150401074721_create_spree_bank_transfers.rb +22 -0
  33. data/db/migrate/20151126050103_add_gateway_profile_ids_to_spree_konbinis.rb +6 -0
  34. data/lib/active_merchant/billing/gateways/komoju.rb +135 -0
  35. data/lib/generators/spree_komoju/install/images/circle-k.png +0 -0
  36. data/lib/generators/spree_komoju/install/images/daily-yamazaki.png +0 -0
  37. data/lib/generators/spree_komoju/install/images/family-mart.png +0 -0
  38. data/lib/generators/spree_komoju/install/images/lawson.png +0 -0
  39. data/lib/generators/spree_komoju/install/images/ministop.png +0 -0
  40. data/lib/generators/spree_komoju/install/images/seven-eleven.png +0 -0
  41. data/lib/generators/spree_komoju/install/images/sunkus.png +0 -0
  42. data/lib/generators/spree_komoju/install/install_generator.rb +36 -0
  43. data/lib/spree_komoju.rb +2 -0
  44. data/lib/spree_komoju/engine.rb +29 -0
  45. data/lib/spree_komoju/factories.rb +6 -0
  46. data/spec/controllers/spree/checkout_controller_spec.rb +13 -0
  47. data/spec/models/spree/bank_transfer_spec.rb +69 -0
  48. data/spec/models/spree/gateway/komoju_bank_transfer_spec.rb +59 -0
  49. data/spec/models/spree/gateway/komoju_credit_card_spec.rb +117 -0
  50. data/spec/models/spree/gateway/komoju_konbini_spec.rb +41 -0
  51. data/spec/models/spree/komoju_gateway_spec.rb +50 -0
  52. data/spec/models/spree/konbini_spec.rb +69 -0
  53. data/spec/spec_helper.rb +87 -0
  54. data/spree_komoju.gemspec +32 -0
  55. metadata +66 -5
@@ -0,0 +1 @@
1
+ <%= render "spree/checkout/payment/gateway", payment_method: payment_method %>
@@ -0,0 +1,11 @@
1
+ <div class="well clearfix">
2
+ <% param_prefix = "payment_source[#{payment_method.id}]" %>
3
+
4
+ <% Spree::Konbini::STORES.each do |store| %>
5
+ <label>
6
+ <%= radio_button "#{param_prefix}", "convenience", store %>
7
+ <%= image_tag "#{store}.png" %>
8
+ <span><%= Spree.t("conveniences.#{store}") %></span>
9
+ </label><br />
10
+ <% end %>
11
+ </div>
@@ -0,0 +1,10 @@
1
+ <div>
2
+ Thank you for your order. Instructions have been sent to your e-mail address.<br>
3
+ <br>
4
+ <h4>Banktransfer ID: <%= source.order_id %></h4>
5
+ The Banktransfer ID is very important! Please make a note of it and bring it with you when you go to pay at the ATM.<br>
6
+ If you have chosen to use bank transfer payment, please use a bank transfer form which your bank offers, or please remit at ATM.<br>
7
+ <br>
8
+ Please make sure to include your banktransfer ID in the payer's name. Please enter your banktransfer ID shown in this email in front of your name as Payer when remitting.<br>
9
+ Please see the confirmation email for further payment instructions.
10
+ </div>
@@ -0,0 +1,17 @@
1
+ <div>
2
+ Thank you for your order. Instructions have been sent to your e-mail address.<br>
3
+ To complete a payment at <%= source.convenience.camelcase %>, Receipt Number and Confirmation Number are required.<br>
4
+ <br>
5
+ <%= link_to source.instructions_url do %>
6
+ How to make a payment at <%= source.convenience.camelcase %>
7
+ <% end %>
8
+ </div>
9
+ <br>
10
+ <div class='alert alert-info' role='alert'>
11
+ <h4>Receipt Number</h4>
12
+ <p><%= source.receipt %></p>
13
+ <h4>Confirmation Number</h4>
14
+ <p><%= source.confirmation_code %></p>
15
+ <h4>End Date</h4>
16
+ <p><%= source.expires_at %></p>
17
+ </div>
data/bin/rails ADDED
@@ -0,0 +1,7 @@
1
+ # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
2
+
3
+ ENGINE_ROOT = File.expand_path('../..', __FILE__)
4
+ ENGINE_PATH = File.expand_path('../../lib/spree_komoju/engine', __FILE__)
5
+
6
+ require 'rails/all'
7
+ require 'rails/engine/commands'
@@ -0,0 +1,16 @@
1
+ en:
2
+ spree:
3
+ conveniences:
4
+ lawson: Lawson
5
+ family-mart: Family Mart
6
+ sunkus: Sunkus
7
+ circle-k: Circle K
8
+ ministop: Ministop
9
+ daily-yamazaki: Daily Yamazaki
10
+ seven-eleven: Seven Eleven
11
+ email: Email
12
+ phone: Phone
13
+ given_name: Given Name
14
+ family_name: Family Name
15
+ given_name_kana: Given Name Kana
16
+ family_name_kana: Family Name Kana
data/config/routes.rb ADDED
@@ -0,0 +1,2 @@
1
+ Spree::Core::Engine.routes.draw do
2
+ end
@@ -0,0 +1,18 @@
1
+ class CreateSpreeKonbinis < ActiveRecord::Migration
2
+ def change
3
+ create_table :spree_konbinis do |t|
4
+ t.string :convenience
5
+ t.integer :user_id
6
+ t.integer :payment_method_id
7
+ t.string :brand, default: "konbini"
8
+ t.string :receipt
9
+ t.string :confirmation_code
10
+ t.string :instructions_url
11
+ t.datetime :expires_at
12
+
13
+ t.timestamps null: false
14
+ end
15
+ add_index :spree_konbinis, :user_id
16
+ add_index :spree_konbinis, :payment_method_id
17
+ end
18
+ end
@@ -0,0 +1,22 @@
1
+ class CreateSpreeBankTransfers < ActiveRecord::Migration
2
+ def change
3
+ create_table :spree_bank_transfers do |t|
4
+ t.string :email
5
+ t.string :phone
6
+ t.string :given_name
7
+ t.string :family_name
8
+ t.string :given_name_kana
9
+ t.string :family_name_kana
10
+ t.integer :user_id
11
+ t.integer :payment_method_id
12
+ t.string :brand, default: "bank_transfers"
13
+ t.string :order_id
14
+ t.string :bank_number
15
+ t.datetime :expires_at
16
+
17
+ t.timestamps null: false
18
+ end
19
+ add_index :spree_bank_transfers, :user_id
20
+ add_index :spree_bank_transfers, :payment_method_id
21
+ end
22
+ end
@@ -0,0 +1,6 @@
1
+ class AddGatewayProfileIdsToSpreeKonbinis < ActiveRecord::Migration
2
+ def change
3
+ add_column :spree_konbinis, :gateway_customer_profile_id, :string
4
+ add_column :spree_konbinis, :gateway_payment_profile_id, :string
5
+ end
6
+ end
@@ -0,0 +1,135 @@
1
+ require 'json'
2
+
3
+ module ActiveMerchant #:nodoc:
4
+ module Billing #:nodoc:
5
+ class KomojuGateway < Gateway
6
+ self.test_url = "https://sandbox.komoju.com/api/v1"
7
+ self.live_url = "https://komoju.com/api/v1"
8
+ self.supported_countries = ['JP']
9
+ self.default_currency = 'JPY'
10
+ self.money_format = :cents
11
+ self.homepage_url = 'https://www.komoju.com/'
12
+ self.display_name = 'Komoju'
13
+ self.supported_cardtypes = [:visa, :master, :american_express, :jcb]
14
+
15
+ STANDARD_ERROR_CODE_MAPPING = {
16
+ "bad_verification_value" => "incorrect_cvc",
17
+ "card_expired" => "expired_card",
18
+ "card_declined" => "card_declined",
19
+ "invalid_number" => "invalid_number"
20
+ }
21
+
22
+ def initialize(options = {})
23
+ requires!(options, :login)
24
+ super
25
+ end
26
+
27
+ def purchase(money, payment, options = {})
28
+ post = {}
29
+ post[:amount] = amount(money)
30
+ post[:description] = options[:description]
31
+ add_payment_details(post, payment, options)
32
+ post[:currency] = options[:currency] || default_currency
33
+ post[:external_order_num] = options[:order_id] if options[:order_id]
34
+ post[:tax] = options[:tax] if options[:tax]
35
+ add_fraud_details(post, options)
36
+
37
+ commit("/payments", post)
38
+ end
39
+
40
+ def refund(money, identification, options = {})
41
+ commit("/payments/#{identification}/refund", {})
42
+ end
43
+
44
+ def store(payment, options = {})
45
+ post = {}
46
+ add_payment_details(post, payment, options)
47
+
48
+ if options[:customer_profile]
49
+ post[:email] = options[:email]
50
+ commit("/customers", post)
51
+ else
52
+ commit("/tokens", post)
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ def add_payment_details(post, payment, options)
59
+ case payment
60
+ when CreditCard
61
+ details = {}
62
+
63
+ details[:type] = 'credit_card'
64
+ details[:number] = payment.number
65
+ details[:month] = payment.month
66
+ details[:year] = payment.year
67
+ details[:verification_value] = payment.verification_value
68
+ details[:given_name] = payment.first_name
69
+ details[:family_name] = payment.last_name
70
+ details[:email] = options[:email] if options[:email]
71
+ post[:payment_details] = details
72
+ when String
73
+ if payment.match(/^tok_/)
74
+ post[:payment_details] = payment
75
+ else
76
+ post[:customer] = payment
77
+ end
78
+ end
79
+ end
80
+
81
+ def add_fraud_details(post, options)
82
+ details = {}
83
+
84
+ details[:customer_ip] = options[:ip] if options[:ip]
85
+ details[:customer_email] = options[:email] if options[:email]
86
+ details[:browser_language] = options[:browser_language] if options[:browser_language]
87
+ details[:browser_user_agent] = options[:browser_user_agent] if options[:browser_user_agent]
88
+
89
+ post[:fraud_details] = details unless details.empty?
90
+ end
91
+
92
+ def api_request(path, data)
93
+ raw_response = nil
94
+ begin
95
+ raw_response = ssl_post("#{url}#{path}", data, headers)
96
+ rescue ResponseError => e
97
+ raw_response = e.response.body
98
+ end
99
+
100
+ JSON.parse(raw_response)
101
+ end
102
+
103
+ def commit(path, params)
104
+ response = api_request(path, params.to_json)
105
+ success = !response.key?("error")
106
+ message = (success ? "Transaction succeeded" : response["error"]["message"])
107
+ Response.new(
108
+ success,
109
+ message,
110
+ response,
111
+ test: test?,
112
+ error_code: (success ? nil : error_code(response["error"]["code"])),
113
+ authorization: (success ? response["id"] : nil)
114
+ )
115
+ end
116
+
117
+ def error_code(code)
118
+ STANDARD_ERROR_CODE_MAPPING[code] || code
119
+ end
120
+
121
+ def url
122
+ test? ? self.test_url : self.live_url
123
+ end
124
+
125
+ def headers
126
+ {
127
+ "Authorization" => "Basic " + Base64.encode64(@options[:login].to_s + ":").strip,
128
+ "Accept" => "application/json",
129
+ "Content-Type" => "application/json",
130
+ "User-Agent" => "Komoju/v1 ActiveMerchantBindings/#{ActiveMerchant::VERSION}"
131
+ }
132
+ end
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,36 @@
1
+ module SpreeKomoju
2
+ module Generators
3
+ class InstallGenerator < Rails::Generators::Base
4
+
5
+ class_option :auto_run_migrations, :type => :boolean, :default => false
6
+ source_root File.expand_path('../', __FILE__)
7
+
8
+ def add_javascripts
9
+ append_file 'vendor/assets/javascripts/spree/frontend/all.js', "//= require spree/frontend/spree_komoju\n"
10
+ append_file 'vendor/assets/javascripts/spree/backend/all.js', "//= require spree/backend/spree_komoju\n"
11
+ end
12
+
13
+ def add_stylesheets
14
+ inject_into_file 'vendor/assets/stylesheets/spree/frontend/all.css', " *= require spree/frontend/spree_komoju\n", :before => /\*\//, :verbose => true
15
+ inject_into_file 'vendor/assets/stylesheets/spree/backend/all.css', " *= require spree/backend/spree_komoju\n", :before => /\*\//, :verbose => true
16
+ end
17
+
18
+ def add_migrations
19
+ run 'bundle exec rake railties:install:migrations FROM=spree_komoju'
20
+ end
21
+
22
+ def add_images
23
+ directory "images", "app/assets/images"
24
+ end
25
+
26
+ def run_migrations
27
+ run_migrations = options[:auto_run_migrations] || ['', 'y', 'Y'].include?(ask 'Would you like to run the migrations now? [Y/n]')
28
+ if run_migrations
29
+ run 'bundle exec rake db:migrate'
30
+ else
31
+ puts 'Skipping rake db:migrate, don\'t forget to run it!'
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,2 @@
1
+ require 'spree_core'
2
+ require 'spree_komoju/engine'
@@ -0,0 +1,29 @@
1
+ module SpreeKomoju
2
+ mattr_accessor :enable_customer_profiles
3
+
4
+ class Engine < Rails::Engine
5
+ require 'spree/core'
6
+ isolate_namespace Spree
7
+ engine_name 'spree_komoju'
8
+
9
+ initializer "spree.gateway.payment_methods", after: "spree.register.payment_methods" do |app|
10
+ app.config.spree.payment_methods << Spree::Gateway::KomojuCreditCard
11
+ app.config.spree.payment_methods << Spree::Gateway::KomojuKonbini
12
+ app.config.spree.payment_methods << Spree::Gateway::KomojuBankTransfer
13
+ end
14
+
15
+ # use rspec for tests
16
+ config.generators do |g|
17
+ g.test_framework :rspec
18
+ end
19
+
20
+ def self.activate
21
+ Dir.glob(File.join(File.dirname(__FILE__), '../../app/**/*_decorator*.rb')) do |c|
22
+ Rails.configuration.cache_classes ? require(c) : load(c)
23
+ end
24
+ require "active_merchant/billing/gateways/komoju"
25
+ end
26
+
27
+ config.to_prepare &method(:activate).to_proc
28
+ end
29
+ end
@@ -0,0 +1,6 @@
1
+ FactoryGirl.define do
2
+ # Define your Spree extensions Factories within this file to enable applications, and other extensions to use and override them.
3
+ #
4
+ # Example adding this to your spec_helper will load these Factories for use:
5
+ # require 'spree_komoju/factories'
6
+ end
@@ -0,0 +1,13 @@
1
+ require "spec_helper"
2
+
3
+ describe Spree::CheckoutController, type: :controller do
4
+ describe "#permitted_source_attributes" do
5
+ it "returns added attributes" do
6
+ source_attributes = [:number, :month, :year, :expiry, :verification_value, :first_name, :last_name, :cc_type,
7
+ :gateway_customer_profile_id, :gateway_payment_profile_id, :last_digits, :name,
8
+ :encrypted_data, :convenience, :email, :phone, :family_name, :given_name, :family_name_kana,
9
+ :given_name_kana]
10
+ expect(controller.permitted_source_attributes).to eq source_attributes
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,69 @@
1
+ require "spec_helper"
2
+
3
+ describe Spree::BankTransfer, type: :model do
4
+ subject { described_class.new }
5
+
6
+ describe "#actions" do
7
+ it { expect(subject.actions).to eq ["capture", "void"] }
8
+ end
9
+
10
+ describe "#can_capture?" do
11
+ let(:payment) { double(Spree::Payment, state: state) }
12
+
13
+ before do
14
+ allow(subject).to receive(:payment) { payment }
15
+ end
16
+
17
+ context "when payment state is not checkout or pending" do
18
+ let(:state) { "void" }
19
+
20
+ it { expect(subject.can_capture?(payment)).to be_falsy }
21
+ end
22
+
23
+ context "when payment state is pending" do
24
+ let(:payment) { double(Spree::Payment, state: state, source: source) }
25
+ let(:state) { "pending" }
26
+ let(:source) { double(Spree::BankTransfer, expires_at: expires_at) }
27
+
28
+ before do
29
+ allow(subject).to receive(:payment) { payment }
30
+ end
31
+
32
+ context "when expires_at is tomorrow" do
33
+ let(:expires_at) { Date.tomorrow }
34
+
35
+ it { expect(subject.can_capture?(payment)).to be_truthy }
36
+ end
37
+
38
+ context "when expires_at is yesterday" do
39
+ let(:expires_at) { Date.yesterday}
40
+
41
+ it { expect(subject.can_capture?(payment)).to be_falsy }
42
+ end
43
+ end
44
+ end
45
+
46
+ describe "#can_void?" do
47
+ let(:payment) { double(Spree::Payment, state: state) }
48
+
49
+ before do
50
+ allow(subject).to receive(:payment) { payment }
51
+ end
52
+
53
+ context "when payment state is void" do
54
+ let(:state) { "void" }
55
+
56
+ it { expect(subject.can_void?(payment)).to be_falsy }
57
+ end
58
+
59
+ context "when payment state is pending" do
60
+ let(:state) { "pending" }
61
+
62
+ it { expect(subject.can_void?(payment)).to be_truthy }
63
+ end
64
+ end
65
+
66
+ describe "#instructions_partial_path" do
67
+ it { expect(subject.instructions_partial_path).to eq "spree/orders/bank_transfer" }
68
+ end
69
+ end