Skip to content

ignacio-chiazzo/ruby_whatsapp_sdk

Repository files navigation

Ruby Whatsapp SDK

Gem Version CircleCI

The SDK provides a set of operations and classes to use the Whatsapp API. Send stickers, messages, audio, videos, locations, react and reply to messages or just ask for the phone numbers through this library in a few steps!

Demo

MessageAPIDemo.mov

Check the Ruby on Rails Whatsapp example repository that uses this library to send messages.

Installation

Add this line to your application's Gemfile:

gem 'whatsapp_sdk'

And then execute:

$ bundle

Or install it yourself as:

$ gem install whatsapp_sdk

Quick Start

There are three primary resources, Messages, Media and PhoneNumbers. Messages allows users to send any message (text, audio, location, video, image, etc.). Media allows users to manage media, and Phone Numbers enable clients to query the associated phone numbers.

To use Messages, Media or PhoneNumbers, you need to initialize the Client that contains auth information. There are two ways to do it.

Option 1) Use an initializer

# config/initializers/whatsapp_sdk.rb
WhatsappSdk.configure do |config|
  config.access_token = ACCESS_TOKEN
  config.api_version = API_VERSION
  config.logger = Logger.new(STDOUT) # optional, Faraday logger to attach
  config.logger_options = { bodies: true } # optional, they are all valid logger_options for Faraday
end

Notes:

  • Optionally, you can specify the desired API version to use (defaults to the latest version if omitted). Available API version can be found here.
  • You can attach a logger. More Details on Faraday Logger Options are here.

Option 2) Create a Client instance :

# without
client = WhatsappSdk::Api::Client.new("<ACCESS TOKEN>") # replace this with a valid access token

# OR optionally use a logger, api_version and
logger = Logger.new(STDOUT)
logger_options = { bodies: true }
client = WhatsappSdk::Api::Client.new("<ACCESS TOKEN>", "<API VERSION>", logger, logger_options)

Set up a Meta app

1) Create a Meta Business app Screen Shot 2022-09-05 at 11 03 47 AM
2) Add Whatsapp to your Application Screen Shot 2022-09-05 at 11 05 43 AM
3) Add a phone number to your account Screen Shot 2022-09-05 at 11 09 22 AM

Try sending a message to your phone in the UI.

4) Copy the ACCESS_TOKEN, the SENDER_ID, the BUSINESS_ID and the RECIPIENT_NUMBER Screen Shot 2022-09-05 at 11 13 24 AM
5) Use the GEM to interact with Whatsapp

Example:

  1. Install the gem by running gem install whatsapp_sdk in the gem.
  2. Open the irb terminal by running irb
  3. require "whatsapp_sdk"
  4. Set up the ACCESS_TOKEN, the SENDER_ID, the BUSINESS_ID and the RECIPIENT_NUMBER in variables.
ACCESS_TOKEN = "EAAZAvvr0DZBs0BABRLF8zohP5Epc6pyNu"
BUSINESS_ID = 1213141516171819
SENDER_ID = 1234567891011
RECIPIENT_NUMBER = 12398765432
  1. Configure the Client by running
WhatsappSdk.configure do |config|
  config.access_token = ACCESS_TOKEN
end
  1. Try the Phone Numbers API or Messages API

Phone Numbers API

registered_number = client.phone_numbers.registered_number(SENDER_ID)

Messages API

message_sent = client.messages.send_text(sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER,
                                      message: "Hey there! it's Whatsapp Ruby SDK")

Check the example.rb file for more examples.

Sneak Peek

client = WhatsappSdk::Api::Client.new("<ACCESS TOKEN>") # replace this with a valid access token

client.phone_numbers.register_number(SENDER_ID, 123456) # register the phone number to uplaod media and send message from.

# send a text and a location
client.messages.send_text(sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER,message: "Hey there! it's Whatsapp Ruby SDK")

client.messages.send_location(sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, longitude: -75.6898604, latitude: 45.4192206, name: "Ignacio", address: "My house")

