transact-payments
Version:
Node module to do payments using transact.io
295 lines (251 loc) • 6.65 kB
text/typescript
const jwt = require('jsonwebtoken');
import { TransactIoError } from './TransactIoError';
import { TransactIoErrorCode } from './TransactIoErrorCode';
import { ITransactJWT } from './TransactToken';
/**
* @description Transact.io message handler
*
* @class TransactIoMsg
*/
export class TransactIoMsg {
/**
*
*
* @param {string} token
* @param {any} callback
* @returns
* @memberof TransactIoMsg
*/
public static verify(token: string, secret: string, callback?: (err, decoded: ITransactJWT) => void):
Promise<object> {
return new Promise((resolve, reject) => {
const jwtOptions = {
algorithm: 'HS256',
};
if (!secret || secret.length < 1) {
const transactIoError = new TransactIoError('Invalid secret', TransactIoErrorCode.INVALID_SECRET, null);
if (callback) {
callback(transactIoError, null);
} else {
reject(transactIoError);
}
return;
}
const jwtToken = jwt.verify(token, secret, jwtOptions, callback ? callback : undefined);
resolve(jwtToken);
});
}
public static isFromTransactServer(token: ITransactJWT) {
if (token.tid) {
return true;
}
return false;
}
private token: ITransactJWT;
private secret: string;
constructor() {
this.token = new ITransactJWT();
this.setMethodClose();
this.setClassProduction();
}
public setMethodPost() {
this.token.method = 'POST';
}
public setMethodClose() {
this.token.method = 'CLOSE';
}
public setMethodGet() {
this.token.method = 'GET';
}
public setClassProduction() {
this.token.tclass = 'PROD';
}
public setClassTest() {
this.token.tclass = 'DEV';
}
/**
*
*
* @param {string} secret Your secret key to sign the message
* @memberof TransactIoMsg
*/
public setSecret(secret: string) {
this.secret = secret;
}
/**
*
*
* @param {string} url address of purchased item
* @memberof TransactIoMsg
*/
public setURL(url: string) {
this.token.url = url;
}
/**
*
*
* @param {string} url address of purchased item
* @memberof TransactIoMsg
*/
public isSubscription(isSubscription: boolean) {
this.token.sub = isSubscription;
}
/**
*
*
* @param {string} title name of what they are buying.
* @memberof TransactIoMsg
*/
public setTitle(title: string) {
this.token.title = title;
}
/**
*
*
* @param {number} price in cents
* @memberof TransactIoMsg
*/
public setPrice(price: number) {
this.token.price = price;
}
/**
*
*
* @param {string} item code to idntify the item they are buying
* @memberof TransactIoMsg
*/
public setItem(item: string) {
this.token.item = item;
}
/**
*
*
* @param {string} item code to idntify the item they are buying
* @memberof TransactIoMsg
*/
public setThumnailImageUrl(url: string) {
this.token.img = url;
}
/**
*
*
* @param {string} uid Unique transaction ID to track on your site.
* @memberof TransactIoMsg
*/
public setUid(uid: string) {
this.token.uid = uid;
}
/**
*
*
* @param {number} recipient user ID on transact
* @memberof TransactIoMsg
*/
public setRecipient(recipient: number) {
this.token.rid = recipient;
}
/**
* @description (Optional) Force the ID of the buyer.
* If you don't specify it will be whoever logs in on transact.io
* If you DO specify, payment will only be accepted from this buyer ID
*
* @param {number} buyerID User ID on transact, who is buying
* @memberof TransactIoMsg
*/
public setBuyer(buyerID: number) {
this.token.bid = buyerID;
}
/**
*
*
* @param {[key: string]: number | string} meta
* @memberof TransactIoMsg
*/
public setMeta(meta: {[key: string]: number | string}) {
this.token.meta = meta;
}
public setMetaKeyValue(key: string, value: number | string) {
if (!this.token.meta) {
this.token.meta = {};
}
this.token.meta.key = value;
}
/**
* @description Check for presense of fields that transact server
* sets. NOTE you still must call verify()
*
* @param {number} buyerID User ID on transact, who is buying
* @memberof TransactIoMsg
*/
public isFromTransactServer(decoded: ITransactJWT) {
if (this.token.tid) {
return true;
}
return false;
}
/**
*
*
* @param {(err, t: string) => void} [callback]
* @returns
* @memberof TransactIoMsg
*/
public getToken(callback?: (err: Error, signature: string) => void): Promise<string> {
return new Promise((resolve, reject) => {
const jwtOptions = {
algorithm: 'HS256',
};
let transactIoError = null;
if (!this.secret || this.secret.length < 1) {
transactIoError = new TransactIoError('Invalid secret', TransactIoErrorCode.INVALID_SECRET, null);
}
if (this.token.price === null || this.token.price < 0
|| this.token.price === undefined || isNaN(this.token.price)) {
transactIoError = new TransactIoError('Invalid Price', TransactIoErrorCode.PRICE_TOO_LOW, null);
}
if (!this.token.rid || isNaN(this.token.rid)) {
transactIoError = new TransactIoError('Invalid recipient ID', TransactIoErrorCode.INVALID_RECIPIENT, null);
}
if (!this.token.title || this.token.title.length < 1) {
transactIoError = new TransactIoError('Invalid title', TransactIoErrorCode.INVALID_RECIPIENT, null);
}
if (transactIoError != null) {
if (callback) {
callback(transactIoError, null);
} else {
reject(transactIoError);
}
return;
}
this.token.iat = Date.now();
const token = Object.assign({}, this.token);
jwt.sign(token, this.secret, jwtOptions, (err: any, signature: string) => {
if (err || !signature) {
transactIoError = new TransactIoError('Signing error', TransactIoErrorCode.SIGNING_ERROR, err);
if (callback) {
callback(transactIoError, null);
} else {
reject(transactIoError);
}
return;
}
if (signature.length > 1000) {
transactIoError = new TransactIoError(
'Signing error: too big, reduce meta-data. sig:' + signature,
TransactIoErrorCode.SIGNATURE_TOO_BIG, null);
if (callback) {
callback(transactIoError, null);
} else {
reject(transactIoError);
}
return;
}
if (callback) {
callback(null, signature);
} else {
resolve(signature);
}
});
});
}
}