tappay_ruby 0.7.0 → 0.8.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: ef378bc35a591f5a2c295d7e2c530e174484e200fde3413978081103c4a7a8e3
4
- data.tar.gz: b15ecfb7ad4c2f13093578a4bfc1a5468ad9b014b04fdc3e561128d6f33cfcbb
3
+ metadata.gz: d18643889a68b9dab0c275a18940d220af312803ee0d7099d67c0b6a9444d32e
4
+ data.tar.gz: 13d363e73d4e0626054c1114fb3d4ca8c2e99cdce1801726322734b6fe4cd9e7
5
5
  SHA512:
6
- metadata.gz: 85a20b681bcd1ba1dd830506a3fab64c81652ae61703790f38866cc6d452926272151918914ffaca2d5f01b5dcdcf94cd251dfc707c77b7fa2926934f8622f8b
7
- data.tar.gz: d72a42f89901fbe206b816d24397a6552326e509cb8c7959f05121091179fe0b50b7b61e075afc70a426e07ed1608e04cb1ae8c67a4c1cc50c3a8e7e3806b43f
6
+ metadata.gz: 92b2a1264def50c34cb1ad8c970bc04d9b0c1784096e0afe1968923603158415ece5469f8242fa9a8968c0574a9e56586c24b71dcd1abc9059a2d85554eca1a2
7
+ data.tar.gz: cb67371f349e6e378fbbe93723ef7926db7bc49f5eb1a96fea0ea00a3af65c0a173aab1bf2aeb8b6772398d8ad7702c5058ff046a3015190f2fd7ad06f37e1e2
data/README.md CHANGED
@@ -8,8 +8,10 @@ A Ruby library for integrating with TapPay payment services. This gem provides a
8
8
 
9
9
  ## Features
10
10
 
11
- - Credit card payments (one-time and tokenized)
12
- - Instalment payments
11
+ - Multiple payment methods:
12
+ - Credit card payments (one-time and tokenized)
13
+ - Instalment payments (3 to 24 months)
14
+ - Line Pay
13
15
  - Refund processing
14
16
  - Transaction status queries
15
17
  - Comprehensive error handling
@@ -59,7 +61,10 @@ Tappay.configure do |config|
59
61
  # OR
60
62
  config.merchant_group_id = 'your_merchant_group_id'.freeze
61
63
 
64
+ # Payment-specific merchant IDs
62
65
  config.instalment_merchant_id = 'your_instalment_merchant_id'.freeze
66
+ config.line_pay_merchant_id = 'your_line_pay_merchant_id'.freeze
67
+
63
68
  config.currency = 'TWD'.freeze
64
69
  config.vat_number = 'your_vat_number'.freeze
65
70
  end
@@ -67,22 +72,44 @@ end
67
72
 
68
73
  ### Merchant ID Configuration
69
74
 
70
- The gem supports two types of merchant identification:
71
- 1. `merchant_id`: Individual merchant ID
72
- 2. `merchant_group_id`: Group merchant ID
75
+ The gem supports flexible merchant ID configuration:
76
+
77
+ 1. Global merchant ID:
78
+ - `merchant_id`: Default merchant ID for all payments
79
+ - `merchant_group_id`: Group merchant ID (mutually exclusive with merchant_id)
73
80
 
74
- Important rules:
75
- - You can set either `merchant_id` or `merchant_group_id` in the configuration, but not both
76
- - When making a payment, you can override the configured merchant ID by providing either `merchant_id` or `merchant_group_id` in the payment options
77
- - If you provide merchant ID in the payment options, it will take precedence over any configuration
81
+ 2. Payment-specific merchant IDs:
82
+ - `instalment_merchant_id`: Specific merchant ID for instalment payments
83
+ - `line_pay_merchant_id`: Specific merchant ID for Line Pay transactions
78
84
 
