Class: Puerta::Nl::Checkout

Inherits:
Object
  • Object
show all
Defined in:
lib/puerta/nl/checkout.rb

Constant Summary collapse

VERSION =
'3.1'
TYPES =
[ 'ATM_ONLINE', 'IB_ONLINE', 'VISA', 'ATM_OFFLINE', 'NH_OFFLINE', 'NL', 'CREDIT_CARD_PREPAID', ]
BANK_CODES =
{
  BIDV: { title: "Ngân hàng TMCP Đầu tư & Phát triển Việt Nam", type: ['ATM_ONLINE', 'IB_ONLINE', 'ATM_OFFLINE', 'NH_OFFLINE'] },
  VCB: { title: "Ngân hàng TMCP Ngoại Thương Việt Nam", type: ['ATM_ONLINE', 'IB_ONLINE', 'ATM_OFFLINE', 'NH_OFFLINE'] },
  DAB: { title: "Ngân hàng Đông Á", type: ['ATM_ONLINE', 'IB_ONLINE', 'ATM_OFFLINE', 'NH_OFFLINE'] },
  TCB: { title: "Ngân hàng Kỹ Thương", type: ['ATM_ONLINE', 'IB_ONLINE', 'ATM_OFFLINE', 'NH_OFFLINE'] },
  MB: { title: "Ngân hàng Quân Đội", type: ['ATM_ONLINE', 'ATM_OFFLINE', 'NH_OFFLINE'] },
  VIB: { title: "Ngân hàng Quốc tế", type: ['ATM_ONLINE', 'NH_OFFLINE'] },
  ICB: { title: "Ngân hàng Công Thương Việt Nam", type: ['ATM_ONLINE', 'ATM_OFFLINE', 'NH_OFFLINE'] },
  EXB: { title: "Ngân hàng Xuất Nhập Khẩu", type: ['ATM_ONLINE'] },
  ACB: { title: "Ngân hàng Á Châu", type: ['ATM_ONLINE', 'ATM_OFFLINE', 'NH_OFFLINE'] },
  HDB: { title: "Ngân hàng Phát triển Nhà TPHCM", type: ['ATM_ONLINE'] },
  MSB: { title: "Ngân hàng Hàng Hải", type: ['ATM_ONLINE', 'ATM_OFFLINE', 'NH_OFFLINE'] },
  NVB: { title: "Ngân hàng Nam Việt", type: ['ATM_ONLINE'] },
  VAB: { title: "Ngân hàng Việt Á", type: ['ATM_ONLINE'] },
  VPB: { title: "Ngân Hàng Việt Nam Thịnh Vượng", type: ['ATM_ONLINE'] },
  SCB: { title: "Ngân hàng Sài Gòn Thương tín", type: ['ATM_ONLINE', 'ATM_OFFLINE', 'NH_OFFLINE'] },
  PGB: { title: "Ngân hàng Xăng dầu Petrolimex", type: ['ATM_ONLINE', 'ATM_OFFLINE', 'NH_OFFLINE'] },
  GPB: { title: "Ngân hàng TMCP Dầu khí Toàn Cầu", type: ['ATM_ONLINE'] },
  AGB: { title: "Ngân hàng Nông nghiệp & Phát triển nông thôn", type: ['ATM_ONLINE', 'ATM_OFFLINE', 'NH_OFFLINE'] },
  SGB: { title: "Ngân hàng Sài Gòn Công Thương", type: ['ATM_ONLINE'] },
  BAB: { title: "Ngân hàng Bắc Á", type: ['ATM_ONLINE'] },
  TPB: { title: "Tền phong bank", type: ['ATM_ONLINE', 'NH_OFFLINE'] },
  NAB: { title: "Ngân hàng Nam Á", type: ['ATM_ONLINE'] },
  SHB: { title: "Ngân hàng TMCP Sài Gòn - Hà Nội (SHB)", type: ['ATM_ONLINE', 'ATM_OFFLINE'] },
  OJB: { title: "Ngân hàng TMCP Đại Dương (OceanBank)", type: ['ATM_ONLINE'] },
  VISA: {title: "Visa", type: ['VISA'] },
  MASTER: {title: "Master", type: ['VISA'] },
}
MODE =
{
  production: {
    host: 'https://www.nganluong.vn',
    endpoint: '/checkout.api.nganluong.post.php',
  },
  sandbox: {
    host: 'https://sandbox.nganluong.vn:8088',
    endpoint: '/nl35/checkout.api.nganluong.post.php',
  }
}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(type, options = {}) ⇒ Checkout

