diff --git a/.gitignore b/.gitignore index a915fcc..477f734 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ .cxx local.properties gradle.properties +*.hprof \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml index 61a9130..b589d56 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml new file mode 100644 index 0000000..0c0c338 --- /dev/null +++ b/.idea/deploymentTargetDropDown.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml new file mode 100644 index 0000000..25be67b --- /dev/null +++ b/.idea/deploymentTargetSelector.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml index 23a89bb..cb865f6 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -4,18 +4,15 @@ diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml new file mode 100644 index 0000000..8d81632 --- /dev/null +++ b/.idea/kotlinc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/migrations.xml b/.idea/migrations.xml new file mode 100644 index 0000000..f8051a6 --- /dev/null +++ b/.idea/migrations.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index d5d35ec..55c0ec2 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,6 +1,6 @@ - + diff --git a/README.md b/README.md index 2c30830..2ae3425 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,19 @@ # FoodCheckout -A simple application that shows how to integrate the Paystack SDK into your Android app. \ No newline at end of file +A simple application that shows how to integrate the Paystack SDK into your Android app. There's an +accompanying guide that explains how you should go about your integration: + +
+ + +
+ + +# Project Setup +- Clone project and open on Android Studio +- The Java source code is on the `main` branch while the Kotlin is on the `kotlin` branch: + - To use the Kotlin source code: `git checkout kotlin` + - To use the Java source code: `git checkout main` +- Open the `gradle.properties` file and add the following param: + - PSTK_PUBLIC_KEY="your_paystack_public_key" +- Sync project +- Run the project when sync is successful \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 60f4364..9af1a35 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,20 +1,18 @@ plugins { id 'com.android.application' + id 'kotlin-android' } android { - compileSdkVersion 29 - defaultConfig { applicationId "com.paystack.foodcheckout" - minSdkVersion 21 - targetSdkVersion 29 + compileSdk 34 + minSdkVersion 23 + targetSdkVersion 34 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - - buildConfigField("String", "PSTK_PUBLIC_KEY", PSTK_PUBLIC_KEY) } buildTypes { @@ -27,17 +25,25 @@ android { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } + + kotlinOptions { + jvmTarget = '1.8' + } + + namespace 'com.paystack.foodcheckout' } dependencies { - implementation 'androidx.appcompat:appcompat:1.2.0' - implementation 'com.google.android.material:material:1.2.1' - implementation 'androidx.constraintlayout:constraintlayout:2.0.2' - testImplementation 'junit:junit:4.13.1' - androidTestImplementation 'androidx.test.ext:junit:1.1.2' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + implementation 'androidx.core:core-ktx:1.13.1' + implementation 'androidx.appcompat:appcompat:1.6.1' + implementation 'com.google.android.material:material:1.12.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.4' + testImplementation 'junit:junit:4.13.2' + androidTestImplementation 'androidx.test.ext:junit:1.1.5' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' // secondary dependencies - implementation 'co.paystack.android:paystack:3.1.2' + implementation 'com.paystack.android:paystack-ui:0.0.8' } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d666b6a..195ad6e 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,6 +1,5 @@ - + @@ -11,8 +10,8 @@ android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.FoodCheckout"> - - + @@ -20,5 +19,4 @@ - \ No newline at end of file diff --git a/app/src/main/java/com/paystack/foodcheckout/CheckoutActivity.java b/app/src/main/java/com/paystack/foodcheckout/CheckoutActivity.java deleted file mode 100644 index 17a9fc9..0000000 --- a/app/src/main/java/com/paystack/foodcheckout/CheckoutActivity.java +++ /dev/null @@ -1,120 +0,0 @@ -package com.paystack.foodcheckout; - -import android.content.Intent; -import android.os.Bundle; -import android.text.Editable; -import android.text.TextWatcher; -import android.util.Log; -import android.widget.Button; -import android.widget.Toast; - -import androidx.appcompat.app.AppCompatActivity; - -import com.google.android.material.textfield.TextInputLayout; - -import java.util.Objects; - -import co.paystack.android.Paystack; -import co.paystack.android.PaystackSdk; -import co.paystack.android.Transaction; -import co.paystack.android.model.Card; -import co.paystack.android.model.Charge; - -public class CheckoutActivity extends AppCompatActivity { - - private TextInputLayout mCardNumber; - private TextInputLayout mCardExpiry; - private TextInputLayout mCardCVV; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_checkout); - - initializePaystack(); - initializeFormVariables(); - } - - private void initializePaystack() { - PaystackSdk.initialize(getApplicationContext()); - PaystackSdk.setPublicKey(BuildConfig.PSTK_PUBLIC_KEY); - } - - - private void initializeFormVariables() { - mCardNumber = findViewById(R.id.til_card_number); - mCardExpiry = findViewById(R.id.til_card_expiry); - mCardCVV = findViewById(R.id.til_card_cvv); - - // this is used to add a forward slash (/) between the cards expiry month - // and year (11/21). After the month is entered, a forward slash is added - // before the year - - Objects.requireNonNull(mCardExpiry.getEditText()).addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - - } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - - } - - @Override - public void afterTextChanged(Editable s) { - if(s.toString().length() == 2 && !s.toString().contains("/")) { - s.append("/"); - } - } - }); - - Button button = findViewById(R.id.btn_make_payment); - button.setOnClickListener(v -> performCharge()); - } - - private void performCharge() { - Intent intent = getIntent(); - - String cardNumber = mCardNumber.getEditText().getText().toString(); - String cardExpiry = mCardExpiry.getEditText().getText().toString(); - String cvv = mCardCVV.getEditText().getText().toString(); - - String[] cardExpiryArray = cardExpiry.split("/"); - int expiryMonth = Integer.parseInt(cardExpiryArray[0]); - int expiryYear = Integer.parseInt(cardExpiryArray[1]); - int amount = intent.getIntExtra(getString(R.string.meal_name), 0); - amount *= 100; - - Card card = new Card(cardNumber, expiryMonth, expiryYear, cvv); - - Charge charge = new Charge(); - charge.setAmount(amount); - charge.setEmail("customer@email.com"); - charge.setCard(card); - - PaystackSdk.chargeCard(this, charge, new Paystack.TransactionCallback() { - @Override - public void onSuccess(Transaction transaction) { - parseResponse(transaction.getReference()); - } - - @Override - public void beforeValidate(Transaction transaction) { - Log.d("Main Activity", "beforeValidate: " + transaction.getReference()); - } - - @Override - public void onError(Throwable error, Transaction transaction) { - Log.d("Main Activity", "onError: " + error.getLocalizedMessage()); - Log.d("Main Activity", "onError: " + error); - } - - }); - } - - private void parseResponse(String transactionReference) { - String message = "Payment Successful - " + transactionReference; - Toast.makeText(this, message, Toast.LENGTH_LONG).show(); - } -} \ No newline at end of file diff --git a/app/src/main/java/com/paystack/foodcheckout/MainActivity.java b/app/src/main/java/com/paystack/foodcheckout/MainActivity.java deleted file mode 100644 index 88943c4..0000000 --- a/app/src/main/java/com/paystack/foodcheckout/MainActivity.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.paystack.foodcheckout; - -import androidx.appcompat.app.AppCompatActivity; - -import android.content.Intent; -import android.os.Bundle; -import android.util.Log; -import android.view.View; -import android.widget.Button; - -public class MainActivity extends AppCompatActivity { - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); - - int price = 4000; - Button mCheckout = findViewById(R.id.btn_checkout); - - mCheckout.setOnClickListener(v -> { - Intent intent = new Intent(MainActivity.this, CheckoutActivity.class); - intent.putExtra(getString(R.string.meal_name), price); - startActivity(intent); - }); - } -} \ No newline at end of file diff --git a/app/src/main/java/com/paystack/foodcheckout/MainActivity.kt b/app/src/main/java/com/paystack/foodcheckout/MainActivity.kt new file mode 100644 index 0000000..1e048ed --- /dev/null +++ b/app/src/main/java/com/paystack/foodcheckout/MainActivity.kt @@ -0,0 +1,54 @@ +package com.paystack.foodcheckout + +import androidx.appcompat.app.AppCompatActivity + +import android.os.Bundle +import android.util.Log +import android.widget.Button +import android.widget.Toast +import com.paystack.android.core.Paystack +import com.paystack.android.ui.paymentsheet.PaymentSheet +import com.paystack.android.ui.paymentsheet.PaymentSheetResult + +class MainActivity : AppCompatActivity() { + private lateinit var paymentSheet: PaymentSheet + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + + Paystack.builder() + .setPublicKey("pk_test_xxxx") + .build() + paymentSheet = PaymentSheet(this, ::paymentComplete) + + val mCheckout: Button = findViewById(R.id.btn_checkout) + mCheckout.setOnClickListener { + makePayment() + } + } + + private fun makePayment() { + // Pass access_code from transaction initialize call + paymentSheet.launch("rtz03myg0lbpe11") + } + + + private fun paymentComplete(paymentSheetResult: PaymentSheetResult) { + val message = when (paymentSheetResult) { + PaymentSheetResult.Cancelled -> "Cancelled" + is PaymentSheetResult.Failed -> { + Log.e("Something went wrong", paymentSheetResult.error.message.orEmpty(), paymentSheetResult.error) + paymentSheetResult.error.message ?: "Failed" + } + + is PaymentSheetResult.Completed -> { + // Returns the transaction reference PaymentCompletionDetails(reference={TransactionRef}) + Log.d("Payment successful", paymentSheetResult.paymentCompletionDetails.toString()) + "Successful" + } + } + + Toast.makeText(this, "Payment $message", Toast.LENGTH_SHORT).show() + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_checkout.xml b/app/src/main/res/layout/activity_checkout.xml deleted file mode 100644 index 12296b1..0000000 --- a/app/src/main/res/layout/activity_checkout.xml +++ /dev/null @@ -1,118 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -