speed_lightning 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: 873dc581d778ff28ddf947b0428a9ce7cc9112c3d756aebc3d11f2a2cb0eca9d
4
- data.tar.gz: 7f86596739118e2922355710e5323f4e4571987bd8f7400a949e751cc0b61e1a
3
+ metadata.gz: 9034ae11f5f106f8cc3e21fcef837d9dba63cb76a9ea97d44a0b4a7e38456b51
4
+ data.tar.gz: 14aa426f9f97f9cf73c172f5ae0da7abc40adf0567338bf583e3fc9b7e80c92b
5
5
  SHA512:
6
- metadata.gz: 90366e79f73dbc5791417310628d86a934c88520f276e5a3990357d6232c61095c470e2300618724e58f1509026be0f0aad45ae0f63edcc8032848dcd36a63e9
7
- data.tar.gz: 2e0f6f97fff00a90e3a5c841a14515e50757c13fc67cdea33ddca3a10ec1dbfa6db8ee3eecc0b0223449b3d4b4f159fd827317a93bb51dc7953e34140106042d
6
+ metadata.gz: b1da6165b682e214932c86956b9958a0f48fb7ff1e169f243c229dca4a3331286ff2e87320eb0cb3139711abf00ca84dcae78b014dceb8e7ba08765c32a7a465
7
+ data.tar.gz: 6a217f61ca76f1356e3cccfa713d88a15e24cc4b195f6e47262320d2aa1bf7c7621f6a7d562edffec519c1799df790b0af663697e606cdb3c6af8827aa4179b6
data/.gitignore CHANGED
@@ -6,3 +6,5 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
+ *.gem
10
+ pkg/*
data/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.2.0] - 2023-10-24
4
+
5
+ ### Added
6
+ - Added support for named parameters in client initialization and method calls for better readability and flexibility.
7
+ - Introduced `Retryable` module for retrying failed requests.
8
+ - Introduced error handling with `SpeedLightning::Error`.
9
+ - Added convenience paid? method to check if payment has been completed.
10
+
11
+ ### Changed
12
+ - Improved the file structure.
13
+ - Renamed methods for creating and retrieving checkout links.
14
+ - Modified client initialization to use named parameter `secret_key`.
15
+ - Refactored `CheckoutLink` class to handle raw API attributes and conversion to Ruby time objects.
16
+
17
+ ## [0.1.1] - 2023-10-23
18
+
19
+ - Minor updates for publishing to RubyGems
20
+
3
21
  ## [0.1.0] - 2023-10-22
4
22
 
5
23
  - Initial release
data/DOCUMENTATION.md ADDED
@@ -0,0 +1,134 @@
1
+ # Speed Lightning Documentation
2
+
3
+ ## Introduction
4
+ This gem makes the Speed Lightning service easier to access from within your Ruby project.
5
+
6
+ It's a "lightly opinionated" gem making a few assumptions about how you will use the API in order to both harden it against failures, and to simplify the operation:
7
+ * By default requests are in livemode: false, meaning it's test mode
8
+ * A successful payment always returns to a success url within your app, instead of displaying a success message within the Speed interface
9
+ * If requests fail, the gem will retry once, before raising an error
10
+ * Target currency is hardcoded as Bitcoin Satoshis "SATS"
11
+ * Created and modified times are converted to Ruby time objects as created_at and updated_at to follow conventions
12
+ * Default metadata includes `client: "ruby"`, so override it with an empty or your own hash if you want to remove this default
13
+ * success_message, cashback, statement_descriptor, object, target_currency, payment_id array are only available within raw_attribute
14
+
15
+ ## Table of Contents
16
+ - [Initialization](#initialization)
17
+ - [Checkout Link](#checkout-link-object)
18
+ - [Error Handling](#error-handling)
19
+
20
+ ## Initialization
21
+ ```
22
+ require 'speed_lightning'
23
+ client = SpeedLightning::Client.new(secret_key: ENV["SPEED_API_SECRET"])
24
+ ```
25
+ ## Checkout Link Object
26
+
27
+ ### Available Parameters
28
+
29
+ * id: speed payment id
30
+ * amount: payment amount in satoshis
31
+ * currency: "SATS" by default
32
+ * url: payment url to be presented to users
33
+ * success_url: url the user is forwarded to after successful payment
34
+ * status: payment status
35
+ * metadata: metadata to link speed payment with ruby application data
36
+ * is_email_enabled: true if user needs to provide email to pay
37
+ * is_phone_enabled: true if user needs to provide phone to pay
38
+ * is_billing_address_enabled: true if user needs to provide billing address to pay
39
+ * is_shipping_address_enabled: true if user needs to provide shipping address to pay
40
+ * livemode: default is false for test mode, true is live
41
+ * created_at: ruby time object
42
+ * updated_at: ruby time object
43
+ * raw_attributes: the raw data returned by the Speed API
44
+
45
+ ### Convenience Methods
46
+
47
+ * paid? : returns true if payment has been completed
48
+
49
+ ### Create
50
+
51
+ Basic usage with only required parameters, the invoice amount and the success return url:
52
+ ```
53
+ client.create_checkout_link(777, "https://yourwebsite.com/thank_you")
54
+ ```
55
+
56
+ Advanced usage with all supported parameters:
57
+ ```
58
+ amount = 777
59
+ currency = "SATS"
60
+ ```
61
+
62
+ The user forwarded to the success url after successful payment (note: `localhost:3000/thank_you` won't validate):
63
+ ```
64
+ success_url = "https://your_website.com/thank_you"
65
+ ```
66
+
67
+ Add optional metadata that links the speed payment with your application data:
68
+ ```
69
+ metadata = {
70
+ order_id: 1,
71
+ user_id: 1,
72
+ product_id: "subscription"}
73
+ ```
74
+
75
+ Options that need to be filled by the customer before processing the payment. Default is all false:
76
+ ```
77
+ is_phone_enabled = false
78
+ is_email_enabled = true
79
+ is_billing_address_enabled = false
80
+ is_shipping_address_enabled = false
81
+ ```
82
+
83
+ For the livemode parameter the default `false` boolean means test payment on testnet, `true` means live payment on livenet:
84
+ ```
85
+ livemode = false
86
+ ```
87
+
88
+ Finally, make a request:
89
+ ```
90
+ checkout_link_object = client.create_checkout_link(
91
+ amount: amount,
92
+ success_url: success_url,
93
+ currency: currency,
94
+ metadata: metadata,
95
+ is_phone_enabled: is_phone_enabled,
96
+ is_email_enabled: is_email_enabled,
97
+ is_billing_address_enabled: is_billing_address_enabled,
98
+ is_shipping_address_enabled: is_shipping_address_enabled,
99
+ livemode: livemode)
100
+ ```
101
+
102
+ If creation of object is successful, you can get payment data:
103
+ * id of the checkout link, needed to retrieve it later: `checkout_link_object.id`
104
+ * url of the checkout link, show to customer so they can pay: `checkout_link_object.url`
105
+ * metadata hash of the payment: `checkout_link_object.metadata`
106
+ * email collection status: `checkout_link_object.is_email_enabled`
107
+ * test or live mode: `checkout_link_object.livemode`
108
+
109
+ To test payments, you can login to speed and pay the invoice with test satoshis: https://www.ln.dev
110
+
111
+ ### Retrieve
112
+
113
+ Retrieve a checkout link with the checkout link object's id:
114
+ ```
115
+ retrieved_object = client.retrieve_checkout_link(checkout_link_object.id)
116
+ ```
117
+
118
+ Get metadata of the payment, for example order_id: `retrieved_object.metadata["order_id"]`
119
+
120
+ Get raw attributes: `retrieved_object.raw_attributes`
121
+
122
+ ## Error handling
123
+ If the request fails, the gem retries once after one second. If it fails again it raises an error.
124
+
125
+ Example of how to deal with an error in your application:
126
+ ```
127
+ begin
128
+ checkout_link_object = client.create_checkout_link(11, "invalid url...")
129
+ rescue SpeedLightning::Error => e
130
+ # Do something when request fails
131
+ puts "Speed API error detected: #{e.message}"
132
+ end
133
+
134
+ ```
data/Gemfile CHANGED
@@ -1,10 +1,2 @@
1
- # frozen_string_literal: true
2
-
3
1
  source "https://rubygems.org"
4
-
5
- # Specify your gem's dependencies in speed_lightning.gemspec
6
- gemspec
7
-
8
- gem "rake", "~> 13.0"
9
-
10
- gem "minitest", "~> 5.0"
2
+ gemspec
data/Gemfile.lock CHANGED
@@ -1,12 +1,18 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- speed_lightning (0.1.0)
4
+ speed_lightning (0.2.0)
5
+ httparty (~> 0.21.0)
5
6
 
6
7
  GEM
7
8
  remote: https://rubygems.org/
8
9
  specs:
10
+ httparty (0.21.0)
11
+ mini_mime (>= 1.0.0)
12
+ multi_xml (>= 0.5.2)
13
+ mini_mime (1.1.5)
9
14
  minitest (5.20.0)
15
+ multi_xml (0.6.0)
10
16
  rake (13.0.6)
11
17
 
12
18
  PLATFORMS
data/README.md CHANGED
@@ -22,7 +22,7 @@ Or install it yourself as:
22
22
 
23
23
  ## Usage
24
24
 
25
- Find full documentation of this gem and more examples under documentation.rb
25
+ Find full documentation of this gem and more examples: [Detailed Documentation](DOCUMENTATION.md)
26
26
 
27
27
  Optionally, if you are testing this gem without installing in IRB
28
28
  ```
@@ -36,27 +36,27 @@ Otherwise once bundled test in your own project:
36
36
 
37
37
  Initialize the library with Speed test environment secret key
38
38
 
39
- `client = SpeedLightning::Client.new("your_speed_secret_key_here")`
39
+ `client = SpeedLightning::Client.new(secret_key: "your_speed_secret_key_here")`
40
40
 
41
- create a new checkout link with required parameters: invoice amount, success return url
41
+ create a new checkout link with required parameters in test mode: invoice amount, success return url
42
42
 
43
- `response = client.create_speed_checkout_link(777, "https://yourwebsite.com/thank_you")`
43
+ `response = client.create_checkout_link(777, "https://your_website.com/thank_you")`
44
44
 
45
45
  get speed checkout url with QR code and LN invoice:
46
46
 
47
- `puts response["url"]`
47
+ `puts response.url`
48
48
 
49
49
  get speed checkout ID:
50
50
 
51
- `puts response["id"]`
51
+ `puts checkout_id = response.id`
52
52
 
53
53
  get invoice status
54
54
 
55
- `response = client.retrieve_speed_checkout_link(checkout_id)`
55
+ `response = client.retrieve_checkout_link(checkout_id)`
56
56
 
57
57
  get payment status
58
58
 
59
- `puts response["status"]`
59
+ `puts response.status`
60
60
 
61
61
  ## Development
62
62
 
@@ -0,0 +1,44 @@
1
+ class CheckoutLink
2
+ attr_accessor :id, :amount, :currency, :url, :success_url, :status, :metadata, :is_email_enabled, :is_phone_enabled, :is_billing_address_enabled, :is_shipping_address_enabled, :livemode, :created_at, :updated_at, :raw_attributes
3
+
4
+ def initialize(attributes = {})
5
+ @id = attributes['id']
6
+ @amount = attributes['amount']
7
+ @currency = attributes['currency']
8
+ @url = attributes['url']
9
+ @success_url = attributes['success_url']
10
+ @status = attributes['status']
11
+ @metadata = attributes['metadata']
12
+ @is_email_enabled = attributes.dig('customer_collections_status', 'is_email_enabled')
13
+ @is_phone_enabled = attributes.dig('customer_collections_status', 'is_phone_enabled')
14
+ @is_billing_address_enabled = attributes.dig('customer_collections_status', 'is_billing_address_enabled')
15
+ @is_shipping_address_enabled = attributes.dig('customer_collections_status', 'is_shipping_address_enabled')
16
+ @livemode = attributes['livemode']
17
+ # Convert the Unix timestamp in milliseconds to Ruby's Time object
18
+ @created_at = Time.at(attributes['created'] / 1000.0)
19
+ @updated_at = Time.at(attributes['modified'] / 1000.0)
20
+ @raw_attributes = attributes
21
+ end
22
+
23
+ def to_hash
24
+ {
25
+ id: @id,
26
+ amount: @amount,
27
+ currency: @currency,
28
+ success_url: @success_url,
29
+ metadata: @metadata,
30
+ customer_collections_status: {
31
+ is_email_enabled: @is_email_enabled,
32
+ is_phone_enabled: @is_phone_enabled,
33
+ is_billing_address_enabled: @is_billing_address_enabled,
34
+ is_shipping_address_enabled: @is_shipping_address_enabled
35
+ },
36
+ livemode: @livemode
37
+ }
38
+ end
39
+
40
+ def paid?
41
+ @status == "paid"
42
+ end
43
+
44
+ end
@@ -0,0 +1,48 @@
1
+ require_relative 'checkout_link'
2
+ require_relative 'retryable'
3
+
4
+ module SpeedLightning
5
+ module CheckoutLinkMethods
6
+ include Retryable
7
+
8
+ def create_checkout_link(
9
+ amount:,
10
+ success_url:,
11
+ currency: "SATS",
12
+ metadata: { client: "ruby" },
13
+ is_phone_enabled: false,
14
+ is_email_enabled: false,
15
+ is_billing_address_enabled: false,
16
+ is_shipping_address_enabled: false,
17
+ livemode: false
18
+ )
19
+ with_retry do
20
+ body_hash = {
21
+ amount: amount,
22
+ success_url: success_url,
23
+ currency: currency,
24
+ metadata: metadata,
25
+ customer_collections_status: {
26
+ is_email_enabled: is_email_enabled,
27
+ is_phone_enabled: is_phone_enabled,
28
+ is_billing_address_enabled: is_billing_address_enabled,
29
+ is_shipping_address_enabled: is_shipping_address_enabled
30
+ },
31
+ livemode: livemode
32
+ }
33
+ endpoint = "checkout-links"
34
+ response = make_request(endpoint, :post, body_hash)
35
+ CheckoutLink.new(response)
36
+ end
37
+ end
38
+
39
+ def retrieve_checkout_link(id)
40
+ with_retry do
41
+ endpoint = "checkout-links/" + id
42
+ response = make_request(endpoint, :get)
43
+ CheckoutLink.new(response)
44
+ end
45
+ end
46
+
47
+ end
48
+ end
@@ -0,0 +1,46 @@
1
+ require 'httparty'
2
+ require_relative 'error'
3
+ require_relative 'checkout_link_methods'
4
+
5
+ module SpeedLightning
6
+ class Client
7
+ include HTTParty
8
+ include CheckoutLinkMethods
9
+ attr_accessor :api_secret
10
+ API_URL = "https://api.tryspeed.com/"
11
+
12
+ def initialize(secret_key:)
13
+ @secret_key = secret_key
14
+ end
15
+
16
+ def make_request(endpoint, request_type, body_hash = nil)
17
+ headers = {
18
+ "Accept" => "application/json",
19
+ "Speed-Version" => "2022-04-15",
20
+ "Authorization" => "Basic " + Base64.strict_encode64(@secret_key + ":")
21
+ }
22
+ headers["Content-Type"] = "application/json" if body_hash
23
+ options = { headers: headers }
24
+ options[:body] = body_hash.to_json if body_hash
25
+ full_url = API_URL + endpoint
26
+ response =
27
+ case request_type
28
+ when :get
29
+ self.class.get(full_url, options)
30
+ when :post
31
+ self.class.post(full_url, options)
32
+ end
33
+
34
+ parsed_response = JSON.parse(response.body)
35
+
36
+ if parsed_response['errors'] && !parsed_response['errors'].empty?
37
+ error_messages = parsed_response['errors'].map { |error| error['message'] }.compact
38
+ concatenated_error_message = error_messages.join(', ')
39
+ raise SpeedLightning::Error, concatenated_error_message
40
+ end
41
+
42
+ parsed_response
43
+ end
44
+
45
+ end
46
+ end
@@ -0,0 +1,3 @@
1
+ module SpeedLightning
2
+ class Error < StandardError; end
3
+ end
@@ -0,0 +1,20 @@
1
+ module SpeedLightning
2
+ module Retryable
3
+
4
+ def with_retry
5
+ should_retry = true
6
+ begin
7
+ yield
8
+ rescue SpeedLightning::Error => e
9
+ if should_retry
10
+ should_retry = false
11
+ sleep 1
12
+ retry
13
+ else
14
+ raise e
15
+ end
16
+ end
17
+ end
18
+
19
+ end
20
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SpeedLightning
4
- VERSION = "0.1.0"
4
+ VERSION = "0.2.0"
5
5
  end
@@ -1,64 +1,12 @@
1
1
  require_relative "speed_lightning/version"
2
- require 'uri'
3
- require 'net/http'
2
+ require_relative "speed_lightning/error"
3
+ require_relative "speed_lightning/retryable"
4
+ require_relative "speed_lightning/checkout_link"
5
+ require_relative "speed_lightning/checkout_link_methods"
6
+ require_relative "speed_lightning/client"
7
+ require 'httparty'
4
8
  require 'base64'
5
9
  require 'json'
6
10
 
7
11
  module SpeedLightning
8
- class Error < StandardError; end
9
- class Client
10
- attr_accessor :api_secret
11
- API_URL = "https://api.tryspeed.com/"
12
-
13
- def initialize(api_secret)
14
- @api_secret = api_secret
15
- end
16
-
17
- def make_request(endpoint, request_type, body_hash = nil)
18
- key = "Basic " + Base64.strict_encode64(@api_secret+":") # no password necessary after colon
19
- url = URI(API_URL + endpoint)
20
- http = Net::HTTP.new(url.host, url.port)
21
- http.use_ssl = true
22
- request = request_type.new(url)
23
- request["accept"] = 'application/json'
24
- request["speed-version"] = '2022-04-15'
25
- request["authorization"] = key
26
- if body_hash
27
- request["content-type"] = 'application/json'
28
- request.body = body_hash.to_json
29
- end
30
- return JSON.parse(http.request(request).read_body)
31
- end
32
-
33
- def create_speed_checkout_link(
34
- amount,
35
- success_url,
36
- currency = "SATS",
37
- metadata = { client: "ruby" },
38
- customer_collections_status = {
39
- is_phone_enabled: false,
40
- is_email_enabled: false,
41
- is_billing_address_enabled: false,
42
- is_shipping_address_enabled: false
43
- }
44
- )
45
- body_hash = {
46
- amount: amount,
47
- success_url: success_url,
48
- currency: currency,
49
- metadata: metadata,
50
- customer_collections_status: customer_collections_status
51
- }
52
- endpoint = "checkout-links"
53
- request_type = Net::HTTP::Post
54
- return make_request(endpoint, request_type, body_hash)
55
- end
56
-
57
- def retrieve_speed_checkout_link(id)
58
- endpoint = "checkout-links/" + id
59
- request_type = Net::HTTP::Get
60
- return make_request(endpoint, request_type)
61
- end
62
-
63
- end
64
- end
12
+ end
@@ -25,5 +25,7 @@ Gem::Specification.new do |spec|
25
25
 
26
26
  spec.add_development_dependency "bundler", "> 2.0"
27
27
  spec.add_development_dependency "rake", "~> 13.0"
28
- spec.add_development_dependency 'minitest'
28
+ spec.add_development_dependency 'minitest', "~> 5.0"
29
+
30
+ spec.add_runtime_dependency "httparty", "~> 0.21.0"
29
31
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: speed_lightning
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
  - Ivan Raszl
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-10-22 00:00:00.000000000 Z
11
+ date: 2023-10-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -42,16 +42,30 @@ dependencies:
42
42
  name: minitest
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ">="
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '0'
47
+ version: '5.0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ">="
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '5.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: httparty
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.21.0
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
53
67
  - !ruby/object:Gem::Version
54
- version: '0'
68
+ version: 0.21.0
55
69
  description: 'For more information visit: https://www.speed.dev/'
56
70
  email:
57
71
  - iraszl@gmail.com
@@ -63,6 +77,7 @@ files:
63
77
  - ".gitignore"
64
78
  - CHANGELOG.md
65
79
  - CODE_OF_CONDUCT.md
80
+ - DOCUMENTATION.md
66
81
  - Gemfile
67
82
  - Gemfile.lock
68
83
  - LICENSE.txt
@@ -70,8 +85,12 @@ files:
70
85
  - Rakefile
71
86
  - bin/console
72
87
  - bin/setup
73
- - documentation.rb
74
88
  - lib/speed_lightning.rb
89
+ - lib/speed_lightning/checkout_link.rb
90
+ - lib/speed_lightning/checkout_link_methods.rb
91
+ - lib/speed_lightning/client.rb
92
+ - lib/speed_lightning/error.rb
93
+ - lib/speed_lightning/retryable.rb
75
94
  - lib/speed_lightning/version.rb
76
95
  - speed_lightning.gemspec
77
96
  homepage: https://github.com/iraszl/speed_lightning
data/documentation.rb DELETED
@@ -1,33 +0,0 @@
1
- # Initialize Speed Lightning client
2
- require 'speed_lightning'
3
- client = SpeedLightning::Client.new(ENV["SPEED_API_SECRET"])
4
-
5
- # Checkout Link
6
-
7
- # Basic usage with only required parameters: invoice amount, success return url:
8
- create_cl_response = client.create_speed_checkout_link(777, "https://yourwebsite.com/thank_you")
9
-
10
- # Advanced usage with all optional parameters:
11
- amount = 777
12
- success_url = "https://yourwebsite.com/thank_you"
13
- currency = "SATS"
14
- metadata = {
15
- order_id: 1,
16
- user_id: 1,
17
- product_id: 1c
18
- }
19
- customer_collections_status = {
20
- is_phone_enabled: false,
21
- is_email_enabled: true,
22
- is_billing_address_enabled: false,
23
- is_shipping_address_enabled: false
24
- }
25
- create_cl_response = client.create_speed_checkout_link(amount, success_url, currency, metadata, customer_collections_status)
26
- puts create_cl_response["id"] # id of the checkout link, needed to retrieve it later
27
- puts create_cl_response["url"] # url of the checkout link, show to customer so they can pay
28
- # pay the invoice with test bitcoins using: https://www.ln.dev
29
-
30
- # Retrieve a checkout link by id:
31
- id = create_cl_response["id"]
32
- retrieve_response = client.retrieve_speed_checkout_link(id)
33
- puts retrieve_response["status"] # status of the payment