![Oracle Drags Its Feet in the JavaScript Trademark Dispute](https://cdn.sanity.io/images/cgdhsj6q/production/919c3b22c24f93884c548d60cbb338e819ff2435-1024x1024.webp?w=400&fit=max&auto=format)
Security News
Oracle Drags Its Feet in the JavaScript Trademark Dispute
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.
A comprehensive TypeScript wrapper for NMI (Network Merchants, Inc.) payment gateway API. This wrapper provides type-safe interactions with NMI's services including customer vault management, transaction processing, product management, invoicing, and recurring payments.
# Using pnpm (recommended)
pnpm add znmi
# Using npm
npm install znmi
# Using yarn
yarn add znmi
import { ZNMI } from "znmi";
const znmi = new ZNMI("your_security_key_here");
My bad for leaving it for so long pointing to the wrong file, I have fixed it and updated the README
<3
Please Note: NMI's Payment API & Query API Docs SUCK. I am doing my best to keep things up to date as I find them, if you find any out of date typedefs or invalid requests, please file a report!
All requests and responses are fully typed using Zod schemas. The library provides comprehensive type definitions for:
Import types directly:
import type {
// Request Types
RequestInfo,
RequestCategory,
TransactionRequestActions,
CustomerVaultRequestActions,
RecurringRequestActions,
InvoiceRequestActions,
ProductManagerRequestActions,
QueryRequestActions,
// Response Types
TransactionResponse,
CustomerVaultResponse,
RecurringResponse,
QueryResponse,
FlatQueryResponse,
} from "znmi";
Manage customer data and payment information securely.
// Add or Update a Customer
const customerData = {
customer_vault: "add_customer",
ccnumber: "4111111111111111",
ccexp: "1225",
};
const response = await znmi.customerVault.addOrUpdateCustomer(customerData);
// Validate Customer by Vault ID
const validateData = {
customer_vault_id: "12345",
};
await znmi.customerVault.validateCustomerVaultId(validateData);
Available Methods:
addOrUpdateCustomer(request: AddUpdateCustomerRequest)
- Add or update customervalidateCustomerVaultId(request: ValidateCustomerVaultIdRequest)
- Validate stored customerauthorizeCustomerByVaultId(request: AuthorizeCustomerByVaultIdRequest)
- Authorize paymentsaleByVaultId(request: SaleByVaultIdRequest)
- Process salecreditTransactionByVaultId(request: CreditTransactionByVaultIdRequest)
- Process creditofflineTransactionByVaultId(request: OfflineTransactionByVaultIdRequest)
- Process offlineinitiateCustomerVaultTransaction(request: CustomerVaultInitiatedTransaction)
- Start transactiondeleteCustomer(request: DeleteCustomerRecord)
- Remove customeraddBillingForCustomer(request: AddBillingForCustomerRequest)
- Add billingupdateBillingForCustomer(request: UpdateBillingForCustomerRequest)
- Update billingdeleteBillingForCustomer(request: DeleteBillingForCustomerRequest)
- Remove billingProcess various types of payment transactions.
// Process a Sale
const saleData = {
type: "sale",
amount: "49.99",
ccnumber: "4111111111111111",
ccexp: "1225",
};
await znmi.transactions.createTransaction(saleData);
// Capture an Authorization
const captureData = {
type: "capture",
transactionid: "1234567",
};
await znmi.transactions.captureTransaction(captureData);
Available Methods:
createTransaction(request: TransactionRequest)
- Process new transactioncaptureTransaction(request: CaptureTransactionRequest)
- Capture authorized transactionrefundTransaction(request: RefundTransaction)
- Process refundvoidTransaction(request: VoidTransactionRequest)
- Void transactionupdateTransaction(request: UpdateTransactionRequest)
- Update transaction detailsSet up and manage recurring payment plans.
// Create a Recurring Plan
const planData = {
plan_payments: 12,
plan_amount: 29.99,
plan_name: "Premium Monthly",
plan_id: "PLAN-001",
month_frequency: 1,
};
await znmi.recurring.createRecurringPlan(planData);
// Add Subscription to Existing Plan
const subscriptionData = {
plan_id: "PLAN-001",
ccnumber: "4111111111111111",
ccexp: "1225",
};
await znmi.recurring.addSubscriptionToExistingPlan(subscriptionData);
Available Methods:
createRecurringPlan(request: AddRecurringPlan)
- Create new planeditRecurringPlan(request: EditRecurringPlan)
- Modify existing planaddSubscriptionToExistingPlan(request: AddSubscriptionToExistingPlan)
- Add to planaddCustomSubscription(request: AddCustomSubscription)
- Create custom subscriptionupdateSubscription(request: UpdateSubscription)
- Update subscriptiondeleteSubscription(request: DeleteSubscriptionRequest)
- Cancel subscriptionQuery transaction data and account information.
// Query a Transaction
const transactionId = "1234567890";
const response = await znmi.query.queryTransaction(transactionId);
// Query Transactions by Date Range with Pagination
const dateResponse = await znmi.query.queryTransactionsWithPagination(
1, // page number
100, // results per page
"asc", // order
{
start_date: "2024-01-01",
end_date: "2024-01-31",
}
);
Available Methods:
queryTransaction(transactionId: string)
- Query single transactionqueryReceipt(transactionId: string)
- Get transaction receiptqueryProfile(includeProcessorDetails?: boolean)
- Query account profilequeryTransactionsByDate(startDate: string, endDate: string, options?: QueryRequestWithoutKey)
- Query by datequeryCustomerVault(customerVaultId?: string, dateRange?: DateRange, options?: QueryRequestWithoutKey)
- Query vaultqueryRecurring(subscriptionId?: string, options?: QueryRequestWithoutKey)
- Query recurringqueryRecurringPlans(options?: QueryRequestWithoutKey)
- Query plansqueryInvoices(invoiceId?: string, status?: string[], options?: QueryRequestWithoutKey)
- Query invoicesqueryTransactionsBySource(sources: QueryTransactionSourceEnum[], options?: QueryRequestWithoutKey)
- By sourcequeryTransactionsByCondition(conditions: QueryTransactionConditionEnum[], options?: QueryRequestWithoutKey)
- By conditionqueryTransactionsByActionType(actionTypes: QueryTransactionActionTypeEnum[], options?: QueryRequestWithoutKey)
- By actionqueryTransactionsByCard(cardNumber: string, options?: QueryRequestWithoutKey)
- By cardqueryTransactionsWithPagination(pageNumber: number, resultLimit: number, resultOrder: QueryResultOrderEnum, options?: QueryRequestWithoutKey)
- PaginatedqueryGatewayProcessors(options?: QueryRequestWithoutKey)
- Query processorsqueryAccountUpdater(options?: QueryRequestWithoutKey)
- Query updater statusqueryTestModeStatus(options?: QueryRequestWithoutKey)
- Query test modeThe wrapper includes comprehensive error handling for both query string and XML responses:
try {
// Query string response
const response = await znmi.transactions.createTransaction(transactionData);
if (response.response === "1") {
console.log("Transaction ID:", response.transactionid);
} else {
console.error("Error:", response.responsetext);
}
// XML response
const queryResponse = await znmi.query.queryTransaction("1234567");
if (queryResponse.status === 200 && queryResponse.data) {
console.log("Transaction data:", queryResponse.data);
} else {
console.error("Query error:", queryResponse.message);
}
} catch (error) {
console.error("API Error:", error);
}
Testing will work for all but the Query API with the default key
To test using your NMI_SECURITY_KEY please set the env variable export ZNMI_SECURITY_KEY=your-security-key
Run the test suite:
pnpm test
MIT License - see LICENSE file for details.
Contributions are welcome! Please feel free to submit a Pull Request.
customer_vault_id
to all recurring charges, they do, in fact, work. They are simply not present in the API docs (confirmed via NMI Support) -- Also fixed some othersQueryCustomerVaultResponseType
, fixed some other types with recurring payments too!QueryCustomerVaultResponseType
-- some type errors, and it can be an array of customers in the object, or just one if you use customer_vault_id
updateCustomer
type to not require the ccnumber
, but addCustomer
doesaddCustomer
in the Customer Vault
not requiring a ccnumber
(kinda dumb if you ask me but I am not the dev)deleteCustomer
from the Customer Vault
requiring a security key, when others do not (it gets added automatically)Query
API to make sure it works, additionally, I updated the main query endpoints to just take an object parameter. I initially made them that way so you could just pass the required info, but I realize that at this point it's probably just annoying.Query
API (some)saleByVaultId
package.json
and tsup.config.ts
to hopefully build it properly so we can reference itupdateSubscription
so it doesn't need an amount
(for example for pausing)addSubscriptionToExistingPlan
FlatQueryResponse
type, cause I like having logging in my database and I can't transform a union into a singular collectionQueryResponse
type, which is just a union of the others, but makes my life (and maybe yours) easierQuery
API, which I didn't know existedFAQs
A simple and easy TypeScript wrapper around NMI's API
We found that znmi demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.
Security News
The Linux Foundation is warning open source developers that compliance with global sanctions is mandatory, highlighting legal risks and restrictions on contributions.
Security News
Maven Central now validates Sigstore signatures, making it easier for developers to verify the provenance of Java packages.