nicepay_ruby 1.0.0 → 1.1.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.
@@ -0,0 +1,99 @@
1
+ module NicepayRuby
2
+ class Config
3
+ @is_production = false
4
+ @is_cloud_server = false
5
+
6
+ class << self
7
+ attr_accessor :is_production, :is_cloud_server
8
+
9
+ def get_sandbox_cloud
10
+ "https://dev-services.nicepay.co.id/"
11
+ end
12
+
13
+ def get_production_cloud
14
+ "https://services.nicepay.co.id/"
15
+ end
16
+
17
+ def get_sandbox_base_url
18
+ "https://dev.nicepay.co.id/"
19
+ end
20
+
21
+ def get_production_base_url
22
+ "https://www.nicepay.co.id/"
23
+ end
24
+
25
+ def base_url
26
+ if @is_cloud_server
27
+ @is_production ? get_production_cloud : get_sandbox_cloud
28
+ else
29
+ @is_production ? get_production_base_url : get_sandbox_base_url
30
+ end
31
+ end
32
+
33
+ def set_environment(production:, cloud_server:)
34
+ @is_production = production
35
+ @is_cloud_server = cloud_server
36
+ end
37
+ end
38
+ end
39
+
40
+ class ApiEndpoints
41
+ attr_reader :create_va, :inquiry_va, :delete_va,
42
+ :payment_ewallet, :status_ewallet, :refund_ewallet,
43
+ :access_token,
44
+ :generate_qris, :status_qris, :refund_qris,
45
+ :create_payout, :approve_payout, :inquiry_payout,
46
+ :cancel_payout, :reject_payout, :balance_payout,
47
+ :regist_v2, :inquiry_v2, :cancel_v2,
48
+ :regist_payout_v2, :inquiry_payout_v2, :reject_payout_v2,
49
+ :approve_payout_v2, :balance_inquiry_v2,
50
+ :regist_redirect_v2
51
+
52
+ def initialize
53
+ # VA
54
+ @create_va = "nicepay/api/v1.0/transfer-va/create-va"
55
+ @inquiry_va = "nicepay/api/v1.0/transfer-va/status"
56
+ @delete_va = "nicepay/api/v1.0/transfer-va/delete-va"
57
+
58
+ # Ewallet
59
+ @payment_ewallet = "nicepay/api/v1.0/debit/payment-host-to-host"
60
+ @status_ewallet = "nicepay/api/v1.0/debit/status"
61
+ @refund_ewallet = "nicepay/api/v1.0/debit/refund"
62
+
63
+ # Auth
64
+ @access_token = "nicepay/v1.0/access-token/b2b"
65
+
66
+ # QRIS
67
+ @generate_qris = "nicepay/api/v1.0/qr/qr-mpm-generate"
68
+ @status_qris = "nicepay/api/v1.0/qr/qr-mpm-query"
69
+ @refund_qris = "nicepay/api/v1.0/qr/qr-mpm-refund"
70
+
71
+ # Payout V1
72
+ @create_payout = "nicepay/api/v1.0/transfer/registration"
73
+ @approve_payout = "nicepay/api/v1.0/transfer/approve"
74
+ @inquiry_payout = "nicepay/api/v1.0/transfer/inquiry"
75
+ @cancel_payout = "nicepay/api/v1.0/transfer/cancel"
76
+ @reject_payout = "nicepay/api/v1.0/transfer/reject"
77
+ @balance_payout = "nicepay/api/v1.0/balance-inquiry"
78
+
79
+ # Direct V2
80
+ @regist_v2 = "nicepay/direct/v2/registration"
81
+ @inquiry_v2 = "nicepay/direct/v2/inquiry"
82
+ @cancel_v2 = "nicepay/direct/v2/cancel"
83
+ @regist_payout_v2 = "nicepay/api/direct/v2/requestPayout"
84
+ @inquiry_payout_v2 = "nicepay/api/direct/v2/inquiryPayout"
85
+ @reject_payout_v2 = "nicepay/api/direct/v2/rejectPayout"
86
+ @approve_payout_v2 = "nicepay/api/direct/v2/approvePayout"
87
+ @balance_inquiry_v2 = "nicepay/api/direct/v2/balanceInquiry"
88
+
89
+ # Redirect
90
+ @regist_redirect_v2 = "nicepay/redirect/v2/registration"
91
+ end
92
+
93
+ # helper buat gabung base_url + endpoint
94
+ def full_url(path)
95
+ "#{NicepayRuby::Config.base_url}#{path}"
96
+ end
97
+
98
+ end
99
+ end
@@ -0,0 +1,122 @@
1
+ require 'net/http'
2
+ require 'uri'
3
+ require 'json'
4
+ require_relative 'signatureUtils'
5
+
6
+ module NicepayRuby
7
+ class ServiceApi
8
+ def initialize(endpoints: nil, client_id: nil, client_secret: nil, channel_id: nil, is_production:, is_cloud_server:)
9
+ @endpoints = endpoints
10
+ @client_id = client_id
11
+ @client_secret = client_secret
12
+ @channel_id = channel_id
13
+ @is_production = is_production
14
+ @is_cloud_server = is_cloud_server
15
+
16
+ # Set environment global
17
+ NicepayRuby::Config.set_environment(
18
+ production: is_production,
19
+ cloud_server: is_cloud_server
20
+ )
21
+ end
22
+
23
+ # ==============================
24
+ # NON-SNAP (simple POST request)
25
+ # ==============================
26
+ def send_post(endpoint, request_body)
27
+ return "Error: Request body is null or empty." if request_body.nil? || request_body.empty?
28
+
29
+ full_url = build_url(endpoint)
30
+ puts "[DEBUG] endpoint: #{full_url}"
31
+
32
+ begin
33
+ json_body = request_body.to_json
34
+ uri = URI(full_url)
35
+ http = Net::HTTP.new(uri.host, uri.port)
36
+ http.use_ssl = uri.scheme == "https"
37
+
38
+ headers = { "Content-Type" => "application/json" }
39
+ request = Net::HTTP::Post.new(uri.request_uri, headers)
40
+ request.body = json_body
41
+
42
+ response = http.request(request)
43
+ body = response.body
44
+
45
+ response.is_a?(Net::HTTPSuccess) ? body : "Error: #{response.code} - #{response.message}\nResponse: #{body}"
46
+ rescue => e
47
+ "Exception occurred: #{e.message}"
48
+ end
49
+ end
50
+
51
+ # ==============================
52
+ # SNAP (secure request w/ signature)
53
+ # ==============================
54
+ def send_post_request(endpoint, access_token, timestamp, request_body, external_id)
55
+ signature = SignatureGeneratorUtils.get_signature(
56
+ "POST", access_token, request_body, endpoint, timestamp, @client_secret
57
+ )
58
+ full_url = build_full_url(endpoint)
59
+ puts "[DEBUG][SNAP POST] #{full_url}"
60
+
61
+ uri = URI(full_url)
62
+ http = Net::HTTP.new(uri.host, uri.port)
63
+ http.use_ssl = true
64
+
65
+ headers = build_snap_headers(signature, access_token, timestamp, external_id)
66
+ request = Net::HTTP::Post.new(uri.path, headers)
67
+ request.body = request_body.to_json
68
+
69
+ response = http.request(request)
70
+ response.body
71
+ end
72
+
73
+ def send_delete_request(endpoint, access_token, timestamp, request_body, external_id)
74
+ signature = SignatureGeneratorUtils.get_signature(
75
+ "DELETE", access_token, request_body, endpoint, timestamp, @client_secret
76
+ )
77
+ full_url = build_full_url(endpoint)
78
+ puts "[DEBUG][SNAP DELETE] #{full_url}"
79
+
80
+ uri = URI(full_url)
81
+ http = Net::HTTP.new(uri.host, uri.port)
82
+ http.use_ssl = true
83
+
84
+ headers = build_snap_headers(signature, access_token, timestamp, external_id)
85
+ request = Net::HTTP::Delete.new(uri.path, headers)
86
+ request.body = request_body.to_json
87
+
88
+ response = http.request(request)
89
+ response.body
90
+ end
91
+
92
+ private
93
+
94
+ # ===== Non-snap builder =====
95
+ def build_url(endpoint)
96
+ base_url = if @is_cloud_server
97
+ @is_production ? NicepayRuby::Config.get_production_cloud : NicepayRuby::Config.get_sandbox_cloud
98
+ else
99
+ @is_production ? NicepayRuby::Config.get_production_base_url : NicepayRuby::Config.get_sandbox_base_url
100
+ end
101
+ URI.join(base_url, endpoint).to_s
102
+ end
103
+
104
+ # ===== Snap builder =====
105
+ def build_full_url(endpoint)
106
+ base_url = NicepayRuby::Config.base_url
107
+ URI.join(base_url, endpoint).to_s
108
+ end
109
+
110
+ def build_snap_headers(signature, access_token, timestamp, external_id)
111
+ {
112
+ "X-TIMESTAMP" => timestamp,
113
+ "X-SIGNATURE" => signature,
114
+ "Authorization" => "Bearer #{access_token}",
115
+ "X-PARTNER-ID" => @client_id,
116
+ "X-EXTERNAL-ID" => external_id,
117
+ "CHANNEL-ID" => @channel_id,
118
+ "Content-Type" => "application/json"
119
+ }
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,100 @@
1
+
2
+ require 'openssl'
3
+ require 'base64'
4
+ require 'json'
5
+ require 'digest'
6
+
7
+ module NicepayRuby
8
+ class SignatureGeneratorUtils
9
+ def initialize
10
+ @client_id = NicepayRuby.configuration.client_id
11
+ @private_key = OpenSSL::PKey::RSA.new(NicepayRuby.configuration.private_key)
12
+ end
13
+
14
+ def self.generate_string_to_sign(client_id, timestamp)
15
+ "#{client_id}|#{timestamp}"
16
+ end
17
+
18
+ # Generate signature for access token (SHA256withRSA)
19
+ def self.generate_signature(private_key_base64, client_id, timestamp)
20
+ string_to_sign = generate_string_to_sign(client_id, timestamp)
21
+ private_key_der = Base64.decode64(private_key_base64)
22
+
23
+ rsa = OpenSSL::PKey::RSA.new(private_key_der)
24
+ signature = rsa.sign(OpenSSL::Digest::SHA256.new, string_to_sign)
25
+ Base64.strict_encode64(signature)
26
+ end
27
+
28
+ # Generate API signature using HMAC-SHA512
29
+ def self.get_signature(http_method, access_token, request_body, endpoint, timestamp, client_secret)
30
+ json_body = JSON.generate(request_body)
31
+ hashed_body = sha256_encode_hex(json_body)
32
+ endpoint_sign = endpoint.sub(/^nicepay/, '')
33
+
34
+ string_to_sign = "#{http_method}:#{endpoint_sign}:#{access_token}:#{hashed_body}:#{timestamp}"
35
+ puts "String to Sign: #{string_to_sign}"
36
+
37
+ hmac_sha512_encode_base64(client_secret, string_to_sign)
38
+ end
39
+
40
+
41
+ # HMAC SHA512 encoding (for API signature)
42
+ def self.hmac_sha512_encode_base64(key, data)
43
+ hmac = OpenSSL::HMAC.digest('sha512', key, data)
44
+ Base64.strict_encode64(hmac)
45
+ end
46
+
47
+ # SHA256 in hex string
48
+ def self.sha256_encode_hex(data)
49
+ Digest::SHA256.hexdigest(data)
50
+ end
51
+
52
+ # Generate random numeric string
53
+ def self.generate_random_number_string(length)
54
+ Array.new(length) { rand(0..9) }.join
55
+ end
56
+
57
+ # Optional: SHA256 encrypt utility
58
+ def self.sha256_encrypt(value)
59
+ Digest::SHA256.hexdigest(value)
60
+ end
61
+
62
+ # Parse JSON and generate payment URL from response
63
+ def self.generate_payment_url(json_response)
64
+ begin
65
+ json = JSON.parse(json_response)
66
+ txid = json["tXid"]
67
+ payment_url = json["paymentURL"]
68
+ return "#{payment_url}?tXid=#{txid}" if txid && payment_url
69
+ rescue => e
70
+ puts "Error parsing payment URL: #{e.message}"
71
+ end
72
+ nil
73
+ end
74
+
75
+ # Optional: Verify signature (public key based)
76
+ def self.verify_sha256_rsa(string_to_sign, public_key_base64, signature_base64)
77
+ public_key_der = Base64.decode64(public_key_base64)
78
+ public_key = OpenSSL::PKey::RSA.new(public_key_der)
79
+ signature = Base64.decode64(signature_base64)
80
+
81
+ is_valid = public_key.verify(OpenSSL::Digest::SHA256.new, signature, string_to_sign)
82
+ puts "Signature is #{is_valid ? 'valid' : 'invalid'}"
83
+ is_valid
84
+ rescue => e
85
+ puts "Error verifying signature: #{e.message}"
86
+ false
87
+
88
+ end
89
+
90
+ def sha256_hex_minified(json_body)
91
+ minified = JSON.generate(JSON.parse(json_body)) # ensure no spaces, sorted
92
+ Digest::SHA256.hexdigest(minified)
93
+ end
94
+
95
+ def self.encrypt(value)
96
+ Digest::SHA256.hexdigest(value)
97
+ end
98
+
99
+ end
100
+ end
data/lib/nicepay_ruby.rb CHANGED
@@ -0,0 +1,34 @@
1
+ # lib/nicepay_ruby.rb
2
+ require_relative "nicepay_ruby/Utils/configuration"
3
+ require_relative "nicepay_ruby/Utils/signatureUtils"
4
+ require_relative "nicepay_ruby/Utils/accessToken"
5
+ require_relative "nicepay_ruby/Utils/merchantToken"
6
+ require_relative "nicepay_ruby/Utils/nicepayConstant"
7
+ require_relative "nicepay_ruby/Utils/serviceUtils"
8
+ require_relative "builder_file"
9
+
10
+ require_relative "nicepay_ruby/Builder/SNAP/VA"
11
+ require_relative "nicepay_ruby/Builder/SNAP/Ewallet"
12
+ require_relative "nicepay_ruby/Builder/SNAP/QRIS"
13
+ require_relative "nicepay_ruby/Builder/SNAP/Payout"
14
+
15
+ require_relative "nicepay_ruby/Builder/V2/VA"
16
+ require_relative "nicepay_ruby/Builder/V2/Ewallet"
17
+ require_relative "nicepay_ruby/Builder/V2/QRIS"
18
+ require_relative "nicepay_ruby/Builder/V2/Payout"
19
+ require_relative "nicepay_ruby/Builder/V2/CC"
20
+ require_relative "nicepay_ruby/Builder/V2/Inquiry"
21
+ require_relative "nicepay_ruby/Builder/V2/Cancel"
22
+ require_relative "nicepay_ruby/Builder/V2/Redirect"
23
+
24
+
25
+ module NicepayRuby
26
+ class << self
27
+ attr_accessor :configuration
28
+ end
29
+
30
+ def self.configure
31
+ self.configuration ||= Configuration.new
32
+ yield(configuration)
33
+ end
34
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nicepay_ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - NICEPay_Integration
@@ -18,7 +18,26 @@ extensions: []
18
18
  extra_rdoc_files: []
