taler 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 96d1418bd3c05ff024f0f3d8e478d9f5e8e2b3f69b05f900ae7c25306fd43d44
4
- data.tar.gz: d3f96d79ced6d329da2a79888a99cc7ecf4bc15ae1b4f8c13e2c776895265040
3
+ metadata.gz: 2264b54990f6df1015504ea8e2d51e9e0f3f9e8fb0d2e6948e32b900e4c899dd
4
+ data.tar.gz: ae655bb16c4a6d5e9aab5c5da7051d19895232388c2709b3d51e67f040137b0e
5
5
  SHA512:
6
- metadata.gz: 48c2d8cb20973d02cbb00117244c9820046da27d91f91bf96d4167749b8fd3b5fc8061e8782ec66d97036c6b1d0f99d37c309484198603837cbd381739809796
7
- data.tar.gz: 8a5c1273e9615eb168fa5a3aa6a2fa14f072c07044ca689720ede647b7ee54ac0bc3052800bbd56590130c0e38cac10705a0f944ef9adf88153de5004f1ff91c
6
+ metadata.gz: '0718fc34e186d2a5af60bad022efa7362eddcc4844b579aa417f43565b5004a0ddbfa1de83148540d6555dcd52f87bb7a09cfdf60d1b1dc90cba70ae0a35c50e'
7
+ data.tar.gz: 3f5b4abddbd440dd5df338aa0269b91360e3ed8cb8a91dd0e23a002b5d2b95b83cb80ec0cdba3beb3eae87dab31949a0037e6c8d98dff1d8a42def2fd180afec
data/.yardopts ADDED
@@ -0,0 +1,2 @@
1
+ --markup=markdown
2
+ --markup-provider=redcarpet
data/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  ## [Unreleased]
2
2
 
3
- ## [0.1.0] - 2025-10-14
3
+ ## [0.2.0] - 2026-02-02
4
+
5
+ - Add `Taler::Order` as an easier interface.
6
+ - Add method to refund orders.
7
+ - Add option for fulfillment message instead of fulfillment URL.
8
+ - Add documentation with yard.
9
+
10
+ ## [0.1.0] - 2026-01-19
11
+
12
+ - Add `Taler::Client` to create access token and orders. Fetch orders.
13
+
14
+ ## [0.0.0] - 2025-10-14
4
15
 
5
16
  - Initial release generated by bundler. Nothing to see yet.
data/README.md CHANGED
@@ -1,33 +1,59 @@
1
1
  # GNU Taler payment API for Ruby
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/taler`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ The Taler library let's you interact with a Taler merchant backend API to
4
+ take payments.
4
5
 
5
6
  ## Installation
6
7
 
7
- TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
8
-
9
- Install the gem and add to the application's Gemfile by executing:
10
-
11
8
  ```bash
12
- bundle add UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
9
+ gem install taler # or
10
+ bundle add taler
13
11
  ```
14
12
 
15
- If bundler is not being used to manage dependencies, install the gem by executing:
13
+ ## Usage
16
14
 
17
- ```bash
18
- gem install UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
15
+ ```rb
16
+ backend_url = "https://backend.demo.taler.net/instances/sandbox"
17
+ backend_password = "sandbox"
18
+
19
+ order = Taler::Order.new(backend_url:, password:)
20
+ order.create(
21
+ amount: "KUDOS:4",
22
+ summary: "Order total",
23
+ fulfillment_message: "Thank you!"
24
+ )
25
+
26
+ puts "Pay at: #{order.status_url}"
27
+
28
+ while order.fetch("order_status") == "unpaid"
29
+ sleep 1
30
+ order.reload
31
+ end
32
+
33
+ if order.fetch("order_status") == "paid"
34
+ puts "Great. All paid."
35
+ else
36
+ puts "Sorry, the order is #{order.fetch("order_status")}. Try again."
37
+ end
19
38
  ```
20
39
 
21
- ## Usage
40
+ Read more in the official documentation:
22
41
 
23
- TODO: Write usage instructions here
42
+ - https://rubydoc.info/gems/taler
24
43
 
25
44
  ## Development
26
45
 
