Skip to content

Commit

Permalink
Merge pull request #103 from VictorKabata/develop
Browse files Browse the repository at this point in the history
Develop -> Main
  • Loading branch information
VictorKabata authored May 2, 2024
2 parents afbeef8 + e01b438 commit 7c006e4
Show file tree
Hide file tree
Showing 33 changed files with 438 additions and 221 deletions.
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[*.{kt,kts}]
disabled_rules = import-ordering, experimental:argument-list-wrapping,experimental:package-name
disabled_rules = import-ordering, experimental:argument-list-wrapping, package-name
insert_final_newline = true
25 changes: 25 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
### Description
<!-- Describe the purpose and changes introduced by this pull request. -->

### Issue
<!-- Link to the related issue(s) if applicable. -->

### Changes Made
<!-- List the main changes made in this pull request. -->

### Screenshots / GIFs
<!-- Add any relevant screenshots or GIFs showcasing the changes (if applicable). -->

### Checklist
<!-- Mark the completed items with [x] and provide any additional comments when necessary. -->
- [] I have run the gradle command: `./gradlew clean build`
- [] I have added or updated relevant tests.
- [] I have updated the documentation. <!--(if applicable)-->
- [] I have ensured code style consistency by running the gradle command: `./gradlew :daraja:ktlintCheck :daraja:detekt` .
- [] I have addressed any potential compatibility issues.
- [] I have considered backward compatibility. <!--(if applicable)-->

### Additional Notes
<!-- Add any other relevant information or notes that may be helpful for the code review. -->

<!-- Feel free to add any additional sections that may be specific to your project. -->
3 changes: 2 additions & 1 deletion .github/workflows/maintenance.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
name: Maintenance

on:
workflow_dispatch:
schedule:
- cron: 00 00 30 * * # At 00:00 on 30th every month

Expand All @@ -24,7 +25,7 @@ jobs:
run: chmod +x ./gradlew

- name: Check for release dependencies
run: ./gradlew :daraja:dependencyUpdates -Drevision=release -DoutputFormatter=html -DreportfileName=dependencies_report -DoutputDir=build/reports --stacktrace
run: ./gradlew :daraja:dependencyUpdates -Drevision=release -DoutputFormatter=html -DreportfileName=dependencies_report --stacktrace

- name: Upload dependencies report artifact
uses: actions/upload-artifact@v3
Expand Down
96 changes: 70 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,44 @@
## Table of Content

