为什么Stripe for Android的createToken()有时不创建令牌?

时间:2019-03-25 20:22:54

标签: android stripe-payments

下面的代码显示一个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);
        }
    }

}

1 个答案:

答案 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);
    }
}