active_merchant_allpay 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
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