19
19
  files:
20
20
  - README.md
21
+ - lib/builder_file.rb
21
22
  - lib/nicepay_ruby.rb
23
+ - lib/nicepay_ruby/Builder/SNAP/Ewallet.rb
24
+ - lib/nicepay_ruby/Builder/SNAP/Payout.rb
25
+ - lib/nicepay_ruby/Builder/SNAP/QRIS.rb
26
+ - lib/nicepay_ruby/Builder/SNAP/VA.rb
27
+ - lib/nicepay_ruby/Builder/V2/CC.rb
28
+ - lib/nicepay_ruby/Builder/V2/Cancel.rb
29
+ - lib/nicepay_ruby/Builder/V2/Ewallet.rb
30
+ - lib/nicepay_ruby/Builder/V2/Inquiry.rb
31
+ - lib/nicepay_ruby/Builder/V2/Payout.rb
32
+ - lib/nicepay_ruby/Builder/V2/QRIS.rb
33
+ - lib/nicepay_ruby/Builder/V2/Redirect.rb
34
+ - lib/nicepay_ruby/Builder/V2/VA.rb
35
+ - lib/nicepay_ruby/Utils/accessToken.rb
36
+ - lib/nicepay_ruby/Utils/configuration.rb
37
+ - lib/nicepay_ruby/Utils/merchantToken.rb
38
+ - lib/nicepay_ruby/Utils/nicepayConstant.rb
39
+ - lib/nicepay_ruby/Utils/serviceUtils.rb
40
+ - lib/nicepay_ruby/Utils/signatureUtils.rb
22
41
  homepage: https://github.com/nicepay-dev/ruby-nicepay.git
23
42
  licenses:
24
43
  - MIT