qrcode_pix_ruby 0.3.2 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 84a357b21f2470212773cc92b26e4c6342e03ab211bc143890dd3f1d9d83fc12
4
- data.tar.gz: ff3a3f5132cd865a342abab66622adeb4e1bdfc3d3b2f09cbfc045856a8b7a02
3
+ metadata.gz: a7d931df9ece2ebd9af528f72a1dda1efefda84c10524b3896194d0d34d96c22
4
+ data.tar.gz: dfb9495a14d4a1607f8451465bb009e8bff5a12816cb79f314e4b7572c60023b
5
5
  SHA512:
6
- metadata.gz: 4d07fafa359a2cc609e7eebd6518af234367e961b5cd427e0520ec15c0d920c5f5c236276157fd9bf73632e60c9543b3de682195cc5f6110790131a89920df49
7
- data.tar.gz: 702724974cb6e1842d576977c7fa155528136b189c0751d022ae2b4f39fc055959b0a992d6fd42d561305763757d0be82367a15cc2dfedc14315f0bb6ce901f7
6
+ metadata.gz: 5b58df6d23aa1f1c884218da52bacf1c0450e7534eef254522f32d021fda4be283b4d001b5a0b04488f208de62512e1e60ea1baccb54e13f98171f97825eae11
7
+ data.tar.gz: 7608914b8ef248a0f6705bc4d14483ffbb5a716009de911302fef9822136b5f51f5213999922df89a8053ba1cb32745887243f6c8f11df2ef5c84c9a8b1f1ed0
@@ -3,11 +3,22 @@ name: CI
3
3
  on: [push, pull_request]
4
4
 
5
5
  jobs:
6
- ci:
6
+ dockerfile:
7
+ runs-on: ubuntu-latest
8
+ steps:
9
+ - uses: actions/checkout@v2
10
+
11
+ - name: Build Dockerfile
12
+ run: docker build -t qrcode_pix_ruby_specs .
13
+
14
+ - name: Run tests inside Docker container
15
+ run: docker run -v $(pwd):/app/ -i qrcode_pix_ruby_specs
16
+
17
+ tests:
7
18
  runs-on: ubuntu-latest
8
19
  strategy:
9
20
  matrix:
10
- ruby-version: [2.7, 3.0]
21
+ ruby-version: [2.3, 2.4, 2.5, 2.6, 2.7, 3.0]
11
22
  env:
12
23
  CODECOV_TOKEN: ${{secrets.CODECOV_TOKEN}}
13
24
  steps:
@@ -0,0 +1,50 @@
1
+ name: Publish to Heroku
2
+
3
+ on:
4
+ push:
5
+ branches: [master]
6
+
7
+ jobs:
8
+ deploy:
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - uses: actions/checkout@v2
12
+
13
+ - name: Install Ruby
14
+ uses: ruby/setup-ruby@v1
15
+ with:
16
+ ruby-version: 3.0
17
+
18
+ - name: Install dependencies
19
+ run: |
20
+ cd demo/
21
+ bundle install
22
+ bundle update qrcode_pix_ruby
23
+ cd ../
24
+
25
+ - name: Define Heroku credentials
26
+ run: |
27
+ cat > ~/.netrc <<EOF
28
+ machine api.heroku.com
29
+ login $HEROKU_EMAIL
30
+ password $HEROKU_API_KEY
31
+ machine git.heroku.com
32
+ login $HEROKU_EMAIL
33
+ password $HEROKU_API_KEY
34
+ EOF
35
+ env:
36
+ HEROKU_API_KEY: ${{ secrets.HEROKU_API_KEY }}
37
+ HEROKU_EMAIL: ${{ secrets.HEROKU_EMAIL }}
38
+
39
+ - name: Define Heroku git remote
40
+ run: heroku git:remote --app $HEROKU_APP_NAME
41
+ env:
42
+ HEROKU_APP_NAME: ${{ secrets.HEROKU_APP_NAME }}
43
+
44
+ - name: Publish to Heroku
45
+ run: |
46
+ git config user.name 'Pedro Furtado'
47
+ git config user.email 'pedro.felipe.azevedo.furtado@gmail.com'
48
+ git add --all
49
+ git commit -m 'Publish to Heroku'
50
+ git push heroku `git subtree split --prefix demo master`:master --force
@@ -5,7 +5,7 @@ on:
5
5
  types: [created]
6
6
 
7
7
  jobs:
8
- publish-to-rubygems:
8
+ deploy:
9
9
  runs-on: ubuntu-latest
10
10
  steps:
11
11
  - uses: actions/checkout@v2
data/.gitignore CHANGED
@@ -1,4 +1,5 @@
1
1
  .rspec_status
2
- *.lock
2
+ /Gemfile.lock
3
3
  *.gem
4
4
  coverage/
