diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml new file mode 100644 index 00000000..635c36d4 --- /dev/null +++ b/.github/workflows/documentation.yml @@ -0,0 +1,37 @@ +name: Deploy Documentation + +on: + workflow_dispatch: + push: + branches: + - main +permissions: + contents: write + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: 3.x + + - name: Set up cache + uses: actions/cache@v2 + with: + key: ${{ github.ref }} + path: .cache + + - name: Install MkDocs-Material + run: pip install mkdocs-material + + - name: Install Pillow CairoSVG + run: pip install pillow cairosvg + + - name: Deploy GH-Page + run: mkdocs gh-deploy --force \ No newline at end of file diff --git a/.github/workflows/publish_kmp_lib.yml b/.github/workflows/publish_kmp_lib.yml index 19fa1e66..80a975f1 100644 --- a/.github/workflows/publish_kmp_lib.yml +++ b/.github/workflows/publish_kmp_lib.yml @@ -40,6 +40,7 @@ jobs: POM_NAME: ${{ secrets.POM_NAME }} POM_DESCRIPTION: ${{ secrets.POM_DESCRIPTION }} POM_GROUPID: ${{ secrets.POM_GROUPID }} + POM_ARTIFACTID: ${{secrets.POM_ARTIFACTID}} POM_URL: ${{ secrets.POM_URL }} POM_DEVELOPER_ID: ${{ secrets.POM_DEVELOPER_ID }} POM_DEVELOPER_NAME: ${{ secrets.POM_DEVELOPER_NAME }} diff --git a/.github/workflows/publish_swift_package.yml b/.github/workflows/publish_swift_package.yml index 0be89cf1..7d2013e8 100644 --- a/.github/workflows/publish_swift_package.yml +++ b/.github/workflows/publish_swift_package.yml @@ -44,7 +44,7 @@ jobs: uses: actions/checkout@v4 - name: Download directory with swift package - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: swiftpackage path: swiftpackage diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..319a0d1a --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2022 Victor Kabata + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md index 14940062..e777bf0d 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,6 @@

