@magic.batua/recharge
Version:
The Recharge module manages all the mobile prepaid, datacard and DTH recharge functionalities of the Magic Batua platform.
238 lines (211 loc) • 7.84 kB
text/typescript
/**
* @module MobilePrepaid
* @overview Defines the `MobilePrepaid` class.
*
* @author Animesh Mishra <hello@animesh.ltd>
* @copyright © Animesh Ltd. All Rights Reserved.
*/
import * as Request from "request-promise-native"
import * as Telecom from "./TelecomCircle"
import * as RechargeError from "../RechargeError"
import { Operator } from "../Operator"
import { RIPCreds } from "../RIPCreds"
import { MobilePlan } from "./MobilePlan"
import { RechargeBill } from "../../index"
import { ExternalError } from "@magic.batua/error"
import { StatusResponse } from "../StatusResponse"
/**
* Response sent by Rocket in Pocket API when querying the account info, i.e.,
* the circle and mobile operator a given phone number belongs to.
*/
interface FindOperatorResponse {
operator_circle: {
circle_code: string,
circle_name: string
},
operator_code: string,
operator_name: string
}
/** Response returned by `MobileRecharge.GetPlans()` method. */
export interface GetPlanResponse {
operator: Operator,
circle: Telecom.Circle,
phone: string
plans: Array<MobilePlan>
}
/**
* Encapsulates all the mobile rechage functionalities.
*/
export class MobilePrepaid {
public operator: Operator
public circle: Telecom.Circle
public plan: MobilePlan
public phone: string
public constructor(json: GetPlanResponse, plan: MobilePlan) {
this.operator = json.operator
this.circle = json.circle
this.plan = plan
this.phone = json.phone
}
/**
* Carries out the mobile recharge operation as specified.
*
* @param creds Merchant credentials to access Rocket in Pocket API
* @param transactionID Transaction ID set by the Magic Transaction module
*/
public async Recharge(creds: RIPCreds, transactionID: string, live: boolean = false): Promise<RechargeBill> {
let options = {
method: "GET",
uri: `https://${creds.baseURL}/recharge/mobile`,
headers: {
Accept: "application/json"
},
qs: {
client_id: creds.merchantID,
client_key: creds.merchantKey,
msisdn: this.phone,
operator_code: this.operator.code,
amount: this.plan.amount,
live: live,
client_order_id: transactionID
}
}
let response = await Request(options)
response = JSON.parse(response)
let error = RechargeError.Check(response)
if(error) { throw error }
return new RechargeBill(this, response)
}
//
// Static Methods
//
/**
* Checks status of a previously submitted recharge request. We make use of Rocket in
* Pocket callbacks for status updates. So this is largely implemented as a backup in
* case RIP callback systems fail.
*
* @param transactionID Magic Batua transaction ID of the recharge request
*/
public static async CheckStatus(creds: RIPCreds, transactionID: string): Promise<StatusResponse> {
let options = {
method: "GET",
uri: `https://${creds.baseURL}/recharge/order`,
headers: {
Accept: "application/json"
},
qs: {
client_order_id: transactionID
}
}
let response = await Request(options)
response = JSON.parse(response)
let error = RechargeError.Check(response)
if(error) { throw error }
return {
operatorReference: response.opr_transid,
vendorReference: response.rocket_trans_id,
status: response.status,
date: response.datetime
}
}
/**
* Fetches a list of all mobile rechage operators supported by the Rocket in Pocket
* API. The result is an array of `Operator` types.
*
* @param creds Merchant credentials to connect with Rocket in Pocket API
* @returns An array of operators
*/
public static async AllOperators(creds: RIPCreds): Promise<Array<Operator>> {
let options = {
method: "GET",
uri: `https://${creds.baseURL}/operators/mobile`,
headers: {
Accept: "application/json"
},
qs: {
client_id: creds.merchantID,
client_key: creds.merchantKey
}
}
let response = await Request(options)
response = JSON.parse(response)
let error = RechargeError.Check(response)
if(error) { throw error }
let mobileOperators = Array<Operator>()
for(var operator of response) {
mobileOperators.push(new Operator(operator))
}
return mobileOperators
}
/**
* Fetches operator and telecom circle info for the given phone number.
*
* @param phone Phone number to be queried
* @param creds Merchant credentials to access Rocket in Pocket API
*
* @returns Operator and circle codes for the given mobile number
*/
public static async FindOperator(phone: string, creds: RIPCreds): Promise<FindOperatorResponse> {
// Get operator for the given phone number
let options = {
method: "GET",
uri: `https://${creds.baseURL}/operators/mobile/+91${phone}`,
headers: {
Accept: "application/json"
},
qs: {
client_id: creds.merchantID,
client_key: creds.merchantKey
}
}
let response = await Request(options)
response = JSON.parse(response)
let error = RechargeError.Check(response)
if(error) { throw error }
return response[0] as FindOperatorResponse
}
/**
* Returns plans for the given phone number. To do this, it first looks up the
* operator and circle information for the user account. Then it calls Rocket in
* Pocket's fetch plan API.
*
* @param phone Phone number to be recharged
* @param creds Merchant credentials for accessing Rocket in Pocket API
*/
public static async GetPlans(phone: string, creds: RIPCreds): Promise<GetPlanResponse> {
// Get all mobile recharge operators
let allOperators = await MobilePrepaid.AllOperators(creds)
// Get operator and circle info for user's phone number
let accountInfo = await MobilePrepaid.FindOperator(phone, creds)
// Get circle
let circle = Telecom.CircleWithCode(accountInfo.operator_circle.circle_code)
// Get operator
let operator = Operator.WithCode(accountInfo.operator_code, allOperators)
if(circle == null || operator == null) {
throw new ExternalError("Couldn't fetch plan info automatically.", "Rocket in Pocket", "Ask the user for operator/circle info instead.")
}
// Get plans
let options = {
method: "GET",
uri: `https://${creds.baseURL}/operators/${operator.code}/plans`,
headers: {
Accept: "application/json"
},
qs: {
client_id: creds.merchantID,
client_key: creds.merchantKey,
circle: circle.code
}
}
let response = await Request(options)
response = JSON.parse(response)
let error = RechargeError.Check(response)
if(error) { throw error }
return {
operator: operator,
circle: circle,
phone: phone,
plans: MobilePlan.InitFromList(response)
}
}
}