ledger_sync 1.4.1 → 1.4.2

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 (143) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +71 -17
  3. data/docs/.gitignore +4 -0
  4. data/documentation/build.sh +3 -1
  5. data/documentation/site/_includes/ledgers/{Stripe_summary.md → stripe_summary.md} +0 -0
  6. data/ledger_sync.gemspec +4 -0
  7. data/lib/ledger_sync/serialization/type/deserializer_references_one_type.rb +1 -1
  8. data/lib/ledger_sync/version.rb +1 -1
  9. metadata +59 -136
  10. data/docs/CNAME +0 -1
  11. data/docs/assets/css/brands.min.css +0 -5
  12. data/docs/assets/css/fontawesome.min.css +0 -5
  13. data/docs/assets/css/main.css +0 -1924
  14. data/docs/assets/css/monokai.css +0 -441
  15. data/docs/assets/js/main.js +0 -214
  16. data/docs/assets/js/plugins.js +0 -22
  17. data/docs/assets/js/prism.js +0 -9
  18. data/docs/assets/webfonts/fa-brands-400.eot +0 -0
  19. data/docs/assets/webfonts/fa-brands-400.svg +0 -3452
  20. data/docs/assets/webfonts/fa-brands-400.ttf +0 -0
  21. data/docs/assets/webfonts/fa-brands-400.woff +0 -0
  22. data/docs/assets/webfonts/fa-brands-400.woff2 +0 -0
  23. data/docs/blog/index.html +0 -282
  24. data/docs/guides/architecture/clients/index.html +0 -458
  25. data/docs/guides/architecture/index.html +0 -435
  26. data/docs/guides/architecture/operations/index.html +0 -465
  27. data/docs/guides/architecture/resources/index.html +0 -461
  28. data/docs/guides/architecture/results/index.html +0 -426
  29. data/docs/guides/architecture/searchers/index.html +0 -446
  30. data/docs/guides/architecture/serialization/index.html +0 -476
  31. data/docs/guides/community/index.html +0 -412
  32. data/docs/guides/contribute/console/index.html +0 -424
  33. data/docs/guides/contribute/deployment/index.html +0 -434
  34. data/docs/guides/contribute/documentation/index.html +0 -450
  35. data/docs/guides/contribute/index.html +0 -434
  36. data/docs/guides/contribute/qa/index.html +0 -436
  37. data/docs/guides/contribute/testing/index.html +0 -424
  38. data/docs/guides/customization/custom_resources/index.html +0 -461
  39. data/docs/guides/customization/custom_serializers/index.html +0 -460
  40. data/docs/guides/customization/index.html +0 -431
  41. data/docs/guides/customization/resource_converters/index.html +0 -491
  42. data/docs/guides/getting-started/get-help/index.html +0 -427
  43. data/docs/guides/getting-started/index.html +0 -421
  44. data/docs/guides/getting-started/installation/index.html +0 -433
  45. data/docs/guides/getting-started/quick-start/index.html +0 -531
  46. data/docs/guides/index.html +0 -428
  47. data/docs/guides/ledgers/index.html +0 -429
  48. data/docs/guides/ledgers/netsuite/index.html +0 -424
  49. data/docs/guides/ledgers/netsuite_soap/index.html +0 -424
  50. data/docs/guides/ledgers/quickbooks_online/index.html +0 -424
  51. data/docs/guides/ledgers/stripe/index.html +0 -424
  52. data/docs/guides/modern-treasury/index.html +0 -411
  53. data/docs/guides/tips_and_more/index.html +0 -471
  54. data/docs/images/1.jpg +0 -0
  55. data/docs/images/10.jpg +0 -0
  56. data/docs/images/2.jpg +0 -0
  57. data/docs/images/3.jpg +0 -0
  58. data/docs/images/4.jpg +0 -0
  59. data/docs/images/5.jpg +0 -0
  60. data/docs/images/6.jpg +0 -0
  61. data/docs/images/7.jpg +0 -0
  62. data/docs/images/8.jpg +0 -0
  63. data/docs/images/9.jpg +0 -0
  64. data/docs/images/logo.svg +0 -8
  65. data/docs/index.html +0 -379
  66. data/docs/overview/index.html +0 -409
  67. data/docs/posts/introducing-docs/index.html +0 -270
  68. data/docs/posts/netsuite-authentication/index.html +0 -624
  69. data/docs/reference/architecture/clients/index.html +0 -332
  70. data/docs/reference/architecture/index.html +0 -311
  71. data/docs/reference/architecture/operations/index.html +0 -302
  72. data/docs/reference/architecture/resources/index.html +0 -335
  73. data/docs/reference/architecture/results/index.html +0 -302
  74. data/docs/reference/architecture/searchers/index.html +0 -302
  75. data/docs/reference/architecture/serialization/index.html +0 -302
  76. data/docs/reference/index.html +0 -281
  77. data/docs/reference/netsuite/authentication/index.html +0 -392
  78. data/docs/reference/netsuite/authentication/token_based_authentication/index.html +0 -486
  79. data/docs/reference/netsuite/index.html +0 -388
  80. data/docs/reference/netsuite/resources/account/index.html +0 -484
  81. data/docs/reference/netsuite/resources/check/index.html +0 -492
  82. data/docs/reference/netsuite/resources/check_line_item/index.html +0 -460
  83. data/docs/reference/netsuite/resources/currency/index.html +0 -476
  84. data/docs/reference/netsuite/resources/customer/index.html +0 -488
  85. data/docs/reference/netsuite/resources/customer_deposit/index.html +0 -480
  86. data/docs/reference/netsuite/resources/department/index.html +0 -484
  87. data/docs/reference/netsuite/resources/deposit/index.html +0 -468
  88. data/docs/reference/netsuite/resources/deposit_line_item/index.html +0 -460
  89. data/docs/reference/netsuite/resources/index.html +0 -436
  90. data/docs/reference/netsuite/resources/invoice/index.html +0 -468
  91. data/docs/reference/netsuite/resources/invoice_line_item/index.html +0 -456
  92. data/docs/reference/netsuite/resources/item/index.html +0 -444
  93. data/docs/reference/netsuite/resources/journal_entry/index.html +0 -488
  94. data/docs/reference/netsuite/resources/journal_entry_line_item/index.html +0 -464
  95. data/docs/reference/netsuite/resources/ledger_class/index.html +0 -484
  96. data/docs/reference/netsuite/resources/location/index.html +0 -468
  97. data/docs/reference/netsuite/resources/resource/index.html +0 -440
  98. data/docs/reference/netsuite/resources/subsidiary/index.html +0 -448
  99. data/docs/reference/netsuite/resources/vendor/index.html +0 -492
  100. data/docs/reference/netsuite_soap/index.html +0 -303
  101. data/docs/reference/netsuite_soap/resources/customer/index.html +0 -364
  102. data/docs/reference/netsuite_soap/resources/index.html +0 -316
  103. data/docs/reference/netsuite_soap/resources/resource/index.html +0 -336
  104. data/docs/reference/netsuite_soap/resources/subsidiary/index.html +0 -356
  105. data/docs/reference/quickbooks_online/authentication/index.html +0 -442
  106. data/docs/reference/quickbooks_online/errors/index.html +0 -395
  107. data/docs/reference/quickbooks_online/index.html +0 -393
  108. data/docs/reference/quickbooks_online/resources/account/index.html +0 -530
  109. data/docs/reference/quickbooks_online/resources/bill/index.html +0 -534
  110. data/docs/reference/quickbooks_online/resources/bill_line_item/index.html +0 -496
  111. data/docs/reference/quickbooks_online/resources/bill_payment/index.html +0 -550
  112. data/docs/reference/quickbooks_online/resources/bill_payment_line_item/index.html +0 -488
  113. data/docs/reference/quickbooks_online/resources/currency/index.html +0 -492
  114. data/docs/reference/quickbooks_online/resources/customer/index.html +0 -514
  115. data/docs/reference/quickbooks_online/resources/department/index.html +0 -518
  116. data/docs/reference/quickbooks_online/resources/deposit/index.html +0 -526
  117. data/docs/reference/quickbooks_online/resources/deposit_line_item/index.html +0 -500
  118. data/docs/reference/quickbooks_online/resources/expense/index.html +0 -538
  119. data/docs/reference/quickbooks_online/resources/expense_line_item/index.html +0 -496
  120. data/docs/reference/quickbooks_online/resources/index.html +0 -484
  121. data/docs/reference/quickbooks_online/resources/invoice/index.html +0 -526
  122. data/docs/reference/quickbooks_online/resources/invoice_sales_line_item/index.html +0 -496
  123. data/docs/reference/quickbooks_online/resources/item/index.html +0 -484
  124. data/docs/reference/quickbooks_online/resources/journal_entry/index.html +0 -518
  125. data/docs/reference/quickbooks_online/resources/journal_entry_line_item/index.html +0 -504
  126. data/docs/reference/quickbooks_online/resources/ledger_class/index.html +0 -518
  127. data/docs/reference/quickbooks_online/resources/payment/index.html +0 -538
  128. data/docs/reference/quickbooks_online/resources/payment_line_item/index.html +0 -488
  129. data/docs/reference/quickbooks_online/resources/preferences/index.html +0 -526
  130. data/docs/reference/quickbooks_online/resources/primary_email_addr/index.html +0 -484
  131. data/docs/reference/quickbooks_online/resources/primary_phone/index.html +0 -484
  132. data/docs/reference/quickbooks_online/resources/resource/index.html +0 -480
  133. data/docs/reference/quickbooks_online/resources/subsidiary/index.html +0 -488
  134. data/docs/reference/quickbooks_online/resources/transfer/index.html +0 -522
  135. data/docs/reference/quickbooks_online/resources/vendor/index.html +0 -526
  136. data/docs/reference/quickbooks_online/webhooks/index.html +0 -427
  137. data/docs/reference/stripe/index.html +0 -293
  138. data/docs/reference/stripe/resources/customer/index.html +0 -366
  139. data/docs/reference/stripe/resources/index.html +0 -309
  140. data/docs/reference/stripe/resources/resource/index.html +0 -330
  141. data/docs/style-guide/index.html +0 -375
  142. data/documentation/site/Gemfile +0 -11
  143. data/documentation/site/Gemfile.lock +0 -69
