ima-claude 2.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (182) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +463 -0
  3. package/dist/cli.js +1064 -0
  4. package/package.json +49 -0
  5. package/platforms/claude/adapter.ts +115 -0
  6. package/platforms/junie/adapter.ts +254 -0
  7. package/platforms/junie/agents-template.md +113 -0
  8. package/platforms/junie/hook-translations.md +84 -0
  9. package/platforms/shared/detector.ts +27 -0
  10. package/platforms/shared/installer.ts +202 -0
  11. package/platforms/shared/types.ts +78 -0
  12. package/plugins/ima-claude/.claude-plugin/plugin.json +25 -0
  13. package/plugins/ima-claude/agents/explorer.md +30 -0
  14. package/plugins/ima-claude/agents/implementer.md +30 -0
  15. package/plugins/ima-claude/agents/memory.md +42 -0
  16. package/plugins/ima-claude/agents/reviewer.md +53 -0
  17. package/plugins/ima-claude/agents/tester.md +33 -0
  18. package/plugins/ima-claude/agents/wp-developer.md +46 -0
  19. package/plugins/ima-claude/hooks/README.md +145 -0
  20. package/plugins/ima-claude/hooks/atlassian_prereqs.py +112 -0
  21. package/plugins/ima-claude/hooks/block_sed_edits.py +59 -0
  22. package/plugins/ima-claude/hooks/bootstrap.sh +90 -0
  23. package/plugins/ima-claude/hooks/bootstrap_utility_check.py +94 -0
  24. package/plugins/ima-claude/hooks/composer_autoload_check.py +70 -0
  25. package/plugins/ima-claude/hooks/docs_organization.py +104 -0
  26. package/plugins/ima-claude/hooks/enforce_rg_over_grep.py +56 -0
  27. package/plugins/ima-claude/hooks/fp_utility_check.py +90 -0
  28. package/plugins/ima-claude/hooks/hook_logger.py +69 -0
  29. package/plugins/ima-claude/hooks/hooks.json +239 -0
  30. package/plugins/ima-claude/hooks/jira_issue_fetch.py +79 -0
  31. package/plugins/ima-claude/hooks/jquery_in_wordpress.py +92 -0
  32. package/plugins/ima-claude/hooks/memory_bootstrap.py +79 -0
  33. package/plugins/ima-claude/hooks/memory_store_reminder.py +75 -0
  34. package/plugins/ima-claude/hooks/prompt_coach.py +125 -0
  35. package/plugins/ima-claude/hooks/prompt_coach_digest.md +48 -0
  36. package/plugins/ima-claude/hooks/prompt_coach_system.md +30 -0
  37. package/plugins/ima-claude/hooks/sequential_thinking_check.py +81 -0
  38. package/plugins/ima-claude/hooks/serena_over_grep.py +96 -0
  39. package/plugins/ima-claude/hooks/serena_over_read.py +66 -0
  40. package/plugins/ima-claude/hooks/serena_project_check.py +133 -0
  41. package/plugins/ima-claude/hooks/sql_injection_check.py +73 -0
  42. package/plugins/ima-claude/hooks/task_master_after_plan.py +31 -0
  43. package/plugins/ima-claude/hooks/task_master_before_impl.py +93 -0
  44. package/plugins/ima-claude/hooks/tavily_extract_advanced.py +48 -0
  45. package/plugins/ima-claude/hooks/vestige_before_external.py +86 -0
  46. package/plugins/ima-claude/hooks/webfetch_to_tavily.py +42 -0
  47. package/plugins/ima-claude/hooks/websearch_to_tavily.py +41 -0
  48. package/plugins/ima-claude/hooks/wp_security_check.py +150 -0
  49. package/plugins/ima-claude/personalities/README.md +45 -0
  50. package/plugins/ima-claude/personalities/enable-40k.md +69 -0
  51. package/plugins/ima-claude/personalities/enable-templars.md +69 -0
  52. package/plugins/ima-claude/skills/.research-summary.md +340 -0
  53. package/plugins/ima-claude/skills/architect/SKILL.md +304 -0
  54. package/plugins/ima-claude/skills/compound-bridge/SKILL.md +200 -0
  55. package/plugins/ima-claude/skills/discourse/SKILL.md +440 -0
  56. package/plugins/ima-claude/skills/discourse-admin/SKILL.md +192 -0
  57. package/plugins/ima-claude/skills/discourse-admin/references/api-endpoints.md +441 -0
  58. package/plugins/ima-claude/skills/discourse-admin/references/gotchas.md +107 -0
  59. package/plugins/ima-claude/skills/discourse-admin/references/staging-defaults.md +98 -0
  60. package/plugins/ima-claude/skills/discourse-admin/scripts/discourse-admin.py +319 -0
  61. package/plugins/ima-claude/skills/docs-organize/SKILL.md +254 -0
  62. package/plugins/ima-claude/skills/docs-organize/templates/active-README.md +50 -0
  63. package/plugins/ima-claude/skills/docs-organize/templates/archive-README.md +57 -0
  64. package/plugins/ima-claude/skills/docs-organize/templates/docs-README.md +43 -0
  65. package/plugins/ima-claude/skills/docs-organize/templates/phase-archive-README.md +83 -0
  66. package/plugins/ima-claude/skills/docs-organize/templates/section-README.md +48 -0
  67. package/plugins/ima-claude/skills/docs-organize/templates/transient-README.md +79 -0
  68. package/plugins/ima-claude/skills/docs-organize/templates/transient-gitignore +9 -0
  69. package/plugins/ima-claude/skills/ember-discourse/SKILL.md +496 -0
  70. package/plugins/ima-claude/skills/functional-programmer/SKILL.md +258 -0
  71. package/plugins/ima-claude/skills/ima-bootstrap/SKILL.md +278 -0
  72. package/plugins/ima-claude/skills/ima-bootstrap/references/bootstrap-patterns.md +356 -0
  73. package/plugins/ima-claude/skills/ima-bootstrap/references/ima-brand.md +273 -0
  74. package/plugins/ima-claude/skills/ima-bootstrap/references/theme-integration.md +212 -0
  75. package/plugins/ima-claude/skills/ima-brand/SKILL.md +108 -0
  76. package/plugins/ima-claude/skills/ima-brand/references/brand-identity.md +140 -0
  77. package/plugins/ima-claude/skills/ima-brand/references/digital-standards.md +180 -0
  78. package/plugins/ima-claude/skills/ima-brand/references/visual-system.md +173 -0
  79. package/plugins/ima-claude/skills/ima-forms-expert/SKILL.md +175 -0
  80. package/plugins/ima-claude/skills/ima-forms-expert/references/container-components.md +154 -0
  81. package/plugins/ima-claude/skills/ima-forms-expert/references/examples.md +328 -0
  82. package/plugins/ima-claude/skills/ima-forms-expert/references/field-components.md +298 -0
  83. package/plugins/ima-claude/skills/ima-forms-expert/references/form-factory.md +193 -0
  84. package/plugins/ima-claude/skills/ima-forms-expert/references/quick-reference.md +153 -0
  85. package/plugins/ima-claude/skills/ima-forms-expert/references/validation-engine.md +336 -0
  86. package/plugins/ima-claude/skills/jira-checkpoint/SKILL.md +178 -0
  87. package/plugins/ima-claude/skills/jquery/SKILL.md +413 -0
  88. package/plugins/ima-claude/skills/js-fp/SKILL.md +463 -0
  89. package/plugins/ima-claude/skills/js-fp/core-principles.md +487 -0
  90. package/plugins/ima-claude/skills/js-fp/examples/pure-functions.js +260 -0
  91. package/plugins/ima-claude/skills/js-fp/examples/tests/pure-functions.test.js +262 -0
  92. package/plugins/ima-claude/skills/js-fp/references/anti-patterns.md +120 -0
  93. package/plugins/ima-claude/skills/js-fp/references/performance-patterns.md +116 -0
  94. package/plugins/ima-claude/skills/js-fp/references/testing-patterns.md +134 -0
  95. package/plugins/ima-claude/skills/js-fp-api/SKILL.md +280 -0
  96. package/plugins/ima-claude/skills/js-fp-api/examples/crud-endpoint.js +258 -0
  97. package/plugins/ima-claude/skills/js-fp-api/references/middleware-patterns.md +134 -0
  98. package/plugins/ima-claude/skills/js-fp-api/references/security-sql.md +110 -0
  99. package/plugins/ima-claude/skills/js-fp-api/references/validation-patterns.md +165 -0
  100. package/plugins/ima-claude/skills/js-fp-react/SKILL.md +447 -0
  101. package/plugins/ima-claude/skills/js-fp-react/examples/ProductCard.tsx +65 -0
  102. package/plugins/ima-claude/skills/js-fp-react/references/hooks-advanced.md +136 -0
  103. package/plugins/ima-claude/skills/js-fp-react/references/performance-patterns.md +175 -0
  104. package/plugins/ima-claude/skills/js-fp-vue/SKILL.md +322 -0
  105. package/plugins/ima-claude/skills/js-fp-vue/references/complete-examples.md +397 -0
  106. package/plugins/ima-claude/skills/js-fp-vue/references/composables-advanced.md +282 -0
  107. package/plugins/ima-claude/skills/js-fp-vue/references/reactivity-patterns.md +348 -0
  108. package/plugins/ima-claude/skills/js-fp-vue/references/testing.md +314 -0
  109. package/plugins/ima-claude/skills/js-fp-wordpress/SKILL.md +301 -0
  110. package/plugins/ima-claude/skills/js-fp-wordpress/references/ajax-patterns.md +192 -0
  111. package/plugins/ima-claude/skills/js-fp-wordpress/references/event-patterns.md +136 -0
  112. package/plugins/ima-claude/skills/js-fp-wordpress/references/wp-integration.md +248 -0
  113. package/plugins/ima-claude/skills/livecanvas/SKILL.md +209 -0
  114. package/plugins/ima-claude/skills/livecanvas/references/livecanvas-features.md +311 -0
  115. package/plugins/ima-claude/skills/livecanvas/references/loops-and-logic.md +730 -0
  116. package/plugins/ima-claude/skills/livecanvas/references/picostrap.md +227 -0
  117. package/plugins/ima-claude/skills/mcp-atlassian/SKILL.md +339 -0
  118. package/plugins/ima-claude/skills/mcp-context7/SKILL.md +109 -0
  119. package/plugins/ima-claude/skills/mcp-memory/SKILL.md +182 -0
  120. package/plugins/ima-claude/skills/mcp-qdrant/SKILL.md +233 -0
  121. package/plugins/ima-claude/skills/mcp-sequential/SKILL.md +149 -0
  122. package/plugins/ima-claude/skills/mcp-serena/SKILL.md +174 -0
  123. package/plugins/ima-claude/skills/mcp-tavily/SKILL.md +118 -0
  124. package/plugins/ima-claude/skills/mcp-vestige/SKILL.md +259 -0
  125. package/plugins/ima-claude/skills/php-authnet/SKILL.md +275 -0
  126. package/plugins/ima-claude/skills/php-authnet/references/api-reference.md +624 -0
  127. package/plugins/ima-claude/skills/php-authnet/references/sandbox-testing.md +424 -0
  128. package/plugins/ima-claude/skills/php-fp/SKILL.md +333 -0
  129. package/plugins/ima-claude/skills/php-fp/examples/pure-functions.php +403 -0
  130. package/plugins/ima-claude/skills/php-fp/examples/tests/PureFunctionsTest.php +515 -0
  131. package/plugins/ima-claude/skills/php-fp/references/core-principles.md +277 -0
  132. package/plugins/ima-claude/skills/php-fp/references/testing-patterns.md +374 -0
  133. package/plugins/ima-claude/skills/php-fp-wordpress/SKILL.md +216 -0
  134. package/plugins/ima-claude/skills/php-fp-wordpress/references/fp-patterns.md +275 -0
  135. package/plugins/ima-claude/skills/php-fp-wordpress/references/plugin-architecture.md +295 -0
  136. package/plugins/ima-claude/skills/php-fp-wordpress/references/security-examples.md +203 -0
  137. package/plugins/ima-claude/skills/php-fp-wordpress/references/testing-strategy.md +259 -0
  138. package/plugins/ima-claude/skills/phpunit-wp/SKILL.md +716 -0
  139. package/plugins/ima-claude/skills/playwright/SKILL.md +434 -0
  140. package/plugins/ima-claude/skills/playwright/references/accessibility-testing.md +153 -0
  141. package/plugins/ima-claude/skills/playwright/references/ci-cd.md +268 -0
  142. package/plugins/ima-claude/skills/playwright/references/network-mocking.md +270 -0
  143. package/plugins/ima-claude/skills/playwright/references/visual-regression.md +215 -0
  144. package/plugins/ima-claude/skills/py-fp/SKILL.md +663 -0
  145. package/plugins/ima-claude/skills/py-fp/examples/pure-functions.py +185 -0
  146. package/plugins/ima-claude/skills/py-fp/examples/tests/test_pure_functions.py +244 -0
  147. package/plugins/ima-claude/skills/py-fp/references/core-principles.md +381 -0
  148. package/plugins/ima-claude/skills/py-fp/references/testing-patterns.md +283 -0
  149. package/plugins/ima-claude/skills/quasar-fp/SKILL.md +327 -0
  150. package/plugins/ima-claude/skills/quasar-fp/metadata.json +85 -0
  151. package/plugins/ima-claude/skills/quasar-fp/references/component-patterns.md +257 -0
  152. package/plugins/ima-claude/skills/quasar-fp/references/theme-integration.md +233 -0
  153. package/plugins/ima-claude/skills/quasar-fp/references/utility-classes.md +237 -0
  154. package/plugins/ima-claude/skills/quickstart/SKILL.md +129 -0
  155. package/plugins/ima-claude/skills/rails/SKILL.md +359 -0
  156. package/plugins/ima-claude/skills/resume-session/SKILL.md +68 -0
  157. package/plugins/ima-claude/skills/rg/SKILL.md +205 -0
  158. package/plugins/ima-claude/skills/ruby-fp/SKILL.md +336 -0
  159. package/plugins/ima-claude/skills/save-session/SKILL.md +81 -0
  160. package/plugins/ima-claude/skills/scorecard/SKILL.md +96 -0
  161. package/plugins/ima-claude/skills/skill-analyzer/SKILL.md +127 -0
  162. package/plugins/ima-claude/skills/skill-analyzer/references/advanced-checklist.md +44 -0
  163. package/plugins/ima-claude/skills/skill-analyzer/references/core-checklist.md +60 -0
  164. package/plugins/ima-claude/skills/skill-analyzer/scripts/analyze_skill.py +418 -0
  165. package/plugins/ima-claude/skills/skill-creator/LICENSE.txt +202 -0
  166. package/plugins/ima-claude/skills/skill-creator/SKILL.md +343 -0
  167. package/plugins/ima-claude/skills/skill-creator/references/output-patterns.md +82 -0
  168. package/plugins/ima-claude/skills/skill-creator/references/workflows.md +28 -0
  169. package/plugins/ima-claude/skills/skill-creator/scripts/init_skill.py +303 -0
  170. package/plugins/ima-claude/skills/skill-creator/scripts/package_skill.py +110 -0
  171. package/plugins/ima-claude/skills/skill-creator/scripts/quick_validate.py +103 -0
  172. package/plugins/ima-claude/skills/task-master/SKILL.md +51 -0
  173. package/plugins/ima-claude/skills/task-planner/SKILL.md +228 -0
  174. package/plugins/ima-claude/skills/task-runner/SKILL.md +192 -0
  175. package/plugins/ima-claude/skills/unit-testing/SKILL.md +198 -0
  176. package/plugins/ima-claude/skills/unit-testing/references/mock-patterns.md +181 -0
  177. package/plugins/ima-claude/skills/unit-testing/references/tdd-workflow.md +177 -0
  178. package/plugins/ima-claude/skills/unit-testing/references/test-strategy.md +126 -0
  179. package/plugins/ima-claude/skills/wp-local/SKILL.md +246 -0
  180. package/plugins/ima-claude/skills/wp-local/references/configuration.md +198 -0
  181. package/plugins/ima-claude/skills/wp-local/references/wp-cli-reference.md +406 -0
  182. package/plugins/ima-claude/skills/wp-local/scripts/wp-local.sh +61 -0
