payabli 2.1.5 → 2.2.15

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.
Files changed (105) hide show
  1. checksums.yaml +4 -4
  2. data/.fern/metadata.json +4 -3
  3. data/.fernignore +1 -0
  4. data/LICENSE.md +8 -0
  5. data/README.md +85 -0
  6. data/lib/payabli/bill/client.rb +19 -6
  7. data/lib/payabli/boarding/client.rb +15 -8
  8. data/lib/payabli/charge_backs/client.rb +11 -5
  9. data/lib/payabli/check_capture/client.rb +2 -4
  10. data/lib/payabli/client.rb +2 -2
  11. data/lib/payabli/cloud/client.rb +12 -6
  12. data/lib/payabli/customer/client.rb +10 -1
  13. data/lib/payabli/export/client.rb +29 -29
  14. data/lib/payabli/hosted_payment_pages/client.rb +7 -0
  15. data/lib/payabli/import/client.rb +3 -0
  16. data/lib/payabli/internal/http/base_request.rb +6 -0
  17. data/lib/payabli/internal/http/raw_client.rb +104 -14
  18. data/lib/payabli/internal/types/model.rb +9 -1
  19. data/lib/payabli/internal/types/union.rb +31 -3
  20. data/lib/payabli/internal/types/utils.rb +17 -2
  21. data/lib/payabli/invoice/client.rb +15 -6
  22. data/lib/payabli/invoice/types/get_invoice_record.rb +1 -1
  23. data/lib/payabli/line_item/client.rb +9 -1
  24. data/lib/payabli/money_in/client.rb +336 -24
  25. data/lib/payabli/money_in/types/get_paid_response_data.rb +1 -1
  26. data/lib/payabli/money_in/types/request_payment_authorize_v_2.rb +13 -0
  27. data/lib/payabli/money_in/types/request_payment_v_2.rb +15 -0
  28. data/lib/payabli/money_in/types/transaction_detail_response_data.rb +2 -0
  29. data/lib/payabli/money_out/client.rb +73 -5
  30. data/lib/payabli/money_out_types/types/allowed_check_payment_status.rb +14 -0
  31. data/lib/payabli/notification/client.rb +5 -0
  32. data/lib/payabli/notificationlogs/client.rb +4 -1
  33. data/lib/payabli/ocr/client.rb +2 -0
  34. data/lib/payabli/organization/client.rb +19 -8
  35. data/lib/payabli/payment_link/client.rb +21 -10
  36. data/lib/payabli/payment_method_domain/client.rb +12 -10
  37. data/lib/payabli/paypoint/client.rb +8 -1
  38. data/lib/payabli/query/client.rb +175 -33
  39. data/lib/payabli/query/types/list_transfer_details_out_request.rb +16 -0
  40. data/lib/payabli/query/types/list_transfers_out_org_request.rb +15 -0
  41. data/lib/payabli/query/types/list_transfers_out_paypoint_request.rb +15 -0
  42. data/lib/payabli/query_types/types/transfer_out_bank_account.rb +14 -0
  43. data/lib/payabli/query_types/types/transfer_out_detail_bill.rb +26 -0
  44. data/lib/payabli/query_types/types/transfer_out_detail_bill_attachment.rb +16 -0
  45. data/lib/payabli/query_types/types/transfer_out_detail_check_data.rb +13 -0
  46. data/lib/payabli/query_types/types/transfer_out_detail_event.rb +14 -0
  47. data/lib/payabli/query_types/types/transfer_out_detail_payment_data.rb +29 -0
  48. data/lib/payabli/query_types/types/transfer_out_detail_query_response.rb +13 -0
  49. data/lib/payabli/query_types/types/transfer_out_detail_record.rb +74 -0
  50. data/lib/payabli/query_types/types/transfer_out_detail_vendor.rb +56 -0
  51. data/lib/payabli/query_types/types/transfer_out_detail_vendor_billing_data.rb +26 -0
  52. data/lib/payabli/query_types/types/transfer_out_event_data.rb +16 -0
  53. data/lib/payabli/query_types/types/transfer_out_message.rb +19 -0
  54. data/lib/payabli/query_types/types/transfer_out_message_properties.rb +13 -0
  55. data/lib/payabli/query_types/types/transfer_out_query_response.rb +13 -0
  56. data/lib/payabli/query_types/types/transfer_out_record.rb +45 -0
  57. data/lib/payabli/query_types/types/transfer_out_summary.rb +14 -0
  58. data/lib/payabli/statistic/client.rb +4 -4
  59. data/lib/payabli/subscription/client.rb +12 -6
  60. data/lib/payabli/templates/client.rb +4 -1
  61. data/lib/payabli/token_storage/client.rb +8 -3
  62. data/lib/payabli/token_storage/types/get_method_response_response_data.rb +3 -0
  63. data/lib/payabli/token_storage/types/get_method_response_response_data_vendors_item.rb +55 -0
  64. data/lib/payabli/token_storage/types/request_token_storage.rb +1 -0
  65. data/lib/payabli/token_storage/types/vendor_data_request.rb +14 -0
  66. data/lib/payabli/types/application_data.rb +1 -0
  67. data/lib/payabli/types/application_data_managed.rb +1 -0
  68. data/lib/payabli/types/application_data_odp.rb +1 -0
  69. data/lib/payabli/types/application_data_pay_in.rb +1 -0
  70. data/lib/payabli/types/{avsresponsetext.rb → avs_response.rb} +2 -2
  71. data/lib/payabli/types/{cvvresponsetext.rb → avs_response_text.rb} +2 -2
  72. data/lib/payabli/types/bill_data.rb +1 -1
  73. data/lib/payabli/types/customer_vault_id.rb +23 -0
  74. data/lib/payabli/types/cvv_response.rb +23 -0
  75. data/lib/payabli/types/cvv_response_text.rb +23 -0
  76. data/lib/payabli/types/emv_auth_response_data.rb +23 -0
  77. data/lib/payabli/types/max_ticket.rb +23 -0
  78. data/lib/payabli/types/min_ticket.rb +23 -0
  79. data/lib/payabli/types/on_create.rb +23 -0
  80. data/lib/payabli/types/query_response_data.rb +2 -0
  81. data/lib/payabli/types/query_subscription_response.rb +1 -1
  82. data/lib/payabli/types/query_transaction_payor_data.rb +1 -1
  83. data/lib/payabli/types/result_code_text.rb +23 -0
  84. data/lib/payabli/types/result_codev_2.rb +23 -0
  85. data/lib/payabli/types/transaction_query_records_customer.rb +1 -1
  86. data/lib/payabli/types/transfer_bank_account.rb +1 -0
  87. data/lib/payabli/user/client.rb +21 -20
  88. data/lib/payabli/v_2_money_in_types/types/v_2_bad_request_error.rb +20 -0
  89. data/lib/payabli/v_2_money_in_types/types/v_2_bad_request_error_detail.rb +13 -0
  90. data/lib/payabli/v_2_money_in_types/types/v_2_declined_transaction_response_wrapper.rb +19 -0
  91. data/lib/payabli/v_2_money_in_types/types/v_2_internal_server_error.rb +16 -0
  92. data/lib/payabli/v_2_money_in_types/types/v_2_response_action.rb +25 -0
  93. data/lib/payabli/v_2_money_in_types/types/v_2_response_code.rb +25 -0
  94. data/lib/payabli/v_2_money_in_types/types/v_2_response_explanation.rb +25 -0
  95. data/lib/payabli/v_2_money_in_types/types/v_2_response_reason.rb +25 -0
  96. data/lib/payabli/v_2_money_in_types/types/v_2_transaction_detail_response_data.rb +27 -0
  97. data/lib/payabli/v_2_money_in_types/types/v_2_transaction_details.rb +64 -0
  98. data/lib/payabli/v_2_money_in_types/types/v_2_transaction_response_wrapper.rb +19 -0
  99. data/lib/payabli/vendor/client.rb +4 -0
  100. data/lib/payabli/version.rb +1 -1
  101. data/lib/payabli/wallet/client.rb +8 -16
  102. data/lib/payabli.rb +51 -7
  103. data/reference.md +3313 -2335
  104. data/wiremock/wiremock-mappings.json +1 -1
  105. metadata +49 -4
