Skip to content

Commit

Permalink
fixed more stk-push errorrs
Browse files Browse the repository at this point in the history
  • Loading branch information
amosmachora committed Dec 26, 2023
1 parent 6a136e0 commit d2a300c
Show file tree
Hide file tree
Showing 8 changed files with 130 additions and 97 deletions.
3 changes: 2 additions & 1 deletion .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ index.css
index.ts
tailwind.config.js
tsconfig.json
types.ts
types.ts
src/
4 changes: 2 additions & 2 deletions src/access-token.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { AccessTokenResponse } from "../types";

export const generateAccessToken = async (): Promise<AccessTokenResponse> => {
const credentials = `${CONSUMER_KEY}:${CONSUMER_SECRET}`;
const encodedCredentials = btoa(credentials);
const encodedAuthString = Buffer.from(credentials).toString("base64");

const token: AccessTokenResponse = cache.get("act");

Expand All @@ -18,7 +18,7 @@ export const generateAccessToken = async (): Promise<AccessTokenResponse> => {
`${BASE_URL}/oauth/v1/generate?grant_type=client_credentials`,
{
headers: {
Authorization: `Bearer ${encodedCredentials}`,
Authorization: `Basic ${encodedAuthString}`,
"Access-Control-Allow-Origin": "*",
},
}
Expand Down
15 changes: 10 additions & 5 deletions src/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,20 @@ export const CONSUMER_SECRET = assertValue(
);

export const BUSINESS_SHORT_CODE = assertValue(
process.env.BUSINESS_SHORT_CODE,
"Missing environment variable: BUSINESS_SHORT_CODE"
process.env.MPESA_BUSINESS_SHORT_CODE,
"Missing environment variable: MPESA_BUSINESS_SHORT_CODE"
);

export const PRODUCTION_PASS_KEY =
export const MPESA_TRANSACTION_TYPE = assertValue(
process.env.MPESA_TRANSACTION_TYPE,
"Missing environment variable: MPESA_TRANSACTION_TYPE"
);

export const PASSKEY =
ENVIRONMENT === "production"
? assertValue(
process.env.PRODUCTION_PASS_KEY,
"Missing environment variable: PRODUCTION_PASS_KEY"
process.env.MPESA_API_PASS_KEY,
"Missing environment variable: PASSKEY"
)
: null;

Expand Down
33 changes: 17 additions & 16 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ import { generateAccessToken } from "./access-token";
export const getStateOfALNMOnlinePayment = async (
stateOfALNMOnlinePaymentBody: StateOfALNMOnlinePaymentBody
): Promise<StateOfALNMOnlinePaymentResponse> => {
const accessToken = await generateAccessToken();
const { access_token } = await generateAccessToken();

try {
const res: StateOfALNMOnlinePaymentResponse = await axios.post(
`${BASE_URL}/mpesa/stkpushquery/v1/query`,
stateOfALNMOnlinePaymentBody,
{
headers: {
Authorization: `Bearer ${accessToken}`,
Authorization: `Bearer ${access_token}`,
},
}
);
Expand All @@ -51,15 +51,15 @@ export const getStateOfALNMOnlinePayment = async (
export const registerC2BUrl = async (
registerUrlBody: RegisterUrlBody
): Promise<RegisterUrlResponse> => {
const accessToken = await generateAccessToken();
const { access_token } = await generateAccessToken();

try {
const res: RegisterUrlResponse = await axios.post(
`${BASE_URL}/mpesa/c2b/v1/registerurl`,
registerUrlBody,
{
headers: {
Authorization: `Bearer ${accessToken}`,
Authorization: `Bearer ${access_token}`,
},
}
);
Expand All @@ -75,15 +75,15 @@ export const registerC2BUrl = async (
export const b2cPaymentRequest = async (
b2CBody: B2CRequestBody
): Promise<B2CRequestResponse> => {
const accessToken = await generateAccessToken();
const { access_token } = await generateAccessToken();

try {
const res: B2CRequestResponse = await axios.post(
`${BASE_URL}/mpesa/b2c/v1/paymentrequest`,
b2CBody,
{
headers: {
Authorization: `Bearer ${accessToken}`,
Authorization: `Bearer ${access_token}`,
},
}
);
Expand All @@ -98,15 +98,15 @@ export const b2cPaymentRequest = async (
export const b2bPaymentRequest = async (
body: BusinessRequestBody
): Promise<BusinessRequestResponse> => {
const accessToken = await generateAccessToken();
const { access_token } = await generateAccessToken();

try {
const res: BusinessRequestResponse = await axios.post(
`${BASE_URL}/mpesa/b2b/v1/paymentrequest`,
body,
{
headers: {
Authorization: `Bearer ${accessToken}`,
Authorization: `Bearer ${access_token}`,
},
}
);
Expand All @@ -121,15 +121,15 @@ export const b2bPaymentRequest = async (
export const getTransactionStatus = async (
transactionStatusBody: TransactionStatusBody
): Promise<TransactionStatusResponse> => {
const accessToken = await generateAccessToken();
const { access_token } = await generateAccessToken();

try {
const res: TransactionStatusResponse = await axios.post(
`${BASE_URL}/mpesa/transactionstatus/v1/query`,
transactionStatusBody,
{
headers: {
Authorization: `Bearer ${accessToken}`,
Authorization: `Bearer ${access_token}`,
},
}
);
Expand All @@ -144,15 +144,15 @@ export const getTransactionStatus = async (
export const getAccountBalance = async (
accountBalance: AccountBalanceBody
): Promise<AccountBalanceResponse> => {
const accessToken = await generateAccessToken();
const { access_token } = await generateAccessToken();

try {
const res: AccountBalanceResponse = await axios.post(
`${BASE_URL}/mpesa/accountbalance/v1/query`,
accountBalance,
{
headers: {
Authorization: `Bearer ${accessToken}`,
Authorization: `Bearer ${access_token}`,
},
}
);
Expand All @@ -167,15 +167,15 @@ export const getAccountBalance = async (
export const reverseC2BTransaction = async (
body: ReverseC2BTransactionBody
): Promise<ReverseC2BTransactionResponse> => {
const accessToken = await generateAccessToken();
const { access_token } = await generateAccessToken();

try {
const res: ReverseC2BTransactionResponse = await axios.post(
`${BASE_URL}/mpesa/reversal/v1/request`,
body,
{
headers: {
Authorization: `Bearer ${accessToken}`,
Authorization: `Bearer ${access_token}`,
},
}
);
Expand All @@ -190,15 +190,15 @@ export const reverseC2BTransaction = async (
export const remitTax = async (
body: TaxRemittanceBody
): Promise<TaxRemittanceResponse> => {
const accessToken = await generateAccessToken();
const { access_token } = await generateAccessToken();

try {
const res: TaxRemittanceResponse = await axios.post(
`${BASE_URL}/mpesa/b2b/v1/remittax`,
body,
{
headers: {
Authorization: `Bearer ${accessToken}`,
Authorization: `Bearer ${access_token}`,
},
}
);
Expand All @@ -212,3 +212,4 @@ export const remitTax = async (

export { stkPushRequest } from "./stk-push";
export { QRCodeDisplay } from "../components/QRCodeDisplay";
export * from "../types";
66 changes: 40 additions & 26 deletions src/stk-push.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,39 @@
import axios from "axios";
import { STKPushBody, STKPushResponse } from "../types";
import { generateTimestamp, generatePassword } from "../util/utils";
import {
BASE_URL,
BUSINESS_SHORT_CODE,
ENVIRONMENT,
PRODUCTION_PASS_KEY,
} from "./env";
AccountReference,
Amount,
CallBackURL,
PhoneNumber,
STKPushBody,
STKPushResponse,
TransactionDesc,
TransactionType,
} from "../types";
import { generateTimestamp, generatePassword } from "../util/utils";
import { BASE_URL, BUSINESS_SHORT_CODE, ENVIRONMENT, PASSKEY } from "./env";
import { generateAccessToken } from "./access-token";

export const stkPushRequest = async (
phoneNumber: string,
amount: string,
callbackURL: string,
transactionDesc: string,
transactionType: "CustomerPayBillOnline" | "CustomerBuyGoodsOnline"
) => {
export const stkPushRequest = async ({
phoneNumber,
amount,
callbackURL,
transactionDesc,
accountReference,
}: {
phoneNumber: PhoneNumber;
amount: Amount;
callbackURL: CallBackURL;
transactionDesc: TransactionDesc;
accountReference: AccountReference;
}) => {
try {
const timestamp = generateTimestamp();
const password =
ENVIRONMENT === "production"
? generatePassword(
BUSINESS_SHORT_CODE!,
PRODUCTION_PASS_KEY!,
timestamp
)
: "MTc0Mzc5YmZiMjc5ZjlhYTliZGJjZjE1OGU5N2RkNzFhNDY3Y2QyZTBjODkzMDU5YjEwZjc4ZTZiNzJhZGExZWQyYzkxOTIwMTYwMjE2MTY1NjI3";

const password = generatePassword(
BUSINESS_SHORT_CODE!,
PASSKEY!,
timestamp
);

const stkPushBody: STKPushBody = {
BusinessShortCode: BUSINESS_SHORT_CODE!,
Expand All @@ -34,26 +42,32 @@ export const stkPushRequest = async (
Password: password,
PartyA: phoneNumber,
PhoneNumber: phoneNumber,
Amount: amount,
Amount: ENVIRONMENT === "production" ? amount : "1",
CallBackURL: callbackURL,
TransactionDesc: transactionDesc,
TransactionType: transactionType,
TransactionType: process.env
.MPESA_TRANSACTION_TYPE as unknown as TransactionType,
AccountReference: accountReference,
};

const accessToken = generateAccessToken();
console.log(stkPushBody);

const accessTokenResponse = await generateAccessToken();

const res: STKPushResponse = await axios.post(
`${BASE_URL}/mpesa/stkpush/v1/processrequest`,
stkPushBody,
{
headers: {
Authorization: `Bearer ${accessToken}`,
Authorization: `Bearer ${accessTokenResponse.access_token}`,
},
}
);

return res;
} catch (err: any) {
console.error(err);

throw new Error(
`Error occurred with status code ${err.response?.status}, ${err.response?.statusText}`
);
Expand Down
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */

/* Emit */
// "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
"declaration": true /* Generate .d.ts files from TypeScript and JavaScript files in your project. */,
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */
Expand Down
Loading

0 comments on commit d2a300c

Please sign in to comment.