bank_gateway_saman 1.0.3
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/README.md +112 -0
- data/lib/generators/saman/install_generator.rb +16 -0
- data/lib/generators/saman/templates/saman_initializer.rb +27 -0
- data/lib/saman.rb +29 -0
- data/lib/saman/authorize.rb +97 -0
- data/lib/saman/configuration.rb +43 -0
- data/lib/saman/health_check.rb +34 -0
- data/lib/saman/verify.rb +44 -0
- metadata +92 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 9f9d330650a5d8e565bd23bace6fcb4676318999401cf1979c9538f6c7ede722
|
4
|
+
data.tar.gz: 77b6be29455d19fca08b02f9df935b6041b0a859fc316ded723d2af8784d6940
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a545e5e4e84896b6be9a021885b595bdcb39cf285cb3d94a5da35dcb289de09c6f0437c3583412338486c06e19288db687d6e582ef97ddd720d98ef96b629d57
|
7
|
+
data.tar.gz: c369ee1f9ba760b6291c6f0b6af97d1096ebc06b9709718c4db523ecd6cf8798c2af37f6fae3bb1c1e11033da76555d7ebfb10fc6dd54541c1faffd9bec013f5
|
data/README.md
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
# Saman
|
2
|
+
|
3
|
+
[Coverage Report](http://amirhosein.zlf.gitlab.io/bank_gateway_saman/)
|
4
|
+
|
5
|
+
This gem will help you to handle all required requests for using Saman gateway using ruby
|
6
|
+
|
7
|
+
## Install
|
8
|
+
### Using in ruby
|
9
|
+
- Add `saman` gem to your Gemfile
|
10
|
+
|
11
|
+
`gem 'saman'`
|
12
|
+
|
13
|
+
- Run bundle install
|
14
|
+
|
15
|
+
`bundle install`
|
16
|
+
|
17
|
+
### Using in Rails
|
18
|
+
- Add `saman` gem to your Gemfile
|
19
|
+
|
20
|
+
`gem 'saman'`
|
21
|
+
|
22
|
+
- Run bundle install
|
23
|
+
|
24
|
+
`bundle install`
|
25
|
+
|
26
|
+
- Create the initializer for it
|
27
|
+
|
28
|
+
`bundle exec rails g saman:install`
|
29
|
+
|
30
|
+
### How to use it?
|
31
|
+
|
32
|
+
#### Configurations
|
33
|
+
|
34
|
+
For `rails` applications it will generate an `initializer` file called `saman.rb` which you could set all the required configurations.
|
35
|
+
|
36
|
+
If you are using this gem in a `ruby`
|
37
|
+
script, you should set the configurations like below before calling any methods.
|
38
|
+
|
39
|
+
```
|
40
|
+
Saman.configure do |config|
|
41
|
+
# config.username = config_hash[:username]
|
42
|
+
# config.password = config_hash[:password]
|
43
|
+
|
44
|
+
# config.proxy = config_hash[:proxy]
|
45
|
+
# e.g. config.proxy = 'http://localhost:8080/'
|
46
|
+
|
47
|
+
# config.terminal_id_default = config_hash[:terminal_id_default]
|
48
|
+
|
49
|
+
# a terminal id which support multi account
|
50
|
+
# config.terminal_id_with_wage = config_hash[:terminal_id_with_wage]
|
51
|
+
|
52
|
+
# a termianl id which is needed for you wage account
|
53
|
+
# config.terminal_id_wage_only = config_hash[:terminal_id_wage_only]
|
54
|
+
|
55
|
+
# config.retry_count = config_hash[:retry_count]
|
56
|
+
# config.authorize_wsdl = config_hash[:authorize_wsdl]
|
57
|
+
# config.authorize_address = config_hash[:authorize_address]
|
58
|
+
# config.verify_wsdl = config_hash[:verify_wsdl]
|
59
|
+
end
|
60
|
+
|
61
|
+
```
|
62
|
+
|
63
|
+
#### Is gateway ready?
|
64
|
+
You can check if the Saman gateway is ready or not, this method always return a `boolean` value
|
65
|
+
|
66
|
+
`Saman.up?`
|
67
|
+
|
68
|
+
#### How get a token from gateway?
|
69
|
+
The `authorize` method get a token for you from bank and it returns a response like below
|
70
|
+
`Saman.authorize(params)`
|
71
|
+
```
|
72
|
+
{
|
73
|
+
method: 'POST',
|
74
|
+
fields: {
|
75
|
+
Token: 'generated_token'
|
76
|
+
},
|
77
|
+
url: 'http://sample.com/'
|
78
|
+
}
|
79
|
+
```
|
80
|
+
This means you should submit a from by `POST` request to `http://sample.com/` with a field named `Token` and value of `generated_token`
|
81
|
+
|
82
|
+
The required params for generating a token are like below
|
83
|
+
```
|
84
|
+
{
|
85
|
+
"amount": 3000,
|
86
|
+
"order_id": 128,
|
87
|
+
"customer": {
|
88
|
+
"mobile_number": "09128987989"
|
89
|
+
},
|
90
|
+
"split_amount": {
|
91
|
+
"amount": 1500,
|
92
|
+
"wage": 1500
|
93
|
+
},
|
94
|
+
"redirect_url": "http://localhost"
|
95
|
+
}
|
96
|
+
```
|
97
|
+
NOTE: if you do not want to use `split_amount` feature, just pass the `amount` and ignore that.
|
98
|
+
|
99
|
+
|
100
|
+
#### How verify a payment?
|
101
|
+
|
102
|
+
For verifying a payment, you just need to pass the parameters which were sending to you from gateway like below and this method returns a boolean after calling verify.
|
103
|
+
|
104
|
+
`Saman.verify(posted_params)`
|
105
|
+
|
106
|
+
### Development
|
107
|
+
if you want to change the gem, you could easily clone it and do whatever you want
|
108
|
+
|
109
|
+
After your changes always run `specs` and `rubocop` to make sure about the code quality
|
110
|
+
|
111
|
+
- `rspec spec`
|
112
|
+
- `rubocop --format html > rubocop.html`
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails/generators'
|
4
|
+
module Saman
|
5
|
+
module Generators
|
6
|
+
# Install generator class for saman gem using in rails
|
7
|
+
class InstallGenerator < Rails::Generators::Base
|
8
|
+
source_root File.expand_path('../templates', __FILE__)
|
9
|
+
desc 'Creates Saman initializer for your application'
|
10
|
+
|
11
|
+
def copy_initializer
|
12
|
+
template 'saman_initializer.rb', 'config/initializers/saman.rb'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
Saman.configure do |config|
|
4
|
+
# You can read config from a file
|
5
|
+
# config_hash = Rails.application.config_for(:saman)
|
6
|
+
# config.username = config_hash[:username]
|
7
|
+
# config.password = config_hash[:password]
|
8
|
+
|
9
|
+
# config.proxy = config_hash[:proxy]
|
10
|
+
# e.g. config.proxy = 'http://localhost:8080/'
|
11
|
+
|
12
|
+
# config.terminal_id_default = config_hash[:terminal_id_default]
|
13
|
+
|
14
|
+
# a terminal id which support multi account
|
15
|
+
# config.terminal_id_with_wage = config_hash[:terminal_id_with_wage]
|
16
|
+
|
17
|
+
# a termianl id which is needed for you wage account
|
18
|
+
# config.terminal_id_wage_only = config_hash[:terminal_id_wage_only]
|
19
|
+
|
20
|
+
# config.retry_count = config_hash[:retry_count]
|
21
|
+
# config.authorize_wsdl = config_hash[:authorize_wsdl]
|
22
|
+
# config.authorize_address = config_hash[:authorize_address]
|
23
|
+
# config.verify_wsdl = config_hash[:verify_wsdl]
|
24
|
+
|
25
|
+
# or you can set all the configs from environment variables
|
26
|
+
# like ENV['saman_username']
|
27
|
+
end
|
data/lib/saman.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'saman/authorize'
|
4
|
+
require_relative 'saman/verify'
|
5
|
+
require_relative 'saman/health_check'
|
6
|
+
require_relative 'saman/configuration'
|
7
|
+
require_relative 'generators/saman/install_generator'
|
8
|
+
|
9
|
+
require 'savon'
|
10
|
+
require 'yaml'
|
11
|
+
require 'rest-client'
|
12
|
+
require 'json'
|
13
|
+
|
14
|
+
# Saman gateway module to handle requests
|
15
|
+
module Saman
|
16
|
+
attr_accessor :config
|
17
|
+
|
18
|
+
def self.authorize(params)
|
19
|
+
Saman::Client.new.authorize(params)
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.verify(params)
|
23
|
+
Saman::Client.new.verify(params)
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.up?
|
27
|
+
Saman::Client.new.health_check
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Saman module for gateway communications
|
4
|
+
module Saman
|
5
|
+
# extend Client class to handle authorize method
|
6
|
+
class Client
|
7
|
+
def authorize(params)
|
8
|
+
config = Saman.configuration
|
9
|
+
request_parameters = create_authorize_parameters(params)
|
10
|
+
response = send_rest_requests(
|
11
|
+
config.authorize_address,
|
12
|
+
request_parameters,
|
13
|
+
config.retry_count
|
14
|
+
)
|
15
|
+
raise response[:error] unless response.is_a? RestClient::Response
|
16
|
+
authorize_result(response)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def authorize_result(response)
|
22
|
+
token = parse_authorize_result(response)
|
23
|
+
{
|
24
|
+
method: 'POST',
|
25
|
+
fields: {
|
26
|
+
Token: token
|
27
|
+
},
|
28
|
+
url: Saman.configuration.authorize_address
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
def create_authorize_parameters(params)
|
33
|
+
{
|
34
|
+
Action: 'Token',
|
35
|
+
Amount: calculate_the_amount(params),
|
36
|
+
Wage: calculate_the_wage(params),
|
37
|
+
TerminalId: get_terminal_id(params),
|
38
|
+
ResNum: params[:order_id],
|
39
|
+
RedirectUrl: params[:redirect_url],
|
40
|
+
CellNumber: params[:customer][:mobile_number]
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
44
|
+
def get_terminal_id(params)
|
45
|
+
case params[:split_amount]&.count
|
46
|
+
when nil
|
47
|
+
Saman.configuration.terminal_id_default
|
48
|
+
when 1
|
49
|
+
return Saman.configuration.terminal_id_wage_only if \
|
50
|
+
params[:split_amount].key?(:wage)
|
51
|
+
Saman.configuration.terminal_id_default
|
52
|
+
else
|
53
|
+
Saman.configuration.terminal_id_with_wage
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def calculate_the_wage(params)
|
58
|
+
return 0 unless multiple_accounts?(params)
|
59
|
+
return 0 if params[:split_amount].count == 1
|
60
|
+
|
61
|
+
params[:split_amount][:wage] || 0
|
62
|
+
end
|
63
|
+
|
64
|
+
def calculate_the_amount(params)
|
65
|
+
return params[:amount] unless multiple_accounts?(params)
|
66
|
+
return params[:amount] if params[:split_amount].count == 1
|
67
|
+
|
68
|
+
params[:split_amount][:amount] || 0
|
69
|
+
end
|
70
|
+
|
71
|
+
def multiple_accounts?(params)
|
72
|
+
params[:split_amount]&.count&.positive?
|
73
|
+
end
|
74
|
+
|
75
|
+
def parse_authorize_result(response)
|
76
|
+
token_result = JSON.parse(response.body)
|
77
|
+
token = token_result['token'] if token_result['status'].to_i == 1
|
78
|
+
raise "Code ##{token_result['errorCode']}, #{token_result['errorDesc']}" \
|
79
|
+
if token.nil?
|
80
|
+
|
81
|
+
token
|
82
|
+
end
|
83
|
+
|
84
|
+
def send_rest_requests(url, parameters, retry_to)
|
85
|
+
RestClient.proxy = Saman.configuration.proxy unless \
|
86
|
+
Saman.configuration.proxy.blank?
|
87
|
+
return RestClient.post(url, parameters.to_json, content_type: :json)
|
88
|
+
rescue RestClient::Exceptions::OpenTimeout => exception
|
89
|
+
retry if (retry_to -= 1).positive?
|
90
|
+
return { error: 'Saman is not available right now,
|
91
|
+
calling web service got time out' }
|
92
|
+
rescue StandardError => exception
|
93
|
+
retry if (retry_to -= 1).positive?
|
94
|
+
return { error: exception.message }
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Saman module for gateway communications
|
4
|
+
module Saman
|
5
|
+
class << self
|
6
|
+
attr_accessor :configuration
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.configure
|
10
|
+
self.configuration ||= Configuration.new
|
11
|
+
yield(configuration)
|
12
|
+
end
|
13
|
+
|
14
|
+
# configure class
|
15
|
+
class Configuration
|
16
|
+
attr_accessor :username
|
17
|
+
attr_accessor :password
|
18
|
+
attr_accessor :proxy
|
19
|
+
attr_accessor :terminal_id_default
|
20
|
+
attr_accessor :terminal_id_with_wage
|
21
|
+
attr_accessor :terminal_id_wage_only
|
22
|
+
attr_writer :retry_count
|
23
|
+
attr_writer :authorize_wsdl
|
24
|
+
attr_writer :authorize_address
|
25
|
+
attr_writer :verify_wsdl
|
26
|
+
|
27
|
+
def authorize_address
|
28
|
+
@authorize_address || 'https://sep.shaparak.ir/MobilePG/MobilePayment'
|
29
|
+
end
|
30
|
+
|
31
|
+
def verify_wsdl
|
32
|
+
@verify_wsdl || 'https://verify.sep.ir/payments/referencepayment.asmx?wsdl'
|
33
|
+
end
|
34
|
+
|
35
|
+
def authorize_wsdl
|
36
|
+
@authorize_wsdl || 'https://sep.shaparak.ir/payments/initpayment.asmx?wsdl'
|
37
|
+
end
|
38
|
+
|
39
|
+
def retry_count
|
40
|
+
@retry_count || 3
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Saman
|
4
|
+
# Client class to handle requests
|
5
|
+
class Client
|
6
|
+
def health_check
|
7
|
+
authorize_up? && verify_up?
|
8
|
+
end
|
9
|
+
|
10
|
+
def verify_up?
|
11
|
+
verify_client = Savon.client(wsdl: Saman.configuration.verify_wsdl)
|
12
|
+
expected_operations_for_verify = %i[
|
13
|
+
verify_transaction
|
14
|
+
verify_transaction1
|
15
|
+
]
|
16
|
+
|
17
|
+
(expected_operations_for_verify - verify_client.operations).empty?
|
18
|
+
rescue StandardError
|
19
|
+
return false
|
20
|
+
end
|
21
|
+
|
22
|
+
def authorize_up?
|
23
|
+
authorize_client = Savon.client(wsdl: Saman.configuration.authorize_wsdl)
|
24
|
+
expected_operations_for_authorize = %i[
|
25
|
+
request_token
|
26
|
+
request_multi_settle_type_token
|
27
|
+
]
|
28
|
+
|
29
|
+
(expected_operations_for_authorize - authorize_client.operations).empty?
|
30
|
+
rescue StandardError
|
31
|
+
return false
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/saman/verify.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Saman module for gateway communications
|
4
|
+
module Saman
|
5
|
+
# extend Client class to handle verify method
|
6
|
+
class Client
|
7
|
+
def verify(params)
|
8
|
+
return false unless params[:State] == 'OK'
|
9
|
+
verify_the_payment(params)
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def verify_the_payment(params)
|
15
|
+
savon_client = create_savon_client_for_verify
|
16
|
+
request_parameters = {
|
17
|
+
String_1: params[:RefNum],
|
18
|
+
String_2: params[:TerminalId]
|
19
|
+
}
|
20
|
+
response = send_verify_request(savon_client, request_parameters)
|
21
|
+
raise response[:error] if response.to_hash.include? :error
|
22
|
+
last_response = response.body[:verify_transaction_response][:result].to_i
|
23
|
+
last_response.positive?
|
24
|
+
end
|
25
|
+
|
26
|
+
def create_savon_client_for_verify
|
27
|
+
config = Saman.configuration
|
28
|
+
options = {
|
29
|
+
wsdl: config.verify_wsdl,
|
30
|
+
convert_request_keys_to: :none
|
31
|
+
}
|
32
|
+
options['proxy'] = config.proxy unless config.proxy.blank?
|
33
|
+
|
34
|
+
Savon.client(options)
|
35
|
+
end
|
36
|
+
|
37
|
+
def send_verify_request(client, parameters, retry_to = 3)
|
38
|
+
client.call(:verify_transaction, message: parameters)
|
39
|
+
rescue StandardError => exception
|
40
|
+
retry if (retry_to -= 1).positive?
|
41
|
+
return { error: exception.message }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
metadata
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bank_gateway_saman
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Amirhosein Zolfaghari
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2010-06-06 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rest-client
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 2.0.2
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 2.0.2
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 2.0.2
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 2.0.2
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: savon
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: 2.12.0
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 2.12.0
|
43
|
+
type: :runtime
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - "~>"
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: 2.12.0
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 2.12.0
|
53
|
+
description: Help you to handle all requests to saman payment gateway
|
54
|
+
email: amirhosein@zolfaghari.me
|
55
|
+
executables: []
|
56
|
+
extensions: []
|
57
|
+
extra_rdoc_files:
|
58
|
+
- README.md
|
59
|
+
files:
|
60
|
+
- README.md
|
61
|
+
- lib/generators/saman/install_generator.rb
|
62
|
+
- lib/generators/saman/templates/saman_initializer.rb
|
63
|
+
- lib/saman.rb
|
64
|
+
- lib/saman/authorize.rb
|
65
|
+
- lib/saman/configuration.rb
|
66
|
+
- lib/saman/health_check.rb
|
67
|
+
- lib/saman/verify.rb
|
68
|
+
homepage: https://gitlab.com/amirhosein.zlf/bank_gateway_saman
|
69
|
+
licenses:
|
70
|
+
- MIT
|
71
|
+
metadata: {}
|
72
|
+
post_install_message:
|
73
|
+
rdoc_options: []
|
74
|
+
require_paths:
|
75
|
+
- lib
|
76
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - "~>"
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '2.4'
|
81
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
requirements: []
|
87
|
+
rubyforge_project:
|
88
|
+
rubygems_version: 2.7.3
|
89
|
+
signing_key:
|
90
|
+
specification_version: 4
|
91
|
+
summary: Help you to communicate better with saman payment gateway
|
92
|
+
test_files: []
|