# upload a photo and send it
image = client.media.upload(sender_id: SENDER_ID, file_path: "test/fixtures/assets/whatsapp.png", type: "image/png")image = client.media.get(media_id: uploaded_media.id)
client.messages.send_image(sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, image_id: image.id)

# upload a sticker and send it
sticker = client.media.upload(sender_id: SENDER_ID, file_path: "test/fixtures/assets/sticker.webp", type: "image/webp")
client.messages.send_sticker(sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, sticker_id: sticker.id)

APIs

Templates

# Get list of templates
client.templates.list(business_id: BUSINESS_ID)

# Get Message Template Namespace
# The message template namespace is required to send messages using the message templates.
client.templates.get_message_template_namespace(business_id: BUSINESS_ID)

# Create a template
client.templates.create(
  business_id: BUSINESS_ID, name: "seasonal_promotion", language: "en_US", category: "MARKETING",
  components_json: components_json, allow_category_change: true
)

# Delete a template
client.templates.delete(business_id: BUSINESS_ID, name: "my_name") # delete by name

Business Profile API

# Get the details of your business
client.business_profiles.get(phone_number_id)

# Update the details of your business
client.business_profiles.update(phone_number_id: SENDER_ID, params: { about: "A very cool business" } )

Phone numbers API

# Get the list of phone numbers registered
client.phone_numbers.list(business_id)

# Get the a phone number by id
client.phone_numbers.get(phone_number_id)

# Register a phone number
client.phone_numbers.register_number(phone_number_id, pin)

# Deregister a phone number
client.phone_numbers.deregister_number(phone_number_id)

Media API

# Upload a media
client.media.upload(sender_id: SENDER_ID, file_path: "tmp/whatsapp.png", type: "image/png")

# Get a media
media = client.media.get(media_id: MEDIA_ID)

# Download media
client.media.download(url: MEDIA_URL, file_path: 'tmp/downloaded_whatsapp.png', media_type: "image/png")

# Delete a media
client.media.delete(media_id: MEDIA_ID)

Messages API

# Send a text message
client.messages.send_text(sender_id: 1234, recipient_number: 112345678, message: "hola")

# Read a message
client.messages.read_message(sender_id: 1234, message_id: "wamid.HBgLMTM0M12345678910=")

# Note: To get the `message_id` you can set up [Webhooks](https://developers.facebook.com/docs/whatsapp/cloud-api/webhooks/components) that will listen and fire an event when a message is received.

# Send a reaction to message
#   To send a reaction to a message, you need to obtain the message id and look for the emoji's unicode you want to use.
client.messages.send_reaction(sender_id: 123_123, recipient_number: 56_789, message_id: "12345", emoji: "\u{1f550}")
client.messages.send_reaction(sender_id: 123_123, recipient_number: 56_789, message_id: "12345", emoji: "⛄️")

# Reply to a message
# To reply to a message, just include the id of the message in the `client.messages` methods. For example, to reply to a text message include the following:
client.messages.send_text(sender_id: 123_123, recipient_number: 56_789, message: "I'm a reply", message_id: "wamid.1234")

# Send a location message
client.messages.send_location(
  sender_id: 123123, recipient_number: 56789,
  longitude: 45.4215, latitude: 75.6972, name: "nacho", address: "141 cooper street"
)

# Send an image message
#  It uses a link or an image_id.
#  with a link
client.messages.send_image(sender_id: 123123, recipient_number: 56789, link: "image_link", caption: "Ignacio Chiazzo Profile")

# with an image id
client.messages.send_image(sender_id: 123123, recipient_number: 56789, image_id: "1234", caption: "Ignacio Chiazzo Profile")


# Send an audio message
# It uses a link or an audio_id.
# with a link
client.messages.send_audio(sender_id: 123123, recipient_number: 56789, link: "audio_link")

# with an audio id
client.messages.send_audio(sender_id: 123123, recipient_number: 56789, audio_id: "1234")

# Send a document message
# It uses a link or a document_id.
# with a link
client.messages.send_document(sender_id: 123123, recipient_number: 56789, link: "document_link", caption: "Ignacio Chiazzo")

