active_merchant_allpay 0.1.3 → 0.1.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d467a9624b0f4d42c7dd14cb9b8ebf8db9c056df
4
- data.tar.gz: 45a5dc9ed7b03596169a6c2df036ac34e71024f8
3
+ metadata.gz: f30de7a7d49b868d7b0b7a0523ff14a284973508
4
+ data.tar.gz: 79018eb6d538f59ff2e050d8608a11fc6f70c520
5
5
  SHA512:
6
- metadata.gz: 337c0e216545c9cba715c918af82c82867ecd6a1bd9e85d93f05a04d6fc7e0cdb8014399c729afcb520f46f6a5a1e46fcdac158515c71e9d6720023e746e81fd
7
- data.tar.gz: 75436bce4417065d222d079fc58fa89e9f033e4136b378261e29738b676b324ce1c19bc3c009bef1e8644035fcc981bd498f07f095a70511238a688b30bed97b
6
+ metadata.gz: eeced86fd5b1092c30d92de9695030cd381658734b55fb1036a4d96ed0ee51889bd669b5a7018f045059075ab7ef499e81495e0bc69789c359607da8e9df115d
7
+ data.tar.gz: a50767cbae566dfe7c0e42735bd197ef55baf796954a3266fe0ff306df91869d4b13b73ffb079d3f8f7ac7d30f4049945187e76bcce676dd78141b7c208e1653
data/README.md CHANGED
@@ -1,13 +1,15 @@
1
1
  # ActiveMerchantAllpay
2
2
 
3
3
  This plugin is an active_merchant patch forAllpay(歐付寶) online payment in Taiwan.
4
- Now it supports Credit card(信用卡), ATM(虛擬ATM) and CVS(超商繳費).
4
+ Now it supports Credit card(信用卡), ATM(虛擬ATM), Alipay(支付寶), CVS(超商繳費) and BARCODE(超商條碼).
5
+
6
+ It has been tested on Rails 4.1.6 successfully.
5
7
 
6
8
  ## Installation
7
9
 
8
10
  Add this line to your application's Gemfile:
9
11
 
10
- gem 'activemerchant'
12
+ gem 'activemerchant', "~> 1.43.3"
11
13
  gem 'active_merchant_allpay', '>=0.1.2'
12
14
 
13
15
  And then execute:
@@ -21,7 +23,7 @@ Or install it yourself as:
21
23
 
22
24
  ## Usage
23
25
 