79
- Example of overriding merchant ID in payment:
85
+ Merchant ID Priority:
86
+ 1. Payment options merchant ID (if provided in the payment call)
87
+ 2. Payment-specific merchant ID (if configured)
88
+ 3. Global merchant ID
89
+
90
+ Example of merchant ID usage:
80
91
  ```ruby
81
- # Using merchant_group_id in payment options
92
+ # Using default merchant ID
93
+ result = Tappay::CreditCard::Pay.by_prime(
94
+ prime: 'prime_from_tappay_sdk',
95
+ amount: 100,
96
+ order_number: 'ORDER-123'
97
+ )
98
+
99
+ # Using payment-specific merchant ID
100
+ # This will automatically use line_pay_merchant_id if configured
101
+ result = Tappay::LinePay::Pay.new(
102
+ prime: 'line_pay_prime',
103
+ amount: 100,
104
+ frontend_redirect_url: 'https://example.com/line_pay/result',
105
+ backend_notify_url: 'https://example.com/line_pay/notify'
106
+ ).execute
107
+
108
+ # Overriding merchant ID in payment options
82
109
  result = Tappay::CreditCard::Pay.by_prime(
83
110
  prime: 'prime_from_tappay_sdk',
84
111
  amount: 100,
85
- merchant_group_id: 'group_123', # This will be used instead of configured merchant_id
112
+ merchant_id: 'override_merchant_id', # This takes highest priority
86
113
  order_number: 'ORDER-123'
87
114
  )
88
115
  ```
@@ -97,236 +124,60 @@ Tappay.configure do |config|
97
124
  config.partner_key = ENV['TAPPAY_PARTNER_KEY'].freeze
98
125
  config.app_id = ENV['TAPPAY_APP_ID'].freeze
99
126
  config.merchant_id = ENV['TAPPAY_MERCHANT_ID'].freeze
127
+ config.line_pay_merchant_id = ENV['TAPPAY_LINE_PAY_MERCHANT_ID'].freeze
128
+ config.instalment_merchant_id = ENV['TAPPAY_INSTALMENT_MERCHANT_ID'].freeze
100
129
  # ... other configurations
101
130
  end
