下面的代码显示一个AlertDialog,该对话框收集信用卡数据,即号码,有效性和CVC,以使用Stripe付款。有了这些数据,stripe.createToken函数(...)应该向TokenCallback()返回一个令牌。问题是,即使使用正确的卡数据(大约五分之一),也不会提取令牌,并且不会返回错误。
private void dialogRenewWithStripe() {
final ViewGroup nullParent = null;
View view = getLayoutInflater().inflate(R.layout.dialog_container_renew_stripe, nullParent, false);
...
CardMultilineWidget mCardMultilineWidget = view.findViewById(R.id.add_source_card_entry_widget);
AlertDialog.Builder builder = dialogBuilder2(mContext);
builder.setView(view);
builder.setIcon(R.drawable.ic_pay);
builder.setCancelable(false);
builder.setTitle(getResources().getString(R.string.msg0333));
builder.setNegativeButton("CANCEL", (dialogInterface, i) -> { });
builder.setPositiveButton("CONFIRM", (dialogInterface, i) -> { });
alertDialog2 = builder.create();
alertDialog2.setOnShowListener(dialogInterface -> {
((AlertDialog)dialogInterface).getButton(AlertDialog.BUTTON_NEGATIVE).setOnClickListener(v -> {
btnRenew.setImageAlpha(255);
btnRenew.setEnabled(true);
alertDialog2.dismiss();
});
((AlertDialog)dialogInterface).getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(v -> {
if (mCardMultilineWidget.getCard() != null) {
alertDialog2.dismiss();
dialogWhait( getResources().getString(R.string.msg0251) );
Stripe stripe = new Stripe(mContext, "pk_test_XXXXXXXXXXXXXXXXXXXX");
stripe.createToken(
mCardMultilineWidget.getCard(),
new TokenCallback() {
public void onSuccess(Token token) {
alertDialogWhaiting.dismiss();
dialogWhait( getResources().getString(R.string.msg0330) );
String stringData = "{" +
"\"_ind\":\"" + Long.toString(paymentOption._option_id) + "\"," +
"\"_token\":\"" + token.getId() + "\"}";
ServerTask serverTask = new ServerTask(AccountActivity.this, API_CKECK_OUT_STRIPE, stringData);
serverTask.execute();
}
public void onError(Exception error) {
alertDialogWhaiting.dismiss();
dialogError(
getResources().getString(R.string.msg0331),
getResources().getString(R.string.msg0332)+" "+error.getLocalizedMessage()
);
btnRenew.setImageAlpha(255);
btnRenew.setEnabled(true);
}
}
);
}
else {
toast...
}
});
});
alertDialog2.show();
}
private static class ServerTask extends AsyncTask<String, Void, String> {
private String data;
private String urlString;
private WeakReference<AccountActivity> activityReference;
private ServerTask(AccountActivity context, String urlString, String data) {
activityReference = new WeakReference<>(context);
this.urlString = urlString;
this.data = data;
}
@Override
protected String doInBackground(String... strings) {
String serverResponse = "";
try {
URL url = new URL(urlString); //there is a connection between the code and PHP script. This is tested.
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
String urlParameters = URLEncoder.encode("data", "UTF-8")+"="+URLEncoder.encode(data, "UTF-8");
connection.setRequestMethod("POST");
connection.setDoOutput(true);
DataOutputStream dStream = new DataOutputStream(connection.getOutputStream());
dStream.writeBytes(urlParameters);
dStream.flush();
dStream.close();
BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line;
StringBuilder responseOutput = new StringBuilder();
while ((line = br.readLine()) != null) {
responseOutput.append(line);
}
br.close();
serverResponse = responseOutput.toString();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return serverResponse;
}
@Override
protected void onPostExecute(String serverResponse) {
super.onPostExecute(serverResponse);
AccountActivity activity = activityReference.get();
if (activity == null || activity.isFinishing()) return;
PaymentResponse paymentResponse = new GsonBuilder().create().fromJson(serverResponse, PaymentResponse.class);
activity.alertDialogWhaiting.dismiss();
activity.btnRenew.setImageAlpha(255);
activity.btnRenew.setEnabled(true);
if (!paymentResponse._t_error.equals("")) {
switch (paymentResponse._t_error) {
case "400":
activity.dialogError( "TITLE", "message");
break;
case "401":
activity.dialogError( "TITLE", "message");
break;
case "402":
activity.dialogError( "TITLE", "message");
break;
case "404":
activity.dialogError( "TITLE", "message");
break;
case "409":
activity.dialogError( "TITLE", "message");
break;
case "429":
activity.dialogError( "TITLE", "message");
break;
case "500":
case "502":
case "503":
case "504":
activity.dialogError( "TITLE", "message");
break;
default:
activity.dialogError( "TITLE", "message");
break;
}
}
else {
activity.dialogRenovatio(paymentResponse);
}
}
}
答案 0 :(得分:0)
来自https://github.com/stripe/stripe-android/issues/803#issuecomment-461840143
我将StripePaymentDialog#createStripeToken中的嵌入式匿名TokenCallback类移动为实例变量(请参见下文),问题似乎消失了。我相信匿名类在内联时会被垃圾回收。
public class StripePaymentDialog extends DialogFragment {
@NonNull private final TokenCallback mTokenCallback = new TokenCallback() {
@Override
public void onSuccess(Token token) {
Log.d("Stripe Token Success: ", token.toString());
setSubmitSuccess(token.getId());
}
@Override
public void onError(Exception error) {
if (error != null && error.getMessage().length() > 0) {
Log.d("Stripe Token Error: ", error.getLocalizedMessage());
setErrorMessage(error.getLocalizedMessage());
setSubmitError();
}
}
};
private void createStripeToken() {
mStripe.createToken(mCard, mDefaultPublishKey, mTokenCallback);
}
}