Skip to content

Commit cdaa76d

Browse files
committed
handle avs_vbvsecurecode auth model payments
1 parent 6c0ce86 commit cdaa76d

File tree

7 files changed

+181
-50
lines changed

7 files changed

+181
-50
lines changed

raveandroid/src/main/java/com/flutterwave/raveandroid/Payload.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,16 @@ public void setSECKEY(String SECKEY) {
112112

113113
private String meta;
114114

115+
public String getBillingzip() {
116+
return billingzip;
117+
}
118+
119+
public void setBillingzip(String billingzip) {
120+
this.billingzip = billingzip;
121+
}
122+
123+
private String billingzip;
124+
115125
public String getPayment_type() {
116126
return payment_type;
117127
}

raveandroid/src/main/java/com/flutterwave/raveandroid/RaveConstants.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ public class RaveConstants {
1515
public static String LIVE_URL = "https://rave-api.herokuapp.com";
1616
public static String VBV = "VBVSECURECODE";
1717
public static String PIN = "PIN";
18+
public static String AVS_VBVSECURECODE = "AVS_VBVSECURECODE";
1819
public static String RAVEPAY = "ravepay";
1920
public static String RAVE_PARAMS = "raveparams";
2021
public static int RAVE_REQUEST_CODE = 4199;

raveandroid/src/main/java/com/flutterwave/raveandroid/card/CardContract.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
import com.flutterwave.raveandroid.Payload;
55
import com.flutterwave.raveandroid.data.SavedCard;
6+
import com.flutterwave.raveandroid.responses.ChargeResponse;
67

78
import java.util.List;
89

@@ -45,6 +46,14 @@ interface View {
4546
void showFetchFeeFailed(String s);
4647

4748
void hideSavedCardsButton();
49+
50+
void onChargeTokenComplete(ChargeResponse response);
51+
52+
void onChargeCardSuccessful(ChargeResponse response);
53+
54+
void onAVS_VBVSECURECODEModelSuggested(Payload payload);
55+
56+
void onAVSVBVSecureCodeModelUsed(String authurl, String flwRef);
4857
}
4958

5059
interface UserActionsListener {

raveandroid/src/main/java/com/flutterwave/raveandroid/card/CardFragment.java

Lines changed: 77 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import com.flutterwave.raveandroid.Utils;
4343
import com.flutterwave.raveandroid.data.Callbacks;
4444
import com.flutterwave.raveandroid.data.SavedCard;
45+
import com.flutterwave.raveandroid.responses.ChargeResponse;
4546

4647
import org.json.JSONException;
4748
import org.json.JSONObject;
@@ -51,6 +52,7 @@
5152
import java.util.regex.Pattern;
5253

5354
import static android.view.View.GONE;
55+
import static com.flutterwave.raveandroid.RaveConstants.AVS_VBVSECURECODE;
5456
import static com.flutterwave.raveandroid.RaveConstants.PIN;
5557

5658

@@ -378,7 +380,7 @@ public void showProgressIndicator(boolean active) {
378380
@Override
379381
public void onPaymentError(String message) {
380382
dismissDialog();
381-
Toast.makeText(getActivity(), message, Toast.LENGTH_SHORT).show();
383+
Toast.makeText(getActivity(), message, Toast.LENGTH_LONG).show();
382384
}
383385

384386
/**
@@ -420,7 +422,7 @@ public void onClick(View v) {
420422
}
421423

422424
/**
423-
* Displays a toast with the message paramater
425+
* Displays a toast with the message parameter
424426
* @param message = text to display
425427
*/
426428
@Override
@@ -459,49 +461,11 @@ public void onValidateSuccessful(String status, String responseAsJSONString) {
459461

460462
closeBottomSheetsIfOpen();
461463

462-
String flwRef = null;
463-
464-
//check for save tag
465-
if (shouldISaveThisCard) {
466-
flwRef = retrieveFlwRefFromValidateResponse(responseAsJSONString);
467-
}
464+
presenter.requeryTx(flwRef, ravePayInitializer.getSecretKey(), shouldISaveThisCard);
468465

469-
onPaymentSuccessful(status, flwRef, responseAsJSONString);
470466
}
471467

472-
/**
473-
* Get the flutterwave reference from a response json string
474-
* @param responseAsJSONString
475-
* @return
476-
*/
477-
private String retrieveFlwRefFromValidateResponse(String responseAsJSONString) {
478-
try {
479-
JSONObject responseObj = new JSONObject(responseAsJSONString);
480-
JSONObject dataObj = responseObj.getJSONObject("data").getJSONObject("tx");
481-
482-
String flwRef = null;
483-
484-
if (dataObj.has("flw_ref")) {
485-
flwRef = dataObj.getString("flw_ref");
486-
}
487-
else if (dataObj.has("flwRef")) {
488-
flwRef = dataObj.getString("flwRef");
489-
}
490-
491-
// check if we have a valid flutterwave reference
492-
if (flwRef != null && flwRef.length() > 0) {
493-
return flwRef;
494-
}
495-
496-
}
497-
catch (JSONException e) {
498-
e.printStackTrace();
499-
Log.d(RAVEPAY, "Error parsing response for flwRef");
500-
return flwRef;
501-
}
502468

503-
return null;
504-
}
505469

506470
/**
507471
* Called when a validation error is received. Shows a toast
@@ -556,8 +520,8 @@ public void onPaymentSuccessful(String status, String flwRef, String responseAsJ
556520
intent.putExtra("response", responseAsJSONString);
557521

558522
if (getActivity() != null) {
559-
((RavePayActivity) getActivity()).setResult(RavePayActivity.RESULT_SUCCESS, intent);
560-
((RavePayActivity) getActivity()).finish();
523+
getActivity().setResult(RavePayActivity.RESULT_SUCCESS, intent);
524+
getActivity().finish();
561525
}
562526
}
563527

@@ -736,6 +700,76 @@ public void hideSavedCardsButton() {
736700
savedCardBtn.setVisibility(GONE);
737701
}
738702

703+
@Override
704+
public void onChargeTokenComplete(ChargeResponse response) {
705+
706+
presenter
707+
.requeryTx(response.getData().getFlwRef(), ravePayInitializer.getSecretKey(), false);
708+
}
709+
710+
@Override
711+
public void onChargeCardSuccessful(ChargeResponse response) {
712+
presenter
713+
.requeryTx(response.getData().getFlwRef(),
714+
ravePayInitializer.getSecretKey(),
715+
shouldISaveThisCard);
716+
}
717+
718+
@Override
719+
public void onAVS_VBVSECURECODEModelSuggested(final Payload payload) {
720+
721+
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
722+
LayoutInflater inflater = LayoutInflater.from(getActivity());
723+
View v = inflater.inflate(R.layout.avsvbv_layout, null, false);
724+
725+
Button zipBtn = (Button) v.findViewById(R.id.zipButton);
726+
final TextInputEditText zipEt = (TextInputEditText) v.findViewById(R.id.zipEt);
727+
final TextInputLayout zipTil = (TextInputLayout) v.findViewById(R.id.zipTil);
728+
729+
zipBtn.setOnClickListener(new View.OnClickListener() {
730+
@Override
731+
public void onClick(View v) {
732+
String zip = zipEt.getText().toString();
733+
734+
zipTil.setError(null);
735+
zipTil.setErrorEnabled(false);
736+
737+
if (zip.length() == 0) {
738+
zipTil.setError("Enter a valid pin");
739+
}
740+
else {
741+
dialog.dismiss();
742+
presenter.chargeCardWithSuggestedAuthModel(payload, zip, AVS_VBVSECURECODE);
743+
}
744+
}
745+
});
746+
747+
builder.setView(v);
748+
dialog = builder.show();
749+
750+
}
751+
752+
/**
753+
* Called when the auth model suggested is AVS_VBVSecureCode. It opens a webview
754+
* that loads the authURL
755+
*
756+
* @param authurl = URL to display in webview
757+
* @param flwRef = reference of the payment transaction
758+
*/
759+
@Override
760+
public void onAVSVBVSecureCodeModelUsed(String authurl, String flwRef) {
761+
762+
this.flwRef = flwRef;
763+
webView.getSettings().setLoadsImagesAutomatically(true);
764+
webView.getSettings().setJavaScriptEnabled(true);
765+
webView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
766+
// Configure the client to use when opening URLs
767+
webView.setWebViewClient(new MyBrowser());
768+
// Load the initial URL
769+
webView.loadUrl(authurl);
770+
bottomSheetBehaviorVBV.setState(BottomSheetBehavior.STATE_EXPANDED);
771+
}
772+
739773
// Manages the behavior when URLs are loaded
740774
private class MyBrowser extends WebViewClient {
741775
@SuppressWarnings("deprecation")

raveandroid/src/main/java/com/flutterwave/raveandroid/card/CardPresenter.java

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222

2323
import java.util.List;
2424

25+
import static com.flutterwave.raveandroid.RaveConstants.AVS_VBVSECURECODE;
26+
import static com.flutterwave.raveandroid.RaveConstants.PIN;
27+
2528
/**
2629
* Created by hamzafetuga on 18/07/2017.
2730
*/
@@ -66,6 +69,9 @@ public void onSuccess(ChargeResponse response, String responseAsJSONString) {
6669
if (suggested_auth.equals(RaveConstants.PIN)) {
6770
mView.onPinAuthModelSuggested(payload);
6871
}
72+
else if (suggested_auth.equals(AVS_VBVSECURECODE)) {
73+
mView.onAVS_VBVSECURECODEModelSuggested(payload);
74+
}
6975
else {
7076
mView.onPaymentError("Unknown auth model");
7177
}
@@ -97,9 +103,15 @@ public void onError(String message, String responseAsJSONString) {
97103
}
98104

99105
@Override
100-
public void chargeCardWithSuggestedAuthModel(Payload payload, String pin, String authModel) {
106+
public void chargeCardWithSuggestedAuthModel(Payload payload, String zipOrPin, String authModel) {
107+
108+
if (authModel.equalsIgnoreCase(AVS_VBVSECURECODE)) {
109+
payload.setBillingzip(zipOrPin);
110+
}
111+
else if (authModel.equalsIgnoreCase(PIN)){
112+
payload.setPin(zipOrPin);
113+
}
101114

102-
payload.setPin(pin);
103115
payload.setSuggestedAuth(authModel);
104116

105117
String cardRequestBodyAsString = Utils.convertChargeRequestPayloadToJson(payload);
@@ -125,14 +137,17 @@ public void onSuccess(ChargeResponse response, String responseAsJSONString) {
125137

126138
if (chargeResponseCode.equalsIgnoreCase("00")) {
127139
// mView.showToast("Payment successful");
128-
String chargeResponseMessage = response.getData().getChargeResponseMessage() == null
129-
? "Payment Successful" : response.getData().getChargeResponseMessage();
130-
mView.onPaymentSuccessful(chargeResponseMessage, response.getData().getFlwRef(), responseAsJSONString);
140+
mView.onChargeCardSuccessful(response);
131141
}
132142
else if (chargeResponseCode.equalsIgnoreCase("02")) {
133-
if (response.getData().getAuthModelUsed().equalsIgnoreCase(RaveConstants.PIN)) {
143+
String authModelUsed = response.getData().getAuthModelUsed();
144+
if (authModelUsed.equalsIgnoreCase(RaveConstants.PIN)) {
134145
mView.showOTPLayout(response.getData().getFlwRef());
135146
}
147+
else if (authModelUsed.equalsIgnoreCase(RaveConstants.AVS_VBVSECURECODE)){
148+
String flwRef = response.getData().getFlwRef();
149+
mView.onAVSVBVSecureCodeModelUsed(response.getData().getAuthurl(), flwRef);
150+
}
136151
else {
137152
mView.onPaymentError("Unknown Auth Model");
138153
}
@@ -377,7 +392,7 @@ public void chargeToken(Payload payload) {
377392
public void onSuccess(ChargeResponse response, String responseAsJSONString) {
378393

379394
mView.showProgressIndicator(false);
380-
mView.onPaymentSuccessful(response.getStatus(), "", responseAsJSONString);
395+
mView.onChargeTokenComplete(response);
381396

382397
}
383398

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3+
android:orientation="vertical" android:layout_width="match_parent"
4+
android:gravity="center"
5+
android:layout_height="wrap_content">
6+
7+
<View
8+
android:layout_width="match_parent"
9+
android:layout_marginBottom="20dp"
10+
android:layout_height="2dp"
11+
style="?PinHeaderStyle"
12+
/>
13+
14+
<TextView
15+
android:layout_width="match_parent"
16+
android:layout_height="wrap_content"
17+
android:gravity="center"
18+
android:layout_marginLeft="30dp"
19+
android:padding="20dp"
20+
android:textColor="#333333"
21+
android:textSize="16sp"
22+
android:layout_marginRight="30dp"
23+
android:layout_marginBottom="20dp"
24+
android:text="@string/enter_your_billing_zip_code"/>
25+
26+
<android.support.design.widget.TextInputLayout
27+
android:layout_width="match_parent"
28+
android:id="@+id/zipTil"
29+
android:layout_marginBottom="20dp"
30+
android:layout_marginLeft="30dp"
31+
android:layout_marginRight="30dp"
32+
android:layout_height="wrap_content">
33+
34+
<android.support.design.widget.TextInputEditText
35+
android:layout_width="match_parent"
36+
android:layout_height="wrap_content"
37+
android:hint="@string/billing_zip_code"
38+
android:drawableLeft="@drawable/ic_lock_outline_black_24dp"
39+
android:drawableStart="@drawable/ic_lock_outline_black_24dp"
40+
android:drawablePadding="7dp"
41+
android:maxLength="4"
42+
android:id="@+id/zipEt"
43+
/>
44+
45+
</android.support.design.widget.TextInputLayout>
46+
47+
<Button
48+
android:id="@+id/zipButton"
49+
android:layout_width="match_parent"
50+
android:layout_height="wrap_content"
51+
android:layout_marginRight="30dp"
52+
android:layout_marginBottom="30dp"
53+
android:layout_marginEnd="30dp"
54+
style="?PinButtonStyle"
55+
android:layout_marginLeft="30dp"
56+
android:layout_marginStart="30dp"
57+
android:text="@string/enter" />
58+
59+
60+
</LinearLayout>

raveandroid/src/main/res/values/strings.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,7 @@
2929
<string name="cvc_cvv2">CVC/CVV2</string>
3030
<string name="expiration">Expiration</string>
3131
<string name="email">Email</string>
32+
<string name="enter_your_billing_zip_code">Enter your billing zip code</string>
33+
<string name="billing_zip_code">Billing zip code</string>
3234

3335
</resources>

0 commit comments

Comments
 (0)