speed_lightning 0.1.1 → 0.2.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: 2d495358c9ef893d5c40687eea21f711202f0eaf44d8df04d01542558587169e
4
- data.tar.gz: c9296ec50d68213968a7b5c7c3f475e89710d62e5ff07cd3b9b145bb59001517
3
+ metadata.gz: 9034ae11f5f106f8cc3e21fcef837d9dba63cb76a9ea97d44a0b4a7e38456b51
4
+ data.tar.gz: 14aa426f9f97f9cf73c172f5ae0da7abc40adf0567338bf583e3fc9b7e80c92b
5
5
  SHA512:
6
- metadata.gz: 6fbed22ee55ca5bc121685ddf5e062591fe181bc632906d41682092233e57c6c7cde8cdf81d0686805966ca9d5ccdd40d3c529268702fb246690d0aaac25538c
7
- data.tar.gz: b1a6b1174aaaa8752f10795812545d469c9934cc691a5aec0d91ed2bc069d92732c04fd9c4ead727530d9828787bcd00e8c112c53b73f09f8168fbb774208db2
6
+ metadata.gz: b1da6165b682e214932c86956b9958a0f48fb7ff1e169f243c229dca4a3331286ff2e87320eb0cb3139711abf00ca84dcae78b014dceb8e7ba08765c32a7a465
7
+ data.tar.gz: 6a217f61ca76f1356e3cccfa713d88a15e24cc4b195f6e47262320d2aa1bf7c7621f6a7d562edffec519c1799df790b0af663697e606cdb3c6af8827aa4179b6
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.1"
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.1
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