# with a document id
client.messages.send_document(sender_id: 123123, recipient_number: 56789, document_id: "1234", caption: "Ignacio Chiazzo")
# Note, you can specify the filename via argument [`filename`](https://developers.facebook.com/docs/whatsapp/cloud-api/reference/messages). 

# Send a sticker message
#  It could use a link or a sticker_id.
#  with a link
client.messages.send_sticker(sender_id: 123123, recipient_number: 56789, link: "link")

# with a sticker_id
client.messages.send_sticker(sender_id: 123123, recipient_number: 56789, sticker_id: "1234")

# Send contacts message
# To send a contact, you need to create a Contact instance object that contain objects embedded like `addresses`, `birthday`, `emails`, `name`, `org`. See this [guide](/test/contact_helper.rb) to learn how to create contacts objects.
client.messages.send_contacts(sender_id: 123123, recipient_number: 56789, contacts: [create_contact(params)])

# Alternatively, you could pass a plain json like this:
client.messages.send_contacts(sender_id: 123123, recipient_number: 56789, contacts_json: {...})

# Send a template message
# WhatsApp message templates are specific message formats that businesses use to send out notifications or customer care messages to people that have opted in to notifications. Messages can include appointment reminders, shipping information, issue resolution or payment updates.

# Before sending a message template, you need to create one. visit the [Official API Documentation](https://developers.facebook.com/docs/whatsapp/cloud-api/guides/send-message-templates)
Component's example
currency = WhatsappSdk::Resource::Currency.new(code: "USD", amount: 1000, fallback_value: "1000")
date_time = WhatsappSdk::Resource::DateTime.new(fallback_value: "2020-01-01T00:00:00Z")
media_component = WhatsappSdk::Resource::MediaComponent.new(type: "image", link: "http(s)://URL")
location = WhatsappSdk::Resource::Location.new(
  latitude: 25.779510, longitude: -80.338631, name: "miami store", address: "820 nw 87th ave, miami, fl"
)

parameter_image = WhatsappSdk::Resource::ParameterObject.new(type: "image", image: media_component)
parameter_text = WhatsappSdk::Resource::ParameterObject.new(type: "text", text: "TEXT_STRING")
parameter_currency = WhatsappSdk::Resource::ParameterObject.new(type: "currency", currency: currency)
parameter_date_time = WhatsappSdk::Resource::ParameterObject.new(type: "date_time", date_time: date_time)
parameter_location = WhatsappSdk::Resource::ParameterObject.new(type: "location", location: location)

header_component = WhatsappSdk::Resource::Component.new(type: "header", parameters: [parameter_image])

body_component = WhatsappSdk::Resource::Component.new(
  type: "body", 
  parameters: [parameter_text, parameter_currency, parameter_date_time]
)

button_component1 = WhatsappSdk::Resource::Component.new(
  type: "button",
  index: 0,
  sub_type: "quick_reply",
  parameters: [
    WhatsappSdk::Resource::ButtonParameter.new(type: "payload", payload: "PAYLOAD")
  ]
)

button_component2 = WhatsappSdk::Resource::Component.new(
  type: "button",
  index: 1,
  sub_type: "quick_reply",
  parameters: [
    WhatsappSdk::Resource::ButtonParameter.new(type: "payload", payload: "PAYLOAD")
  ]
)

location_component = WhatsappSdk::Resource::Component.new(type: "header", parameters: [parameter_location])
client.messages.send_template(
  sender_id: 12_345, recipient_number: 12345678, name: "hello_world", language: "en_US", components: [...]
)

Alternatively, you could pass a plain json like this:

client.messages.send_template(sender_id: 12_345, recipient_number: 12345678, name: "hello_world", language: "en_US", components_json: [{...}])

Send interactive messages Visit the Official API Documentation

List Message's example
interactive_header = WhatsappSdk::Resource::InteractiveHeader.new(type: "text", text: "I am the header!")
interactive_body = WhatsappSdk::Resource::InteractiveBody.new(text: "I am the body!")
interactive_footer = WhatsappSdk::Resource::InteractiveFooter.new(text: "I am the footer!")
interactive_action = WhatsappSdk::Resource::InteractiveAction.new(type: "list_message")

