Skip to content
This repository was archived by the owner on May 30, 2025. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 105 additions & 34 deletions lib/cards.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { check, checkString } from "./helpers/checks.js";
import { Err } from "./helpers/errors.js";

/** @typedef {import('./paymentMethods.js').PaymentMethod} PaymentMethod */

/** @external Promise */

/**
Expand Down Expand Up @@ -92,17 +94,35 @@ export const CARD_VERIFICATION_STATUS = {
*
* @tag Cards
*/

/** @template T
* @template K {extends keyof T}
* @typedef {Pick<Partial<T>, K> & Omit<T, K>} Optional
*/

/**
* Card information collected for acquisition.
* @typedef LinkCard
* @property {string} cardNumber - All digits of the card
* @property {CardExpiration} expiration - Card expiration date
* @property {string} cardCvv - 3-4 digit card verification value
* @property {string} holderName - Full name of the card holder
* @property {CardBillingAddress} billingAddress - The billing address of the card
* @property {Optional<CardBillingAddress, 'addressLine1' | 'addressLine2' | 'city' | 'stateOrProvince' | 'country'>} billingAddress - The billing address of the card
* @property {boolean} [ cardOnFile = false ] - Indicates cardholder has authorized card to be stored for future payments. Only cards marked as card-on-file are eligible for automatic updates via card account updater
*
* @tag Cards
*/

/**
* Card information that can be updated.
* @typedef UpdateCard
* @property {CardExpiration} expiration - Card expiration date
* @property {string} cardCvv - 3-4 digit card verification value
* @property {Optional<CardBillingAddress, 'addressLine1' | 'addressLine2' | 'city' | 'stateOrProvince' | 'country'>} billingAddress - The billing address of the card
*
* @tag Cards
*/

/**
* Card billing address
* @typedef CardBillingAddress
Expand Down Expand Up @@ -141,37 +161,56 @@ export const CARD_VERIFICATION_STATUS = {
* @property {CardVerficationStatuses} cardVerfication - The results of submitting cardholder data to a card network for verification
* @property {string} issuer - The name of the issuer
* @property {string} issuerCountry - The country of the issuer
*
* @property {string} merchantAccountID
* @property {PaymentMethod[]} [paymentMethods]
*
* @example
* {
"cardID": "ec7e1848-dc80-4ab0-8827-dd7fc0737b43",
"fingerprint": "9948962d92a1ce40c9f918cd9ece3a22bde62fb325a2f1fe2e833969de672ba3",
"brand": "American Express",
"cardType": "debit",
"lastFourCardNumber": "1234",
"bin": "123456",
"expiration": {
"month": "01",
"year": "21"
},
"holderName": "Jules Jackson",
"billingAddress": {
"addressLine1": "123 Main Street",
"addressLine2": "Apt 302",
"city": "Boulder",
"stateOrProvince": "CO",
"postalCode": "80301",
"country": "US"
},
"cardVerification": {
"cvv": "match",
"addressLine1": "match",
"postalCode": "match"
},
"issuer": "GRINGOTTS BANK",
"issuerCountry": "US"
"billingAddress": {
"addressLine1": "123 Main Street",
"addressLine2": "Apt 302",
"city": "Boulder",
"country": "US",
"postalCode": "80301",
"stateOrProvince": "CO"
},
"bin": "123456",
"brand": "Discover",
"cardAccountUpdater": {
"updateType": "number-update",
"updatedOn": "2019-08-24T14:15:22Z"
},
"cardID": "ec7e1848-dc80-4ab0-8827-dd7fc0737b43",
"cardOnFile": true,
"cardType": "debit",
"cardVerification": {
"addressLine1": "match",
"cvv": "match",
"postalCode": "match"
},
"domesticPushToCard": "fast-funds",
"expiration": {
"month": "01",
"year": "21"
},
"fingerprint": "9948962d92a1ce40c9f918cd9ece3a22bde62fb325a2f1fe2e833969de672ba3",
"holderName": "Jules Jackson",
"issuer": "GRINGOTTS BANK",
"issuerCountry": "US",
"lastFourCardNumber": "1234",
"merchantAccountID": "50469144-f859-46dc-bdbd-9587c2fa7b42",
"paymentMethods": [
{
"paymentMethodID": "9506dbf6-4208-44c3-ad8a-e4431660e1f2",
"paymentMethodType": "card-payment"
},
{
"paymentMethodID": "3f9969cf-a1f3-4d83-8ddc-229a506651cf",
"paymentMethodType": "push-to-card"
}
]
}
*
*
* @tag Cards
*/

Expand All @@ -187,7 +226,7 @@ export class Cards {
/**
* Retrieves details for the card with the specified ID.
* The `CARDS_READ` scope enum is required when making a request from the browser.
*
*
* @param {string} accountID - Account to query
* @param {string} cardID - Card to query
* @returns {Promise<Card>}
Expand All @@ -210,7 +249,7 @@ export class Cards {
/**
* Lists all the cards associated with a particular Moov account.
* The `CARDS_READ` scope enum is required when making a request from the browser.
*
*
* @param {string} accountID - Account to query
* @returns {Promise<Card[]>}
* @tag Cards
Expand All @@ -232,19 +271,24 @@ export class Cards {
* Links a card to a Moov account. Only use this endpoint if you have provided Moov with a
* copy of your PCI attestation of compliance.
* The `CARDS_WRITE` scope enum is required when making a request from the browser.
*
*
* @param {string} accountID - Account to link
* @param {LinkCard} card - Card information
* @param {boolean} [waitForPaymentMethods = false] whether to wait for payment methods to be created and included in response
* @returns {Promise<Card>}
* @tag Cards
*/
async link(accountID, card) {
async link(accountID, card, waitForPaymentMethods = false) {
checkString(accountID).or(Err.MISSING_ACCOUNT_ID);
check(card).or(Err.MISSING_CARD);

const headers = {};
if (waitForPaymentMethods) headers['X-Wait-For'] = 'payment-method'

const result = await this.moov
.got({
url: `accounts/${accountID}/cards`,
headers,
method: "POST",
json: card,
})
Expand All @@ -253,10 +297,37 @@ export class Cards {
return result;
}

/**
* Updates a card in a Moov account. Only use this endpoint if you have provided Moov with a
* copy of your PCI attestation of compliance.
* The `CARDS_WRITE` scope enum is required when making a request from the browser.
*
* @param {string} accountID - Account linked to card
* @param {string} cardID - Card to update
* @param {UpdateCard} cardUpdates - Card information
* @returns {Promise<Card>}
* @tag Cards
*/
async update(accountID, cardID, cardUpdates) {
checkString(accountID).or(Err.MISSING_ACCOUNT_ID);
checkString(cardID).or(Err.MISSING_CARD_ID);
check(cardUpdates).or(Err.MISSING_CARD);

const result = await this.moov
.got({
url: `accounts/${accountID}/cards/${cardID}`,
method: "PATCH",
json: cardUpdates,
})
.json();

return result;
}

/**
* Disables a card with the specified ID.
* The `CARDS_WRITE` scope enum is required when making a request from the browser.
*
*
* @param {string} accountID - Account to query
* @param {string} cardID - Card to query
* @returns {Promise<void>}
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"docs": "node ./scripts/generateDocs.cjs",
"docs-watch": "watch \"npm run docs\" ./docs/templates",
"docs-clean": "rm ./docs/output/*.*",
"prepare": "npm run build",
"test": "ava ./lib/**/*.test.js",
"generate-types": "tsc",
"test-watch": "ava --watch ./lib/**/*.test.js"
Expand Down