@@ -28,7 +28,7 @@ module Payabli
28
28
  #
29
29
  # @return [Hash[String, Object]]
30
30
  def export_applications(request_options: {}, **params)
31
- params = Payabli::Internal::Types::Utils.symbolize_keys(params)
31
+ params = Payabli::Internal::Types::Utils.normalize_keys(params)
32
32
  query_param_names = %i[columns_export from_record limit_record parameters]
33
33
  query_params = {}
34
34
  query_params["columnsExport"] = params[:columns_export] if params.key?(:columns_export)
@@ -76,7 +76,7 @@ module Payabli
76
76
  #
77
77
  # @return [Hash[String, Object]]
78
78
  def export_batch_details(request_options: {}, **params)
79
- params = Payabli::Internal::Types::Utils.symbolize_keys(params)
79
+ params = Payabli::Internal::Types::Utils.normalize_keys(params)
80
80
  query_param_names = %i[columns_export from_record limit_record parameters]
81
81
  query_params = {}
82
82
  query_params["columnsExport"] = params[:columns_export] if params.key?(:columns_export)
@@ -124,7 +124,7 @@ module Payabli
124
124
  #
125
125
  # @return [Hash[String, Object]]
126
126
  def export_batch_details_org(request_options: {}, **params)
127
- params = Payabli::Internal::Types::Utils.symbolize_keys(params)
127
+ params = Payabli::Internal::Types::Utils.normalize_keys(params)
128
128
  query_param_names = %i[columns_export from_record limit_record parameters]