@type(string), @option(Hash:merchant_password, :receiver_email, :cur_code)



54
55
56
57
58
59
# File 'lib/puerta/nl/checkout.rb', line 54

def initialize(type, options={})
  raise "Invalid type: #{type} in #{Checkout::TYPES}" if !Checkout::TYPES.include?(type)

  @type    = type
  @options = options
end

Instance Attribute Details

#resultObject

Returns the value of attribute result.



51
52
53
# File 'lib/puerta/nl/checkout.rb', line 51

def result
  @result
end

#typeObject

Returns the value of attribute type.



51
52
53
# File 'lib/puerta/nl/checkout.rb', line 51

def type
  @type
end

Class Method Details

.payment_typesObject



77
78
79
80
81
82
83
# File 'lib/puerta/nl/checkout.rb', line 77

def self.payment_types
  result = {}
  TYPES.each do |payment_type|
    result[payment_type] = Checkout::BANK_CODES.reject {|k,v|  !v[:type].include?(payment_type)}
  end
  result
end

Instance Method Details

#call(card_options) ⇒ Object

<< paymennt_options(card_options)



164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
# File 'lib/puerta/nl/checkout.rb', line 164

def call(card_options)
  params = payment_options(card_options)

  connection = Faraday::Connection.new host, ssl: { verify: false }

  response = connection.post do |req|
    req.url endpoint
    req.body = params
  end

  docs= parse_xml(response.body)
  error_code = docs.at("//error_code").text

  @result = {
    token: docs.at('//token').text,
    error_code: error_code,
    error_message: error(error_code.to_s),
    time_limit: docs.at("//time_limit").text,
    description: docs.at("//description").text,
    checkout_url: docs.at("//checkout_url").text,
  }
  @result
end

#endpointObject



69
70
71
72
73
74
75
# File 'lib/puerta/nl/checkout.rb', line 69

def endpoint
  if Puerta.config.sandbox?
    Checkout::MODE[:sandbox][:endpoint]
  elsif Puerta.config.production?
    Checkout::MODE[:production][:endpoint]
  end
end

#error(error_code) ⇒ Object

@error_code(string)



194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
# File 'lib/puerta/nl/checkout.rb', line 194

def error(error_code)
  errors = {
'00' => 'Thành công',
'99' => 'Lỗi chưa xác minh',
'06' => 'Mã merchant không tồn tại hoặc bị khóa',
'02' => 'Địa chỉ IP truy cập bị từ chối',
'03' => 'Mã checksum không chính xác, truy cập bị từ chối',
'04' => 'Tên hàm API do merchant gọi tới không hợp lệ (không tồn tại)',
'05' => 'Sai version của API',
'07' => 'Sai mật khẩu của merchant',
'08' => 'Địa chỉ email tài khoản nhận tiền không tồn tại',
'09' => 'Tài khoản nhận tiền đang bị phong tỏa giao dịch',
'10' => 'Mã đơn hàng không hợp lệ',
'11' => 'Số tiền giao dịch lớn hơn hoặc nhỏ hơn quy định',
'12' => 'Loại tiền tệ không hợp lệ',
'29' => 'Token không tồn tại',
'80' => 'Không thêm được đơn hàng',
'81' => 'Đơn hàng chưa được thanh toán',
'110' => 'Địa chỉ email tài khoản nhận tiền không phải email chính',
'111' => 'Tài khoản nhận tiền đang bị khóa',
'113' => 'Tài khoản nhận tiền chưa cấu hình là người bán nội dung số',
'114' => 'Giao dịch đang thực hiện, chưa kết thúc',
'115' => 'Giao dịch bị hủy',
'118' => 'tax_amount không hợp lệ',
'119' => 'discount_amount không hợp lệ',
'120' => 'fee_shipping không hợp lệ',
'121' => 'return_url không hợp lệ',
'122' => 'cancel_url không hợp lệ',
'123' => 'items không hợp lệ',
'124' => 'transaction_info không hợp lệ',
'125' => 'quantity không hợp lệ',
'126' => 'order_description không hợp lệ',
'127' => 'affiliate_code không hợp lệ',
'128' => 'time_limit không hợp lệ',
'129' => 'buyer_fullname không hợp lệ',
'130' => 'buyer_email không hợp lệ',
'131' => 'buyer_mobile không hợp lệ',
'132' => 'buyer_address không hợp lệ',
'133' => 'total_item không hợp lệ',
'134' => 'payment_method, bank_code không hợp lệ',
'135' => 'Lỗi kết nối tới hệ thống ngân hàng',
'140' => 'Đơn hàng không hỗ trợ thanh toán trả góp'
  }
  errors[error_code]