24
- You can get Payment API and SPEC in [Allpay API](http://www.allpay.com.tw/Service/API).
26
+ You can get Payment API and SPEC in [Allpay API](https://www.allpay.com.tw/Service/API_Help).
25
27
  Then create an initializer, like initializers/allpay.rb. Add the following configurations depends on your settings.
26
28
 
27
29
  ``` ruby
@@ -39,12 +41,16 @@ end
39
41
  ```
40
42
 
41
43
  ``` ruby
44
+
45
+ # initializers/allpay.rb
42
46
  ActiveMerchant::Billing::Integrations::Allpay.setup do |allpay|
43
47
  if Rails.env.development?
44
- allpay.merchant_id = '5566183'
45
- allpay.hash_key = '56cantdieohyeah'
46
- allpay.hash_iv = '183club'
48
+ # default setting for stage test
49
+ allpay.merchant_id = '2000132'
50
+ allpay.hash_key = '5294y06JbISpM5x9'
51
+ allpay.hash_iv = 'v77hoKGq4kWxNNIS'
47
52
  else
53
+ # change to yours
48
54
  allpay.merchant_id = '7788520'
49
55
  allpay.hash_key = 'adfas123412343j'
50
56
  allpay.hash_iv = '123ddewqerasdfas'
@@ -65,6 +71,12 @@ Now support three payment methods:
65
71
 
66
72
  # 3. CVS (convenience store)
67
73
  ActiveMerchant::Billing::Integrations::Allpay::PAYMENT_CVS
74
+
75
+ # 4. Alipay
76
+ ActiveMerchant::Billing::Integrations::Allpay::PAYMENT_ALIPAY
77
+
78
+ # 5. BARCODE
79
+ ActiveMerchant::Billing::Integrations::Allpay::PAYMENT_BARCODE
68
80
  ```
69
81
 
70
82
  Once you’ve configured ActiveMerchantAllpay, you need a checkout form; it looks like:
@@ -77,11 +89,11 @@ Once you’ve configured ActiveMerchantAllpay, you need a checkout form; it look
77
89
  <% service.merchant_trade_no @order.payments.last.identifier %>
78
90
  <% service.merchant_trade_date @order.created_at %>
79
91
  <% service.total_amount @order.total.to_i %>
80
- <% service.trade_desc @order.number %>
92
+ <% service.description @order.number %>
81
93
  <% service.item_name @order.number %>
82
94
  <% service.choose_payment ActiveMerchant::Billing::Integrations::Allpay::PAYMENT_ATM %>
83
- <% service.client_back_url spree.orders_account_url %>
84
- <% service.return_url allpay_atm_return_url %>
95
+ <% service.return_url spree.orders_account_url %>
96
+ <% service.notify_url allpay_atm_return_url %>
85
97
  <% service.encrypted_data %>
86
98
  <%= submit_tag 'Buy!' %>
87
99
  <% end %>
@@ -91,7 +103,7 @@ Also need a notification action when Allpay service notifies your server; it loo
91
103
 
92
104
  ``` ruby
93
105
  def notify
94
- notification = ActiveMerchant::Billing::Integrations::Allpay::Notification.new(params)
106
+ notification = ActiveMerchant::Billing::Integrations::Allpay::Notification.new(request.raw_post)
95
107
 
96
108
  order = Order.find_by_number(notification.merchant_trade_no)
97
109
 
@@ -105,6 +117,30 @@ Also need a notification action when Allpay service notifies your server; it loo
105
117
  end
106
118
  ```
107
119
 
120
+ ## Troublechooting
121
+ If you get a error "undefined method \`payment\_service\_for\`", you can add following configurations to initializers/allpay.rb.
122
+ ```
123
+ require "active_merchant/billing/integrations/action_view_helper"
124
+ ActionView::Base.send(:include, ActiveMerchant::Billing::Integrations::ActionViewHelper)
125
+ ```
126
+
127
+ Some allpay error due to CSRF token ("authenticity_token is not in spec"), you can add following scripts to remove them manually.
128
+ ```
129
+ <script>
130
+ $("input[name=utf8]").remove();
131
+ $("input[name=authenticity_token]").remove();
132
+ </script>
133
+ ```
134
+ It's caused from payment\_service\_for helper function when generating by [offsite_payments](https://github.com/Shopify/offsite_payments) gem (offsite\_payments/lib/offsite\_payments/action\_view\_helper.rb)
135
+
136
+
137
+ ## Upgrade Notes
138
+
139
+ When upgrading from 0.1.3 and below to any higher versions, you need to make the following changes:
140
+
141
+ - the notification initialize with raw post string (instead of a hash of params)
142
+ - `return_url()` should be renamed to `notify_url()` (server-side callback url).
143
+
108
144
  ## Contributing
109
145
 
110
146
  1. Fork it
data/Rakefile CHANGED
@@ -1 +1,19 @@
1
1
  require "bundler/gem_tasks"
2
+
3
+ require 'rake/testtask'
4
+
5
+ desc "Run the unit test suite"
6
+ task :default => 'test:units'
7
+
8
+ task :test => 'test:units'
9
+
10
+ namespace :test do
11
+
12
+ Rake::TestTask.new(:units) do |t|
13
+ t.pattern = 'test/unit/**/*_test.rb'
14
+ t.ruby_opts << '-rubygems'
15
+ t.libs << 'test'
16
+ t.verbose = true
17
+ end
18
+
19
+ end
@@ -18,7 +18,8 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_dependency 'activemerchant', '>= 1.9.4'
21
+ spec.add_dependency 'activemerchant', '~> 1.43.3'
22
+ spec.add_development_dependency('test-unit', '~> 2.5.5')
22
23
 
23
24
  spec.add_development_dependency('rake')
24
25
  spec.add_development_dependency('mocha', '~> 0.13.0')
@@ -11,6 +11,22 @@ module ActiveMerchant #:nodoc:
11
11
  PAYMENT_CREDIT_CARD = 'Credit'
12
12
  PAYMENT_ATM = 'ATM'
13
13
  PAYMENT_CVS = 'CVS'
14
+ PAYMENT_ALIPAY = 'Alipay'
15
+ PAYMENT_BARCODE = 'BARCODE'
16
+
17
+ SUBPAYMENT_ATM_TAISHIN = 'TAISHIN'
18
+ SUBPAYMENT_ATM_ESUN = 'ESUN'
19
+ SUBPAYMENT_ATM_HUANAN = 'HUANAN'
20
+ SUBPAYMENT_ATM_BOT = 'BOT'
21
+ SUBPAYMENT_ATM_FUBON = 'FUBON'
22
+ SUBPAYMENT_ATM_CHINATRUST = 'CHINATRUST'
23
+ SUBPAYMENT_ATM_FIRST = 'FIRST'
24
+
25
+ SUBPAYMENT_CVS_CVS = 'CVS'
26
+ SUBPAYMENT_CVS_OK = 'OK'
27
+ SUBPAYMENT_CVS_FAMILY = 'FAMILY'
28
+ SUBPAYMENT_CVS_HILIFE = 'HILIFE'
29
+ SUBPAYMENT_CVS_IBON = 'IBON'
14
30
 
15
31
  PAYMENT_TYPE = 'aio'
16
32
 
@@ -18,6 +34,7 @@ module ActiveMerchant #:nodoc:
18
34
  mattr_accessor :merchant_id
19
35
  mattr_accessor :hash_key
20
36
  mattr_accessor :hash_iv
37
+ mattr_accessor :debug
21
38
 
22
39
  def self.service_url
23
40
  mode = ActiveMerchant::Billing::Base.integration_mode
@@ -9,65 +9,126 @@ module ActiveMerchant #:nodoc:
9
9
  module Allpay
10
10
  class Helper < ActiveMerchant::Billing::Integrations::Helper
11
11
 
12
+ ### 常見介面
13
+
14
+ # 廠商編號
12
15
  mapping :merchant_id, 'MerchantID'
16
+ mapping :account, 'MerchantID' # AM common
17
+ # 廠商交易編號
13
18
  mapping :merchant_trade_no, 'MerchantTradeNo'
14
- mapping :payment_type, 'PaymentType'
19
+ mapping :order, 'MerchantTradeNo' # AM common
20
+ # 交易金額
15
21
  mapping :total_amount, 'TotalAmount'
16
- mapping :return_url, 'ReturnURL'
17
- mapping :client_back_url, 'ClientBackURL'
22
+ mapping :amount, 'TotalAmount' # AM common
23
+ # 付款完成通知回傳網址
24
+ mapping :notify_url, 'ReturnURL' # AM common
25
+ # Client 端返回廠商網址
26
+ # mapping :client_back_url, 'ClientBackURL'
27
+ mapping :return_url, 'ClientBackURL' # AM common
28
+ # 付款完成 redirect 的網址
29
+ mapping :redirect_url, 'OrderResultURL'
30
+ # 交易描述
31
+ mapping :description, 'TradeDesc'
32
+ # 商品銷售網址
33
+ mapping :item_url, 'ItemURL'
34
+ # 是否需要額外的付款資訊, defalut: N
35
+ mapping :need_extra_paid_info, 'NeedExtraPaidInfo'
36
+ # 裝置來源, defalut: P
37
+ mapping :devise_source, 'DeviceSource'
38
+ # 忽略的付款方式
39
+ mapping :ignore_payment, 'IgnorePayment'
40
+ # 特約合作平台商代號(由allpay提供)
41
+ mapping :platform_id, 'PlatformID'
42
+ # 電子發票開註記
43
+ mapping :invoice_mark, 'InvoiceMark'
44
+ # 是否延遲撥款, defalut: 0
45
+ mapping :hold_trade_amt, 'HoldTradeAMT'
46
+ # allpay 的會員編號
47
+ mapping :allpay_id, 'AllPayID'
48
+ # allpay 的會員識別碼
49
+ mapping :account_id, 'AccountID'
50
+ # CheckMacValue 加密類型, defalut: 0
51
+ mapping :encrypt_type, 'EncryptType'
52
+ # ATM 允許繳費有效天數
53
+ mapping :expire_date, 'ExpireDate'
54
+ # ATM, CVS 序號回傳網址 (Server Side)
55
+ mapping :payment_info_url, 'PaymentInfoURL'
56
+ # ATM, CVS 序號頁面回傳網址 (Client Side)
57
+ mapping :payment_redirect_url, 'ClientRedirectURL'
58
+ # BARCODE, CVS 超商繳費截止時間
59
+ mapping :store_expire_date, 'StoreExpireDate'
60
+ # BARCODE, CVS 交易描述1
61
+ mapping :desc_1, 'Desc_1'
62
+ # BARCODE, CVS 交易描述2
63
+ mapping :desc_2, 'Desc_2'
64
+ # BARCODE, CVS 交易描述3
65
+ mapping :desc_3, 'Desc_3'
66
+ # BARCODE, CVS 交易描述4
67
+ mapping :desc_4, 'Desc_4'
68
+
69
+ ### Allpay 專屬介面
70
+
71
+ # 交易類型
72
+ mapping :payment_type, 'PaymentType'
73
+
74
+ # 選擇預設付款方式
75
+ # Credit:信用卡
76
+ # WebATM:網路 ATM
77
+ # ATM:自動櫃員機
78
+ # CVS:超商代碼
79
+ # BARCODE:超商條碼
80
+ # Alipay:支付寶
81
+ # Tenpay:財付通
82
+ # TopUpUsed:儲值消費
83
+ # ALL:不指定付款方式, 由歐付寶顯示付款方式 選擇頁面
18
84
  mapping :choose_payment, 'ChoosePayment'
19
85
 
86
+ mapping :choose_sub_payment, 'ChooseSubPayment'
87
+
88
+ # 商品名稱
89
+ # 多筆請以井號分隔 (#)
90
+ mapping :item_name, 'ItemName'
91
+
20
92
  def initialize(order, account, options = {})
21
93
  super
22
94
  add_field 'MerchantID', ActiveMerchant::Billing::Integrations::Allpay.merchant_id
23
95
  add_field 'PaymentType', ActiveMerchant::Billing::Integrations::Allpay::PAYMENT_TYPE
24
96
  end
25
97
 
26
- def merchant_trade_no(trade_number)
27
- add_field 'MerchantTradeNo', trade_number
28
- end
29
-
30
98
  def merchant_trade_date(date)
31
99
  add_field 'MerchantTradeDate', date.strftime('%Y/%m/%d %H:%M:%S')
32
100
  end
33
101
 
34
- def total_amount(amount)
35
- add_field 'TotalAmount', amount
36
- end
37
-
38
- def trade_desc(description)
39
- add_field 'TradeDesc', description
40
- end
41
-
42
- def item_name(item)
43
- add_field 'ItemName', item
44
- end
45
-
46
- def choose_payment(payment)
47
- add_field 'ChoosePayment', payment
48
- end
49
-
50
- def return_url(url)
51
- add_field 'ReturnURL', url
52
- end
53
-
54
- def client_back_url(url)
55
- add_field 'ClientBackURL', url
56
- end
57
-
58
102
  def encrypted_data
59
103
 
60
104
  raw_data = @fields.sort.map{|field, value|
61
- "#{field}=#{value}"
105
+ # utf8, authenticity_token, commit are generated from form helper, needed to skip
106
+ "#{field}=#{value}" if field!='utf8' && field!='authenticity_token' && field!='commit'
62
107
  }.join('&')
63
108
 
64
109
  hash_raw_data = "HashKey=#{ActiveMerchant::Billing::Integrations::Allpay.hash_key}&#{raw_data}&HashIV=#{ActiveMerchant::Billing::Integrations::Allpay.hash_iv}"
110
+ url_encode_data = self.class.url_encode(hash_raw_data)
111
+ url_encode_data.downcase!
65
112
 
66
- url_endcode_data = (CGI::escape(hash_raw_data)).downcase
113
+ binding.pry if ActiveMerchant::Billing::Integrations::Allpay.debug
67
114
 
68
- add_field 'CheckMacValue', Digest::MD5.hexdigest(url_endcode_data)
115
+ add_field 'CheckMacValue', Digest::MD5.hexdigest(url_encode_data).upcase
69
116
  end
70
117
 
118
+ # Allpay .NET url encoding
119
+ # Code based from CGI.escape()
120
+ # Some special characters (e.g. "()*!") are not escaped on Allpay server when they generate their check sum value, causing CheckMacValue Error.
121
+ #
122
+ # TODO: The following characters still cause CheckMacValue error:
123
+ # '<', "\n", "\r", '&'
124
+ def self.url_encode(text)
125
+ text = text.dup
126
+ text.gsub!(/([^ a-zA-Z0-9\(\)\!\*_.-]+)/) do
127
+ '%' + $1.unpack('H2' * $1.bytesize).join('%')
128
+ end
129
+ text.tr!(' ', '+')
130
+ text
131
+ end
71
132
  end
72
133
  end
73
134
  end
@@ -14,14 +14,36 @@ module ActiveMerchant #:nodoc:
14
14
  end
15
15
  end
16
16
 
17
+ # TODO 使用查詢功能實作 acknowledge
18
+ # Allpay 沒有遠端驗證功能,
19
+ # 而以 checksum_ok? 代替
20
+ def acknowledge
21
+ checksum_ok?
22
+ end
23
+
24
+ def complete?
25
+ case @params['RtnCode']
26
+ when '1' #付款成功
27
+ true
28
+ when '2' # ATM 取號成功
29
+ true
30
+ when '10100073' # CVS 或 BARCODE 取號成功
31
+ true
32
+ when '800' #貨到付款訂單建立成功
33
+ true
34
+ else
35
+ false
36
+ end
37
+ end
38
+
17
39
  def checksum_ok?
18
- checksum = @params.delete('CheckMacValue')
40
+ params_copy = @params.clone
19
41
 
20
- @params.delete('controller')
21
- @params.delete('action')
42
+ checksum = params_copy.delete('CheckMacValue')
22
43
 
23
44
  # 把 params 轉成 query string 前必須先依照 hash key 做 sort
24
- raw_data = Hash[@params.sort].map do |x, y|
45
+ # 依照英文字母排序,由 A Z 且大小寫不敏感
46
+ raw_data = params_copy.sort_by{ |k,v| k.downcase }.map do |x, y|
25
47
  "#{x}=#{y}"
26
48
  end.join('&')
27
49
 
@@ -32,16 +54,6 @@ module ActiveMerchant #:nodoc:
32
54
  (Digest::MD5.hexdigest(url_endcode_data) == checksum.to_s.downcase)
33
55
  end
34
56
 
35
- def initialize(params)
36
- self.params = params
37
- end
38
-
39
- def params=(params)
40
- @params = params.inject({}) do |buffer, (name, value)|
41
- buffer.merge(name.to_s => value)
42
- end
43
- end
44
-
45
57
  def rtn_code
46
58
  @params['RtnCode']
47
59
  end
@@ -50,21 +62,28 @@ module ActiveMerchant #:nodoc:
50
62
  @params['MerchantID']
51
63
  end
52
64
 
65
+ # 廠商交易編號
53
66
  def merchant_trade_no
54
67
  @params['MerchantTradeNo']
55
68
  end
69
+ alias :item_id :merchant_trade_no
56
70
 
57
71
  def rtn_msg
58
72
  @params['RtnMsg']
59
73
  end
60
74
 
75
+ # AllPay 的交易編號
61
76
  def trade_no
62
77
  @params['TradeNo']
63
78
  end
79
+ alias :transaction_id :trade_no
64
80
 
65
81
  def trade_amt
66
82
  @params['TradeAmt']
67
83
  end
84
+ def gross
85
+ ::Money.new(@params['TradeAmt'].to_i * 100, currency)
86
+ end
68
87
 
69
88
  def payment_date
70
89
  @params['PaymentDate']
@@ -90,17 +109,40 @@ module ActiveMerchant #:nodoc:
90
109
  @params['CheckMacValue']
91
110
  end
92
111
 
93
- private
112
+ # for ATM
113
+ def bank_code
114
+ @params['BankCode']
115
+ end
94
116
 
95
- # Take the posted data and move the relevant data into a hash
96
- def parse(post)
97
- @raw = post.to_s
98
- for line in @raw.split('&')
99
- key, value = *line.scan(%r{^([A-Za-z0-9_.]+)\=(.*)$}).flatten
100
- params[key] = CGI.unescape(value)
101
- end
117
+ def v_account
118
+ @params['vAccount']
119
+ end
120
+
121
+ def expire_date
122
+ @params['ExpireDate']
123
+ end
124
+
125
+ # for CVS
126
+ def payment_no
127
+ @params['PaymentNo']
102
128
  end
103
129
 
130
+ def currency
131
+ 'TWD'
132
+ end
133
+
134
+ # for BARCODE
135
+ def barcode1
136
+ @params['Barcode1']
137
+ end
138
+
139
+ def barcode2
140
+ @params['Barcode2']
141
+ end
142
+
143
+ def barcode3
144
+ @params['Barcode3']
145
+ end
104
146
  end
105
147
  end
106
148
  end
@@ -1,3 +1,3 @@
1
1
  module ActiveMerchantAllpay
2
- VERSION = "0.1.3"
2
+ VERSION = "0.1.4"
3
3
  end
@@ -0,0 +1,105 @@
1
+ #!/usr/bin/env ruby
2
+ $:.unshift File.expand_path('../../lib', __FILE__)
3
+
4
+ begin
5
+ require 'rubygems'
6
+ require 'bundler'
7
+ Bundler.setup
8
+ rescue LoadError => e
9
+ puts "Error loading bundler (#{e.message}): \"gem install bundler\" for bundler support."
10
+ end
11
+
12
+ require 'active_merchant_allpay'
13
+
14
+ require 'test/unit'
15
+ require 'money'
16
+
17
+ ActiveMerchant::Billing::Base.mode = :test
18
+
19
+ module ActiveMerchant
20
+ module Assertions
21
+ AssertionClass = Test::Unit::AssertionFailedError
22
+
23
+ def assert_field(field, value)
24
+ clean_backtrace do
25
+ assert_equal value, @helper.fields[field]
26
+ end
27
+ end
28
+
29
+ # Allows the testing of you to check for negative assertions:
30
+ #
31
+ # # Instead of
32
+ # assert !something_that_is_false
33
+ #
34
+ # # Do this
35
+ # assert_false something_that_should_be_false
36
+ #
37
+ # An optional +msg+ parameter is available to help you debug.
38
+ def assert_false(boolean, message = nil)
39
+ message = build_message message, '<?> is not false or nil.', boolean
40
+
41
+ clean_backtrace do
42
+ assert_block message do
43
+ not boolean
44
+ end
45
+ end
46
+ end
47
+
48
+ # A handy little assertion to check for a successful response:
49
+ #
50
+ # # Instead of
51
+ # assert_success response
52
+ #
53
+ # # DRY that up with
54
+ # assert_success response
55
+ #
56
+ # A message will automatically show the inspection of the response
57
+ # object if things go afoul.
58
+ def assert_success(response)
59
+ clean_backtrace do
60
+ assert response.success?, "Response failed: #{response.inspect}"
61
+ end
62
+ end
63
+
64
+ # The negative of +assert_success+
65
+ def assert_failure(response)
66
+ clean_backtrace do
67
+ assert_false response.success?, "Response expected to fail: #{response.inspect}"
68
+ end
69
+ end
70
+
71
+ def assert_valid(validateable)
72
+ clean_backtrace do
73
+ assert validateable.valid?, "Expected to be valid"
74
+ end
75
+ end
76
+
77
+ def assert_not_valid(validateable)
78
+ clean_backtrace do
79
+ assert_false validateable.valid?, "Expected to not be valid"
80
+ end
81
+ end
82
+
83
+ def assert_deprecation_warning(message, target)
84
+ target.expects(:deprecated).with(message)
85
+ yield
86
+ end
87
+
88
+ def assert_no_deprecation_warning(target)
89
+ target.expects(:deprecated).never
90
+ yield
91
+ end
92
+
93
+ private
94
+ def clean_backtrace(&block)
95
+ yield
96
+ rescue AssertionClass => e
97
+ path = File.expand_path(__FILE__)
98
+ raise AssertionClass, e.message, e.backtrace.reject { |line| File.expand_path(line) =~ /#{path}/ }
99
+ end
100
+ end
101
+ end
102
+
103
+ Test::Unit::TestCase.class_eval do
104
+ include ActiveMerchant::Assertions
105
+ end
@@ -6,4 +6,47 @@ class AllpayHelperTest < Test::Unit::TestCase
6
6
  def setup
7
7
  end
8
8
 
9
+ def test_check_mac_value
10
+ @helper = Allpay::Helper.new 'sdfasdfa', '12345678'
11
+ @helper.add_field 'ItemName', 'sdfasdfa'
12
+ @helper.add_field 'MerchantID', '12345678'
13
+ @helper.add_field 'MerchantTradeDate', '2013/03/12 15:30:23'
14
+ @helper.add_field 'MerchantTradeNo','allpay_1234'
15
+ @helper.add_field 'PaymentType', 'allpay'
16
+ @helper.add_field 'ReturnURL', 'http:sdfasdfa'
17
+ @helper.add_field 'TotalAmount', '500'
18
+ @helper.add_field 'TradeDesc', 'dafsdfaff'
19
+
20
+ ActiveMerchant::Billing::Integrations::Allpay.hash_key = 'xdfaefasdfasdfa32d'
21
+ ActiveMerchant::Billing::Integrations::Allpay.hash_iv = 'sdfxfafaeafwexfe'
22
+
23
+ @helper.encrypted_data
24
+
25
+ assert_equal '40D9A6C00A4A78A300ED458237071BDA', @helper.fields['CheckMacValue']
26
+ end
27
+
28
+ def test_check_mac_value_with_special_characters
29
+ @helper = Allpay::Helper.new 'R435729525344', '2000132'
30
+ @helper.add_field 'ItemName', 'Guava'
31
+ @helper.add_field 'MerchantID', '2000132'
32
+ @helper.add_field 'MerchantTradeDate', '2014/08/07 17:17:33'
33
+ @helper.add_field 'MerchantTradeNo','R435729525344'
34
+ @helper.add_field 'PaymentType', 'aio'
35
+ @helper.add_field 'ReturnURL', 'http://example.com/notify'
36
+ @helper.add_field 'TotalAmount', '1000'
37
+ @helper.add_field 'TradeDesc', ( '~`@#$%*^()_-+={}[]|\\"\'>,.?/:;' + "\t" )
38
+ @helper.add_field 'ChoosePayment', 'Credit'
39
+
40
+ ActiveMerchant::Billing::Integrations::Allpay.hash_key = '5294y06JbISpM5x9'
41
+ ActiveMerchant::Billing::Integrations::Allpay.hash_iv = 'v77hoKGq4kWxNNIS'
42
+
43
+ @helper.encrypted_data
44
+
45
+ assert_equal 'DF1186B7B8651F44380BEF8AB8A5727B', @helper.fields['CheckMacValue']
46
+ end
47
+
48
+ def test_url_encoding
49
+ encoded = Allpay::Helper.url_encode('-_.!~*() @#$%^&=+;?/\\><`[]{}:\'",|')
50
+ assert_equal encoded, '-_.!%7e*()+%40%23%24%25%5e%26%3d%2b%3b%3f%2f%5c%3e%3c%60%5b%5d%7b%7d%3a%27%22%2c%7c'
51
+ end
9
52
  end
@@ -4,8 +4,35 @@ class AllpayNotificationTest < Test::Unit::TestCase
4
4
  include ActiveMerchant::Billing::Integrations
5
5
 
6
6
  def setup
7
+ ActiveMerchant::Billing::Integrations::Allpay.hash_key = '5294y06JbISpM5x9'
8
+ ActiveMerchant::Billing::Integrations::Allpay.hash_iv = 'v77hoKGq4kWxNNIS'
7
9
  @allpay = Allpay::Notification.new(http_raw_data)
8
10
  end
9
11
 
12
+ def test_params
13
+ p = @allpay.params
10
14
 
15
+ assert_equal 12, p.size
16
+ assert_equal 'Credit_CreditCard', p['PaymentType']
17
+ assert_equal 'BC586977559ED305BEC4C334DFDC881D', p['CheckMacValue']
18
+ assert_equal '2014/04/15 15:39:38', p['PaymentDate']
19
+ end
20
+
21
+ def test_complete?
22
+ assert @allpay.complete?
23
+ end
24
+
25
+ def test_checksum_ok?
26
+ assert @allpay.checksum_ok?
27
+
28
+ # Should preserve mac value
29
+ assert @allpay.params['CheckMacValue'].present?
30
+ end
31
+
32
+ private
33
+
34
+ def http_raw_data
35
+ # Sample notification from test environment
36
+ "TradeAmt=2760&RtnMsg=付款成功&MerchantTradeNo=81397545579&PaymentType=Credit_CreditCard&TradeNo=1404151506342901&SimulatePaid=1&MerchantID=2000132&TradeDate=2014-04-15 15:06:34&PaymentDate=2014/04/15 15:39:38&PaymentTypeChargeFee=0&CheckMacValue=BC586977559ED305BEC4C334DFDC881D&RtnCode=1"
37
+ end
11
38
  end
metadata CHANGED
@@ -1,29 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_merchant_allpay
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - xwaynec
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-04-14 00:00:00.000000000 Z
11
+ date: 2015-09-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemerchant
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 1.9.4
19
+ version: 1.43.3
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 1.43.3
27
+ - !ruby/object:Gem::Dependency
28
+ name: test-unit
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 2.5.5
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
25
39
  - !ruby/object:Gem::Version
26
- version: 1.9.4
40
+ version: 2.5.5
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: rake
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -98,10 +112,10 @@ files:
98
112
  - lib/active_merchant/billing/integrations/allpay/notification.rb
99
113
  - lib/active_merchant_allpay.rb
100
114
  - lib/active_merchant_allpay/version.rb
115
+ - test/test_helper.rb
101
116
  - test/unit/integrations/allpay_module_test.rb
102
117
  - test/unit/integrations/helpers/allpay_helper_test.rb
103
118
  - test/unit/integrations/notifications/allpay_notification_test.rb
104
- - test/unit/test_helper.rb
105
119
  homepage: https://github.com/xwaynec/active_merchant_allpay
106
120
  licenses:
107
121
  - MIT
@@ -122,12 +136,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
122
136
  version: '0'
123
137
  requirements: []
124
138
  rubyforge_project:
125
- rubygems_version: 2.2.2
139
+ rubygems_version: 2.4.5
126
140
  signing_key:
127
141
  specification_version: 4
128
142
  summary: A rails plugin to add active_merchant patch for Taiwan payment
129
143
  test_files:
144
+ - test/test_helper.rb
130
145
  - test/unit/integrations/allpay_module_test.rb
131
146
  - test/unit/integrations/helpers/allpay_helper_test.rb
132
147
  - test/unit/integrations/notifications/allpay_notification_test.rb
133
- - test/unit/test_helper.rb
148
+ has_rdoc:
@@ -1,261 +0,0 @@
1
- #!/usr/bin/env ruby
2
- $:.unshift File.expand_path('../../lib', __FILE__)
3
-
4
- begin
5
- require 'rubygems'
6
- require 'bundler'
7
- Bundler.setup
8
- rescue LoadError => e
9
- puts "Error loading bundler (#{e.message}): \"gem install bundler\" for bundler support."
10
- end
11
-
12
- require 'test/unit'
13
- require 'money'
14
- require 'mocha/version'
15
- if(Mocha::VERSION.split(".")[1].to_i < 12)
16
- require 'mocha'
17
- else
18
- require 'mocha/setup'
19
- end
20
- require 'yaml'
21
- require 'json'
22
- require 'active_merchant'
23
- require 'comm_stub'
24
-
25
- require 'active_support/core_ext/integer/time'
26
- require 'active_support/core_ext/numeric/time'
27
-
28
- begin
29
- require 'active_support/core_ext/time/acts_like'
30
- rescue LoadError
31
- end
32
-
33
- begin
34
- gem 'actionpack'
35
- rescue LoadError
36
- raise StandardError, "The view tests need ActionPack installed as gem to run"
37
- end
38
-
39
- require 'action_controller'
40
- require "action_view/template"
41
- begin
42
- require 'active_support/core_ext/module/deprecation'
43
- require 'action_dispatch/testing/test_process'
44
- rescue LoadError
45
- require 'action_controller/test_process'
46
- end
47
- require 'active_merchant/billing/integrations/action_view_helper'
48
-
49
- ActiveMerchant::Billing::Base.mode = :test
50
-
51
- if ENV['DEBUG_ACTIVE_MERCHANT'] == 'true'
52
- require 'logger'
53
- ActiveMerchant::Billing::Gateway.logger = Logger.new(STDOUT)
54
- ActiveMerchant::Billing::Gateway.wiredump_device = STDOUT
55
- end
56
-
57
- # Test gateways
58
- class SimpleTestGateway < ActiveMerchant::Billing::Gateway
59
- end
60
-
61
- class SubclassGateway < SimpleTestGateway
62
- end
63
-
64
-
65
- module ActiveMerchant
66
- module Assertions
67
- AssertionClass = RUBY_VERSION > '1.9' ? MiniTest::Assertion : Test::Unit::AssertionFailedError
68
-
69
- def assert_field(field, value)
70
- clean_backtrace do
71
- assert_equal value, @helper.fields[field]
72
- end
73
- end
74
-
75
- # Allows the testing of you to check for negative assertions:
76
- #
77
- # # Instead of
78
- # assert !something_that_is_false
79
- #
80
- # # Do this
81
- # assert_false something_that_should_be_false
82
- #
83
- # An optional +msg+ parameter is available to help you debug.
84
- def assert_false(boolean, message = nil)
85
- message = build_message message, '<?> is not false or nil.', boolean
86
-
87
- clean_backtrace do
88
- assert_block message do
89
- not boolean
90
- end
91
- end
92
- end
93
-
94
- # A handy little assertion to check for a successful response:
95
- #
96
- # # Instead of
97
- # assert response.success?
98
- #
99
- # # DRY that up with
100
- # assert_success response
101
- #
102
- # A message will automatically show the inspection of the response
103
- # object if things go afoul.
104
- def assert_success(response, message=nil)
105
- clean_backtrace do
106
- assert response.success?, build_message(nil, "#{message + "\n" if message}Response expected to succeed: <?>", response)
107
- end
108
- end
109
-
110
- # The negative of +assert_success+
111
- def assert_failure(response, message=nil)
112
- clean_backtrace do
113
- assert !response.success?, build_message(nil, "#{message + "\n" if message}Response expected to fail: <?>", response)
114
- end
115
- end
116
-
117
- def assert_valid(validateable)
118
- clean_backtrace do
119
- assert validateable.valid?, "Expected to be valid"
120
- end
121
- end
122
-
123
- def assert_not_valid(validateable)
124
- clean_backtrace do
125
- assert_false validateable.valid?, "Expected to not be valid"
126
- end
127
- end
128
-
129
- def assert_deprecation_warning(message, target)
130
- target.expects(:deprecated).with(message)
131
- yield
132
- end
133
-
134
- def assert_no_deprecation_warning(target)
135
- target.expects(:deprecated).never
136
- yield
137
- end
138
-
139
- private
140
- def clean_backtrace(&block)
141
- yield
142
- rescue AssertionClass => e
143
- path = File.expand_path(__FILE__)
144
- raise AssertionClass, e.message, e.backtrace.reject { |line| File.expand_path(line) =~ /#{path}/ }
145
- end
146
- end
147
-
148
- module Fixtures
149
- HOME_DIR = RUBY_PLATFORM =~ /mswin32/ ? ENV['HOMEPATH'] : ENV['HOME'] unless defined?(HOME_DIR)
150
- LOCAL_CREDENTIALS = File.join(HOME_DIR.to_s, '.active_merchant/fixtures.yml') unless defined?(LOCAL_CREDENTIALS)
151
- DEFAULT_CREDENTIALS = File.join(File.dirname(__FILE__), 'fixtures.yml') unless defined?(DEFAULT_CREDENTIALS)
152
-
153
- private
154
- def credit_card(number = '4242424242424242', options = {})
155
- defaults = {
156
- :number => number,
157
- :month => 9,
158
- :year => Time.now.year + 1,
159
- :first_name => 'Longbob',
160
- :last_name => 'Longsen',
161
- :verification_value => '123',
162
- :brand => 'visa'
163
- }.update(options)
164
-
165
- Billing::CreditCard.new(defaults)
166
- end
167
-
168
- def check(options = {})
169
- defaults = {
170
- :name => 'Jim Smith',
171
- :bank_name => 'Bank of Elbonia',
172
- :routing_number => '244183602',
173
- :account_number => '15378535',
174
- :account_holder_type => 'personal',
175
- :account_type => 'checking',
176
- :number => '1'
177
- }.update(options)
178
-
179
- Billing::Check.new(defaults)
180
- end
181
-
182
- def address(options = {})
183
- {
184
- :name => 'Jim Smith',
185
- :address1 => '1234 My Street',
186
- :address2 => 'Apt 1',
187
- :company => 'Widgets Inc',
188
- :city => 'Ottawa',
189
- :state => 'ON',
190
- :zip => 'K1C2N6',
191
- :country => 'CA',
192
- :phone => '(555)555-5555',
193
- :fax => '(555)555-6666'
194
- }.update(options)
195
- end
196
-
197
- def all_fixtures
198
- @@fixtures ||= load_fixtures
199
- end
200
-
201
- def fixtures(key)
202
- data = all_fixtures[key] || raise(StandardError, "No fixture data was found for '#{key}'")
203
-
204
- data.dup
205
- end
206
-
207
- def load_fixtures
208
- [DEFAULT_CREDENTIALS, LOCAL_CREDENTIALS].inject({}) do |credentials, file_name|
209
- if File.exists?(file_name)
210
- yaml_data = YAML.load(File.read(file_name))
211
- credentials.merge!(symbolize_keys(yaml_data))
212
- end
213
- credentials
214
- end
215
- end
216
-
217
- def symbolize_keys(hash)
218
- return unless hash.is_a?(Hash)
219
-
220
- hash.symbolize_keys!
221
- hash.each{|k,v| symbolize_keys(v)}
222
- end
223
- end
224
- end
225
-
226
- Test::Unit::TestCase.class_eval do
227
- include ActiveMerchant::Billing
228
- include ActiveMerchant::Assertions
229
- include ActiveMerchant::Utils
230
- include ActiveMerchant::Fixtures
231
- end
232
-
233
- module ActionViewHelperTestHelper
234
-
235
- def self.included(base)
236
- base.send(:include, ActiveMerchant::Billing::Integrations::ActionViewHelper)
237
- base.send(:include, ActionView::Helpers::FormHelper)
238
- base.send(:include, ActionView::Helpers::FormTagHelper)
239
- base.send(:include, ActionView::Helpers::UrlHelper)
240
- base.send(:include, ActionView::Helpers::TagHelper)
241
- base.send(:include, ActionView::Helpers::CaptureHelper)
242
- base.send(:include, ActionView::Helpers::TextHelper)
243
- base.send(:attr_accessor, :output_buffer)
244
- end
245
-
246
- def setup
247
- @controller = Class.new do
248
- attr_reader :url_for_options
249
- def url_for(options, *parameters_for_method_reference)
250
- @url_for_options = options
251
- end
252
- end
253
- @controller = @controller.new
254
- @output_buffer = ''
255
- end
256
-
257
- protected
258
- def protect_against_forgery?
259
- false
260
- end
261
- end