@@ -1,270 +0,0 @@
1
- <!doctype html>
2
- <html lang="en">
3
-
4
- <head>
5
-
6
- <title>LedgerSync - Introducing Documentation - LedgerSync</title>
7
- <meta charset="utf-8">
8
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
9
- <meta name="description" content="Completely re-designed the documentation, including guides, ledger references, and the LedgerSync blog." />
10
- <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700,700i%26display=swap" rel="stylesheet">
11
- <link rel="stylesheet" href="/assets/css/main.css">
12
-
13
- <!-- Global site tag (gtag.js) - Google Analytics -->
14
- <script async src="https://www.googletagmanager.com/gtag/js?id=UA-152343827-1"></script>
15
- <script>
16
- window.dataLayer = window.dataLayer || [];
17
- function gtag(){dataLayer.push(arguments);}
18
- gtag('js', new Date());
19
-
20
- gtag('config', 'UA-152343827-1');
21
- </script>
22
-
23
- </head>
24
-
25
- <body>
26
-
27
- <div id="page" class="site">
28
- <header id="masthead" class="site-header outer">
29
- <div class="inner">
30
- <div class="site-header-inside">
31
- <div class="site-branding">
32
-
33
-
34
- <p class="site-logo"><a href="/"><img src="/images/logo.svg" alt="LedgerSync" /></a></p>
35
-
36
- </div><!-- .site-branding -->
37
-
38
-
39
- <nav id="main-navigation" class="site-navigation" aria-label="Main Navigation">
40
- <div class="site-nav-inside">
41
- <button id="menu-close" class="menu-toggle"><span class="screen-reader-text">Open Menu</span><span class="icon-close" aria-hidden="true"></span></button>
42
- <ul class="menu">
43
-
44
- <li class="menu-item">
45
-
46
-
47
- <a class="" href="/" >
48
-
49
- Home
50
-
51
- </a>
52
-
53
- </li>
54
-
55
- <li class="menu-item">
56
-
57
-
58
- <a class="" href="/guides/" >
59
-
60
- Guides
61
-
62
- </a>
63
-
64
- </li>
65
-
66
- <li class="menu-item has-children">
67
-
68
-
69
- <a class="" href="/reference" >
70
-
71
- Reference
72
-
73
- </a>
74
-
75
-
76
- <ul class="submenu">
77
-
78
- <li class="menu-item">
79
-
80
-
81
- <a class="" href="/reference/netsuite" >
82
-
83
- NetSuite REST
84
-
85
- </a>
86
- </li>
87
-
88
- <li class="menu-item">
89
-
90
-
91
- <a class="" href="/reference/netsuite_soap" >
92
-
93
- NetSuite SOAP
94
-
95
- </a>
96
- </li>
97
-
98
- <li class="menu-item">
99
-
100
-
101
- <a class="" href="/reference/quickbooks_online" >
102
-
103
- QuickBooks Online
104
-
105
- </a>
106
- </li>
107
-
108
- <li class="menu-item">
109
-
110
-
111
- <a class="" href="/reference/stripe" >
112
-
113
- Stripe
114
-
115
- </a>
116
- </li>
117
-
118
- </ul>
119
-
120
-
121
- </li>
122
-
123
- <li class="menu-item">
124
-
125
-
126
- <a class="" href="/blog" >
127
-
128
- Blog
129
-
130
- </a>
131
-
132
- </li>
133
-
134
- <li class="menu-item">
135
-
136
-
137
- <a class="" href="/guides/contribute" >
138
-
139
- Contribute
140
-
141
- </a>
142
-
143
- </li>
144
-
145
- <li class="menu-item menu-button">
146
-
147
-
148
- <a class="button" href="https://github.com/LedgerSync/ledger_sync" >
149
-
150
- GitHub
151
-
152
- </a>
153
-
154
- </li>
155
-
156
- </ul>
157
- </div><!-- .site-nav-inside -->
158
- </nav><!-- .site-navigation -->
159
- <button id="menu-open" class="menu-toggle"><span class="screen-reader-text">Close Menu</span><span class="icon-menu" aria-hidden="true"></span></button>
160
-
161
- </div><!-- .site-header-inside -->
162
- </div><!-- .inner -->
163
- </header><!-- .site-header -->
164
-
165
- <main id="content" class="site-content">
166
- <article class="post post-full">
167
- <header class="post-header has-gradient outer">
168
-
169
-
170
- <div class="inner-sm">
171
- <div class="post-meta">
172
- <time class="published" datetime="2020-06-01 00:00">June 01, 2020</time>
173
- </div>
174
- <h1 class="post-title">Introducing Documentation</h1>
175
-
176
-
177
- </div>
178
- </header>
179
- <div class="inner-md outer">
180
- <div class="post-content">
181
- <p>LedgerSync has now grown to support three different ledgers! As LedgerSync grows, we want to ensure the library is easy
182
- to use and understand. Our README was growing quite unwieldy, so we decided to generate this static website.</p>
183
-
184
- <p>These docs contain a mix of manually and automatically generated content. We have developed scripts that keep our
185
- docs in sync with the code. Our goal is to reduce the need to write documentation with each commit.</p>
186
-
187
- <p>If you find any bugs or have any suggestions, please <a href="https://github.com/LedgerSync/ledger_sync/issues/new">open an issue on Github</a>.</p>
188
-
189
- </div><!-- .post-content -->
190
- </div><!-- .inner-md -->
191
- </article><!-- .post -->
192
-
193
- <!-- Next/previous post navigation TBD -->
194
- <!--
195
- <div class="inner-md outer">
196
- <nav class="read-next">
197
- <h2 class="read-next-title line-left">Read Next</h2>
198
- <div class="nav-links">
199
- <article class="post">
200
- <div class="post-meta">
201
- <time class="published" datetime="">Previous post date</time>
202
- </div>
203
- <h3 class="post-title"><a href="#" rel="bookmark">Previous Post Title</a></h3>
204
- </article>
205
- <article class="post">
206
- <div class="post-meta">
207
- <time class="published" datetime="">Next post date</time>
208
- </div>
209
- <h3 class="post-title"><a href="#" rel="bookmark">Next Post Title</a></h3>
210
- </article>
211
- </div>
212
- </nav>
213
- </div>
214
- -->
215
-
216
- </main><!-- .site-content -->
217
- <footer id="colophon" class="site-footer outer">
218
- <div class="inner">
219
- <div class="site-footer-inside">
220
- <p class="site-info">
221
-
222
- <span class="copyright">&copy; Modern Treasury Inc. All rights reserved.</span>
223
- <a class="" href="https://www.moderntreasury.com" target="_blank" rel="noopener" >
224
-
225
- Maintained with ❤️ in San Francisco, CA by Modern Treasury
226
-
227
- </a>
228
- </p>
229
- <!-- .site-info -->
230
-
231
- <div class="social-links">
232
-
233
- <a class="" href="https://www.netlify.com" target="_blank" rel="noopener" >
234
-
235
- <img src="https://www.netlify.com/img/global/badges/netlify-dark.svg" alt="Deploys by Netlify" />
236
-
237
- </a>
238
- <a class="button button-icon" href="https://twitter.com/ModernTreasury" target="_blank" rel="noopener" >
239
-
240
- <span class="icon fab fa-twitter" aria-hidden="true"></span><span class="screen-reader-text">Twitter</span>
241
-
242
- </a>
243
- <a class="button button-icon" href="https://www.linkedin.com/company/modern-treasury" target="_blank" rel="noopener" >
244
-
245
- <span class="icon fab fa-linkedin" aria-hidden="true"></span><span class="screen-reader-text">LinkedIn</span>
246
-
247
- </a>
248
- <a class="button button-icon" href="https://github.com/LedgerSync/ledger_sync" target="_blank" rel="noopener" >
249
-
250
- <span class="icon fab fa-github" aria-hidden="true"></span><span class="screen-reader-text">GitHub</span>
251
-
252
- </a>
253
- </div>
254
- <!-- .social-links -->
255
-
256
- </div>
257
- <!-- .site-footer-inside -->
258
- </div>
259
- <!-- .inner -->
260
- </footer>
261
- <!-- .site-footer -->
262
- </div><!-- .site -->
263
-
264
- <!-- Scripts -->
265
- <script src="/assets/js/plugins.js"></script>
266
- <script src="/assets/js/prism.js" data-manual></script>
267
- <script src="/assets/js/main.js"></script>
268
- </body>
269
-
270
- </html>
@@ -1,624 +0,0 @@
1
- <!doctype html>
2
- <html lang="en">
3
-
4
- <head>
5
-
6
- <title>LedgerSync - How to authenticate to NetSuite's SuiteTalk REST Web Services API - LedgerSync</title>
7
- <meta charset="utf-8">
8
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
9
- <meta name="description" content="A step-by-step guide to authenticating to the new NetSuite REST API." />
10
- <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700,700i%26display=swap" rel="stylesheet">
11
- <link rel="stylesheet" href="/assets/css/main.css">
12
-
13
- <!-- Global site tag (gtag.js) - Google Analytics -->
14
- <script async src="https://www.googletagmanager.com/gtag/js?id=UA-152343827-1"></script>
15
- <script>
16
- window.dataLayer = window.dataLayer || [];
17
- function gtag(){dataLayer.push(arguments);}
18
- gtag('js', new Date());
19
-
20
- gtag('config', 'UA-152343827-1');
21
- </script>
22
-
23
- </head>
24
-
25
- <body>
26
-
27
- <div id="page" class="site">
28
- <header id="masthead" class="site-header outer">
29
- <div class="inner">
30
- <div class="site-header-inside">
31
- <div class="site-branding">
32
-
33
-
34
- <p class="site-logo"><a href="/"><img src="/images/logo.svg" alt="LedgerSync" /></a></p>
35
-
36
- </div><!-- .site-branding -->
37
-
38
-
39
- <nav id="main-navigation" class="site-navigation" aria-label="Main Navigation">
40
- <div class="site-nav-inside">
41
- <button id="menu-close" class="menu-toggle"><span class="screen-reader-text">Open Menu</span><span class="icon-close" aria-hidden="true"></span></button>
42
- <ul class="menu">
43
-
44
- <li class="menu-item">
45
-
46
-
47
- <a class="" href="/" >
48
-
49
- Home
50
-
51
- </a>
52
-
53
- </li>
54
-
55
- <li class="menu-item">
56
-
57
-
58
- <a class="" href="/guides/" >
59
-
60
- Guides
61
-
62
- </a>
63
-
64
- </li>
65
-
66
- <li class="menu-item has-children">
67
-
68
-
69
- <a class="" href="/reference" >
70
-
71
- Reference
72
-
73
- </a>
74
-
75
-
76
- <ul class="submenu">
77
-
78
- <li class="menu-item">
79
-
80
-
81
- <a class="" href="/reference/netsuite" >
82
-
83
- NetSuite REST
84
-
85
- </a>
86
- </li>
87
-
88
- <li class="menu-item">
89
-
90
-
91
- <a class="" href="/reference/netsuite_soap" >
92
-
93
- NetSuite SOAP
94
-
95
- </a>
96
- </li>
97
-
98
- <li class="menu-item">
99
-
100
-
101
- <a class="" href="/reference/quickbooks_online" >
102
-
103
- QuickBooks Online
104
-
105
- </a>
106
- </li>
107
-
108
- <li class="menu-item">
109
-
110
-
111
- <a class="" href="/reference/stripe" >
112
-
113
- Stripe
114
-
115
- </a>
116
- </li>
117
-
118
- </ul>
119
-
120
-
121
- </li>
122
-
123
- <li class="menu-item">
124
-
125
-
126
- <a class="" href="/blog" >
127
-
128
- Blog
129
-
130
- </a>
131
-
132
- </li>
133
-
134
- <li class="menu-item">
135
-
136
-
137
- <a class="" href="/guides/contribute" >
138
-
139
- Contribute
140
-
141
- </a>
142
-
143
- </li>
144
-
145
- <li class="menu-item menu-button">
146
-
147
-
148
- <a class="button" href="https://github.com/LedgerSync/ledger_sync" >
149
-
150
- GitHub
151
-
152
- </a>
153
-
154
- </li>
155
-
156
- </ul>
157
- </div><!-- .site-nav-inside -->
158
- </nav><!-- .site-navigation -->
159
- <button id="menu-open" class="menu-toggle"><span class="screen-reader-text">Close Menu</span><span class="icon-menu" aria-hidden="true"></span></button>
160
-
161
- </div><!-- .site-header-inside -->
162
- </div><!-- .inner -->
163
- </header><!-- .site-header -->
164
-
165
- <main id="content" class="site-content">
166
- <article class="post post-full">
167
- <header class="post-header has-gradient outer">
168
-
169
-
170
- <div class="inner-sm">
171
- <div class="post-meta">
172
- <time class="published" datetime="2020-06-01 00:00">June 01, 2020</time>
173
- </div>
174
- <h1 class="post-title">How to authenticate to NetSuite's SuiteTalk REST Web Services API</h1>
175
-
176
-
177
- </div>
178
- </header>
179
- <div class="inner-md outer">
180
- <div class="post-content">
181
- <p>Earlier this year, NetSuite released their new REST API called SuiteTalk REST Web Services. While still incomplete, this API provides a much friendlier interface for developers than its predecessors— the SOAP API and RESTlets. We chose to use the new REST API, because we believe it is the future for building integrations to NetSuite. The REST standard is much more intuitive, with many resources across many languages and frameworks.</p>
182
-
183
- <div class="alert info">
184
- <strong>Tip:</strong> We do our best to write comprehensive unit tests for the entire library. Tests are a great resource for examples on inputs, outputs, and usage, not all of which may be documented here.
185
- </div>
186
-
187
- <h2 id="options-for-authentication">Options for Authentication</h2>
188
-
189
- <p>The REST API offers two types of authentication: Token-Based Authentication (TBA) and OAuth 2.0. We chose to use TBA for the REST client.</p>
190
-
191
- <p>Simply put, TBA is based on OAuth 1.0. Ultimately, you need to generate a request header that includes a signature created using tokens retrieved from the NetSuite dashboard and the OAuth 1.0 standard. Unfortunately, at the time of development, we hit a few walls trying to authenticate:</p>
192
-
193
- <ul>
194
- <li>The NetSuite documentation was only for their SOAP API and RESTlets</li>
195
- <li>There were no examples in Ruby</li>
196
- <li>Code samples relied on libraries or packages, making it hard to understand what was actually happening under the hood.</li>
197
- <li>The nonce and timestamp were not defined in the inputs of examples we found, so outputs would naturally vary given that these values are meant to change in practice.</li>
198
- <li>There were very few examples that had both inputs and signature output to test against.</li>
199
- </ul>
200
-
201
- <p>In the end, the challenge of authenticating to NetSuite in the REST API was computing the signature. No examples we found worked for us, and regardless, we needed it in Ruby. Frustratingly, the only way to know if we were correct was to try API calls after making tweaks to our signature generation algorithm.</p>
202
-
203
- <p>If you’re reading this post, hopefully this will save you a headache or two. We will clearly lay out our solution, break it down step-by-step, and we will give you some real examples. Let’s get going!</p>
204
-
205
- <h2 id="our-solution">Our Solution</h2>
206
-
207
- <p>Let’s start with the full solution, which can be found in the LedgerSync library class <code class="highlighter-rouge">LedgerSync::Ledgers::NetSuite::Token</code> (code can be found here). The Token handles creating the authorization header that will be used to sign the request. The request header looks something like this:</p>
208
-
209
- <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Authorization: OAuth realm="TEST_REALM",oauth_consumer_key="ef40afdd8abaac111b13825dd5e5e2ddddb44f86d5a0dd6dcf38c20aae6b67e4",oauth_token="2b0ce516420110bcbd36b69e99196d1b7f6de3c6234c5afb799b73d87569f5cc",oauth_signature_method="HMAC-SHA256",oauth_timestamp="1508242306",oauth_nonce="fjaLirsIcCGVZWzBX0pg",oauth_version="1.0",oauth_signature="i7MEtGwhCTIZbTsTrNGw9LdcERn4wsjt5C7TxmKWIfU%3D"
210
- </code></pre></div></div>
211
-
212
- <h2 id="the-inputs">The Inputs</h2>
213
-
214
- <p>To compute a signature, we need a few things first. Let’s walk through each one and how to find it:</p>
215
-
216
- <h3 id="method"><code class="highlighter-rouge">method</code></h3>
217
-
218
- <p>The request method will be one of the following:</p>
219
-
220
- <ul>
221
- <li><code class="highlighter-rouge">POST</code></li>
222
- <li><code class="highlighter-rouge">PUT</code></li>
223
- <li><code class="highlighter-rouge">PATCH</code></li>
224
- <li><code class="highlighter-rouge">GET</code></li>
225
- <li><code class="highlighter-rouge">DELETE</code></li>
226
- </ul>
227
-
228
- <h3 id="consumer_key-consumer_secret"><code class="highlighter-rouge">consumer_key</code>, <code class="highlighter-rouge">consumer_secret</code></h3>
229
-
230
- <p>The consumer key and secret can be retrieved from NetSuite by creating an Integration Record. Note that these values are only shown once at the end of creating a new Integration Record. Once you navigate away, you will no longer be able to see these values. You can reset the key and secret on existing Integration Records should you need to generate a new pair.</p>
231
-
232
- <h3 id="signature_method"><code class="highlighter-rouge">signature_method</code></h3>
233
-
234
- <p>NetSuite supports multiple signature methods. Our library uses HMAC-SHA256.</p>
235
-
236
- <h3 id="timestamp"><code class="highlighter-rouge">timestamp</code></h3>
237
-
238
- <p>We need to include a current timestamp in the signature and header.</p>
239
-
240
- <h3 id="nonce"><code class="highlighter-rouge">nonce</code></h3>
241
-
242
- <p>We need to include a random alphanumeric string to be used in the signature and header.</p>
243
-
244
- <h3 id="oauth_version"><code class="highlighter-rouge">oauth_version</code></h3>
245
-
246
- <p>The OAuth Version is defaults to “1.0”</p>
247
-
248
- <h3 id="realm"><code class="highlighter-rouge">realm</code></h3>
249
-
250
- <p>The realm is the NetSuite account ID. You can find this in your account or in the URL:</p>
251
-
252
- <p><code class="highlighter-rouge">https://&lt;ACCOUNT_ID&gt;.app.netsuite.com/app/center/card.nl</code></p>
253
-
254
- <p>If you are using a sandbox or test drive account, your account ID will include a hyphen and some other characters. For example, it may look like this: <code class="highlighter-rouge">9876543-sb1</code>.</p>
255
-
256
- <p>Once you have the account ID, we will need to transform it to the format the API expects. You replace any hyphens with underscores (a.k.a. <code class="highlighter-rouge">_</code>) and capitalize all letters. So <code class="highlighter-rouge">9876543-sb1</code> will become <code class="highlighter-rouge">9876543_SB1</code>.</p>
257
-
258
- <h3 id="token_id-token_secret"><code class="highlighter-rouge">token_id</code>, <code class="highlighter-rouge">token_secret</code></h3>
259
-
260
- <p>These values can be found in NetSuite when you <a href="https://system.netsuite.com/app/setup/accesstokens.nl">create an Access Token</a>. Like the Integration Record, these values are only visible at the end of creating the token and will not be shown again. You can also reset these values on existing Access Tokens.</p>
261
-
262
- <h3 id="url"><code class="highlighter-rouge">url</code></h3>
263
-
264
- <p>This is the URL of the request, which must include any query string parameters you intend to pass.</p>
265
-
266
- <h2 id="example-values">Example Values</h2>
267
-
268
- <p>For this guide, we will use the following values:</p>
269
-
270
- <div class="responsive-table">
271
- <table>
272
- <caption>Input values</caption>
273
- <thead>
274
- <tr>
275
- <th>Variable</th>
276
- <th>Value</th>
277
- </tr>
278
- </thead>
279
- <tbody>
280
- <tr>
281
- <td><code>method</code></td>
282
- <td><code>"GET"</code></td>
283
- </tr>
284
- <tr>
285
- <td><code>consumer_key</code></td>
286
- <td><code>"CONSUMER_KEY_VALUE"</code></td>
287
- </tr>
288
- <tr>
289
- <td><code>consumer_secret</code></td>
290
- <td><code>"CONSUMER_SECRET_VALUE"</code></td>
291
- </tr>
292
- <tr>
293
- <td><code>signature_method</code></td>
294
- <td>default, <code>"HMAC-SHA256"</code></td>
295
- </tr>
296
- <tr>
297
- <td><code>timestamp</code></td>
298
- <td>Typically, you will leave this empty, but we will use <code>1234567890</code></td>
299
- </tr>
300
- <tr>
301
- <td><code>nonce</code></td>
302
- <td>Typically, you will leave this empty, but we will use <code>"asdfasdf"</code></td>
303
- </tr>
304
- <tr>
305
- <td><code>oauth_version</code></td>
306
- <td>default, <code>"1.0"</code></td>
307
- </tr>
308
- <tr>
309
- <td><code>realm</code></td>
310
- <td><code>"9876543_SB1"</code></td>
311
- </tr>
312
- <tr>
313
- <td><code>token_id</code></td>
314
- <td><code>"TOKEN_ID_VALUE"</code></td>
315
- </tr>
316
- <tr>
317
- <td><code>token_secret</code></td>
318
- <td><code>"TOKEN_SECRET_VALUE"</code></td>
319
- </tr>
320
- <tr>
321
- <td><code>url</code></td>
322
- <td><code>"https://9876543-sb1.suitetalk.api.netsuite.com/services/rest/record/v1/customer/123?expandSubResources=true"</code></td>
323
- </tr>
324
- </tbody>
325
- </table>
326
- </div>
327
-
328
- <div class="alert info">
329
- <strong>Note:</strong>
330
- The values for <code>nonce</code> and <code>timestamp</code> should be left <code>nil</code> or unpassed in practice. They are included here for purposes of having a consistent input and output, where typically they would be generated on the fly.
331
-
332
- </div>
333
-
334
- <p>Throughout this tutorial, examples will appear in the following style. You can copy and paste this code in sequence to get the same results.</p>
335
-
336
- <div class="example-container">
337
- <div class="content">
338
- <div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">method</span> <span class="o">=</span> <span class="s1">'GET'</span>
339
- <span class="n">consumer_key</span> <span class="o">=</span> <span class="s1">'CONSUMER_KEY_VALUE'</span>
340
- <span class="n">consumer_secret</span> <span class="o">=</span> <span class="s1">'CONSUMER_SECRET_VALUE'</span>
341
- <span class="n">nonce</span> <span class="o">=</span> <span class="s1">'asdfasdf'</span>
342
- <span class="n">oauth_version</span> <span class="o">=</span> <span class="s1">'1.0'</span>
343
- <span class="n">realm</span> <span class="o">=</span> <span class="s1">'9876543_SB1'</span>
344
- <span class="n">signature_method</span> <span class="o">=</span> <span class="s1">'HMAC-SHA256'</span>
345
- <span class="n">timestamp</span> <span class="o">=</span> <span class="mi">1_234_567_890</span>
346
- <span class="n">token_id</span> <span class="o">=</span> <span class="s1">'TOKEN_ID_VALUE'</span>
347
- <span class="n">token_secret</span> <span class="o">=</span> <span class="s1">'TOKEN_SECRET_VALUE'</span>
348
- <span class="n">url</span> <span class="o">=</span> <span class="s1">'https://9876543-sb1.suitetalk.api.netsuite.com/services/rest/record/v1/customer/123?expandSubResources=true'</span>
349
- </code></pre></div> </div>
350
- </div>
351
-
352
- </div>
353
-
354
- <h2 id="generating-the-header">Generating the header</h2>
355
-
356
- <p>Now that we have our inputs, we can walk through computing the signature and header.</p>
357
-
358
- <p>Before we dive in, please note that many values need to be escaped. If you see <code class="highlighter-rouge">escape(...)</code> being used below, it is shorthand for the following:</p>
359
-
360
- <div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">escape</span><span class="p">(</span><span class="n">str</span><span class="p">)</span>
361
- <span class="no">CGI</span><span class="p">.</span><span class="nf">escape</span><span class="p">(</span><span class="n">str</span><span class="p">.</span><span class="nf">to_s</span><span class="p">).</span><span class="nf">gsub</span><span class="p">(</span><span class="sr">/\+/</span><span class="p">,</span> <span class="s1">'%20'</span><span class="p">)</span>
362
- <span class="k">end</span>
363
- </code></pre></div></div>
364
-
365
- <p>Now let’s walk through each step:</p>
366
-
367
- <h3 id="1-build-data-string">1. Build data string</h3>
368
-
369
- <p>We need to create a string that will be used to compute a digest (a.k.a. signature) from. Using our values above, we can retrieve the string using the following:</p>
370
-
371
- <div class="example-container">
372
- <div class="content">
373
- <div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">token</span> <span class="o">=</span> <span class="no">LedgerSync</span><span class="o">::</span><span class="no">Ledgers</span><span class="o">::</span><span class="no">NetSuite</span><span class="o">::</span><span class="no">Token</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span>
374
- <span class="ss">method: </span><span class="nb">method</span><span class="p">,</span>
375
- <span class="ss">consumer_key: </span><span class="n">consumer_key</span><span class="p">,</span>
376
- <span class="ss">consumer_secret: </span><span class="n">consumer_secret</span><span class="p">,</span>
377
- <span class="ss">realm: </span><span class="n">realm</span><span class="p">,</span>
378
- <span class="ss">token_id: </span><span class="n">token_id</span><span class="p">,</span>
379
- <span class="ss">token_secret: </span><span class="n">token_secret</span><span class="p">,</span>
380
- <span class="ss">url: </span><span class="n">url</span>
381
- <span class="p">)</span>
382
-
383
- <span class="nb">puts</span> <span class="n">token</span><span class="p">.</span><span class="nf">signature_data_string</span>
384
- </code></pre></div> </div>
385
- </div>
386
-
387
- <div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="s2">"GET&amp;https%3A%2F%2F9876543-sb1.suitetalk.api.netsuite.com%2Fservices%2Frest%2Frecord%2Fv1%2Fcustomer%2F123&amp;expandSubResources%3Dtrue%26oauth_consumer_key%3DCONSUMER_KEY_VALUE%26oauth_nonce%3Dasdfasdf%26oauth_signature_method%3DHMAC-SHA256%26oauth_timestamp%3D1234567890%26oauth_token%3DTOKEN_ID_VALUE%26oauth_version%3D1.0"</span>
388
- </code></pre></div> </div>
389
-
390
- </div>
391
-
392
- <p>But how is this created? It is composed of three values that are escaped and joined with <code class="highlighter-rouge">&amp;</code>. The values are as follows:</p>
393
-
394
- <ul>
395
- <li><code class="highlighter-rouge">method</code>: Described in the inputs above.</li>
396
- <li><code class="highlighter-rouge">url_without_params</code>: The <code class="highlighter-rouge">url</code> with all query parameters removed. In our example, this would be <code class="highlighter-rouge">https://9876543-sb1.suitetalk.api.netsuite.com/services/rest/record/v1/customer/123</code></li>
397
- <li><code class="highlighter-rouge">parameters_string</code>: A string representation of all URL parameters as well as the oauth parameters.</li>
398
- </ul>
399
-
400
- <p>Let’s dive a level deeper and look into creating the <code class="highlighter-rouge">parameters</code> string.</p>
401
-
402
- <h3 id="1a-build-parameters-string">1a. Build parameters string</h3>
403
-
404
- <p>The parameters string is a sorted list of key/value pairs each joined with an ampersand (<code class="highlighter-rouge">&amp;</code>). The key/value pairs come from two sources:</p>
405
-
406
- <ul>
407
- <li>Query parameters parsed out of the URL, in our case <code class="highlighter-rouge">{ "expandSubResources" =&gt; "true }</code></li>
408
- <li>OAuth parameters</li>
409
- </ul>
410
-
411
- <p>For our example, we would have the following:</p>
412
-
413
- <div class="example-container">
414
- <div class="content">
415
- <div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">url_params</span> <span class="o">=</span> <span class="p">{</span>
416
- <span class="s2">"expandSubResources"</span> <span class="o">=&gt;</span> <span class="s2">"true"</span>
417
- <span class="p">}</span>
418
-
419
- <span class="n">oauth_parameters_array</span> <span class="o">=</span> <span class="p">{</span>
420
- <span class="ss">oauth_consumer_key: </span><span class="n">consumer_key</span><span class="p">,</span>
421
- <span class="ss">oauth_nonce: </span><span class="n">nonce</span><span class="p">,</span>
422
- <span class="ss">oauth_signature_method: </span><span class="n">signature_method</span><span class="p">,</span>
423
- <span class="ss">oauth_timestamp: </span><span class="n">timestamp</span><span class="p">,</span>
424
- <span class="ss">oauth_token: </span><span class="n">token_id</span><span class="p">,</span>
425
- <span class="ss">oauth_version: </span><span class="n">oauth_version</span>
426
- <span class="p">}.</span><span class="nf">to_a</span>
427
-
428
- <span class="n">parameters_string</span> <span class="o">=</span> <span class="n">url_params</span><span class="p">.</span><span class="nf">to_a</span>
429
- <span class="p">.</span><span class="nf">concat</span><span class="p">(</span><span class="n">oauth_parameters_array</span><span class="p">)</span>
430
- <span class="p">.</span><span class="nf">map</span> <span class="p">{</span> <span class="o">|</span><span class="n">k</span><span class="p">,</span> <span class="n">v</span><span class="o">|</span> <span class="p">[</span><span class="n">escape</span><span class="p">(</span><span class="n">k</span><span class="p">),</span> <span class="n">escape</span><span class="p">(</span><span class="n">v</span><span class="p">)]</span> <span class="p">}</span>
431
- <span class="p">.</span><span class="nf">sort</span> <span class="p">{</span> <span class="o">|</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="o">|</span> <span class="n">a</span> <span class="o">&lt;=&gt;</span> <span class="n">b</span> <span class="p">}</span>
432
- <span class="p">.</span><span class="nf">map</span> <span class="p">{</span> <span class="o">|</span><span class="n">e</span><span class="o">|</span> <span class="s2">"</span><span class="si">#{</span><span class="n">e</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="si">}</span><span class="s2">=</span><span class="si">#{</span><span class="n">e</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="si">}</span><span class="s2">"</span> <span class="p">}</span>
433
- <span class="p">.</span><span class="nf">join</span><span class="p">(</span><span class="s1">'&amp;'</span><span class="p">)</span>
434
-
435
- <span class="nb">puts</span> <span class="n">parameters_string</span>
436
- </code></pre></div> </div>
437
- </div>
438
-
439
- <div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="s2">"expandSubResources=true&amp;oauth_consumer_key=CONSUMER_KEY_VALUE&amp;oauth_nonce=asdfasdf&amp;oauth_signature_method=HMAC-SHA256&amp;oauth_timestamp=1234567890&amp;oauth_token=TOKEN_ID_VALUE&amp;oauth_version=1.0"</span>
440
- </code></pre></div> </div>
441
-
442
- </div>
443
-
444
- <h3 id="1b-put-it-together">1b. Put it together</h3>
445
-
446
- <p>Now that we have our <code class="highlighter-rouge">parameters_string</code>, we can generate the following:</p>
447
-
448
- <div class="example-container">
449
- <div class="content">
450
- <div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">url_without_params</span> <span class="o">=</span> <span class="s2">"https://9876543-sb1.suitetalk.api.netsuite.com/services/rest/record/v1/customer/123"</span>
451
-
452
- <span class="n">signature_data_string</span> <span class="o">=</span> <span class="p">[</span>
453
- <span class="nb">method</span><span class="p">,</span>
454
- <span class="n">escape</span><span class="p">(</span><span class="n">url_without_params</span><span class="p">),</span>
455
- <span class="n">escape</span><span class="p">(</span><span class="n">parameters_string</span><span class="p">)</span>
456
- <span class="p">].</span><span class="nf">join</span><span class="p">(</span><span class="s1">'&amp;'</span><span class="p">)</span>
457
- </code></pre></div> </div>
458
- </div>
459
-
460
- <div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="s2">"GET&amp;https%3A%2F%2F9876543-sb1.suitetalk.api.netsuite.com%2Fservices%2Frest%2Frecord%2Fv1%2Fcustomer%2F123&amp;expandSubResources%3Dtrue%26oauth_consumer_key%3DCONSUMER_KEY_VALUE%26oauth_nonce%3Dasdfasdf%26oauth_signature_method%3DHMAC-SHA256%26oauth_timestamp%3D1234567890%26oauth_token%3DTOKEN_ID_VALUE%26oauth_version%3D1.0"</span>
461
- </code></pre></div> </div>
462
-
463
- </div>
464
-
465
- <h2 id="2-build-signature-key">2. Build signature key</h2>
466
-
467
- <p>The final piece needed to generate a signature is the key. Our key is made by joining our <code class="highlighter-rouge">consumer_secret</code> to <code class="highlighter-rouge">token_secret</code> with an ampersand (<code class="highlighter-rouge">&amp;</code>):</p>
468
-
469
- <div class="example-container">
470
- <div class="content">
471
- <div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">key</span> <span class="o">||=</span> <span class="p">[</span>
472
- <span class="n">consumer_secret</span><span class="p">,</span>
473
- <span class="n">token_secret</span>
474
- <span class="p">].</span><span class="nf">join</span><span class="p">(</span><span class="s1">'&amp;'</span><span class="p">)</span>
475
- </code></pre></div> </div>
476
- </div>
477
-
478
- <div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="s2">"CONSUMER_SECRET_VALUE&amp;TOKEN_SECRET_VALUE"</span>
479
- </code></pre></div> </div>
480
-
481
- </div>
482
-
483
- <h2 id="3-compute-signature">3. Compute signature</h2>
484
-
485
- <p>Now with our <code class="highlighter-rouge">signature_data_string</code>, we will use the desired <code class="highlighter-rouge">signature_method</code> to compute a digest. We will assume we are using <code class="highlighter-rouge">HMAC-SHA256</code>.</p>
486
-
487
- <div class="example-container">
488
- <div class="content">
489
- <div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">signature</span> <span class="o">||=</span> <span class="no">Base64</span><span class="p">.</span><span class="nf">encode64</span><span class="p">(</span>
490
- <span class="no">OpenSSL</span><span class="o">::</span><span class="no">HMAC</span><span class="p">.</span><span class="nf">digest</span><span class="p">(</span>
491
- <span class="no">OpenSSL</span><span class="o">::</span><span class="no">Digest</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s1">'sha256'</span><span class="p">),</span>
492
- <span class="n">key</span><span class="p">,</span>
493
- <span class="n">signature_data_string</span>
494
- <span class="p">)</span>
495
- <span class="p">).</span><span class="nf">strip</span>
496
- </code></pre></div> </div>
497
- </div>
498
-
499
- <div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="s2">"cId0B3hP0sFVQw/gjQ/P6YiOSx76u0WfyO8umOlq3gg="</span>
500
- </code></pre></div> </div>
501
-
502
- </div>
503
-
504
- <h2 id="4-generate-header">4. Generate Header</h2>
505
-
506
- <p>Last but not least, we can now generate our header. The header is made by combining all of the inputs and our signature together in comma-separated, key-value pairs:</p>
507
-
508
- <div class="example-container">
509
- <div class="content">
510
- <div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">authorization_parts</span> <span class="o">=</span> <span class="p">[</span>
511
- <span class="p">[</span><span class="ss">:realm</span><span class="p">,</span> <span class="n">realm</span><span class="p">],</span>
512
- <span class="p">[</span><span class="ss">:oauth_consumer_key</span><span class="p">,</span> <span class="n">escape</span><span class="p">(</span><span class="n">consumer_key</span><span class="p">)],</span>
513
- <span class="p">[</span><span class="ss">:oauth_token</span><span class="p">,</span> <span class="n">escape</span><span class="p">(</span><span class="n">token_id</span><span class="p">)],</span>
514
- <span class="p">[</span><span class="ss">:oauth_signature_method</span><span class="p">,</span> <span class="n">signature_method</span><span class="p">],</span>
515
- <span class="p">[</span><span class="ss">:oauth_timestamp</span><span class="p">,</span> <span class="n">timestamp</span><span class="p">],</span>
516
- <span class="p">[</span><span class="ss">:oauth_nonce</span><span class="p">,</span> <span class="n">escape</span><span class="p">(</span><span class="n">nonce</span><span class="p">)],</span>
517
- <span class="p">[</span><span class="ss">:oauth_version</span><span class="p">,</span> <span class="n">oauth_version</span><span class="p">],</span>
518
- <span class="p">[</span><span class="ss">:oauth_signature</span><span class="p">,</span> <span class="n">escape</span><span class="p">(</span><span class="n">signature</span><span class="p">)]</span>
519
- <span class="p">]</span>
520
-
521
- <span class="n">headers</span> <span class="o">=</span> <span class="p">{</span>
522
- <span class="s1">'Authorization'</span> <span class="o">=&gt;</span> <span class="s2">"OAuth </span><span class="si">#{</span><span class="n">authorization_parts</span><span class="p">.</span><span class="nf">map</span> <span class="p">{</span> <span class="o">|</span><span class="n">k</span><span class="p">,</span> <span class="n">v</span><span class="o">|</span> <span class="s2">"</span><span class="si">#{</span><span class="n">k</span><span class="si">}</span><span class="s2">=</span><span class="se">\"</span><span class="si">#{</span><span class="n">v</span><span class="si">}</span><span class="se">\"</span><span class="s2">"</span> <span class="si">}</span><span class="s2">.join(',')}"</span>
523
- <span class="p">}</span>
524
-
525
- <span class="nb">puts</span> <span class="n">headers</span>
526
- </code></pre></div> </div>
527
-
528
- </div>
529
-
530
- <div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="s2">"Authorization"</span><span class="o">=&gt;</span><span class="s2">"OAuth realm=</span><span class="se">\"</span><span class="s2">9876543_SB1</span><span class="se">\"</span><span class="s2">,oauth_consumer_key=</span><span class="se">\"</span><span class="s2">CONSUMER_KEY_VALUE</span><span class="se">\"</span><span class="s2">,oauth_token=</span><span class="se">\"</span><span class="s2">TOKEN_ID_VALUE</span><span class="se">\"</span><span class="s2">,oauth_signature_method=</span><span class="se">\"</span><span class="s2">HMAC-SHA256</span><span class="se">\"</span><span class="s2">,oauth_timestamp=</span><span class="se">\"</span><span class="s2">1234567890</span><span class="se">\"</span><span class="s2">,oauth_nonce=</span><span class="se">\"</span><span class="s2">asdfasdf</span><span class="se">\"</span><span class="s2">,oauth_version=</span><span class="se">\"</span><span class="s2">1.0</span><span class="se">\"</span><span class="s2">,oauth_signature=</span><span class="se">\"</span><span class="s2">cId0B3hP0sFVQw%2FgjQ%2FP6YiOSx76u0WfyO8umOlq3gg%3D</span><span class="se">\"</span><span class="s2">"</span><span class="p">}</span>
531
- </code></pre></div> </div>
532
-
533
- </div>
534
-
535
- <h2 id="wrapping-up">Wrapping up</h2>
536
-
537
- <p>All that is left is to use this header in a request. You will need a new signature (and therefore new header) per-request. And that’s it!</p>
538
-
539
- <p>While not difficult in practice, it was by trial-and-error we were ultimately able to authenticate to NetSuite. Hopefully this post saves you some time!</p>
540
-
541
- <p>It is highly recommended that you write comprehensive unit tests for this code. We wrote some tests in RSpec. These test are a great resource for examples you can test against.</p>
542
-
543
- </div><!-- .post-content -->
544
- </div><!-- .inner-md -->
545
- </article><!-- .post -->
546
-
547
- <!-- Next/previous post navigation TBD -->
548
- <!--
549
- <div class="inner-md outer">
550
- <nav class="read-next">
551
- <h2 class="read-next-title line-left">Read Next</h2>
552
- <div class="nav-links">
553
- <article class="post">
554
- <div class="post-meta">
555
- <time class="published" datetime="">Previous post date</time>
556
- </div>
557
- <h3 class="post-title"><a href="#" rel="bookmark">Previous Post Title</a></h3>
558
- </article>
559
- <article class="post">
560
- <div class="post-meta">
561
- <time class="published" datetime="">Next post date</time>
562
- </div>
563
- <h3 class="post-title"><a href="#" rel="bookmark">Next Post Title</a></h3>
564
- </article>
565
- </div>
566
- </nav>
567
- </div>
568
- -->
569
-
570
- </main><!-- .site-content -->
571
- <footer id="colophon" class="site-footer outer">
572
- <div class="inner">
573
- <div class="site-footer-inside">
574
- <p class="site-info">
575
-
576
- <span class="copyright">&copy; Modern Treasury Inc. All rights reserved.</span>
577
- <a class="" href="https://www.moderntreasury.com" target="_blank" rel="noopener" >
578
-
579
- Maintained with ❤️ in San Francisco, CA by Modern Treasury
580
-
581
- </a>
582
- </p>
583
- <!-- .site-info -->
584
-
585
- <div class="social-links">
586
-
587
- <a class="" href="https://www.netlify.com" target="_blank" rel="noopener" >
588
-
589
- <img src="https://www.netlify.com/img/global/badges/netlify-dark.svg" alt="Deploys by Netlify" />
590
-
591
- </a>
592
- <a class="button button-icon" href="https://twitter.com/ModernTreasury" target="_blank" rel="noopener" >
593
-
594
- <span class="icon fab fa-twitter" aria-hidden="true"></span><span class="screen-reader-text">Twitter</span>
595
-
596
- </a>
597
- <a class="button button-icon" href="https://www.linkedin.com/company/modern-treasury" target="_blank" rel="noopener" >
598
-
599
- <span class="icon fab fa-linkedin" aria-hidden="true"></span><span class="screen-reader-text">LinkedIn</span>
600
-
601
- </a>
602
- <a class="button button-icon" href="https://github.com/LedgerSync/ledger_sync" target="_blank" rel="noopener" >
603
-
604
- <span class="icon fab fa-github" aria-hidden="true"></span><span class="screen-reader-text">GitHub</span>
605
-
606
- </a>
607
- </div>
608
- <!-- .social-links -->
609
-
610
- </div>
611
- <!-- .site-footer-inside -->
612
- </div>
613
- <!-- .inner -->
614
- </footer>
615
- <!-- .site-footer -->
616
- </div><!-- .site -->
617
-
618
- <!-- Scripts -->
619
- <script src="/assets/js/plugins.js"></script>
620
- <script src="/assets/js/prism.js" data-manual></script>
621
- <script src="/assets/js/main.js"></script>
622
- </body>
623
-
624
- </html>