102
131
  ```
103
132
 
104
- ### 3. Using Rails Credentials
105
-
106
- If you're using Rails, you can use credentials:
107
-
108
- ```ruby
109
- Tappay.configure do |config|
110
- config.mode = Rails.env.production? ? :production : :sandbox
111
- config.partner_key = Rails.application.credentials.tappay[:partner_key].freeze
112
- config.app_id = Rails.application.credentials.tappay[:app_id].freeze
113
- # ... other configurations
114
- end
115
- ```
116
-
117
- ## Environment-based Endpoints
118
-
119
- The gem automatically handles different endpoints for sandbox and production environments. You don't need to specify the full URLs - just set the mode:
120
-
121
- ```ruby
122
- # For sandbox (default)
123
- config.mode = :sandbox # Uses https://sandbox.tappaysdk.com/...
124
-
125
- # For production
126
- config.mode = :production # Uses https://prod.tappaysdk.com/...
127
- ```
128
-
129
- ## Card Holder Information
130
-
131
- You can provide cardholder information in two ways:
132
-
133
- ### 1. Using CardHolder Object (Recommended)
134
-
135
- ```ruby
136
- # Create a CardHolder object
137
- card_holder = Tappay::CardHolder.new(
138
- name: 'John Doe',
139
- email: 'john@example.com',
140
- phone_number: '+886923456789'
141
- )
142
-
143
- # Use in payment directly
144
- result = Tappay::CreditCard::Pay.by_prime(
145
- prime: 'prime_from_tappay_sdk',
146
- amount: 100,
147
- order_number: 'ORDER-123',
148
- card_holder: card_holder # No need to call as_json
149
- )
150
- ```
151
-
152
- ### 2. Using Hash Directly
153
-
154
- ```ruby
155
- result = Tappay::CreditCard::Pay.by_prime(
156
- prime: 'prime_from_tappay_sdk',
157
- amount: 100,
158
- order_number: 'ORDER-123',
159
- card_holder: {
160
- name: 'John Doe',
161
- email: 'john@example.com',
162
- phone_number: '+886923456789'
163
- }
164
- )
165
- ```
166
-
167
- Both approaches are valid and will work the same way. The CardHolder object provides a more structured way to handle cardholder information and includes validation.
168
-
169
- ## Payment URL
170
-
171
- When processing payments, the API response may include a `payment_url` field. This URL is used for redirecting users to complete their payment in scenarios such as:
172
-
173
- - 3D Secure verification
174
- - LINE Pay payment page
175
- - JKO Pay payment page
176
-
177
- Note: payment_url is not supported for:
178
- - Apple Pay
179
- - Google Pay
180
- - Samsung Pay
181
-
182
- Example of handling payment URL in response:
183
- ```ruby
184
- result = Tappay::CreditCard::Pay.by_prime(
185
- prime: 'prime_from_tappay_sdk',
186
- amount: 100,
187
- order_number: 'ORDER-123'
188
- )
189
-
190
- if result['status'] == 0
191
- if result['payment_url']
192
- # Redirect user to payment page for:
193
- # - 3D Secure verification
194
- # - LINE Pay payment
195
- # - JKO Pay payment
196
- redirect_to result['payment_url']
197
- end
198
- end
199
- ```
200
-
201
- ## URL Properties
202
-
203
- The `result_url` (JSONObject) property is required when using LINE Pay, JKOPAY, 悠遊付, Atome, Pi錢包, 全盈支付, or when three_domain_secure is true. It contains the following URL fields:
204
-
205
- ```json
206
- {
207
- "frontend_redirect_url": "https://example.com/redirect", // Required - URL where consumer will be redirected after completing the transaction
208
- "backend_notify_url": "https://example.com/notify", // Required - URL where your server receives transaction results (only port 443)
209
- "go_back_url": "https://example.com/back" // Optional - URL for 3D verification error cases (E.SUN, Cathay United, Taishin banks)
210
- }
211
- ```
212
-
213
- - `frontend_redirect_url` (String): After the consumer completes the transaction process in LINE Pay, JKOPAY, 悠遊付, Atome, Pi錢包, 全盈支付, or 3D verification, they will be redirected to this frontend URL. Must start with https.
214
-
215
- - `backend_notify_url` (String): URL where your server receives transaction results. Must start with https and only supports port 443.
216
-
217
- - `go_back_url` (String): For 3D verification transactions, this URL is used when consumers are redirected to the TapPay Error page due to improper operation. This scenario only occurs with E.SUN Bank, Cathay United Bank, and Taishin Bank. You can define this URL in the transaction request or set it in TapPay Portal > Developer Content > System Settings > Redirect Link Settings. It's strongly recommended to define this field for 3D transactions to ensure consumers can return to complete the transaction or view results.
218
-
219
133
  ## Usage
220
134
 
221
- ### Pay by Prime
222
-
223
- Use this method when the customer wants to pay with their credit card without storing the card information. The customer will need to enter their card information for each transaction.
135
+ ### Credit Card Payment
224
136
 
225
137
  ```ruby
