nihaopay-ruby 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +5 -0
- data/LICENSE +22 -0
- data/README.md +344 -0
- data/lib/nihaopay-ruby.rb +29 -0
- data/lib/nihaopay/configure.rb +14 -0
- data/lib/nihaopay/credit_card.rb +27 -0
- data/lib/nihaopay/errors.rb +6 -0
- data/lib/nihaopay/merchant.rb +47 -0
- data/lib/nihaopay/mixins/api.rb +41 -0
- data/lib/nihaopay/mixins/queryable.rb +41 -0
- data/lib/nihaopay/query.rb +61 -0
- data/lib/nihaopay/secure_pay/ali_pay.rb +11 -0
- data/lib/nihaopay/secure_pay/base.rb +48 -0
- data/lib/nihaopay/secure_pay/union_pay.rb +11 -0
- data/lib/nihaopay/secure_pay/we_chat_pay.rb +11 -0
- data/lib/nihaopay/transactions/authorize.rb +37 -0
- data/lib/nihaopay/transactions/base.rb +78 -0
- data/lib/nihaopay/transactions/cancel.rb +28 -0
- data/lib/nihaopay/transactions/capture.rb +29 -0
- data/lib/nihaopay/transactions/purchase.rb +11 -0
- data/lib/nihaopay/transactions/refund.rb +31 -0
- data/lib/nihaopay/transactions/release.rb +28 -0
- data/lib/nihaopay/util/hash_util.rb +30 -0
- data/lib/nihaopay/version.rb +3 -0
- data/spec/credit_card_spec.rb +56 -0
- data/spec/merchant_spec.rb +142 -0
- data/spec/mixins/api_spec.rb +81 -0
- data/spec/mixins/queryable_spec.rb +95 -0
- data/spec/query_spec.rb +129 -0
- data/spec/secure_pay/ali_pay_spec.rb +112 -0
- data/spec/secure_pay/union_pay_spec.rb +13 -0
- data/spec/secure_pay/we_chat_pay_spec.rb +13 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/transactions/authorize_spec.rb +115 -0
- data/spec/transactions/base_spec.rb +184 -0
- data/spec/transactions/cancel_spec.rb +83 -0
- data/spec/transactions/capture_spec.rb +85 -0
- data/spec/transactions/purchase_spec.rb +7 -0
- data/spec/transactions/refund_spec.rb +98 -0
- data/spec/transactions/release_spec.rb +83 -0
- data/spec/util/hash_util_spec.rb +22 -0
- metadata +187 -0
@@ -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,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,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
|