end

#error_codeObject



125
126
127
# File 'lib/puerta/nl/checkout.rb', line 125

def error_code
  @result[:error_code]
end

#error_messageObject



129
130
131
# File 'lib/puerta/nl/checkout.rb', line 129

def error_message
  error(@result[:error_code] )
end

#get_transaction_detail(token) ⇒ Object

@token(string)



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/puerta/nl/checkout.rb', line 90

def get_transaction_detail(token)
  params = {
    merchant_id: @options[:merchant_id],
    merchant_password: Digest::MD5.hexdigest(@options[:merchant_password]),
    version: VERSION,
    function: 'GetTransactionDetail',
    token:token
  }

  connection = Faraday::Connection.new host, ssl: { verify: false }

  response = connection.post do |req|
    req.url endpoint
    req.body = params
  end

  docs = parse_xml(response.body)

  error_code = docs.at('//error_code').text

  @result = {
    error_code: error_code,
    error_message: error(error_code.to_s),
    token: docs.at('//token').text,
    transaction_id: docs.at('//token').text,
    transaction_status: docs.at('//transaction_status').text,
    bank_code: docs.at('//bank_code').text,
  }
  @result
end

#hostObject



61
62
63
64
65
66
67
# File 'lib/puerta/nl/checkout.rb', line 61

def host
  if Puerta.config.sandbox?
    Checkout::MODE[:sandbox][:host]
  elsif Puerta.config.production?
    Checkout::MODE[:production][:host]
  end
end

#ok?Boolean

Returns:

  • (Boolean)


121
122
123
# File 'lib/puerta/nl/checkout.rb', line 121

def ok?
  @result && @result[:error_code] == '00'
end

#parse_xml(xml_string) ⇒ Object

@xml_string(string)



189
190
191
# File 'lib/puerta/nl/checkout.rb', line 189

def parse_xml(xml_string)
   Nokogiri::XML(xml_string)
end

#payment_methodsObject



85
86
87
# File 'lib/puerta/nl/checkout.rb', line 85

def payment_methods
  Checkout::BANK_CODES.reject {|k,v|  !v[:type].include?(@type)}
end

#payment_options(card_options) ⇒ Object

@card_options(Hash({:order_code, :total_amount, :payment_type, :order_description, :tax_amount, :fee_shipping, :discount_amount, :return_url, :cancel_url, :buyer_fullname, :buyer_email, :buyer_mobile, :buyer_address, :array_items, :bank_code OjO: bank_code: ( VISA, CREDIT_CARD_PREPAID, ATM_ONLINE, ATM_OFFLINE), no bank code: ( NH_OFFLINE, NL, IB_ONLINE )



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/puerta/nl/checkout.rb', line 136

def payment_options(card_options)
  card_options[:array_items] ||= []

  params = {
    function: 'SetExpressCheckout',
    version: Checkout::VERSION,
    payment_method: @type,
    merchant_password: Digest::MD5.hexdigest(@options[:merchant_password]),
    total_item: card_options[:array_items].count
  }


  params = params.merge(@options.select{|k,v| [:cur_code, :receiver_email, :merchant_id].include?(k)})
  params = params.merge(card_options.select{|k,v| k != :array_items } )

  sending_params = params.reject{|k,v| v == nil || v == ''}

  if(card_options[:array_items] && card_options[:array_items].count > 0)
    card_options[:array_items].each do |item|
      item.each do |key, value|
        sending_params[key] = value
      end
    end
  end
  sending_params
end