├── .gitignore ├── .rspec ├── .travis.yml ├── CODE_OF_CONDUCT.md ├── Gemfile ├── LICENSE.txt ├── README.md ├── Rakefile ├── bin ├── console └── setup ├── lib ├── neon_api.rb └── neon_api │ ├── client.rb │ ├── configuration.rb │ ├── methods.rb │ ├── methods │ ├── balance.rb │ ├── cancel_payment.rb │ ├── confirm_payment.rb │ ├── confirm_transfer.rb │ ├── create_payer.rb │ ├── create_sub_account.rb │ ├── generate_payment_slip_to_payer.rb │ ├── get_account_types.rb │ ├── get_accounts.rb │ ├── get_banks.rb │ ├── get_finality.rb │ ├── get_payers.rb │ ├── get_payment.rb │ ├── get_payment_slip_by_payer.rb │ ├── get_payment_slip_by_sub_account.rb │ ├── get_statement.rb │ ├── send_payment.rb │ └── send_transfer.rb │ └── version.rb ├── neon_api.gemspec └── spec ├── neon_api ├── client_spec.rb └── methods │ ├── confirm_transfer_spec.rb │ ├── get_statement_spec.rb │ └── send_transfer_spec.rb ├── neon_api_spec.rb └── spec_helper.rb /.gitignore: -------------------------------------------------------------------------------- 1 | /.bundle/ 2 | /.yardoc 3 | /Gemfile.lock 4 | /_yardoc/ 5 | /coverage/ 6 | /doc/ 7 | /pkg/ 8 | /spec/reports/ 9 | /tmp/ 10 | 11 | # rspec failure tracking 12 | .rspec_status 13 | 14 | 15 | /.env 16 | .idea 17 | /public_decrypt.pem 18 | /public_encrypt.pem 19 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --format documentation 2 | --color 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: ruby 3 | rvm: 4 | - 2.4.1 5 | before_install: gem install bundler -v 1.15.3 6 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level of experience, 9 | nationality, personal appearance, race, religion, or sexual identity and 10 | orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at ghamdan.eng@gmail.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at [http://contributor-covenant.org/version/1/4][version] 72 | 73 | [homepage]: http://contributor-covenant.org 74 | [version]: http://contributor-covenant.org/version/1/4/ 75 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | git_source(:github) {|repo_name| "https://github.com/#{repo_name}" } 4 | 5 | gemspec 6 | 7 | gem 'pry' 8 | gem 'awesome_print' 9 | gem 'rest-client' 10 | gem 'aes' 11 | gem 'openssl' 12 | gem 'dotenv' 13 | gem 'rake' -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Gabriel Hamdan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Gem Version](https://badge.fury.io/rb/neon_api.svg)](https://badge.fury.io/rb/neon_api) 2 | 3 | 4 | # NeonApi 5 | 6 | Gem used to integrate any rails system to Bank NeonApi 7 | 8 | ## Installation 9 | 10 | Add this line to your application's Gemfile: 11 | 12 | ```ruby 13 | gem 'neon_api' 14 | ``` 15 | 16 | And then execute: 17 | 18 | $ bundle install 19 | 20 | Or install it yourself as: 21 | 22 | $ gem install neon_api 23 | 24 | ## Usage 25 | 26 | Initialize the system on its own initializer file: 27 | 28 | config/initializer/neon_api.rb 29 | ```ruby 30 | NeonApi.configure do |config| 31 | config.token = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' 32 | config.username = 'user@name.com' 33 | config.password = 'password' 34 | config.proxy = 'http://dasd:asd@asd.asd.com:80' # neon needs a fixed outbound ip 35 | config.encrypt_pem = 'public_encrypt.pem' # path to your encryption pem 36 | config.decrypt_pem = 'public_decrypt.pem' # path to your decryption pem 37 | config.environment = :development # environment :development or :production 38 | end 39 | ``` 40 | 41 | PS: YOU WILL NEED TO CHANGE YOUR KEYS FROM XML TO PEM!!! THIS IS IMPORTANT! 42 | you can use this(https://superdry.apphb.com/tools/online-rsa-key-converter) for this purpose. 43 | 44 | Use the bank methods in order to create or manage your transactions: 45 | 46 | Get Balance: 47 | ```ruby 48 | NeonApi::Balance.get_balance 49 | ``` 50 | 51 | Create Payer: 52 | ```ruby 53 | NeonApi::CreatePayer.create(bank_acc_id, name, cpf, email, address, number, complement, zipcode, city, state, country) 54 | ``` 55 | 56 | CancelPayment: 57 | ```ruby 58 | NeonApi::CancelPayment.create(list_uniq_id) 59 | ``` 60 | 61 | ConfirmPayment 62 | ```ruby 63 | NeonApi::ConfirmPayment.create(list_uniq_id) 64 | ``` 65 | 66 | Generate Payment Slip 67 | ```ruby 68 | GeneratePaymentSlipToPayer.create(bank_acc_id, name, cpf, email, address, number, complement, zipcode, city, state, country) 69 | ``` 70 | More methods (and their arguments) can be found on methods folder 71 | 72 | ## Development 73 | 74 | I made this for myself, in a hurry. It works but it's not tested or well documented. Sorry for that. 75 | 76 | ## Contributing 77 | BUUUUUT... You can help!!!! 78 | Help me to test and document it. It's good for everybody. (please rspec) 79 | 80 | Bug reports and pull requests are welcome on GitHub at https://github.com/Hamdan85/neon_api. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct. 81 | 82 | ## License 83 | 84 | The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT). 85 | 86 | ## Code of Conduct 87 | 88 | Everyone interacting in the NeonApi project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/neon_api/blob/master/CODE_OF_CONDUCT.md). 89 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "bundler/gem_tasks" 2 | require "rspec/core/rake_task" 3 | 4 | RSpec::Core::RakeTask.new(:spec) 5 | 6 | task :default => :spec 7 | -------------------------------------------------------------------------------- /bin/console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require "bundler/setup" 4 | require "neon_api" 5 | 6 | # You can add fixtures and/or initialization code here to make experimenting 7 | # with your gem easier. You can also use a different console, if you like. 8 | 9 | # (If you use this, don't forget to add pry to your Gemfile!) 10 | # require "pry" 11 | # Pry.start 12 | 13 | require "irb" 14 | require "pry" 15 | require "dotenv/load" 16 | IRB.start(__FILE__) 17 | #Pry.start -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | IFS=$'\n\t' 4 | set -vx 5 | 6 | bundle install 7 | 8 | # Do any other automated setup that you need to do here 9 | -------------------------------------------------------------------------------- /lib/neon_api.rb: -------------------------------------------------------------------------------- 1 | require "neon_api/version" 2 | require "neon_api/configuration" 3 | require "neon_api/client" 4 | 5 | require "neon_api/methods" 6 | module NeonApi 7 | 8 | end 9 | -------------------------------------------------------------------------------- /lib/neon_api/client.rb: -------------------------------------------------------------------------------- 1 | module NeonApi 2 | require "rest-client" 3 | require "openssl" 4 | require "aes" 5 | require "base64" 6 | require "json" 7 | 8 | class Client 9 | attr_accessor :url, :environment, :payload, :token, :last_authenticated_at, :response, 10 | :auth_token, :aes_key, :aes_iv, :expire_time, :client_id, :bank_account, :response, :base_url 11 | 12 | attr_reader :time_klass 13 | 14 | def initialize(environment, token, login, password, encrypt_pem, decrypt_pem, proxy) 15 | @environment = environment 16 | @token = token 17 | @username = login 18 | @password = password 19 | @encrypt_pem = encrypt_pem 20 | @decrypt_pem = decrypt_pem 21 | @proxy = proxy 22 | @time_klass = Time.respond_to?(:zone) ? Time.zone : Time 23 | @expire_time = time_klass.now - 3600 # initialize in an expired condition to force first authentication 24 | 25 | RestClient.proxy = @proxy if @proxy 26 | end 27 | 28 | def authenticate 29 | @last_authenticated_at = time_klass.now 30 | 31 | request = begin 32 | RestClient::Request.execute(method: :post, url: "#{base_url}/V1/Client/Authentication", 33 | payload: { "Data": encrypted_payload(authentication: true) }, headers: auth_headers) 34 | rescue RestClient::ExceptionWithResponse => err 35 | err.response 36 | end 37 | 38 | if request.code == 200 39 | update_auth JSON.parse(decrypt_payload(payload: JSON.parse(request.body)["Data"], authentication: true)) 40 | else 41 | raise request 42 | end 43 | end 44 | 45 | def send_request(object, url) 46 | 47 | authenticate if time_klass.now > expire_time 48 | 49 | request = begin 50 | RestClient::Request.execute(method: :post, url: base_url + url, 51 | payload: { "Data": encrypted_payload(payload: object) }, headers: headers) 52 | rescue RestClient::ExceptionWithResponse => err 53 | err.response 54 | end 55 | 56 | if request.code != 500 57 | @response = JSON.parse(decrypt_payload(payload: JSON.parse(request.body)['Data'])) 58 | else 59 | @response = request 60 | end 61 | 62 | return @response 63 | end 64 | 65 | def production? 66 | @environment == :production 67 | end 68 | 69 | def auth_headers 70 | { 71 | "Cache-Control": "no-cache", 72 | "Content-Type": "application/x-www-form-urlencoded", 73 | "Token": token 74 | } 75 | end 76 | 77 | def headers 78 | { 79 | "Cache-Control": "no-cache", 80 | "Content-Type": "application/x-www-form-urlencoded", 81 | "Token": auth_token 82 | } 83 | end 84 | 85 | def update_auth(auth_answer) 86 | @data_return = auth_answer['DataReturn'] 87 | @auth_token = auth_answer['DataReturn']['Token'] 88 | @aes_key = auth_answer['DataReturn']['AESKey'] 89 | @aes_iv = auth_answer['DataReturn']['AESIV'] 90 | @expire_time = time_klass.at(auth_answer['DataReturn']['DataExpiracao'].gsub(/[^\d]/, '').to_i) 91 | @client_id = auth_answer['DataReturn']['ClientId'] 92 | @bank_account = auth_answer['DataReturn']['BankAccountId'] 93 | end 94 | 95 | def encrypted_payload(payload: self.payload, authentication: false) 96 | if authentication 97 | Base64.encode64 OpenSSL::PKey::RSA.new(File.read(@encrypt_pem)).public_encrypt(payload) 98 | else 99 | Base64.encode64(aes_cipher(:encrypt, payload)) 100 | end 101 | end 102 | 103 | def decrypt_payload(payload:, authentication: false) 104 | if authentication 105 | OpenSSL::PKey::RSA.new(File.read(@decrypt_pem)).private_decrypt(Base64.decode64 payload) 106 | else 107 | aes_cipher(:decrypt, Base64.decode64(payload)) 108 | end 109 | end 110 | 111 | def aes_cipher(method, payload) 112 | cipher = OpenSSL::Cipher::AES.new(256, :CBC) 113 | cipher.send(method) 114 | cipher.key = aes_key.map { |u| u.chr }.join 115 | cipher.iv = aes_iv.map { |u| u.chr }.join 116 | (cipher.update(payload) + cipher.final).force_encoding('UTF-8') 117 | end 118 | 119 | def payload 120 | { 121 | "Username": @username, 122 | "Password": @password, 123 | "RequestDate": time_klass.now.strftime('%Y-%m-%dT%H:%M:%S') 124 | }.to_json 125 | end 126 | 127 | def base_url 128 | @base_url ||= production? ? 'https://apiparceiros.neonpagamentos.com.br/' : 'https://servicosdev.neonhomol.com.br/servicopj/' 129 | end 130 | end 131 | end 132 | -------------------------------------------------------------------------------- /lib/neon_api/configuration.rb: -------------------------------------------------------------------------------- 1 | module NeonApi 2 | class << self 3 | attr_accessor :configuration 4 | end 5 | 6 | def self.configure 7 | self.configuration ||= Configuration.new 8 | yield(configuration) 9 | self.configuration.client_setup 10 | end 11 | 12 | def self.client 13 | self.configuration.client 14 | end 15 | 16 | # Configuration 17 | class Configuration 18 | attr_accessor :environment, :token, :client, :username, :password, :encrypt_pem, :decrypt_pem, :proxy 19 | 20 | def client_setup 21 | @client ||= Client.new(environment, token, username, password, encrypt_pem, decrypt_pem, proxy) 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /lib/neon_api/methods.rb: -------------------------------------------------------------------------------- 1 | require "neon_api/methods/balance" 2 | require "neon_api/methods/cancel_payment" 3 | require "neon_api/methods/confirm_payment" 4 | require "neon_api/methods/create_payer" 5 | require "neon_api/methods/create_sub_account" 6 | require "neon_api/methods/generate_payment_slip_to_payer" 7 | require "neon_api/methods/get_accounts" 8 | require "neon_api/methods/get_banks" 9 | require "neon_api/methods/get_finality" 10 | require "neon_api/methods/get_payers" 11 | require "neon_api/methods/get_payment_slip_by_payer" 12 | require "neon_api/methods/get_payment_slip_by_sub_account" 13 | require "neon_api/methods/get_statement" 14 | require "neon_api/methods/send_payment" 15 | require "neon_api/methods/send_transfer" 16 | require "neon_api/methods/confirm_transfer" 17 | -------------------------------------------------------------------------------- /lib/neon_api/methods/balance.rb: -------------------------------------------------------------------------------- 1 | module NeonApi 2 | module Balance 3 | URL = 'V1/Client/GetBalanceAccount' 4 | 5 | def self.get_balance 6 | NeonApi.client.send_request(payload, URL) 7 | end 8 | 9 | def self.payload 10 | { 11 | "ClientID": NeonApi.client.client_id 12 | }.to_json 13 | end 14 | end 15 | end -------------------------------------------------------------------------------- /lib/neon_api/methods/cancel_payment.rb: -------------------------------------------------------------------------------- 1 | module NeonApi 2 | module CancelPayment 3 | URL = 'V1/PaymentSlip/CancelPayment' 4 | def self.create(list_uniq_id) 5 | NeonApi.client.send_request(payload(list_uniq_id), URL) 6 | end 7 | 8 | def self.payload(list_uniq_id) 9 | { 10 | "ClientID": NeonApi.client.client_id, 11 | "ListUniqueId": list_uniq_id 12 | }.to_json 13 | end 14 | end 15 | end 16 | 17 | -------------------------------------------------------------------------------- /lib/neon_api/methods/confirm_payment.rb: -------------------------------------------------------------------------------- 1 | module NeonApi 2 | module ConfirmPayment 3 | URL = 'V1/PaymentSlip/ConfirmPayment' 4 | def self.create(list_uniq_id) 5 | NeonApi.client.send_request(payload(list_uniq_id), URL) 6 | end 7 | 8 | def self.payload(list_uniq_id) 9 | { 10 | "ClientID": NeonApi.client.client_id, 11 | "ListUniqueId": list_uniq_id 12 | }.to_json 13 | end 14 | end 15 | end 16 | 17 | -------------------------------------------------------------------------------- /lib/neon_api/methods/confirm_transfer.rb: -------------------------------------------------------------------------------- 1 | module NeonApi 2 | module ConfirmTransfer 3 | URL = 'V1/Transfer/ConfirmTransfer' 4 | def self.create(uniq_id) 5 | NeonApi.client.send_request(payload(uniq_id), URL) 6 | end 7 | 8 | def self.payload(uniq_id) 9 | { 10 | "ClientID": NeonApi.client.client_id, 11 | "UniqueId": uniq_id 12 | }.to_json 13 | end 14 | end 15 | end 16 | 17 | -------------------------------------------------------------------------------- /lib/neon_api/methods/create_payer.rb: -------------------------------------------------------------------------------- 1 | module NeonApi 2 | module CreatePayer 3 | URL = 'V1/Payer/CreatePayersBySubAccount' 4 | def self.create(bank_acc_id, name, cpf, email, address, number, complement, zipcode, city, state, country) 5 | NeonApi.client.send_request(payload(bank_acc_id, name, cpf, email, address, number, complement, zipcode, city, state, country), URL) 6 | end 7 | 8 | def self.payload(bank_acc_id, name, cpf, email, address, number, complement, zipcode, city, state, country) 9 | { 10 | "BankAccountId": bank_acc_id, 11 | "Name": name, 12 | "CPF": cpf, 13 | "Email": email, 14 | "ClientID": NeonApi.client.client_id, 15 | "Address": address, 16 | "Number": number, 17 | "Complement": complement, 18 | "PostalCode": zipcode, 19 | "City": city, 20 | "State": state, 21 | "Country": country 22 | }.to_json 23 | end 24 | end 25 | end 26 | 27 | -------------------------------------------------------------------------------- /lib/neon_api/methods/create_sub_account.rb: -------------------------------------------------------------------------------- 1 | module NeonApi 2 | module CreateSubAccount 3 | URL = 'V1/SubAccount/CreateSubAccount' 4 | def self.create(name, percentage, main_percentage) 5 | NeonApi.client.send_request(payload(name, percentage, main_percentage), URL) 6 | end 7 | 8 | def self.payload(name, percentage, main_percentage) 9 | { 10 | "ClientID": NeonApi.client.client_id, 11 | "SubAccountName": name, 12 | "PercentageRedemption": percentage, 13 | "PercentageRedemptionMain": main_percentage 14 | }.to_json 15 | end 16 | end 17 | end -------------------------------------------------------------------------------- /lib/neon_api/methods/generate_payment_slip_to_payer.rb: -------------------------------------------------------------------------------- 1 | module NeonApi 2 | module GeneratePaymentSlipToPayer 3 | URL = 'V1/PaymentSlip/GeneratePaymentSlipToPayer' 4 | def self.create(bank_acc_id, name, cpf, email, address, number, complement, zipcode, city, state, country) 5 | NeonApi.client.send_request(payload(bank_acc_id, name, cpf, email, address, number, complement, zipcode, city, state, country), URL) 6 | end 7 | 8 | def self.payload(bank_account, payer_id, cpf, due_date, value, instructions = []) 9 | { 10 | "ClientId": NeonApi.client.client_id, 11 | "BankAccountId": bank_account, 12 | "PayerId": payer_id, 13 | "CPF": cpf, 14 | "DueDate": due_date, 15 | "Value": value, 16 | "Instructions": instructions 17 | }.to_json 18 | end 19 | end 20 | end 21 | 22 | -------------------------------------------------------------------------------- /lib/neon_api/methods/get_account_types.rb: -------------------------------------------------------------------------------- 1 | module NeonApi 2 | module GetAccountTypes 3 | URL = 'V1/Transfer/GetAccountTypes' 4 | def self.create 5 | NeonApi.client.send_request(payload, URL) 6 | end 7 | 8 | def self.payload 9 | { 10 | "ClientID": NeonApi.client.client_id 11 | }.to_json 12 | end 13 | end 14 | end 15 | 16 | -------------------------------------------------------------------------------- /lib/neon_api/methods/get_accounts.rb: -------------------------------------------------------------------------------- 1 | module NeonApi 2 | module GetAccounts 3 | URL = 'V1/SubAccount/GetAccounts' 4 | def self.get 5 | NeonApi.client.send_request(payload, URL) 6 | end 7 | 8 | def self.payload 9 | { 10 | "ClientID": NeonApi.client.client_id, 11 | }.to_json 12 | end 13 | end 14 | end -------------------------------------------------------------------------------- /lib/neon_api/methods/get_banks.rb: -------------------------------------------------------------------------------- 1 | module NeonApi 2 | module GetBanks 3 | URL = 'V1/Transfer/GetBanks' 4 | def self.get 5 | NeonApi.client.send_request(payload, URL) 6 | end 7 | 8 | def self.payload 9 | { 10 | "ClientID": NeonApi.client.client_id 11 | }.to_json 12 | end 13 | end 14 | end 15 | 16 | -------------------------------------------------------------------------------- /lib/neon_api/methods/get_finality.rb: -------------------------------------------------------------------------------- 1 | module NeonApi 2 | module GetFinality 3 | URL = 'V1/Transfer/GetFinality' 4 | def self.get 5 | NeonApi.client.send_request(payload, URL) 6 | end 7 | 8 | def self.payload 9 | { 10 | "ClientID": NeonApi.client.client_id 11 | }.to_json 12 | end 13 | end 14 | end 15 | 16 | -------------------------------------------------------------------------------- /lib/neon_api/methods/get_payers.rb: -------------------------------------------------------------------------------- 1 | module NeonApi 2 | module GetPayers 3 | URL = 'V1/Payer/GetPayersBySubAccount' 4 | def self.create(bank_acc_id, name, cpf, email, address, number, complement, zipcode, city, state, country) 5 | NeonApi.client.send_request(payload(bank_acc_id, name, cpf, email, address, number, complement, zipcode, city, state, country), URL) 6 | end 7 | 8 | def self.payload(bank_acc_id, name, cpf, email, address, number, complement, zipcode, city, state, country) 9 | { 10 | "BankAccountId": bank_acc_id, 11 | "ClientID": NeonApi.client.client_id, 12 | }.to_json 13 | end 14 | end 15 | end 16 | 17 | -------------------------------------------------------------------------------- /lib/neon_api/methods/get_payment.rb: -------------------------------------------------------------------------------- 1 | module NeonApi 2 | module GetPayment 3 | URL = 'V1/PaymentSlip/GetPayment' 4 | def self.create(uniq_id) 5 | NeonApi.client.send_request(payload(uniq_id), URL) 6 | end 7 | 8 | def self.payload(uniq_id) 9 | { 10 | "ClientID": NeonApi.client.client_id, 11 | "UniqueID": uniq_id 12 | }.to_json 13 | end 14 | end 15 | end 16 | 17 | -------------------------------------------------------------------------------- /lib/neon_api/methods/get_payment_slip_by_payer.rb: -------------------------------------------------------------------------------- 1 | module NeonApi 2 | module GetPaymentSlipByPayer 3 | URL = 'V1/PaymentSlip/GetPaymentSlipByPayer' 4 | def self.create(payer_id) 5 | NeonApi.client.send_request(payload(payer_id), URL) 6 | end 7 | 8 | def self.payload(payer_id) 9 | { 10 | "PayerId": payer_id, 11 | "ClientID": NeonApi.client.client_id, 12 | }.to_json 13 | end 14 | end 15 | end 16 | 17 | -------------------------------------------------------------------------------- /lib/neon_api/methods/get_payment_slip_by_sub_account.rb: -------------------------------------------------------------------------------- 1 | module NeonApi 2 | module GetPaymentSlipBySubAccount 3 | URL = 'V1/PaymentSlip/GetPaymentSlipBySubAccount' 4 | def self.create(payer_id, bank_account_id) 5 | NeonApi.client.send_request(payload(payer_id, bank_account_id), URL) 6 | end 7 | 8 | def self.payload(payer_id, bank_account_id) 9 | { 10 | "PayerId": payer_id, 11 | "BankAccountId": bank_account_id 12 | }.to_json 13 | end 14 | end 15 | end 16 | 17 | -------------------------------------------------------------------------------- /lib/neon_api/methods/get_statement.rb: -------------------------------------------------------------------------------- 1 | module NeonApi 2 | module GetStatement 3 | URL = 'V1/Statement/GetStatement' 4 | 5 | def self.get(month, year) 6 | NeonApi.client.send_request(payload(month, year), URL) 7 | end 8 | 9 | def self.payload(month, year) 10 | { 11 | 'ClientID': NeonApi.client.client_id, 12 | 'Year': year, 13 | 'Month': month 14 | }.to_json 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/neon_api/methods/send_payment.rb: -------------------------------------------------------------------------------- 1 | module NeonApi 2 | module SendPayment 3 | URL = 'V1/PaymentSlip/SendPayment' 4 | def self.create(description, bar_code, due_date, value, discount, tx) 5 | NeonApi.client.send_request(payload(description, bar_code, due_date, value, discount, tx), URL) 6 | end 7 | 8 | def self.payload(description, bar_code, due_date, value, discount, tx) 9 | { 10 | "ClientId": NeonApi.client.client_id, 11 | "Payments": [ 12 | { 13 | "description": description, 14 | "BarCodeNumber": bar_code, 15 | "DueDate": due_date, 16 | "Assignor": "Cedente", 17 | "Value": value, 18 | "Discount": discount, 19 | "TaxValue": tx 20 | } 21 | ] 22 | }.to_json 23 | end 24 | end 25 | end 26 | 27 | -------------------------------------------------------------------------------- /lib/neon_api/methods/send_transfer.rb: -------------------------------------------------------------------------------- 1 | module NeonApi 2 | module SendTransfer 3 | URL = 'V1/Transfer/SendTransfer' 4 | def self.create(bank_account_id, finality_id, description, credit_to_bank, account_type, branch, bank_account_number, name, document, value, scheduled_to) 5 | NeonApi.client.send_request(payload(bank_account_id, finality_id, description, credit_to_bank, account_type, branch, bank_account_number, name, document, value, scheduled_to), URL) 6 | end 7 | 8 | def self.payload(bank_account_id, finality_id, description, credit_to_bank, account_type = "CC", branch = "1", bank_account_number, name, document, value, scheduled_to) 9 | { 10 | "BankAccountId": bank_account_id, 11 | "FinalityId": finality_id, 12 | "Description": description, 13 | "CreditTo": { 14 | "CodBank": credit_to_bank, 15 | "AccountyType": account_type, 16 | "Branch": branch, 17 | "BankAccountNumber": bank_account_number, 18 | "Name": name, 19 | "Document": document, 20 | "Value": value, 21 | "SchedulingDate": scheduled_to 22 | }, 23 | "ClientID": NeonApi.client.client_id 24 | }.to_json 25 | end 26 | end 27 | end 28 | 29 | -------------------------------------------------------------------------------- /lib/neon_api/version.rb: -------------------------------------------------------------------------------- 1 | module NeonApi 2 | VERSION = "0.1.11" 3 | end 4 | -------------------------------------------------------------------------------- /neon_api.gemspec: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | lib = File.expand_path("../lib", __FILE__) 3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 4 | require "neon_api/version" 5 | 6 | Gem::Specification.new do |spec| 7 | spec.name = "neon_api" 8 | spec.version = NeonApi::VERSION 9 | spec.authors = ["Gabriel Hamdan"] 10 | spec.email = ["ghamdan.eng@gmail.com"] 11 | 12 | spec.summary = %q{Gem to integrate with Bank Neon's API} 13 | spec.description = %q{Gem to integrate with Bank Neon's API and its encrypted authentication process} 14 | spec.homepage = "https://github.com/Hamdan85/neon_api" 15 | spec.license = "MIT" 16 | 17 | # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host' 18 | # to allow pushing to a single host or delete this section to allow pushing to any host. 19 | # if spec.respond_to?(:metadata) 20 | # spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'" 21 | # else 22 | # raise "RubyGems 2.0 or newer is required to protect against " \ 23 | # "public gem pushes." 24 | # end 25 | 26 | spec.files = `git ls-files -z`.split("\x0").reject do |f| 27 | f.match(%r{^(test|spec|features)/}) 28 | end 29 | spec.bindir = "exe" 30 | spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } 31 | spec.require_paths = ["lib"] 32 | 33 | spec.add_development_dependency "bundler", "~> 1.15" 34 | spec.add_development_dependency "rake", "~> 10.0" 35 | spec.add_development_dependency "rspec", "~> 3.0" 36 | spec.add_development_dependency "openssl", "~> 2.0" 37 | spec.add_dependency "aes", "~> 0.5.0" 38 | end 39 | -------------------------------------------------------------------------------- /spec/neon_api/client_spec.rb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | 3 | RSpec.describe NeonApi::Client do 4 | 5 | describe '#base_url' do 6 | 7 | let(:client) { described_class.new(environment, 'token-example', 'login', 'password', '/path/to/encrypt.pem', '/path/to/decrypt.pem', nil) } 8 | 9 | context 'when environment is production' do 10 | let(:environment) { :production } 11 | 12 | it 'sets the correct base_url' do 13 | expect(client.base_url).to eq('https://apiparceiros.banconeon.com.br/') 14 | end 15 | end 16 | 17 | context 'when environment is not production' do 18 | let(:environment) { :development } 19 | 20 | it 'sets the correct base_url' do 21 | expect(client.base_url).to eq('https://servicosdev.neonhomol.com.br/servicopj/') 22 | end 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /spec/neon_api/methods/confirm_transfer_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | RSpec.describe NeonApi::ConfirmTransfer do 4 | let(:args) { [ "abc-123" ] } 5 | let(:expected_payload) { "{\"ClientID\":null,\"UniqueId\":\"abc-123\"}" } 6 | let(:expected_url) { "V1/Transfer/ConfirmTransfer" } 7 | 8 | before do 9 | NeonApi.configure do |config| 10 | config.token = 'neon-token' 11 | config.username = 'neon-username' 12 | config.password = 'neon-pass' 13 | config.encrypt_pem = '/etc/public.pem' 14 | config.decrypt_pem = '/etc/private.pem' 15 | config.environment = :test 16 | end 17 | 18 | allow_any_instance_of(NeonApi::Client).to receive(:authenticate).and_return(true) 19 | allow_any_instance_of(NeonApi::Client).to receive(:send_request) 20 | end 21 | 22 | describe ".create" do 23 | it 'sends the payload to ConfirmTransfer' do 24 | expect_any_instance_of(NeonApi::Client).to receive(:send_request).with( 25 | expected_payload, expected_url 26 | ) 27 | 28 | subject.create(*args) 29 | end 30 | end 31 | 32 | describe ".payload" do 33 | it 'returns the correct payload in json format' do 34 | expect(subject.payload(*args)).to eq(expected_payload) 35 | end 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /spec/neon_api/methods/get_statement_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | RSpec.describe NeonApi::GetStatement do 4 | let(:args) { [11, 2017] } 5 | let(:expected_payload) { "{\"ClientID\":null,\"Year\":2017,\"Month\":11}" } 6 | let(:expected_url) { "V1/Statement/GetStatement"} 7 | 8 | before do 9 | NeonApi.configure do |config| 10 | config.token = 'neon-token' 11 | config.username = 'neon-username' 12 | config.password = 'neon-pass' 13 | config.encrypt_pem = '/etc/public.pem' 14 | config.decrypt_pem = '/etc/private.pem' 15 | config.environment = :test 16 | end 17 | 18 | allow_any_instance_of(NeonApi::Client).to receive(:authenticate).and_return(true) 19 | allow_any_instance_of(NeonApi::Client).to receive(:send_request) 20 | end 21 | 22 | describe ".get" do 23 | it 'sends the payload to GetStatement' do 24 | expect_any_instance_of(NeonApi::Client).to receive(:send_request).with( 25 | expected_payload, expected_url 26 | ) 27 | 28 | subject.get(*args) 29 | end 30 | end 31 | 32 | describe ".payload" do 33 | it 'returns the correct payload in json format' do 34 | expect(subject.payload(*args)).to eq(expected_payload) 35 | end 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /spec/neon_api/methods/send_transfer_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | RSpec.describe NeonApi::SendTransfer do 4 | let(:args) { [666, 1, "Transfer", 735, 2, 1, 123456, "Foo", "987654321", 120.0, "2017-12-24 00:00:00"] } 5 | let(:expected_payload) { "{\"BankAccountId\":666,\"FinalityId\":1,\"Description\":\"Transfer\",\"CreditTo\":{\"CodBank\":735,\"AccountyType\":2,\"Branch\":1,\"BankAccountNumber\":123456,\"Name\":\"Foo\",\"Document\":\"987654321\",\"Value\":120.0,\"SchedulingDate\":\"2017-12-24 00:00:00\"},\"ClientID\":null}" } 6 | let(:expected_url) { "V1/Transfer/SendTransfer" } 7 | 8 | before do 9 | NeonApi.configure do |config| 10 | config.token = 'neon-token' 11 | config.username = 'neon-username' 12 | config.password = 'neon-pass' 13 | config.encrypt_pem = '/etc/public.pem' 14 | config.decrypt_pem = '/etc/private.pem' 15 | config.environment = :test 16 | end 17 | 18 | allow_any_instance_of(NeonApi::Client).to receive(:authenticate).and_return(true) 19 | allow_any_instance_of(NeonApi::Client).to receive(:send_request) 20 | end 21 | 22 | describe ".create" do 23 | it 'sends the payload to SendTransfer' do 24 | expect_any_instance_of(NeonApi::Client).to receive(:send_request).with( 25 | expected_payload, expected_url 26 | ) 27 | 28 | subject.create(*args) 29 | end 30 | end 31 | 32 | describe ".payload" do 33 | it 'returns the correct payload in json format' do 34 | expect(subject.payload(*args)).to eq(expected_payload) 35 | end 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /spec/neon_api_spec.rb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | 3 | RSpec.describe NeonApi do 4 | it "has a version number" do 5 | expect(NeonApi::VERSION).not_to be nil 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require "bundler/setup" 2 | require "neon_api" 3 | 4 | RSpec.configure do |config| 5 | # Enable flags like --only-failures and --next-failure 6 | config.example_status_persistence_file_path = ".rspec_status" 7 | 8 | # Disable RSpec exposing methods globally on `Module` and `main` 9 | config.disable_monkey_patching! 10 | 11 | config.expect_with :rspec do |c| 12 | c.syntax = :expect 13 | end 14 | end 15 | --------------------------------------------------------------------------------