129
129
  query_params = {}
130
130
  query_params["columnsExport"] = params[:columns_export] if params.key?(:columns_export)
@@ -172,7 +172,7 @@ module Payabli
172
172
  #
173
173
  # @return [Hash[String, Object]]
174
174
  def export_batches(request_options: {}, **params)
175
- params = Payabli::Internal::Types::Utils.symbolize_keys(params)
175
+ params = Payabli::Internal::Types::Utils.normalize_keys(params)
176
176
  query_param_names = %i[columns_export from_record limit_record parameters]
177
177
  query_params = {}
178
178
  query_params["columnsExport"] = params[:columns_export] if params.key?(:columns_export)
@@ -220,7 +220,7 @@ module Payabli
220
220
  #
221
221
  # @return [Hash[String, Object]]
222
222
  def export_batches_org(request_options: {}, **params)
223
- params = Payabli::Internal::Types::Utils.symbolize_keys(params)
223
+ params = Payabli::Internal::Types::Utils.normalize_keys(params)
224
224
  query_param_names = %i[columns_export from_record limit_record parameters]
225
225
  query_params = {}
226
226
  query_params["columnsExport"] = params[:columns_export] if params.key?(:columns_export)
@@ -268,7 +268,7 @@ module Payabli
268
268
  #
269
269
  # @return [Hash[String, Object]]
270
270
  def export_batches_out(request_options: {}, **params)
271
- params = Payabli::Internal::Types::Utils.symbolize_keys(params)
271
+ params = Payabli::Internal::Types::Utils.normalize_keys(params)
272
272
  query_param_names = %i[columns_export from_record limit_record parameters]
273
273
  query_params = {}
274
274
  query_params["columnsExport"] = params[:columns_export] if params.key?(:columns_export)
@@ -316,7 +316,7 @@ module Payabli
316
316
  #
317
317
  # @return [Hash[String, Object]]
318
318
  def export_batches_out_org(request_options: {}, **params)
319
- params = Payabli::Internal::Types::Utils.symbolize_keys(params)
319
+ params = Payabli::Internal::Types::Utils.normalize_keys(params)
320
320
  query_param_names = %i[columns_export from_record limit_record parameters]
321
321
  query_params = {}
322
322
  query_params["columnsExport"] = params[:columns_export] if params.key?(:columns_export)
@@ -364,7 +364,7 @@ module Payabli
364
364
  #
365
365
  # @return [Hash[String, Object]]
366
366
  def export_bills(request_options: {}, **params)
367
- params = Payabli::Internal::Types::Utils.symbolize_keys(params)
367
+ params = Payabli::Internal::Types::Utils.normalize_keys(params)
368
368
  query_param_names = %i[columns_export from_record limit_record parameters]
369
369
  query_params = {}
370
370
  query_params["columnsExport"] = params[:columns_export] if params.key?(:columns_export)
@@ -412,7 +412,7 @@ module Payabli
412
412
  #
413
413
  # @return [Hash[String, Object]]
414
414
  def export_bills_org(request_options: {}, **params)
415
- params = Payabli::Internal::Types::Utils.symbolize_keys(params)
415
+ params = Payabli::Internal::Types::Utils.normalize_keys(params)
416
416
  query_param_names = %i[columns_export from_record limit_record parameters]
417
417
  query_params = {}
418
418
  query_params["columnsExport"] = params[:columns_export] if params.key?(:columns_export)
@@ -460,7 +460,7 @@ module Payabli
460
460
  #
461
461
  # @return [Hash[String, Object]]
462
462
  def export_chargebacks(request_options: {}, **params)
463
- params = Payabli::Internal::Types::Utils.symbolize_keys(params)
463
+ params = Payabli::Internal::Types::Utils.normalize_keys(params)
464
464
  query_param_names = %i[columns_export from_record limit_record parameters]
465
465
  query_params = {}
466
466
  query_params["columnsExport"] = params[:columns_export] if params.key?(:columns_export)
@@ -508,7 +508,7 @@ module Payabli
508
508
  #
509
509
  # @return [Hash[String, Object]]
510
510
  def export_chargebacks_org(request_options: {}, **params)
511
- params = Payabli::Internal::Types::Utils.symbolize_keys(params)
511
+ params = Payabli::Internal::Types::Utils.normalize_keys(params)
512
512
  query_param_names = %i[columns_export from_record limit_record parameters]
513
513
  query_params = {}
514
514
  query_params["columnsExport"] = params[:columns_export] if params.key?(:columns_export)
@@ -556,7 +556,7 @@ module Payabli
556
556
  #
557
557
  # @return [Hash[String, Object]]
558
558
  def export_customers(request_options: {}, **params)
559
- params = Payabli::Internal::Types::Utils.symbolize_keys(params)
559
+ params = Payabli::Internal::Types::Utils.normalize_keys(params)
560
560
  query_param_names = %i[columns_export from_record limit_record parameters]
561
561
  query_params = {}
