0.0
The project is in a healthy, maintained state
Builds CMI payment form parameters and SHA-512 hash; parses server callbacks.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Development

~> 13.0
~> 3.12
~> 1.60
 Project Readme

cmi_gateway

Gem Version

Ruby helpers for CMI (Centre Monétique Interbancaire) 3D Pay Hosting integration: build signed checkout form parameters (SHA-512 + Base64) and parse server callbacks.

  • RubyGems: rubygems.org/gems/cmi_gateway
  • No Rails required — uses only the Ruby standard library.
  • Multiple merchant profiles (e.g. multiple CMI merchant accounts) via CmiGateway.configure.

Installation

Add to your Gemfile:

gem "cmi_gateway", "~> 0.1"

From GitHub instead of RubyGems (edge / contribution):

gem "cmi_gateway", github: "merouaneamqor/cmi_gateway"
# local path during development:
# gem "cmi_gateway", path: "../cmi_gateway"

Then:

bundle install

Configuration

require "cmi_gateway"

CmiGateway.configure do |config|
  config.environment = :test # or :production

  config.client_id = ENV.fetch("CMI_CLIENT_ID", nil)
  config.store_key = ENV.fetch("CMI_STORE_KEY", nil)

  # Named profiles for additional CMI merchant accounts
  config.add_profile(:merchant_a,
    client_id: ENV["CMI_MERCHANT_A_CLIENT_ID"],
    store_key: ENV["CMI_MERCHANT_A_STORE_KEY"])
  config.add_profile(:merchant_b,
    client_id: ENV["CMI_MERCHANT_B_CLIENT_ID"],
    store_key: ENV["CMI_MERCHANT_B_STORE_KEY"])
end

In Rails, put this in config/initializers/cmi_gateway.rb and map config.environment to Rails.env.production?.

Building a checkout (browser POST to CMI)

checkout = CmiGateway::Checkout.new(
  amount: 199.00,
  order_id: "BOOK-123",
  ok_url: "https://example.com/pay/ok",
  fail_url: "https://example.com/pay/fail",
  callback_url: "https://api.example.com/webhooks/cmi",
  email: "user@example.com",
  phone: "0600000000",
  bill_to_name: "Jean Dupont",
  bill_to_street1: "12 Rue Example",
  bill_to_city: "Casablanca",
  bill_to_postal_code: "20000",
  shopurl: "https://example.com",
  lang: "fr",
  tran_type: "PreAuth",
  profile: :default,      # or any named profile (:merchant_a, :merchant_b, ...)
  accent_strip: false,   # set true for stricter accent handling on hash inputs
  extra_params: {}       # merged into signed params (string keys recommended)
)

checkout.action_url # test or production est3Dgate URL
checkout.params     # Hash including "hash" — use as hidden fields in a form POST

Validate before rendering:

checkout.validate! # raises CmiGateway::ValidationError
# or
checkout.valid?
checkout.errors

Low-level hash (tests / custom param sets)

params_without_hash = { "clientid" => "...", "amount" => "10.00", "encoding" => "utf-8" }
digest = CmiGateway::Checkout.build_hash(params_without_hash, "store_key", accent_strip: false)

Parsing callbacks

CMI posts form fields back to your callbackUrl. Success is detected the same way as common CMI samples: ProcReturnCode == "00" or Response case-insensitively equals "Approved".

callback = CmiGateway::Callback.new(request.request_parameters) # Rails
# or CmiGateway::Callback.new(params.to_unsafe_h)

callback.success?
callback.order_id
callback.transaction_id
callback.auth_code
callback.error_code   # when not successful
callback.error_message
callback.raw          # indifferent string-key hash

Security note: This gem does not verify a callback hash from CMI; confirm with your acquirer whether server-to-server verification is required and implement it if so.

Development

bundle install
bundle exec rspec
bundle exec rubocop

Community

License

MIT — see LICENSE.txt.