-## ⚠️Work in progress - Sandbox Mode⚠️ - [Kotlin multiplatform](https://kotlinlang.org/docs/multiplatform.html) wrapper for Mpesa API dubbed [_Daraja API_](https://developer.safaricom.co.ke/) (Daraja means bridge in Swahili) that supports integration with your Android(Kotlin/Java), iOS(Swift) and JVM applications. @@ -16,27 +14,16 @@ supports integration with your Android(Kotlin/Java), iOS(Swift) and JVM applicat > M-PESA is a mobile money transfer service in Kenya that allows users to store and transfer money > through their mobile phones. +> > [!WARNING] +> Daraja Multiplatform is under heavy development and, despite being heavily tested, its API isn't yet stabilized; _breaking changes +> might happen on minor releases._ However, we will always provide migration guides. +> +> Report any issue or bug in the GitHub repository. + ## 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) - - [Dynamic QR](#generate-dynamic-qr-code) - - [Query M-Pesa Transaction](#query-m-pesa-transaction) - - [Customer To Business(C2B)](#customer-to-businessc2b) - - [Account Balance](#account-balance) - - [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) - - [Dynamic QR](#generate-dynamic-qr-code) - - [Query M-Pesa Transaction](#query-m-pesa-transaction-1) - - [Customer To Business(C2B)](#customer-to-businessc2b) - - [Account Balance](#account-balance) ## Prerequisite @@ -67,358 +54,7 @@ The SDK offers the following functionalities from the Daraja API: - [ ] Business Buy Goods - Pay for goods and services directly from your business account to a till number or merchant store number. -## Usage - -# Android - Kotlin - -### Setting Up - -- In your android application project-level gradle file add the following dependency: - -
-Kotlin - -```Kotlin - dependencies { - implementation("io.github.victorkabata:daraja-multiplatform:0.9.3") -} -``` - -
- -
-Groovy - -```Groovy - dependencies { - implementation 'io.github.victorkabata:daraja-multiplatform:0.9.3' -} -``` - -
- -- 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). - -> 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. - -```Kotlin -val daraja: Daraja = Daraja.Builder() - .setConsumerSecret("your_consumer_secret") - .setConsumerKey("your_consumer_key") - .setPassKey("your_pass_key") - .isProduction() // Optional. Will default to sandbox_mode = true - .build() -``` - -> 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 disabled in production mode. - -### Request Access Token - -- To request an access token from Daraja API, invoke the `authorization` function: - -```Kotlin -val accessTokenResult: DarajaResult = daraja.authorization() - -accessTokenResult - .onSuccess { accessToken -> - // Successfully fetched daraja access token - } - .onFailure { error -> - // Failure fetching daraja access token - } -``` - -### Initiate M-Pesa Express STK Request - -- To initiate M-Pesa Express(Lipa na M-Pesa Online) STK request, invoke the `mpesaExpress` function: - -```kotlin -val darajaPaymentResponse: DarajaResult = daraja.mpesaExpress( - businessShortCode = "174379", - amount = 1, - phoneNumber = "07xxxxxxxx", - transactionDesc = "M-Pesa payment", - callbackUrl = "your_callback_url", - accountReference = "CompanyName" -) - -darajaPaymentResponse.onSuccess { paymentResponse -> - // Successfully requested M-Pesa STK request -}.onFailure { error -> - // Failed to request M-Pesa STK -} -``` - -### Query M-Pesa Express STK - -- To check the status of M-Pesa Express(Lipa na M-Pesa Online) STK request, invoke the `mpesaExpressQuery` function: - -```kotlin -val darajaMpesaExpressQuery:DarajaResult = daraja.mpesaExpressQuery( - businessShortCode = "174379", - timeStamp = "20160216165627", - checkOutRequestID = "ws_CO_260520211133524545" -) - -darajaMpesaExpressQuery.onSuccess{ mpesaExpressQuery-> - // Successfully request M-Pesa STK request status -}.onFailure{ error-> - // Failed to request M-Pesa STK status -} -``` - - - - - -### Customer To Business(C2B) - -- To register the C2B validation and confirmation URL, invoke the `c2bRegistration` function: - -```kotlin -val darajaC2BRegistrationResponse: DarajaResult = 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 = 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 -} -``` - -### Account Balance - -Request the account balance of a short code. This can be used for both B2C, buy goods and pay bill -accounts. - -```kotlin - val accountBalanceResponse = daraja.accountBalance( - initiator = "testapi", - initiatorPassword = "Safaricom999!*!", - partyA = 600987, - identifierType = DarajaIdentifierType.TILL_NUMBER, - queueTimeOutURL = "https://mydomain.com/AccountBalance/queue/", - resultURL = "https://mydomain.com/AccountBalance/result/" -) - -accountBalanceResponse.onSuccess { - // Successfully request account balance -}.onFailure { - // Failed to request account balance -} -``` - -# iOS - Swift - -### Setting Up - -- To add **_DarajaMultiplatform_** package to your Xcode Project, open your Xcode project, navigate - to the File tab within the macOS bar and click **Select Packages** then **Add Package Dependency - **. Enter the package name ie. DarajaMultiplatform or the URL package GitHub URL: - -```curl -https://github.com/VictorKabata/DarajaSwiftPackage.git -``` - -https://github.com/VictorKabata/DarajaSwiftPackage/assets/39780120/b9283612-3c5e-4100-aff8-c2c0d9f31863 - -- 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. - -```swift -var daraja=Daraja( - consumerKey: "your_consumer_key", - consumerSecret: "your_customer_secret", - passKey:"your_pass_key", - environment: DarajaEnvironment.sandboxEnvironment - ) -``` - -> Network logging is enabled by default when using Daraja Multiplatform. in sandbox/testing mode. -> The logs can be accessed from the logs in XCode IDE - -> Network logs are strictly disabled in production mode ie. DarajaEnvironment.productionEnvironment - -### Request Access Token - -- To request an access token from Daraja API, invoke the `authorization` function: - -```swift -var accessTokenResult = daraja.authorization() - -accessTokenResult.onSuccess(action: { accessToken in - // Successfully fetched daraja access token - // Successfully fetched the access token - }).onFailure(action: { error in - // Failure fetching daraja access token - }) -``` - -### Initiate M-Pesa Express STK Request - -- To initiate M-Pesa Express(Lipa na M-Pesa Online) STK request, invoke the `mpesaExpress` function: - -```swift -var darajaResponse = daraja.mpesaExpress( - businessShortCode: "174379", - amount: 1, - phoneNumber: "07xxxxxxxx", - transactionType: DarajaTransactionType.customerpaybillonline, transactionDesc: "M-Pesa payment", - callbackUrl: "https://mydomain.com/path", - accountReference: "Company name") - - darajaResponse.onSuccess(action: { data in - // Successfully requested M-Pesa STK request - }) - .onFailure(action: { error in - // Failed to request M-Pesa STK - }) - -``` - -### Query M-Pesa Express STK - -- To check the status of M-Pesa Express(Lipa na M-Pesa Online) STK request, invoke the `mpesaExpressQuery` function: - -```swift -var mpesaExpressQuery = daraja.mpesaExpressQuery( - businessShortCode: "174379", - timestamp: "20160216165627", - checkoutRequestID: "ws_CO_260520211133524545" -) - -mpesaExpressQuery.onSuccess(action:{ data in -// Successfully requested M-Pesa STK request status -}) -.onFailure(action: {error in -// Failed to request M-Pesa STK status -}) -``` - - - - - - \ No newline at end of file diff --git a/docs/index.md b/docs/index.md index ff324186..48bfceab 100644 --- a/docs/index.md +++ b/docs/index.md @@ -16,19 +16,19 @@ Currently, Daraja Multiplatform supports Kotlin and Swift applications. Core features include: -* [x] Authorization - Gives you a time bound access token to call allowed APIs. -- [x] M-Pesa Express - Merchant initiated online payments. -- [x] M-Pesa Express Query - Check the status of a Lipa Na M-Pesa Online Payment(M-Pesa Express). -- [ ] Dynamic QR - Generates a dynamic M-PESA QR code. -- [ ] Customer To Business (C2B) -- [ ] Business To Customer (B2C) - Transact between an M-Pesa short code to a phone number +* Authorization - Gives you a time bound access token to call allowed APIs. +- M-Pesa Express - Merchant initiated online payments. +- M-Pesa Express Query - Check the status of a Lipa Na M-Pesa Online Payment(M-Pesa Express). +- Dynamic QR - Generates a dynamic M-PESA QR code. +- Customer To Business (C2B) +- Business To Customer (B2C) - Transact between an M-Pesa short code to a phone number registered on M-Pesa. -- [ ] Transaction Status - Check the status of a transaction. -- [ ] Account Balance - 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 +- Transaction Status - Check the status of a transaction. +- Account Balance - 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. +- Business Buy Goods - Pay for goods and services directly from your business account to a till number or merchant store number. diff --git a/mkdocs.yml b/mkdocs.yml index faf9731d..d3aa1c01 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -11,11 +11,14 @@ remote_branch: gh-pages nav: - Overview: index.md - Kotlin SDK: kotlin.md - - Swift SDK: swift.md +# - Swift SDK: swift.md theme: name: material language: en + font: + text: Roboto + code: Roboto Mono features: - navigation.tabs - navigation.sections @@ -29,18 +32,18 @@ theme: - scheme: default media: "(prefers-color-scheme: light)" toggle: - icon: material/brightness-7 + icon: material/weather-night name: Switch to dark theme - primary: teal - accent: purple + primary: green + accent: green - scheme: slate media: "(prefers-color-scheme: dark)" toggle: - icon: material/brightness-4 + icon: material/weather-sunny name: Switch to light theme - primary: teal - accent: lime + primary: green + accent: green markdown_extensions: - pymdownx.highlight: diff --git a/samples/android/app/build.gradle.kts b/samples/android/app/build.gradle.kts index 6f0f9e7d..ef1554c9 100644 --- a/samples/android/app/build.gradle.kts +++ b/samples/android/app/build.gradle.kts @@ -59,11 +59,19 @@ dependencies { implementation(libs.androidx.ui.graphics) implementation(libs.androidx.ui.tooling.preview) implementation(libs.androidx.material3) + + implementation(platform(libs.koin.bom)) + implementation(libs.koin.android) + + implementation("io.github.victorkabata:daraja-multiplatform:0.9.6") + testImplementation(libs.junit) + androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.androidx.espresso.core) androidTestImplementation(platform(libs.androidx.compose.bom)) androidTestImplementation(libs.androidx.ui.test.junit4) + debugImplementation(libs.androidx.ui.tooling) debugImplementation(libs.androidx.ui.test.manifest) } \ No newline at end of file diff --git a/samples/android/app/src/main/AndroidManifest.xml b/samples/android/app/src/main/AndroidManifest.xml index 5885a0c1..1408c004 100644 --- a/samples/android/app/src/main/AndroidManifest.xml +++ b/samples/android/app/src/main/AndroidManifest.xml @@ -2,7 +2,10 @@ + +