562
562
  query_params["columnsExport"] = params[:columns_export] if params.key?(:columns_export)
@@ -604,7 +604,7 @@ module Payabli
604
604
  #
605
605
  # @return [Hash[String, Object]]
606
606
  def export_customers_org(request_options: {}, **params)
607
- params = Payabli::Internal::Types::Utils.symbolize_keys(params)
607
+ params = Payabli::Internal::Types::Utils.normalize_keys(params)
608
608
  query_param_names = %i[columns_export from_record limit_record parameters]
609
609
  query_params = {}
610
610
  query_params["columnsExport"] = params[:columns_export] if params.key?(:columns_export)
@@ -652,7 +652,7 @@ module Payabli
652
652
  #
653
653
  # @return [Hash[String, Object]]
654
654
  def export_invoices(request_options: {}, **params)
655
- params = Payabli::Internal::Types::Utils.symbolize_keys(params)
655
+ params = Payabli::Internal::Types::Utils.normalize_keys(params)
656
656
  query_param_names = %i[columns_export from_record limit_record parameters]
657
657
  query_params = {}
658
658
  query_params["columnsExport"] = params[:columns_export] if params.key?(:columns_export)
@@ -700,7 +700,7 @@ module Payabli
700
700
  #
701
701
  # @return [Hash[String, Object]]
702
702
  def export_invoices_org(request_options: {}, **params)
703
- params = Payabli::Internal::Types::Utils.symbolize_keys(params)
703
+ params = Payabli::Internal::Types::Utils.normalize_keys(params)
704
704
  query_param_names = %i[columns_export from_record limit_record parameters]
705
705
  query_params = {}
706
706
  query_params["columnsExport"] = params[:columns_export] if params.key?(:columns_export)
@@ -748,7 +748,7 @@ module Payabli
748
748
  #
749
749
  # @return [Hash[String, Object]]
750
750
  def export_organizations(request_options: {}, **params)
751
- params = Payabli::Internal::Types::Utils.symbolize_keys(params)
751
+ params = Payabli::Internal::Types::Utils.normalize_keys(params)
752
752
  query_param_names = %i[columns_export from_record limit_record parameters]
753
753
  query_params = {}
754
754
  query_params["columnsExport"] = params[:columns_export] if params.key?(:columns_export)
@@ -796,7 +796,7 @@ module Payabli
796
796
  #
797
797
  # @return [Hash[String, Object]]
798
798
  def export_payout(request_options: {}, **params)
799
- params = Payabli::Internal::Types::Utils.symbolize_keys(params)
799
+ params = Payabli::Internal::Types::Utils.normalize_keys(params)
800
800
  query_param_names = %i[columns_export from_record limit_record parameters]
801
801
  query_params = {}
802
802
  query_params["columnsExport"] = params[:columns_export] if params.key?(:columns_export)
@@ -844,7 +844,7 @@ module Payabli
844
844
  #
845
845
  # @return [Hash[String, Object]]
846
846
  def export_payout_org(request_options: {}, **params)
847
- params = Payabli::Internal::Types::Utils.symbolize_keys(params)
847
+ params = Payabli::Internal::Types::Utils.normalize_keys(params)
848
848
  query_param_names = %i[columns_export from_record limit_record parameters]
849
849
  query_params = {}
850
850
  query_params["columnsExport"] = params[:columns_export] if params.key?(:columns_export)
@@ -892,7 +892,7 @@ module Payabli
892
892
  #
893
893
  # @return [Hash[String, Object]]
894
894
  def export_paypoints(request_options: {}, **params)
895
- params = Payabli::Internal::Types::Utils.symbolize_keys(params)
895
+ params = Payabli::Internal::Types::Utils.normalize_keys(params)
896
896
  query_param_names = %i[columns_export from_record limit_record parameters]
897
897
  query_params = {}
898
898
  query_params["columnsExport"] = params[:columns_export] if params.key?(:columns_export)
@@ -940,7 +940,7 @@ module Payabli
940
940
  #
941
941
  # @return [Hash[String, Object]]
942
942
  def export_settlements(request_options: {}, **params)
943
- params = Payabli::Internal::Types::Utils.symbolize_keys(params)
943
+ params = Payabli::Internal::Types::Utils.normalize_keys(params)
944
944
  query_param_names = %i[columns_export from_record limit_record parameters]
945
945
  query_params = {}
946
946
  query_params["columnsExport"] = params[:columns_export] if params.key?(:columns_export)
@@ -988,7 +988,7 @@ module Payabli
988
988
  #
989
989
  # @return [Hash[String, Object]]
990
990
  def export_settlements_org(request_options: {}, **params)
991
- params = Payabli::Internal::Types::Utils.symbolize_keys(params)
991
+ params = Payabli::Internal::Types::Utils.normalize_keys(params)
992
992
  query_param_names = %i[columns_export from_record limit_record parameters]
993
993
  query_params = {}
