diff --git a/.idea/encodings.xml b/.idea/encodings.xml
new file mode 100644
index 0000000..97626ba
--- /dev/null
+++ b/.idea/encodings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index 4278f32..73eec85 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -13,6 +13,13 @@
+
diff --git a/.idea/misc.xml b/.idea/misc.xml
index fd96ddb..0131e93 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -55,7 +55,7 @@
-
+
diff --git a/.idea/modules.xml b/.idea/modules.xml
index 4458e64..587a25c 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -2,9 +2,9 @@
-
+
\ No newline at end of file
diff --git a/Paystack.iml b/Paystack.iml
deleted file mode 100644
index 696f563..0000000
--- a/Paystack.iml
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/example/build.gradle b/example/build.gradle
index 78a5406..0dbe985 100644
--- a/example/build.gradle
+++ b/example/build.gradle
@@ -3,12 +3,12 @@ apply plugin: 'com.android.application'
android {
compileSdkVersion 23
- buildToolsVersion "23.0.0"
+ buildToolsVersion "23.0.2"
defaultConfig {
applicationId "co.paystack.example"
minSdkVersion 9
- targetSdkVersion 21
+ targetSdkVersion 23
versionCode 1
versionName "1.0"
}
@@ -30,18 +30,19 @@ dependencies {
testCompile 'junit:junit:4.12'
testCompile "org.assertj:assertj-core:1.7.0"
- testCompile 'org.robolectric:robolectric:3.0'
+ testCompile 'org.robolectric:robolectric:3.1-SNAPSHOT'
testCompile 'org.mockito:mockito-core:1.9.5'
- //compile 'co.paystack.android:paystack:1.0.2'
- //compile 'co.paystack:paystack:1.0.1'
- //compile project(':paystack')
+ compile project(':paystack')
}
repositories {
maven {
url 'https://dl.bintray.com/paystack/maven/'
}
+ maven {
+ url "https://oss.sonatype.org/content/repositories/snapshots"
+ }
}
dependencies {
diff --git a/example/example.iml b/example/example.iml
index 4cfc739..22fbbc2 100644
--- a/example/example.iml
+++ b/example/example.iml
@@ -1,5 +1,5 @@
-
+
@@ -67,62 +67,61 @@
-
-
+
-
-
-
-
+
+
-
-
-
-
-
+
-
+
-
-
+
+
+
+
+
+
+
-
-
+
+
-
-
-
-
+
+
+
+
+
+
-
+
-
-
-
+
+
\ No newline at end of file
diff --git a/example/src/androidTest/java/co/paystack/example/ApplicationTest.java b/example/src/androidTest/java/co/paystack/example/ApplicationTest.java
index ac44514..6b95e85 100644
--- a/example/src/androidTest/java/co/paystack/example/ApplicationTest.java
+++ b/example/src/androidTest/java/co/paystack/example/ApplicationTest.java
@@ -7,7 +7,7 @@
* Testing Fundamentals
*/
public class ApplicationTest extends ApplicationTestCase {
- public ApplicationTest() {
- super(Application.class);
- }
+ public ApplicationTest() {
+ super(Application.class);
+ }
}
\ No newline at end of file
diff --git a/example/src/main/AndroidManifest.xml b/example/src/main/AndroidManifest.xml
index 4df4046..f6b7ca6 100644
--- a/example/src/main/AndroidManifest.xml
+++ b/example/src/main/AndroidManifest.xml
@@ -1,28 +1,28 @@
-
+
+ android:theme="@style/AppTheme">
+ android:value="pk_test"/>
+ android:label="@string/app_name">
-
+
-
+
diff --git a/example/src/main/java/co/paystack/example/App.java b/example/src/main/java/co/paystack/example/App.java
index 969004c..68a8af4 100644
--- a/example/src/main/java/co/paystack/example/App.java
+++ b/example/src/main/java/co/paystack/example/App.java
@@ -4,33 +4,35 @@
import android.content.Context;
/**
- * Created by Segun Famisa {segunfamisa@gmail.com} on 9/22/15.
+ * The Example App
+ *
+ * This class allows us capture the application context and capture the app instance
*/
public class App extends Application {
- private static Context sContext;
+ private static Context sContext;
- private static App sInstance;
+ private static App sInstance;
- @Override
- public void onCreate() {
- super.onCreate();
-
- sInstance = this;
- sContext = getApplicationContext();
-
- setAppContext(sContext);
- }
-
- public static Context getAppContext(){
+ public static Context getAppContext() {
// if(sContext == null){
// return getApplica;
// }
- return sContext;
- }
+ return sContext;
+ }
+
+ private void setAppContext(Context context) {
+ sContext = context;
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+
+ sInstance = this;
+ sContext = getApplicationContext();
- private void setAppContext(Context context){
- sContext = context;
- }
+ setAppContext(sContext);
+ }
}
diff --git a/example/src/main/java/co/paystack/example/MainActivity.java b/example/src/main/java/co/paystack/example/MainActivity.java
index 5cfb20d..c813741 100644
--- a/example/src/main/java/co/paystack/example/MainActivity.java
+++ b/example/src/main/java/co/paystack/example/MainActivity.java
@@ -18,190 +18,188 @@
public class MainActivity extends AppCompatActivity {
- //private static final String PUBLISHABLE_KEY = "your publishable key";
+ //private static final String PUBLISHABLE_KEY = "your publishable key";
- EditText mEditCardNum;
- EditText mEditCVC;
- EditText mEditExpiryMonth;
- EditText mEditExpiryYear;
- Button mButtonCreateToken;
+ EditText mEditCardNum;
+ EditText mEditCVC;
+ EditText mEditExpiryMonth;
+ EditText mEditExpiryYear;
+ Button mButtonCreateToken;
- TextView mTextCard;
- TextView mTextToken;
+ TextView mTextCard;
+ TextView mTextToken;
- Token token;
- Card card;
+ Token token;
+ Card card;
- ProgressDialog dialog;
+ ProgressDialog dialog;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
- mEditCardNum = (EditText)findViewById(R.id.edit_card_number);
- mEditCVC = (EditText)findViewById(R.id.edit_cvc);
- mEditExpiryMonth = (EditText)findViewById(R.id.edit_expiry_month);
- mEditExpiryYear = (EditText)findViewById(R.id.edit_expiry_year);
+ mEditCardNum = (EditText) findViewById(R.id.edit_card_number);
+ mEditCVC = (EditText) findViewById(R.id.edit_cvc);
+ mEditExpiryMonth = (EditText) findViewById(R.id.edit_expiry_month);
+ mEditExpiryYear = (EditText) findViewById(R.id.edit_expiry_year);
- mButtonCreateToken = (Button)findViewById(R.id.button_create_token);
+ mButtonCreateToken = (Button) findViewById(R.id.button_create_token);
- mTextCard = (TextView)findViewById(R.id.textview_card);
- mTextToken = (TextView)findViewById(R.id.textview_token);
+ mTextCard = (TextView) findViewById(R.id.textview_card);
+ mTextToken = (TextView) findViewById(R.id.textview_token);
- dialog = new ProgressDialog(this);
+ dialog = new ProgressDialog(this);
- //initialize sdk
- PaystackSdk.initialize(getApplicationContext());
+ //initialize sdk
+ PaystackSdk.initialize(getApplicationContext());
- //set click listener
- mButtonCreateToken.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
+ //set click listener
+ mButtonCreateToken.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
- //validate form
- validateForm();
+ //validate form
+ validateForm();
- //check card validity
- if(card.isValid()){
- dialog.setMessage("Request token please wait");
- dialog.setCancelable(true);
- dialog.setCanceledOnTouchOutside(true);
+ //check card validity
+ if (card.isValid()) {
+ dialog.setMessage("Request token please wait");
+ dialog.setCancelable(true);
+ dialog.setCanceledOnTouchOutside(true);
- dialog.show();
+ dialog.show();
- createToken(card);
- }
- }
- });
+ createToken(card);
+ }
+ }
+ });
+ }
+
+ /**
+ * Method to validate the form, and set errors on the edittexts.
+ */
+ private void validateForm() {
+ //validate fields
+ String cardNum = mEditCardNum.getText().toString().trim();
+
+ if (isEmpty(cardNum)) {
+ mEditCardNum.setError("Empty card number");
+ return;
}
- /**
- * Method to validate the form, and set errors on the edittexts.
- */
- private void validateForm(){
- //validate fields
- String cardNum = mEditCardNum.getText().toString().trim();
+ //build card object with ONLY the number, update the other fields later
+ card = new Card.Builder(cardNum, 0, 0, "").build();
+ if (!card.validNumber()) {
+ mEditCardNum.setError("Invalid card number");
+ return;
+ }
- if(isEmpty(cardNum)){
- mEditCardNum.setError("Empty card number");
- return;
- }
+ //validate cvc
+ String cvc = mEditCVC.getText().toString().trim();
+ if (isEmpty(cvc)) {
+ mEditCVC.setError("Empty cvc");
+ return;
+ }
+ //update the cvc field of the card
+ card.setCvc(cvc);
- //build card object with ONLY the number, update the other fields later
- card = new Card.Builder(cardNum, 0, 0, "").build();
- if(!card.validNumber()){
- mEditCardNum.setError("Invalid card number");
- return;
- }
+ //check that it's valid
+ if (!card.validCVC()) {
+ mEditCVC.setError("Invalid cvc");
+ return;
+ }
- //validate cvc
- String cvc = mEditCVC.getText().toString().trim();
- if(isEmpty(cvc)){
- mEditCVC.setError("Empty cvc");
- return;
- }
- //update the cvc field of the card
- card.setCvc(cvc);
+ //validate expiry month;
+ String sMonth = mEditExpiryMonth.getText().toString().trim();
+ int month = -1;
+ try {
+ month = Integer.parseInt(sMonth);
+ } catch (Exception ignored) {
+ }
- //check that it's valid
- if(!card.validCVC()){
- mEditCVC.setError("Invalid cvc");
- return;
- }
+ if (month < 1) {
+ mEditExpiryMonth.setError("Invalid month");
+ return;
+ }
- //validate expiry month;
- String sMonth = mEditExpiryMonth.getText().toString().trim();
- int month = -1;
- try{
- month = Integer.parseInt(sMonth);
- }
- catch (Exception e){}
+ card.setExpiryMonth(month);
- if(month < 1){
- mEditExpiryMonth.setError("Invalid month");
- return;
- }
+ String sYear = mEditExpiryYear.getText().toString().trim();
+ int year = -1;
+ try {
+ year = Integer.parseInt(sYear);
+ } catch (Exception ignored) {
+ }
- card.setExpiryMonth(month);
+ if (year < 1) {
+ mEditExpiryYear.setError("invalid year");
+ return;
+ }
- String sYear = mEditExpiryYear.getText().toString().trim();
- int year = -1;
- try{
- year = Integer.parseInt(sYear);
- }
- catch(Exception e){}
+ card.setExpiryYear(year);
- if(year < 1){
- mEditExpiryYear.setError("invalid year");
- return;
- }
+ //validate expiry
+ if (!card.validExpiryDate()) {
+ mEditExpiryMonth.setError("Invalid expiry");
+ mEditExpiryYear.setError("Invalid expiry");
+ }
+ }
- card.setExpiryYear(year);
+ private void createToken(Card card) {
+ //then create token using PaystackSdk class
+ PaystackSdk.createToken(card, new Paystack.TokenCallback() {
+ @Override
+ public void onCreate(Token token) {
- //validate expiry
- if(!card.validExpiryDate()){
- mEditExpiryMonth.setError("Invalid expiry");
- mEditExpiryYear.setError("Invalid expiry");
- return;
+ //here you retrieve the token, and send to your server for charging.
+ if (dialog.isShowing()) {
+ dialog.dismiss();
}
- }
- private void createToken(Card card){
- //then create token using PaystackSdk class
- PaystackSdk.createToken(card, new Paystack.TokenCallback() {
- @Override
- public void onCreate(Token token) {
-
- //here you retrieve the token, and send to your server for charging.
- if(dialog.isShowing()){
- dialog.dismiss();
- }
-
- Toast.makeText(MainActivity.this, token.token, Toast.LENGTH_LONG).show();
- MainActivity.this.token = token;
- updateTextViews(token);
- }
-
- @Override
- public void onError(Exception error) {
- if(dialog.isShowing()){
- dialog.dismiss();
- }
- Toast.makeText(MainActivity.this, error.getMessage(), Toast.LENGTH_LONG).show();
- updateTextViews(null);
- }
- });
- }
+ Toast.makeText(MainActivity.this, token.token, Toast.LENGTH_LONG).show();
+ MainActivity.this.token = token;
+ updateTextViews(token);
+ }
- private void updateTextViews(Token token){
- if(token != null){
- mTextCard.setText("Card last 4 digits: " + token.last4);
- mTextToken.setText("Token: " + token.token);
- }
- else{
- mTextCard.setText("Unable to get token");
- mTextToken.setText("Token was null");
+ @Override
+ public void onError(Exception error) {
+ if (dialog.isShowing()) {
+ dialog.dismiss();
}
+ Toast.makeText(MainActivity.this, error.getMessage(), Toast.LENGTH_LONG).show();
+ updateTextViews(null);
+ }
+ });
+ }
+
+ private void updateTextViews(Token token) {
+ if (token != null) {
+ mTextCard.setText(String.format("Card last 4 digits: %s", token.last4));
+ mTextToken.setText(String.format("Token: %s", token.token));
+ } else {
+ mTextCard.setText(R.string.token_not_gotten);
+ mTextToken.setText(R.string.token_null_message);
}
+ }
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
- }
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ }
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- // Inflate the menu; this adds items to the action bar if it is present.
- getMenuInflater().inflate(R.menu.menu_main, menu);
- return true;
- }
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ // Inflate the menu; this adds items to the action bar if it is present.
+ getMenuInflater().inflate(R.menu.menu_main, menu);
+ return true;
+ }
- private boolean isEmpty(String s){
- return s == null || s.length() < 1;
- }
+ private boolean isEmpty(String s) {
+ return s == null || s.length() < 1;
+ }
}
diff --git a/example/src/main/res/layout/activity_main.xml b/example/src/main/res/layout/activity_main.xml
index 1c234de..d2ed4d3 100644
--- a/example/src/main/res/layout/activity_main.xml
+++ b/example/src/main/res/layout/activity_main.xml
@@ -1,11 +1,13 @@
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ tools:context=".MainActivity">
+
+
+ android:hint="@string/cvv"
+ android:inputType="number"
+ android:maxLength="4"
+ android:minEms="4"/>
+ android:hint="@string/mm"
+ android:inputType="number"
+ android:maxEms="3"
+ android:maxLength="2"/>
+ android:hint="@string/yyyy"
+ android:inputType="number"
+ android:maxEms="4"
+ android:maxLength="4"/>
+ android:text="@string/create_token"/>
@@ -89,29 +91,29 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/layout_custom_form"
- android:gravity="center_vertical"
android:background="#1C3A4B"
+ android:gravity="center_vertical"
android:minHeight="150dp"
>
+ android:text="@string/no_card_yet"
+ android:textColor="#ffffff"/>
+ android:text="@string/no_token"
+ android:textColor="#ffffff"/>
diff --git a/example/src/main/res/menu/menu_main.xml b/example/src/main/res/menu/menu_main.xml
index 40e369b..ae84c3c 100644
--- a/example/src/main/res/menu/menu_main.xml
+++ b/example/src/main/res/menu/menu_main.xml
@@ -1,9 +1,10 @@
diff --git a/example/src/main/res/values/strings.xml b/example/src/main/res/values/strings.xml
index 4ad5f2a..5f35b76 100644
--- a/example/src/main/res/values/strings.xml
+++ b/example/src/main/res/values/strings.xml
@@ -3,4 +3,13 @@
Hello world!
Settings
+ Card number
+ CVV
+ MM
+ YYYY
+ Create token
+ No card yet
+ No token
+ Token was null
+ Unable to get token
diff --git a/example/src/test/java/co/paystack/example/tests/CardTest.java b/example/src/test/java/co/paystack/example/tests/CardTest.java
index 0d4201f..31c61c2 100644
--- a/example/src/test/java/co/paystack/example/tests/CardTest.java
+++ b/example/src/test/java/co/paystack/example/tests/CardTest.java
@@ -1,13 +1,9 @@
package co.paystack.example.tests;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricGradleTestRunner;
-import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import java.util.Calendar;
@@ -15,84 +11,87 @@
import co.paystack.android.model.Card;
import co.paystack.example.BuildConfig;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
/**
- * Created by Segun Famisa {segunfamisa@gmail.com} on 9/16/15.
+ * Test the card class
*/
@RunWith(RobolectricGradleTestRunner.class)
@Config(constants = BuildConfig.class /*, sdk = 21, manifest = "src/main/AndroidManifest.xml"*/)
public class CardTest {
- private static final int YEAR_FUTURE = 2016;
- private static final int YEAR_PAST = 2014;
- private static final int MONTH_PAST = 8;
-
- private static final int YEAR = 2017;
- private static final int MONTH = 3;
- private static final int DAY = 17;
-
- private static final String CVC_3 = "123";
- private static final String CVC_4 = "1234";
-
- private static final String MASTER_CARD_NUMBER = "5105105105105100";
-
- private static final String DISCOVER_CARD_NUMBER = "6500000000000002";
-
- private static final String VISA_CARD_NUMBER = "4111111111111111";
- private static final String VISA_CARD_NUMBER_2 = "4342-5611-1111-1118";
-
- private static final String AMEX_CARD_NUMBER = "341111111111111";
-
-
- Calendar cal;
-
- @Before
- public void setup(){
- cal = Calendar.getInstance();
- cal.set(Calendar.YEAR, 2015);
- cal.set(Calendar.MONTH, Calendar.MARCH);
- cal.set(Calendar.DAY_OF_MONTH, 17);
- }
-
- @Test
- public void testExpiredCardMonth() throws Exception{
- Card card = new Card.Builder(MASTER_CARD_NUMBER, 2015, MONTH_PAST, "123").build();
- assertSame(false, card.validExpiryDate());
- }
-
- @Test
- public void testExpiredCardYear() throws Exception{
- Card card = new Card.Builder(MASTER_CARD_NUMBER, YEAR_PAST, Calendar.DECEMBER+1, "123").build();
- assertSame(false, card.validExpiryDate());
- }
-
- @Test
- public void canInitializeCardWithBuilder() throws Exception{
- Card card = new Card.Builder(MASTER_CARD_NUMBER, 2017, 03, "123").build();
- assertTrue(card.isValid());
- }
-
- @Test
- public void testTypeDetectionMasterCard() throws Exception{
- Card card = new Card(MASTER_CARD_NUMBER, YEAR, MONTH, CVC_3);
- assertSame(Card.CardType.MASTERCARD, card.getType());
- }
-
- @Test
- public void testTypeDetectionAmericanExpress() throws Exception{
- Card card = new Card(AMEX_CARD_NUMBER, YEAR, MONTH, CVC_4);
- assertSame(Card.CardType.AMERICAN_EXPRESS, card.getType());
- }
-
- @Test
- public void testTypeDetectionVisaCard() throws Exception{
- Card card = new Card(VISA_CARD_NUMBER, YEAR, MONTH, CVC_3);
- assertSame(Card.CardType.VISA, card.getType());
- }
-
- @Test
- public void testTypeDetectionDiscoverCard() throws Exception{
- Card card = new Card(DISCOVER_CARD_NUMBER, YEAR, MONTH, CVC_3);
- assertSame(Card.CardType.DISCOVER, card.getType());
- }
+ private static final int YEAR = Calendar.getInstance().get(Calendar.YEAR);
+ private static final int MONTH = Calendar.getInstance().get(Calendar.MONTH);
+
+ private static final int YEAR_FUTURE = Calendar.getInstance().get(Calendar.YEAR) + 1;
+ private static final int YEAR_PAST = Calendar.getInstance().get(Calendar.YEAR) - 2;
+ private static final int MONTH_PAST = (MONTH > Calendar.getInstance().getMinimum(Calendar.MONTH)) ? MONTH - 1 : Calendar.getInstance().getMaximum(Calendar.MONTH);
+
+
+ private static final String CVC_3 = "123";
+ private static final String CVC_4 = "1234";
+
+ private static final String MASTER_CARD_NUMBER = "5105105105105100";
+
+ private static final String DISCOVER_CARD_NUMBER = "6500000000000002";
+
+ private static final String VISA_CARD_NUMBER = "4111111111111111";
+ private static final String VISA_CARD_NUMBER_2 = "4342-5611-1111-1118";
+
+ private static final String AMEX_CARD_NUMBER = "341111111111111";
+
+
+ // Calendar cal;
+
+ @Before
+ public void setup() {
+// cal = Calendar.getInstance();
+// cal.set(Calendar.YEAR, 2015);
+// cal.set(Calendar.MONTH, Calendar.MARCH);
+// cal.set(Calendar.DAY_OF_MONTH, 17);
+ }
+
+ @Test
+ public void testExpiredCardMonth() throws Exception {
+ Card card = new Card.Builder(MASTER_CARD_NUMBER, YEAR, MONTH_PAST, "123").build();
+ assertSame(false, card.validExpiryDate());
+ }
+
+ @Test
+ public void testExpiredCardYear() throws Exception {
+ Card card = new Card.Builder(MASTER_CARD_NUMBER, YEAR_PAST, Calendar.DECEMBER + 1, "123").build();
+ assertSame(false, card.validExpiryDate());
+ }
+
+ @Test
+ public void canInitializeCardWithBuilder() throws Exception {
+ Card card = new Card.Builder(MASTER_CARD_NUMBER, 3, YEAR_FUTURE, "123").build();
+ assertTrue(card.isValid());
+ }
+
+ @Test
+ public void testTypeDetectionMasterCard() throws Exception {
+ Card card = new Card(MASTER_CARD_NUMBER, YEAR, MONTH, CVC_3);
+ assertSame(Card.CardType.MASTERCARD, card.getType());
+ }
+
+ @Test
+ public void testTypeDetectionAmericanExpress() throws Exception {
+ Card card = new Card(AMEX_CARD_NUMBER, YEAR, MONTH, CVC_4);
+ assertSame(Card.CardType.AMERICAN_EXPRESS, card.getType());
+ }
+
+ @Test
+ public void testTypeDetectionVisaCard() throws Exception {
+ Card card = new Card(VISA_CARD_NUMBER, YEAR, MONTH, CVC_3);
+ assertSame(Card.CardType.VISA, card.getType());
+ }
+
+ @Test
+ public void testTypeDetectionDiscoverCard() throws Exception {
+ Card card = new Card(DISCOVER_CARD_NUMBER, YEAR, MONTH, CVC_3);
+ assertSame(Card.CardType.DISCOVER, card.getType());
+ }
}
diff --git a/example/src/test/java/co/paystack/example/tests/PaystackSdkTest.java b/example/src/test/java/co/paystack/example/tests/PaystackSdkTest.java
index c0a5620..f3066aa 100644
--- a/example/src/test/java/co/paystack/example/tests/PaystackSdkTest.java
+++ b/example/src/test/java/co/paystack/example/tests/PaystackSdkTest.java
@@ -5,23 +5,23 @@
import org.robolectric.RobolectricGradleTestRunner;
import org.robolectric.annotation.Config;
-import co.paystack.android.Paystack;
import co.paystack.android.PaystackSdk;
-import co.paystack.android.exceptions.PaystackSdkNotInitializedException;
import co.paystack.example.App;
import co.paystack.example.BuildConfig;
import static org.junit.Assert.assertTrue;
/**
- * Created by Segun Famisa {segunfamisa@gmail.com} on 9/22/15.
+ * PaystackSdk Test Class
+ *
+ * Tests the paystack sdk
*/
@RunWith(RobolectricGradleTestRunner.class)
@Config(constants = BuildConfig.class /*, sdk = 21, manifest = "src/main/AndroidManifest.xml"*/)
public class PaystackSdkTest {
- private static final String TEST_PUBLISHABLE_KEY = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANIsL+RHqfkBiKGn/D1y1QnNrMkKzxWP\n" +
- "2wkeSokw2OJrCI+d6YGJPrHHx+nmb/Qn885/R01Gw6d7M824qofmCvkCAwEAAQ==";
+ private static final String TEST_PUBLISHABLE_KEY = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANIsL+RHqfkBiKGn/D1y1QnNrMkKzxWP\n" +
+ "2wkeSokw2OJrCI+d6YGJPrHHx+nmb/Qn885/R01Gw6d7M824qofmCvkCAwEAAQ==";
// @Test(expected = PaystackSdkNotInitializedException.class)
@@ -34,17 +34,16 @@ public class PaystackSdkTest {
// PaystackSdk.initialize(App.getAppContext());
// }
- @Test(expected = NullPointerException.class)
- public void initPaystackSdkWithNullParamsShouldThrowException(){
- PaystackSdk.initialize(null);
- }
-
- @Test
- public void initPaystackSdkWithPaystackActivityShouldPass(){
- PaystackSdk.initialize(App.getAppContext());
- assertTrue(PaystackSdk.isSdkInitialized());
- }
+ @Test(expected = NullPointerException.class)
+ public void initPaystackSdkWithNullParamsShouldThrowException() {
+ PaystackSdk.initialize(null);
+ }
+ @Test
+ public void initPaystackSdkWithPaystackActivityShouldPass() {
+ PaystackSdk.initialize(App.getAppContext());
+ assertTrue(PaystackSdk.isSdkInitialized());
+ }
}
diff --git a/paystack/build.gradle b/paystack/build.gradle
index 76b00ef..61dd8e4 100644
--- a/paystack/build.gradle
+++ b/paystack/build.gradle
@@ -3,14 +3,14 @@ apply plugin: "com.jfrog.bintray"
apply plugin: 'com.github.dcendents.android-maven'
android {
- compileSdkVersion 17
- buildToolsVersion '19.1.0'
+ compileSdkVersion 23
+ buildToolsVersion '23.0.2'
defaultConfig {
minSdkVersion 9
- targetSdkVersion 19
- versionCode 1
- versionName "1.0"
+ targetSdkVersion 23
+ versionCode 2
+ versionName "1.0.1"
}
buildTypes {
release {
@@ -23,7 +23,7 @@ android {
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.squareup.retrofit:retrofit:1.6.1'
- compile 'com.google.code.gson:gson:2.3'
+ compile 'com.google.code.gson:gson:2.4'
compile 'org.parceler:parceler:0.2.13'
}
@@ -41,7 +41,7 @@ ext {
artifact = 'paystack'
libraryDescription = 'An android sdk for working with paystack'
- libraryVersion = '1.0.0'
+ libraryVersion = '1.0.1'
developerId = 'paystack'
developerName = 'Paystack'
diff --git a/paystack/paystack.iml b/paystack/paystack.iml
index 752670e..a239242 100644
--- a/paystack/paystack.iml
+++ b/paystack/paystack.iml
@@ -1,5 +1,5 @@
-
+
@@ -22,13 +22,13 @@
-
+
-
+
@@ -67,36 +67,22 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
+
-
+
\ No newline at end of file
diff --git a/paystack/src/androidTest/java/co/paystack/android/ApplicationTest.java b/paystack/src/androidTest/java/co/paystack/android/ApplicationTest.java
index add4bd9..7758473 100644
--- a/paystack/src/androidTest/java/co/paystack/android/ApplicationTest.java
+++ b/paystack/src/androidTest/java/co/paystack/android/ApplicationTest.java
@@ -7,7 +7,7 @@
* Testing Fundamentals
*/
public class ApplicationTest extends ApplicationTestCase {
- public ApplicationTest() {
- super(Application.class);
- }
+ public ApplicationTest() {
+ super(Application.class);
+ }
}
\ No newline at end of file
diff --git a/paystack/src/main/AndroidManifest.xml b/paystack/src/main/AndroidManifest.xml
index 58c1b3a..deb30db 100644
--- a/paystack/src/main/AndroidManifest.xml
+++ b/paystack/src/main/AndroidManifest.xml
@@ -1,7 +1,5 @@
-
+
diff --git a/paystack/src/main/java/co/paystack/android/Config.java b/paystack/src/main/java/co/paystack/android/Config.java
index 507f4bf..ed2fdd9 100644
--- a/paystack/src/main/java/co/paystack/android/Config.java
+++ b/paystack/src/main/java/co/paystack/android/Config.java
@@ -3,11 +3,11 @@
/**
* Config files for Paystack
*
- * @author {androidsupport@paystack.co} on 9/17/15.
+ * @author {androidsupport@paystack.co} on 9/17/15.
*/
public class Config {
- public static final int VERSION_CODE = 1;
+ public static final int VERSION_CODE = 1;
- public static final String VERSION_NAME = "1.0";
+ public static final String VERSION_NAME = "1.0";
}
diff --git a/paystack/src/main/java/co/paystack/android/Paystack.java b/paystack/src/main/java/co/paystack/android/Paystack.java
index c392070..fc96da4 100644
--- a/paystack/src/main/java/co/paystack/android/Paystack.java
+++ b/paystack/src/main/java/co/paystack/android/Paystack.java
@@ -12,107 +12,105 @@
/**
* This is the Paystack model class.\n
- *
+ *
* Try not to use this class directly.
* Instead, access the functionalities of this class via the {@link PaystackSdk}
*
- * @author {androidsupport@paystack.co} on 9/16/15.
+ * @author {androidsupport@paystack.co} on 9/16/15.
*/
public class Paystack extends PaystackModel {
- private String publishableKey;
-
- private static final TokenManager tokenManager = new TokenManager();
-
- /**
- * Constructor.
- */
- protected Paystack() throws PaystackSdkNotInitializedException {
- //validate sdk initialized
- Utils.Validate.validateSdkInitialized();
+ private static final TokenManager tokenManager = new TokenManager();
+ private String publishableKey;
+
+ /**
+ * Constructor.
+ */
+ protected Paystack() throws PaystackSdkNotInitializedException {
+ //validate sdk initialized
+ Utils.Validate.validateSdkInitialized();
+ }
+
+ protected Paystack(String publishableKey) throws AuthenticationException {
+ setPublishableKey(publishableKey);
+ }
+
+ /**
+ * Sets the publishable key
+ *
+ * @param publishableKey - App Developer's publishable key
+ */
+ public void setPublishableKey(String publishableKey) throws AuthenticationException {
+ //validate the publishable key
+ validatePublishableKey(publishableKey);
+ this.publishableKey = publishableKey;
+ }
+
+ private void validatePublishableKey(String publishableKey) throws AuthenticationException {
+ //check for null value, and length and startswith pk_
+ if (publishableKey == null || publishableKey.length() < 1 || !publishableKey.startsWith("pk_")) {
+ throw new AuthenticationException("Invalid publishable key. To create a token, " +
+ "you must use a valid publishable key.\nEnsure that you have set a publishable key." +
+ "\nCheck http://paystack.co for more");
}
- protected Paystack(String publishableKey) throws AuthenticationException{
- setPublishableKey(publishableKey);
+ }
+
+ /**
+ * Method to create token for the transaction, assumes the publishable key has been previously set.
+ *
+ * @param card - a card whose token we want to create
+ * @param tokenCallback - a callback to execute after getting the token
+ * @throws AuthenticationException if publishable key hasn't been set.
+ */
+ public void createToken(Card card, TokenCallback tokenCallback) {
+ createToken(card, publishableKey, tokenCallback);
+ }
+
+ /**
+ * Method to create token for the transaction
+ *
+ * @param card - a card
+ * @param publishableKey - the key provided by App Developer
+ * @param tokenCallback - a callback to execute after getting the token
+ */
+ public void createToken(Card card, String publishableKey, TokenCallback tokenCallback) {
+ //check for the needed data, if absent, send an exception through the tokenCallback;
+ try {
+ //null check for card
+ if (card == null) {
+ throw new RuntimeException("Required parameter: Card cannot be null");
+ }
+ //validate card
+ if (!card.isValid()) {
+ throw new CardException("Invalid parameter: Card not valid");
+ }
+
+ //validate publishable key
+ validatePublishableKey(publishableKey);
+
+ //null check for tokenCallback
+ if (tokenCallback == null) {
+ throw new RuntimeException("Required parameter, tokenCallback cannot be null");
+ }
+
+
+ //do actual create token.
+ tokenManager.create(card, publishableKey, tokenCallback, null);
+ } catch (AuthenticationException | CardException ae) {
+ assert tokenCallback != null;
+ tokenCallback.onError(ae);
}
+ }
- /**
- * Sets the publishable key
- * @param publishableKey
- */
- public void setPublishableKey(String publishableKey) throws AuthenticationException{
- //validate the publishable key
- validatePublishableKey(publishableKey);
- this.publishableKey = publishableKey;
- }
+ interface TokenCreator {
+ void create(Card card, String publishableKey, TokenCallback tokenCallback, Executor executor);
+ }
- private void validatePublishableKey(String publishableKey) throws AuthenticationException{
- //check for null value, and length
- if(publishableKey == null || publishableKey.length() < 1){
- throw new AuthenticationException("Invalid publishable key. To create a token, " +
- "you must use a valid publishable key.\nEnsure that you have set a publishable key."+
- "\nCheck http://paystack.co for more");
- }
+ public interface TokenCallback {
+ void onCreate(Token token);
- }
-
- /**
- * Method to create token for the transaction, assumes the publishable key has been previously set.
- *
- * @param card
- * @param tokenCallback
- *
- * @throws AuthenticationException if publishable key hasn't been set.
- */
- public void createToken(Card card, TokenCallback tokenCallback){
- createToken(card, publishableKey, tokenCallback);
- }
-
- /**
- * Method to create token for for the transaction
- * @param card
- * @param publishableKey
- * @param tokenCallback
- */
- public void createToken(Card card, String publishableKey, TokenCallback tokenCallback){
- //check for the needed data, if absent, a stripe exception through the tokenCallback;
- try{
- //null check for card
- if(card == null){
- throw new RuntimeException("Required parameter: Card cannot be null");
- }
- //validate card
- if(!card.isValid()){
- throw new CardException("Invalid parameter: Card not valid");
- }
-
- //validate publishable key
- validatePublishableKey(publishableKey);
-
- //null check for tokenCallback
- if(tokenCallback == null){
- throw new RuntimeException("Required parameter, tokenCallback cannot be null");
- }
-
-
- //do actual create token.
- tokenManager.create(card, publishableKey, tokenCallback, null);
- }
- catch (AuthenticationException ae){
- tokenCallback.onError(ae);
- }
- catch (CardException ce){
- tokenCallback.onError(ce);
- }
- }
-
- interface TokenCreator{
- void create(Card card, String publishableKey, TokenCallback tokenCallback, Executor executor);
- }
-
- public interface TokenCallback{
- public void onCreate(Token token);
- public void onError(Exception error);
- }
+ void onError(Exception error);
+ }
}
diff --git a/paystack/src/main/java/co/paystack/android/PaystackSdk.java b/paystack/src/main/java/co/paystack/android/PaystackSdk.java
index 366bf63..97b32bd 100644
--- a/paystack/src/main/java/co/paystack/android/PaystackSdk.java
+++ b/paystack/src/main/java/co/paystack/android/PaystackSdk.java
@@ -12,169 +12,160 @@
* This is the overall paystack sdk manager class.
* Must be used to initialize the Sdk.
*
- *
- * @author {androidsupport@paystack.co} on 9/20/15.
+ * @author {androidsupport@paystack.co} on 9/20/15.
*/
public final class PaystackSdk {
- /**
- * Value for the version code of this sdk
- */
- public static final int VERSION_CODE = Config.VERSION_CODE;
-
-
- /**
- * Flag to know if sdk has been initialized
- */
- private static boolean sdkInitialized;
-
- /**
- * Reference to the publishable key
- */
- private static volatile String publishableKey;
-
- private static volatile String merchantId;
-
- private static volatile String secretKey;
-
- private static Context applicationContext;
-
- /**
- * key for publishable key property in the AndroidManifest.xml
- */
- private static final String KEY_PUBLISHABLE_KEY_PROP = "co.paystack.android.PublishableKey";
-
-
- /**
- * Initialize PaystackSdk with a callback when has been initilized successfully.
- *
- * @param applicationContext
- * @param initializeCallback
- */
- public static synchronized void initialize(Context applicationContext, SdkInitializeCallback initializeCallback){
- //do all the init work here
-
- //check if initializa callback is set and sdk is actually intialized
- if(initializeCallback != null && sdkInitialized){
- initializeCallback.onInitialized();
- return;
- }
-
- //null check for applicationContext
- Utils.Validate.validateNotNull(applicationContext, "applicationContext");
-
- //check for internet permissions
- Utils.Validate.hasInternetPermission(applicationContext);
-
- //load data from PaystackSdk
- PaystackSdk.loadFromManifest(applicationContext);
-
- PaystackSdk.applicationContext = applicationContext;
-
- sdkInitialized = true;
-
- if(initializeCallback != null){
- initializeCallback.onInitialized();
- }
+ /**
+ * Value for the version code of this sdk
+ */
+ public static final int VERSION_CODE = Config.VERSION_CODE;
+ /**
+ * key for publishable key property in the AndroidManifest.xml
+ */
+ private static final String KEY_PUBLISHABLE_KEY_PROP = "co.paystack.android.PublishableKey";
+ /**
+ * Flag to know if sdk has been initialized
+ */
+ private static boolean sdkInitialized;
+ /**
+ * Reference to the publishable key
+ */
+ private static volatile String publishableKey;
+ private static volatile String merchantId;
+ private static volatile String secretKey;
+ private static Context applicationContext;
+
+ /**
+ * Initialize PaystackSdk with a callback when has been initilized successfully.
+ *
+ * @param applicationContext - Application Context
+ * @param initializeCallback - callback to execute after initializing
+ */
+ public static synchronized void initialize(Context applicationContext, SdkInitializeCallback initializeCallback) {
+ //do all the init work here
+
+ //check if initialize callback is set and sdk is actually intialized
+ if (initializeCallback != null && sdkInitialized) {
+ initializeCallback.onInitialized();
+ return;
}
- /**
- * Initialize an sdk without a callback
- * @param context
- */
- public static synchronized void initialize(Context context){
- initialize(context, null);
- }
+ //null check for applicationContext
+ Utils.Validate.validateNotNull(applicationContext, "applicationContext");
+ //check for internet permissions
+ Utils.Validate.hasInternetPermission(applicationContext);
+ //load data from PaystackSdk
+ PaystackSdk.loadFromManifest(applicationContext);
- public static boolean isSdkInitialized(){
- return sdkInitialized;
- }
+ PaystackSdk.applicationContext = applicationContext;
- /**
- * Return publishable key
- * @return publishable key
- *
- * @throws PaystackSdkNotInitializedException if the sdk hasn't been initialized
- */
- public static String getPublishableKey() throws PaystackSdkNotInitializedException {
- //validate that the sdk has been initialized
- Utils.Validate.validateSdkInitialized();
-
- return publishableKey;
- }
+ sdkInitialized = true;
- /**
- * Sets the publishable key
- * @param publishableKey
- */
- public static void setPublishableKey(String publishableKey){
- PaystackSdk.publishableKey = publishableKey;
+ if (initializeCallback != null) {
+ initializeCallback.onInitialized();
}
-
- public static Context getApplicationContext(){
- return applicationContext;
+ }
+
+ /**
+ * Initialize an sdk without a callback
+ *
+ * @param context - Application Context
+ */
+ public static synchronized void initialize(Context context) {
+ initialize(context, null);
+ }
+
+
+ public static boolean isSdkInitialized() {
+ return sdkInitialized;
+ }
+
+ /**
+ * Return publishable key
+ *
+ * @return publishable key
+ * @throws PaystackSdkNotInitializedException if the sdk hasn't been initialized
+ */
+ public static String getPublishableKey() throws PaystackSdkNotInitializedException {
+ //validate that the sdk has been initialized
+ Utils.Validate.validateSdkInitialized();
+
+ return publishableKey;
+ }
+
+ /**
+ * Sets the publishable key
+ *
+ * @param publishableKey - App Developer's publishable key
+ */
+ public static void setPublishableKey(String publishableKey) {
+ PaystackSdk.publishableKey = publishableKey;
+ }
+
+ public static Context getApplicationContext() {
+ return applicationContext;
+ }
+
+ private static void loadFromManifest(Context context) {
+ if (context == null) {
+ return;
}
- public interface SdkInitializeCallback{
- void onInitialized();
+ ApplicationInfo applicationInfo;
+ try {
+ applicationInfo = context.getPackageManager().getApplicationInfo(
+ context.getPackageName(),
+ PackageManager.GET_ACTIVITIES | PackageManager.GET_META_DATA
+ );
+ } catch (PackageManager.NameNotFoundException e) {
+ return;
}
- private static void loadFromManifest(Context context){
- if(context == null){
- return;
- }
-
- ApplicationInfo applicationInfo = null;
- try{
- applicationInfo = context.getPackageManager().getApplicationInfo(
- context.getPackageName(),
- PackageManager.GET_ACTIVITIES|PackageManager.GET_META_DATA
- );
- }
- catch (PackageManager.NameNotFoundException e) {
- return;
- }
-
- //check if we can get any metadata, return if not
- if(applicationInfo == null || applicationInfo.metaData == null){
- return;
- }
-
- //check publishable key
- if(publishableKey == null){
- publishableKey = applicationInfo.metaData.getString(KEY_PUBLISHABLE_KEY_PROP);
- }
-
+ //check if we can get any metadata, return if not
+ if (applicationInfo == null || applicationInfo.metaData == null) {
+ return;
}
- /**
- * Method for creating a token, using {@link PaystackSdk}. You won't need to create an instance
- * of {@link Paystack} by yourself.
- *
- * Equivalent to these two lines:
- *
- * {@code
- * Paystack paystack = new Paystack(PUBLISHABLE_KEY);
- * paystack.createToken();
- * }
- *
- * @param card
- * @param callback
- */
- public static void createToken(Card card, Paystack.TokenCallback callback){
- //validate that sdk has been initialized
- Utils.Validate.validateSdkInitialized();
-
- //validate publishable keys
- Utils.Validate.hasPublishableKey();
-
- //construct paystack object
- Paystack paystack = new Paystack(PaystackSdk.getPublishableKey());
-
- //create token
- paystack.createToken(card, callback);
+ //check publishable key
+ if (publishableKey == null) {
+ publishableKey = applicationInfo.metaData.getString(KEY_PUBLISHABLE_KEY_PROP);
}
+ }
+
+ /**
+ * Method for creating a token, using {@link PaystackSdk}. You won't need to create an instance
+ * of {@link Paystack} by yourself.
+ *
+ * Equivalent to these two lines:
+ *
+ * {@code
+ * Paystack paystack = new Paystack(PUBLISHABLE_KEY);
+ * paystack.createToken();
+ * }
+ *
+ * @param card - card whose token we need to create
+ * @param callback - callback to execute after creating token
+ */
+ public static void createToken(Card card, Paystack.TokenCallback callback) {
+ //validate that sdk has been initialized
+ Utils.Validate.validateSdkInitialized();
+
+ //validate publishable keys
+ Utils.Validate.hasPublishableKey();
+
+ //construct paystack object
+ Paystack paystack = new Paystack(PaystackSdk.getPublishableKey());
+
+ //create token
+ paystack.createToken(card, callback);
+ }
+
+ public interface SdkInitializeCallback {
+ void onInitialized();
+ }
+
}
diff --git a/paystack/src/main/java/co/paystack/android/TokenManager.java b/paystack/src/main/java/co/paystack/android/TokenManager.java
index 2f38b12..df454c8 100644
--- a/paystack/src/main/java/co/paystack/android/TokenManager.java
+++ b/paystack/src/main/java/co/paystack/android/TokenManager.java
@@ -1,5 +1,7 @@
package co.paystack.android;
+import android.util.Log;
+
import java.util.HashMap;
import java.util.concurrent.Executor;
@@ -21,103 +23,103 @@
/**
* TokenManager class, to perform action token creation. You don't have to use this class.
*
- * @author {androidsupport@paystack.co} on 9/17/15.
+ * @author {androidsupport@paystack.co} on 9/17/15.
*/
public class TokenManager implements Paystack.TokenCreator {
- private static final String CARD_CONCATENATOR = "*";
+ private static final String CARD_CONCATENATOR = "*";
+ private static final String RSA_PUBLIC_KEY = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANIsL+RHqfkBiKGn/D1y1QnNrMkKzxWP" +
+ "2wkeSokw2OJrCI+d6YGJPrHHx+nmb/Qn885/R01Gw6d7M824qofmCvkCAwEAAQ==";
+
+ private static final String LOG_TAG = TokenManager.class.getSimpleName();
+
+ @Override
+ public void create(final Card card, String publishableKey, final Paystack.TokenCallback tokenCallback, Executor executor) {
+ try {
+ //concatenate card fields
+ String cardString = concatenateCardFields(card);
+
+ //encrypt
+ final String encCardString = Crypto.encrypt(cardString, RSA_PUBLIC_KEY);
+
+ //create tokenRequestBody
+ final TokenRequestBody tokenRequestBody = new TokenRequestBody(encCardString, publishableKey);
+
+ //request token from paystack server
+ createServerSideToken(tokenRequestBody, tokenCallback);
+
+ } catch (CardException ce) {
+ if (tokenCallback != null) {
+ tokenCallback.onError(ce);
+ }
+ Log.e(LOG_TAG, ce.getMessage(), ce);
+ } catch (AuthenticationException ae) {
+ if (tokenCallback != null) {
+ tokenCallback.onError(ae);
+ Log.e(LOG_TAG, ae.getMessage(), ae);
+ }
+ }
- private static final String TAG = "TokenManager";
+ }
- @Override
- public void create(final Card card, String publishableKey, final Paystack.TokenCallback tokenCallback, Executor executor) {
- try{
- //concatenate card fields
- String cardString = concatenateCardFields(card);
- //encrypt
- final String encCardString = Crypto.encrypt(cardString, publishableKey);
+ private void createServerSideToken(TokenRequestBody tokenRequestBody, final Paystack.TokenCallback tokenCallback) {
+ //call retrofit api service
+ ApiService apiService = new ApiClient().getApiService();
- //create tokenRequestBody
- final TokenRequestBody tokenRequestBody = new TokenRequestBody(encCardString, card.getType());
+ HashMap params = new HashMap<>();
+ params.put(TokenRequestBody.FIELD_PUBLISHABLE_KEY, tokenRequestBody.publishableKey);
+ params.put(TokenRequestBody.FIELD_CLIENT_DATA, tokenRequestBody.clientData);
- //request token from paystack server
- createServerSideToken(tokenRequestBody, tokenCallback);
+ apiService.createToken(params, new Callback() {
+ @Override
+ public void success(TokenApiResponse tokenApiResponse, Response response) {
+ if (tokenApiResponse != null) {
+ //check for status...if 0 return an error with the message
+ if (tokenApiResponse.status == 0) {
+ //throw an error
+ tokenCallback.onError(new TokenException(tokenApiResponse.message));
+ } else {
+ Token token = new Token();
+ token.token = tokenApiResponse.token;
+ token.last4 = tokenApiResponse.last4;
+ tokenCallback.onCreate(token);
+ }
}
- catch (CardException ce){
- if(tokenCallback != null)
- tokenCallback.onError(ce);
- }
- catch (AuthenticationException ae) {
- if(tokenCallback != null){
- tokenCallback.onError(ae);
- }
- }
-
+ }
+
+ @Override
+ public void failure(RetrofitError error) {
+ tokenCallback.onError(error);
+ }
+ });
+ }
+
+ private String concatenateCardFields(Card card) throws CardException {
+ if (card == null) {
+ throw new CardException("Card cannot be null");
}
-
- private void createServerSideToken(TokenRequestBody tokenRequestBody, final Paystack.TokenCallback tokenCallback){
- //call retrofit api service
- ApiService apiService = new ApiClient().getApiService();
-
- HashMap params = new HashMap();
- params.put(TokenRequestBody.FIELD_CARDTYPE, tokenRequestBody.cardtype);
- params.put(TokenRequestBody.FIELD_CLIENTDATA, tokenRequestBody.clientdata);
-
- apiService.createToken(params, new Callback() {
- @Override
- public void success(TokenApiResponse tokenApiResponse, Response response) {
- if(tokenApiResponse != null){
- //check for status...if 0 return an error with the message
- if(tokenApiResponse.status == 0){
- //throw an error
- tokenCallback.onError(new TokenException(tokenApiResponse.message));
- }
- else{
- Token token = new Token();
- token.token = tokenApiResponse.token;
- token.last4 = tokenApiResponse.last4;
-
- tokenCallback.onCreate(token);
- }
- }
- }
-
- @Override
- public void failure(RetrofitError error) {
- tokenCallback.onError(error);
- }
- });
- }
-
- private String concatenateCardFields(Card card) throws CardException{
- if(card == null){
- throw new CardException("Card cannot be null");
- }
-
- String number = StringUtils.nullify(card.getNumber());
- String cvc = StringUtils.nullify(card.getCvc());
- int expiryMonth = card.getExpiryMonth();
- int expiryYear = card.getExpiryYear();
-
- String cardString = null;
- String[] cardFields = {number, cvc, expiryMonth+"", expiryYear+""};
-
- if(!StringUtils.isEmpty(number)){
- for(int i=0; i 1)
- cardString = cardFields[i] + CARD_CONCATENATOR;
- else if(i == cardFields.length - 1)
- cardString += cardFields[i];
- else
- cardString = cardString + cardFields[i] + CARD_CONCATENATOR;
- }
- return cardString;
- }
-
- else{
- throw new CardException("Invalid card details: Card number is empty or null");
- }
+ String number = StringUtils.nullify(card.getNumber());
+ String cvc = StringUtils.nullify(card.getCvc());
+ int expiryMonth = card.getExpiryMonth();
+ int expiryYear = card.getExpiryYear();
+
+ String cardString = null;
+ String[] cardFields = {number, cvc, expiryMonth + "", expiryYear + ""};
+
+ if (!StringUtils.isEmpty(number)) {
+ for (int i = 0; i < cardFields.length; i++) {
+ if (i == 0 && cardFields.length > 1)
+ cardString = cardFields[i] + CARD_CONCATENATOR;
+ else if (i == cardFields.length - 1)
+ cardString += cardFields[i];
+ else
+ cardString = cardString + cardFields[i] + CARD_CONCATENATOR;
+ }
+ return cardString;
+ } else {
+ throw new CardException("Invalid card details: Card number is empty or null");
}
+ }
}
diff --git a/paystack/src/main/java/co/paystack/android/api/ApiClient.java b/paystack/src/main/java/co/paystack/android/api/ApiClient.java
index 78c6c30..86bff34 100644
--- a/paystack/src/main/java/co/paystack/android/api/ApiClient.java
+++ b/paystack/src/main/java/co/paystack/android/api/ApiClient.java
@@ -8,33 +8,32 @@
import retrofit.converter.GsonConverter;
/**
- * Created by {androidsupport@paystack.co} on 9/17/15.
+ * API Client Class
+ *
+ * Provides a service by which we can make API calls
*/
public class ApiClient {
- private static String BASE_URL = "https://paystack.ng/";
- public static String API_URL = BASE_URL;
+ private static final String BASE_URL = "https://standard.paystack.co/";
+ public static String API_URL = BASE_URL;
+ private ApiService apiService;
- private ApiService apiService;
+ public ApiClient() {
+ Gson gson = new GsonBuilder()
+ .setDateFormat("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'SSS'Z'")
+ .create();
- public ApiClient()
- {
- Gson gson = new GsonBuilder()
- .setDateFormat("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'SSS'Z'")
- .create();
+ RestAdapter restAdapter = new RestAdapter.Builder()
+ .setLogLevel(RestAdapter.LogLevel.FULL)
+ .setEndpoint(API_URL)
+ .setConverter(new GsonConverter(gson))
+ .build();
- RestAdapter restAdapter = new RestAdapter.Builder()
- .setLogLevel(RestAdapter.LogLevel.FULL)
- .setEndpoint(API_URL)
- .setConverter(new GsonConverter(gson))
- .build();
+ apiService = restAdapter.create(ApiService.class);
+ }
- apiService = restAdapter.create(ApiService.class);
- }
-
- public ApiService getApiService()
- {
- return apiService;
- }
+ public ApiService getApiService() {
+ return apiService;
+ }
}
diff --git a/paystack/src/main/java/co/paystack/android/api/model/ApiResponse.java b/paystack/src/main/java/co/paystack/android/api/model/ApiResponse.java
index d27dadf..ed83a9e 100644
--- a/paystack/src/main/java/co/paystack/android/api/model/ApiResponse.java
+++ b/paystack/src/main/java/co/paystack/android/api/model/ApiResponse.java
@@ -3,14 +3,14 @@
import com.google.gson.annotations.SerializedName;
/**
- * Created by {androidsupport@paystack.co} on 9/20/15.
+ * An API response always includes a status and a message
*/
-public class ApiResponse extends BaseApiModel{
+public class ApiResponse extends BaseApiModel {
- @SerializedName("status")
- public int status;
+ @SerializedName("status")
+ public int status;
- @SerializedName("message")
- public String message;
+ @SerializedName("message")
+ public String message;
}
diff --git a/paystack/src/main/java/co/paystack/android/api/model/TokenApiResponse.java b/paystack/src/main/java/co/paystack/android/api/model/TokenApiResponse.java
index fd15a00..9ab86a0 100644
--- a/paystack/src/main/java/co/paystack/android/api/model/TokenApiResponse.java
+++ b/paystack/src/main/java/co/paystack/android/api/model/TokenApiResponse.java
@@ -7,14 +7,14 @@
import java.io.Serializable;
/**
- * Created by {androidsupport@paystack.co} on 9/17/15.
+ * A Response received from the API when a Token Request is made
*/
@Parcel
-public class TokenApiResponse extends ApiResponse implements Serializable{
+public class TokenApiResponse extends ApiResponse implements Serializable {
- @SerializedName("token")
- public String token;
+ @SerializedName("token")
+ public String token;
- @SerializedName("last4")
- public String last4;
+ @SerializedName("last4")
+ public String last4;
}
diff --git a/paystack/src/main/java/co/paystack/android/api/request/TokenRequestBody.java b/paystack/src/main/java/co/paystack/android/api/request/TokenRequestBody.java
index a42e4de..f44d87b 100644
--- a/paystack/src/main/java/co/paystack/android/api/request/TokenRequestBody.java
+++ b/paystack/src/main/java/co/paystack/android/api/request/TokenRequestBody.java
@@ -2,33 +2,30 @@
import com.google.gson.annotations.SerializedName;
-import java.io.Serializable;
-
/**
- * Created by {androidsupport@paystack.co} on 9/18/15.
+ * A token request
*/
public class TokenRequestBody {
- /**
- * Value for encrypted & concatenated card details
- */
- @SerializedName("clientdata")
- public String clientdata;
-
- /**
- * Value for cardtype
- */
- @SerializedName("cardtype")
- public String cardtype;
-
- public TokenRequestBody(){}
-
- public TokenRequestBody(String clientData, String cardType){
- this.clientdata = clientData;
- this.cardtype = cardType;
- }
-
-
- public static final String FIELD_CLIENTDATA = "clientdata";
- public static final String FIELD_CARDTYPE = "cardtype";
+ public static final String FIELD_CLIENT_DATA = "clientdata";
+ public static final String FIELD_PUBLISHABLE_KEY = "publishablekey";
+ /**
+ * Value for encrypted & concatenated card details
+ */
+ @SerializedName("clientdata")
+ public String clientData;
+ /**
+ * Value for cardtype
+ */
+ @SerializedName("publishablekey")
+ public String publishableKey;
+
+
+ public TokenRequestBody() {
+ }
+
+ public TokenRequestBody(String clientData, String publishableKey) {
+ this.clientData = clientData;
+ this.publishableKey = publishableKey;
+ }
}
diff --git a/paystack/src/main/java/co/paystack/android/api/request/TransactionRequestBody.java b/paystack/src/main/java/co/paystack/android/api/request/TransactionRequestBody.java
index da851e6..b1795f7 100644
--- a/paystack/src/main/java/co/paystack/android/api/request/TransactionRequestBody.java
+++ b/paystack/src/main/java/co/paystack/android/api/request/TransactionRequestBody.java
@@ -3,45 +3,45 @@
import com.google.gson.annotations.SerializedName;
/**
- * Created by {androidsupport@paystack.co} on 9/25/15.
+ * A transaction request
*/
public class TransactionRequestBody {
- public static final String FIELD_MERCHANT_ID = "merchantid";
- public static final String FIELD_SECRET_KEY = "secretkey";
- public static final String FIELD_TRX_REF = "trxref";
- public static final String FIELD_EMAIL = "email";
- public static final String FIELD_AMOUNT = "amount";
- public static final String FIELD_TOKEN = "token";
- public static final String FIELD_PLAN = "plan";
- public static final String FIELD_QUANTITY = "quantity";
- public static final String FIELD_COUPON = "coupon";
+ public static final String FIELD_MERCHANT_ID = "merchantid";
+ public static final String FIELD_SECRET_KEY = "secretkey";
+ public static final String FIELD_TRX_REF = "trxref";
+ public static final String FIELD_EMAIL = "email";
+ public static final String FIELD_AMOUNT = "amount";
+ public static final String FIELD_TOKEN = "token";
+ public static final String FIELD_PLAN = "plan";
+ public static final String FIELD_QUANTITY = "quantity";
+ public static final String FIELD_COUPON = "coupon";
- @SerializedName(FIELD_MERCHANT_ID)
- public String merchantId;
+ @SerializedName(FIELD_MERCHANT_ID)
+ public String merchantId;
- @SerializedName(FIELD_SECRET_KEY)
- public String secretKey;
+ @SerializedName(FIELD_SECRET_KEY)
+ public String secretKey;
- @SerializedName(FIELD_TRX_REF)
- public String transactionRef;
+ @SerializedName(FIELD_TRX_REF)
+ public String transactionRef;
- @SerializedName(FIELD_EMAIL)
- public String email;
+ @SerializedName(FIELD_EMAIL)
+ public String email;
- @SerializedName(FIELD_AMOUNT)
- public String amount;
+ @SerializedName(FIELD_AMOUNT)
+ public String amount;
- @SerializedName(FIELD_TOKEN)
- public String token;
+ @SerializedName(FIELD_TOKEN)
+ public String token;
- @SerializedName(FIELD_PLAN)
- public String plan;
+ @SerializedName(FIELD_PLAN)
+ public String plan;
- @SerializedName(FIELD_QUANTITY)
- public String quantity;
+ @SerializedName(FIELD_QUANTITY)
+ public String quantity;
- @SerializedName(FIELD_COUPON)
- public String coupon;
+ @SerializedName(FIELD_COUPON)
+ public String coupon;
}
diff --git a/paystack/src/main/java/co/paystack/android/api/service/ApiService.java b/paystack/src/main/java/co/paystack/android/api/service/ApiService.java
index 5123baf..34b15b0 100644
--- a/paystack/src/main/java/co/paystack/android/api/service/ApiService.java
+++ b/paystack/src/main/java/co/paystack/android/api/service/ApiService.java
@@ -3,28 +3,25 @@
import java.util.HashMap;
import co.paystack.android.api.model.TokenApiResponse;
-import co.paystack.android.api.request.TokenRequestBody;
import retrofit.Callback;
-import retrofit.http.Field;
import retrofit.http.FieldMap;
import retrofit.http.FormUrlEncoded;
import retrofit.http.POST;
/**
- * @author {androidsupport@paystack.co} on 9/17/15.
+ * ApiService
*/
public interface ApiService {
- /**
- * ApiService for creating token
- * @param fields
- * @param callback
- */
- @FormUrlEncoded
- @POST("/bosco/createmobiletoken")
- public void createToken(@FieldMap HashMap fields, Callback callback);
-
-
+ /**
+ * call for creating token
+ *
+ * @param fields
+ * @param callback
+ */
+ @FormUrlEncoded
+ @POST("/bosco/createmobiletoken")
+ void createToken(@FieldMap HashMap fields, Callback callback);
}
diff --git a/paystack/src/main/java/co/paystack/android/api/utils/SessionRequestInterceptor.java b/paystack/src/main/java/co/paystack/android/api/utils/SessionRequestInterceptor.java
index 55550a9..d0ab049 100644
--- a/paystack/src/main/java/co/paystack/android/api/utils/SessionRequestInterceptor.java
+++ b/paystack/src/main/java/co/paystack/android/api/utils/SessionRequestInterceptor.java
@@ -4,16 +4,18 @@
import retrofit.RequestInterceptor;
/**
- * Created by {androidsupport@paystack.co} on 9/18/15.
+ * Session Request interceptor
+ *
+ * Add User agent to the headers sent by our request, not yet used
*/
public class SessionRequestInterceptor implements RequestInterceptor {
- String USER_AGENT = "Android_" + Config.VERSION_CODE;
- String CHARSET = "UTF-8";
+ String USER_AGENT = "Android_" + Config.VERSION_CODE;
+ String CHARSET = "UTF-8";
- @Override
- public void intercept(RequestFacade request) {
- request.addHeader("User-Agent", USER_AGENT);
- request.addHeader("Charset", CHARSET);
- }
+ @Override
+ public void intercept(RequestFacade request) {
+ request.addHeader("User-Agent", USER_AGENT);
+ request.addHeader("Charset", CHARSET);
+ }
}
diff --git a/paystack/src/main/java/co/paystack/android/exceptions/AuthenticationException.java b/paystack/src/main/java/co/paystack/android/exceptions/AuthenticationException.java
index 95e130e..3064081 100644
--- a/paystack/src/main/java/co/paystack/android/exceptions/AuthenticationException.java
+++ b/paystack/src/main/java/co/paystack/android/exceptions/AuthenticationException.java
@@ -1,14 +1,14 @@
package co.paystack.android.exceptions;
/**
- * @author {androidsupport@paystack.co} on 9/16/15.
+ * @author {androidsupport@paystack.co} on 9/16/15.
*/
public class AuthenticationException extends PaystackException {
- public AuthenticationException(String message) {
- super(message);
- }
+ public AuthenticationException(String message) {
+ super(message);
+ }
- public AuthenticationException(String message, Throwable e) {
- super(message, e);
- }
+ public AuthenticationException(String message, Throwable e) {
+ super(message, e);
+ }
}
diff --git a/paystack/src/main/java/co/paystack/android/exceptions/CardException.java b/paystack/src/main/java/co/paystack/android/exceptions/CardException.java
index 92568af..be0bc0c 100644
--- a/paystack/src/main/java/co/paystack/android/exceptions/CardException.java
+++ b/paystack/src/main/java/co/paystack/android/exceptions/CardException.java
@@ -1,15 +1,15 @@
package co.paystack.android.exceptions;
/**
- * @author {androidsupport@paystack.co} on 9/13/15.
+ * @author {androidsupport@paystack.co} on 9/13/15.
*/
public class CardException extends PaystackException {
- public CardException(String message) {
- super(message);
- }
+ public CardException(String message) {
+ super(message);
+ }
- public CardException(String message, Throwable e) {
- super(message, e);
- }
+ public CardException(String message, Throwable e) {
+ super(message, e);
+ }
}
diff --git a/paystack/src/main/java/co/paystack/android/exceptions/PaystackActivityNotFoundException.java b/paystack/src/main/java/co/paystack/android/exceptions/PaystackActivityNotFoundException.java
index 0c8a8f0..18f3fff 100644
--- a/paystack/src/main/java/co/paystack/android/exceptions/PaystackActivityNotFoundException.java
+++ b/paystack/src/main/java/co/paystack/android/exceptions/PaystackActivityNotFoundException.java
@@ -1,14 +1,14 @@
package co.paystack.android.exceptions;
/**
- * @author {androidsupport@paystack.co} on 9/22/15.
+ * @author {androidsupport@paystack.co} on 9/22/15.
*/
public class PaystackActivityNotFoundException extends PaystackException {
- public PaystackActivityNotFoundException(String message) {
- super(message);
- }
+ public PaystackActivityNotFoundException(String message) {
+ super(message);
+ }
- public PaystackActivityNotFoundException(String message, Throwable e) {
- super(message, e);
- }
+ public PaystackActivityNotFoundException(String message, Throwable e) {
+ super(message, e);
+ }
}
diff --git a/paystack/src/main/java/co/paystack/android/exceptions/PaystackException.java b/paystack/src/main/java/co/paystack/android/exceptions/PaystackException.java
index 0355871..a5c26fa 100644
--- a/paystack/src/main/java/co/paystack/android/exceptions/PaystackException.java
+++ b/paystack/src/main/java/co/paystack/android/exceptions/PaystackException.java
@@ -4,15 +4,16 @@
/**
* Base class for exceptions
- * @author {androidsupport@paystack.co} on 9/13/15.
+ *
+ * @author {androidsupport@paystack.co} on 9/13/15.
*/
public class PaystackException extends RuntimeException implements Serializable {
- public PaystackException(String message){
- super(message, null);
- }
+ public PaystackException(String message) {
+ super(message, null);
+ }
- public PaystackException(String message, Throwable e) {
- super(message, e);
- }
+ public PaystackException(String message, Throwable e) {
+ super(message, e);
+ }
}
diff --git a/paystack/src/main/java/co/paystack/android/exceptions/PaystackSdkNotInitializedException.java b/paystack/src/main/java/co/paystack/android/exceptions/PaystackSdkNotInitializedException.java
index 3f95690..772913f 100644
--- a/paystack/src/main/java/co/paystack/android/exceptions/PaystackSdkNotInitializedException.java
+++ b/paystack/src/main/java/co/paystack/android/exceptions/PaystackSdkNotInitializedException.java
@@ -1,10 +1,10 @@
package co.paystack.android.exceptions;
/**
- * @author {androidsupport@paystack.co} on 9/22/15.
+ * @author {androidsupport@paystack.co} on 9/22/15.
*/
public class PaystackSdkNotInitializedException extends PaystackException {
- public PaystackSdkNotInitializedException(String message) {
- super(message);
- }
+ public PaystackSdkNotInitializedException(String message) {
+ super(message);
+ }
}
diff --git a/paystack/src/main/java/co/paystack/android/exceptions/TokenException.java b/paystack/src/main/java/co/paystack/android/exceptions/TokenException.java
index 00f6364..482e0e3 100644
--- a/paystack/src/main/java/co/paystack/android/exceptions/TokenException.java
+++ b/paystack/src/main/java/co/paystack/android/exceptions/TokenException.java
@@ -1,10 +1,10 @@
package co.paystack.android.exceptions;
/**
- * @author {androidsupport@paystack.co} on 9/20/15.
+ * @author {androidsupport@paystack.co} on 9/20/15.
*/
public class TokenException extends PaystackException {
- public TokenException(String message) {
- super(message);
- }
+ public TokenException(String message) {
+ super(message);
+ }
}
diff --git a/paystack/src/main/java/co/paystack/android/exceptions/TransactionException.java b/paystack/src/main/java/co/paystack/android/exceptions/TransactionException.java
index fe7d8cd..fd753d8 100644
--- a/paystack/src/main/java/co/paystack/android/exceptions/TransactionException.java
+++ b/paystack/src/main/java/co/paystack/android/exceptions/TransactionException.java
@@ -1,10 +1,10 @@
package co.paystack.android.exceptions;
/**
- * @author {androidsupport@paystack.co} on 9/25/15.
+ * @author {androidsupport@paystack.co} on 9/25/15.
*/
public class TransactionException extends PaystackException {
- public TransactionException(String message) {
- super(message);
- }
+ public TransactionException(String message) {
+ super(message);
+ }
}
diff --git a/paystack/src/main/java/co/paystack/android/model/Card.java b/paystack/src/main/java/co/paystack/android/model/Card.java
index c61416c..e6f30ff 100644
--- a/paystack/src/main/java/co/paystack/android/model/Card.java
+++ b/paystack/src/main/java/co/paystack/android/model/Card.java
@@ -11,612 +11,598 @@
* The class for the card model. Has utility methods for validating the card.\n
* Best initialized with the Card.Builder class
*
- * @author {androidsupport@paystack.co} on 8/10/15.
+ * @author {androidsupport@paystack.co} on 8/10/15.
*/
-public class Card extends PaystackModel implements Serializable{
-
-
- //declare fields in a typical card
- /**
- * Name on the card
- */
+public class Card extends PaystackModel implements Serializable {
+
+
+ //declare fields in a typical card
+ /**
+ * List of cardTypes
+ */
+ private static final List cardTypes = Arrays.asList(
+ new Visa(),
+ new MasterCard(),
+ new AmericanExpress(),
+ new DinersClub(),
+ new Jcb(),
+ new Discover()
+ );
+ /**
+ * Name on the card
+ */
+ private String name;
+ /**
+ * Card number
+ */
+ private String number;
+ /**
+ * CVC number
+ */
+ private String cvc;
+ /**
+ * Expiry month
+ */
+ private Integer expiryMonth;
+ /**
+ * Expiry year
+ */
+ private Integer expiryYear;
+ /**
+ * Bank Address line 1-4
+ */
+ private String addressLine1;
+ private String addressLine2;
+ private String addressLine3;
+ private String addressLine4;
+ /**
+ * Postal code of the bank address
+ */
+ private String addressPostalCode;
+ /**
+ * Country of the bank
+ */
+ private String addressCountry;
+ private String country;
+ /**
+ * Type of card
+ */
+ private String type;
+ private String last4digits;
+
+ /**
+ * Private constructor for a Card object, using a Builder;
+ *
+ * @param builder - a builder with which to build the card object
+ */
+ private Card(Builder builder) {
+ this.number = StringUtils.nullify(builder.number);
+ this.expiryMonth = builder.expiryMonth;
+ this.expiryYear = builder.expiryYear;
+ this.cvc = StringUtils.nullify(builder.cvc);
+
+ this.name = StringUtils.nullify(builder.name);
+ this.addressLine1 = StringUtils.nullify(builder.addressLine1);
+ this.addressLine2 = StringUtils.nullify(builder.addressLine2);
+ this.addressLine3 = StringUtils.nullify(builder.addressLine3);
+ this.addressLine4 = StringUtils.nullify(builder.addressLine4);
+ this.addressCountry = StringUtils.nullify(builder.addressCountry);
+ this.addressPostalCode = StringUtils.nullify(builder.addressPostalCode);
+
+ this.country = StringUtils.nullify(builder.country);
+ this.type = getType();
+ this.last4digits = getLast4digits();
+ }
+
+ /**
+ * Public constructor for a Card object using field values:
+ *
+ * @param number - card number
+ * @param expiryMonth - card expiry month
+ * @param expiryYear - card expiry year
+ * @param cvc - card CVC
+ * @param name - card owner's name
+ * @param addressLine1 - address line 1
+ * @param addressLine2 - address line 2
+ * @param addressLine3 - address line 3
+ * @param addressLine4 - address line 4
+ * @param addressCountry - address country
+ * @param addressPostalCode - address postal code
+ * @param country - card country
+ */
+ public Card(String number, Integer expiryMonth, Integer expiryYear, String cvc, String name,
+ String addressLine1, String addressLine2, String addressLine3, String addressLine4,
+ String addressCountry, String addressPostalCode, String country) {
+ this.number = StringUtils.nullify(number);
+ this.expiryMonth = expiryMonth;
+ this.expiryYear = expiryYear;
+ this.cvc = StringUtils.nullify(cvc);
+
+ this.name = StringUtils.nullify(name);
+ this.addressLine1 = StringUtils.nullify(addressLine1);
+ this.addressLine2 = StringUtils.nullify(addressLine2);
+ this.addressLine3 = StringUtils.nullify(addressLine3);
+ this.addressLine4 = StringUtils.nullify(addressLine4);
+ this.addressCountry = StringUtils.nullify(addressCountry);
+ this.addressPostalCode = StringUtils.nullify(addressPostalCode);
+
+ this.country = StringUtils.nullify(country);
+
+ this.type = getType();
+ this.last4digits = getLast4digits();
+ }
+
+ /**
+ * Public constructor for a Card object using field values:
+ *
+ * @param number - card number
+ * @param expiryMonth - card expiry month
+ * @param expiryYear - card expiry year
+ * @param cvc - card CVC
+ * @param name - card owner's name
+ * @param addressLine1 - address line 1
+ * @param addressLine2 - address line 2
+ * @param addressLine3 - address line 3
+ * @param addressLine4 - address line 4
+ * @param addressCountry - address country
+ * @param addressPostalCode - address postal code
+ */
+ public Card(String number, Integer expiryMonth, Integer expiryYear, String cvc, String name,
+ String addressLine1, String addressLine2, String addressLine3, String addressLine4,
+ String addressCountry, String addressPostalCode) {
+ this(number, expiryMonth, expiryYear, cvc, name, addressLine1, addressLine2, addressLine3,
+ addressLine4, addressCountry, addressPostalCode, null);
+ }
+
+ /**
+ * Public constructor for a Card object using field values:
+ *
+ * @param number - card number
+ * @param expiryMonth - card expiry month
+ * @param expiryYear - card expiry year
+ * @param cvc - card CVC
+ * @param name - card owner's name
+ */
+ public Card(String number, Integer expiryMonth, Integer expiryYear, String cvc, String name) {
+ this(number, expiryMonth, expiryYear, cvc, name, null, null, null,
+ null, null, null);
+ }
+
+ /**
+ * Public constructor for a Card object using field values:
+ *
+ * @param number - card number
+ * @param expiryMonth - card expiry month
+ * @param expiryYear - card expiry year
+ * @param cvc - card CVC
+ */
+ public Card(String number, Integer expiryMonth, Integer expiryYear, String cvc) {
+ this(number, expiryMonth, expiryYear, cvc, null, null, null, null,
+ null, null, null);
+ }
+
+ /**
+ * Validates the Card object
+ *
+ * @return True if card is valid, false otherwise
+ */
+ public boolean isValid() {
+ //if it has a cvc, validate number, validate expiry date and validate cvc
+ if (cvc != null) {
+ return validNumber() && validExpiryDate() && validCVC();
+ } else {
+ return validNumber() && validExpiryDate();
+ }
+ }
+
+ /**
+ * Method that validates the CVC or CVV of the card object
+ *
+ * @return true if the cvc is valid
+ */
+ public boolean validCVC() {
+ //validate cvc
+ if (StringUtils.isEmpty(cvc)) {
+ return false;
+ }
+ String cvcValue = cvc.trim();
+
+ boolean validLength = ((type == null && cvcValue.length() >= 3 && cvcValue.length() <= 4) ||
+ (CardType.AMERICAN_EXPRESS.equals(type) && cvcValue.length() == 4) ||
+ (!CardType.AMERICAN_EXPRESS.equals(type) && cvcValue.length() == 3));
+
+ return !(!CardUtils.isWholePositiveNumber(cvcValue) || !validLength);
+ }
+
+ /**
+ * Method that validates the card number of the card object
+ *
+ * @return true if the card number is valid
+ */
+ public boolean validNumber() {
+ if (StringUtils.isEmpty(number)) return false;
+
+ //remove all spaces
+ String formattedNumber = number.trim().replaceAll("\\s+|-", "");
+
+ //check if formattedNumber is empty or card isn't a hwole positive number or isn't Luhn-valid
+ if (StringUtils.isEmpty(formattedNumber)
+ || !CardUtils.isWholePositiveNumber(number)
+ || !isValidLuhnNumber(number)) {
+ return false;
+ }
+
+ //check type for lengths
+ if (CardType.AMERICAN_EXPRESS.equals(type)) {
+ return formattedNumber.length() == CardType.MAX_LENGTH_AMERICAN_EXPRESS;
+ } else if (CardType.DINERS_CLUB.equals(type)) {
+ return formattedNumber.length() == CardType.MAX_LENGTH_DINERS_CLUB;
+ } else {
+ return formattedNumber.length() == CardType.MAX_LENGTH_NORMAL;
+ }
+ }
+
+ /**
+ * Validates the number against Luhn algorithm https://de.wikipedia.org/wiki/Luhn-Algorithmus#Java
+ *
+ * @param number - number to validate
+ * @return true if the number is Luhn-valid
+ */
+ private boolean isValidLuhnNumber(String number) {
+ int sum = 0;
+ int length = number.trim().length();
+
+ //iterate through from the rear
+ for (int i = 0; i < length; i++) {
+ char c = number.charAt(length - 1 - i);
+
+ //check if character is a digit before parsing it
+ if (!Character.isDigit(c)) {
+ return false;
+ }
+
+ int digit = Integer.parseInt(c + "");
+
+ //if it's odd, multiply by 2
+ if (i % 2 == 1)
+ digit *= 2;
+
+ sum += digit > 9 ? digit - 9 : digit;
+ }
+ return sum % 10 == 0;
+ }
+
+ /**
+ * Method that validates the expiry date of the card
+ *
+ * @return true if the expiry date is valid or hasn't been passed, false otherwise
+ */
+ public boolean validExpiryDate() {
+ //validate month and year
+ return !(expiryMonth == null || expiryYear == null) && CardUtils.isExpired(expiryYear, expiryMonth);
+
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getNumber() {
+ return number;
+ }
+
+ public void setNumber(String number) {
+ this.number = number;
+ }
+
+ public String getCvc() {
+ return cvc;
+ }
+
+ public void setCvc(String cvc) {
+ this.cvc = cvc;
+ }
+
+ public Integer getExpiryMonth() {
+ return expiryMonth;
+ }
+
+ public void setExpiryMonth(Integer expiryMonth) {
+ this.expiryMonth = expiryMonth;
+ }
+
+ public Integer getExpiryYear() {
+ return expiryYear;
+ }
+
+ public void setExpiryYear(Integer expiryYear) {
+ this.expiryYear = expiryYear;
+ }
+
+ public String getAddressLine1() {
+ return addressLine1;
+ }
+
+ public void setAddressLine1(String addressLine1) {
+ this.addressLine1 = addressLine1;
+ }
+
+ public String getAddressLine2() {
+ return addressLine2;
+ }
+
+ public void setAddressLine2(String addressLine2) {
+ this.addressLine2 = addressLine2;
+ }
+
+ public String getAddressLine3() {
+ return addressLine3;
+ }
+
+ public void setAddressLine3(String addressLine3) {
+ this.addressLine3 = addressLine3;
+ }
+
+ public String getAddressLine4() {
+ return addressLine4;
+ }
+
+ public void setAddressLine4(String addressLine4) {
+ this.addressLine4 = addressLine4;
+ }
+
+ public String getAddressPostalCode() {
+ return addressPostalCode;
+ }
+
+ public void setAddressPostalCode(String addressPostalCode) {
+ this.addressPostalCode = addressPostalCode;
+ }
+
+ public String getAddressCountry() {
+ return addressCountry;
+ }
+
+ public void setAddressCountry(String addressCountry) {
+ this.addressCountry = addressCountry;
+ }
+
+ public String getCountry() {
+ return country;
+ }
+
+ public void setCountry(String country) {
+ this.country = country;
+ }
+
+ /**
+ * Method that returns the type of the card
+ *
+ * @return a String representation of the card type detected. You can use this to improve the experience on your form,
+ * to display the card type logo, while the user is entering the card number e.g MasterCard, Discover, Visa etc.
+ */
+ public String getType() {
+ //if type is empty and the number isn't empty
+ if (StringUtils.isEmpty(type) && !StringUtils.isEmpty(number)) {
+ for (CardType cardType : cardTypes) {
+ if (cardType.matches(number)) {
+ return cardType.toString();
+ }
+ }
+ return CardType.UNKNOWN;
+ }
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public String getLast4digits() {
+ return last4digits;
+ }
+
+ public void setLast4digits(String last4digits) {
+ this.last4digits = last4digits;
+ }
+
+ /**
+ * Builder class to build a card;
+ */
+ public static class Builder {
private String name;
-
- /**
- * Card number
- */
private String number;
-
- /**
- * CVC number
- */
private String cvc;
-
- /**
- * Expiry month
- */
private Integer expiryMonth;
-
- /**
- * Expiry year
- */
private Integer expiryYear;
-
- /**
- * Bank Address line 1-4
- */
private String addressLine1;
private String addressLine2;
private String addressLine3;
private String addressLine4;
-
- /**
- * Postal code of the bank address
- */
private String addressPostalCode;
-
- /**
- * Country of the bank
- */
private String addressCountry;
-
-
private String country;
-
- /**
- * Type of card
- */
private String type;
-
private String last4digits;
-
- /**
- * Builder class to build a card;
- */
- public static class Builder{
- private String name;
- private String number;
- private String cvc;
- private Integer expiryMonth;
- private Integer expiryYear;
- private String addressLine1;
- private String addressLine2;
- private String addressLine3;
- private String addressLine4;
- private String addressPostalCode;
- private String addressCountry;
- private String country;
- private String type;
- private String last4digits;
-
- /**
- * Public constructor for the builder, with important fields set
- * @param number
- * @param expiryMonth
- * @param expiryYear
- * @param cvc
- */
- public Builder(String number, Integer expiryMonth, Integer expiryYear, String cvc){
- this.number = number;
- this.expiryMonth = expiryMonth;
- this.expiryYear = expiryYear;
- this.cvc = cvc;
- }
-
- public Builder setName(String name){
- this.name = name;
- return this;
- }
- public Builder setAddressLine1(String addressLine1) {
- this.addressLine1 = addressLine1;
- return this;
- }
-
- public Builder setAddressLine2(String addressLine2) {
- this.addressLine2 = addressLine2;
- return this;
- }
-
- public Builder setAddressLine3(String addressLine3) {
- this.addressLine3 = addressLine3;
- return this;
- }
-
- public Builder setAddressLine4(String addressLine4) {
- this.addressLine4 = addressLine4;
- return this;
- }
-
- public Builder setAddressCountry(String addressCountry) {
- this.addressCountry = addressCountry;
- return this;
- }
-
- public Builder setAddressPostalCode(String addressPostalCode) {
- this.addressPostalCode = addressPostalCode;
- return this;
- }
-
-
- public Builder setCountry(String country) {
- this.country = country;
- return this;
- }
-
-
- public Builder setLast4digits(String last4digits) {
- this.last4digits = last4digits;
- return this;
- }
-
- public Builder setType(String type) {
- this.type = type;
- return this;
- }
-
-
- public Card build(){
- return new Card(this);
- }
- }
-
- /**
- * Private constructor for a Card object, using a Builder;
- * @param builder
- */
- private Card(Builder builder){
- this.number = StringUtils.nullify(builder.number);
- this.expiryMonth = builder.expiryMonth;
- this.expiryYear = builder.expiryYear;
- this.cvc = StringUtils.nullify(builder.cvc);
-
- this.name = StringUtils.nullify(builder.name);
- this.addressLine1 = StringUtils.nullify(builder.addressLine1);
- this.addressLine2 = StringUtils.nullify(builder.addressLine2);
- this.addressLine3 = StringUtils.nullify(builder.addressLine3);
- this.addressLine4 = StringUtils.nullify(builder.addressLine4);
- this.addressCountry = StringUtils.nullify(builder.addressCountry);
- this.addressPostalCode = StringUtils.nullify(builder.addressPostalCode);
-
- this.country = StringUtils.nullify(builder.country);
- this.type = getType();
- this.last4digits = getLast4digits();
- }
-
- /**
- * Public constructor for a Card object using field values:
- * @param number
- * @param expiryMonth
- * @param expiryYear
- * @param cvc
- * @param name
- * @param addressLine1
- * @param addressLine2
- * @param addressLine3
- * @param addressLine4
- * @param addressCountry
- * @param addressPostalCode
- * @param country
- * @param type
- * @param last4digits
- */
- public Card(String number, Integer expiryMonth, Integer expiryYear, String cvc, String name,
- String addressLine1, String addressLine2, String addressLine3, String addressLine4,
- String addressCountry, String addressPostalCode, String country, String type, String last4digits){
- this.number = StringUtils.nullify(number);
- this.expiryMonth = expiryMonth;
- this.expiryYear = expiryYear;
- this.cvc = StringUtils.nullify(cvc);
-
- this.name = StringUtils.nullify(name);
- this.addressLine1 = StringUtils.nullify(addressLine1);
- this.addressLine2 = StringUtils.nullify(addressLine2);
- this.addressLine3 = StringUtils.nullify(addressLine3);
- this.addressLine4 = StringUtils.nullify(addressLine4);
- this.addressCountry = StringUtils.nullify(addressCountry);
- this.addressPostalCode = StringUtils.nullify(addressPostalCode);
-
- this.country = StringUtils.nullify(country);
-
- this.type = getType();
- this.last4digits = getLast4digits();
- }
-
- /**
- * Public constructor for a Card object using field values:
- * @param number
- * @param expiryMonth
- * @param expiryYear
- * @param cvc
- * @param name
- * @param addressLine1
- * @param addressLine2
- * @param addressLine3
- * @param addressLine4
- * @param addressCountry
- * @param addressPostalCode
- */
- public Card(String number, Integer expiryMonth, Integer expiryYear, String cvc, String name,
- String addressLine1, String addressLine2, String addressLine3, String addressLine4,
- String addressCountry, String addressPostalCode){
- this(number, expiryMonth, expiryYear, cvc, name, addressLine1, addressLine2, addressLine3,
- addressLine4, addressCountry, addressPostalCode, null, null, null);
- }
-
- /**
- * Public constructor for a Card object using field values:
- * @param number
- * @param expiryMonth
- * @param expiryYear
- * @param cvc
- * @param name
- */
- public Card(String number, Integer expiryMonth, Integer expiryYear, String cvc, String name){
- this(number, expiryMonth, expiryYear, cvc, name, null, null, null,
- null, null, null);
- }
-
- /**
- * Public constructor for a Card object using field values:
- * @param number
- * @param expiryMonth
- * @param expiryYear
- * @param cvc
- */
- public Card(String number, Integer expiryMonth, Integer expiryYear, String cvc){
- this(number, expiryMonth, expiryYear, cvc, null, null, null, null,
- null, null, null);
- }
-
- /**
- * Validates the Card object
- * @return True if card is valid, false otherwise
- */
- public boolean isValid(){
- //if it has a cvc, validate number, validate expiry date and validate cvc
- if(cvc != null){
- return validNumber() && validExpiryDate() && validCVC();
- }
- else{
- return validNumber() && validExpiryDate();
- }
- }
-
- /**
- * Method that validates the CVC or CVV of the card object
- *
- * @return true if the cvc is valid
- */
- public boolean validCVC(){
- //validate cvc
- if (StringUtils.isEmpty(cvc)) {
- return false;
- }
- String cvcValue = cvc.trim();
-
- boolean validLength = ((type == null && cvcValue.length() >= 3 && cvcValue.length() <= 4) ||
- (CardType.AMERICAN_EXPRESS.equals(type) && cvcValue.length() == 4) ||
- (!CardType.AMERICAN_EXPRESS.equals(type) && cvcValue.length() == 3));
-
- if (!CardUtils.isWholePositiveNumber(cvcValue) || !validLength) {
- return false;
- }
- return true;
- }
-
- /**
- * Method that validates the card number of the card object
- *
- * @return true if the card number is valid
- */
- public boolean validNumber(){
- if(StringUtils.isEmpty(number)) return false;
-
- //remove all spaces
- String formattedNumber = number.trim().replaceAll("\\s+|-", "");
-
- //check if formattedNumber is empty or card isn't a hwole positive number or isn't Luhn-valid
- if(StringUtils.isEmpty(formattedNumber)
- || !CardUtils.isWholePositiveNumber(number)
- || !isValidLuhnNumber(number)){
- return false;
- }
-
- //check type for lengths
- if(CardType.AMERICAN_EXPRESS.equals(type)){
- return formattedNumber.length() == CardType.MAX_LENGTH_AMERICAN_EXPRESS;
- }
- else if(CardType.DINERS_CLUB.equals(type)){
- return formattedNumber.length() == CardType.MAX_LENGTH_DINERS_CLUB;
- }
- else{
- return formattedNumber.length() == CardType.MAX_LENGTH_NORMAL;
- }
- }
-
/**
- * Validates the number against Luhn algorithm https://de.wikipedia.org/wiki/Luhn-Algorithmus#Java
+ * Public constructor for the builder, with important fields set
*
- * @param number
- * @return true if the number is Luhn-valid
- */
- private boolean isValidLuhnNumber(String number){
- int sum = 0;
- int length = number.trim().length();
-
- //iterate through from the rear
- for(int i=0; i 9 ? digit - 9 : digit;
- }
- return sum % 10 == 0;
- }
-
- /**
- * Method that validates the expiry date of the card
- * @return true if the expiry date is valid or hasn't been passed, false otherwise
+ * @param number - Card number
+ * @param expiryMonth - card Expiry Month
+ * @param expiryYear - card Expiry Year
+ * @param cvc - Card CVC
*/
- public boolean validExpiryDate(){
- //validate month and year
- if(expiryMonth == null || expiryYear == null)
- return false;
-
- return CardUtils.isExpired(expiryYear, expiryMonth);
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public String getNumber() {
- return number;
+ public Builder(String number, Integer expiryMonth, Integer expiryYear, String cvc) {
+ this.number = number;
+ this.expiryMonth = expiryMonth;
+ this.expiryYear = expiryYear;
+ this.cvc = cvc;
}
- public void setNumber(String number) {
- this.number = number;
+ public Builder setName(String name) {
+ this.name = name;
+ return this;
}
- public String getCvc() {
- return cvc;
+ public Builder setAddressLine1(String addressLine1) {
+ this.addressLine1 = addressLine1;
+ return this;
}
- public void setCvc(String cvc) {
- this.cvc = cvc;
+ public Builder setAddressLine2(String addressLine2) {
+ this.addressLine2 = addressLine2;
+ return this;
}
- public Integer getExpiryMonth() {
- return expiryMonth;
+ public Builder setAddressLine3(String addressLine3) {
+ this.addressLine3 = addressLine3;
+ return this;
}
- public void setExpiryMonth(Integer expiryMonth) {
- this.expiryMonth = expiryMonth;
+ public Builder setAddressLine4(String addressLine4) {
+ this.addressLine4 = addressLine4;
+ return this;
}
- public Integer getExpiryYear() {
- return expiryYear;
+ public Builder setAddressCountry(String addressCountry) {
+ this.addressCountry = addressCountry;
+ return this;
}
- public void setExpiryYear(Integer expiryYear) {
- this.expiryYear = expiryYear;
+ public Builder setAddressPostalCode(String addressPostalCode) {
+ this.addressPostalCode = addressPostalCode;
+ return this;
}
- public String getAddressLine1() {
- return addressLine1;
- }
-
- public void setAddressLine1(String addressLine1) {
- this.addressLine1 = addressLine1;
- }
-
- public String getAddressLine2() {
- return addressLine2;
- }
- public void setAddressLine2(String addressLine2) {
- this.addressLine2 = addressLine2;
+ public Builder setCountry(String country) {
+ this.country = country;
+ return this;
}
- public String getAddressLine3() {
- return addressLine3;
- }
- public void setAddressLine3(String addressLine3) {
- this.addressLine3 = addressLine3;
+ public Builder setLast4digits(String last4digits) {
+ this.last4digits = last4digits;
+ return this;
}
- public String getAddressLine4() {
- return addressLine4;
+ public Builder setType(String type) {
+ this.type = type;
+ return this;
}
- public void setAddressLine4(String addressLine4) {
- this.addressLine4 = addressLine4;
- }
- public String getAddressPostalCode() {
- return addressPostalCode;
+ public Card build() {
+ return new Card(this);
}
+ }
- public void setAddressPostalCode(String addressPostalCode) {
- this.addressPostalCode = addressPostalCode;
- }
+ public static abstract class CardType {
+ //card types
+ public static final String VISA = "Visa";
+ public static final String MASTERCARD = "MasterCard";
+ public static final String AMERICAN_EXPRESS = "American Express";
+ public static final String DINERS_CLUB = "Diners Club";
+ public static final String DISCOVER = "Discover";
+ public static final String JCB = "JCB";
+ public static final String UNKNOWN = "Unknown";
+ //lengths for some cards
+ public static final int MAX_LENGTH_NORMAL = 16;
+ public static final int MAX_LENGTH_AMERICAN_EXPRESS = 15;
+ public static final int MAX_LENGTH_DINERS_CLUB = 14;
+ //source of these regex patterns http://stackoverflow.com/questions/72768/how-do-you-detect-credit-card-type-based-on-number
+ static final String PATTERN_VISA = "^4[0-9]{6,}$";
+ static final String PATTERN_MASTERCARD = "^5[1-5][0-9]{5,}$";
+ static final String PATTERN_AMERICAN_EXPRESS = "^3[47][0-9]{5,}$";
+ static final String PATTERN_DINERS_CLUB = "^3(?:0[0-5]|[68][0-9])[0-9]{4,}$";
+ static final String PATTERN_DISCOVER = "^6(?:011|5[0-9]{2})[0-9]{3,}$";
+ static final String PATTERN_JCB = "^(?:2131|1800|35[0-9]{3})[0-9]{3,}$";
- public String getAddressCountry() {
- return addressCountry;
- }
+ public abstract boolean matches(String card);
- public void setAddressCountry(String addressCountry) {
- this.addressCountry = addressCountry;
- }
+ @Override
+ public abstract String toString();
+ }
- public String getCountry() {
- return country;
+ /**
+ * Private clsas for VISA card
+ */
+ private static class Visa extends CardType {
+ @Override
+ public boolean matches(String card) {
+ return card.matches(PATTERN_VISA);
}
- public void setCountry(String country) {
- this.country = country;
+ @Override
+ public String toString() {
+ return VISA;
}
+ }
- /**
- * Method that returns the type of the card
- * @return a String representation of the card type detected. You can use this to improve the experience on your form,
- * to display the card type logo, while the user is entering the card number e.g MasterCard, Discover, Visa etc.
- */
- public String getType() {
- //if type is empty and the number isn't empty
- if(StringUtils.isEmpty(type) && !StringUtils.isEmpty(number)){
- for(CardType cardType : cardTypes){
- if(cardType.matches(number)){
- return cardType.toString();
- }
- }
- return CardType.UNKNOWN;
- }
- return type;
+ private static class MasterCard extends CardType {
+ @Override
+ public boolean matches(String card) {
+ return card.matches(PATTERN_MASTERCARD);
}
- public void setType(String type) {
- this.type = type;
+ @Override
+ public String toString() {
+ return MASTERCARD;
}
+ }
- public String getLast4digits() {
- return last4digits;
+ private static class AmericanExpress extends CardType {
+ @Override
+ public boolean matches(String card) {
+ return card.matches(PATTERN_AMERICAN_EXPRESS);
}
- public void setLast4digits(String last4digits) {
- this.last4digits = last4digits;
+ @Override
+ public String toString() {
+ return AMERICAN_EXPRESS;
}
+ }
- /**
- * List of cardTypes
- *
- */
- private static final List cardTypes = Arrays.asList(
- new Visa(),
- new MasterCard(),
- new AmericanExpress(),
- new DinersClub(),
- new Jcb(),
- new Discover()
- );
-
- public static abstract class CardType{
- //card types
- public static final String VISA = "Visa";
- public static final String MASTERCARD = "MasterCard";
- public static final String AMERICAN_EXPRESS = "American Express";
- public static final String DINERS_CLUB = "Diners Club";
- public static final String DISCOVER = "Discover";
- public static final String JCB = "JCB";
- public static final String UNKNOWN = "Unknown";
-
- //source of these regex patterns http://stackoverflow.com/questions/72768/how-do-you-detect-credit-card-type-based-on-number
- static final String PATTERN_VISA = "^4[0-9]{6,}$";
- static final String PATTERN_MASTERCARD = "^5[1-5][0-9]{5,}$";
- static final String PATTERN_AMERICAN_EXPRESS = "^3[47][0-9]{5,}$";;
- static final String PATTERN_DINERS_CLUB = "^3(?:0[0-5]|[68][0-9])[0-9]{4,}$";
- static final String PATTERN_DISCOVER = "^6(?:011|5[0-9]{2})[0-9]{3,}$";
- static final String PATTERN_JCB = "^(?:2131|1800|35[0-9]{3})[0-9]{3,}$";
-
- //lengths for some cards
- public static final int MAX_LENGTH_NORMAL = 16;
- public static final int MAX_LENGTH_AMERICAN_EXPRESS = 15;
- public static final int MAX_LENGTH_DINERS_CLUB = 14;
-
-
- public abstract boolean matches(String card);
-
- @Override
- public abstract String toString();
+ private static class DinersClub extends CardType {
+ @Override
+ public boolean matches(String card) {
+ return card.matches(PATTERN_DINERS_CLUB);
}
- /**
- * Private clsas for VISA card
- */
- private static class Visa extends CardType{
- @Override
- public boolean matches(String card) {
- return card.matches(PATTERN_VISA);
- }
- @Override
- public String toString() {
- return VISA;
- }
+ @Override
+ public String toString() {
+ return DINERS_CLUB;
}
+ }
- private static class MasterCard extends CardType{
- @Override
- public boolean matches(String card) {
- return card.matches(PATTERN_MASTERCARD);
- }
- @Override
- public String toString() {
- return MASTERCARD;
- }
- }
+ private static class Discover extends CardType {
- private static class AmericanExpress extends CardType{
- @Override
- public boolean matches(String card) {
- return card.matches(PATTERN_AMERICAN_EXPRESS);
- }
- @Override
- public String toString() {
- return AMERICAN_EXPRESS;
- }
+ @Override
+ public boolean matches(String card) {
+ return card.matches(PATTERN_DISCOVER);
}
- private static class DinersClub extends CardType{
- @Override
- public boolean matches(String card) {
- return card.matches(PATTERN_DINERS_CLUB);
- }
-
- @Override
- public String toString() {
- return DINERS_CLUB;
- }
+ @Override
+ public String toString() {
+ return DISCOVER;
}
+ }
- private static class Discover extends CardType{
-
- @Override
- public boolean matches(String card) {
- return card.matches(PATTERN_DISCOVER);
- }
+ private static class Jcb extends CardType {
- @Override
- public String toString() {
- return DISCOVER;
- }
+ @Override
+ public boolean matches(String card) {
+ return card.matches(PATTERN_JCB);
}
- private static class Jcb extends CardType{
-
- @Override
- public boolean matches(String card) {
- return card.matches(PATTERN_JCB);
- }
-
- @Override
- public String toString() {
- return JCB;
- }
+ @Override
+ public String toString() {
+ return JCB;
}
+ }
}
diff --git a/paystack/src/main/java/co/paystack/android/model/PaystackModel.java b/paystack/src/main/java/co/paystack/android/model/PaystackModel.java
index 90ebec6..e0952e6 100644
--- a/paystack/src/main/java/co/paystack/android/model/PaystackModel.java
+++ b/paystack/src/main/java/co/paystack/android/model/PaystackModel.java
@@ -3,7 +3,7 @@
/**
* Base class for Paystack Model classes
*
- * @author {androidsupport@paystack.co} on 9/13/15.
+ * @author {androidsupport@paystack.co} on 9/13/15.
*/
public abstract class PaystackModel {
}
diff --git a/paystack/src/main/java/co/paystack/android/model/Token.java b/paystack/src/main/java/co/paystack/android/model/Token.java
index 0593bfa..1296652 100644
--- a/paystack/src/main/java/co/paystack/android/model/Token.java
+++ b/paystack/src/main/java/co/paystack/android/model/Token.java
@@ -1,21 +1,17 @@
package co.paystack.android.model;
-import android.os.Parcel;
-import android.os.Parcelable;
-
import java.io.Serializable;
/**
* The class for Token model.
*
- * @author {androidsupport@paystack.co} on 8/10/15.
+ * @author {androidsupport@paystack.co} on 8/10/15.
*/
-public class Token implements Serializable{
-
- public String token;
+public class Token implements Serializable {
- public String last4;
+ public String token;
+ public String last4;
// private Token(Parcel in){
diff --git a/paystack/src/main/java/co/paystack/android/utils/CardUtils.java b/paystack/src/main/java/co/paystack/android/utils/CardUtils.java
index 5457a77..de5df0b 100644
--- a/paystack/src/main/java/co/paystack/android/utils/CardUtils.java
+++ b/paystack/src/main/java/co/paystack/android/utils/CardUtils.java
@@ -6,53 +6,54 @@
/**
* Utils used with the Card model.
*
- * @author {androidsupport@paystack.co} on 9/13/15.
+ * @author {androidsupport@paystack.co} on 9/13/15.
*/
public class CardUtils {
- public static boolean isWholePositiveNumber(String value) {
- if (value == null) {
- return false;
- }
- for (char c : value.toCharArray()) {
- if (!Character.isDigit(c)) {
- return false;
- }
- }
- return true;
+ public static boolean isWholePositiveNumber(String value) {
+ if (value == null) {
+ return false;
}
-
- public static boolean hasMonthPassed(int year, int month){
- Calendar now = Calendar.getInstance();
- // Expires at end of specified month, Calendar month starts at 0
- return hasYearPassed(year) || normalizeYear(year) == now.get(Calendar.YEAR) && month < (now.get(Calendar.MONTH) + 1);
+ for (char c : value.toCharArray()) {
+ if (!Character.isDigit(c)) {
+ return false;
+ }
}
+ return true;
+ }
- public static boolean hasYearPassed(int year){
- int normalized = normalizeYear(year);
- Calendar now = Calendar.getInstance();
- return normalized < now.get(Calendar.YEAR);
- }
+ public static boolean hasMonthPassed(int year, int month) {
+ Calendar now = Calendar.getInstance();
+ // Expires at end of specified month, Calendar month starts at 0
+ return hasYearPassed(year) || normalizeYear(year) == now.get(Calendar.YEAR) && month < (now.get(Calendar.MONTH) + 1);
+ }
- /**
- * Check if card is expired
- * @param year - Non-zero based index for year
- * @param month - Non-zero based index for month
- * @return true if the card has expired.
- */
- public static boolean isExpired(int year, int month){
- //check if year && month have passed
- return !hasYearPassed(year) && !hasMonthPassed(year, month);
- }
+ public static boolean hasYearPassed(int year) {
+ int normalized = normalizeYear(year);
+ Calendar now = Calendar.getInstance();
+ return normalized < now.get(Calendar.YEAR);
+ }
+
+ /**
+ * Check if card is expired
+ *
+ * @param year - Non-zero based index for year
+ * @param month - Non-zero based index for month
+ * @return true if the card has expired.
+ */
+ public static boolean isExpired(int year, int month) {
+ //check if year && month have passed
+ return !hasYearPassed(year) && !hasMonthPassed(year, month);
+ }
- // Convert two-digit year to full year if necessary
- private static int normalizeYear(int year) {
- if (year < 100 && year >= 0) {
- Calendar now = Calendar.getInstance();
- String currentYear = String.valueOf(now.get(Calendar.YEAR));
- String prefix = currentYear.substring(0, currentYear.length() - 2);
- year = Integer.parseInt(String.format(Locale.US, "%s%02d", prefix, year));
- }
- return year;
+ // Convert two-digit year to full year if necessary
+ private static int normalizeYear(int year) {
+ if (year < 100 && year >= 0) {
+ Calendar now = Calendar.getInstance();
+ String currentYear = String.valueOf(now.get(Calendar.YEAR));
+ String prefix = currentYear.substring(0, currentYear.length() - 2);
+ year = Integer.parseInt(String.format(Locale.US, "%s%02d", prefix, year));
}
+ return year;
+ }
}
diff --git a/paystack/src/main/java/co/paystack/android/utils/Crypto.java b/paystack/src/main/java/co/paystack/android/utils/Crypto.java
index b43d8b4..dccd4b8 100644
--- a/paystack/src/main/java/co/paystack/android/utils/Crypto.java
+++ b/paystack/src/main/java/co/paystack/android/utils/Crypto.java
@@ -1,14 +1,14 @@
package co.paystack.android.utils;
import android.util.Base64;
-import android.util.Log;
+
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
-import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
+
import javax.crypto.Cipher;
import co.paystack.android.exceptions.AuthenticationException;
@@ -17,78 +17,73 @@
/**
* Class for encrypting the card details, for token creation.
*
- * @author {androidsupport@paystack.co} on 8/10/15.
+ * @author {androidsupport@paystack.co} on 8/10/15.
*/
public class Crypto {
- private static String ALGORITHM = "RSA";
- private static String CIPHER = "RSA/ECB/PKCS1Padding";
+ private static String ALGORITHM = "RSA";
+ private static String CIPHER = "RSA/ECB/PKCS1Padding";
- private static byte[] encrypt(String text, PublicKey key) {
- byte[] cipherText = null;
+ private static byte[] encrypt(String text, PublicKey key) {
+ byte[] cipherText = null;
- try {
+ try {
- // get an RSA cipher object
- final Cipher cipher = Cipher.getInstance(CIPHER);
+ // get an RSA cipher object
+ final Cipher cipher = Cipher.getInstance(CIPHER);
- //init cipher and encrypt the plain text using the public key
- cipher.init(Cipher.ENCRYPT_MODE, key);
- cipherText = cipher.doFinal(text.getBytes());
+ //init cipher and encrypt the plain text using the public key
+ cipher.init(Cipher.ENCRYPT_MODE, key);
+ cipherText = cipher.doFinal(text.getBytes());
- } catch (Exception e) {
+ } catch (Exception e) {
- e.printStackTrace();
- }
- return cipherText;
- }
- public static String encrypt(String text, String publicKey) throws AuthenticationException{
- String cipher = new String(Base64.encode(encrypt(text, getPublicKeyFromString(publicKey)), Base64.NO_WRAP));
- return cipher;
+ e.printStackTrace();
}
+ return cipherText;
+ }
- private static String decrypt(byte[] text, PrivateKey key) {
- byte[] dectyptedText = null;
-
- try {
- // get an RSA cipher object
- final Cipher cipher = Cipher.getInstance(CIPHER);
-
- //init cipher and decrypt the text using the private key
- cipher.init(Cipher.DECRYPT_MODE, key);
- dectyptedText = cipher.doFinal(text);
- }
- catch (Exception ex) {
- ex.printStackTrace();
- }
- return new String(dectyptedText);
- }
+ public static String encrypt(String text, String publicKey) throws AuthenticationException {
+ return new String(Base64.encode(encrypt(text, getPublicKeyFromString(publicKey)), Base64.NO_WRAP));
+ }
- private static PublicKey getPublicKeyFromString(String pubKey) throws AuthenticationException{
+ private static String decrypt(byte[] text, PrivateKey key) {
+ byte[] decryptedText = null;
- PublicKey key = null;
+ try {
+ // get an RSA cipher object
+ final Cipher cipher = Cipher.getInstance(CIPHER);
- try{
- //init keyfactory
- KeyFactory kf = KeyFactory.getInstance(ALGORITHM);
+ //init cipher and decrypt the text using the private key
+ cipher.init(Cipher.DECRYPT_MODE, key);
+ decryptedText = cipher.doFinal(text);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ return new String((decryptedText != null) ? decryptedText : new byte[0]);
+ }
+
+ private static PublicKey getPublicKeyFromString(String pubKey) throws AuthenticationException {
- //decode the key into a byte array
- byte[] keyBytes = Base64.decode(pubKey, Base64.NO_WRAP);
+ PublicKey key;
- //create spec
- X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
+ try {
+ //init keyfactory
+ KeyFactory kf = KeyFactory.getInstance(ALGORITHM);
- //generate public key
- key = kf.generatePublic(spec);
- }
- catch (InvalidKeySpecException e) {
- throw new AuthenticationException("Invalid publishable key: " + e.getMessage());
- }
- catch (NoSuchAlgorithmException e) {
- throw new AuthenticationException("Invalid publishable key: " + e.getMessage());
- }
- return key;
+ //decode the key into a byte array
+ byte[] keyBytes = Base64.decode(pubKey, Base64.NO_WRAP);
+ //create spec
+ X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
+ //generate public key
+ key = kf.generatePublic(spec);
+ } catch (InvalidKeySpecException | NoSuchAlgorithmException e) {
+ throw new AuthenticationException("Invalid publishable key: " + e.getMessage());
}
+ return key;
+
+
+ }
}
diff --git a/paystack/src/main/java/co/paystack/android/utils/Logger.java b/paystack/src/main/java/co/paystack/android/utils/Logger.java
index bb16149..9941034 100644
--- a/paystack/src/main/java/co/paystack/android/utils/Logger.java
+++ b/paystack/src/main/java/co/paystack/android/utils/Logger.java
@@ -5,30 +5,30 @@
/**
* Logger util class
*
- * @author {androidsupport@paystack.co} on 9/18/15.
+ * @author {androidsupport@paystack.co} on 9/18/15.
*/
public class Logger {
- public static boolean DEBUG_ON = false;
- public static String DEFAULT_TAG = "Paystack";
+ public static boolean DEBUG_ON = false;
+ public static String DEFAULT_TAG = "Paystack";
- public static void d(String tag, String message){
- if(DEBUG_ON)
- Log.d(tag, message);
- }
+ public static void d(String tag, String message) {
+ if (DEBUG_ON)
+ Log.d(tag, message);
+ }
- public static void d(String message){
- d(DEFAULT_TAG, message);
- }
+ public static void d(String message) {
+ d(DEFAULT_TAG, message);
+ }
+ public static void e(String tag, String message) {
+ if (DEBUG_ON)
+ Log.e(tag, message);
+ }
- public static void e(String tag, String message){
- if(DEBUG_ON)
- Log.e(tag, message);
- }
- public static void e(String message){
- e(DEFAULT_TAG, message);
- }
+ public static void e(String message) {
+ e(DEFAULT_TAG, message);
+ }
}
diff --git a/paystack/src/main/java/co/paystack/android/utils/StringUtils.java b/paystack/src/main/java/co/paystack/android/utils/StringUtils.java
index 1bf29e1..7961630 100644
--- a/paystack/src/main/java/co/paystack/android/utils/StringUtils.java
+++ b/paystack/src/main/java/co/paystack/android/utils/StringUtils.java
@@ -1,33 +1,30 @@
package co.paystack.android.utils;
-import android.text.TextUtils;
-
-import org.parceler.guava.primitives.Chars;
-
/**
* String utility methods
*
- * @author {androidsupport@paystack.co} on 9/13/15.
+ * @author {androidsupport@paystack.co} on 9/13/15.
*/
public class StringUtils {
- public static boolean isEmpty(String value){
- return value == null || value.length() < 1 || value.equalsIgnoreCase("null");
- }
+ public static boolean isEmpty(String value) {
+ return value == null || value.length() < 1 || value.equalsIgnoreCase("null");
+ }
- public static boolean isEmpty(CharSequence charSequence){
- return charSequence == null || isEmpty(charSequence.toString());
- }
+ public static boolean isEmpty(CharSequence charSequence) {
+ return charSequence == null || isEmpty(charSequence.toString());
+ }
- /**
- * Method to nullify a String.
- * @param value
- * @return null if a value is empty or null, otherwise, returns the value
- */
- public static String nullify(String value){
- if(isEmpty(value)){
- return null;
- }
- return value;
+ /**
+ * Method to nullify an empty String.
+ *
+ * @param value - A string we want to be sure to keep null if empty
+ * @return null if a value is empty or null, otherwise, returns the value
+ */
+ public static String nullify(String value) {
+ if (isEmpty(value)) {
+ return null;
}
+ return value;
+ }
}
diff --git a/paystack/src/main/java/co/paystack/android/utils/Utils.java b/paystack/src/main/java/co/paystack/android/utils/Utils.java
index c6c70fe..5283c2c 100644
--- a/paystack/src/main/java/co/paystack/android/utils/Utils.java
+++ b/paystack/src/main/java/co/paystack/android/utils/Utils.java
@@ -10,54 +10,55 @@
/**
* General utils class
*
- * @author {androidsupport@paystack.co} on 9/22/15.
+ * @author {androidsupport@paystack.co} on 9/22/15.
*/
public class Utils {
+ /**
+ * Util class for validation
+ */
+ public static class Validate {
/**
- * Util class for validation
+ * To validate if the sdk has been initialized
+ *
+ * @throws PaystackSdkNotInitializedException
*/
- public static class Validate{
- /**
- * To validate if the sdk has been initialized
- *
- * @throws PaystackSdkNotInitializedException
- */
- public static void validateSdkInitialized() throws PaystackSdkNotInitializedException{
- if(!PaystackSdk.isSdkInitialized()){
- throw new PaystackSdkNotInitializedException("Paystack SDK has not been initialized." +
- "The SDK has to be initialized before use");
- }
- }
-
- /**
- * To check for internet permission
- * @param context
- */
- public static void hasInternetPermission(Context context){
- validateNotNull(context, "context");
- PackageManager pm = context.getPackageManager();
- int hasPermission = pm.checkPermission(Manifest.permission.INTERNET, context.getPackageName());//context.checkCallingOrSelfPermission(Manifest.permission.INTERNET);
- if ( hasPermission ==
- PackageManager.PERMISSION_DENIED) {
- throw new IllegalStateException("Paystack requires internet permission. " +
- "Please add the intenet permission to your AndroidManifest.xml");
- }
- }
-
- public static String hasPublishableKey() throws PaystackSdkNotInitializedException {
- String publishableKey = PaystackSdk.getPublishableKey();
- if (publishableKey == null) {
- throw new IllegalStateException("No Publishable key found, please set the Publishable key.");
- }
- return publishableKey;
- }
-
- public static void validateNotNull(Object arg, String name) {
- if (arg == null) {
- throw new NullPointerException("Argument '" + name + "' cannot be null");
- }
- }
+ public static void validateSdkInitialized() throws PaystackSdkNotInitializedException {
+ if (!PaystackSdk.isSdkInitialized()) {
+ throw new PaystackSdkNotInitializedException("Paystack SDK has not been initialized." +
+ "The SDK has to be initialized before use");
+ }
}
+
+ /**
+ * To check for internet permission
+ *
+ * @param context - Application context for current run
+ */
+ public static void hasInternetPermission(Context context) {
+ validateNotNull(context, "context");
+ PackageManager pm = context.getPackageManager();
+ int hasPermission = pm.checkPermission(Manifest.permission.INTERNET, context.getPackageName());//context.checkCallingOrSelfPermission(Manifest.permission.INTERNET);
+ if (hasPermission ==
+ PackageManager.PERMISSION_DENIED) {
+ throw new IllegalStateException("Paystack requires internet permission. " +
+ "Please add the intenet permission to your AndroidManifest.xml");
+ }
+ }
+
+ public static String hasPublishableKey() throws PaystackSdkNotInitializedException {
+ String publishableKey = PaystackSdk.getPublishableKey();
+ if (publishableKey == null) {
+ throw new IllegalStateException("No Publishable key found, please set the Publishable key.");
+ }
+ return publishableKey;
+ }
+
+ public static void validateNotNull(Object arg, String name) {
+ if (arg == null) {
+ throw new NullPointerException("Argument '" + name + "' cannot be null");
+ }
+ }
+ }
}