@@ -0,0 +1,624 @@
1
+ # Authorize.Net PHP SDK — API Reference
2
+
3
+ Complete SDK class and method reference for `authorizenet/authorizenet` ^2.0.
4
+
5
+ ## Table of Contents
6
+
7
+ - [SDK Namespaces](#sdk-namespaces)
8
+ - [Payment Transactions](#payment-transactions)
9
+ - [Customer Profiles (CIM)](#customer-profiles-cim)
10
+ - [Recurring Billing (ARB)](#recurring-billing-arb)
11
+ - [Accept.js Token Handling](#acceptjs-token-handling)
12
+ - [Webhooks](#webhooks)
13
+ - [Transaction Reporting](#transaction-reporting)
14
+ - [Response Codes](#response-codes)
15
+ - [Field Constraints](#field-constraints)
16
+
17
+ ---
18
+
19
+ ## SDK Namespaces
20
+
21
+ ```php
22
+ use net\authorize\api\contract\v1 as AnetAPI; // Data contracts
23
+ use net\authorize\api\controller as AnetController; // Request controllers
24
+ use net\authorize\api\constants\ANetEnvironment; // SANDBOX / PRODUCTION
25
+ ```
26
+
27
+ ## Payment Transactions
28
+
29
+ ### CreateTransactionRequest
30
+
31
+ The universal transaction endpoint. Behavior varies by `transactionType`.
32
+
33
+ **Controller**: `AnetController\CreateTransactionController`
34
+
35
+ ```php
36
+ $request = new AnetAPI\CreateTransactionRequest();
37
+ $request->setMerchantAuthentication($merchant_auth);
38
+ $request->setTransactionRequest($transaction_request);
39
+
40
+ $controller = new AnetController\CreateTransactionController($request);
41
+ $response = $controller->executeWithApiResponse($api_url);
42
+ ```
43
+
44
+ ### TransactionRequestType — Key Setters
45
+
46
+ | Method | Type | Required | Notes |
47
+ |--------|------|----------|-------|
48
+ | `setTransactionType()` | string | Yes | See transaction types table |
49
+ | `setAmount()` | float | Yes | Decimal (e.g., 29.99) |
50
+ | `setPayment()` | PaymentType | Conditional | Required for new charges; not for profile charges |
51
+ | `setProfile()` | CustomerProfilePaymentType | Conditional | For charging stored profiles |
52
+ | `setRefTransId()` | string | Conditional | Required for refunds, voids, prior auth capture |
53
+ | `setBillTo()` | CustomerAddressType | No | Billing address |
54
+ | `setShipTo()` | CustomerAddressType | No | Shipping address |
55
+ | `setOrder()` | OrderType | No | Order description, invoice number |
56
+ | `setCustomer()` | CustomerDataType | No | Customer email, ID |
57
+ | `setLineItems()` | LineItemType[] | No | Array of line items |
58
+ | `setTax()` | ExtendedAmountType | No | Tax info |
59
+ | `setPoNumber()` | string | No | Purchase order number |
60
+
61
+ ### Transaction Types
62
+
63
+ | Value | Description |
64
+ |-------|-------------|
65
+ | `authCaptureTransaction` | Authorize and capture in one step |
66
+ | `authOnlyTransaction` | Authorize only (capture later) |
67
+ | `priorAuthCaptureTransaction` | Capture a prior auth (requires `refTransId`) |
68
+ | `refundTransaction` | Refund settled transaction (requires `refTransId` + last 4 of card) |
69
+ | `voidTransaction` | Void unsettled transaction (requires `refTransId`) |
70
+
71
+ ### Refund Requirements
72
+
73
+ Refunds require the original transaction ID AND payment info (last 4 digits):
74
+
75
+ ```php
76
+ $credit_card = new AnetAPI\CreditCardType();
77
+ $credit_card->setCardNumber('XXXX1234'); // last 4 digits
78
+ $credit_card->setExpirationDate('XXXX'); // literal 'XXXX'
79
+
80
+ $payment = new AnetAPI\PaymentType();
81
+ $payment->setCreditCard($credit_card);
82
+
83
+ $tx = new AnetAPI\TransactionRequestType();
84
+ $tx->setTransactionType('refundTransaction');
85
+ $tx->setAmount($refund_amount);
86
+ $tx->setRefTransId($original_transaction_id);
87
+ $tx->setPayment($payment);
88
+ ```
89
+
90
+ Refund constraints:
91
+ - Transaction must be settled (usually within 24h of capture)
92
+ - Refund amount ≤ original captured amount
93
+ - Partial refunds allowed (multiple refunds up to original amount)
94
+ - Default refund window: 180 days from settlement
95
+
96
+ ### Void Requirements
97
+
98
+ Voids only work on **unsettled** transactions:
99
+
100
+ ```php
101
+ $tx = new AnetAPI\TransactionRequestType();
102
+ $tx->setTransactionType('voidTransaction');
103
+ $tx->setRefTransId($transaction_id);
104
+ ```
105
+
106
+ ### Response Parsing
107
+
108
+ ```php
109
+ $response = $controller->executeWithApiResponse($api_url);
110
+
111
+ // Top-level result
112
+ $result_code = $response->getMessages()->getResultCode(); // 'Ok' or 'Error'
113
+ $messages = $response->getMessages()->getMessage(); // AnetAPI\MessagesType\MessageAType[]
114
+ $messages[0]->getCode(); // e.g., 'I00001'
115
+ $messages[0]->getText(); // e.g., 'Successful.'
116
+
117
+ // Transaction response (may be null)
118
+ $tresponse = $response->getTransactionResponse();
119
+ $tresponse->getTransId(); // Transaction ID
120
+ $tresponse->getAuthCode(); // Authorization code
121
+ $tresponse->getResponseCode(); // '1'=Approved, '2'=Declined, '3'=Error, '4'=Held
122
+ $tresponse->getAccountNumber(); // Masked card (e.g., 'XXXX1234')
123
+ $tresponse->getAccountType(); // 'Visa', 'Mastercard', etc.
124
+
125
+ // Transaction-level messages (success details)
126
+ $tresponse->getMessages(); // array of message objects (null if failed)
127
+ $tresponse->getMessages()[0]->getCode();
128
+ $tresponse->getMessages()[0]->getDescription();
129
+
130
+ // Transaction-level errors (decline/error details)
131
+ $tresponse->getErrors(); // array of error objects (null if success)
132
+ $tresponse->getErrors()[0]->getErrorCode();
133
+ $tresponse->getErrors()[0]->getErrorText();
134
+ ```
135
+
136
+ ### Response Code Values
137
+
138
+ | Code | Meaning |
139
+ |------|---------|
140
+ | `1` | Approved |
141
+ | `2` | Declined |
142
+ | `3` | Error |
143
+ | `4` | Held for review |
144
+
145
+ ---
146
+
147
+ ## Customer Profiles (CIM)
148
+
149
+ CIM stores customer payment data securely on Authorize.Net's servers.
150
+
151
+ ### Hierarchy
152
+
153
+ ```
154
+ CustomerProfile
155
+ ├── description, email, merchantCustomerId
156
+ ├── PaymentProfile[] (credit cards, bank accounts)
157
+ │ ├── billTo (CustomerAddressType)
158
+ │ └── payment (PaymentType)
159
+ └── ShippingAddress[] (CustomerAddressType)
160
+ ```
161
+
162
+ ### Create Customer Profile
163
+
164
+ **Controller**: `AnetController\CreateCustomerProfileController`
165
+
166
+ ```php
167
+ $payment_profile = new AnetAPI\CustomerPaymentProfileType();
168
+ $payment_profile->setCustomerType('individual'); // or 'business'
169
+ $payment_profile->setBillTo($bill_to);
170
+ $payment_profile->setPayment($payment_type);
171
+
172
+ $customer_profile = new AnetAPI\CustomerProfileType();
173
+ $customer_profile->setDescription('Profile description');
174
+ $customer_profile->setEmail($email);
175
+ $customer_profile->setPaymentProfiles([$payment_profile]);
176
+
177
+ $request = new AnetAPI\CreateCustomerProfileRequest();
178
+ $request->setMerchantAuthentication($merchant_auth);
179
+ $request->setProfile($customer_profile);
180
+ $request->setValidationMode('liveMode'); // or 'testMode' for sandbox
181
+
182
+ $controller = new AnetController\CreateCustomerProfileController($request);
183
+ $response = $controller->executeWithApiResponse($api_url);
184
+
185
+ $customer_profile_id = $response->getCustomerProfileId();
186
+ $payment_profile_ids = $response->getCustomerPaymentProfileIdList(); // array
187
+ ```
188
+
189
+ ### Validation Modes
190
+
191
+ | Mode | Behavior |
192
+ |------|----------|
193
+ | `liveMode` | Runs $0.00 or $0.01 auth to validate card (production) |
194
+ | `testMode` | Validates format only, no auth (sandbox-safe) |
195
+ | `none` | No validation |
196
+
197
+ **Sandbox gotcha**: `liveMode` validation may fail with Accept.js opaque data in sandbox. Use `testMode` for sandbox environments.
198
+
199
+ ### Create Customer Profile from Transaction
200
+
201
+ More reliable than direct creation, especially in sandbox:
202
+
203
+ ```php
204
+ $request = new AnetAPI\CreateCustomerProfileFromTransactionRequest();
205
+ $request->setMerchantAuthentication($merchant_auth);
206
+ $request->setTransId($transaction_id);
207
+
208
+ // Optional: attach email
209
+ $customer = new AnetAPI\CustomerProfileBaseType();
210
+ $customer->setEmail($email);
211
+ $request->setCustomer($customer);
212
+
213
+ $controller = new AnetController\CreateCustomerProfileFromTransactionController($request);
214
+ $response = $controller->executeWithApiResponse($api_url);
215
+ ```
216
+
217
+ ### Add Payment Profile to Existing Customer
218
+
219
+ ```php
220
+ $request = new AnetAPI\CreateCustomerPaymentProfileRequest();
221
+ $request->setMerchantAuthentication($merchant_auth);
222
+ $request->setCustomerProfileId($customer_profile_id);
223
+ $request->setPaymentProfile($payment_profile);
224
+ $request->setValidationMode($validation_mode);
225
+
226
+ $controller = new AnetController\CreateCustomerPaymentProfileController($request);
227
+ $response = $controller->executeWithApiResponse($api_url);
228
+
229
+ $new_payment_profile_id = $response->getCustomerPaymentProfileId();
230
+ ```
231
+
232
+ ### Get Customer Profile
233
+
234
+ ```php
235
+ $request = new AnetAPI\GetCustomerProfileRequest();
236
+ $request->setMerchantAuthentication($merchant_auth);
237
+ $request->setCustomerProfileId($customer_profile_id);
238
+
239
+ $controller = new AnetController\GetCustomerProfileController($request);
240
+ $response = $controller->executeWithApiResponse($api_url);
241
+
242
+ $profile = $response->getProfile();
243
+ $payment_profiles = $profile->getPaymentProfiles(); // array
244
+ ```
245
+
246
+ ### Update Customer Payment Profile
247
+
248
+ ```php
249
+ $request = new AnetAPI\UpdateCustomerPaymentProfileRequest();
250
+ $request->setMerchantAuthentication($merchant_auth);
251
+ $request->setCustomerProfileId($customer_profile_id);
252
+ $request->setPaymentProfile($updated_payment_profile);
253
+
254
+ $controller = new AnetController\UpdateCustomerPaymentProfileController($request);
255
+ ```
256
+
257
+ ### Delete Customer Profile
258
+
259
+ Deletes the profile AND all associated payment profiles and shipping addresses:
260
+
261
+ ```php
262
+ $request = new AnetAPI\DeleteCustomerProfileRequest();
263
+ $request->setMerchantAuthentication($merchant_auth);
264
+ $request->setCustomerProfileId($customer_profile_id);
265
+
266
+ $controller = new AnetController\DeleteCustomerProfileController($request);
267
+ $response = $controller->executeWithApiResponse($api_url);
268
+ ```
269
+
270
+ ### Delete Payment Profile
271
+
272
+ ```php
273
+ $request = new AnetAPI\DeleteCustomerPaymentProfileRequest();
274
+ $request->setMerchantAuthentication($merchant_auth);
275
+ $request->setCustomerProfileId($customer_profile_id);
276
+ $request->setCustomerPaymentProfileId($payment_profile_id);
277
+
278
+ $controller = new AnetController\DeleteCustomerPaymentProfileController($request);
279
+ ```
280
+
281
+ ### Charge Stored Profile
282
+
283
+ ```php
284
+ $profile_to_charge = new AnetAPI\CustomerProfilePaymentType();
285
+ $profile_to_charge->setCustomerProfileId($customer_profile_id);
286
+
287
+ $payment_profile = new AnetAPI\PaymentProfileType();
288
+ $payment_profile->setPaymentProfileId($payment_profile_id);
289
+ $profile_to_charge->setPaymentProfile($payment_profile);
290
+
291
+ $tx = new AnetAPI\TransactionRequestType();
292
+ $tx->setTransactionType('authCaptureTransaction');
293
+ $tx->setAmount($amount);
294
+ $tx->setProfile($profile_to_charge);
295
+ ```
296
+
297
+ ---
298
+
299
+ ## Recurring Billing (ARB)
300
+
301
+ ### Create Subscription
302
+
303
+ **Controller**: `AnetController\ARBCreateSubscriptionController`
304
+
305
+ ```php
306
+ $interval = new AnetAPI\PaymentScheduleType\IntervalAType();
307
+ $interval->setLength(1); // billing interval length
308
+ $interval->setUnit('months'); // 'months' or 'days'
309
+
310
+ $schedule = new AnetAPI\PaymentScheduleType();
311
+ $schedule->setInterval($interval);
312
+ $schedule->setStartDate(new \DateTime($start_date)); // Y-m-d
313
+ $schedule->setTotalOccurrences(9999); // 9999 = unlimited
314
+
315
+ // Optional trial period
316
+ $schedule->setTrialOccurrences(1);
317
+
318
+ // Using CIM profile (recommended)
319
+ $profile = new AnetAPI\CustomerProfileIdType();
320
+ $profile->setCustomerProfileId($customer_profile_id);
321
+ $profile->setCustomerPaymentProfileId($payment_profile_id);
322
+
323
+ $subscription = new AnetAPI\ARBSubscriptionType();
324
+ $subscription->setName('Monthly Membership'); // max 50 chars
325
+ $subscription->setPaymentSchedule($schedule);
326
+ $subscription->setAmount($amount);
327
+ $subscription->setProfile($profile);
328
+ $subscription->setTrialAmount(0.00); // if trial
329
+
330
+ $request = new AnetAPI\ARBCreateSubscriptionRequest();
331
+ $request->setMerchantAuthentication($merchant_auth);
332
+ $request->setSubscription($subscription);
333
+
334
+ $controller = new AnetController\ARBCreateSubscriptionController($request);
335
+ $response = $controller->executeWithApiResponse($api_url);
336
+
337
+ $subscription_id = $response->getSubscriptionId();
338
+ ```
339
+
340
+ ### Interval Constraints
341
+
342
+ | Unit | Min Length | Max Length |
343
+ |------|-----------|-----------|
344
+ | `days` | 7 | 365 |
345
+ | `months` | 1 | 12 |
346
+
347
+ ### Cancel Subscription
348
+
349
+ ```php
350
+ $request = new AnetAPI\ARBCancelSubscriptionRequest();
351
+ $request->setMerchantAuthentication($merchant_auth);
352
+ $request->setSubscriptionId($subscription_id);
353
+
354
+ $controller = new AnetController\ARBCancelSubscriptionController($request);
355
+ $response = $controller->executeWithApiResponse($api_url);
356
+ ```
357
+
358
+ ### Get Subscription Status
359
+
360
+ ```php
361
+ $request = new AnetAPI\ARBGetSubscriptionStatusRequest();
362
+ $request->setMerchantAuthentication($merchant_auth);
363
+ $request->setSubscriptionId($subscription_id);
364
+
365
+ $controller = new AnetController\ARBGetSubscriptionStatusController($request);
366
+ $response = $controller->executeWithApiResponse($api_url);
367
+
368
+ $status = $response->getStatus(); // active, expired, suspended, canceled, terminated
369
+ ```
370
+
371
+ ### Subscription Statuses
372
+
373
+ | Status | Meaning |
374
+ |--------|---------|
375
+ | `active` | Billing normally |
376
+ | `expired` | All occurrences completed |
377
+ | `suspended` | Payment failed (auto-retry pending) |
378
+ | `canceled` | Merchant canceled via API or UI |
379
+ | `terminated` | System terminated (too many failures) |
380
+
381
+ ### Update Subscription
382
+
383
+ Once created, you CANNOT change: start date, interval length/unit, trial period. Create a new subscription for those changes.
384
+
385
+ You CAN update: amount, payment profile, name, billing address.
386
+
387
+ ```php
388
+ $subscription = new AnetAPI\ARBSubscriptionType();
389
+ $subscription->setAmount($new_amount);
390
+
391
+ $request = new AnetAPI\ARBUpdateSubscriptionRequest();
392
+ $request->setMerchantAuthentication($merchant_auth);
393
+ $request->setSubscriptionId($subscription_id);
394
+ $request->setSubscription($subscription);
395
+
396
+ $controller = new AnetController\ARBUpdateSubscriptionController($request);
397
+ ```
398
+
399
+ ---
400
+
401
+ ## Accept.js Token Handling
402
+
403
+ Accept.js sends card data directly to Authorize.Net from the browser, returning a one-time payment nonce.
404
+
405
+ ### Payment Nonce → OpaqueDataType
406
+
407
+ ```php
408
+ $opaque_data = new AnetAPI\OpaqueDataType();
409
+ $opaque_data->setDataDescriptor('COMMON.ACCEPT.INAPP.PAYMENT');
410
+ $opaque_data->setDataValue($nonce_from_acceptjs);
411
+
412
+ $payment = new AnetAPI\PaymentType();
413
+ $payment->setOpaqueData($opaque_data);
414
+ ```
415
+
416
+ ### Token Lifecycle
417
+
418
+ - Valid for **15 minutes** after creation
419
+ - Single-use — consumed on first API call
420
+ - Contains no readable card data (opaque)
421
+
422
+ ### Accept.js vs Accept Hosted vs Accept.UI
423
+
424
+ | Method | PCI Level | Control | Description |
425
+ |--------|-----------|---------|-------------|
426
+ | Accept.js (custom form) | SAQ A-EP | Full | Your form, JS tokenizes before submit |
427
+ | Accept.js (hosted form) | SAQ A | Medium | Authorize.Net renders fields in modal |
428
+ | Accept Hosted | SAQ A | Low | Full redirect/iframe to Authorize.Net page |
429
+
430
+ ---
431
+
432
+ ## Webhooks
433
+
434
+ ### Event Types
435
+
436
+ **Payment events** (triggered by transactions):
437
+
438
+ | Event | Description |
439
+ |-------|-------------|
440
+ | `net.authorize.payment.authcapture.created` | Auth+capture completed |
441
+ | `net.authorize.payment.authorization.created` | Auth-only completed |
442
+ | `net.authorize.payment.capture.created` | Prior auth captured |
443
+ | `net.authorize.payment.refund.created` | Refund processed |
444
+ | `net.authorize.payment.void.created` | Transaction voided |
445
+ | `net.authorize.payment.priorAuthCapture.created` | Prior auth captured |
446
+
447
+ **Subscription events**:
448
+
449
+ | Event | Description |
450
+ |-------|-------------|
451
+ | `net.authorize.customer.subscription.created` | Subscription created |
452
+ | `net.authorize.customer.subscription.updated` | Subscription modified |
453
+ | `net.authorize.customer.subscription.suspended` | Payment failed |
454
+ | `net.authorize.customer.subscription.terminated` | System terminated |
455
+ | `net.authorize.customer.subscription.cancelled` | Merchant cancelled |
456
+ | `net.authorize.customer.subscription.expiring` | Approaching end date |
457
+
458
+ **Customer profile events**:
459
+
460
+ | Event | Description |
461
+ |-------|-------------|
462
+ | `net.authorize.customer.created` | Customer profile created |
463
+ | `net.authorize.customer.updated` | Customer profile updated |
464
+ | `net.authorize.customer.deleted` | Customer profile deleted |
465
+ | `net.authorize.customer.paymentProfile.created` | Payment profile added |
466
+ | `net.authorize.customer.paymentProfile.updated` | Payment profile updated |
467
+ | `net.authorize.customer.paymentProfile.deleted` | Payment profile deleted |
468
+
469
+ **Fraud events**:
470
+
471
+ | Event | Description |
472
+ |-------|-------------|
473
+ | `net.authorize.payment.fraud.approved` | Held transaction approved |
474
+ | `net.authorize.payment.fraud.declined` | Held transaction declined |
475
+ | `net.authorize.payment.fraud.held` | Transaction held for review |
476
+
477
+ ### Subscription Billing: Which Event Fires?
478
+
479
+ When a subscription charges the next billing cycle, it fires a **payment event** (`net.authorize.payment.authcapture.created`), NOT a subscription event. Subscription events only fire for lifecycle changes (create, cancel, suspend, terminate).
480
+
481
+ ### HMAC-SHA512 Signature Validation
482
+
483
+ Authorize.Net signs webhook payloads with the Signature Key using HMAC-SHA512. The signature is in the `X-ANET-Signature` header as `sha512=<HEXDIGEST>`.
484
+
485
+ ```php
486
+ function validate_webhook_signature(
487
+ string $raw_body,
488
+ ?string $signature_header,
489
+ string $signature_key
490
+ ): bool {
491
+ if (empty($raw_body) || empty($signature_header) || empty($signature_key)) {
492
+ return false;
493
+ }
494
+
495
+ $prefix = 'sha512=';
496
+ if (stripos($signature_header, $prefix) !== 0) {
497
+ return false;
498
+ }
499
+
500
+ $received = strtoupper(substr($signature_header, strlen($prefix)));
501
+ $computed = strtoupper(hash_hmac('sha512', $raw_body, $signature_key));
502
+
503
+ return hash_equals($computed, $received);
504
+ }
505
+ ```
506
+
507
+ ### Webhook Payload Structure
508
+
509
+ ```json
510
+ {
511
+ "notificationId": "unique-notification-id",
512
+ "eventType": "net.authorize.payment.authcapture.created",
513
+ "eventDate": "2025-01-15T12:00:00Z",
514
+ "webhookId": "webhook-config-id",
515
+ "payload": {
516
+ "responseCode": 1,
517
+ "authCode": "ABC123",
518
+ "avsResponse": "Y",
519
+ "authAmount": 29.99,
520
+ "entityName": "transaction",
521
+ "id": "123456789"
522
+ }
523
+ }
524
+ ```
525
+
526
+ ### Idempotency
527
+
528
+ Authorize.Net may deliver webhooks multiple times. Use `notificationId` for deduplication:
529
+
530
+ ```php
531
+ $idempotency_key = 'ima_wh_' . md5($notification_id);
532
+ if (get_transient($idempotency_key)) {
533
+ return; // already processed
534
+ }
535
+ set_transient($idempotency_key, true, 3 * DAY_IN_SECONDS);
536
+ ```
537
+
538
+ ---
539
+
540
+ ## Transaction Reporting
541
+
542
+ ### Get Transaction Details
543
+
544
+ ```php
545
+ $request = new AnetAPI\GetTransactionDetailsRequest();
546
+ $request->setMerchantAuthentication($merchant_auth);
547
+ $request->setTransId($transaction_id);
548
+
549
+ $controller = new AnetController\GetTransactionDetailsController($request);
550
+ $response = $controller->executeWithApiResponse($api_url);
551
+
552
+ $tx = $response->getTransaction();
553
+ $tx->getTransId();
554
+ $tx->getTransactionStatus(); // settledSuccessfully, authorizedPendingCapture, etc.
555
+ $tx->getSettleAmount();
556
+ $tx->getSubmitTimeUTC();
557
+ ```
558
+
559
+ ### Get Merchant Details (Connection Test)
560
+
561
+ ```php
562
+ $request = new AnetAPI\GetMerchantDetailsRequest();
563
+ $request->setMerchantAuthentication($merchant_auth);
564
+
565
+ $controller = new AnetController\GetMerchantDetailsController($request);
566
+ $response = $controller->executeWithApiResponse($api_url);
567
+ // result_code 'Ok' = credentials valid
568
+ ```
569
+
570
+ ---
571
+
572
+ ## Response Codes
573
+
574
+ ### API-Level Result Codes
575
+
576
+ | Result | Meaning |
577
+ |--------|---------|
578
+ | `Ok` | Request processed (check transaction-level for actual result) |
579
+ | `Error` | API-level failure (auth, format, etc.) |
580
+
581
+ ### Common Error Codes
582
+
583
+ | Code | Description | Recovery |
584
+ |------|-------------|----------|
585
+ | `E00001` | Internal error | Retry after delay |
586
+ | `E00003` | Invalid credentials | Verify api_login_id and transaction_key |
587
+ | `E00007` | Permission denied | Check account permissions |
588
+ | `E00012` | Duplicate subscription | Check existing subscriptions |
589
+ | `E00027` | Transaction declined | User should try different payment method |
590
+ | `E00039` | Duplicate record | Extract existing ID from error text with regex `/ID\s+(\d+)/` |
591
+ | `E00040` | Record not found | Profile was deleted or ID is wrong |
592
+ | `E00042` | Max payment profiles reached | Delete an old profile first (max 10 per customer) |
593
+ | `E00043` | Max shipping addresses reached | Delete an old address first |
594
+
595
+ ### Transaction Response Codes
596
+
597
+ | Code | Meaning | Action |
598
+ |------|---------|--------|
599
+ | `1` | Approved | Process success |
600
+ | `2` | Declined | Show decline message to user |
601
+ | `3` | Error | Log and show generic error |
602
+ | `4` | Held for review | Wait for webhook notification |
603
+
604
+ ---
605
+
606
+ ## Field Constraints
607
+
608
+ | Field | Max Length | Notes |
609
+ |-------|-----------|-------|
610
+ | Subscription name | 50 chars | Truncate, don't reject |
611
+ | Order description | 255 chars | Truncate, don't reject |
612
+ | Invoice number | 20 chars | Alphanumeric |
613
+ | First/Last name | 50 chars each | |
614
+ | Company | 50 chars | |
615
+ | Address | 60 chars | |
616
+ | City | 40 chars | |
617
+ | State | 40 chars | |
618
+ | Zip | 20 chars | |
619
+ | Country | 60 chars | |
620
+ | Phone | 25 chars | |
621
+ | Email | 255 chars | |
622
+ | Customer ID | 20 chars | merchantCustomerId |
623
+ | Payment profiles per customer | 10 max | Error E00042 if exceeded |
624
+ | Shipping addresses per customer | 100 max | |