994
994
  query_params["columnsExport"] = params[:columns_export] if params.key?(:columns_export)
@@ -1036,7 +1036,7 @@ module Payabli
1036
1036
  #
1037
1037
  # @return [Hash[String, Object]]
1038
1038
  def export_subscriptions(request_options: {}, **params)
1039
- params = Payabli::Internal::Types::Utils.symbolize_keys(params)
1039
+ params = Payabli::Internal::Types::Utils.normalize_keys(params)
1040
1040
  query_param_names = %i[columns_export from_record limit_record parameters]
1041
1041
  query_params = {}
1042
1042
  query_params["columnsExport"] = params[:columns_export] if params.key?(:columns_export)
@@ -1084,7 +1084,7 @@ module Payabli
1084
1084
  #
1085
1085
  # @return [Hash[String, Object]]
1086
1086
  def export_subscriptions_org(request_options: {}, **params)
1087
- params = Payabli::Internal::Types::Utils.symbolize_keys(params)
1087
+ params = Payabli::Internal::Types::Utils.normalize_keys(params)
1088
1088
  query_param_names = %i[columns_export from_record limit_record parameters]
1089
1089
  query_params = {}
1090
1090
  query_params["columnsExport"] = params[:columns_export] if params.key?(:columns_export)
@@ -1133,7 +1133,7 @@ module Payabli
1133
1133
  #
1134
1134
  # @return [Hash[String, Object]]
1135
1135
  def export_transactions(request_options: {}, **params)
1136
- params = Payabli::Internal::Types::Utils.symbolize_keys(params)
1136
+ params = Payabli::Internal::Types::Utils.normalize_keys(params)
1137
1137
  query_param_names = %i[columns_export from_record limit_record parameters]
1138
1138
  query_params = {}
1139
1139
  query_params["columnsExport"] = params[:columns_export] if params.key?(:columns_export)
@@ -1182,7 +1182,7 @@ module Payabli
1182
1182
  #
1183
1183
  # @return [Hash[String, Object]]
1184
1184
  def export_transactions_org(request_options: {}, **params)
1185
- params = Payabli::Internal::Types::Utils.symbolize_keys(params)
1185
+ params = Payabli::Internal::Types::Utils.normalize_keys(params)
1186
1186
  query_param_names = %i[columns_export from_record limit_record parameters]
1187
1187
  query_params = {}
1188
1188
  query_params["columnsExport"] = params[:columns_export] if params.key?(:columns_export)
@@ -1232,7 +1232,7 @@ module Payabli
1232
1232
  #
1233
1233
  # @return [Hash[String, Object]]
1234
1234
  def export_transfer_details(request_options: {}, **params)
1235
- params = Payabli::Internal::Types::Utils.symbolize_keys(params)
1235
+ params = Payabli::Internal::Types::Utils.normalize_keys(params)
1236
1236
  query_param_names = %i[columns_export from_record limit_record parameters sort_by]
1237
1237
  query_params = {}
1238
1238
  query_params["columnsExport"] = params[:columns_export] if params.key?(:columns_export)
@@ -1281,7 +1281,7 @@ module Payabli
1281
1281
  #
1282
1282
  # @return [Hash[String, Object]]
1283
1283
  def export_transfers(request_options: {}, **params)
1284
- params = Payabli::Internal::Types::Utils.symbolize_keys(params)
1284
+ params = Payabli::Internal::Types::Utils.normalize_keys(params)
1285
1285
  query_param_names = %i[columns_export from_record limit_record parameters sort_by]
1286
1286
  query_params = {}
1287
1287
  query_params["columnsExport"] = params[:columns_export] if params.key?(:columns_export)
@@ -1330,7 +1330,7 @@ module Payabli
1330
1330
  #
1331
1331
  # @return [Hash[String, Object]]
1332
1332
  def export_vendors(request_options: {}, **params)
1333
- params = Payabli::Internal::Types::Utils.symbolize_keys(params)
1333
+ params = Payabli::Internal::Types::Utils.normalize_keys(params)
1334
1334
  query_param_names = %i[columns_export from_record limit_record parameters]
1335
1335
  query_params = {}
1336
1336
  query_params["columnsExport"] = params[:columns_export] if params.key?(:columns_export)
@@ -1378,7 +1378,7 @@ module Payabli
1378
1378
  #
1379
1379
  # @return [Hash[String, Object]]
1380
1380
  def export_vendors_org(request_options: {}, **params)
1381
- params = Payabli::Internal::Types::Utils.symbolize_keys(params)
1381
+ params = Payabli::Internal::Types::Utils.normalize_keys(params)
1382
1382
  query_param_names = %i[columns_export from_record limit_record parameters]
1383
1383
  query_params = {}
1384
1384
  query_params["columnsExport"] = params[:columns_export] if params.key?(:columns_export)
@@ -25,6 +25,7 @@ module Payabli
25
25
  #
26
26
  # @return [Payabli::Types::PayabliPages]
