Skip to content
Draft
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
16 changes: 13 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
CHANGELOG
=========

9.1.1
------------------

9.2.0
------------------

* Added the inputs `/billing/phone_verification_method`,
`/billing/phone_was_verification_successful`,
`/billing/phone_verification_time`,
`/shipping/phone_verification_method`,
`/shipping/phone_was_verification_successful`, and
`/shipping/phone_verification_time`. They describe the most recent
verification of the billing or shipping phone number. You may provide them
by providing `phoneVerificationMethod`, `phoneWasVerificationSuccessful`,
and `phoneVerificationTime` to `Billing` or `Shipping`. The
`PhoneVerificationMethod` enum lists the valid methods.
* Added `maxmind` as a direct dependency. The `IpAddressWebRecord` type extends
`CityResponse` from that package, so it is part of this package's published
type surface. It was previously resolved only as a transitive dependency of
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,9 @@ try {
lastName: 'Bar',
phoneCountryCode: '1',
phoneNumber: '123-456-1234',
phoneVerificationMethod: minFraud.Constants.PhoneVerificationMethod.DeliveredCode,
phoneVerificationTime: new Date('2026-10-01T14:30:00Z'),
phoneWasVerificationSuccessful: true,
postal: '12345',
region: 'MA',
}),
Expand All @@ -231,6 +234,9 @@ try {
lastName: 'Bar',
phoneCountryCode: '1',
phoneNumber: '123-456-0000',
phoneVerificationMethod: minFraud.Constants.PhoneVerificationMethod.DeliveredCode,
phoneVerificationTime: new Date('2026-10-01T14:30:00Z'),
phoneWasVerificationSuccessful: true,
postal: '12345',
region: 'MA',
}),
Expand Down
6 changes: 6 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ export enum DeliverySpeed {
Standard = 'standard',
}

export enum PhoneVerificationMethod {
DeliveredCode = 'delivered_code',
Network = 'network',
Other = 'other',
}

export enum PaymentMethod {
BankDebit = 'bank_debit',
BankRedirect = 'bank_redirect',
Expand Down
16 changes: 16 additions & 0 deletions src/request/location.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { describe, expect, it } from 'vitest';
import { PhoneVerificationMethod } from '../constants.js';
import { ArgumentError } from '../errors.js';
import Location from './location.js';

Expand All @@ -20,4 +21,19 @@ describe('Location()', () => {
});
}).not.toThrow();
});

it('stores the phone verification properties', () => {
const time = new Date('2026-10-01T14:30:00Z');
const location = new Location({
country: 'CA',
phoneVerificationMethod: PhoneVerificationMethod.Network,
phoneVerificationTime: time,
phoneWasVerificationSuccessful: false,
});

expect(location.country).toBe('CA');
expect(location.phoneVerificationMethod).toBe('network');
expect(location.phoneVerificationTime).toBe(time);
expect(location.phoneWasVerificationSuccessful).toBe(false);
});
});
20 changes: 20 additions & 0 deletions src/request/location.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { PhoneVerificationMethod } from '../constants.js';
import { ArgumentError } from '../errors.js';

export interface LocationProps {
Expand Down Expand Up @@ -46,6 +47,19 @@ export interface LocationProps {
* The phone number, without the country code, associated with the address.
*/
phoneCountryCode?: string;
/**
* The most recent method used to verify the phone number.
*/
phoneVerificationMethod?: PhoneVerificationMethod;
/**
* The date and time of the most recent verification of the phone number.
*/
phoneVerificationTime?: Date;
/**
* Whether the most recent verification of the phone number succeeded. Omit
* this if no verification was attempted.
*/
phoneWasVerificationSuccessful?: boolean;
}

const countryRegex = /^[A-Z]{2}$/;
Expand Down Expand Up @@ -76,6 +90,12 @@ export default class Location implements LocationProps {
public phoneNumber?: string;
/** @inheritDoc LocationProps.phoneCountryCode */
public phoneCountryCode?: string;
/** @inheritDoc LocationProps.phoneVerificationMethod */
public phoneVerificationMethod?: PhoneVerificationMethod;
/** @inheritDoc LocationProps.phoneVerificationTime */
public phoneVerificationTime?: Date;
/** @inheritDoc LocationProps.phoneWasVerificationSuccessful */
public phoneWasVerificationSuccessful?: boolean;

public constructor(location: LocationProps) {
if (location.country != null && !countryRegex.test(location.country)) {
Expand Down
39 changes: 39 additions & 0 deletions src/request/transaction.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { describe, expect, it, test } from 'vitest';
import { PhoneVerificationMethod } from '../constants.js';
import { ArgumentError } from '../errors.js';
import Account from './account.js';
import Billing from './billing.js';
Expand Down Expand Up @@ -267,6 +268,44 @@ describe('Transaction()', () => {
expect(test.toString()).toContain('"billing":{"address_2":"foo"}');
});

it('it handles billing phone verification fields', () => {
const test = new Transaction({
billing: new Billing({
phoneVerificationMethod: PhoneVerificationMethod.DeliveredCode,
phoneVerificationTime: new Date('2026-10-01T14:30:00Z'),
phoneWasVerificationSuccessful: false,
}),
device: new Device({
ipAddress: '1.1.1.1',
}),
});

expect(JSON.parse(test.toString()).billing).toEqual({
phone_verification_method: 'delivered_code',
phone_verification_time: '2026-10-01T14:30:00.000Z',
phone_was_verification_successful: false,
});
});

it('it handles shipping phone verification fields', () => {
const test = new Transaction({
shipping: new Shipping({
phoneVerificationMethod: PhoneVerificationMethod.DeliveredCode,
phoneVerificationTime: new Date('2026-10-01T14:30:00Z'),
phoneWasVerificationSuccessful: false,
}),
device: new Device({
ipAddress: '1.1.1.1',
}),
});

expect(JSON.parse(test.toString()).shipping).toEqual({
phone_verification_method: 'delivered_code',
phone_verification_time: '2026-10-01T14:30:00.000Z',
phone_was_verification_successful: false,
});
});

it('does not mutate the caller’s input objects when serializing', () => {
const billing = new Billing({ address2: 'foo' });
const shipping = new Shipping({ address2: 'bar' });
Expand Down
Loading