interactive_action.button = "I am the button CTA"

interactive_section_1 = WhatsappSdk::Resource::InteractiveActionSection.new(title: "I am the section 1")
interactive_section_1_row_1 = WhatsappSdk::Resource::InteractiveActionSectionRow.new(
  title: "I am the row 1 title",
  id: "section_1_row_1",
  description: "I am the optional section 1 row 1 description"
)
interactive_section_1.add_row(interactive_section_1_row_1)
interactive_action.add_section(interactive_section_1)

interactive_list_messages = WhatsappSdk::Resource::Interactive.new(
  type: "list",
  header: interactive_header,
  body: interactive_body,
  footer: interactive_footer,
  action: interactive_action
)

client.messages.send_interactive_list_messages(
  sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER,
  interactive: interactive_list_messages
)

Alternatively, you could pass a plain json like this:

client.messages.send_interactive_list_messages(
  sender_id: 12_345, recipient_number: 1234567890
  interactive_json: {...}
)
Reply Button's example
interactive_header = WhatsappSdk::Resource::InteractiveHeader.new(type: "text", text: "I am the header!")
interactive_body = WhatsappSdk::Resource::InteractiveBody.new(text: "I am the body!")
interactive_footer = WhatsappSdk::Resource::InteractiveFooter.new(text: "I am the footer!")

interactive_action = WhatsappSdk::Resource::InteractiveAction.new(type: "reply_button")
interactive_reply_button_1 = WhatsappSdk::Resource::InteractiveActionReplyButton.new(
  title: "I am the reply button 1",
  id: "button_1"
)
interactive_action.add_reply_button(interactive_reply_button_1)

interactive_reply_button_2 = WhatsappSdk::Resource::InteractiveActionReplyButton.new(
  title: "I am the reply button 2",
  id: "button_2"
)
interactive_action.add_reply_button(interactive_reply_button_2)

interactive_reply_buttons = WhatsappSdk::Resource::Interactive.new(
  type: "reply_button",
  header: interactive_header,
  body: interactive_body,
  footer: interactive_footer,
  action: interactive_action
)

client.messages.send_interactive_reply_buttons(
  sender_id: 12_345, recipient_number: 1234567890,
  interactive: interactive_reply_buttons
)

Alternative, you could pass a plain json like this:

client.messages.send_interactive_reply_buttons(
  sender_id: 12_345, recipient_number: 1234567890
  interactive_json: {...}
)

Errors

If the API returns an error then an exception WhatsappSdk::Api::Responses::HttpResponseError is raised. The object contains information returned by the Cloud API. For more information about the potential error check the official documentation.

Examples

Visit the example file with examples to call the API in a single file.

Whatsapp Cloud API

Troubleshooting

If you try to send a text message directly without a message template created and approved in your Meta control panel, you can't start a chat with other people. But if you receive a message before, it's possible to send a message.

If the API response is still success, but the message is not delivered:

  • ensure the device you're sending the message to is using a supported Whatsapp version. Check documentation. Try also replying a message to the number you are registered on your Whatsapp.
  • Ensure your Meta App uses an API version greater than or equal to v.14.
  • Ensure that the Panel in the Facebook dashboard doesn't display any errors.

Note: Sometimes the messages are delayed; see Meta documentation.

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake test to run the tests.

Run ' bundle exec rake install ' to install this gem onto your local machine. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.

Run all the tests

  • Unit tests: Run rake test
  • Sorbet Typecheck: run srb tc
  • Linters: bundle exec rubocop

To update the Cloud API version update the version in lib/whatsapp_sdk/api/api_configuration.rb. Check the Cloud API changelog for API udpates.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/ignacio-chiazzo/ruby_whatsapp_sdk This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.

If you want a feature to be implemented in the gem, please, open an issue and we will take a look as soon as we can.

Do you want to contribute and are unsure where to start? Ping me on Twitter, and I will help you!

Check Contributing file.

License

The gem is available as open source under the terms of the MIT License.