Simple and flexible CloudPayments API client. (https://developers.cloudpayments.ru/, https://developers.cloudpayments.ru/en/)
It's a kind of fork of the cloud_payments gem. The main idea to build a simple and flexible client.
So what is the difference:
CloudPay
- has fewer dependencies. It depends on only the
faradaygem. - doesn't contain value objects for responses. Now, it is the responsibility of an app to provide value objects for all responses.
- has a flexible system of configuration.
- provides an ability to send idempotent requests.
- allows using of namespaces as standalone classes.
- provides a unified interface for API methods.
- has two ways to handle errors: with exceptions and result object.
Add this line to your application's Gemfile:
gem'cloud_pay'And then execute:
$ bundle install
Or install it yourself as:
$ gem install cloud_pay
We can have a few configuration presets. It's easy to define using the CloudPay.configure method. Example:
CloudPay.configuredo |c|
# default configuration presetendCloudPay.confugure(:preset_name)do |c|
# named configuration presetendThen, we can select the needed config when we are creating a client:
config=CloudPay::Config.new(host: '...')CloudPay.client# Client with default configCloudPay.client(:preset_name)# Client with predefined configCloudPay::Client.newCloudPay::Client.new(:preset_name)Also, we can configure the client using an instance of the CloudPay::Config class or hash.
config=CloudPay::Config.new(host: '...')CloudPay.client(host: '...')CloudPay.client(config)CloudPay::Client.new(host: '...')CloudPay::Client.new(config)This way to resolve config is also applied to all API namespaces and webhooks handler.
# NamespacesCloudPay::Payments::Tokens.newCloudPay::Payments::Tokens.new(:preset_name)CloudPay::Payments::Tokens.new(host: '...')CloudPay::Payments::Tokens.new(config)# WebhooksCloudPay::Webhooks.newCloudPay::Webhooks.new(:preset_name)CloudPay::Webhooks.new(host: '...')CloudPay::Webhooks.new(config)It's also possible to switch the default config for some block of code. It can be used in middlewares, for example.
CloudPay.with_config(Rails.env.to_sym)doCloudPay.client# Client with `:development`, `:test` or `:production` configendclassCloudPayMiddlewaredefcall(env)config=config_name(env)CloudPay.with_config(config)do@app.call(env)endendprivatedefconfig_name(env)# choose predefined config name according to some conditionsendendThe example above allows switching configs according to some conditions: domain name, headers, or some other. So when we use CloudPay::Client.new in the app, it will use config defined in the middleware.
It's also possible to use a simple hash to initialize the client (or any namespace). Such a solution allows implementing multitenancy systems when the config is a part of application data and cannot be predefined in the config stage.
CloudPay::Client.new(public_key: '...',secret_key: '...')Note: All undefined options will be inherit from default config when we use hash as a config. That means we can override some options ad-hoc:
CloudPay::Client.new(public_key: '...',secret_key: '...').config# #<CloudPay::Config:0x00007f8fd1af04e8# @connection_block=nil,# @connection_options={},# @host="https://api.cloudpayments.ru",# @log=false,# @public_key="...",# @secret_key="...">CloudPay.with_config(:test)doCloudPay::Client.new(public_key: '...',secret_key: '...').config# #<CloudPay::Config:0x00007f8fd1af04e8# @connection_block=nil,# @connection_options={},# @host="http://localhost:9292",# @log=false,# @public_key="...",# @secret_key="...">endThere are two ways to handle errors in the gem: using the result object and using exceptions. We use exceptions when we call a method with an exclamation mark (!), and we use the result object otherwise.
The result object has a simple interface that consists of only three meaningful methods: success?, model, and error_message. Every API method returns this result object so that we can check the result of the request. Look at the example below:
result=CloudPay.client.payments.cards.charge(params)ifresult.success?# do something with data using the `model` method.# pp result.modelelse# Handle an error.# You can use the `error_message` method to get a real error message or# You can use the `model` method to get response data.# pp result.model# pp result.error_messageendUsing an exclamation mark forces the client to raise an exception in case of an unsuccessful response. The specific exception depends on the type of response.
It can be a
CloulPay::ValidationErrorexception if the request has missing attributes.It can be an exception inherited from
CloudPay::ServerErrorin theCloudPay::HttpErrorsnamespace if an HTTP request is ended with any status code more than or equal to 300.It can be an exception inherited from
CloudPay::ReasonedGatewayErrorinCloudPay::GatewayErrorsnamespace ifReasonCodekey in theModelobject has some meaningful code.it can be a
CloudPay::GatewayErrorexception if the gem cannot determine a specific reason for an error.
It can also raise other exceptions that depend on the HTTP transport, such as faraday's errors or network errors.
beginmodel=CloudPay.client.payments.cards.charge!(params,idempotency_key: idempotency_key)# do something with datarescueCloudPay::ValidationError=>e# handle validation errorsrescue *CloudPay.retryable_errors=>e# put in queue to retry laterrescueCloudPay::Error=>e# handle the rest of errorsendThe gem provides a list of retryable errors. This list is needed to catch exceptions that can be the reason for retrying the request. We can redefine this list using the CloudPay.set_retryable_errors method.
CloudPay.set_retryable_errors([CloudPay::GatewayErrors::FormatError,CloudPay::GatewayErrors::InsufficientFunds,CloudPay::GatewayErrors::Timeout,CloudPay::GatewayErrors::CannotReachNetwork,CloudPay::GatewayErrors::SystemError,Faraday::ConnectionFailed,Faraday::TimeoutError])Note: Use the idempotency_key option if you intend to retry requests. It can lead to multiple write-offs of funds if you retry your request without the idempotency key.
CloudPay.client.payments.cards.charge(params,idempotency_key: 'some-unique-id')It should be an unique value for every separate payment.
This gem supports the following API methods:
Test method - The method to test the interaction with the API and returns
trueorfalse.CloudPay.client.test
Payment by a Cryptogram - The method to make a payment by a cryptogram generated by the Checkout script, Apple Pay, or Google Pay.
CloudPay.client.payments.cards.charge(params)CloudPay.client.payments.cards.auth(params)# orns=CloudPay::Payments::Cards.newns.charge(params)ns.auth(params)
3-D Secure Processing - The method to complete the payment when 3-D Secure authentication is used.
CloudPay.client.payments.cards.post3ds(params)# orns=CloudPay::Payments::Cards.newns.post3ds(id,params)
Payment by a Token (Recurring) - The method to make a payment by a token received either with payment by cryptogram or via Pay notification.
CloudPay.client.payments.tokens.charge(params)CloudPay.client.payments.tokens.auth(params)# orns=CloudPay::Payments::Tokens.newns.charge(params)ns.auth(params)
Payment Confirmation - For payments made by the DMS scheme, you need to confirm a transaction. Confirmation can be done through the Back office or via calling this API method.
CloudPay.client.payments.confirm(params)# orns=CloudPay::Payments.newns.confirm(params)
Payment Cancellation - Cancellation of payment can be executed through your Back Office or by calling the API method.
CloudPay.client.payments.void(id)# orns=CloudPay::Payments.newns.void(id)
It has a
cancelalias.CloudPay.client.payments.cancel(id)# orns=CloudPay::Payments.newns.cancel(id)
Refund - Refund can be executed through your Back Office or by calling the API method.
CloudPay.client.payments.refund(id,params)# orns=CloudPay::Payments.newns.refund(id,params)
Payout by a Cryptogram - Payment by a cryptogram can be executed through the calling of this API method.
CloudPay.client.payments.cards.topup(params)# orns=CloudPay::Payments::Cards.newns.topup(params)
Payout by a Token - Payout by a token can be executed through the calling of the following API method.
CloudPay.client.payments.tokens.topup(params)# orns=CloudPay::Payments::Tokens.newns.topup(params)
Transaction Details - The method returns a transaction details.
CloudPay.client.payments.get(id)# orns=CloudPay::Payments.newns.get(id)
Payment Status Check - The method for payment searching, which returns its status.
CloudPay.client.payments.find(invoice_id)# orns=CloudPay::Payments.newns.find(invoice_id)
This method has two versions. It performs first version by default. However, you can specify the version as an
:versionoption in the last argument:CloudPay.client.payments.find(invoice_id,version: 2)# orns=CloudPay::Payments.newns.find(invoice_id,version: 2)
Transaction List - The method to get a list of transactions for a day.
CloudPay.client.payments.list(params)# orns=CloudPay::Payments.newns.list(params)
Token List - The method to get a list of all payment tokens of CloudPayments.
CloudPay.client.payments.tokens.list# orns=CloudPay::Payments::Tokens.newns.list
Creation of Subscriptions on Recurrent Payments - The method to create subscriptions on recurrent payments.
CloudPay.client.subscriptions.create(params)# orns=CloudPay::Subscriptions.newns.create(params)
Subscription Details - The method to get an information about subscription status.
CloudPay.client.subscriptions.get(id)# orns=CloudPay::Subscriptions.newns.get(id)
Subscriptions Search - The method to get a list of subscriptions for a particular account.
CloudPay.client.subscriptions.find(account_id)# orns=CloudPay::Subscriptions.newns.find(account_id)
Recurrent Payments Subscription Change - The method to change a subscription on recurrent payments.
CloudPay.client.subscriptions.update(params)# orns=CloudPay::Subscriptions.newns.update(params)
Subscription on Recurrent Payments Cancellation - The method to cancel subscription on recurrent payments.
CloudPay.client.subscriptions.cancel(id)# orns=CloudPay::Subscriptions.newns.cancel(id)
Invoice Creation on Email - The method to generate a payment link and sending it to a payer's email.
CloudPay.client.orders.create(params)# orns=CloudPay::Orders.newns.create(params)
Created Invoice Cancellation - The method to create invoice cancellation.
CloudPay.client.orders.cancel(id)# orns=CloudPay::Orders.newns.cancel(id)
View of Notification Settings - The method to view notification settings.
CloudPay.client.notifications.get(type)# orns=CloudPay::Notifications.newns.get(type)
Change of Notification Settings - The method to change notification settings.
CloudPay.client.notifications.update(type,params)# orns=CloudPay::Notifications.newns.update(type,params)
Start of Apple Pay Session - Start of a session is required to take payments via Apple Pay on Web.
CloudPay.client.apple_pay.start_session(params)# orns=CloudPay::ApplePay.newns.start_session(params)
CloudKassir: Register Fiscalization - The method of launching a cash register to the fiscal operation mode.
CloudPay.client.kassir.fiscalize(params)# orns=CloudPay::Kassir.newns.fiscalize(params)
CloudKassir: Online Receipt Generation - Method of an online receipt generation.
CloudPay.client.kassir.receipt.create(params)# orns=CloudPay::Kassir::Receipt.newns.create(params)
CloudKassir: Receipt Status Request - Method of getting the receipt status.
CloudPay.client.kassir.receipt.status(id)# orns=CloudPay::Kassir::Receipt.newns.status(id)
CloudKassir: Receipt Details Request - Method of getting the receipt details.
CloudPay.client.kassir.receipt.get(id)# orns=CloudPay::Kassir::Receipt.newns.get(id)
CloudKassir: Cash Register State Change - The method of manual control of the state of the cash register. The cash register can be turned off (for maintenance) and activated (put into operation).
CloudPay.client.kassir.state.update(params)# orns=CloudPay::Kassir::State.newns.update(params)
CloudKassir: Receiving Cash Register Data - Method of receiving cash register data.
CloudPay.client.kassir.state.get(params)# orns=CloudPay::Kassir::State.newns.get(params)
- Coming soon -
Bug reports and pull requests are welcome on GitHub at https://github.com/undr/cloud_pay.