Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add advanced invoice #8

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## [1.1.0] - 2024-08-12
- add ability make payments' requests more advanced by adding more params into `MonopayRuby::Invoices::AdvancedInvoice::create` method
- change private methods to protected
- modify `request_body` for additional params

## [1.0.0] - 2023-06-27

### Changed
Expand Down
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ source "https://rubygems.org"
gemspec

gem "rake", "~> 13.0"
gem 'activesupport', '~> 7.0'
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

це точно потрібно?

20 changes: 19 additions & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
monopay-ruby (1.0.0)
monopay-ruby (1.1.0)
base64 (~> 0.1.1)
json (~> 2.5)
money (~> 6.13)
Expand All @@ -10,13 +10,26 @@ PATH
GEM
remote: https://rubygems.org/
specs:
activesupport (7.1.3.4)
base64
bigdecimal
concurrent-ruby (~> 1.0, >= 1.0.2)
connection_pool (>= 2.2.5)
drb
i18n (>= 1.6, < 2)
minitest (>= 5.1)
mutex_m
tzinfo (~> 2.0)
base64 (0.1.1)
bigdecimal (3.1.8)
coderay (1.1.3)
concurrent-ruby (1.2.2)
connection_pool (2.4.1)
diff-lcs (1.5.0)
docile (1.4.0)
domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0)
drb (2.2.1)
http-accept (1.7.0)
http-cookie (1.0.5)
domain_name (~> 0.5)
Expand All @@ -27,8 +40,10 @@ GEM
mime-types (3.4.1)
mime-types-data (~> 3.2015)
mime-types-data (3.2023.0218.1)
minitest (5.25.1)
money (6.16.0)
i18n (>= 0.6.4, <= 2)
mutex_m (0.2.0)
netrc (0.11.0)
pry (0.14.2)
coderay (~> 1.1)
Expand Down Expand Up @@ -58,6 +73,8 @@ GEM
simplecov_json_formatter (~> 0.1)
simplecov-html (0.12.3)
simplecov_json_formatter (0.1.4)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
unf (0.1.4)
unf_ext
unf_ext (0.0.8.2)
Expand All @@ -67,6 +84,7 @@ PLATFORMS
x86_64-linux

DEPENDENCIES
activesupport (~> 7.0)
monopay-ruby!
pry (~> 0.14.2)
rake (~> 13.0)
Expand Down
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,29 @@ class PaymentsController < ApplicationController
end
```

## Generate advanced payment request:

```ruby
# app/controllers/payments_controller.rb
class PaymentsController < ApplicationController
def create
payment = MonopayRuby::Invoices::AdvancedInvoice.new(
redirect_url: "https://example.com",
webhook_url: "https://example.com/payments/webhook"
)

if payment.create(amount, additional_params: {})
# your success code processing
else
# your error code processing
# flash[:error] = payment.error_messages
end
end
end
```

`additional_params` - [Read more about params](https://api.monobank.ua/docs/acquiring.html)

### Verify transaction

```ruby
Expand Down
74 changes: 74 additions & 0 deletions lib/monopay-ruby/invoices/advanced_invoice.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
require_relative 'simple_invoice'
require 'active_support/all'

module MonopayRuby
module Invoices
class AdvancedInvoice < MonopayRuby::Invoices::SimpleInvoice
attr_reader :additional_params, :amount

# Create invoice for Monobank API
#
# This method sets up the required instance variables and then calls the `create`
# method from the parent class with the relevant parameters.
#
# @param amount [Numeric] The amount of the payment.
# @param additional_params [Hash] (optional) Additional parameters for the payment.
# - :merchantPaymInfo [Hash] Information about the merchant payment.
# - :destination [String] The destination of the payment.
# - :reference [String] A reference for the payment.
#
# @return [Boolean] The result of the `create` method in the parent class,
# which returns true if invoice was created successfully, false otherwise
#
# @example Create a payment with amount and additional parameters
# create(100, additional_params: { merchantPaymInfo: { destination: "Happy payment", reference: "ref123" } })
def create(amount, additional_params: {})
@amount = amount
@additional_params = additional_params
@destination = @additional_params&.dig(:merchantPaymInfo, :destination)
@reference = @additional_params&.dig(:merchantPaymInfo, :reference)
Comment on lines +28 to +29
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

так це ріквайред параметри, вони не можуть бути відсутні, якщо ж відсутні, то рейзани якусь помилку

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

але ж вони по дефолту ніл, то чому ж вони ріквайред?


super(amount, destination: @destination, reference: @reference)
end

protected

