Permalink
Cannot retrieve contributors at this time
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
176 lines (158 sloc)
4.61 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import snake from 'lodash.snakecase' | |
import { Req } from '../../client' | |
export class Request implements Req { | |
private _input: Input | |
private _output: Output | |
private _raw: { [k: string]: any } | |
constructor (input: Input) { | |
if (input.provider === 'vodafone' && input.voucher === undefined) { | |
throw new MissingVoucherError(input.provider) | |
} | |
this._input = input | |
} | |
/** | |
* The relative URL endpoint to use when | |
* performing the request. | |
* | |
* @property to | |
*/ | |
get to (): string { | |
return 'receive.json' | |
} | |
/** | |
* The HTTP method to use when performing the request. | |
* | |
* @property method | |
*/ | |
get method (): string { | |
return 'POST' | |
} | |
/** | |
* @property | |
*/ | |
get output (): Output { | |
return this._output | |
} | |
/** | |
* Returns JSON object of the request's input, ready | |
* to be sent as the body of an HTTP request. | |
* | |
* @property body | |
*/ | |
get body (): Object { | |
return Object.entries(this._input).reduce( | |
(b, [k, v]) => { | |
if (k === 'callbackURLs') { | |
// `lodash.snakecase` can't handle this key properly. | |
b['callback_urls'] = v | |
} else { | |
b[snake(k)] = v | |
} | |
return b | |
}, | |
{ service_code: 'cashout' } as { [k: string]: any } | |
) | |
} | |
/** | |
* @property | |
*/ | |
get response (): { [k: string]: any } { | |
return this._raw | |
} | |
/** | |
* Sets the output of the request. | |
* The response received after performing the request is | |
* converted to the expected output type. It also sets | |
* the raw response that was received. | |
* | |
* @param {object} data Response | |
*/ | |
set response (data: { [k: string]: any }) { | |
this._raw = data | |
this.handleError(data) | |
const { reference, provider, recipient, amount, currency, message } = data.response | |
this._output = { | |
success: true, | |
response: { | |
reference, | |
provider, | |
recipient, | |
amount, | |
currency, | |
message | |
} | |
} | |
} | |
handleError (data: { [k: string]: any }) { | |
if (data.success === false) { | |
const { error_type: type, error_message: message } = data.response | |
switch (type) { | |
case 'invalid_voucher': { | |
throw new InvalidVoucherError() | |
} | |
default: { | |
throw new Error(`unknown error type: ${type}, with message: ${message}`) | |
} | |
} | |
} | |
} | |
} | |
// Input represents the set of required and optional | |
// parameters to send when requesting for funds from | |
// a certain Mobile Money Account. | |
// While `provider` is optional, it's recommended that | |
// you set it since the heuristic used to automatically | |
// detect fails if the payee's number is ported. For | |
// example, the 024 prefix will be wrongly identified | |
// as MTN even after the owner has ported to a different | |
// network. | |
export interface Input { | |
// required | |
amount: number // Amount to receive | |
currency: string // Currency of amount, e.g. GHS | |
customerNo: string // Mobile Money Account to receive from | |
countryCode: string // Country code of Mobile Money Account, e.g. GH | |
reference: string // Alphanumeric, uniquely identifies transaction to client | |
// optional | |
provider?: string // Mobile Money Operator of payee. Due to porting it's a good idea to specify | |
voucher?: string // Required for Vodafone. It is generated by dialing *110# and reply with option #6. | |
customerName?: string // Name of payee or description of transaction | |
remarks?: string // Remarks on the transaction | |
scheduleDate?: string // Day to execute, if not immediately | |
scheduleTime?: string // Time to execute, if not immediately | |
live?: boolean // Production? | |
dummy?: boolean // Default: true. Set to false to receive callbacks | |
callbackURLs?: string[] // Allows to customize callbacks per request. Defaults to global if none given | |
} | |
// Output is what we received after a successful | |
// or failed call to the Flopay API. | |
export interface Output { | |
success: boolean | |
response: Response | |
} | |
// Response maps onto the structure of the expected | |
// JSON response for successful requests. | |
// See https://developer.flopay.io/accept-payment/mobile-wallet | |
// for more information. | |
export interface Response { | |
reference: string | |
provider: string | |
recipient: string | |
amount: number | |
currency: string | |
message: string | |
} | |
// Missing | |
export class MissingVoucherError extends Error { | |
constructor (provider: string) { | |
super(`voucher is required when provider is ${provider}`) | |
} | |
} | |
// InvalidVoucherError is the exception thrown | |
// when the given voucher (for transactions that require | |
// a voucher) is wrong. | |
export class InvalidVoucherError extends Error { | |
constructor () { | |
super('Voucher number is required') | |
} | |
} |