zipMoney 1.0.1
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 +7 -0
- data/.gitignore +9 -0
- data/.travis.yml +4 -0
- data/CODE_OF_CONDUCT.md +13 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +287 -0
- data/Rakefile +13 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/lib/zipMoney.rb +54 -0
- data/lib/zipMoney/api.rb +192 -0
- data/lib/zipMoney/api/cancel.rb +44 -0
- data/lib/zipMoney/api/capture.rb +44 -0
- data/lib/zipMoney/api/checkout.rb +52 -0
- data/lib/zipMoney/api/configure.rb +34 -0
- data/lib/zipMoney/api/query.rb +43 -0
- data/lib/zipMoney/api/quote.rb +54 -0
- data/lib/zipMoney/api/refund.rb +46 -0
- data/lib/zipMoney/api/settings.rb +16 -0
- data/lib/zipMoney/configuration.rb +49 -0
- data/lib/zipMoney/errors.rb +11 -0
- data/lib/zipMoney/express.rb +65 -0
- data/lib/zipMoney/request.rb +22 -0
- data/lib/zipMoney/resources.rb +71 -0
- data/lib/zipMoney/response.rb +68 -0
- data/lib/zipMoney/util.rb +53 -0
- data/lib/zipMoney/version.rb +3 -0
- data/lib/zipMoney/webhook.rb +67 -0
- data/zipMoney.gemspec +37 -0
- metadata +145 -0
@@ -0,0 +1,46 @@
|
|
1
|
+
module ZipMoney
|
2
|
+
class Refund
|
3
|
+
include Request
|
4
|
+
|
5
|
+
attr_accessor :params
|
6
|
+
|
7
|
+
Struct.new("RefundParams", :reason, :refund_amount, :txn_id, :order_id, :quote_id, :order, :reference, :version, :metadata, :merchant_id, :merchant_key)
|
8
|
+
|
9
|
+
# Initializes a ZipMoney::Refund object
|
10
|
+
#
|
11
|
+
# Returns ZipMoney::Refund object
|
12
|
+
def initialize
|
13
|
+
@params = Struct::RefundParams.new
|
14
|
+
@params.order = Struct::Order.new
|
15
|
+
@params.metadata = Struct::Metadata.new
|
16
|
+
@params.version = Struct::Version.new
|
17
|
+
@params.order.detail = Array.new
|
18
|
+
end
|
19
|
+
|
20
|
+
# Performs the Refund api call on zipMoney endpoint
|
21
|
+
#
|
22
|
+
# Returns ZipMoney::Refund object
|
23
|
+
def do
|
24
|
+
validate
|
25
|
+
ZipMoney.api.refund(@params)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Performs the parameters validation
|
29
|
+
def validate
|
30
|
+
raise ArgumentError, "Params emtpy" if @params.nil?
|
31
|
+
@errors = []
|
32
|
+
@errors << 'reason must be provided' if @params.reason.nil?
|
33
|
+
@errors << 'refund_amount must be provided' if @params.refund_amount.nil?
|
34
|
+
@errors << 'txn_id must be provided' if @params.txn_id.nil?
|
35
|
+
@errors << 'order.id must be provided' if @params.order.id.nil?
|
36
|
+
@errors << 'order.total must be provided' if @params.order.total.nil?
|
37
|
+
@errors << 'order.shipping_value must be provided' if @params.order.shipping_value.nil?
|
38
|
+
@errors << 'order.tax must be provided' if @params.order.tax.nil?
|
39
|
+
@errors << 'order detail must be provided' if @params.order.detail.nil?
|
40
|
+
|
41
|
+
validate_item_details @params.order.detail
|
42
|
+
|
43
|
+
raise ZipMoney::RequestError.new("Following error(s) occurred while making request, please resolve them to make the request: #{@errors}") if @errors.any?
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module ZipMoney
|
2
|
+
class Settings
|
3
|
+
include Request
|
4
|
+
|
5
|
+
attr_accessor :params
|
6
|
+
|
7
|
+
Struct.new("SettingsParams", :merchant_id, :merchant_key, :version, :metadata)
|
8
|
+
|
9
|
+
# Performs the Checkout api call on zipMoney endpoint
|
10
|
+
#
|
11
|
+
# Returns ZipMoney::Checkout object
|
12
|
+
def do
|
13
|
+
ZipMoney.api.settings()
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module ZipMoney
|
2
|
+
class Configuration
|
3
|
+
|
4
|
+
API_VERSION = "1.0.1"
|
5
|
+
API_PLATFORM = "ruby"
|
6
|
+
API_NAME = "zipMoney Ruby SDK"
|
7
|
+
|
8
|
+
ENV_LIVE_API_URL = "https://api.zipmoney.com.au/v1/"
|
9
|
+
ENV_TEST_API_URL = "https://api.sandbox.zipmoney.com.au/v1/"
|
10
|
+
|
11
|
+
ATTRIBUTES = [
|
12
|
+
:merchant_id,
|
13
|
+
:merchant_key,
|
14
|
+
:environment,
|
15
|
+
]
|
16
|
+
|
17
|
+
attr_accessor *ATTRIBUTES
|
18
|
+
|
19
|
+
class << self
|
20
|
+
attr_accessor *ATTRIBUTES
|
21
|
+
|
22
|
+
# Checks if passed value is valid and assigns it true
|
23
|
+
#
|
24
|
+
# @param [env] Environment sandbox|live
|
25
|
+
#
|
26
|
+
# @return true|false
|
27
|
+
def environment=(env)
|
28
|
+
env = env.to_sym
|
29
|
+
raise ArgumentError, "#{env.inspect} is not a valid environment" unless [:sandbox, :live].include?(env)
|
30
|
+
@environment = env
|
31
|
+
end
|
32
|
+
|
33
|
+
# Checks if environment is sandbox
|
34
|
+
#
|
35
|
+
# @return true|false
|
36
|
+
def is_sandbox
|
37
|
+
environment.to_s == "sandbox"
|
38
|
+
end
|
39
|
+
|
40
|
+
# Checks if passed merchant_id and merchant_key match with the one provided during setup
|
41
|
+
#
|
42
|
+
# @param [merchant_id] Merchant Id
|
43
|
+
# @param [merchant_key] Merchant Key
|
44
|
+
def credentials_valid(merchant_id,merchant_key)
|
45
|
+
raise ExpressError, "Invalid merchant credentials in the request" unless @merchant_id.to_i.eql?(merchant_id.to_i) && @merchant_key.to_s.eql?(merchant_key.to_s)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module ZipMoney
|
2
|
+
class ApiError < StandardError; end
|
3
|
+
class InvalidArgumentError < StandardError; end
|
4
|
+
class RequestError < StandardError; end
|
5
|
+
class ResponseError < StandardError; end
|
6
|
+
class WebHookError < StandardError; end
|
7
|
+
class WebHookRequestError < StandardError; end
|
8
|
+
class ExpressError < StandardError; end
|
9
|
+
class ExpressRequestError < StandardError; end
|
10
|
+
class ExpressResponseError < StandardError; end
|
11
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module ZipMoney
|
2
|
+
module Express
|
3
|
+
attr_accessor :merchant_id, :merchant_key
|
4
|
+
|
5
|
+
ACTION_GET_QUOTE_DETAILS = 'quotedetails';
|
6
|
+
ACTION_GET_SHIPPING_METHODS = 'shippingmethods';
|
7
|
+
ACTION_CONFIRM_SHIPPING_METHOD = 'confirmshippingmethod';
|
8
|
+
ACTION_CONFIRM_ORDER = 'confirmorder';
|
9
|
+
ACTION_FINALISE_ORDER = 'finaliseorder';
|
10
|
+
ACTION_CANCEL_QUOTE = 'cancelquote';
|
11
|
+
|
12
|
+
# Process the express checkout action
|
13
|
+
#
|
14
|
+
# @param [action] Action
|
15
|
+
# @param [request] Express checkout request
|
16
|
+
# @param [block] Actions to be taken for respective actions
|
17
|
+
#
|
18
|
+
# Returns the response to the zipMoney Express Api
|
19
|
+
def self.process(action, request, &block)
|
20
|
+
raise ExpressRequestError, "Action empty" if action.nil?
|
21
|
+
raise ExpressRequestError, "Request empty" if request.nil?
|
22
|
+
request = Util.json_parse(request)
|
23
|
+
Configuration.credentials_valid(request["merchant_id"], request["merchant_key"])
|
24
|
+
if (block.arity > 0)
|
25
|
+
response = block.call(action, request)
|
26
|
+
raise ExpressResponseError, "No response provided" if response.nil?
|
27
|
+
puts send_response(response)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Appends api credentials to the express checkout response
|
32
|
+
#
|
33
|
+
# @param [response] response
|
34
|
+
def self.append_api_credentials(response)
|
35
|
+
response = Hash.new if !response.is_a?(Hash)
|
36
|
+
|
37
|
+
if response["merchant_id"] == nil
|
38
|
+
response["merchant_id"] = Configuration.merchant_id
|
39
|
+
end
|
40
|
+
|
41
|
+
if response["merchant_key"] == nil
|
42
|
+
response["merchant_key"] = Configuration.merchant_key
|
43
|
+
end
|
44
|
+
response
|
45
|
+
end
|
46
|
+
|
47
|
+
# Prepars the express checkout response
|
48
|
+
#
|
49
|
+
# @param [response] response
|
50
|
+
def self.prepare_response(response)
|
51
|
+
response = Util.json_parse(response)
|
52
|
+
append_api_credentials(response)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Prints the express checkout response
|
56
|
+
#
|
57
|
+
# @param [response] response
|
58
|
+
def self.send_response(response)
|
59
|
+
prepare_response(response).to_json
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module ZipMoney
|
2
|
+
module Request
|
3
|
+
Struct.new("Order", :id, :tax, :shipping_value, :total, :detail)
|
4
|
+
Struct.new("Detail", :quantity, :name, :price, :description, :sku, :id, :category, :image_url)
|
5
|
+
Struct.new("Address",:first_name, :last_name, :line1, :line2, :country, :zip, :city, :state)
|
6
|
+
Struct.new("Consumer",:first_name, :last_name,:city, :phone, :gender, :dob, :email, :title)
|
7
|
+
Struct.new("Metadata",:order_reference, :attributes)
|
8
|
+
Struct.new("Version",:client, :platform)
|
9
|
+
Struct.new("ApiCredentials",:merchant_id, :merchant_key, :version)
|
10
|
+
|
11
|
+
attr_accessor :errors
|
12
|
+
|
13
|
+
def validate_item_details(order_items)
|
14
|
+
order_items.each_with_index do |item,index|
|
15
|
+
@errors << "order.detail[#{index}].id must be provided" if item.id.nil?
|
16
|
+
@errors << "order.detail[#{index}].name must be provided" if item.name.nil?
|
17
|
+
@errors << "order.detail[#{index}].quantity must be provided" if item.quantity.nil?
|
18
|
+
@errors << "order.detail[#{index}].price must be provided" if item.price.nil?
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module ZipMoney
|
2
|
+
class Resources
|
3
|
+
|
4
|
+
RESOURCE_SETTINGS = 'settings'
|
5
|
+
RESOURCE_CONFIGURE = 'configure'
|
6
|
+
RESOURCE_QUOTE = 'quote'
|
7
|
+
RESOURCE_CANCEL = 'cancel'
|
8
|
+
RESOURCE_REFUND = 'refund'
|
9
|
+
RESOURCE_CHECKOUT = 'checkout'
|
10
|
+
RESOURCE_QUERY = 'query'
|
11
|
+
RESOURCE_CAPTURE = 'capture'
|
12
|
+
RESOURCE_HEART_BEAT = 'Heartbeat'
|
13
|
+
|
14
|
+
class << self
|
15
|
+
# Checks if passed resource is valid and returns RestClient::Resource object
|
16
|
+
# configured with the passed resource and url
|
17
|
+
#
|
18
|
+
# @param [resource] endpoint resource
|
19
|
+
# @param [method] method get|post
|
20
|
+
# @param [query_string] query_string parameters
|
21
|
+
#
|
22
|
+
# @return RestClient::Resource object
|
23
|
+
def get(resource, method = :post, query_string = nil)
|
24
|
+
return false unless resource_exists(resource)
|
25
|
+
url = get_url(resource, (method == :get ? query_string : nil))
|
26
|
+
ssl_opts = {:verify_ssl => OpenSSL::SSL::VERIFY_PEER}
|
27
|
+
opts = {}
|
28
|
+
RestClient::Resource.new(url, opts.merge(ssl_opts))
|
29
|
+
end
|
30
|
+
|
31
|
+
# Checks if passed resource exists
|
32
|
+
#
|
33
|
+
# @param [resource] endpoint resource
|
34
|
+
#
|
35
|
+
# @return ZipMoney::Response object
|
36
|
+
def resource_exists(resource)
|
37
|
+
if resource.is_a?(String)
|
38
|
+
if self.constants.map{ |k| self.const_get(k).downcase }.include?resource
|
39
|
+
resource
|
40
|
+
end
|
41
|
+
else
|
42
|
+
raise ArgumentError, "#{resource} should be a string"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Builds the proper endpoint url with the given resource
|
47
|
+
#
|
48
|
+
# @param [resource] endpoint resource
|
49
|
+
# @param [query_string] query_string parameters
|
50
|
+
#
|
51
|
+
# @return String
|
52
|
+
def get_url(resource, query_string = nil)
|
53
|
+
if Configuration.is_sandbox
|
54
|
+
url = "#{Configuration::ENV_TEST_API_URL}"
|
55
|
+
else
|
56
|
+
url = "#{Configuration::ENV_LIVE_API_URL}"
|
57
|
+
end
|
58
|
+
|
59
|
+
url = url + resource
|
60
|
+
|
61
|
+
unless query_string.nil?
|
62
|
+
url = url + "?" +
|
63
|
+
query_string.map do |key, value|
|
64
|
+
"#{key}=#{value}"
|
65
|
+
end.join("&")
|
66
|
+
end
|
67
|
+
url
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module ZipMoney
|
2
|
+
class Response
|
3
|
+
|
4
|
+
attr_accessor :_response , :_responseBody, :_responseHeader, :_statusCode
|
5
|
+
|
6
|
+
# Initializes a new api response object
|
7
|
+
#
|
8
|
+
# @param [response] response
|
9
|
+
#
|
10
|
+
# @return ZipMoney::Response object
|
11
|
+
def initialize(response)
|
12
|
+
raise ArgumentError, "Response doesnot exist" if ((response.nil? || response.empty?) && response.code.nil? && response.code.empty?)
|
13
|
+
@_response = response
|
14
|
+
@_statusCode = response.code
|
15
|
+
@_responseBody = response.body
|
16
|
+
end
|
17
|
+
|
18
|
+
# Converts the response body to Hash
|
19
|
+
#
|
20
|
+
# @return Hash
|
21
|
+
def toHash
|
22
|
+
raise ResponseError, "Response body doesnot exist" if @_responseBody.nil? || @_responseBody.empty?
|
23
|
+
JSON.parse(@_responseBody)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Converts the response body to Object
|
27
|
+
#
|
28
|
+
# @return OpenStruct
|
29
|
+
def toObject
|
30
|
+
raise ResponseError, "Response body doesnot exist" if @_responseBody.nil? || @_responseBody.empty?
|
31
|
+
responseObject = JSON.parse(@_responseBody, object_class: OpenStruct)
|
32
|
+
responseObject
|
33
|
+
end
|
34
|
+
|
35
|
+
# Returns the redirect_url from the checkout and quote calls
|
36
|
+
#
|
37
|
+
# @return String
|
38
|
+
def getRedirectUrl
|
39
|
+
raise ArgumentError, "Response body doesnot exist" if @_responseBody.nil? || @_responseBody.empty?
|
40
|
+
resObj = toObject
|
41
|
+
return false if resObj.redirect_url.nil? || resObj.redirect_url.empty?
|
42
|
+
resObj.redirect_url
|
43
|
+
end
|
44
|
+
|
45
|
+
# Returns the http status code
|
46
|
+
#
|
47
|
+
# @return Int
|
48
|
+
def getStatusCode
|
49
|
+
@_statusCode
|
50
|
+
end
|
51
|
+
|
52
|
+
# Returns if the api call was a success or failure
|
53
|
+
#
|
54
|
+
# @return true|false
|
55
|
+
def isSuccess
|
56
|
+
return @_statusCode == 200 || @_statusCode == 201? true : false
|
57
|
+
end
|
58
|
+
|
59
|
+
# Returns error string
|
60
|
+
#
|
61
|
+
# @return String
|
62
|
+
def getError
|
63
|
+
raise ArgumentError, "Response body doesnot exist" if @_responseBody.nil? || @_responseBody.empty?
|
64
|
+
resObj = toObject
|
65
|
+
resObj.Message
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module ZipMoney
|
2
|
+
class Util
|
3
|
+
class << self
|
4
|
+
|
5
|
+
# Converts Struct objects to Hash
|
6
|
+
#
|
7
|
+
# @param [object] Struct Object
|
8
|
+
#
|
9
|
+
# @return Hash
|
10
|
+
def struct_to_hash(object)
|
11
|
+
hash = {}
|
12
|
+
object.to_h.each do |k,v|
|
13
|
+
if v.is_a?(Struct)
|
14
|
+
v = struct_to_hash(v)
|
15
|
+
hash[k] = v unless v.empty?
|
16
|
+
elsif v.is_a?(Array)
|
17
|
+
|
18
|
+
a = Array.new
|
19
|
+
v.each_with_index do |k1,v1|
|
20
|
+
v2 = struct_to_hash(k1)
|
21
|
+
a[v1] = v2 unless v2.empty?
|
22
|
+
end
|
23
|
+
|
24
|
+
hash[k] = a
|
25
|
+
else
|
26
|
+
hash[k] = v unless v.nil?
|
27
|
+
end
|
28
|
+
end
|
29
|
+
hash
|
30
|
+
end
|
31
|
+
|
32
|
+
# Converts Hash|Struct|OpenStruct objects to Hash
|
33
|
+
#
|
34
|
+
# @param [data] Json String
|
35
|
+
#
|
36
|
+
# @return data
|
37
|
+
def json_parse(data)
|
38
|
+
begin
|
39
|
+
data = JSON.parse(data)
|
40
|
+
rescue TypeError => e
|
41
|
+
if !data.is_a?(Hash) && !data.is_a?(Struct) && !data.is_a?(OpenStruct)
|
42
|
+
raise ArgumentError, "Invalid params provided"
|
43
|
+
end
|
44
|
+
rescue JSON::ParserError => e
|
45
|
+
if !data.is_a?(Hash) && !data.is_a?(Struct) && !data.is_a?(OpenStruct)
|
46
|
+
raise ArgumentError, "Invalid params provided"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
data
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module ZipMoney
|
2
|
+
module WebHook
|
3
|
+
attr_accessor :merchant_id, :merchant_key
|
4
|
+
|
5
|
+
EVENT_AUTH_SUCCESS = "authorise_succeeded"
|
6
|
+
EVENT_AUTH_FAIL = "authorise_failed"
|
7
|
+
EVENT_AUTH_REVIEW = "authorise_under_review"
|
8
|
+
EVENT_AUTH_DECLINED = "authorise_declined"
|
9
|
+
EVENT_CANCEL_SUCCESS = "cancel_succeeded"
|
10
|
+
EVENT_CANCEL_FAIL = "cancel_failed"
|
11
|
+
EVENT_CAPTURE_SUCCESS = "capture_succeeded"
|
12
|
+
EVENT_CAPTURE_FAIL = "capture_failed"
|
13
|
+
EVENT_REFUND_SUCCESS = "refund_succeeded"
|
14
|
+
EVENT_REFUND_FAIL = "refund_failed"
|
15
|
+
EVENT_ORDER_CANCELLED = "order_cancelled"
|
16
|
+
EVENT_CHARGE_SUCCESS = "charge_succeeded"
|
17
|
+
EVENT_CHARGE_FAIL = "charge_failed"
|
18
|
+
EVENT_CONFIG_UPDATE = "configuration_updated"
|
19
|
+
|
20
|
+
TYPE_SUBSCRIPTION_CONFIRMATION = "SubscriptionConfirmation"
|
21
|
+
TYPE_NOTIFICATION = "Notification"
|
22
|
+
|
23
|
+
# Process the webhook
|
24
|
+
#
|
25
|
+
# @param [request] WebHook's request
|
26
|
+
# @param [block] Actions to be taken for respective notifications
|
27
|
+
def self.process(request,&block)
|
28
|
+
raise WebHookRequestError, "Payload emtpy" if request.nil?
|
29
|
+
request = Util.json_parse(request)
|
30
|
+
if request["Type"] == TYPE_SUBSCRIPTION_CONFIRMATION
|
31
|
+
subscribe(request["SubscribeURL"])
|
32
|
+
elsif request["Type"] == TYPE_NOTIFICATION
|
33
|
+
process_notifications(request, &block)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Process the webhook notifications
|
38
|
+
#
|
39
|
+
# @param [request] WebHook's request
|
40
|
+
# @param [block] Actions to be taken for respective notifications
|
41
|
+
def self.process_notifications(request, &block)
|
42
|
+
raise ArgumentError, "Invalid params provided" if request["Message"].nil?
|
43
|
+
message = Util.json_parse(request["Message"])
|
44
|
+
Configuration.credentials_valid(message["response"]["merchant_id"], message["response"]["merchant_key"])
|
45
|
+
raise ArgumentError, "Response empty" if message["response"].nil?
|
46
|
+
|
47
|
+
if (block.arity > 0)
|
48
|
+
block.call(message['type'], message["response"])
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# Subscribes for the webhook notifications by calling the subscription url
|
53
|
+
#
|
54
|
+
# @param [request] WebHook's request
|
55
|
+
# @param [block] Actions to be taken for respective notifications
|
56
|
+
def self.subscribe(url)
|
57
|
+
raise WebHookError, "Url emtpy" if url.nil?
|
58
|
+
|
59
|
+
begin
|
60
|
+
response = RestClient.get(url)
|
61
|
+
rescue
|
62
|
+
raise WebHookError, "Unable to reach the subscription url #{url}" if response.nil?
|
63
|
+
end
|
64
|
+
response.code == 200 || response.code == 201
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|