226
- # Basic payment with prime
138
+ # One-time payment
227
139
  result = Tappay::CreditCard::Pay.by_prime(
228
140
  prime: 'prime_from_tappay_sdk',
229
- amount: 100,
230
- order_number: 'ORDER-123',
231
- currency: 'TWD',
232
- three_domain_secure: true, # Enable 3D secure if needed
233
- remember: true, # Set to true if you want to store the card for future payments
234
- card_holder: card_holder # Optional cardholder information
235
- )
236
-
237
- if result['status'] == 0
238
- # Payment successful
239
- transaction_id = result['rec_trade_id']
240
- if result['card_secret']
241
- # If remember is true, you'll get these tokens
242
- card_key = result['card_secret']['card_key']
243
- card_token = result['card_secret']['card_token']
244
- # Store card_key and card_token securely for future payments
245
- end
246
-
247
- # Handle payment URL if present (for 3D Secure, LINE Pay, JKO Pay)
248
- if result['payment_url']
249
- redirect_to result['payment_url']
250
- end
251
- end
252
- ```
253
-
254
- ### Pay by Token
255
-
256
- Use this method when the customer has opted to save their card information for future purchases. This provides a more convenient checkout experience as customers don't need to re-enter their card information.
257
-
258
- ```ruby
259
- # Recurring payment with stored card token
260
- result = Tappay::CreditCard::Pay.by_token(
261
- card_key: 'stored_card_key',
262
- card_token: 'stored_card_token',
263
- amount: 100,
264
- order_number: 'ORDER-124',
265
- currency: 'TWD',
266
- three_domain_secure: true, # Enable 3D secure if needed
267
- card_holder: card_holder # Optional cardholder information
141
+ amount: 1000,
142
+ details: 'Order Details',
143
+ cardholder: {
144
+ phone_number: '0912345678',
145
+ name: 'Test User',
146
+ email: 'test@example.com'
147
+ }
268
148
  )
269
149
 
