medusa-payment-kadima 0.1.0 → 0.1.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.
- package/.medusa/server/src/{chunk-MKSGS2DZ.js → chunk-KVJTOLRY.js} +5 -1
- package/.medusa/server/src/{chunk-R62JQB26.js → chunk-UO5EBYD2.js} +5 -1
- package/.medusa/server/src/index.d.ts +4 -1
- package/.medusa/server/src/index.js +3 -3
- package/.medusa/server/src/providers/kadima-ach.js +2 -2
- package/.medusa/server/src/providers/kadima-card.js +2 -2
- package/README.md +20 -2
- package/package.json +7 -5
- package/src/index.ts +0 -43
- package/src/lib/errors.ts +0 -46
- package/src/lib/kadima-ach-client.ts +0 -166
- package/src/lib/kadima-card-client.ts +0 -259
- package/src/lib/kadima-vault-client.ts +0 -163
- package/src/lib/webhook.test.ts +0 -56
- package/src/lib/webhook.ts +0 -41
- package/src/providers/kadima-ach.ts +0 -178
- package/src/providers/kadima-card.ts +0 -270
- package/src/storefront/hosted-fields-example.md +0 -82
- package/src/types.ts +0 -61
- package/.medusa/server/src/{chunk-A4QO3PSZ.js → chunk-RPREKUY6.js} +11 -11
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
CARD_HOSTS,
|
|
3
3
|
DASHBOARD_HOSTS,
|
|
4
4
|
verifySignature
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-RPREKUY6.js";
|
|
6
6
|
|
|
7
7
|
// src/providers/kadima-card.ts
|
|
8
8
|
import { AbstractPaymentProvider, BigNumber } from "@medusajs/framework/utils";
|
|
@@ -284,6 +284,10 @@ var KadimaCardProviderService = class extends AbstractPaymentProvider {
|
|
|
284
284
|
this.options_ = options;
|
|
285
285
|
this.client = new KadimaCardClient(options);
|
|
286
286
|
this.vault = new KadimaVaultClient(options);
|
|
287
|
+
const sb = !!options.sandbox;
|
|
288
|
+
console.info(
|
|
289
|
+
`[kadima-card] init \u2014 sandbox=${sb} \xB7 gateway=${sb ? CARD_HOSTS.sandbox : CARD_HOSTS.prod} \xB7 dashboard=${sb ? DASHBOARD_HOSTS.sandbox : DASHBOARD_HOSTS.prod} \xB7 terminal=${options.terminalId ?? "(unset)"} \xB7 token=${options.apiToken ? "set" : "MISSING"}`
|
|
290
|
+
);
|
|
287
291
|
}
|
|
288
292
|
/**
|
|
289
293
|
* No money moves. Mint a Hosted Fields token so the storefront can collect the
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DASHBOARD_HOSTS,
|
|
3
3
|
verifySignature
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-RPREKUY6.js";
|
|
5
5
|
|
|
6
6
|
// src/providers/kadima-ach.ts
|
|
7
7
|
import { AbstractPaymentProvider } from "@medusajs/framework/utils";
|
|
@@ -90,6 +90,10 @@ var KadimaAchProviderService = class extends AbstractPaymentProvider {
|
|
|
90
90
|
super(container, options);
|
|
91
91
|
this.options_ = options;
|
|
92
92
|
this.client = new KadimaAchClient(options);
|
|
93
|
+
const sb = !!options.sandbox;
|
|
94
|
+
console.info(
|
|
95
|
+
`[kadima-ach] init \u2014 sandbox=${sb} \xB7 host=${sb ? DASHBOARD_HOSTS.sandbox : DASHBOARD_HOSTS.prod}/api/ach \xB7 dba=${options.dbaId ?? "(unset)"} \xB7 token=${options.apiToken ? "set" : "MISSING"}`
|
|
96
|
+
);
|
|
93
97
|
}
|
|
94
98
|
async initiatePayment(input) {
|
|
95
99
|
return {
|
|
@@ -21,7 +21,9 @@ import './types-BUuMxNOL.js';
|
|
|
21
21
|
* terminalId: Number(process.env.KADIMA_TERMINAL_ID),
|
|
22
22
|
* webhookSecret: process.env.KADIMA_WEBHOOK_SECRET,
|
|
23
23
|
* captureMethod: "auth", // or "sale"
|
|
24
|
-
*
|
|
24
|
+
* // Set explicitly — NODE_ENV is "production" on most hosts, which
|
|
25
|
+
* // would silently send sandbox creds to the LIVE host (→ 401).
|
|
26
|
+
* sandbox: process.env.KADIMA_SANDBOX === "true",
|
|
25
27
|
* },
|
|
26
28
|
* },
|
|
27
29
|
* {
|
|
@@ -32,6 +34,7 @@ import './types-BUuMxNOL.js';
|
|
|
32
34
|
* dbaId: Number(process.env.KADIMA_DBA_ID),
|
|
33
35
|
* webhookSecret: process.env.KADIMA_WEBHOOK_SECRET,
|
|
34
36
|
* secCode: "WEB",
|
|
37
|
+
* sandbox: process.env.KADIMA_SANDBOX === "true",
|
|
35
38
|
* },
|
|
36
39
|
* },
|
|
37
40
|
* ],
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
kadima_ach_default
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-UO5EBYD2.js";
|
|
4
4
|
import {
|
|
5
5
|
kadima_card_default
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-KVJTOLRY.js";
|
|
7
|
+
import "./chunk-RPREKUY6.js";
|
|
8
8
|
|
|
9
9
|
// src/index.ts
|
|
10
10
|
import { ModuleProvider, Modules } from "@medusajs/framework/utils";
|
package/README.md
CHANGED
|
@@ -38,7 +38,7 @@ module.exports = defineConfig({
|
|
|
38
38
|
dbaId: Number(process.env.KADIMA_DBA_ID), // for saved cards
|
|
39
39
|
webhookSecret: process.env.KADIMA_WEBHOOK_SECRET,
|
|
40
40
|
captureMethod: "auth", // or "sale"
|
|
41
|
-
sandbox: process.env.
|
|
41
|
+
sandbox: process.env.KADIMA_SANDBOX === "true",
|
|
42
42
|
},
|
|
43
43
|
},
|
|
44
44
|
{
|
|
@@ -49,7 +49,7 @@ module.exports = defineConfig({
|
|
|
49
49
|
dbaId: Number(process.env.KADIMA_DBA_ID),
|
|
50
50
|
webhookSecret: process.env.KADIMA_WEBHOOK_SECRET,
|
|
51
51
|
secCode: "WEB",
|
|
52
|
-
sandbox: process.env.
|
|
52
|
+
sandbox: process.env.KADIMA_SANDBOX === "true",
|
|
53
53
|
},
|
|
54
54
|
},
|
|
55
55
|
],
|
|
@@ -59,6 +59,24 @@ module.exports = defineConfig({
|
|
|
59
59
|
})
|
|
60
60
|
```
|
|
61
61
|
|
|
62
|
+
> ⚠️ **Set `sandbox` explicitly — do not derive it from `NODE_ENV`.** Most hosting
|
|
63
|
+
> platforms (Railway, Render, Vercel, Heroku, Fly) set `NODE_ENV=production`, so
|
|
64
|
+
> `NODE_ENV !== "production"` silently evaluates to `false` and your test build hits
|
|
65
|
+
> the **live** Kadima hosts with sandbox credentials → `HTTP 401: invalid credentials`.
|
|
66
|
+
> While testing, set `KADIMA_SANDBOX=true` in your env; unset it (or `false`) for production.
|
|
67
|
+
> `sandbox: true` uses `sandbox.kadimadashboard.com` / `sandbox-gateway.kadimadashboard.com`;
|
|
68
|
+
> `false` uses the live hosts. The token, terminal ID and DBA ID must come from the
|
|
69
|
+
> **same** environment as the flag (a sandbox token on a live host, or vice-versa, is a 401).
|
|
70
|
+
|
|
71
|
+
On startup each provider logs its resolved configuration so mismatches are obvious, e.g.:
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
[kadima-card] init — sandbox=true · gateway=https://sandbox-gateway.kadimadashboard.com · dashboard=https://sandbox.kadimadashboard.com · terminal=404 · token=set
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
If you see `token=MISSING`, the env var isn't set in your deployment. If `sandbox` or the
|
|
78
|
+
host is wrong for your token, fix the flag and redeploy.
|
|
79
|
+
|
|
62
80
|
Enable the providers in your sales channel / region, point your Kadima webhook at
|
|
63
81
|
`https://<your-store>/hooks/payment/kadima-card` (and `/kadima-ach`), and add the
|
|
64
82
|
storefront components from [`storefront/`](./storefront/README.md).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "medusa-payment-kadima",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Medusa v2 payment provider for Kadima — direct card + ACH, no middle gateway",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"private": false,
|
|
@@ -26,20 +26,22 @@
|
|
|
26
26
|
"exports": {
|
|
27
27
|
".": {
|
|
28
28
|
"types": "./.medusa/server/src/index.d.ts",
|
|
29
|
-
"import": "./.medusa/server/src/index.js"
|
|
29
|
+
"import": "./.medusa/server/src/index.js",
|
|
30
|
+
"default": "./.medusa/server/src/index.js"
|
|
30
31
|
},
|
|
31
32
|
"./providers/kadima-card": {
|
|
32
33
|
"types": "./.medusa/server/src/providers/kadima-card.d.ts",
|
|
33
|
-
"import": "./.medusa/server/src/providers/kadima-card.js"
|
|
34
|
+
"import": "./.medusa/server/src/providers/kadima-card.js",
|
|
35
|
+
"default": "./.medusa/server/src/providers/kadima-card.js"
|
|
34
36
|
},
|
|
35
37
|
"./providers/kadima-ach": {
|
|
36
38
|
"types": "./.medusa/server/src/providers/kadima-ach.d.ts",
|
|
37
|
-
"import": "./.medusa/server/src/providers/kadima-ach.js"
|
|
39
|
+
"import": "./.medusa/server/src/providers/kadima-ach.js",
|
|
40
|
+
"default": "./.medusa/server/src/providers/kadima-ach.js"
|
|
38
41
|
}
|
|
39
42
|
},
|
|
40
43
|
"files": [
|
|
41
44
|
".medusa/server",
|
|
42
|
-
"src",
|
|
43
45
|
"storefront",
|
|
44
46
|
"README.md"
|
|
45
47
|
],
|
package/src/index.ts
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { ModuleProvider, Modules } from "@medusajs/framework/utils"
|
|
2
|
-
import KadimaCardProviderService from "./providers/kadima-card"
|
|
3
|
-
import KadimaAchProviderService from "./providers/kadima-ach"
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Registers BOTH providers under the Payment module. In medusa-config.ts:
|
|
7
|
-
*
|
|
8
|
-
* modules: [
|
|
9
|
-
* {
|
|
10
|
-
* resolve: "@medusajs/medusa/payment",
|
|
11
|
-
* options: {
|
|
12
|
-
* providers: [
|
|
13
|
-
* {
|
|
14
|
-
* resolve: "medusa-payment-kadima/providers/kadima-card",
|
|
15
|
-
* id: "kadima-card",
|
|
16
|
-
* options: {
|
|
17
|
-
* apiToken: process.env.KADIMA_CARD_TOKEN,
|
|
18
|
-
* terminalId: Number(process.env.KADIMA_TERMINAL_ID),
|
|
19
|
-
* webhookSecret: process.env.KADIMA_WEBHOOK_SECRET,
|
|
20
|
-
* captureMethod: "auth", // or "sale"
|
|
21
|
-
* sandbox: process.env.NODE_ENV !== "production",
|
|
22
|
-
* },
|
|
23
|
-
* },
|
|
24
|
-
* {
|
|
25
|
-
* resolve: "medusa-payment-kadima/providers/kadima-ach",
|
|
26
|
-
* id: "kadima-ach",
|
|
27
|
-
* options: {
|
|
28
|
-
* apiToken: process.env.KADIMA_ACH_TOKEN,
|
|
29
|
-
* dbaId: Number(process.env.KADIMA_DBA_ID),
|
|
30
|
-
* webhookSecret: process.env.KADIMA_WEBHOOK_SECRET,
|
|
31
|
-
* secCode: "WEB",
|
|
32
|
-
* },
|
|
33
|
-
* },
|
|
34
|
-
* ],
|
|
35
|
-
* },
|
|
36
|
-
* },
|
|
37
|
-
* ]
|
|
38
|
-
*/
|
|
39
|
-
export default ModuleProvider(Modules.PAYMENT, {
|
|
40
|
-
services: [KadimaCardProviderService, KadimaAchProviderService],
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
export { KadimaCardProviderService, KadimaAchProviderService }
|
package/src/lib/errors.ts
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { KadimaTxnStatus } from "../types"
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Kadima returns a rich set of decline reasons (see docs/2-Payment Gateway API.pdf).
|
|
5
|
-
* We surface the raw reason but classify a few that Medusa / the storefront should
|
|
6
|
-
* treat specially (retryable vs hard decline vs needs-action).
|
|
7
|
-
*/
|
|
8
|
-
export class KadimaError extends Error {
|
|
9
|
-
constructor(
|
|
10
|
-
message: string,
|
|
11
|
-
readonly status: KadimaTxnStatus,
|
|
12
|
-
readonly reason?: string | null,
|
|
13
|
-
readonly raw?: unknown
|
|
14
|
-
) {
|
|
15
|
-
super(message)
|
|
16
|
-
this.name = "KadimaError"
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const RETRYABLE = new Set([
|
|
21
|
-
"Time out",
|
|
22
|
-
"System Error",
|
|
23
|
-
"Error on Host",
|
|
24
|
-
"Host connectivity failed",
|
|
25
|
-
"Issuer or Switch inoperative",
|
|
26
|
-
"Functionality currently not available",
|
|
27
|
-
])
|
|
28
|
-
|
|
29
|
-
export function isRetryable(reason?: string): boolean {
|
|
30
|
-
return reason ? RETRYABLE.has(reason) : false
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/** Throw if Kadima did not approve. */
|
|
34
|
-
export function assertApproved(resp: {
|
|
35
|
-
status?: { status?: KadimaTxnStatus; reason?: string | null }
|
|
36
|
-
}): void {
|
|
37
|
-
const s = resp.status?.status
|
|
38
|
-
if (s !== "Approved") {
|
|
39
|
-
throw new KadimaError(
|
|
40
|
-
`Kadima transaction ${s ?? "Error"}: ${resp.status?.reason ?? "unknown"}`,
|
|
41
|
-
s ?? "Error",
|
|
42
|
-
resp.status?.reason,
|
|
43
|
-
resp
|
|
44
|
-
)
|
|
45
|
-
}
|
|
46
|
-
}
|
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
import { DASHBOARD_HOSTS, KadimaAchOptions } from "../types"
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Client over the Kadima ACH API (kadimadashboard.com/api/ach).
|
|
5
|
-
*
|
|
6
|
-
* Verified against Kadima_Dashboard_API_COMPLETE.md:
|
|
7
|
-
* POST /api/ach create a Debit/Credit (returns { id })
|
|
8
|
-
* GET /api/ach/<id> view a transaction
|
|
9
|
-
* POST /api/ach/<id>/<action> void | cancel | verify
|
|
10
|
-
* POST /api/ach/customer create a vault customer
|
|
11
|
-
* POST /api/ach/customer/<id>/account add a bank account to a customer
|
|
12
|
-
*
|
|
13
|
-
* ACH is ASYNCHRONOUS: create returns status Pending; settlement (`Settled`) or
|
|
14
|
-
* failure (`Returned`) arrive later via the ach/updateStatus webhook. So a debit
|
|
15
|
-
* create means "submitted", not "captured".
|
|
16
|
-
*
|
|
17
|
-
* Request field names are exact and case-sensitive: `SECCode`, `transactionType`,
|
|
18
|
-
* `accountName`, `accountNumber`, `routingNumber`, `accountType`, `dba.id`.
|
|
19
|
-
*/
|
|
20
|
-
export class KadimaAchClient {
|
|
21
|
-
private readonly base: string
|
|
22
|
-
|
|
23
|
-
constructor(private readonly opts: KadimaAchOptions) {
|
|
24
|
-
this.base = `${opts.sandbox ? DASHBOARD_HOSTS.sandbox : DASHBOARD_HOSTS.prod}/api/ach`
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Create returns { id }. NOTE: id is a string in the minimal response but
|
|
28
|
-
// numeric in the save-customer response — treat it as string | number.
|
|
29
|
-
/** Create a debit. Returns the new ACH transaction id. */
|
|
30
|
-
async debit(input: AchTxnInput): Promise<{ id: string | number }> {
|
|
31
|
-
return this.request(this.base, "POST", this.buildBody(input, "Debit"))
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/** Offsetting credit — refunds a settled debit (PPD/CCD only). */
|
|
35
|
-
async credit(input: AchTxnInput): Promise<{ id: string | number }> {
|
|
36
|
-
return this.request(this.base, "POST", this.buildBody(input, "Credit"))
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/** void | cancel | verify (void only while Held/Pending/Submitted). */
|
|
40
|
-
async action(id: string | number, action: "void" | "cancel" | "verify") {
|
|
41
|
-
return this.request(`${this.base}/${id}/${action}`, "POST")
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
async get(id: string | number): Promise<KadimaAchTxn> {
|
|
45
|
-
return this.request(`${this.base}/${id}`, "GET")
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// --- Customer Vault ------------------------------------------------------
|
|
49
|
-
async createCustomer(data: Record<string, unknown>): Promise<{ id: string }> {
|
|
50
|
-
return this.request(`${this.base}/customer`, "POST", data)
|
|
51
|
-
}
|
|
52
|
-
async addAccount(customerId: string | number, account: Record<string, unknown>) {
|
|
53
|
-
return this.request(`${this.base}/customer/${customerId}/account`, "POST", account)
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
private buildBody(input: AchTxnInput, transactionType: "Debit" | "Credit") {
|
|
57
|
-
const body: Record<string, unknown> = {
|
|
58
|
-
amount: input.amount,
|
|
59
|
-
transactionType,
|
|
60
|
-
SECCode: input.secCode ?? this.opts.secCode ?? "WEB",
|
|
61
|
-
dba: { id: this.opts.dbaId },
|
|
62
|
-
...(input.tax != null ? { tax: input.tax } : {}),
|
|
63
|
-
...(input.memo ? { memo: input.memo } : {}),
|
|
64
|
-
...(input.addendaText ? { addendaText: input.addendaText } : {}),
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
if (input.customerId) {
|
|
68
|
-
// Existing vault customer (+ optional specific saved account).
|
|
69
|
-
body.customer = { id: input.customerId }
|
|
70
|
-
if (input.accountId) body.account = { id: input.accountId }
|
|
71
|
-
} else {
|
|
72
|
-
// New inline bank account. Bank fields are TOP-LEVEL, not nested.
|
|
73
|
-
body.accountName = input.accountName
|
|
74
|
-
body.accountNumber = input.accountNumber
|
|
75
|
-
body.routingNumber = input.routingNumber
|
|
76
|
-
body.accountType = input.accountType ?? "Checking"
|
|
77
|
-
body.customer = {
|
|
78
|
-
...(input.saveCustomer ? { save: "Yes" } : {}),
|
|
79
|
-
...input.customer,
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
return body
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
private async request<T = any>(
|
|
86
|
-
url: string,
|
|
87
|
-
method: "POST" | "GET",
|
|
88
|
-
body?: unknown
|
|
89
|
-
): Promise<T> {
|
|
90
|
-
const resp = await fetch(url, {
|
|
91
|
-
method,
|
|
92
|
-
headers: {
|
|
93
|
-
Authorization: `Bearer ${this.opts.apiToken}`,
|
|
94
|
-
"Content-Type": "application/json",
|
|
95
|
-
},
|
|
96
|
-
...(body !== undefined ? { body: JSON.stringify(body) } : {}),
|
|
97
|
-
})
|
|
98
|
-
const text = await resp.text()
|
|
99
|
-
const json = text ? JSON.parse(text) : {}
|
|
100
|
-
if (!resp.ok) {
|
|
101
|
-
const msg = (json as any)?.message ?? text
|
|
102
|
-
throw new Error(`Kadima ACH HTTP ${resp.status}: ${msg}`)
|
|
103
|
-
}
|
|
104
|
-
return json as T
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
export interface AchTxnInput {
|
|
109
|
-
amount: number
|
|
110
|
-
tax?: number
|
|
111
|
-
secCode?: "PPD" | "CCD" | "WEB" | "TEL"
|
|
112
|
-
memo?: string
|
|
113
|
-
addendaText?: string
|
|
114
|
-
// Either an existing vault customer ...
|
|
115
|
-
customerId?: string | number
|
|
116
|
-
accountId?: string | number
|
|
117
|
-
// ... or a new inline bank account (top-level fields) + customer details.
|
|
118
|
-
accountName?: string
|
|
119
|
-
accountNumber?: string
|
|
120
|
-
routingNumber?: string
|
|
121
|
-
accountType?: "Checking" | "Savings"
|
|
122
|
-
saveCustomer?: boolean // customer.save = "Yes"
|
|
123
|
-
customer?: {
|
|
124
|
-
firstName?: string
|
|
125
|
-
lastName?: string
|
|
126
|
-
email?: string
|
|
127
|
-
phone?: string
|
|
128
|
-
address1?: string
|
|
129
|
-
address2?: string
|
|
130
|
-
city?: string
|
|
131
|
-
state?: string
|
|
132
|
-
zipCode?: string
|
|
133
|
-
identifier?: string // merchant-side unique id for the payer
|
|
134
|
-
sendReceipt?: "Yes" | "No"
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/** ACH transaction object (List/View/webhook achObject). */
|
|
139
|
-
export interface KadimaAchTxn {
|
|
140
|
-
id: number | string
|
|
141
|
-
amount: string
|
|
142
|
-
tax?: string
|
|
143
|
-
SECCode?: "PPD" | "CCD" | "WEB" | "TEL"
|
|
144
|
-
accountName?: string
|
|
145
|
-
accountNumber?: string
|
|
146
|
-
accountType?: "Checking" | "Savings"
|
|
147
|
-
routingNumber?: string
|
|
148
|
-
transactionType?: "Debit" | "Credit"
|
|
149
|
-
transactionStatus?: KadimaAchStatus
|
|
150
|
-
dba?: { id: number; name?: string }
|
|
151
|
-
customer?: { id?: string | null; identifier?: string | null; email?: string | null }
|
|
152
|
-
verification?: { status?: string; date?: string | null }
|
|
153
|
-
return?: { code?: string | null; date?: string | null }
|
|
154
|
-
source?: string
|
|
155
|
-
createdOn?: string
|
|
156
|
-
updatedOn?: string
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
export type KadimaAchStatus =
|
|
160
|
-
| "Voided"
|
|
161
|
-
| "Hold"
|
|
162
|
-
| "Pending"
|
|
163
|
-
| "Submitted"
|
|
164
|
-
| "Transmitted"
|
|
165
|
-
| "Settled"
|
|
166
|
-
| "Returned"
|