openmarket 0.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 313f1285d8dfc0d1a615e4d0e34b8d833df72e35
4
+ data.tar.gz: 54bf9d7d27719f8883faf50abc03ccba6619e6a5
5
+ SHA512:
6
+ metadata.gz: 4b97d23e3d060dae73ae4489b75e2291ff8b8f491ab05be1d5dd76e6512a9584fc5234580e353b9a8848ea7fc1f262dc7215cbea5ad3757675def646e8662ede
7
+ data.tar.gz: f9e13cf97a53740a26f755e7d201cf92048c521cc78ccbaac75452462de1bb023e74e884d9787092ce42b4b875d66d0c3a8b2f9e2d6ece78c1947ef1a647484e
@@ -0,0 +1,15 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+ secrets.yml
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --order random
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in open_market.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Isaac Betesh
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,129 @@
1
+ # OpenMarket
2
+
3
+ We use HTTParty to send SMS messages using the OpenMarket API. See USAGE below for details.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'openmarket'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install openmarket
20
+
21
+ ## Usage
22
+
23
+ ### Configuratiion
24
+
25
+ The openmarket gem requires you to provide an id, password, program_id and short_code. Configure them before attempting any API calls.
26
+
27
+ ```ruby
28
+ OpenMarket.configure do |config|
29
+ config.id = "000-000-000-00000"
30
+ config.password = "Re@llyL0ngR&om$tr1ng"
31
+ config.program_id = "ABC"
32
+ config.short_code = 99999 # You can override this on an individual message if necessary
33
+ end
34
+ ```
35
+
36
+ Since the openmarket gem depends on sms_validation (https://github.com/betesh/sms_validation/), it is also recommended that you configure sms_validation.
37
+ openmarket uses sms_validation's logger. In a Rails environment, you will probably want to rely on the default configuration,
38
+ but outside of Rails, you will need to configure it if you want any logging:
39
+
40
+ ```ruby
41
+ SmsValidation.configure do |config|
42
+ config.logger = ::Logger.new(STDOUT)
43
+ end
44
+ ```
45
+
46
+ ### API calls
47
+
48
+ `OpenMarket::API` supports 3 API calls: `carrier_lookup`, `send_sms`, and `status`.
49
+
50
+ #### carrier_lookup
51
+
52
+ ```ruby
53
+ require 'openmarket'
54
+ phone = 2125551212
55
+ result = OpenMarket::API.carrier_lookup(phone)
56
+
57
+ # First, make sure the call succeeded
58
+ puts result.code # should be 0
59
+ puts result.description # should be 'No Error'
60
+
61
+ # If the call succeeded, you can check the carrier_id:
62
+ puts result.carrier_id # You are probably most interested in the carrier_id
63
+ puts result.inspect # But there are a lot of other attributes returned by this API call as well
64
+ ```
65
+
66
+ #### send_sms
67
+
68
+ ```ruby
69
+ require 'openmarket'
70
+ phone = 2125551212
71
+ message = "Hello, this is a test of the OpenMarket API"
72
+ result = OpenMarket::API.send_sms(phone, message)
73
+
74
+ # First, make sure the call succeeded
75
+ puts result.code # should be 2
76
+ puts result.description # should be 'Message received.'
77
+
78
+ # Save the ticket ID for later. We'll use this to query the status of the ticket.
79
+ ticket_id = result.ticket_id
80
+
81
+ # Save the carrier ID for later. We'll use this next time we send an SMS to this number.
82
+ carrier_id = result.carrier_id
83
+
84
+ # There are some options you can pass along as well:
85
+ result = OpenMarket::API.send_sms(
86
+ phone,
87
+ message,
88
+
89
+ # If you want to receive DR's, you must pass a dr_url option. If you don't pass a URL, no DR will be sent to the default URL.
90
+ dr_url: "http://www.example.com/drs",
91
+
92
+ # It is highly recommended to pass a carrier_id. If you don't, the openmarket gem will make an extra API call to look up the carrier before sending the message.
93
+ carrier_id: carrier_id, # Remember the carrier ID we saved from the previous SMS?
94
+
95
+ # If you don't want to the short_code you configured above, provide another short_code to send to:
96
+ short_code: 33333,
97
+
98
+ # By default, OpenMarket re-attempts delivery for 3 days. To make OpenMarket give up and report it as a failure sooner, pass a number of minutes you would like to retry for:
99
+ minutes_to_retry: 120, # 2 hours
100
+
101
+ note: "Information that will be passed on to the DR",
102
+
103
+ ticket_id_for_retry: ticket_id # If this is a re-try of a failed ticket.
104
+ )
105
+
106
+ ```
107
+ #### status
108
+
109
+ ```ruby
110
+ require 'openmarket'
111
+ result = OpenMarket::API.status(ticket_id) # Remember the ticket ID we saved from #send_sms?
112
+
113
+ # First, make sure the call succeeded
114
+ puts result.code # should be 0
115
+ puts result.description # should be 'No Error'
116
+
117
+ # Check the result of the SMS message
118
+ puts result.status_code
119
+ puts result.status_description
120
+
121
+ ```
122
+
123
+ ## Contributing
124
+
125
+ 1. Fork it ( https://github.com/betesh/open_market/fork )
126
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
127
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
128
+ 4. Push to the branch (`git push origin my-new-feature`)
129
+ 5. Create a new Pull Request
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,4 @@
1
+ require "open_market/api"
2
+
3
+ module OpenMarket
4
+ end
@@ -0,0 +1,83 @@
1
+ require "open_market/configuration"
2
+ require "open_market/response"
3
+ require "open_market/version"
4
+
5
+ require "builder"
6
+ require "httparty"
7
+ require "sms_validation"
8
+
9
+ module OpenMarket
10
+ class Api
11
+ class Http
12
+ include HTTParty
13
+ base_uri "https://smsc.openmarket.com"
14
+ end
15
+
16
+ ALLOWED_OPTIONS = [:dr_url, :ticket_id_for_retry, :carrier_id, :note, :minutes_to_retry, :short_code]
17
+ class InvalidOptions < ::StandardError; end
18
+
19
+ def carrier_lookup(phone)
20
+ CarrierLookupResponse.new(post(:preview) do |b|
21
+ b.destination(ton: 1, address: "1#{phone.to_s[-10..-1]}")
22
+ end)
23
+ end
24
+
25
+ def send_sms(phone, message, options = {})
26
+ phone = SmsValidation::Sms.new(phone, message).phone
27
+ options = options.inject({}) { |hash, (k,v)| hash[k.to_sym] = v; hash }
28
+ unrecognized_keys = options.keys - ALLOWED_OPTIONS
29
+ raise InvalidOptions, "#{unrecognized_keys.join(", ")} #{1 == unrecognized_keys.size ? "is not a" : "are not"} valid option#{:s if unrecognized_keys.size > 1}" unless unrecognized_keys.empty?
30
+ request_options = options.select{ |k,v| k.to_sym == :ticket_id_for_retry }
31
+ carrier_id = options[:carrier_id] || carrier_lookup(phone).carrier_id
32
+ SendSmsResponse.new(post(:submit, request_options) do |b|
33
+ b.delivery(receipt_requested: true, url: options[:dr_url]) if options[:dr_url]
34
+ b.option((options[:note] ? { note: options[:note] } : {}).merge(charge_type: 0, program_id: configuration.program_id, mlc: message_length_control))
35
+ b.source(ton: 3, address: options[:short_code] || configuration.short_code)
36
+ b.destination(ton: 1, address: phone, carrier: carrier_id)
37
+ b.message((options[:minutes_to_retry] ? { validity_period: (options[:minutes_to_retry].to_f * 60).round } : {}).merge(text: message))
38
+ end, carrier_id)
39
+ end
40
+
41
+ def status(ticket_id)
42
+ StatusResponse.new(post(:query) do |b|
43
+ b.ticket(id: ticket_id)
44
+ end)
45
+ end
46
+
47
+ private
48
+ def configuration
49
+ @configuration ||= Module.nesting.last.configuration
50
+ end
51
+
52
+ def filtered(value)
53
+ [:account, :user].inject(value) { |v, k| v.gsub(/<#{k}.*?\/>/, "") }
54
+ end
55
+
56
+ def post(type, options = {})
57
+ builder = Builder::XmlMarkup.new
58
+ builder.instruct!(:xml, version: 1.0)
59
+ body = builder.request(options.merge(version: 3.0, protocol: :wmp, type: type)) do |r|
60
+ r.user(agent: "openmarket_rubygem/SMS/#{OpenMarket::VERSION}")
61
+ r.account(id: configuration.id, password: configuration.password)
62
+ yield r
63
+ end
64
+ SmsValidation.log { "OpenMarket API: POST #{filtered(body)}" }
65
+ Http.post("/wmp", body: body.to_s).tap do |result|
66
+ SmsValidation.log { "OpenMarket API Result: #{result.respond_to?(:body) ? result.body : result}" }
67
+ end
68
+ end
69
+
70
+ def message_length_control
71
+ case SmsValidation.configuration.on_message_too_long
72
+ when :truncate
73
+ 1
74
+ when :raise_error
75
+ 0
76
+ when :split
77
+ 2
78
+ end
79
+ end
80
+ end
81
+
82
+ API ||= Api.new
83
+ end
@@ -0,0 +1,38 @@
1
+ module OpenMarket
2
+ class << self
3
+ def configuration
4
+ @configuration ||= Configuration.new
5
+ end
6
+
7
+ def configure
8
+ yield configuration
9
+ end
10
+ end
11
+
12
+ class Configuration
13
+ class Error < ::StandardError; end
14
+ CONFIGURATION_OPTIONS = [:id, :password, :program_id, :short_code]
15
+
16
+ (CONFIGURATION_OPTIONS - [:short_code]).each do |accessor|
17
+ define_method(:"#{accessor}=") do |arg|
18
+ raise Error, "#{accessor} must be a String" unless arg.nil? || arg.is_a?(String)
19
+ raise Error, "#{accessor} cannot be blank" if arg.nil? || arg.empty?
20
+ instance_variable_set("@#{accessor}", arg)
21
+ end
22
+ end
23
+
24
+ def short_code=(arg)
25
+ raise Error, "short_code cannot be blank" if arg.nil?
26
+ raise Error, "short_code must be a 5-digit number" unless arg.to_s.scan(/\A[0-9]{5}\z/)
27
+ @short_code = arg
28
+ end
29
+
30
+ CONFIGURATION_OPTIONS.each do |accessor|
31
+ define_method(accessor) do
32
+ instance_variable_get("@#{accessor}").tap do |result|
33
+ raise Error, "#{accessor} has not been set. Set it with `#{Module.nesting.last}.configuration.#{accessor} = ...`" if result.nil?
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,27 @@
1
+ require "rexml/document"
2
+
3
+ module OpenMarket
4
+ class DR
5
+ attr_reader :code, :description, :note, :parent_ticket_id, :segment_number, :state_description, :state_id, :ticket_id, :timestamp
6
+ def initialize(data)
7
+ (class << self; self; end).class_eval do
8
+ # Defining a member variable for xml would pollute #inspect
9
+ # This solution is inspired by https://github.com/jordansissel/software-patterns/tree/master/dont-log-secrets/ruby
10
+ define_method(:xml) { REXML::Document.new(data).root }
11
+ private :xml
12
+ end
13
+ @ticket_id = xml.attributes["ticketId"]
14
+ @parent_ticket_id = xml.attributes["parentTicketId"]
15
+ @note = xml.attributes["note"]
16
+ response = xml.elements["response"]
17
+ @description = response.attributes["description"]
18
+ @code = response.attributes["code"].to_i
19
+ message = xml.elements["message"]
20
+ @segment_number = message.attributes["segmentNumber"]
21
+ @timestamp = DateTime.strptime(message.attributes["deliveryDate"] + "+0000", '%FT%T.%LZ%z').utc
22
+ state = message.elements["state"]
23
+ @state_id = state.attributes["id"].to_i
24
+ @state_description = state.attributes["description"]
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,37 @@
1
+ require "rexml/document"
2
+
3
+ module OpenMarket
4
+ class MO
5
+ attr_reader :account_id, :carrier_id, :data, :data_coding, :destination_address, :destination_ton, :source_address, :source_ton, :ticket_id, :udhi
6
+ def initialize(data)
7
+ (class << self; self; end).class_eval do
8
+ # Defining a member variable for xml would pollute #inspect
9
+ # This solution is inspired by https://github.com/jordansissel/software-patterns/tree/master/dont-log-secrets/ruby
10
+ define_method(:xml) { REXML::Document.new(data).root }
11
+ private :xml
12
+ end
13
+ if ticket = xml.elements["ticket"]
14
+ @ticket_id = ticket.attributes["id"]
15
+ end
16
+ if account = xml.elements["account"]
17
+ @account_id = account.attributes["id"]
18
+ end
19
+ if source = xml.elements["source"]
20
+ @carrier_id = source.elements["carrier"]
21
+ @source_ton = source.elements["ton"]
22
+ @source_address = source.elements["address"]
23
+ end
24
+ if destination = xml.elements["destination"]
25
+ @destination_ton = destination.elements["ton"]
26
+ @destination_address = destination.elements["address"]
27
+ end
28
+ if option = xml.elements["option"]
29
+ @data_coding = option.attributes["datacoding"]
30
+ end
31
+ if message = xml.elements["message"]
32
+ @udhi = message.attributes["udhi"] == true
33
+ @data = message.attributes["data"]
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,98 @@
1
+ require "rexml/document"
2
+
3
+ module OpenMarket
4
+ class Response
5
+ attr_reader :code, :description
6
+ def initialize(http_response)
7
+ (class << self; self; end).class_eval do
8
+ # Defining a member variable for xml would pollute #inspect
9
+ # This solution is inspired by https://github.com/jordansissel/software-patterns/tree/master/dont-log-secrets/ruby
10
+ define_method(:xml) do
11
+ if http_response.respond_to?(:body)
12
+ REXML::Document.new(http_response.body).root
13
+ else
14
+ REXML::Document.new(http_response.to_xml).root.elements["response"]
15
+ end
16
+ end
17
+ private :xml
18
+ end
19
+ error = xml.elements["error"]
20
+ @code = (error.attributes["code"] || error.elements["code"].text).to_i
21
+ @description = error.attributes["description"] || error.elements["description"].text
22
+ end
23
+ end
24
+
25
+ class CarrierLookupResponse < Response
26
+ attr_reader :country_code, :national_number, :intl_notation, :area_code, :area_code_length, :num_min_length, :num_max_length, :na_nxx, :na_line, :local_notation, :local_format, :digits_all, :digits_local, :ported, :ported_from
27
+ attr_reader :city, :country, :country_name, :estimated_latitude, :estimated_longitude, :region, :region_name, :timezone_min, :timezone_max, :zone, :zone_name
28
+ attr_reader :carrier_id, :name, :binary_length, :text_length, :unicode_length, :binary, :ems, :smart_messaging, :unicode, :wap_push
29
+
30
+ def initialize(http_response)
31
+ super
32
+ if destination = xml.elements["destination"]
33
+ @country_code = destination.attributes["country_code"].to_i
34
+ @national_number = destination.attributes["national_number"]
35
+ @intl_notation = destination.attributes["intl_notation"]
36
+ @area_code = destination.attributes["area_code"]
37
+ @area_code_length = destination.attributes["area_code_length"].to_i
38
+ @num_min_length = destination.attributes["num_min_length"].to_i
39
+ @num_max_length = destination.attributes["num_max_length"].to_i
40
+ @na_nxx = destination.attributes["na_nxx"]
41
+ @na_line = destination.attributes["na_line"]
42
+ @local_notation = destination.attributes["local_notation"]
43
+ @local_format = destination.attributes["local_format"]
44
+ @digits_all = destination.attributes["digits_all"].to_i
45
+ @digits_local = destination.attributes["digits_local"].to_i
46
+ @ported = destination.attributes["ported"] == "true"
47
+ @ported_from = destination.attributes["ported_from"]
48
+ end
49
+ if location = xml.elements["location"]
50
+ @city = location.attributes["city"]
51
+ @country = location.attributes["country"]
52
+ @country_name = location.attributes["country_name"]
53
+ @estimated_latitude = location.attributes["estimated_latitude"].to_f
54
+ @estimated_longitude = location.attributes["estimated_longitude"].to_f
55
+ @region = location.attributes["region"]
56
+ @region_name = location.attributes["region_name"]
57
+ @timezone_min = location.attributes["timezone_min"].to_i
58
+ @timezone_max= location.attributes["timezone_max"].to_i
59
+ @zone = location.attributes["zone"].to_i
60
+ @zone_name = location.attributes["zone_name"]
61
+ end
62
+ if operator = xml.elements["operator"]
63
+ @carrier_id = operator.attributes["id"].to_i
64
+ @name = operator.attributes["name"]
65
+ @binary_length = operator.attributes["binary_length"].to_i
66
+ @text_length = operator.attributes["text_length"].to_i
67
+ @unicode_length = operator.attributes["unicode_length"].to_i
68
+ @binary = operator.attributes["binary"] == "true"
69
+ @ems = operator.attributes["ems"] == "true"
70
+ @smart_messaging = operator.attributes["smart_messaging"] == "true"
71
+ @unicode = operator.attributes["unicode"] == "true"
72
+ @wap_push = operator.attributes["wap_push"] == "true"
73
+ end
74
+ end
75
+ end
76
+
77
+ class SendSmsResponse < Response
78
+ attr_reader :ticket_id, :carrier_id
79
+ def initialize(http_response, carrier_id)
80
+ super(http_response)
81
+ @carrier_id = carrier_id
82
+ if ticket = xml.elements["ticket"]
83
+ @ticket_id = ticket.attributes["id"]
84
+ end
85
+ end
86
+ end
87
+
88
+ class StatusResponse < Response
89
+ attr_reader :status_code, :status_description
90
+ def initialize(http_response)
91
+ super
92
+ if status = xml.elements["status"]
93
+ @status_code = status.attributes["code"].to_i
94
+ @status_description = status.attributes["description"]
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,3 @@
1
+ module OpenMarket
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1 @@
1
+ require "open_market"
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'open_market/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "openmarket"
8
+ spec.version = OpenMarket::VERSION
9
+ spec.authors = ["Isaac Betesh"]
10
+ spec.email = ["iybetesh@gmail.com"]
11
+ spec.summary = "Send SMS messages using the OpenMarket API"
12
+ spec.description = `cat README.md`
13
+ spec.homepage = "https://github.com/betesh/open_market"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.7"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_development_dependency "rspec", "~> 3"
24
+
25
+ spec.add_dependency "sms_validation", "~> 0.0.2"
26
+ spec.add_dependency "httparty"
27
+ spec.add_dependency "builder"
28
+ end
@@ -0,0 +1,220 @@
1
+ require "open_market/api"
2
+ require "support/configuration_from_yaml"
3
+
4
+ describe OpenMarket::Api do
5
+ subject { OpenMarket::API }
6
+
7
+ describe "#carrier_lookup" do
8
+ it "should succeed without a 1 preceding the phone number" do
9
+ result = subject.carrier_lookup(phone)
10
+ expect(result).to be_a(OpenMarket::CarrierLookupResponse)
11
+ expect(result.code).to eq(0)
12
+ expect(result.description).to eq("No Error")
13
+ expect(result.carrier_id).to eq(carrier_id)
14
+ end
15
+
16
+ it "should succeed with a 1 preceding the phone number" do
17
+ result = subject.carrier_lookup("1#{phone}")
18
+ expect(result).to be_a(OpenMarket::CarrierLookupResponse)
19
+ expect(result.code).to eq(0)
20
+ expect(result.description).to eq("No Error")
21
+ expect(result.carrier_id).to eq(carrier_id)
22
+ end
23
+ end
24
+
25
+ describe "#send_sms" do
26
+ it "should send an SMS" do
27
+ result = subject.send_sms(phone, "Test of OpenMarket API", carrier_id: carrier_id)
28
+ expect(result.code).to eq(2)
29
+ expect(result.description).to eq("Message received.")
30
+ expect(result.ticket_id).not_to be_nil
31
+ end
32
+
33
+ it "looks up the carrier_id if it is not passed as an option and returns it" do
34
+ expect(OpenMarket::Api::Http).to receive(:post).and_wrap_original do |original, *args, &block|
35
+ expect(args[0]).to eq("/wmp")
36
+ puts args[1][:body].inspect
37
+ expect(args[1][:body]).to match /\A<\?xml version=\"1.0\" encoding=\"UTF-8\"\?><request version=\"3.0\" protocol=\"wmp\" type=\"preview\"><user agent=\"openmarket_rubygem\/SMS\/0\.0\.1\"\/><account id=\"#{id}\" password=\"#{password}\"\/><destination ton=\"1\" address=\"1#{phone}\"\/><\/request>\z/
38
+ original.call(*args, &block)
39
+ end
40
+ expect(OpenMarket::Api::Http).to receive(:post).and_wrap_original do |original, *args, &block|
41
+ expect(args[0]).to eq("/wmp")
42
+ expect(args[1][:body]).to match /\A<\?xml version=\"1.0\" encoding=\"UTF-8\"\?><request version=\"3.0\" protocol=\"wmp\" type=\"submit\"><user agent=\"openmarket_rubygem\/SMS\/0\.0\.1\"\/><account id=\"#{id}\" password=\"#{password}\"\/><option charge_type=\"0\" program_id=\"#{program_id}\" mlc=\"0\"\/><source ton=\"3\" address=\"#{short_code}\"\/><destination ton=\"1\" address=\"1#{phone}\" carrier=\"#{carrier_id}\"\/><message text=\"Test of OpenMarket API\"\/><\/request>\z/
43
+ original.call(*args, &block)
44
+ end
45
+ result = subject.send_sms(phone, "Test of OpenMarket API")
46
+ expect(result.carrier_id).to eq(carrier_id)
47
+ end
48
+
49
+ describe "message_length_control" do
50
+ describe "when SmsValidation.configuration.on_message_too_long is truncate" do
51
+ it "should be 1" do
52
+ SmsValidation.configuration.on_message_too_long = :truncate
53
+ expect(OpenMarket::Api::Http).to receive(:post).and_wrap_original do |original, *args, &block|
54
+ expect(args[0]).to eq("/wmp")
55
+ expect(args[1][:body]).to match /\A<\?xml version=\"1.0\" encoding=\"UTF-8\"\?><request version=\"3.0\" protocol=\"wmp\" type=\"submit\"><user agent=\"openmarket_rubygem\/SMS\/0\.0\.1\"\/><account id=\"#{id}\" password=\"#{password}\"\/><option charge_type=\"0\" program_id=\"#{program_id}\" mlc=\"1\"\/><source ton=\"3\" address=\"#{short_code}\"\/><destination ton=\"1\" address=\"1#{phone}\" carrier=\"#{carrier_id}\"\/><message text=\"Test of OpenMarket API\"\/><\/request>\z/
56
+ original.call(*args, &block)
57
+ end
58
+ subject.send_sms(phone, "Test of OpenMarket API", carrier_id: carrier_id)
59
+ end
60
+ end
61
+
62
+ describe "when SmsValidation.configuration.on_message_too_long is split" do
63
+ it "should be 2" do
64
+ SmsValidation.configuration.on_message_too_long = :split
65
+ expect(OpenMarket::Api::Http).to receive(:post).and_wrap_original do |original, *args, &block|
66
+ expect(args[0]).to eq("/wmp")
67
+ expect(args[1][:body]).to match /\A<\?xml version=\"1.0\" encoding=\"UTF-8\"\?><request version=\"3.0\" protocol=\"wmp\" type=\"submit\"><user agent=\"openmarket_rubygem\/SMS\/0\.0\.1\"\/><account id=\"#{id}\" password=\"#{password}\"\/><option charge_type=\"0\" program_id=\"#{program_id}\" mlc=\"2\"\/><source ton=\"3\" address=\"#{short_code}\"\/><destination ton=\"1\" address=\"1#{phone}\" carrier=\"#{carrier_id}\"\/><message text=\"Test of OpenMarket API\"\/><\/request>\z/
68
+ original.call(*args, &block)
69
+ end
70
+ subject.send_sms(phone, "Test of OpenMarket API", carrier_id: carrier_id)
71
+ end
72
+ end
73
+
74
+ describe "when SmsValidation.configuration.on_message_too_long is raise_error" do
75
+ it "should be 0" do
76
+ SmsValidation.configuration.on_message_too_long = :raise_error
77
+ expect(OpenMarket::Api::Http).to receive(:post).and_wrap_original do |original, *args, &block|
78
+ expect(args[0]).to eq("/wmp")
79
+ expect(args[1][:body]).to match /\A<\?xml version=\"1.0\" encoding=\"UTF-8\"\?><request version=\"3.0\" protocol=\"wmp\" type=\"submit\"><user agent=\"openmarket_rubygem\/SMS\/0\.0\.1\"\/><account id=\"#{id}\" password=\"#{password}\"\/><option charge_type=\"0\" program_id=\"#{program_id}\" mlc=\"0\"\/><source ton=\"3\" address=\"#{short_code}\"\/><destination ton=\"1\" address=\"1#{phone}\" carrier=\"#{carrier_id}\"\/><message text=\"Test of OpenMarket API\"\/><\/request>\z/
80
+ original.call(*args, &block)
81
+ end
82
+ subject.send_sms(phone, "Test of OpenMarket API", carrier_id: carrier_id)
83
+ end
84
+ end
85
+ end
86
+
87
+ describe "invalid keys" do
88
+ it "should raise a gramatically correct error with 1 unknown option" do
89
+ expect{subject.send_sms(phone, "Test of OpenMarket API", carrier_id: carrier_id, unknown_option: true)}.to raise_error(OpenMarket::Api::InvalidOptions, "unknown_option is not a valid option")
90
+ end
91
+
92
+ it "should raise a gramatically correct error with 2 unknown options" do
93
+ expect{subject.send_sms(phone, "Test of OpenMarket API", carrier_id: carrier_id, unknown_option: true, other_unknown: false)}.to raise_error(OpenMarket::Api::InvalidOptions, "unknown_option, other_unknown are not valid options")
94
+ end
95
+
96
+ it "automatically converts String keys to Symbol" do
97
+ expect{subject.send_sms(phone, "Test of OpenMarket API", "carrier_id" => carrier_id, "ticket_id_for_retry" => "ABC", "dr_url" => dr_url, "note" => "ABCDEFFF", "minutes_to_retry" => 10, "short_code" => 99998)}.not_to raise_error
98
+ end
99
+ end
100
+
101
+ describe "valid keys" do
102
+ describe "carrier_id" do
103
+ let(:carrier_id) { 1000000 }
104
+ it "should be in the XML" do
105
+ expect(OpenMarket::Api::Http).to receive(:post).and_wrap_original do |original, *args, &block|
106
+ expect(args[0]).to eq("/wmp")
107
+ expect(args[1][:body]).to match /\A<\?xml version=\"1.0\" encoding=\"UTF-8\"\?><request version=\"3.0\" protocol=\"wmp\" type=\"submit\"><user agent=\"openmarket_rubygem\/SMS\/0\.0\.1\"\/><account id=\"#{id}\" password=\"#{password}\"\/><option charge_type=\"0\" program_id=\"#{program_id}\" mlc=\"0\"\/><source ton=\"3\" address=\"#{short_code}\"\/><destination ton=\"1\" address=\"1#{phone}\" carrier=\"#{carrier_id}\"\/><message text=\"Test of OpenMarket API\"\/><\/request>\z/
108
+ original.call(*args, &block)
109
+ end
110
+ subject.send_sms(phone, "Test of OpenMarket API", carrier_id: carrier_id)
111
+ end
112
+ end
113
+
114
+ describe "note" do
115
+ let(:note) { "The quick brown fox jumps over the lazy dog" }
116
+ it "should be in the XML" do
117
+ expect(OpenMarket::Api::Http).to receive(:post).and_wrap_original do |original, *args, &block|
118
+ expect(args[0]).to eq("/wmp")
119
+ expect(args[1][:body]).to match /\A<\?xml version=\"1.0\" encoding=\"UTF-8\"\?><request version=\"3.0\" protocol=\"wmp\" type=\"submit\"><user agent=\"openmarket_rubygem\/SMS\/0\.0\.1\"\/><account id=\"#{id}\" password=\"#{password}\"\/><option note=\"#{note}\" charge_type=\"0\" program_id=\"#{program_id}\" mlc=\"0\"\/><source ton=\"3\" address=\"#{short_code}\"\/><destination ton=\"1\" address=\"1#{phone}\" carrier=\"#{carrier_id}\"\/><message text=\"Test of OpenMarket API\"\/><\/request>\z/
120
+ original.call(*args, &block)
121
+ end
122
+ subject.send_sms(phone, "Test of OpenMarket API", carrier_id: carrier_id, note: note)
123
+ end
124
+ end
125
+
126
+ describe "ticket_id_for_retry" do
127
+ let(:ticket_id_for_retry) { 1999998888 }
128
+ it "should be in the XML" do
129
+ expect(OpenMarket::Api::Http).to receive(:post).and_wrap_original do |original, *args, &block|
130
+ expect(args[0]).to eq("/wmp")
131
+ expect(args[1][:body]).to match /\A<\?xml version=\"1.0\" encoding=\"UTF-8\"\?><request ticket_id_for_retry=\"#{ticket_id_for_retry}\" version=\"3.0\" protocol=\"wmp\" type=\"submit\"><user agent=\"openmarket_rubygem\/SMS\/0\.0\.1\"\/><account id=\"#{id}\" password=\"#{password}\"\/><option charge_type=\"0\" program_id=\"#{program_id}\" mlc=\"0\"\/><source ton=\"3\" address=\"#{short_code}\"\/><destination ton=\"1\" address=\"1#{phone}\" carrier=\"#{carrier_id}\"\/><message text=\"Test of OpenMarket API\"\/><\/request>\z/
132
+ original.call(*args, &block)
133
+ end
134
+ subject.send_sms(phone, "Test of OpenMarket API", carrier_id: carrier_id, ticket_id_for_retry: ticket_id_for_retry)
135
+ end
136
+ end
137
+
138
+ describe "dr_url" do
139
+ let(:dr_url) { "example.com" }
140
+ it "should be in the XML" do
141
+ expect(OpenMarket::Api::Http).to receive(:post).and_wrap_original do |original, *args, &block|
142
+ expect(args[0]).to eq("/wmp")
143
+ expect(args[1][:body]).to match /\A<\?xml version=\"1.0\" encoding=\"UTF-8\"\?><request version=\"3.0\" protocol=\"wmp\" type=\"submit\"><user agent=\"openmarket_rubygem\/SMS\/0\.0\.1\"\/><account id=\"#{id}\" password=\"#{password}\"\/><delivery receipt_requested=\"true\" url=\"#{dr_url}\"\/><option charge_type=\"0\" program_id=\"#{program_id}\" mlc=\"0\"\/><source ton=\"3\" address=\"#{short_code}\"\/><destination ton=\"1\" address=\"1#{phone}\" carrier=\"#{carrier_id}\"\/><message text=\"Test of OpenMarket API\"\/><\/request>\z/
144
+ original.call(*args, &block)
145
+ end
146
+ subject.send_sms(phone, "Test of OpenMarket API", dr_url: dr_url, carrier_id: carrier_id)
147
+ end
148
+ end
149
+
150
+ describe "minutes_to_retry" do
151
+ it "should be in the XML" do
152
+ expect(OpenMarket::Api::Http).to receive(:post).and_wrap_original do |original, *args, &block|
153
+ expect(args[0]).to eq("/wmp")
154
+ expect(args[1][:body]).to match /\A<\?xml version=\"1.0\" encoding=\"UTF-8\"\?><request version=\"3.0\" protocol=\"wmp\" type=\"submit\"><user agent=\"openmarket_rubygem\/SMS\/0\.0\.1\"\/><account id=\"#{id}\" password=\"#{password}\"\/><delivery receipt_requested=\"true\" url=\"#{dr_url}\"\/><option charge_type=\"0\" program_id=\"#{program_id}\" mlc=\"0\"\/><source ton=\"3\" address=\"#{short_code}\"\/><destination ton=\"1\" address=\"1#{phone}\" carrier=\"#{carrier_id}\"\/><message validity_period=\"1080\" text=\"Test of OpenMarket API\"\/><\/request>\z/
155
+ original.call(*args, &block)
156
+ end
157
+ subject.send_sms(phone, "Test of OpenMarket API", dr_url: dr_url, carrier_id: carrier_id, minutes_to_retry: 18)
158
+ end
159
+
160
+ describe "can be a fraction of a number and is rounded to the nearest integer number of seconds" do
161
+ [19, 20, 21].each do |divisor|
162
+ describe do
163
+ it "should be in the XML" do
164
+ expect(OpenMarket::Api::Http).to receive(:post).and_wrap_original do |original, *args, &block|
165
+ expect(args[0]).to eq("/wmp")
166
+ expect(args[1][:body]).to match /\A<\?xml version=\"1.0\" encoding=\"UTF-8\"\?><request version=\"3.0\" protocol=\"wmp\" type=\"submit\"><user agent=\"openmarket_rubygem\/SMS\/0\.0\.1\"\/><account id=\"#{id}\" password=\"#{password}\"\/><delivery receipt_requested=\"true\" url=\"#{dr_url}\"\/><option charge_type=\"0\" program_id=\"#{program_id}\" mlc=\"0\"\/><source ton=\"3\" address=\"#{short_code}\"\/><destination ton=\"1\" address=\"1#{phone}\" carrier=\"#{carrier_id}\"\/><message validity_period=\"3\" text=\"Test of OpenMarket API\"\/><\/request>\z/
167
+ original.call(*args, &block)
168
+ end
169
+ subject.send_sms(phone, "Test of OpenMarket API", dr_url: dr_url, carrier_id: carrier_id, minutes_to_retry: 1.0/divisor )
170
+ end
171
+ end
172
+ end
173
+ end
174
+ end
175
+
176
+ describe "short_code" do
177
+ let(:short_code) { 66666 }
178
+ it "should be in the XML" do
179
+ expect(OpenMarket::Api::Http).to receive(:post).and_wrap_original do |original, *args, &block|
180
+ expect(args[0]).to eq("/wmp")
181
+ expect(args[1][:body]).to match /\A<\?xml version=\"1.0\" encoding=\"UTF-8\"\?><request version=\"3.0\" protocol=\"wmp\" type=\"submit\"><user agent=\"openmarket_rubygem\/SMS\/0\.0\.1\"\/><account id=\"#{id}\" password=\"#{password}\"\/><option charge_type=\"0\" program_id=\"#{program_id}\" mlc=\"0\"\/><source ton=\"3\" address=\"#{short_code}\"\/><destination ton=\"1\" address=\"1#{phone}\" carrier=\"#{carrier_id}\"\/><message text=\"Test of OpenMarket API\"\/><\/request>\z/
182
+ original.call(*args, &block)
183
+ end
184
+ subject.send_sms(phone, "Test of OpenMarket API", carrier_id: carrier_id, short_code: short_code)
185
+ end
186
+ end
187
+ end
188
+ end
189
+
190
+ describe "#status" do
191
+ let(:sms) { subject.send_sms(phone, "Test of OpenMarket API") }
192
+ let(:ticket_id) { sms.ticket_id }
193
+
194
+ def get_status
195
+ subject.status(ticket_id)
196
+ end
197
+
198
+ it "should look up the status of a ticket" do
199
+ status = get_status
200
+ expect(status.code).to eq(0)
201
+ expect(status.description).to eq("No Error")
202
+ expect(status.status_code).to eq(3)
203
+ expect(status.status_description).to eq("Message buffered with carrier and waiting for delivery response.")
204
+ print "Waiting for the message to be delivered..."
205
+ i = 0
206
+ SmsValidation.configuration.logger = nil
207
+ begin
208
+ sleep 1
209
+ print "."
210
+ status = get_status
211
+ break if 4 == status.status_code
212
+ i += 1
213
+ end while i < 5
214
+ expect(status.code).to eq(0)
215
+ expect(status.description).to eq("No Error")
216
+ expect(status.status_code).to eq(4)
217
+ expect(status.status_description).to eq("Message successfully delivered.")
218
+ end
219
+ end
220
+ end
@@ -0,0 +1,35 @@
1
+ require "support/configuration_from_yaml"
2
+ require "open_market/configuration"
3
+
4
+ describe OpenMarket::Configuration do
5
+ subject { OpenMarket.configuration }
6
+ let(:skip_open_market_configuration) { true }
7
+
8
+ [:id, :password, :program_id].each do |configuration_option|
9
+ describe "##{configuration_option}" do
10
+ it "cannot be nil" do
11
+ expect{subject.public_send("#{configuration_option}=", nil)}.to raise_error(OpenMarket::Configuration::Error, "#{configuration_option} cannot be blank")
12
+ end
13
+
14
+ it "cannot be an empty String" do
15
+ expect{subject.public_send("#{configuration_option}=", "")}.to raise_error(OpenMarket::Configuration::Error, "#{configuration_option} cannot be blank")
16
+ end
17
+
18
+ it "cannot be a Hash" do
19
+ expect{subject.public_send("#{configuration_option}=", {})}.to raise_error(OpenMarket::Configuration::Error, "#{configuration_option} must be a String")
20
+ end
21
+
22
+ it "must be set before accessing it" do
23
+ expect{subject.public_send(configuration_option)}.to raise_error(OpenMarket::Configuration::Error, "#{configuration_option} has not been set. Set it with `OpenMarket.configuration.#{configuration_option} = ...`")
24
+ end
25
+
26
+ describe "when configured" do
27
+ let(:skip_open_market_configuration) { false }
28
+
29
+ it "is accessible" do
30
+ expect(subject.public_send(configuration_option)).to eq(public_send(configuration_option))
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,33 @@
1
+ require "yaml"
2
+ require "logger"
3
+ require "rspec/core/shared_context"
4
+ require "sms_validation"
5
+
6
+ module ConfigurationFromYaml
7
+ extend RSpec::Core::SharedContext
8
+ SECRETS = YAML::load(File.open(File.expand_path("#{__FILE__}/../secrets.yml")))
9
+
10
+ SECRETS.keys.each do |key|
11
+ let(key) { SECRETS[key] }
12
+ end
13
+
14
+ let(:skip_open_market_configuration) { false }
15
+
16
+ before(:each) do
17
+ SmsValidation.configure do |config|
18
+ config.logger = ::Logger.new(STDOUT)
19
+ end
20
+ OpenMarket.configure do |config|
21
+ config.id, config.password, config.short_code, config.program_id = id, password, short_code, program_id
22
+ end unless skip_open_market_configuration
23
+ end
24
+
25
+ after(:each) do
26
+ OpenMarket.instance_variable_set("@configuration", nil)
27
+ SmsValidation.instance_variable_set("@configuration", nil)
28
+ end
29
+ end
30
+
31
+ RSpec.configure do |config|
32
+ config.include ConfigurationFromYaml
33
+ end
@@ -0,0 +1,7 @@
1
+ id: 000-000-000-00000
2
+ password: Re@llyL0ngR&om$tr1ng
3
+ short_code: 99999
4
+ program_id: ABC
5
+ phone: 2125551212
6
+ carrier_id: 788
7
+ dr_url: http://www.example.com/drs
metadata ADDED
@@ -0,0 +1,280 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: openmarket
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Isaac Betesh
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-05-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3'
55
+ - !ruby/object:Gem::Dependency
56
+ name: sms_validation
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.0.2
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.0.2
69
+ - !ruby/object:Gem::Dependency
70
+ name: httparty
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: builder
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: |
98
+ # OpenMarket
99
+
100
+ We use HTTParty to send SMS messages using the OpenMarket API. See USAGE below for details.
101
+
102
+ ## Installation
103
+
104
+ Add this line to your application's Gemfile:
105
+
106
+ ```ruby
107
+ gem 'openmarket'
108
+ ```
109
+
110
+ And then execute:
111
+
112
+ $ bundle
113
+
114
+ Or install it yourself as:
115
+
116
+ $ gem install openmarket
117
+
118
+ ## Usage
119
+
120
+ ### Configuratiion
121
+
122
+ The openmarket gem requires you to provide an id, password, program_id and short_code. Configure them before attempting any API calls.
123
+
124
+ ```ruby
125
+ OpenMarket.configure do |config|
126
+ config.id = "000-000-000-00000"
127
+ config.password = "Re@llyL0ngR&om$tr1ng"
128
+ config.program_id = "ABC"
129
+ config.short_code = 99999 # You can override this on an individual message if necessary
130
+ end
131
+ ```
132
+
133
+ Since the openmarket gem depends on sms_validation (https://github.com/betesh/sms_validation/), it is also recommended that you configure sms_validation.
134
+ openmarket uses sms_validation's logger. In a Rails environment, you will probably want to rely on the default configuration,
135
+ but outside of Rails, you will need to configure it if you want any logging:
136
+
137
+ ```ruby
138
+ SmsValidation.configure do |config|
139
+ config.logger = ::Logger.new(STDOUT)
140
+ end
141
+ ```
142
+
143
+ ### API calls
144
+
145
+ `OpenMarket::API` supports 3 API calls: `carrier_lookup`, `send_sms`, and `status`.
146
+
147
+ #### carrier_lookup
148
+
149
+ ```ruby
150
+ require 'openmarket'
151
+ phone = 2125551212
152
+ result = OpenMarket::API.carrier_lookup(phone)
153
+
154
+ # First, make sure the call succeeded
155
+ puts result.code # should be 0
156
+ puts result.description # should be 'No Error'
157
+
158
+ # If the call succeeded, you can check the carrier_id:
159
+ puts result.carrier_id # You are probably most interested in the carrier_id
160
+ puts result.inspect # But there are a lot of other attributes returned by this API call as well
161
+ ```
162
+
163
+ #### send_sms
164
+
165
+ ```ruby
166
+ require 'openmarket'
167
+ phone = 2125551212
168
+ message = "Hello, this is a test of the OpenMarket API"
169
+ result = OpenMarket::API.send_sms(phone, message)
170
+
171
+ # First, make sure the call succeeded
172
+ puts result.code # should be 2
173
+ puts result.description # should be 'Message received.'
174
+
175
+ # Save the ticket ID for later. We'll use this to query the status of the ticket.
176
+ ticket_id = result.ticket_id
177
+
178
+ # Save the carrier ID for later. We'll use this next time we send an SMS to this number.
179
+ carrier_id = result.carrier_id
180
+
181
+ # There are some options you can pass along as well:
182
+ result = OpenMarket::API.send_sms(
183
+ phone,
184
+ message,
185
+
186
+ # If you want to receive DR's, you must pass a dr_url option. If you don't pass a URL, no DR will be sent to the default URL.
187
+ dr_url: "http://www.example.com/drs",
188
+
189
+ # It is highly recommended to pass a carrier_id. If you don't, the openmarket gem will make an extra API call to look up the carrier before sending the message.
190
+ carrier_id: carrier_id, # Remember the carrier ID we saved from the previous SMS?
191
+
192
+ # If you don't want to the short_code you configured above, provide another short_code to send to:
193
+ short_code: 33333,
194
+
195
+ # By default, OpenMarket re-attempts delivery for 3 days. To make OpenMarket give up and report it as a failure sooner, pass a number of minutes you would like to retry for:
196
+ minutes_to_retry: 120, # 2 hours
197
+
198
+ note: "Information that will be passed on to the DR",
199
+
200
+ ticket_id_for_retry: ticket_id # If this is a re-try of a failed ticket.
201
+ )
202
+
203
+ ```
204
+ #### status
205
+
206
+ ```ruby
207
+ require 'openmarket'
208
+ result = OpenMarket::API.status(ticket_id) # Remember the ticket ID we saved from #send_sms?
209
+
210
+ # First, make sure the call succeeded
211
+ puts result.code # should be 0
212
+ puts result.description # should be 'No Error'
213
+
214
+ # Check the result of the SMS message
215
+ puts result.status_code
216
+ puts result.status_description
217
+
218
+ ```
219
+
220
+ ## Contributing
221
+
222
+ 1. Fork it ( https://github.com/betesh/open_market/fork )
223
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
224
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
225
+ 4. Push to the branch (`git push origin my-new-feature`)
226
+ 5. Create a new Pull Request
227
+ email:
228
+ - iybetesh@gmail.com
229
+ executables: []
230
+ extensions: []
231
+ extra_rdoc_files: []
232
+ files:
233
+ - ".gitignore"
234
+ - ".rspec"
235
+ - Gemfile
236
+ - LICENSE.txt
237
+ - README.md
238
+ - Rakefile
239
+ - lib/open_market.rb
240
+ - lib/open_market/api.rb
241
+ - lib/open_market/configuration.rb
242
+ - lib/open_market/dr.rb
243
+ - lib/open_market/mo.rb
244
+ - lib/open_market/response.rb
245
+ - lib/open_market/version.rb
246
+ - lib/openmarket.rb
247
+ - open_market.gemspec
248
+ - spec/api_spec.rb
249
+ - spec/configuration_spec.rb
250
+ - spec/support/configuration_from_yaml.rb
251
+ - spec/support/secrets.yml.example
252
+ homepage: https://github.com/betesh/open_market
253
+ licenses:
254
+ - MIT
255
+ metadata: {}
256
+ post_install_message:
257
+ rdoc_options: []
258
+ require_paths:
259
+ - lib
260
+ required_ruby_version: !ruby/object:Gem::Requirement
261
+ requirements:
262
+ - - ">="
263
+ - !ruby/object:Gem::Version
264
+ version: '0'
265
+ required_rubygems_version: !ruby/object:Gem::Requirement
266
+ requirements:
267
+ - - ">="
268
+ - !ruby/object:Gem::Version
269
+ version: '0'
270
+ requirements: []
271
+ rubyforge_project:
272
+ rubygems_version: 2.4.3
273
+ signing_key:
274
+ specification_version: 4
275
+ summary: Send SMS messages using the OpenMarket API
276
+ test_files:
277
+ - spec/api_spec.rb
278
+ - spec/configuration_spec.rb
279
+ - spec/support/configuration_from_yaml.rb
280
+ - spec/support/secrets.yml.example