- [Prerequisite](#prerequisite)
- [Features](#features)
- [Usage](#usage)
- [Android - Kotlin](#android---kotlin)
- [Setting Up](#setting-up)
- [Request Access Token](#request-access-token)
- [Initiate M-Pesa Express STK Request](#initiate-m-pesa-express-stk-request)
- [Query M-Pesa Transaction](#query-m-pesa-transaction)
- [Customer To Business(C2B)](#customer-to-businessc2b)
- [iOS - Swift](#ios---swift)
- [Setting Up](#setting-up-1)
- [Request Access Token](#request-access-token)
- [Initiate M-Pesa Express STK Request](#initiate-m-pesa-express-stk-request-1)
- [Query M-Pesa Transaction](#query-m-pesa-transaction-1)
- [Customer To Business(C2B)](#customer-to-businessc2b)


## Prerequisite

To get started, you’ll need to create an account on the Daraja API portal to use the Daraja API. [How to get started with Daraja API](https://developer.safaricom.co.ke/Documentation).

After successfully creating an account on the Daraja API portal and creating a new Daraja app, you’ll need to add your ___consumer key___, ___consumer secret___ and ___pass key___ obtained from the Daraja API portal to your project.

## Features

The SDK offers the following functionalities from the Daraja API:

- [x] Authorization - Gives you a time bound access token to call allowed APIs.
- [x] M-Pesa Express - Merchant initiated online payments.
- [x] Customer To Business (C2B)
- [ ] Business To Customer (B2C) - Transact between an M-Pesa short code to a phone number registered on M-Pesa.
- [x] Transaction Status - Check the status of a transaction.
- [ ] Account Balanace - Enquire the balance on an M-Pesa BuyGoods (Till Number)
- [ ] Reversal - Reverses an M-Pesa transaction.
- [ ] Tax Remittance - This API enables businesses to remit tax to Kenya Revenue Authority (KRA).
- [ ] Business Pay Bill - Pay bills directly from your business account to a pay bill number, or a paybill store.
- [ ] Business Buy Goods - Pay for goods and services directly from your business account to a till number or merchant store number.


## Usage

# Android - Kotlin <img src="assets/kotlin_logo.png" width="34" />
Expand Down Expand Up @@ -65,15 +85,7 @@ After successfully creating an account on the Daraja API portal and creating a n

- Add your consumer secret, consumer key and pass key to your project. You can get them from the [Daraja API portal](https://developer.safaricom.co.ke/MyApps).

```Kotlin
object Constants {
const val CONSUMER_SECRET="your_consumer_secret"
const val CONSUMER_KEY="your_consumer_key"
const val PASS_KEY="your_pass_key"
}
```

> You should not add your daraja API environment variables in a production application because it is a vulnerability to expose your environment secrets/variables in your version control system. Ideally, you should add them to your `Local.properties` files as demonstrated in the [sample](https://github.com/VictorKabata/DarajaMultiplatform/tree/main/app-android) android application.
> You should not add your daraja API environment variables in a production application because it is a vulnerability to expose your environment secrets/variables in your version control system. Ideally, you should add them to your `local.properties` files as demonstrated in the [sample](https://github.com/VictorKabata/DarajaMultiplatform/tree/main/app-android) android application.
- Create an instance of the Daraja object by passing the daraja environment variables. The daraja object provides functions to request for an access token and initiate M-Pesa express STK request.

Expand All @@ -88,14 +100,14 @@ val daraja: Daraja = Daraja.Builder()

> Network logging is enabled by default when using Daraja Multiplatform. in sandbox/testing mode. The logs can be accessed from the logcat in Android Studio under the `Daraja Multiplatform` tag.
> Network logs are strictly disabled in production mode.
> Network logs are disabled in production mode.
### Request Access Token

- To request an access token from Daraja API, invoke the `requestAccessToken` function:
- To request an access token from Daraja API, invoke the `authorization` function:

```Kotlin
val accessTokenResult: DarajaResult<DarajaToken> = daraja.requestAuthToken()
val accessTokenResult: DarajaResult<DarajaToken> = daraja.authorization()

accessTokenResult
.onSuccess { accessToken ->
Expand All @@ -108,10 +120,10 @@ accessTokenResult

### Initiate M-Pesa Express STK Request

- To initiate M-Pesa Express(Lipa na M-Pesa Online) STK request, invoke the `initiateDarajaStk` function:
- To initiate M-Pesa Express(Lipa na M-Pesa Online) STK request, invoke the `mpesaExpress` function:

```Kotlin
val darajaPaymentResponse: DarajaResult<DarajaPaymentResponse> = daraja.initiateDarajaStk(
val darajaPaymentResponse: DarajaResult<DarajaPaymentResponse> = daraja.mpesaExpress(
businessShortCode = "174379",
amount = 1,
phoneNumber = "07xxxxxxxx",
Expand All @@ -123,31 +135,63 @@ val darajaPaymentResponse: DarajaResult<DarajaPaymentResponse> = daraja.initiate
darajaPaymentResponse
.onSuccess { paymentResponse ->
// Successfully requested M-Pesa STK request
}
.onFailure { error ->
}.onFailure { error ->
// Failed to request M-Pesa STK
}
```

### Query M-Pesa Transaction

- To check the status of an M-pesa transaction, invoke the `queryMpesaTransaction` function:
- To check the status of an M-pesa transaction, invoke the `transactionStatus` function:

```Kotlin
val darajaTransactionResponse: DarajaResult<DarajaTransactionResponse> = daraja.queryMpesaTransaction(
val darajaTransactionResponse: DarajaResult<DarajaTransactionResponse> = daraja.transactionStatus(
businessShortCode = "174379",
checkoutRequestID = "ws_CO_20122022180112029708374149"
)

darajaTransactionResponse
.onSuccess { transactionResponse ->
// Successfully fetched M-pesa transaction status
}
.onFailure { error ->
}.onFailure { error ->
// Failure fetching M-pesa transaction status
}
```

### Customer To Business(C2B)
- To register the C2B validation and confirmation URL, invoke the `c2bRegistration` function:
```kotlin
val darajaC2BRegistrationResponse:DarajaResult<C2BResponse> = daraja.c2bRegistration(
confirmationURL = "https://mydomain.com/confirmation",
responseType = C2BResponseType.COMPLETED, // C2BResponseType.CANCELLED
businessShortCode = 600981,
validationURL = "https://mydomain.com/validation"
)

darajaC2BRegistrationResponse.onSuccess {
// Successfully registered confirmation and validation URL
}.onFailure{
// Failure registering confirmation and validation URL
}

```
- To initiate a Customer to Business paybill, invoke the `c2b` function:
```kotlin
val c2bResponse: DarajaResult<C2BResponse> = daraja.c2b(
amount = 1,
billReferenceNumber = "600977",
transactionType = DarajaTransactionType.CustomerBuyGoodsOnline, // DarajaTransactionType.CustomerPayBillOnline
phoneNumber = "0708374149",
businessShortCode = "600977" //Optional when using CustomerBuyGoodsOnline
)

c2bResponse.onSuccess {
// Successfully invoked C2B request
}.onFailure{
// Failure invoking C2B request
}
```

# iOS - Swift <img src="assets/swift_logo.png" width="40" />

### Setting Up
Expand Down Expand Up @@ -176,10 +220,10 @@ var daraja=Daraja(
> Network logs are strictly disabled in production mode ie. DarajaEnvironment.productionEnvironment
### Request Access Token
- To request an access token from Daraja API, invoke the `requestAccessToken` function:
- To request an access token from Daraja API, invoke the `authorization` function:

```swift
var accessTokenResult = daraja.requestAccessToken()
var accessTokenResult = daraja.authorization()

accessTokenResult.onSuccess(action: { accessToken in
// Successfully fetched daraja access token
Expand All @@ -192,10 +236,10 @@ accessTokenResult.onSuccess(action: { accessToken in

### Initiate M-Pesa Express STK Request

- To initiate M-Pesa Express(Lipa na M-Pesa Online) STK request, invoke the `initiateDarajaStk` function:
- To initiate M-Pesa Express(Lipa na M-Pesa Online) STK request, invoke the `mpesaExpress` function:

```swift
var darajaResponse = daraja.initiateMpesaExpressPayment(
var darajaResponse = daraja.mpesaExpress(
businessShortCode: "174379",
amount: 1,
phoneNumber: "07xxxxxxxx",
Expand All @@ -216,10 +260,10 @@ var darajaResponse = daraja.initiateMpesaExpressPayment(

### Query M-Pesa Transaction

- To check the status of an M-pesa transaction, invoke the `queryMpesaTransaction` function:
- To check the status of an M-pesa transaction, invoke the `transactionStatus` function:

```swift
var darajaTransactionResponse = daraja.queryMpesaTransaction(
var darajaTransactionResponse = daraja.transactionStatus(
businessShortCode: "174379", checkoutRequestID: "ws_CO_20122022180112029708374149")

darajaTransactionResponse.onSuccess(action: { data in
Expand Down
2 changes: 1 addition & 1 deletion app-android/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ android {
compose = true
}
composeOptions {
kotlinCompilerExtensionVersion = "1.4.6"
kotlinCompilerExtensionVersion = "1.5.7"
}
packagingOptions {
resources {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.vickbt.app_android.ui.screens.home

import android.util.Log
import android.widget.Toast
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
Expand Down Expand Up @@ -164,6 +165,7 @@ fun HomeScreen(viewModel: HomeViewModel = get()) {
Toast.makeText(context, "Success: $it", Toast.LENGTH_SHORT).show()
}?.onFailure {
Toast.makeText(context, "Error: ${it.errorMessage}", Toast.LENGTH_SHORT).show()
Log.e("VicKbt", "Error: $it")
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@ package com.vickbt.app_android.ui.screens.home
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.vickbt.darajakmp.Daraja
import com.vickbt.darajakmp.network.models.DarajaPaymentResponse
import com.vickbt.darajakmp.network.models.MpesaExpressResponse
import com.vickbt.darajakmp.utils.DarajaResult
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch

class HomeViewModel constructor(private val daraja: Daraja) : ViewModel() {

private val _mpesaResponse = MutableStateFlow<DarajaResult<DarajaPaymentResponse>?>(null)
private val _mpesaResponse = MutableStateFlow<DarajaResult<MpesaExpressResponse>?>(null)
val mpesaResponse get() = _mpesaResponse.asStateFlow()

fun initiateMpesaPayment(
Expand All @@ -38,7 +38,7 @@ class HomeViewModel constructor(private val daraja: Daraja) : ViewModel() {
callbackUrl: String,
accountReference: String
) = viewModelScope.launch {
val response = daraja.initiateMpesaExpressPayment(
val response = daraja.mpesaExpress(
businessShortCode = businessShortCode.trim(),
amount = amount,
phoneNumber = phoneNumber.trim(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ private val LightColorScheme = lightColorScheme(
onTertiary = Color.White,
onBackground = Color(0xFF1C1B1F),
onSurface = Color(0xFF1C1B1F),
*/
*/
)

@Composable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,5 @@ val Typography = Typography(
lineHeight = 16.sp,
letterSpacing = 0.5.sp
)
*/
*/
)
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ fun HomeScreen() {
}

fun initiateMpesaStk(daraja: Daraja, tillNumber: String, amount: Int, phoneNumber: String) {
daraja.initiateMpesaExpressPayment(
daraja.mpesaExpress(
businessShortCode = tillNumber,
amount = amount,
phoneNumber = phoneNumber,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ private val LightColorScheme = lightColors(
onTertiary = Color.White,
onBackground = Color(0xFF1C1B1F),
onSurface = Color(0xFF1C1B1F),
*/
*/
)

@Composable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,5 @@ val Typography = Typography(
lineHeight = 16.sp,
letterSpacing = 0.5.sp
)
*/
*/
)
3 changes: 1 addition & 2 deletions app-iOS/app-iOS/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ func initiateMpesaPayment(daraja:Daraja,
transactionDesc: String,
callbackUrl: String,
accountReference: String){

let response=daraja.initiateMpesaExpressPayment(businessShortCode: businessShortCode, amount: amount, phoneNumber: phoneNumber,transactionType: DarajaTransactionType.customerpaybillonline, transactionDesc: "M-Pesa payment", callbackUrl: "https://mydomain.com/path", accountReference: "Daraja KMP iOS")

response.onSuccess(action: {data in
Expand All @@ -89,8 +90,6 @@ func initiateMpesaPayment(daraja:Daraja,
.onFailure(action: {error in
print(error)
})

print(response)
}

struct ContentView_Previews: PreviewProvider {
Expand Down
7 changes: 4 additions & 3 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ plugins {
alias(libs.plugins.jvm) apply false
alias(libs.plugins.nativeCocoapod) apply false

// alias(libs.plugins.ktLint)
alias(libs.plugins.ktLint)
alias(libs.plugins.detekt)
alias(libs.plugins.spotless)
}

subprojects {
/*apply(plugin = "org.jlleitschuh.gradle.ktlint")
apply(plugin = "org.jlleitschuh.gradle.ktlint")
ktlint {
debug.set(true)
verbose.set(true)
Expand All @@ -22,8 +22,9 @@ subprojects {
filter {
enableExperimentalRules.set(true)
exclude { projectDir.toURI().relativize(it.file.toURI()).path.contains("/generated/") }
include("**/kotlin/**")
}
}*/
}

apply(plugin = "io.gitlab.arturbosch.detekt")
detekt {
Expand Down
Loading

0 comments on commit 7c006e4

Please sign in to comment.