Skip to content
Merged
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
15 changes: 12 additions & 3 deletions apps/mno/src/modules/selcom/controllers/selcom.controller.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
import { CreateOrder } from '@flexpay/common';
import { Body, Controller, Post, Res } from '@nestjs/common';
import { CheckoutResponse, ErrorResponse, MnoCheckout } from 'azampay';
import { SelcomService } from '../services/selcom.service';
import { Response } from 'express';
import { SelcomService } from '../services/selcom.service';

@Controller('api')
export class SelcomController {
constructor(private service: SelcomService) {}

@Post('selcomPush')
async mnoCheckout(@Res() res: Response, @Body() payload: MnoCheckout) {
async selcomPush(@Res() res: Response, @Body() payload: MnoCheckout) {
const response: CheckoutResponse | ErrorResponse = await this.service.push(
payload,
);
return res.status(response.statusCode).send(response);
}

@Post('selcomPush')
async selcomCreateOrder(@Res() res: Response, @Body() payload: CreateOrder) {
const response: CheckoutResponse | ErrorResponse =
await this.service.selcomPush(payload);
await this.service.createOrder(payload);
return res.status(response.statusCode).send(response);
}
}
78 changes: 61 additions & 17 deletions apps/mno/src/modules/selcom/services/selcom.service.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
import { APPENV, phoneNumber, requestResource } from '@flexpay/common';
import {
APPENV,
CreateOrder,
phoneNumber,
requestResource,
} from '@flexpay/common';
import { HttpStatus, Injectable } from '@nestjs/common';
import { CheckoutResponse, MnoCheckout, ErrorResponse } from 'azampay';
import * as crypto from 'crypto';

// Types
type SelcomPayload = Record<string, string>;
type Headers = Record<string, string>;
// ======= Config & Execution ======= //
const apiKey = APPENV.SELCOM_APIKEY;
const apiSecret = APPENV.SELCOM_APISECRET;
const baseUrl = APPENV.SELCOM_APIURL;
const vendor = APPENV.SELCOM_VENDOR;
const authorization = Buffer.from(apiKey, 'ascii').toString('base64');

@Injectable()
export class SelcomService {
Expand Down Expand Up @@ -57,7 +68,29 @@ export class SelcomService {
return res;
};

selcomPush = async (
/**
*
* @param payload: CreateOrder
* @returns CheckoutResponse | ErrorResponse
*/

createOrder = async (
payload: CreateOrder,
): Promise<CheckoutResponse | ErrorResponse> => {
const url = `${baseUrl}/checkout/wallet-payment`;
const signedFields = Object.keys(payload).join(',');
const headers: Headers = this.headers(payload as any, signedFields);
const result = await this.sendSelcomRequest(url, payload as any, headers);
console.log(JSON.stringify(result));
return result;
};

/**
* @param request
* @returns CheckoutResponse | ErrorResponse
*/

push = async (
request: MnoCheckout,
): Promise<CheckoutResponse | ErrorResponse> => {
const { valid, withCode } = phoneNumber(request.accountNumber);
Expand All @@ -69,32 +102,46 @@ export class SelcomService {
code: 'FAIL',
} as unknown as CheckoutResponse | ErrorResponse;
}
// ======= Config & Execution ======= //
const apiKey = APPENV.SELCOM_APIKEY;
const apiSecret = APPENV.SELCOM_APISECRET;

const url = `${APPENV.SELCOM_APIURL}/wallet/pushussd`;
// const url = `${APPENV.SELCOM_APIURL}/checkout/wallet-payment`;
const order = await this.createOrder({
order_id: request.externalId,
amount: request.amount,
buyer_email: 'benny@example.com',
buyer_name: 'Benny',
buyer_phone: withCode,
currency: 'TZS',
buyer_remarks: 'None',
merchant_remarks: 'None',
no_of_items: 1,
} as unknown as CreateOrder);
console.log(JSON.stringify(order));

const url = `${baseUrl}/checkout/wallet-payment`;
const payload: SelcomPayload = {
utilityref: APPENV.SELCOM_VENDOR,
utilityref: vendor,
transid: request.externalId,
amount: request.amount,
vendor: APPENV.SELCOM_VENDOR,
vendor,
msisdn: withCode,
order_id: request.externalId,
};

const authorization = Buffer.from(apiKey, 'ascii').toString('base64');
const timestamp = new Date().toISOString();
const signedFields = Object.keys(payload).join(',');
const headers: Headers = this.headers(payload, signedFields);
const result = await this.sendSelcomRequest(url, payload, headers);
console.log(JSON.stringify(result));
return result;
};

headers = (payload: SelcomPayload, signedFields: string): Headers => {
const timestamp = new Date().toISOString();

const digest = this.computeSignature(
payload,
signedFields,
timestamp,
apiSecret,
);

const headers: Headers = {
return {
'Content-Type': 'application/json;charset=utf-8',
Accept: 'application/json',
'Cache-Control': 'no-cache',
Expand All @@ -104,8 +151,5 @@ export class SelcomService {
Timestamp: timestamp,
'Signed-Fields': signedFields,
};
const result = await this.sendSelcomRequest(url, payload, headers);
console.log(JSON.stringify(result));
return result;
};
}
13 changes: 13 additions & 0 deletions libs/common/src/interfaces/shared.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,16 @@ export interface GetManyReqInterface {
page: number;
pageSize: number;
}

export interface CreateOrder {
vendor: string;
order_id: string;
buyer_email: string;
buyer_name: string;
buyer_phone: string;
amount: number;
currency: string;
buyer_remarks: string;
merchant_remarks: string;
no_of_items: number;
}
Loading