nihaopay-ruby 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +5 -0
  3. data/LICENSE +22 -0
  4. data/README.md +344 -0
  5. data/lib/nihaopay-ruby.rb +29 -0
  6. data/lib/nihaopay/configure.rb +14 -0
  7. data/lib/nihaopay/credit_card.rb +27 -0
  8. data/lib/nihaopay/errors.rb +6 -0
  9. data/lib/nihaopay/merchant.rb +47 -0
  10. data/lib/nihaopay/mixins/api.rb +41 -0
  11. data/lib/nihaopay/mixins/queryable.rb +41 -0
  12. data/lib/nihaopay/query.rb +61 -0
  13. data/lib/nihaopay/secure_pay/ali_pay.rb +11 -0
  14. data/lib/nihaopay/secure_pay/base.rb +48 -0
  15. data/lib/nihaopay/secure_pay/union_pay.rb +11 -0
  16. data/lib/nihaopay/secure_pay/we_chat_pay.rb +11 -0
  17. data/lib/nihaopay/transactions/authorize.rb +37 -0
  18. data/lib/nihaopay/transactions/base.rb +78 -0
  19. data/lib/nihaopay/transactions/cancel.rb +28 -0
  20. data/lib/nihaopay/transactions/capture.rb +29 -0
  21. data/lib/nihaopay/transactions/purchase.rb +11 -0
  22. data/lib/nihaopay/transactions/refund.rb +31 -0
  23. data/lib/nihaopay/transactions/release.rb +28 -0
  24. data/lib/nihaopay/util/hash_util.rb +30 -0
  25. data/lib/nihaopay/version.rb +3 -0
  26. data/spec/credit_card_spec.rb +56 -0
  27. data/spec/merchant_spec.rb +142 -0
  28. data/spec/mixins/api_spec.rb +81 -0
  29. data/spec/mixins/queryable_spec.rb +95 -0
  30. data/spec/query_spec.rb +129 -0
  31. data/spec/secure_pay/ali_pay_spec.rb +112 -0
  32. data/spec/secure_pay/union_pay_spec.rb +13 -0
  33. data/spec/secure_pay/we_chat_pay_spec.rb +13 -0
  34. data/spec/spec_helper.rb +7 -0
  35. data/spec/transactions/authorize_spec.rb +115 -0
  36. data/spec/transactions/base_spec.rb +184 -0
  37. data/spec/transactions/cancel_spec.rb +83 -0
  38. data/spec/transactions/capture_spec.rb +85 -0
  39. data/spec/transactions/purchase_spec.rb +7 -0
  40. data/spec/transactions/refund_spec.rb +98 -0
  41. data/spec/transactions/release_spec.rb +83 -0
  42. data/spec/util/hash_util_spec.rb +22 -0
  43. metadata +187 -0