def request_body
current_params = default_params

return current_params.to_json if additional_params.blank?

unless additional_params[:merchantPaymInfo].blank?
current_params[:merchantPaymInfo] = {
reference: @reference,
destination: @destination
}.merge!(additional_params[:merchantPaymInfo].except(:reference, :destination))
end

current_params.merge!(additional_params.except(:merchantPaymInfo))

# It adds and modifies sum and qty params of merchantPaymInfo[basketOrder] parameters if it is present
# It adds and modifies sum and qty params of items parameters if it is present
set_sum_and_qty_params(current_params&.dig(:merchantPaymInfo, :basketOrder))
set_sum_and_qty_params(current_params[:items])
Comment on lines +52 to +53
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

поясни будь ласка, що тут відбувається

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

я спробувала розписати це у коментарях


current_params.to_json
end

# Set sum and qty params
# @param current_param [Array] The current parameter to set sum and qty
# It sets the converted amount or sum parameter as sum and pasted quantity parameter or default value as qty parameters for the current parameter
# @return [Object] It could be Hash or Array or nil. It depends on the current parameter
def set_sum_and_qty_params(current_param)
return if current_param.blank?

current_param.each do |item|
return if item.blank?

item[:sum] = convert_to_cents(item[:sum] || amount)
item[:qty] = item[:qty] || 1
end
end
end
end
end
18 changes: 12 additions & 6 deletions lib/monopay-ruby/invoices/simple_invoice.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,11 @@ def create(amount, destination: nil, reference: nil)
end
end

private
protected

# Request body required for Monobank API
#
# @return [Hash] request body
def request_body
# Default params required for request into Monobank

def default_params
# TODO: add "ccy" and another missing params
# TODO: remove nil valued params
{
Expand All @@ -69,7 +68,14 @@ def request_body
reference: reference,
destination: destination
}
}.to_json
}
end

# Request body required for Monobank API
#
# @return [Hash] request body
def request_body
default_params.to_json
end

def convert_to_cents(amount)
Expand Down
2 changes: 1 addition & 1 deletion lib/monopay-ruby/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# frozen_string_literal: true

module MonopayRuby
VERSION = "1.0.0"
VERSION = "1.1.0"
end
53 changes: 53 additions & 0 deletions spec/lib/invoices/advanced_invoice_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# frozen_string_literal: true

RSpec.describe MonopayRuby::Invoices::AdvancedInvoice do
describe "#new" do
let!(:redirect_url) { "https://redirect.example.com" }
let!(:webhook_url) { "https://webhook.example.com" }

context "with keyword parameters" do
subject { described_class.new(redirect_url: redirect_url, webhook_url: webhook_url) }

it "initializes with correct redirect_url" do
expect(subject.redirect_url).to eq(redirect_url)
end

it "initializes with correct webhook_url" do
expect(subject.webhook_url).to eq(webhook_url)
end
end

context "without keyword parameters" do
subject { described_class.new(redirect_url, webhook_url) }

it "raises an ArgumentError" do
expect { subject }.to raise_error(ArgumentError)
end
end

context "without parameters" do
subject { described_class.new }

it { is_expected.to be_a(described_class) }
end
end

describe "#create" do
context "when request is successful" do
let(:simple_invoice_instance) { described_class.new }
let(:invoice_id) { "p2_9ZgpZVsl3" }
let(:page_url) { "https://pay.mbnk.biz/p2_9ZgpZVsl3" }
let(:basket_order) { { name: "product", qty: 1 } }
let(:additional_params) { { merchantPaymInfo: { basketOrder: [basket_order] }, ccy: 9 } }
let(:response_example) { { "invoiceId": invoice_id, "pageUrl": page_url } }

before do
allow(RestClient).to receive(:post).and_return(double(body: response_example.to_json))
end

it "returns true" do
expect(simple_invoice_instance.create(2000, additional_params: additional_params)).to be_truthy
end
end
end
end
8 changes: 7 additions & 1 deletion spec/lib/invoices/simple_invoice_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,13 @@
context "when request is failed" do
context "with missing token" do
# move this code to shared example or mb shared context
let(:missing_x_token_server_message) { { "errorDescription" => "Missing required header 'X-Token'" } }
let(:missing_x_token_server_message) {
{
"errCode" => "BAD_REQUEST",
"errText" => "Missing required header 'X-Token'",
"errorDescription" => "Missing required header 'X-Token'"
}
}
let(:error_code) { "400 Bad Request" }
let(:missing_x_token_header_error_message) do
[error_code, missing_x_token_server_message].join(", ")
Expand Down