270
- if result['status'] == 0
271
- # Payment successful
272
- transaction_id = result['rec_trade_id']
273
- end
274
- ```
275
-
276
- ### Instalment Payment
277
-
278
- ```ruby
279
- payment = Tappay::CreditCard::Instalment.new(
150
+ # Instalment payment (3-30 months)
151
+ result = Tappay::CreditCard::Instalment.by_prime(
280
152
  prime: 'prime_from_tappay_sdk',
281
- amount: 10000,
282
- instalment: 6, # 6 monthly installments
283
- details: 'Product description',
153
+ amount: 1000,
154
+ instalment: 12, # 12 months instalment
155
+ details: 'Order Details',
284
156
  cardholder: {
285
- phone_number: '+886923456789',
286
- name: 'John Doe',
287
- email: 'john@example.com'
157
+ phone_number: '0912345678',
158
+ name: 'Test User',
159
+ email: 'test@example.com'
288
160
  }
289
161
  )
290
-
291
- begin
292
- result = payment.execute
293
- if result['status'] == 0
294
- # Payment successful
295
- instalment_info = result['instalment_info']
296
- number_of_instalments = instalment_info['number_of_instalments']
297
- first_payment = instalment_info['first_payment']
298
- each_payment = instalment_info['each_payment']
299
-
300
- # Handle payment URL if present (for 3D Secure)
301
- if result['payment_url']
302
- redirect_to result['payment_url']
303
- end
304
- end
305
- rescue Tappay::PaymentError => e
306
- # Handle payment error
307
- end
308
162
  ```
309
163
 
310
- ### Refund Processing
164
+ ### Line Pay
311
165
 
312
166
  ```ruby
313
- refund = Tappay::CreditCard::Refund.new(
314
- transaction_id: 'transaction_id_from_payment',
315
- amount: 100
316
- )
317
-
318
- begin
319
- result = refund.execute
320
- if result['status'] == 0
321
- # Refund successful
322
- end
323
- rescue Tappay::RefundError => e
324
- # Handle refund error
325
- end
167
+ # Create Line Pay payment
168
+ result = Tappay::LinePay::Pay.new(
169
+ prime: 'line_pay_prime',
170
+ amount: 1000,
171
+ details: 'Order Details',
172
+ frontend_redirect_url: 'https://example.com/line_pay/result',
173
+ backend_notify_url: 'https://example.com/line_pay/notify'
174
+ ).execute
326
175
  ```
327
176
 
328
177
  ### Error Handling
329
178
 
179
+ The gem provides comprehensive error handling:
180
+
330
181
  ```ruby
331
182
  begin
332
183
  result = Tappay::CreditCard::Pay.by_prime(
@@ -334,48 +185,21 @@ begin
334
185
  amount: 100,
335
186
  order_number: 'ORDER-123'
336
187
  )
337
- rescue Tappay::PaymentError => e
338
- # Handle payment error
339
- puts e.message
340
188
  rescue Tappay::ValidationError => e
341
- # Handle validation error
342
- puts e.message
189
+ # Handle validation errors (e.g., missing required fields)
190
+ puts "Validation error: #{e.message}"
191
+ rescue Tappay::APIError => e
192
+ # Handle API errors (e.g., invalid prime, insufficient balance)
193
+ puts "API error: #{e.message}"
194
+ rescue Tappay::Error => e
195
+ # Handle other TapPay errors
196
+ puts "TapPay error: #{e.message}"
343
197
  end
344
198
  ```
345
199
 
346
- ### Example Usage with result_url
347
-
348
- ```ruby
349
- # Example of payment with result_url for LINE Pay
350
- result = Tappay::LinePay::Pay.create(
351
- prime: 'prime_from_tappay_sdk',
352
- amount: 100,
353
- merchant_id: 'your_merchant_id',
354
- details: 'Product Item',
355
- result_url: {
356
- frontend_redirect_url: 'https://example.com/payment/complete',
357
- backend_notify_url: 'https://example.com/payment/notify',
358
- go_back_url: 'https://example.com/payment/error'
359
- }
360
- )
361
-
362
- # Example of payment with result_url for 3D verification
363
- result = Tappay::CreditCard::Pay.by_prime(
364
- prime: 'prime_from_tappay_sdk',
365
- amount: 100,
366
- merchant_id: 'your_merchant_id',
367
- three_domain_secure: true,
368
- result_url: {
369
- frontend_redirect_url: 'https://example.com/3d/complete',
370
- backend_notify_url: 'https://example.com/3d/notify',
371
- go_back_url: 'https://example.com/3d/error'
372
- }
373
- )
374
- ```
375
-
376
200
  ## Development
377
201
 
378
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests.
202
+ 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.
379
203
 
380
204
  ## Contributing
381
205
 
@@ -1,6 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Tappay
2
4
  class Configuration
3
- attr_accessor :partner_key, :merchant_id, :merchant_group_id, :instalment_merchant_id, :app_id, :currency, :vat_number
5
+ attr_accessor :partner_key, :merchant_id, :merchant_group_id, :instalment_merchant_id,
6
+ :line_pay_merchant_id, :app_id, :currency, :vat_number
4
7
  attr_writer :api_version
5
8
 
6
9
  def initialize
@@ -33,6 +33,10 @@ module Tappay
33
33
 
34
34
  private
35
35
 
36
+ def get_merchant_id
37
+ Tappay.configuration.instalment_merchant_id || super
38
+ end
39
+
36
40
  def additional_required_options
37
41
  [:prime, :cardholder, :instalment]
38
42
  end
@@ -70,6 +74,10 @@ module Tappay
70
74
 
71
75
  private
72
76
 
77
+ def get_merchant_id
78
+ Tappay.configuration.instalment_merchant_id || super
79
+ end
80
+
73
81
  def additional_required_options
74
82
  [:card_key, :card_token, :instalment]
75
83
  end
@@ -59,17 +59,5 @@ module Tappay
59
59
  end
60
60
  end
61
61
  end
62
-
63
- module LinePay
64
- class << self
65
- def redirect_url
66
- "#{Endpoints.base_url}/tpc/payment/redirect"
67
- end
68
-
69
- def query_url
70
- "#{Endpoints.base_url}/tpc/transaction/query"
71
- end
72
- end
73
- end
74
62
  end
75
63
  end
@@ -22,6 +22,10 @@ module Tappay
22
22
 
23
23
  private
24
24
 
25
+ def get_merchant_id
26
+ Tappay.configuration.line_pay_merchant_id || super
27
+ end
28
+
25
29
  def additional_required_options
26
30
  [:prime, :frontend_redirect_url, :backend_notify_url]
27
31
  end
@@ -2,6 +2,8 @@
2
2
 
3
3
  module Tappay
4
4
  class PaymentBase < Client
5
+ VALID_INSTALMENT_VALUES = [0, 3, 6, 12, 24, 30].freeze
6
+
5
7
  def initialize(options = {})
6
8
  super
7
9
  validate_options!
@@ -39,7 +41,7 @@ module Tappay
39
41
  else
40
42
  # If no options, use configuration
41
43
  merchant_group_id = Tappay.configuration.merchant_group_id
42
- merchant_id = Tappay.configuration.merchant_id
44
+ merchant_id = get_merchant_id
43
45
  end
44
46
 
45
47
  # Check if at least one is provided
@@ -61,8 +63,8 @@ module Tappay
61
63
  data[:merchant_id] = merchant_id
62
64
  end
63
65
  data[:cardholder] = card_holder_data if options[:cardholder]
64
- data[:instalment] = options[:instalment] if options[:instalment]
65
66
  data[:result_url] = options[:result_url] if options[:result_url]
67
+ data[:instalment] = options[:instalment] || 0
66
68
  end
67
69
  end
68
70
 
@@ -84,12 +86,26 @@ module Tappay
84
86
  missing = required.select { |key| options[key].nil? }
85
87
  raise ValidationError, "Missing required options: #{missing.join(', ')}" if missing.any?
86
88
 
89
+ validate_amount!
87
90
  validate_instalment! if options[:instalment]
88
91
  validate_result_url! if options[:three_domain_secure]
89
92
  end
90
93
 
91
94
  private
92
95
 
96
+ def validate_amount!
97
+ amount = options[:amount]
98
+ if !amount.is_a?(Numeric)
99
+ raise ValidationError, "amount must be a number"
100
+ elsif amount <= 0
101
+ raise ValidationError, "amount must be greater than 0"
102
+ end
103
+ end
104
+
105
+ def get_merchant_id
106
+ Tappay.configuration.merchant_id
107
+ end
108
+
93
109
  def base_required_options
94
110
  [:amount, :details]
95
111
  end
@@ -99,17 +115,22 @@ module Tappay
99
115
  end
100
116
 
101
117
  def validate_instalment!
102
- unless options[:instalment].to_i.between?(1, 12)
103
- raise ValidationError, "Invalid instalment value. Must be between 1 and 12"
118
+ instalment = options[:instalment].to_i
119
+ unless VALID_INSTALMENT_VALUES.include?(instalment)
120
+ raise ValidationError, "Instalment must be one of: #{VALID_INSTALMENT_VALUES.join(', ')}"
104
121
  end
105
122
  end
106
123
 
107
124
  def validate_result_url!
108
- return if options[:result_url] &&
109
- options[:result_url][:frontend_redirect_url] &&
110
- options[:result_url][:backend_notify_url]
125
+ result_url = options[:result_url]
126
+ raise ValidationError, "result_url must be a hash" unless result_url.is_a?(Hash)
111
127
 
112
- raise ValidationError, "result_url with frontend_redirect_url and backend_notify_url is required when three_domain_secure is true"
128
+ required_fields = %w[frontend_redirect_url backend_notify_url]
129
+ missing = required_fields.select { |field| result_url[field.to_sym].nil? && result_url[field].nil? }
130
+
131
+ if missing.any?
132
+ raise ValidationError, "result_url must contain both frontend_redirect_url and backend_notify_url"
133
+ end
113
134
  end
114
135
  end
115
136
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Tappay
4
- VERSION = "0.7.0"
4
+ VERSION = "0.8.0"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tappay_ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Zac