@@ -0,0 +1,6 @@
1
+ module Nihaopay
2
+ TransactionError = Class.new(StandardError)
3
+ SecurePayTransactionError = Class.new(TransactionError)
4
+ ExpressPayTransactionError = Class.new(TransactionError)
5
+ TransactionLookUpError = Class.new(TransactionError)
6
+ end
@@ -0,0 +1,47 @@
1
+ module Nihaopay
2
+ class Merchant
3
+ attr_accessor :token
4
+
5
+ def initialize(token)
6
+ self.token = token
7
+ end
8
+
9
+ def union_pay(amount, currency, options = {})
10
+ options[:token] = token
11
+ Nihaopay::SecurePay::UnionPay.start(amount, currency, options)
12
+ end
13
+
14
+ def ali_pay(amount, currency, options = {})
15
+ options[:token] = token
16
+ Nihaopay::SecurePay::AliPay.start(amount, currency, options)
17
+ end
18
+
19
+ def wechat_pay(amount, currency, options = {})
20
+ options[:token] = token
21
+ Nihaopay::SecurePay::WeChatPay.start(amount, currency, options)
22
+ end
23
+
24
+ def authorize(amount, credit_card, options = {})
25
+ options[:token] = token
26
+ Nihaopay::Transactions::Authorize.start(amount, credit_card, options)
27
+ end
28
+
29
+ def capture(transaction_id, amount, currency)
30
+ Nihaopay::Transactions::Capture.start(transaction_id, amount, currency, token: token)
31
+ end
32
+
33
+ def purchase(amount, credit_card, options = {})
34
+ options[:token] = token
35
+ Nihaopay::Transactions::Purchase.start(amount, credit_card, options)
36
+ end
37
+
38
+ def release(transaction_id)
39
+ Nihaopay::Transactions::Release.start(transaction_id, token: token)
40
+ end
41
+
42
+ def refund(transaction_id, amount, currency, options = {})
43
+ options[:token] = token
44
+ Nihaopay::Transactions::Refund.start(transaction_id, amount, currency, options)
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,41 @@
1
+ module Nihaopay
2
+ module Api
3
+ def self.included(base)
4
+ base.extend(ClassMethods)
5
+ end
6
+
7
+ LIVE_HOST = 'https://api.nihaopay.com'.freeze
8
+ TEST_HOST = 'http://api.test.nihaopay.com'.freeze
9
+ VERSION = 'v1.1'.freeze
10
+
11
+ module ClassMethods
12
+ def host
13
+ Nihaopay.test_mode ? TEST_HOST : LIVE_HOST
14
+ end
15
+
16
+ def base_url
17
+ "#{host}/#{VERSION}"
18
+ end
19
+
20
+ def authorization
21
+ { 'Authorization' => "Bearer #{merchant_token}" }
22
+ end
23
+
24
+ def merchant_token
25
+ @token || Nihaopay.token
26
+ end
27
+
28
+ def validate_resource!(response)
29
+ return if response.parsed_response['id']
30
+ parsed_response = response.parsed_response.map { |k, v| "#{k}: #{v}" }.join(', ')
31
+ fail Nihaopay::TransactionError, parsed_response
32
+ end
33
+
34
+ def validate_collection!(response)
35
+ return if response.parsed_response['transactions']
36
+ parsed_response = response.parsed_response.map { |k, v| "#{k}: #{v}" }.join(', ')
37
+ fail Nihaopay::TransactionError, parsed_response
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,41 @@
1
+ module Nihaopay
2
+ module Queryable
3
+ def self.included(base)
4
+ base.extend(ClassMethods)
5
+ end
6
+
7
+ module ClassMethods
8
+ def find(transaction_id)
9
+ url = "#{base_url}/transactions/#{transaction_id}"
10
+ response = HTTParty.get(url, headers: request_headers)
11
+ build_from_response!(response)
12
+ rescue Nihaopay::TransactionError => e
13
+ raise Nihaopay::TransactionLookUpError, e.message
14
+ end
15
+
16
+ def fetch(options = {})
17
+ options[:starting_after] = options.delete(:after) if options[:after]
18
+ options[:ending_before] = options.delete(:before) if options[:before]
19
+ q.fetch(options)
20
+ end
21
+
22
+ def limit(num)
23
+ q.limit(num)
24
+ end
25
+
26
+ def before(time)
27
+ q.before(time)
28
+ end
29
+
30
+ def after(time)
31
+ q.after(time)
32
+ end
33
+
34
+ private
35
+
36
+ def q
37
+ Nihaopay::Query.new
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,61 @@
1
+ module Nihaopay
2
+ class Query
3
+ include ::Nihaopay::Api
4
+
5
+ VALID_OPTIONS = %i(limit starting_after ending_before).freeze
6
+
7
+ def limit(num)
8
+ @limit = num
9
+ self
10
+ end
11
+
12
+ def before(time)
13
+ @ending_before = time
14
+ self
15
+ end
16
+
17
+ def after(time)
18
+ @starting_after = time
19
+ self
20
+ end
21
+
22
+ def fetch(options = nil)
23
+ options ||= { limit: @limit, starting_after: @starting_after, ending_before: @ending_before }
24
+ self.class.fetch(options)
25
+ end
26
+
27
+ class << self
28
+ def fetch(options = {})
29
+ query = query_params(options)
30
+ response = if query && !query.empty?
31
+ HTTParty.get(url, headers: request_headers, query: query)
32
+ else
33
+ HTTParty.get(url, headers: request_headers)
34
+ end
35
+ build_transactions(response)
36
+ rescue Nihaopay::TransactionError => e
37
+ raise Nihaopay::TransactionLookUpError, e.message
38
+ end
39
+
40
+ def url
41
+ "#{base_url}/transactions"
42
+ end
43
+
44
+ def request_headers
45
+ authorization
46
+ end
47
+
48
+ def query_params(options)
49
+ Nihaopay::HashUtil.slice(options, *VALID_OPTIONS).select { |_, v| v && (!v.respond_to?(:empty?) || !v.empty?) }
50
+ end
51
+
52
+ def build_transactions(response)
53
+ validate_collection!(response)
54
+ transactions = response.parsed_response['transactions']
55
+ transactions.map do |transaction|
56
+ Nihaopay::Transactions::Base.build(transaction)
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,11 @@
1
+ module Nihaopay
2
+ module SecurePay
3
+ class AliPay < Base
4
+ class << self
5
+ def vendor
6
+ :alipay
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,48 @@
1
+ module Nihaopay
2
+ module SecurePay
3
+ class Base
4
+ include ::Nihaopay::Api
5
+
6
+ class << self
7
+ def with_failure(&_)
8
+ response = yield
9
+ if response.code != 200
10
+ message = response.parsed_response.map { |k, v| "#{k}: #{v}" }.join(', ')
11
+ fail SecurePayTransactionError, message
12
+ end
13
+ response
14
+ end
15
+
16
+ def start(amount, currency, options = {})
17
+ with_failure do
18
+ @token = options.delete(:token)
19
+ params = request_params(amount, currency, options)
20
+ body = request_body(params)
21
+ HTTParty.post(request_url, headers: request_headers, body: body)
22
+ end
23
+ end
24
+
25
+ def request_url
26
+ "#{base_url}/transactions/securepay"
27
+ end
28
+
29
+ def request_headers
30
+ authorization
31
+ end
32
+
33
+ def request_params(amount, currency, options)
34
+ { amount: amount.to_i,
35
+ currency: currency.to_s,
36
+ vendor: vendor.to_s,
37
+ reference: options[:reference].to_s.slice(0, 30),
38
+ ipn_url: options[:ipn_url].to_s,
39
+ callback_url: options[:callback_url].to_s }
40
+ end
41
+
42
+ def request_body(params = {})
43
+ params.map { |k, v| "#{k}=#{v}" }.join('&')
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,11 @@
1
+ module Nihaopay
2
+ module SecurePay
3
+ class UnionPay < Base
4
+ class << self
5
+ def vendor
6
+ :unionpay
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Nihaopay
2
+ module SecurePay
3
+ class WeChatPay < Base
4
+ class << self
5
+ def vendor
6
+ :wechatpay
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,37 @@
1
+ module Nihaopay
2
+ module Transactions
3
+ class Authorize < Base
4
+ class << self
5
+ def start(amount, credit_card, options = {})
6
+ @token = options.delete(:token)
7
+ params = request_params(amount, credit_card, options)
8
+ body = request_body(params)
9
+ response = HTTParty.post(request_url, headers: request_headers, body: body)
10
+ build_from_response!(response)
11
+ end
12
+
13
+ def request_url
14
+ "#{base_url}/transactions/expresspay"
15
+ end
16
+
17
+ def request_params(amount, credit_card, options)
18
+ params = {}
19
+ params.merge! credit_card.to_params_hash
20
+ params.merge! Nihaopay::HashUtil.slice(options, *valid_options)
21
+ params[:capture] = capture_param
22
+ params[:amount] = amount
23
+ params[:currency] ||= Nihaopay.currency
24
+ params
25
+ end
26
+
27
+ def valid_options
28
+ %i(currency description note reference)
29
+ end
30
+
31
+ def capture_param
32
+ false
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,78 @@
1
+ module Nihaopay
2
+ module Transactions
3
+ class Base
4
+ include ::Nihaopay::Api
5
+ include ::Nihaopay::Queryable
6
+
7
+ attr_accessor :token, :transaction_id, :type, :status
8
+ attr_accessor :captured, :reference, :currency, :amount, :note, :time
9
+
10
+ def initialize(attributes = {})
11
+ assign_attributes(attributes)
12
+ end
13
+
14
+ def capture
15
+ Nihaopay::Transactions::Capture.start(transaction_id, amount, currency, token: token)
16
+ end
17
+
18
+ def partial_capture(capture_amount)
19
+ Nihaopay::Transactions::Capture.start(transaction_id, capture_amount, currency, token: token)
20
+ end
21
+
22
+ def release
23
+ Nihaopay::Transactions::Release.start(transaction_id, token: token)
24
+ end
25
+
26
+ def cancel
27
+ Nihaopay::Transactions::Cancel.start(transaction_id, token: token)
28
+ end
29
+
30
+ def refund(options = {})
31
+ options[:token] = token
32
+ Nihaopay::Transactions::Refund.start(transaction_id, amount, currency, options)
33
+ end
34
+
35
+ def partial_refund(refund_amount, options = {})
36
+ options[:token] = token
37
+ Nihaopay::Transactions::Refund.start(transaction_id, refund_amount, currency, options)
38
+ end
39
+
40
+ class << self
41
+ def request_headers
42
+ authorization.merge('Content-Type' => 'application/x-www-form-urlencoded')
43
+ end
44
+
45
+ def request_body(params = {})
46
+ params.map { |k, v| "#{k}=#{v}" }.join('&')
47
+ end
48
+
49
+ def build_from_response!(response)
50
+ validate_resource!(response)
51
+ build(response.parsed_response)
52
+ end
53
+
54
+ def build(options = {})
55
+ options = Nihaopay::HashUtil.symbolize_keys(options)
56
+ attributes = Nihaopay::HashUtil.slice(options, *valid_attributes)
57
+ attributes[:token] ||= merchant_token
58
+ response_keys_map.each { |k, v| attributes[v] = options[k] }
59
+ new(attributes)
60
+ end
61
+
62
+ def valid_attributes
63
+ %i(token transaction_id type status captured currency reference amount note time)
64
+ end
65
+
66
+ def response_keys_map
67
+ { id: :transaction_id }
68
+ end
69
+ end
70
+
71
+ private
72
+
73
+ def assign_attributes(attributes)
74
+ self.class.valid_attributes.each { |f| send("#{f}=", attributes[f]) }
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,28 @@
1
+ module Nihaopay
2
+ module Transactions
3
+ class Cancel < Base
4
+ attr_accessor :cancelled, :cancel_transaction_id
5
+
6
+ class << self
7
+ def start(transaction_id, options = {})
8
+ @token = options.delete(:token)
9
+ url = request_url(transaction_id)
10
+ response = HTTParty.post(url, headers: request_headers, body: request_body)
11
+ build_from_response!(response)
12
+ end
13
+
14
+ def request_url(transaction_id)
15
+ "#{base_url}/transactions/#{transaction_id}/cancel"
16
+ end
17
+
18
+ def valid_attributes
19
+ %i(transaction_id status cancelled cancel_transaction_id)
20
+ end
21
+
22
+ def response_keys_map
23
+ { id: :transaction_id, transaction_id: :cancel_transaction_id }
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,29 @@
1
+ module Nihaopay
2
+ module Transactions
3
+ class Capture < Base
4
+ attr_accessor :captured, :capture_transaction_id
5
+
6
+ class << self
7
+ def start(transaction_id, amount, currency, options = {})
8
+ @token = options.delete(:token)
9
+ url = request_url(transaction_id)
10
+ params = request_body(amount: amount, currency: currency)
11
+ response = HTTParty.post(url, headers: request_headers, body: params)
12
+ build_from_response!(response)
13
+ end
14
+
15
+ def request_url(transaction_id)
16
+ "#{base_url}/transactions/#{transaction_id}/capture"
17
+ end
18
+
19
+ def valid_attributes
20
+ %i(transaction_id status captured capture_transaction_id)
21
+ end
22
+
23
+ def response_keys_map
24
+ { id: :transaction_id, transaction_id: :capture_transaction_id }
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end