5
+ *.log
data/.rubocop.yml ADDED
@@ -0,0 +1,38 @@
1
+ AllCops:
2
+ NewCops: enable
3
+ SuggestExtensions: false
4
+ Exclude:
5
+ - spec/*
6
+ - demo/*
7
+
8
+ Style/RegexpLiteral:
9
+ Enabled: false
10
+
11
+ Layout/LineLength:
12
+ Max: 120
13
+ Exclude:
14
+ - qrcode_pix_ruby.gemspec
15
+
16
+ Metrics/MethodLength:
17
+ Max: 20
18
+
19
+ Gemspec/RequiredRubyVersion:
20
+ Enabled: false
21
+
22
+ Style/Documentation:
23
+ Enabled: false
24
+
25
+ Metrics/AbcSize:
26
+ Enabled: false
27
+
28
+ Metrics/BlockNesting:
29
+ Enabled: false
30
+
31
+ Style/IfUnlessModifier:
32
+ Enabled: false
33
+
34
+ Metrics/CyclomaticComplexity:
35
+ Enabled: false
36
+
37
+ Metrics/PerceivedComplexity:
38
+ Enabled: false
data/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.5.0] - 2021-07-13
4
+
5
+ - Add option to pass Pix informations directly in initializer
6
+ - CI speedup
7
+ - Specs reorganization
8
+
9
+ ## [0.4.0] - 2021-07-10
10
+
11
+ - Add URL option for PIX, in order to generate dynamic QR Codes
12
+
13
+ ## [0.3.4] - 2021-06-28
14
+
15
+ - Fix behavior of EMV field 'repeatable' (the logic was inversed)
16
+
17
+ ## [0.3.3] - 2021-06-25
18
+
19
+ - Rubocop setup
20
+ - Add rubies 2.3, 2.4, 2.5 and 2.6 to support of gem
21
+
3
22
  ## [0.3.2] - 2021-06-24
4
23
 
5
24
  - Setup for run tests/specs locally with Docker
data/Dockerfile CHANGED
@@ -1,8 +1,6 @@
1
1
  FROM ruby:3.0.0-alpine
2
2
  RUN apk update && apk add git
3
- RUN mkdir -p /app/
4
- WORKDIR /app/
5
- VOLUME /app/
6
- COPY . /app/
3
+ WORKDIR /app
4
+ COPY . .
7
5
  RUN bundle install
8
6
  CMD bundle exec rake
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2021 TODO: Write your name
3
+ Copyright (c)
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -7,10 +7,11 @@
7
7
  [![Gem](https://img.shields.io/gem/dt/qrcode_pix_ruby.svg)]()
8
8
  [![license](https://img.shields.io/github/license/pedrofurtado/qrcode_pix_ruby.svg)]()
9
9
  [![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/pedrofurtado/qrcode_pix_ruby)
10
+ [![Ruby Style Guide](https://img.shields.io/badge/code_style-rubocop-brightgreen.svg)](https://github.com/rubocop/rubocop)
10
11
 
11
12
  Ruby gem for Qrcode generation of Pix (Pagamento Instantâneo Brasileiro - Banco Central do Brasil).
12
13
 
13
- <img src="https://github.com/pedrofurtado/qrcode_pix_ruby/blob/master/pix_logo.png?raw=true" height="100px" />
14
+ <img style="max-width: 100%;" src="https://github.com/pedrofurtado/qrcode_pix_ruby/blob/master/pix_logo.png?raw=true" height="100px" />
14
15
 
15
16
  ## Installation
16
17
 
@@ -28,33 +29,87 @@ Or install it yourself as:
28
29
 
29
30
  gem install qrcode_pix_ruby
30
31
 
31
- ## Usage
32
+ ## Usage (examples)
33
+
34
+ ### Static QR Code
32
35
 
33
36
  ```ruby
34
37
  require 'qrcode_pix_ruby'
35
38
 
36
- pix = QrcodePixRuby::Payload.new
39
+ pix = QrcodePixRuby::Payload.new(
40
+ pix_key: 'minhachavedopix',
41
+ description: 'Pagamento do pedido 123456',
42
+ merchant_name: 'Fulano de Tal',
43
+ merchant_city: 'SAO PAULO',
44
+ transaction_id: 'TID12345',
45
+ amount: '100.00',
46
+ currency: '986',
47
+ country_code: 'BR',
48
+ postal_code: '01131010',
49
+ repeatable: false
50
+ )
51
+
52
+ # If needed, change the attributes value later
53
+ pix.pix_key = 'minhaoutrachavepix'
54
+ pix.merchant_city = 'BRASILIA'
55
+
56
+ # QRCode copia-e-cola
57
+ puts pix.payload
58
+
59
+ # QRCode for images
60
+ puts pix.base64
61
+ ```
62
+
63
+ ### Dynamic QR Code
64
+
65
+ ```ruby
66
+ require 'qrcode_pix_ruby'
37
67
 
38
- pix.pix_key = 'minhachavedopix'
39
- pix.description = 'Pagamento do pedido 123456'
40
- pix.merchant_name = 'Fulano de Tal'
41
- pix.merchant_city = 'SAO PAULO'
42
- pix.transaction_id = 'TID12345'
43
- pix.amount = '100.00'
44
- pix.currency = '986'
45
- pix.country_code = 'BR'
46
- pix.postal_code = '01131010'
47
- pix.repeatable = false
68
+ pix = QrcodePixRuby::Payload.new(
69
+ url: 'https://example.com',
70
+ merchant_name: 'Fulano de Tal',
71
+ merchant_city: 'SAO PAULO',
72
+ amount: '100.00',
73
+ transaction_id: 'TID12345',
74
+ repeatable: false
75
+ )
76
+
77
+ # If needed, change the attributes value later
78
+ pix.url = 'https://another-example.com'
79
+ pix.amount = 1.50
48
80
 
49
81
  # QRCode copia-e-cola
50
82
  puts pix.payload
51
83
 
52
- # QRCode estático
84
+ # QRCode para uso em imagens
53
85
  puts pix.base64
54
86
  ```
55
87
 
56
88
  🚨 Important note: BACEN (Banco Central do Brasil) sets a variety of rules for each field in QRCode Payload (maximum number of characters, invalid values, mandatory and optional fields, and so on). So, pay attention that a QRCode payload+base64 generated by the gem can be valid, theorically, but may not be accepted in banking apps because of these restrictions (that are out of scope of gem).
57
89
 
90
+ ## Execute tests/specs
91
+
92
+ To execute gem tests locally, use Docker with the commands below:
93
+
94
+ ```bash
95
+ git clone https://github.com/pedrofurtado/qrcode_pix_ruby
96
+ cd qrcode_pix_ruby/
97
+ docker build -t qrcode_pix_ruby_specs .
98
+
99
+ # Then, run this command how many times you want,
100
+ # after editing local files, and so on, to get
101
+ # feedback from test suite of gem.
102
+ docker run -v $(pwd):/app/ -it qrcode_pix_ruby_specs
103
+ ```
104
+
105
+ ## Demo
106
+
107
+ It's provided a simple demo app, in Heroku, that uses the gem always in latest commit. You can check and test your QRCodes here:
108
+
109
+ https://qrcode-pix-ruby.herokuapp.com
110
+
111
+ 🚨 Important note: The first page load can be slow, because of Heroku free tier. But don't worry, the demo works well 🤓
112
+
58
113
  ## Useful links
59
114
 
60
115
  * https://github.com/joseviniciusnunes/qrcode-pix
@@ -67,27 +122,19 @@ puts pix.base64
67
122
  * https://openpix.com.br/qrcode/scanner
68
123
  * https://openpix.com.br/qrcode/debug
69
124
  * https://github.com/william-costa/wdev-qrcode-pix-estatico-php
125
+ * https://github.com/william-costa/wdev-qrcode-pix-php
70
126
  * https://www.youtube.com/watch?v=eO11iFgrdCA
71
127
  * https://qrcodepix.dinheiro.tech
72
128
  * http://decoder.qrcodepix.dinheiro.tech
73
129
  * https://www.bcb.gov.br/estabilidadefinanceira/pix
74
130
  * https://gerencianet.com.br/blog/qr-code-estatico-qr-code-dinamico-no-pix
75
131
  * https://blog.juno.com.br/pix-qr-code-estatico-x-qr-code-dinamico
76
-
77
- ## Execute tests/specs
78
-
79
- To execute gem tests locally, use Docker with the commands below:
80
-
81
- ```bash
82
- git clone https://github.com/pedrofurtado/qrcode_pix_ruby
83
- cd qrcode_pix_ruby/
84
- docker build -t qrcode_pix_ruby_specs .
85
-
86
- # Then, run this command how many times you want,
87
- # after editing local files, and so on, to get
88
- # feedback from test suite of gem.
89
- docker run -v $(pwd):/app/ -it qrcode_pix_ruby_specs
90
- ```
132
+ * https://github.com/entria/awesome-pix
133
+ * https://zxing.org/w/decode.jspx
134
+ * https://github.com/hiagodotme/gpix
135
+ * https://github.com/EnssureIT/faz-um-pix
136
+ * https://github.com/jesobreira/pixkey
137
+ * https://github.com/pedrinholemes/pix-br
91
138
 
92
139
  ## Contributing
93
140
 
data/Rakefile CHANGED
@@ -2,5 +2,7 @@
2
2
 
3
3
  require 'bundler/gem_tasks'
4
4
  require 'rspec/core/rake_task'
5
+ require 'rubocop/rake_task'
6
+ RuboCop::RakeTask.new
5
7
  RSpec::Core::RakeTask.new(:spec)
6
- task default: %i[spec]
8
+ task default: %i[rubocop spec]
data/demo/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+ gem 'qrcode_pix_ruby', github: 'pedrofurtado/qrcode_pix_ruby', branch: 'master'
5
+ gem 'rack'
data/demo/config.ru ADDED
@@ -0,0 +1,171 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'qrcode_pix_ruby'
4
+
5
+ def generate_html_with(env)
6
+ qrcode_data = Rack::Request.new(env).params
7
+ payload = ''
8
+ data_uri = ''
9
+ pix = QrcodePixRuby::Payload.new
10
+
11
+ unless qrcode_data.empty?
12
+ pix.pix_key = qrcode_data['pix_key'] if !qrcode_data['pix_key'].nil? && !qrcode_data['pix_key'].empty?
13
+ pix.url = qrcode_data['url'] if !qrcode_data['url'].nil? && !qrcode_data['url'].empty?
14
+ pix.description = qrcode_data['description'] if !qrcode_data['description'].nil? && !qrcode_data['description'].empty?
15
+ pix.merchant_name = qrcode_data['merchant_name'] if !qrcode_data['merchant_name'].nil? && !qrcode_data['merchant_name'].empty?
16
+ pix.merchant_city = qrcode_data['merchant_city'] if !qrcode_data['merchant_city'].nil? && !qrcode_data['merchant_city'].empty?
17
+ pix.transaction_id = qrcode_data['transaction_id'] if !qrcode_data['transaction_id'].nil? && !qrcode_data['transaction_id'].empty?
18
+ pix.amount = qrcode_data['amount'] if !qrcode_data['amount'].nil? && !qrcode_data['amount'].empty?
19
+ pix.currency = qrcode_data['currency'] if !qrcode_data['currency'].nil? && !qrcode_data['currency'].empty?
20
+ pix.country_code = qrcode_data['country_code'] if !qrcode_data['country_code'].nil? && !qrcode_data['country_code'].empty?
21
+ pix.postal_code = qrcode_data['postal_code'] if !qrcode_data['postal_code'].nil? && !qrcode_data['postal_code'].empty?
22
+ pix.repeatable = qrcode_data['repeatable'] == 't' if !qrcode_data['repeatable'].nil? && !qrcode_data['repeatable'].empty?
23
+
24
+ payload = <<-HTML
25
+ <label for='payload'>Payload</label>
26
+ <div class='input-group mb-3'>
27
+ <input class='form-control' id='payload' value='#{pix.payload}'>
28
+ <button class='btn btn-outline-success btn-clipboard' data-clipboard-target='#payload' data-bs-toggle='tooltip' data-bs-placement='top' title='Copied!' data-bs-trigger='click'>Copy</button>
29
+ </div>
30
+ HTML
31
+
32
+ data_uri = "<img style='max-width: 100%; display: block; margin: 0 auto;' src='#{pix.base64}'>"
33
+ end
34
+
35
+ StringIO.new <<-HTML
36
+ <!DOCTYPE html>
37
+ <html>
38
+ <head>
39
+ <meta charset='utf-8'>
40
+ <meta name='viewport' content='width=device-width, initial-scale=1'>
41
+ <link href='https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css' rel='stylesheet'>
42
+ <script src='https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js'></script>
43
+ <script src='https://cdn.jsdelivr.net/npm/clipboard@2.0.8/dist/clipboard.min.js'></script>
44
+ <title>QRCode Pix Ruby - Demo App</title>
45
+ </head>
46
+ <body>
47
+ <div class='container' style='margin-top: 50px;'>
48
+ <div class='row'>
49
+ <div class='col-md-12'>
50
+ <h1 class='text-center'>QRCode Pix Ruby - Demo App</h1>
51
+ <br>
52
+ <img style='display: block; margin: 0 auto; max-width: 100%;' src="https://github.com/pedrofurtado/qrcode_pix_ruby/blob/master/pix_logo.png?raw=true" height="100px" />
53
+ <br>
54
+ <p style='word-break: break-all;' class='text-center'>For more details check the official repo: <a href="https://github.com/pedrofurtado/qrcode_pix_ruby">https://github.com/pedrofurtado/qrcode_pix_ruby</a></p>
55
+ <br>
56
+ <br>
57
+ </div>
58
+ </div>
59
+ <div class='row' style='padding-bottom: 50px;'>
60
+ <div class='col-sm-6'>
61
+ <strong>QRCode informations</strong>
62
+ <br>
63
+ <br>
64
+ <form action='https://qrcode-pix-ruby.herokuapp.com' method='post'>
65
+ <div class='mb-3'>
66
+ <div class='form-text'>
67
+ For static Pix, please fill the 'Pix key' field.<br>
68
+ For dynamic Pix, fill the 'URL' field.<br>
69
+ Do not fill both fields.
70
+ </div>
71
+ </div>
72
+ <div class='mb-3'>
73
+ <label for='pix_key'>* Pix key</label>
74
+ <input type='text' class='form-control' id='pix_key' value='#{qrcode_data["pix_key"]}' name='pix_key'>
75
+ <div class='form-text'>
76
+ Formats of Pix keys:<br>
77
+ CPF: 12345678910 (only numbers)<br>
78
+ Phone: +5511912345678 (+55 + DDD + phone, only numbers)<br>
79
+ Email: example@mail.com<br>
80
+ Random: a6hf7jdk3nc8iK (generated by bank)
81
+ </div>
82
+ </div>
83
+ <div class='mb-3 text-center'> or</div>
84
+ <div class='mb-3'>
85
+ <label for='url'>* URL</label>
86
+ <input type='url' pattern='https?:\/\/.+' class='form-control' id='url' value='#{qrcode_data["url"]}' name='url'>
87
+ </div>
88
+ <hr>
89
+ <div class='mb-3'>
90
+ <label for='merchant_name'>* Merchant name</label>
91
+ <input required maxlength='10' type='text' class='form-control' id='merchant_name' value='#{qrcode_data["merchant_name"]}' name='merchant_name'>
92
+ </div>
93
+ <div class='mb-3'>
94
+ <label for='merchant_city'>* Merchant city</label>
95
+ <input required maxlength='10' type='text' class='form-control' id='merchant_city' value='#{qrcode_data["merchant_city"]}' name='merchant_city'>
96
+ </div>
97
+ <div class='mb-3'>
98
+ <label for='country_code'>* Country</label>
99
+ <select required id='country_code' name='country_code' class='form-select'>
100
+ <option></option>
101
+ <option value='BR' #{qrcode_data['country_code'] == 'BR' ? 'selected' : ''}>Brazil</option>
102
+ </select>
103
+ </div>
104
+ <div class='mb-3'>
105
+ <label for='currency'>* Currency</label>
106
+ <select required id='currency' name='currency' class='form-select'>
107
+ <option></option>
108
+ <option value='986' #{qrcode_data['currency'] == '986' ? 'selected' : ''}>Brazilian Real (R$)</option>
109
+ </select>
110
+ </div>
111
+ <div class='mb-3'>
112
+ <label for='description'>Description</label>
113
+ <input maxlength='10' type='text' class='form-control' id='description' value='#{qrcode_data["description"]}' name='description'>
114
+ </div>
115
+ <div class='mb-3'>
116
+ <label for='transaction_id'>Transaction ID</label>
117
+ <input maxlength='10' pattern='[a-zA-z0-9]*' type='text' class='form-control' id='transaction_id' value='#{qrcode_data["transaction_id"]}' name='transaction_id'>
118
+ <div class='form-text'>Only numbers and simple characters, without whitespaces.</div>
119
+ </div>
120
+ <div class='mb-3'>
121
+ <label for='amount'>Amount</label>
122
+ <input type='number' step='0.01' pattern='[0-9]{1,}\.[0-9][0-9]' class='form-control' id='amount' value='#{qrcode_data["amount"]}' name='amount'>
123
+ <div class='form-text'>Only numbers with 2 decimal places.</div>
124
+ </div>
125
+ <div class='mb-3'>
126
+ <label for='postal_code'>Postal code</label>
127
+ <input maxlength='8' pattern='[0-9]{8}' type='tel' class='form-control' id='postal_code' value='#{qrcode_data["postal_code"]}' name='postal_code'>
128
+ <div class='form-text'>Only numbers.</div>
129
+ </div>
130
+ <div class='mb-3'>
131
+ <label for='repeatable'>Can be paid multiple times?</label>
132
+ <select required id='repeatable' name='repeatable' class='form-select'>
133
+ <option></option>
134
+ <option value='t' #{qrcode_data['repeatable'] == 't' ? 'selected' : ''}>Yes</option>
135
+ <option value='f' #{qrcode_data['repeatable'] == 'f' ? 'selected' : ''}>No</option>
136
+ </select>
137
+ </div>
138
+ <div class='d-grid gap-2' style='padding-bottom: 20px;'>
139
+ <button type='submit' class='btn btn-lg btn-primary'>Generate</button>
140
+ </div>
141
+ </form>
142
+ </div>
143
+ <div class='col-sm-6'>
144
+ <strong>Preview</strong>
145
+ <br>
146
+ <br>
147
+ #{payload}
148
+ #{data_uri}
149
+ </div>
150
+ </div>
151
+ </div>
152
+ <script>
153
+ new ClipboardJS('.btn-clipboard');
154
+ Array.from(document.querySelectorAll('[data-bs-toggle="tooltip"]')).forEach(function(tooltipTriggerEl) {
155
+ new bootstrap.Tooltip(tooltipTriggerEl);
156
+ });
157
+ </script>
158
+ </body>
159
+ </html>
160
+ HTML
161
+ end
162
+
163
+ run lambda { |env|
164
+ [
165
+ 200,
166
+ {
167
+ 'Content-Type' => 'text/html'
168
+ },
169
+ generate_html_with(env)
170
+ ]
171
+ }
@@ -3,5 +3,4 @@
3
3
  require_relative 'qrcode_pix_ruby/version'
4
4
  require_relative 'qrcode_pix_ruby/payload'
5
5
 
6
- module QrcodePixRuby
7
- end
6
+ module QrcodePixRuby end
@@ -3,37 +3,41 @@
3
3
  require 'rqrcode'
4
4
 
5
5
  module QrcodePixRuby
6
+ class PayloadArgumentError < ArgumentError; end
7
+
6
8
  class Payload
7
- ID_PAYLOAD_FORMAT_INDICATOR = '00'.freeze
8
- ID_POINT_OF_INITIATION_METHOD = '01'.freeze
9
- ID_MERCHANT_ACCOUNT_INFORMATION = '26'.freeze
10
- ID_MERCHANT_ACCOUNT_INFORMATION_GUI = '00'.freeze
11
- ID_MERCHANT_ACCOUNT_INFORMATION_KEY = '01'.freeze
12
- ID_MERCHANT_ACCOUNT_INFORMATION_DESCRIPTION = '02'.freeze
13
- ID_MERCHANT_CATEGORY_CODE = '52'.freeze
14
- ID_TRANSACTION_CURRENCY = '53'.freeze
15
- ID_TRANSACTION_AMOUNT = '54'.freeze
16
- ID_COUNTRY_CODE = '58'.freeze
17
- ID_MERCHANT_NAME = '59'.freeze
18
- ID_MERCHANT_CITY = '60'.freeze
19
- ID_POSTAL_CODE = '61'.freeze
20
- ID_ADDITIONAL_DATA_FIELD_TEMPLATE = '62'.freeze
21
- ID_ADDITIONAL_DATA_FIELD_TEMPLATE_TXID = '05'.freeze
22
- ID_CRC16 = '63'.freeze
23
-
24
- attr_accessor :pix_key,
25
- :repeatable,
26
- :currency,
27
- :country_code,
28
- :description,
29
- :postal_code,
30
- :merchant_name,
31
- :merchant_city,
32
- :transaction_id,
33
- :amount
9
+ ID_PAYLOAD_FORMAT_INDICATOR = '00'
10
+ ID_POINT_OF_INITIATION_METHOD = '01'
11
+ ID_MERCHANT_ACCOUNT_INFORMATION = '26'
12
+ ID_MERCHANT_ACCOUNT_INFORMATION_GUI = '00'
13
+ ID_MERCHANT_ACCOUNT_INFORMATION_KEY = '01'
14
+ ID_MERCHANT_ACCOUNT_INFORMATION_DESCRIPTION = '02'
15
+ ID_MERCHANT_ACCOUNT_INFORMATION_URL = '25'
16
+ ID_MERCHANT_CATEGORY_CODE = '52'
17
+ ID_TRANSACTION_CURRENCY = '53'
18
+ ID_TRANSACTION_AMOUNT = '54'
19
+ ID_COUNTRY_CODE = '58'
20
+ ID_MERCHANT_NAME = '59'
21
+ ID_MERCHANT_CITY = '60'
22
+ ID_POSTAL_CODE = '61'
23
+ ID_ADDITIONAL_DATA_FIELD_TEMPLATE = '62'
24
+ ID_ADDITIONAL_DATA_FIELD_TEMPLATE_TXID = '05'
25
+ ID_CRC16 = '63'
26
+
27
+ ATTRIBUTES = %i[pix_key url repeatable currency country_code description postal_code
28
+ merchant_name merchant_city transaction_id amount].freeze
29
+
30
+ def initialize(**kwargs)
31
+ verify_kwargs(kwargs.keys)
32
+
33
+ ATTRIBUTES.each do |attribute|
34
+ singleton_class.class_eval { attr_accessor attribute }
35
+ instance_variable_set("@#{attribute}", kwargs[attribute])
36
+ end
37
+ end
34
38
 
35
39
  def payload
36
- p = ''
40
+ p = ''
37
41
 
38
42
  p += emv(ID_PAYLOAD_FORMAT_INDICATOR, '01')
39
43
  p += emv_repeatable
@@ -51,56 +55,68 @@ module QrcodePixRuby
51
55
  end
52
56
 
53
57
  def base64
54
- ::RQRCode::QRCode.new(payload).as_png(bit_depth: 1, border_modules: 0, color_mode: 0, color: 'black', file: nil, fill: 'white', module_px_size: 6, resize_exactly_to: false, resize_gte_to: false).to_data_url
58
+ ::RQRCode::QRCode.new(payload).as_png(
59
+ bit_depth: 1,
60
+ border_modules: 0,
61
+ color_mode: 0,
62
+ color: 'black',
63
+ file: nil,
64
+ fill: 'white',
65
+ module_px_size: 6,
66
+ resize_exactly_to: false,
67
+ resize_gte_to: false
68
+ ).to_data_url
55
69
  end
56
70
 
57
71
  private
58
72
 
73
+ def verify_kwargs(keys)
74
+ unknowns = keys - ATTRIBUTES
75
+
76
+ return unless unknowns.any?
77
+
78
+ raise QrcodePixRuby::PayloadArgumentError, "Unknown attributes: #{unknowns.join(', ')}"
79
+ end
80
+
59
81
  def emv(id, value)
60
82
  size = value.to_s.length.to_s.rjust(2, '0')
61
83
  "#{id}#{size}#{value}"
62
84
  end
63
85
 
64
86
  def emv_repeatable
65
- emv(ID_POINT_OF_INITIATION_METHOD, repeatable ? '12' : '11')
87
+ emv(ID_POINT_OF_INITIATION_METHOD, repeatable ? '11' : '12')
66
88
  end
67
89
 
68
90
  def emv_merchant
69
- merchant_gui = emv ID_MERCHANT_ACCOUNT_INFORMATION_GUI, 'BR.GOV.BCB.PIX'
70
- merchant_pix_key = emv ID_MERCHANT_ACCOUNT_INFORMATION_KEY, pix_key
91
+ merchant_gui = emv(ID_MERCHANT_ACCOUNT_INFORMATION_GUI, 'BR.GOV.BCB.PIX')
92
+ merchant_pix_key = emv(ID_MERCHANT_ACCOUNT_INFORMATION_KEY, pix_key) if pix_key
71
93
  merchant_description = emv(ID_MERCHANT_ACCOUNT_INFORMATION_DESCRIPTION, description) if description
72
-
73
- emv ID_MERCHANT_ACCOUNT_INFORMATION, "#{merchant_gui}#{merchant_pix_key}#{merchant_description}"
94
+ merchant_url = emv(ID_MERCHANT_ACCOUNT_INFORMATION_URL, url.gsub(/https?:\/\//, '')) if url
95
+ emv(ID_MERCHANT_ACCOUNT_INFORMATION, "#{merchant_gui}#{merchant_pix_key}#{merchant_description}#{merchant_url}")
74
96
  end
75
97
 
76
98
  def emv_additional_data
77
99
  txid = emv(ID_ADDITIONAL_DATA_FIELD_TEMPLATE_TXID, transaction_id || '***')
78
- emv ID_ADDITIONAL_DATA_FIELD_TEMPLATE, txid
100
+ emv(ID_ADDITIONAL_DATA_FIELD_TEMPLATE, txid)
79
101
  end
80
102
 
81
- def crc16(t)
82
- extended_payload = "#{t}#{ID_CRC16}04"
103
+ def crc16(text)
104
+ extended_payload = "#{text}#{ID_CRC16}04"
83
105
  extended_payload_length = extended_payload.length
84
106
  polynomial = 0x1021
85
107
  result = 0xFFFF
86
108
 
87
- if extended_payload_length > 0
109
+ if extended_payload_length.positive?
88
110
  offset = 0
89
111
 
90
112
  while offset < extended_payload_length
91
- result = result ^ (extended_payload[offset].bytes[0] << 8)
92
-
113
+ result ^= extended_payload[offset].bytes[0] << 8
93
114
  bitwise = 0
94
115
 
95
116
  while bitwise < 8
96
- result = result << 1
97
-
98
- if result & 0x10000 != 0
99
- result = result ^ polynomial
100
- end
101
-
102
- result = result & 0xFFFF
103
-
117
+ result <<= 1
118
+ result ^= polynomial if result & 0x10000 != 0
119
+ result &= 0xFFFF
104
120
  bitwise += 1
105
121
  end
106
122
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module QrcodePixRuby
4
- VERSION = '0.3.2'.freeze
4
+ VERSION = '0.5.0'
5
5
  end
@@ -5,15 +5,16 @@ require_relative 'lib/qrcode_pix_ruby/version'
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = 'qrcode_pix_ruby'
7
7
  spec.version = QrcodePixRuby::VERSION
8
- spec.authors = ["Pedro Furtado", "Marcio de Jesus", "William Radi", "Leonardo Comar"]
9
- spec.email = ["pedro.felipe.azevedo.furtado@gmail.com", "marciodejesusrj@gmail.com", "williamw@lbv.org.br", "lfcomar@lbv.org.br"]
10
- spec.summary = "Ruby gem for Qrcode generation of Pix (Pagamento Instantâneo Brasileiro - Banco Central do Brasil)"
11
- spec.description = "Ruby gem for Qrcode generation of Pix (Pagamento Instantâneo Brasileiro - Banco Central do Brasil)"
12
- spec.homepage = "https://github.com/pedrofurtado/qrcode_pix_ruby"
13
- spec.license = "MIT"
14
- spec.metadata["homepage_uri"] = spec.homepage
15
- spec.metadata["source_code_uri"] = spec.homepage
16
- spec.metadata["changelog_uri"] = "#{spec.homepage}/CHANGELOG.md"
8
+ spec.authors = ['Pedro Furtado', 'Marcio de Jesus', 'William Radi', 'Leonardo Comar']
9
+ spec.email = ['pedro.felipe.azevedo.furtado@gmail.com', 'marciodejesusrj@gmail.com', 'williamw@lbv.org.br', 'lfcomar@lbv.org.br']
10
+ spec.summary = 'Ruby gem for Qrcode generation of Pix (Pagamento Instantâneo Brasileiro - Banco Central do Brasil)'
11
+ spec.description = 'Ruby gem for Qrcode generation of Pix (Pagamento Instantâneo Brasileiro - Banco Central do Brasil)'
12
+ spec.homepage = 'https://github.com/pedrofurtado/qrcode_pix_ruby'
13
+ spec.license = 'MIT'
14
+ spec.metadata['homepage_uri'] = spec.homepage
15
+ spec.metadata['source_code_uri'] = spec.homepage
16
+ spec.metadata['changelog_uri'] = "#{spec.homepage}/CHANGELOG.md"
17
+ spec.required_ruby_version = '>= 2.3.0'
17
18
 
18
19
  spec.files = Dir.chdir(File.expand_path(__dir__)) do
19
20
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
@@ -23,7 +24,8 @@ Gem::Specification.new do |spec|
23
24
  spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
24
25
  spec.require_paths = ['lib']
25
26
 
26
- spec.add_dependency 'rake', '~> 13.0'
27
- spec.add_dependency 'rspec', '~> 3.0'
28
- spec.add_dependency 'rqrcode', '~> 2.0'
27
+ spec.add_dependency 'rqrcode'
28
+ spec.add_development_dependency 'rake'
29
+ spec.add_development_dependency 'rspec'
30
+ spec.add_development_dependency 'rubocop'
29
31
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: qrcode_pix_ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pedro Furtado
@@ -11,50 +11,64 @@ authors:
11
11
  autorequire:
12
12
  bindir: exe
13
13
  cert_chain: []
14
- date: 2021-06-25 00:00:00.000000000 Z
14
+ date: 2021-07-13 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
- name: rake
17
+ name: rqrcode
18
18
  requirement: !ruby/object:Gem::Requirement
19
19
  requirements:
20
- - - "~>"
20
+ - - ">="
21
21
  - !ruby/object:Gem::Version
22
- version: '13.0'
22
+ version: '0'
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
- - - "~>"
27
+ - - ">="
28
28
  - !ruby/object:Gem::Version
29
- version: '13.0'
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ requirements:
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: '0'
37
+ type: :development
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
30
44
  - !ruby/object:Gem::Dependency
31
45
  name: rspec
32
46
  requirement: !ruby/object:Gem::Requirement
33
47
  requirements:
34
- - - "~>"
48
+ - - ">="
35
49
  - !ruby/object:Gem::Version
36
- version: '3.0'
37
- type: :runtime
50
+ version: '0'
51
+ type: :development
38
52
  prerelease: false
39
53
  version_requirements: !ruby/object:Gem::Requirement
40
54
  requirements:
41
- - - "~>"
55
+ - - ">="
42
56
  - !ruby/object:Gem::Version
43
- version: '3.0'
57
+ version: '0'
44
58
  - !ruby/object:Gem::Dependency
45
- name: rqrcode
59
+ name: rubocop
46
60
  requirement: !ruby/object:Gem::Requirement
47
61
  requirements:
48
- - - "~>"
62
+ - - ">="
49
63
  - !ruby/object:Gem::Version
50
- version: '2.0'
51
- type: :runtime
64
+ version: '0'
65
+ type: :development
52
66
  prerelease: false
53
67
  version_requirements: !ruby/object:Gem::Requirement
54
68
  requirements:
55
- - - "~>"
69
+ - - ">="
56
70
  - !ruby/object:Gem::Version
57
- version: '2.0'
71
+ version: '0'
58
72
  description: Ruby gem for Qrcode generation of Pix (Pagamento Instantâneo Brasileiro
59
73
  - Banco Central do Brasil)
60
74
  email:
@@ -67,9 +81,11 @@ extensions: []
67
81
  extra_rdoc_files: []
68
82
  files:
69
83
  - ".github/workflows/ci.yml"
84
+ - ".github/workflows/heroku.yml"
70
85
  - ".github/workflows/rubygems.yml"
71
86
  - ".gitignore"
72
87
  - ".rspec"
88
+ - ".rubocop.yml"
73
89
  - CHANGELOG.md
74
90
  - CODE_OF_CONDUCT.md
75
91
  - Dockerfile
@@ -79,6 +95,8 @@ files:
79
95
  - Rakefile
80
96
  - bin/console
81
97
  - bin/setup
98
+ - demo/Gemfile
99
+ - demo/config.ru
82
100
  - lib/qrcode_pix_ruby.rb
83
101
  - lib/qrcode_pix_ruby/payload.rb
84
102
  - lib/qrcode_pix_ruby/version.rb
@@ -99,14 +117,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
99
117
  requirements:
100
118
  - - ">="
101
119
  - !ruby/object:Gem::Version
102
- version: '0'
120
+ version: 2.3.0
103
121
  required_rubygems_version: !ruby/object:Gem::Requirement
104
122
  requirements:
105
123
  - - ">="
106
124
  - !ruby/object:Gem::Version
107
125
  version: '0'
108
126
  requirements: []
109
- rubygems_version: 3.2.15
127
+ rubygems_version: 3.2.22
110
128
  signing_key:
111
129
  specification_version: 4
112
130
  summary: Ruby gem for Qrcode generation of Pix (Pagamento Instantâneo Brasileiro -