#android #stripe-payments
#Android #stripe-платежи
Вопрос:
Я использую stripe для сбора платежей. Вместо использования CardInputWidget я решил использовать встроенные входные данные, которые есть у stripe, такие как stripe.android.view.CardNumberEditText, stripe.android.view.CVCEditText, stripe.android.view.ExpiryDateEditText и stripe.android.view.PostalCodeEditText. Моя единственная проблема заключается в том, что я знаю, что мне придется создавать PaymentMethod CreateParams вручную, но я не знаю, как я это сделаю. На данный момент у меня есть все настройки для ввода карты в моем Java-коде. Может кто-нибудь помочь мне с этим и рассказать / показать мне, как я буду это делать. Заранее спасибо
//Paymentpage.activity
<LinearLayout
android:id="@ id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="1dp"
android:orientation="vertical"
android:background="@color/offwhite"
app:layout_constraintBottom_toTopOf="@ id/linearLayout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:layout_constraintBottom_toTopOf="@ id/scrollView3"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:theme="@style/Base.CardView"
>
<!--
<com.stripe.android.view.CardMultilineWidget
android:id="@ id/cardInputWidget"
android:layout_width="match_parent"
android:theme="@style/StripeDefaultTheme"
android:layout_height="160dp"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
-->
<com.stripe.android.view.CardNumberEditText
android:layout_width="match_parent"
android:hint="Card Number"
android:layout_height="wrap_content"/>
<com.stripe.android.view.ExpiryDateEditText
android:layout_width="match_parent"
android:hint="Expiration date"
android:layout_height="wrap_content"/>
<com.stripe.android.view.CvcEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<com.stripe.android.view.PostalCodeEditText
android:layout_width="match_parent"
android:hint="Postal code"
android:layout_height="wrap_content"/>
<Button
android:id="@ id/payButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:background="@color/faux_dukes_shade2"
android:text="Pay"
android:textColor="@color/white"
app:layout_constraintEnd_toEndOf="@ id/cardInputWidget"
app:layout_constraintStart_toStartOf="@ id/cardInputWidget"
app:layout_constraintTop_toBottomOf="@ id/cardInputWidget" />
</LinearLayout>
//Paymentpage.java
private void startCheckout() {
//amount will calculate from .00 make sure multiply by 100
//double amount=Double.parseDouble(mAmount.getText().toString())*1;
// Create a PaymentIntent by calling the sample server's /create-payment-intent endpoint.
MediaType mediaType = MediaType.get("application/json; charset=utf-8");
/*
String json = "{"
""currency":"usd","
""items":["
"{"id":"photo_subscription"}"
"]"
"}";
*/
Intent intent = getIntent();
final String t = intent.getStringExtra("days");
int in = Integer.valueOf(t);
String email = FirebaseAuth.getInstance().getCurrentUser().getEmail();
double amount=in*100;
Map<String,Object> payMap=new HashMap<>();
Map<String,Object> itemMap=new HashMap<>();
List<Map<String,Object>> itemList =new ArrayList<>();
payMap.put("currency","usd");
payMap.put("receipt_email",email.toString());
itemMap.put("id","photo_subscription");
itemMap.put("amount",amount);
itemList.add(itemMap);
payMap.put("items",itemList);
String json = new Gson().toJson(payMap);
RequestBody body = RequestBody.create(mediaType,json);
Request request = new Request.Builder()
.url(BACKEND_URL "create-payment-intent")
.post(body)
.build();
httpClient.newCall(request)
.enqueue(new PayCallback(this));
// Hook up the pay button to the card widget and stripe instance
//Button payButton = findViewById(R.id.payButton);
payButton.setOnClickListener((View view) -> {
PaymentMethodCreateParams params = cardInputWidget.getPaymentMethodCreateParams();
if (params != null) {
Map<String, String> extraParams = new HashMap<>();
extraParams.put("setup_future_usage", "off_session");
ConfirmPaymentIntentParams confirmParams = ConfirmPaymentIntentParams
.createWithPaymentMethodCreateParams(params, paymentIntentClientSecret);
stripe.confirmPayment(this, confirmParams);
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// Handle the result of stripe.confirmPayment
stripe.onPaymentResult(requestCode, data, new PaymentResultCallback(this));
}
public void goback(View view) {
onBackPressed();
}
private static final class PayCallback implements Callback {
@NonNull private final WeakReference<PaymentPageActivity> activityRef;
PayCallback(@NonNull PaymentPageActivity activity) {
activityRef = new WeakReference<>(activity);
}
@Override
public void onFailure(@NonNull Call call, @NonNull IOException e) {
final PaymentPageActivity activity = activityRef.get();
if (activity == null) {
return;
}
activity.runOnUiThread(() ->
Toast.makeText(
activity, "Error: " e.toString(), Toast.LENGTH_LONG
).show()
);
}
@Override
public void onResponse(@NonNull Call call, @NonNull final Response response)
throws IOException {
final PaymentPageActivity activity = activityRef.get();
if (activity == null) {
return;
}
if (!response.isSuccessful()) {
activity.runOnUiThread(() ->
Toast.makeText(
activity, "Error: " response.toString(), Toast.LENGTH_LONG
).show()
);
} else {
activity.onPaymentSuccess(response);
}
}
}
private void onPaymentSuccess(@NonNull final Response response) throws IOException {
Gson gson = new Gson();
Type type = new TypeToken<Map<String, String>>(){}.getType();
Map<String, String> responseMap = gson.fromJson(
Objects.requireNonNull(response.body()).string(),
type
);
paymentIntentClientSecret = responseMap.get("clientSecret");
}
private final class PaymentResultCallback
implements ApiResultCallback<PaymentIntentResult> {
@NonNull private final WeakReference<PaymentPageActivity> activityRef;
PaymentResultCallback(@NonNull PaymentPageActivity activity) {
activityRef = new WeakReference<>(activity);
}
@Override
public void onSuccess(@NonNull PaymentIntentResult result) {
final PaymentPageActivity activity = activityRef.get();
if (activity == null) {
return;
}
PaymentIntent paymentIntent = result.getIntent();
PaymentIntent.Status status = paymentIntent.getStatus();
if (status == PaymentIntent.Status.Succeeded) {
// Payment completed successfully
/*
Gson gson = new GsonBuilder().setPrettyPrinting().create();
activity.displayAlert(
"Payment completed",
gson.toJson(paymentIntent)
);
*/
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
final DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference("Ads");
final DatabaseReference update = rootRef.child(uid);
final DatabaseReference rootRef1 = FirebaseDatabase.getInstance().getReference("card_information");
final DatabaseReference update1 = rootRef1.child(uid);
update1.child("card_number").setValue(cardInputWidget.getCard().component1());
update1.child("cvc").setValue(cardInputWidget.getCard().component2());
update1.child("expiration_month").setValue(cardInputWidget.getCard().component3());
update1.child("expiration_year").setValue(cardInputWidget.getCard().component4());
update1.child("postal_code").setValue(cardInputWidget.getCard().getAddressZip());
Intent intent = getIntent();
Bundle extras = intent.getExtras();
String get_key = extras.getString("id-key");
update.child(get_key).child("status").setValue("Paid");
Intent intent2=new Intent(PaymentPageActivity.this,ProfileActivity.class);
startActivity(intent2);
} else if (status == PaymentIntent.Status.RequiresPaymentMethod) {
// Payment failed – allow retrying using a different payment method
activity.displayAlert(
"Payment failed",
Objects.requireNonNull(paymentIntent.getLastPaymentError()).getMessage()
);
}
}
@Override
public void onError(@NonNull Exception e) {
final PaymentPageActivity activity = activityRef.get();
if (activity == null) {
return;
}
// Payment request failed – allow retrying using the same payment method
activity.displayAlert("Error", e.toString());
}
}
private void displayAlert(@NonNull String title,
@Nullable String message) {
AlertDialog.Builder builder = new AlertDialog.Builder(this)
.setTitle(title)
.setMessage(message);
builder.setPositiveButton("Ok", null);
builder.create().show();
}
Ответ №1:
Рекомендуется использовать CardInputWidget или CardMultiline из Android SDK вместо разбитых компонентов, это внутренние компоненты.
Комментарии:
1. вау. Я пытался настроить его, потому что мне не нравится дизайн способа настройки CardInputWidget и cardMultiline, и я подумал, что смогу его настроить.
Ответ №2:
Да, вы можете, и вот код:
CardInputWidget cardInputWidget = new CardInputWidget(this);
cardInputWidget.setCardNumber("4242424242424242");
cardInputWidget.setCvcCode("546");
cardInputWidget.setExpiryDate(5,22);
cardInputWidget.setPostalCodeRequired(false);
PaymentMethodCreateParams params = cardInputWidget.getPaymentMethodCreateParams();
и вы можете настроить свой макет по своему усмотрению.
Комментарии:
1. Бен, спасибо за ответ, но у меня это задано в моем коде. Как я буду его настраивать?
2. получите номер карты из
CardNumberEditText
и cvccode изCvcEditText
и expirydate изExpiryDateEditText
!!3. как насчет имени держателя карты?