27
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
46
+ After checking out the repo, run `bin/setup` to install dependencies.
47
+ Then, run `rake` to run the tests.
48
+ You can also run `bin/console` for an interactive prompt.
28
49
 
29
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
50
+ To install this gem onto your local machine, run `bundle exec rake install`.
51
+ To release a new version, update the version number in `version.rb`,
52
+ and then run `bundle exec rake release`, which will create a git tag for the
53
+ version, push git commits and the created tag, and push the `.gem` file
54
+ to [rubygems.org](https://rubygems.org).
30
55
 
31
56
  ## Contributing
32
57
 
33
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/taler.
58
+ Bug reports and pull requests are welcome on GitHub
59
+ at https://github.com/openfoodfoundation/taler-ruby.
data/lib/taler/client.rb CHANGED
@@ -4,6 +4,9 @@ require "json"
4
4
  require "net/http"
5
5
 
6
6
  module Taler
7
+ # Access the GNU Taler merchant backend API.
8
+ #
9
+ # See: https://docs.taler.net/core/api-merchant.html
7
10
  class Client
8
11
  def initialize(backend_url, password)
9
12
  @backend_url = backend_url
@@ -17,24 +20,33 @@ module Taler
17
20
  result.fetch("token")
18
21
  end
19
22
 
20
- def create_order(amount, summary, fulfillment_url)
23
+ def create_order(amount:, summary:, fulfillment_url: nil, fulfillment_message: nil)
21
24
  url = "#{@backend_url}/private/orders"
22
- payload = {
23
- order: {
24
- amount: amount,
25
- summary: summary,
26
- fulfillment_url: fulfillment_url
27
- },
28
- create_token: false
25
+ order = {
26
+ amount: amount,
27
+ summary: summary
29
28
  }
29
+ order[:fulfillment_url] = fulfillment_url unless fulfillment_url.nil?
30
+ order[:fulfillment_message] = fulfillment_message unless fulfillment_message.nil?
31
+ payload = {order:, create_token: false}
30
32
  request(url, payload:)
31
33
  end
32
34
 
35
+ def order_status_url(order_id)
36
+ "#{@backend_url}/orders/#{order_id}"
37
+ end
38
+
33
39
  def fetch_order(order_id)
34
40
  url = "#{@backend_url}/private/orders/#{order_id}"
35
41
  request(url)
36
42
  end
37
43
 
44
+ def refund_order(order_id, refund:, reason:)
45
+ url = "#{@backend_url}/private/orders/#{order_id}/refund"
46
+ payload = {refund:, reason:}
47
+ request(url, payload:)
48
+ end
49
+
38
50
  private
39
51
 
40
52
  def auth_token
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Taler
4
+ # Order representation with convenient access to the merchant API.
5
+ class Order
6
+ # Connect an Order to the Taler merchant backend.
7
+ #
8
+ # @param backend_url [String] e.g. `"https://backend.demo.taler.net/instances/sandbox"`
9
+ # @param password [String] e.g. `"sandbox"`
10
+ # @param id [String] The order id of an existing order.
11
+ def initialize(backend_url:, password:, id: nil)
12
+ @client = Client.new(backend_url, password)
13
+ @id = id
14
+ end
15
+
16
+ # Create a new order record ready to take a payment.
17
+ #
18
+ # @return [String] The id of the new order.
19
+ def create(amount:, summary:, fulfillment_url: nil, fulfillment_message: nil)
20
+ response = @client.create_order(
21
+ amount:, summary:, fulfillment_url:, fulfillment_message:
22
+ )
23
+ @id = response.fetch("order_id")
24
+ end
25
+
26
+ # The page where the customer can pay or accept a refund,
27
+ # depending on the state of the order.
28
+ #
29
+ # The merchant backend opens the Taler plugin or app if it can.
30
+ # Otherwise it shows a QR code to scan in the app and provides
31
+ # installation instructions.
32
+ def status_url
33
+ @client.order_status_url(@id)
34
+ end
35
+
36
+ # Access order status fields.
37
+ #
38
+ # It queries the backend if it hasn't done that already.
39
+ # Call `#reload` beforehand to get the latest status from the backend.
40
+ #
41
+ # @param key [String] A field in the order status response of the backend,
42
+ # e.g. `order_status`.
43
+ # @return [String,TrueClass,FalseClass] The value of the field.
44
+ # Any simple type supported by JSON.
45
+ def fetch(key)
46
+ reload unless @status
47
+ @status.fetch(key)
48
+ end
49
+
50
+ # Query the latest order information from the backend.
51
+ #
52
+ # If you called `#fetch` in the past and are expecting updates from
53
+ # user interaction, you want to call this.
54
+ def reload
55
+ @status = @client.fetch_order(@id)
56
+ end
57
+
58
+ # Issue a refund request for this order.
59
+ #
60
+ # @param refund [String] The amount with currency.
61
+ # @param reason [String] Why are you refunding?
62
+ #
63
+ # @return [Hash] Response from the merchant backend.
64
+ def refund(refund:, reason:)
65
+ @client.refund_order(@id, refund:, reason:)
66
+ end
67
+ end
68
+ end
data/lib/taler/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Taler
4
- VERSION = "0.1.0"
4
+ VERSION = "0.2.0"
5
5
  end
data/lib/taler.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "taler/client"
4
+ require_relative "taler/order"
4
5
  require_relative "taler/version"
5
6
 
6
7
  module Taler
data/sig/client.rbs ADDED
@@ -0,0 +1,23 @@
1
+ module Taler
2
+ class Client
3
+ @backend_url: untyped
4
+
5
+ @password: untyped
6
+
7
+ def initialize: (untyped backend_url, untyped password) -> void
8
+
9
+ def request_token: () -> untyped
10
+
11
+ def create_order: (untyped amount, untyped summary, untyped fulfillment_url) -> untyped
12
+
13
+ def fetch_order: (untyped order_id) -> untyped
14
+
15
+ private
16
+
17
+ def auth_token: () -> ::String
18
+
19
+ def get: (untyped url, ?untyped token) -> untyped
20
+
21
+ def request: (untyped url, ?token: untyped, ?payload: untyped?) -> untyped
22
+ end
23
+ end
metadata CHANGED
@@ -1,14 +1,127 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: taler
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Maikel Linke
8
8
  bindir: bin
9
9
  cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
- dependencies: []
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: irb
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '0'
19
+ type: :development
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '0'
26
+ - !ruby/object:Gem::Dependency
27
+ name: rake
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ - !ruby/object:Gem::Dependency
41
+ name: rspec
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ type: :development
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ - !ruby/object:Gem::Dependency
55
+ name: vcr
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ type: :development
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ - !ruby/object:Gem::Dependency
69
+ name: webmock
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ type: :development
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ - !ruby/object:Gem::Dependency
83
+ name: standard
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ type: :development
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ - !ruby/object:Gem::Dependency
97
+ name: yard
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ type: :development
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: redcarpet
112
+ requirement: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ type: :development
118
+ prerelease: false
119
+ version_requirements: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ description: Create and refund orders through the Taler merchant backend API.
12
125
  email:
13
126
  - maikel@email.org.au
14
127
  executables: []
@@ -17,13 +130,16 @@ extra_rdoc_files: []
17
130
  files:
18
131
  - ".rspec"
19
132
  - ".standard.yml"
133
+ - ".yardopts"
20
134
  - CHANGELOG.md
21
135
  - LICENSE
22
136
  - README.md
23
137
  - Rakefile
24
138
  - lib/taler.rb
25
139
  - lib/taler/client.rb
140
+ - lib/taler/order.rb
26
141
  - lib/taler/version.rb
142
+ - sig/client.rbs
27
143
  - sig/taler.rbs
28
144
  homepage: https://github.com/openfoodfoundation/taler-ruby
29
145
  licenses:
@@ -38,7 +154,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
38
154
  requirements:
39
155
  - - ">="
40
156
  - !ruby/object:Gem::Version
41
- version: 3.1.0
157
+ version: 3.4.0
42
158
  required_rubygems_version: !ruby/object:Gem::Requirement
43
159
  requirements:
44
160
  - - ">="