27
27
  def load_page(request_options: {}, **params)
28
+ params = Payabli::Internal::Types::Utils.normalize_keys(params)
28
29
  request = Payabli::Internal::JSON::Request.new(
29
30
  base_url: request_options[:base_url],
30
31
  method: "GET",
@@ -62,13 +63,18 @@ module Payabli
62
63
  #
63
64
  # @return [Payabli::Types::PayabliApiResponse00Responsedatanonobject]
64
65
  def new_page(request_options: {}, **params)
66
+ params = Payabli::Internal::Types::Utils.normalize_keys(params)
65
67
  path_param_names = %i[entry]
66
68
  body_params = params.except(*path_param_names)
67
69
 
70
+ headers = {}
71
+ headers["idempotencyKey"] = params[:idempotency_key] if params[:idempotency_key]
72
+
68
73
  request = Payabli::Internal::JSON::Request.new(
69
74
  base_url: request_options[:base_url],
70
75
  method: "POST",
71
76
  path: "Paypoint/#{params[:entry]}",
77
+ headers: headers,
72
78
  body: Payabli::Types::PayabliPages.new(body_params).to_h,
73
79
  request_options: request_options
74
80
  )
@@ -100,6 +106,7 @@ module Payabli
100
106
  #
101
107
  # @return [Payabli::Types::PayabliApiResponse00Responsedatanonobject]
102
108
  def save_page(request_options: {}, **params)
109
+ params = Payabli::Internal::Types::Utils.normalize_keys(params)
103
110
  request = Payabli::Internal::JSON::Request.new(
104
111
  base_url: request_options[:base_url],
105
112
  method: "PUT",
@@ -24,6 +24,7 @@ module Payabli
24
24
  #
25
25
  # @return [Payabli::Types::PayabliApiResponseImport]
26
26
  def import_bills(request_options: {}, **params)
27
+ params = Payabli::Internal::Types::Utils.normalize_keys(params)
27
28
  body = Internal::Multipart::FormData.new
28
29
 
29
30
  body.add_part(params[:file].to_form_data_part(name: "file")) if params[:file]
@@ -64,6 +65,7 @@ module Payabli
64
65
  #
65
66
  # @return [Payabli::Types::PayabliApiResponseImport]
66
67
  def import_customer(request_options: {}, **params)
68
+ params = Payabli::Internal::Types::Utils.normalize_keys(params)
67
69
  body = Internal::Multipart::FormData.new
68
70
 
69
71
  body.add_part(params[:file].to_form_data_part(name: "file")) if params[:file]
@@ -103,6 +105,7 @@ module Payabli
103
105
  #
104
106
  # @return [Payabli::Types::PayabliApiResponseImport]
105
107
  def import_vendor(request_options: {}, **params)
108
+ params = Payabli::Internal::Types::Utils.normalize_keys(params)
106
109
  body = Internal::Multipart::FormData.new
107
110
 
108
111
  body.add_part(params[:file].to_form_data_part(name: "file")) if params[:file]
@@ -22,6 +22,12 @@ module Payabli
22
22
  @request_options = request_options
23
23
  end
24
24
 
25
+ # @return [Hash] The query parameters merged with additional query parameters from request options.
26
+ def encode_query
27
+ additional_query = @request_options&.dig(:additional_query_parameters) || @request_options&.dig("additional_query_parameters") || {}
28
+ @query.merge(additional_query)
29
+ end
30
+
25
31
  # Child classes should implement:
26
32
  # - encode_headers: Returns the encoded HTTP request headers.
27
33
  # - encode_body: Returns the encoded HTTP request body.
@@ -5,6 +5,18 @@ module Payabli
5
5
  module Http
6
6
  # @api private
7
7
  class RawClient
8
+ # Default HTTP status codes that trigger a retry
9
+ RETRYABLE_STATUSES = [408, 429, 500, 502, 503, 504, 521, 522, 524].freeze
10
+ # Initial delay between retries in seconds
11
+ INITIAL_RETRY_DELAY = 0.5
12
+ # Maximum delay between retries in seconds
13
+ MAX_RETRY_DELAY = 60.0
14
+ # Jitter factor for randomizing retry delays (20%)
15
+ JITTER_FACTOR = 0.2
16
+
17
+ # @return [String] The base URL for requests
18
+ attr_reader :base_url
19
+
8
20
  # @param base_url [String] The base url for the request.
9
21
  # @param max_retries [Integer] The number of times to retry a failed request, defaults to 2.
10
22
  # @param timeout [Float] The timeout for the request, defaults to 60.0 seconds.
@@ -24,30 +36,106 @@ module Payabli
24
36
  # @return [HTTP::Response] The HTTP response.
25
37
  def send(request)
26
38
  url = build_url(request)
39
+ attempt = 0
40
+ response = nil
27
41
 
28
- http_request = build_http_request(
29
- url:,
30
- method: request.method,
31
- headers: request.encode_headers,
32
- body: request.encode_body
33
- )
42
+ loop do
43
+ http_request = build_http_request(
44
+ url:,
45
+ method: request.method,
46
+ headers: request.encode_headers,
47
+ body: request.encode_body
48
+ )
49
+
50
+ conn = connect(url)
51
+ conn.open_timeout = @timeout
52
+ conn.read_timeout = @timeout
53
+ conn.write_timeout = @timeout
54
+ conn.continue_timeout = @timeout
55
+
56
+ response = conn.request(http_request)
34
57
 
35
- conn = connect(url)
36
- conn.open_timeout = @timeout
37
- conn.read_timeout = @timeout
38
- conn.write_timeout = @timeout
39
- conn.continue_timeout = @timeout
58
+ break unless should_retry?(response, attempt)
40
59
 
41
- conn.request(http_request)
60
+ delay = retry_delay(response, attempt)
61
+ sleep(delay)
62
+ attempt += 1
63
+ end
64
+
65
+ response
66
+ end
67
+
68
+ # Determines if a request should be retried based on the response status code.
69
+ # @param response [Net::HTTPResponse] The HTTP response.
70
+ # @param attempt [Integer] The current retry attempt (0-indexed).
71
+ # @return [Boolean] Whether the request should be retried.
72
+ def should_retry?(response, attempt)
73
+ return false if attempt >= @max_retries
74
+
75
+ status = response.code.to_i
76
+ RETRYABLE_STATUSES.include?(status)
77
+ end
78
+
79
+ # Calculates the delay before the next retry attempt using exponential backoff with jitter.
80
+ # Respects Retry-After header if present.
81
+ # @param response [Net::HTTPResponse] The HTTP response.
82
+ # @param attempt [Integer] The current retry attempt (0-indexed).
83
+ # @return [Float] The delay in seconds before the next retry.
84
+ def retry_delay(response, attempt)
85
+ # Check for Retry-After header (can be seconds or HTTP date)
86
+ retry_after = response["Retry-After"]
87
+ if retry_after
88
+ delay = parse_retry_after(retry_after)
89
+ return [delay, MAX_RETRY_DELAY].min if delay&.positive?
90
+ end
91
+
92
+ # Exponential backoff with jitter: base_delay * 2^attempt
93
+ base_delay = INITIAL_RETRY_DELAY * (2**attempt)
94
+ add_jitter([base_delay, MAX_RETRY_DELAY].min)
95
+ end
96
+
97
+ # Parses the Retry-After header value.
98
+ # @param value [String] The Retry-After header value (seconds or HTTP date).
99
+ # @return [Float, nil] The delay in seconds, or nil if parsing fails.
100
+ def parse_retry_after(value)
101
+ # Try parsing as integer (seconds)
102
+ seconds = Integer(value, exception: false)
103
+ return seconds.to_f if seconds
104
+
105
+ # Try parsing as HTTP date
106
+ begin
107
+ retry_time = Time.httpdate(value)
108
+ delay = retry_time - Time.now
109
+ delay.positive? ? delay : nil
110
+ rescue ArgumentError
111
+ nil
112
+ end
113
+ end
114
+
115
+ # Adds random jitter to a delay value.
116
+ # @param delay [Float] The base delay in seconds.
117
+ # @return [Float] The delay with jitter applied.
118
+ def add_jitter(delay)
119
+ jitter = delay * JITTER_FACTOR * (rand - 0.5) * 2
120
+ [delay + jitter, 0].max
42
121
  end
43
122
 
44
123
  # @param request [Payabli::Internal::Http::BaseRequest] The HTTP request.
45
124
  # @return [URI::Generic] The URL.
46
125
  def build_url(request)
126
+ encoded_query = request.encode_query
127
+
128
+ # If the path is already an absolute URL, use it directly
129
+ if request.path.start_with?("http://", "https://")
130
+ url = request.path
131
+ url = "#{url}?#{encode_query(encoded_query)}" if encoded_query&.any?
132
+ return URI.parse(url)
133
+ end
134
+
47
135
  path = request.path.start_with?("/") ? request.path[1..] : request.path
48
136
  base = request.base_url || @base_url
49
137
  url = "#{base.chomp("/")}/#{path}"
50
- url = "#{url}?#{encode_query(request.query)}" if request.query&.any?
138
+ url = "#{url}?#{encode_query(encoded_query)}" if encoded_query&.any?
51
139
  URI.parse(url)
52
140
  end
53
141
 
@@ -92,7 +180,9 @@ module Payabli
92
180
 
93
181
  http = Net::HTTP.new(url.host, port)
94
182
  http.use_ssl = is_https
95
- http.max_retries = @max_retries
183
+ # NOTE: We handle retries at the application level with HTTP status code awareness,
184
+ # so we set max_retries to 0 to disable Net::HTTP's built-in network-level retries.
185
+ http.max_retries = 0
96
186
  http
97
187
  end
98
188
 
@@ -161,7 +161,7 @@ module Payabli
161
161
  end
162
162
 
163
163
  def to_h
164
- self.class.fields.merge(self.class.extra_fields).each_with_object({}) do |(name, field), acc|
164
+ result = self.class.fields.merge(self.class.extra_fields).each_with_object({}) do |(name, field), acc|
165
165
  # If there is a value present in the data, use that value
166
166
  # If there is a `nil` value present in the data, and it is optional but NOT nullable, exclude key altogether
167
167
  # If there is a `nil` value present in the data, and it is optional and nullable, use the nil value
@@ -178,6 +178,14 @@ module Payabli
178
178
 
179
179
  acc[field.api_name] = value
180
180
  end
181
+
182
+ # Inject union discriminant if this instance was coerced from a discriminated union
183
+ # and the discriminant key is not already present in the result
184
+ discriminant_key = instance_variable_get(:@_fern_union_discriminant_key)
185
+ discriminant_value = instance_variable_get(:@_fern_union_discriminant_value)
186
+ result[discriminant_key] = discriminant_value if discriminant_key && discriminant_value && !result.key?(discriminant_key)
187
+
188
+ result
181
189
  end
182
190
 
183
191
  def ==(other)
@@ -63,11 +63,27 @@ module Payabli
63
63
  # @return [Class]
64
64
  private def resolve_member(value)
65
65
  if discriminated? && value.is_a?(::Hash)
66
- discriminant_value = value.fetch(@discriminant, nil)
66
+ # Try both symbol and string keys for the discriminant
67
+ discriminant_value = value.fetch(@discriminant, nil) || value.fetch(@discriminant.to_s, nil)
67
68
 
68
69
  return if discriminant_value.nil?
69
70
 
70
- members.to_h[discriminant_value]&.call
71
+ # Convert to string for consistent comparison
72
+ discriminant_str = discriminant_value.to_s
73
+
74
+ # First try exact match
75
+ members_hash = members.to_h
76
+ result = members_hash[discriminant_str]&.call
77
+ return result if result
78
+
79
+ # Try case-insensitive match as fallback
80
+ discriminant_lower = discriminant_str.downcase
81
+ matching_keys = members_hash.keys.select { |k| k.to_s.downcase == discriminant_lower }
82
+
83
+ # Only use case-insensitive match if exactly one key matches (avoid ambiguity)
84
+ return members_hash[matching_keys.first]&.call if matching_keys.length == 1
85
+
86
+ nil
71
87
  else
72
88
  # First try exact type matching
73
89
  result = members.find do |_key, mem|
@@ -117,7 +133,19 @@ module Payabli
117
133
  raise Errors::TypeError, "could not resolve to member of union #{self}"
118
134
  end
119
135
 
120
- Utils.coerce(type, value, strict: strict)
136
+ coerced = Utils.coerce(type, value, strict: strict)
137
+
138
+ # For discriminated unions, store the discriminant info on the coerced instance
139
+ # so it can be injected back during serialization (to_h)
140
+ if discriminated? && value.is_a?(::Hash) && coerced.is_a?(Model)
141
+ discriminant_value = value.fetch(@discriminant, nil) || value.fetch(@discriminant.to_s, nil)
142
+ if discriminant_value
143
+ coerced.instance_variable_set(:@_fern_union_discriminant_key, @discriminant.to_s)
144
+ coerced.instance_variable_set(:@_fern_union_discriminant_value, discriminant_value)
145
+ end
146
+ end
147
+
148
+ coerced
121
149
  end
122
150
 
123
151
  # Parse JSON string and coerce to the correct union member type
@@ -76,8 +76,8 @@ module Payabli
76
76
  in Module
77
77
  case type
78
78
  in ->(t) {
79
- t.singleton_class.included_modules.include?(Enum) ||
80
- t.singleton_class.included_modules.include?(Union)
79
+ t.singleton_class.include?(Enum) ||
80
+ t.singleton_class.include?(Union)
81
81
  }
82
82
  return type.coerce(value, strict: strict)
83
83
  else
@@ -95,6 +95,21 @@ module Payabli
95
95
  def self.symbolize_keys(hash)
96
96
  hash.transform_keys(&:to_sym)
97
97
  end
98
+
99
+ # Converts camelCase keys to snake_case symbols
100
+ # This allows SDK methods to accept both snake_case and camelCase keys
101
+ # e.g., { refundMethod: ... } becomes { refund_method: ... }
102
+ #
103
+ # @param hash [Hash]
104
+ # @return [Hash]
105
+ def self.normalize_keys(hash)
106
+ hash.transform_keys do |key|
107
+ key_str = key.to_s
108
+ # Convert camelCase to snake_case
109
+ snake_case = key_str.gsub(/([a-z\d])([A-Z])/, '\1_\2').downcase
110
+ snake_case.to_sym
111
+ end
112
+ end
98
113
  end
99
114
  end
100
115
  end