Class: MoteSMS::MobileTechnicsTransport

Inherits:
Object
  • Object
show all
Defined in:
lib/mote_sms/transports/mobile_technics_transport.rb

Overview

MoteSMS::MobileTechnicsTransport provides the implementation to send messages using nth.ch bulk SMS HTTP/S API. Each customer has custom endpoint (with port) and username/password.

Examples:

transport = MoteSMS::MobileTechnicsTransport.new 'https://mygateway.nth.ch', 'username', 'password'
transport.deliver message
# => ['000-791234', '001-7987324']

Constant Summary collapse

MAX_RECIPIENT =

Maximum recipients allowed by API

100
CERTS_PATH =

Path to certificates

File.expand_path File.join(File.dirname(__FILE__), '..', 'ssl_certs')
ServiceError =

Custom exception subclass.

Class.new(::Exception)

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(endpoint, username, password, options = nil) ⇒ MobileTechnicsTransport

Public: Create a new instance using specified endpoint, username and password.

username - The String with username. password - The String with password. options - The Hash with additional URL params passed to mobile techics endpoint

:endpoint - The String with the URL, defaults to https://mygateway.nth.ch
:ssl - SSL client options

Returns a new instance.



102
103
104
105
106
107
# File 'lib/mote_sms/transports/mobile_technics_transport.rb', line 102

def initialize(endpoint, username, password, options = nil)
  @endpoint = URI.parse(endpoint)
  @username = username
  @password = password
  @options = options || {}
end

Instance Attribute Details

#endpointObject (readonly)

Readable attributes



30
31
32
# File 'lib/mote_sms/transports/mobile_technics_transport.rb', line 30

def endpoint
  @endpoint
end

#optionsObject (readonly)

Readable attributes



30
31
32
# File 'lib/mote_sms/transports/mobile_technics_transport.rb', line 30

def options
  @options
end

#passwordObject (readonly)

Readable attributes



30
31
32
# File 'lib/mote_sms/transports/mobile_technics_transport.rb', line 30

def password
  @password
end

#usernameObject (readonly)

Readable attributes



30
31
32
# File 'lib/mote_sms/transports/mobile_technics_transport.rb', line 30

def username
  @username
end

Class Method Details

.default_cert_storeObject

Internal: The default certificate store, adds all *CA.pem files from mote_sms/ssl_certs directory.

Returns a OpenSSL::X509::Store



36
37
38
39
40
# File 'lib/mote_sms/transports/mobile_technics_transport.rb', line 36

def self.default_cert_store
  @cert_store ||= OpenSSL::X509::Store.new.tap do |store|
    Dir["#{CERTS_PATH}/*CA.pem"].each { |c| store.add_file c }
  end
end

.defaultsObject

Public: Global default parameters for sending messages, Procs/lambdas are evaluated on #deliver. Ensure to use only symbols as keys. Contains ‘allow_adaption: true` as default.

Examples:

MoteSMS::MobileTechnicsTransports.defaults[:messageid] = ->(msg) { "#{msg.from}-#{SecureRandom.hex}" }

Returns Hash with options.



63
64
65
66
67
68
69
70
71
72
# File 'lib/mote_sms/transports/mobile_technics_transport.rb', line 63

def self.defaults
  @@options ||= {
    allow_adaption: true,
    ssl: ->(http) {
      http.verify_mode = OpenSSL::SSL::VERIFY_PEER
      http.verify_depth = 9
      http.cert_store = self.default_cert_store
    }
  }
end

.fingerprint_cert(host) ⇒ Object

Internal: Load a X509::Certificate based on the hostname, used to handle server certificate fingerprinting.

host - The String with the hostname

Returns OpenSSL::X509::Certificate or nil if no certificate for this host

is found


49
50
51
52
# File 'lib/mote_sms/transports/mobile_technics_transport.rb', line 49

def self.fingerprint_cert(host)
  cert = "#{CERTS_PATH}/#{host}.pem"
  OpenSSL::X509::Certificate.new(File.read(cert)) if File.exists?(cert)
end

.loggerObject

Public: Logger used to log HTTP requests to mobile technics API endpoint.

Returns Logger instance.



78
79
80
# File 'lib/mote_sms/transports/mobile_technics_transport.rb', line 78

def self.logger
  @@logger ||= ::Logger.new($stdout)
end

.logger=(logger) ⇒ Object

Public: Change the logger used to log all HTTP requests to the endpoint.

logger - The Logger instance, should at least respond to #debug, #error.

Returns nothing.



88
89
90
# File 'lib/mote_sms/transports/mobile_technics_transport.rb', line 88

def self.logger=(logger)
  @@logger = logger
end

Instance Method Details

#deliver(message, options = {}) ⇒ Object

Public: Delivers message using mobile technics HTTP/S API.

message - The MoteSMS::Message instance to send. options - The Hash with service specific options.

Returns Array with sender ids.

Raises:

  • (ArgumentError)


115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/mote_sms/transports/mobile_technics_transport.rb', line 115

def deliver(message, options = {})
  raise ArgumentError, "too many recipients, max. is #{MAX_RECIPIENT} (current: #{message.to.length})" if message.to.length > MAX_RECIPIENT

  # Prepare request
  options = prepare_options options
  http = http_client options
  request = http_request post_params(message, options)

  # Log as `curl` request
  self.class.logger.debug "curl -X#{request.method} '#{endpoint}' -d '#{request.body}'"

  # Perform request
  resp = http.request(request)

  # Handle errors
  raise ServiceError, "endpoint did respond with #{resp.code}" unless resp.code.to_i == 200
  raise ServiceError, "unable to deliver message to all recipients (CAUSE: #{resp.body.strip})" unless resp.body.split("\n").all? { |l| l =~ /Result_code: 00/ }

  # extract Nth-SmsIds
  resp['X-Nth-SmsId'].split(',')
end