From edd421654ac9b3098f3faec939c9587cd20b95cb Mon Sep 17 00:00:00 2001 From: Bernard Labno Date: Fri, 27 Apr 2018 15:38:31 +0200 Subject: [PATCH] Add payment method: moneygram --- .../paymentmethods/MoneyGramForm.java | 269 ++++++++++++++++++ .../fiataccounts/FiatAccountsView.java | 11 + .../steps/buyer/BuyerStep2View.java | 32 +++ .../steps/seller/SellerStep3View.java | 3 + 4 files changed, 315 insertions(+) create mode 100644 src/main/java/bisq/desktop/components/paymentmethods/MoneyGramForm.java diff --git a/src/main/java/bisq/desktop/components/paymentmethods/MoneyGramForm.java b/src/main/java/bisq/desktop/components/paymentmethods/MoneyGramForm.java new file mode 100644 index 0000000000..ca78e5230c --- /dev/null +++ b/src/main/java/bisq/desktop/components/paymentmethods/MoneyGramForm.java @@ -0,0 +1,269 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package bisq.desktop.components.paymentmethods; + +import bisq.desktop.components.InputTextField; +import bisq.desktop.util.BSFormatter; +import bisq.desktop.util.FormBuilder; +import bisq.desktop.util.Layout; +import bisq.desktop.util.validation.EmailValidator; + +import bisq.core.locale.BankUtil; +import bisq.core.locale.Country; +import bisq.core.locale.CountryUtil; +import bisq.core.locale.CurrencyUtil; +import bisq.core.locale.Region; +import bisq.core.locale.Res; +import bisq.core.payment.AccountAgeWitnessService; +import bisq.core.payment.MoneyGramAccount; +import bisq.core.payment.PaymentAccount; +import bisq.core.payment.payload.MoneyGramAccountPayload; +import bisq.core.payment.payload.PaymentAccountPayload; +import bisq.core.util.validation.InputValidator; + +import bisq.common.util.Tuple2; +import bisq.common.util.Tuple3; + +import org.apache.commons.lang3.StringUtils; + +import javafx.scene.control.CheckBox; +import javafx.scene.control.ComboBox; +import javafx.scene.control.Label; +import javafx.scene.control.Tooltip; +import javafx.scene.layout.FlowPane; +import javafx.scene.layout.GridPane; + +import javafx.geometry.Insets; +import javafx.geometry.VPos; + +import javafx.collections.FXCollections; + +import javafx.util.StringConverter; + +import lombok.extern.slf4j.Slf4j; + +import static bisq.desktop.util.FormBuilder.addLabel; +import static bisq.desktop.util.FormBuilder.addLabelTextFieldWithCopyIcon; + +@Slf4j +public class MoneyGramForm extends PaymentMethodForm { + + public static int addFormForBuyer(GridPane gridPane, int gridRow, + PaymentAccountPayload paymentAccountPayload) { + final MoneyGramAccountPayload payload = (MoneyGramAccountPayload) paymentAccountPayload; + addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, Res.getWithCol("payment.account.fullName"), + payload.getHolderName()); + FormBuilder.addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, + Res.getWithCol("payment.bank.country"), + CountryUtil.getNameAndCode(((MoneyGramAccountPayload) paymentAccountPayload).getCountryCode())); + if (BankUtil.isStateRequired(payload.getCountryCode())) + addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, Res.get("payment.account.state"), + payload.getState()); + addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, Res.get("payment.email"), + payload.getEmail()); + + return gridRow; + } + + protected final MoneyGramAccountPayload moneyGramAccountPayload; + protected InputTextField holderNameInputTextField, emailInputTextField, stateInputTextField; + private Label stateLabel; + private final EmailValidator emailValidator; + + public MoneyGramForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, InputValidator inputValidator, + GridPane gridPane, int gridRow, BSFormatter formatter) { + super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter); + this.moneyGramAccountPayload = (MoneyGramAccountPayload) paymentAccount.paymentAccountPayload; + + emailValidator = new EmailValidator(); + } + + @Override + public void addFormForDisplayAccount() { + gridRowFrom = gridRow; + final Country country = getMoneyGramPaymentAccount().getCountry(); + FormBuilder.addLabelTextField(gridPane, gridRow, Res.get("payment.account.name"), paymentAccount.getAccountName(), Layout.FIRST_ROW_AND_GROUP_DISTANCE); + FormBuilder.addLabelTextField(gridPane, ++gridRow, Res.getWithCol("shared.paymentMethod"), + Res.get(paymentAccount.getPaymentMethod().getId())); + FormBuilder.addLabelTextField(gridPane, ++gridRow, Res.get("payment.country"), country != null ? country.name : ""); + FormBuilder.addLabelTextField(gridPane, ++gridRow, Res.getWithCol("payment.account.fullName"), + moneyGramAccountPayload.getHolderName()); + if (BankUtil.isStateRequired(moneyGramAccountPayload.getCountryCode())) + FormBuilder.addLabelTextField(gridPane, ++gridRow, Res.get("payment.account.state"), + moneyGramAccountPayload.getState()).second.setMouseTransparent(false); + FormBuilder.addLabelTextField(gridPane, ++gridRow, Res.get("payment.email"), + moneyGramAccountPayload.getEmail()); + addLimitations(); + addCurrenciesGrid(false); + } + + @Override + public void addFormForAddAccount() { + gridRowFrom = gridRow + 1; + + Tuple3 tuple3 = FormBuilder.addLabelComboBoxComboBox(gridPane, ++gridRow, Res.get("payment.country")); + + //noinspection unchecked,unchecked,unchecked + ComboBox regionComboBox = tuple3.second; + regionComboBox.setPromptText(Res.get("payment.select.region")); + regionComboBox.setConverter(new StringConverter() { + @Override + public String toString(Region region) { + return region.name; + } + + @Override + public Region fromString(String s) { + return null; + } + }); + regionComboBox.setItems(FXCollections.observableArrayList(CountryUtil.getAllRegions())); + + //noinspection unchecked,unchecked,unchecked + ComboBox countryComboBox = tuple3.third; + countryComboBox.setVisibleRowCount(15); + countryComboBox.setDisable(true); + countryComboBox.setPromptText(Res.get("payment.select.country")); + countryComboBox.setConverter(new StringConverter() { + @Override + public String toString(Country country) { + return country.name + " (" + country.code + ")"; + } + + @Override + public Country fromString(String s) { + return null; + } + }); + countryComboBox.setOnAction(e -> { + Country selectedItem = countryComboBox.getSelectionModel().getSelectedItem(); + if (selectedItem != null) { + getMoneyGramPaymentAccount().setCountry(selectedItem); + updateFromInputs(); + applyIsStateRequired(); + stateInputTextField.setText(""); + } + }); + + regionComboBox.setOnAction(e -> { + Region selectedItem = regionComboBox.getSelectionModel().getSelectedItem(); + if (selectedItem != null) { + countryComboBox.setDisable(false); + countryComboBox.setItems(FXCollections.observableArrayList(CountryUtil.getAllCountriesForRegion(selectedItem))); + } + }); + + holderNameInputTextField = FormBuilder.addLabelInputTextField(gridPane, + ++gridRow, Res.getWithCol("payment.account.fullName")).second; + holderNameInputTextField.textProperty().addListener((ov, oldValue, newValue) -> { + moneyGramAccountPayload.setHolderName(newValue); + updateFromInputs(); + }); + holderNameInputTextField.setValidator(inputValidator); + + final Tuple2 tuple2 = FormBuilder.addLabelInputTextField(gridPane, ++gridRow, Res.get("payment.account.state")); + stateLabel = tuple2.first; + stateInputTextField = tuple2.second; + stateInputTextField.textProperty().addListener((ov, oldValue, newValue) -> { + moneyGramAccountPayload.setState(newValue); + updateFromInputs(); + + }); + applyIsStateRequired(); + + emailInputTextField = FormBuilder.addLabelInputTextField(gridPane, ++gridRow, Res.get("payment.email")).second; + emailInputTextField.textProperty().addListener((ov, oldValue, newValue) -> { + moneyGramAccountPayload.setEmail(newValue); + updateFromInputs(); + }); + emailInputTextField.setValidator(emailValidator); + + addCurrenciesGrid(true); + addLimitations(); + addAccountNameTextFieldWithAutoFillCheckBox(); + + updateFromInputs(); + } + + private void addCurrenciesGrid(boolean isEditable) { + Label label = addLabel(gridPane, ++gridRow, Res.get("payment.supportedCurrencies"), 0); + GridPane.setValignment(label, VPos.TOP); + FlowPane flowPane = new FlowPane(); + flowPane.setPadding(new Insets(10, 10, 10, 10)); + flowPane.setVgap(10); + flowPane.setHgap(10); + + if (isEditable) + flowPane.setId("flow-pane-checkboxes-bg"); + else + flowPane.setId("flow-pane-checkboxes-non-editable-bg"); + + CurrencyUtil.getAllMoneyGramCurrencies().forEach(e -> { + CheckBox checkBox = new CheckBox(e.getCode()); + checkBox.setMouseTransparent(!isEditable); + checkBox.setSelected(paymentAccount.getTradeCurrencies().contains(e)); + checkBox.setMinWidth(60); + checkBox.setMaxWidth(checkBox.getMinWidth()); + checkBox.setTooltip(new Tooltip(e.getName())); + checkBox.setOnAction(event -> { + if (checkBox.isSelected()) + paymentAccount.addCurrency(e); + else + paymentAccount.removeCurrency(e); + + updateAllInputsValid(); + }); + flowPane.getChildren().add(checkBox); + }); + + GridPane.setRowIndex(flowPane, gridRow); + GridPane.setColumnIndex(flowPane, 1); + gridPane.getChildren().add(flowPane); + } + + private void applyIsStateRequired() { + final boolean stateRequired = BankUtil.isStateRequired(moneyGramAccountPayload.getCountryCode()); + stateLabel.setManaged(stateRequired); + stateLabel.setVisible(stateRequired); + stateInputTextField.setManaged(stateRequired); + stateInputTextField.setVisible(stateRequired); + } + + private MoneyGramAccount getMoneyGramPaymentAccount() { + return (MoneyGramAccount) this.paymentAccount; + } + + @Override + protected void autoFillNameTextField() { + if (useCustomAccountNameCheckBox != null && !useCustomAccountNameCheckBox.isSelected()) { + accountNameTextField.setText(Res.get(paymentAccount.getPaymentMethod().getId()) + .concat(": ") + .concat(StringUtils.abbreviate(holderNameInputTextField.getText(), 9))); + } + } + + @Override + public void updateAllInputsValid() { + boolean result = isAccountNameValid() + && getMoneyGramPaymentAccount().getCountry() != null + && inputValidator.validate(moneyGramAccountPayload.getHolderName()).isValid + && emailValidator.validate(moneyGramAccountPayload.getEmail()).isValid + && paymentAccount.getTradeCurrencies().size() > 0; + allInputsValid.set(result); + } +} diff --git a/src/main/java/bisq/desktop/main/account/content/fiataccounts/FiatAccountsView.java b/src/main/java/bisq/desktop/main/account/content/fiataccounts/FiatAccountsView.java index 0ba81a7201..f1e3a167ee 100644 --- a/src/main/java/bisq/desktop/main/account/content/fiataccounts/FiatAccountsView.java +++ b/src/main/java/bisq/desktop/main/account/content/fiataccounts/FiatAccountsView.java @@ -30,6 +30,7 @@ import bisq.desktop.components.paymentmethods.ClearXchangeForm; import bisq.desktop.components.paymentmethods.FasterPaymentsForm; import bisq.desktop.components.paymentmethods.InteracETransferForm; import bisq.desktop.components.paymentmethods.MoneyBeamForm; +import bisq.desktop.components.paymentmethods.MoneyGramForm; import bisq.desktop.components.paymentmethods.NationalBankForm; import bisq.desktop.components.paymentmethods.OKPayForm; import bisq.desktop.components.paymentmethods.PaymentMethodForm; @@ -73,6 +74,7 @@ import bisq.core.app.BisqEnvironment; import bisq.core.locale.Res; import bisq.core.payment.AccountAgeWitnessService; import bisq.core.payment.ClearXchangeAccount; +import bisq.core.payment.MoneyGramAccount; import bisq.core.payment.PaymentAccount; import bisq.core.payment.PaymentAccountFactory; import bisq.core.payment.WesternUnionAccount; @@ -252,6 +254,13 @@ public class FiatAccountsView extends ActivatableViewAndModel doSaveNewAccount(paymentAccount)) .show(); + } else if (paymentAccount instanceof MoneyGramAccount) { + new Popup<>().information(Res.get("payment.moneyGram.info")) + .width(700) + .closeButtonText(Res.get("shared.cancel")) + .actionButtonText(Res.get("shared.iUnderstand")) + .onAction(() -> doSaveNewAccount(paymentAccount)) + .show(); } else { doSaveNewAccount(paymentAccount); } @@ -467,6 +476,8 @@ public class FiatAccountsView extends ActivatableViewAndModel(); + popup.headLine(Res.get("portfolio.pending.step2_buyer.moneyGramMTCNInfo.headline")) + .feedback(Res.get("portfolio.pending.step2_buyer.moneyGramMTCNInfo.msg", email)) + .onAction(this::showConfirmPaymentStartedPopup) + .actionButtonText(Res.get("shared.yes")) + .closeButtonText(Res.get("shared.no")) + .onClose(popup::hide) + .dontShowAgainId(key) + .show(); + } else { + showConfirmPaymentStartedPopup(); + } } else { showConfirmPaymentStartedPopup(); } @@ -432,6 +455,15 @@ public class BuyerStep2View extends TradeStepView { paymentDetailsForTradePopup + ".\n" + copyPaste + "\n\n" + extra; + } else if (paymentAccountPayload instanceof MoneyGramAccountPayload) { + final String email = ((MoneyGramAccountPayload) paymentAccountPayload).getEmail(); + final String extra = Res.get("portfolio.pending.step2_buyer.moneyGram.extra", email); + message += Res.get("portfolio.pending.step2_buyer.moneyGram", + amount) + + accountDetails + + paymentDetailsForTradePopup + ".\n" + + copyPaste + "\n\n" + + extra; } else if (paymentAccountPayload instanceof USPostalMoneyOrderAccountPayload) { //noinspection UnusedAssignment message += Res.get("portfolio.pending.step2_buyer.postal", amount) + diff --git a/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/seller/SellerStep3View.java b/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/seller/SellerStep3View.java index 5bcc0e826e..f89da41fbf 100644 --- a/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/seller/SellerStep3View.java +++ b/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/seller/SellerStep3View.java @@ -30,6 +30,7 @@ import bisq.core.locale.Res; import bisq.core.payment.payload.BankAccountPayload; import bisq.core.payment.payload.CashDepositAccountPayload; import bisq.core.payment.payload.CryptoCurrencyAccountPayload; +import bisq.core.payment.payload.MoneyGramAccountPayload; import bisq.core.payment.payload.PaymentAccountPayload; import bisq.core.payment.payload.SepaAccountPayload; import bisq.core.payment.payload.SepaInstantAccountPayload; @@ -315,6 +316,8 @@ public class SellerStep3View extends TradeStepView { message = message + Res.get("portfolio.pending.step3_seller.cash", part); else if (paymentAccountPayload instanceof WesternUnionAccountPayload) message = message + Res.get("portfolio.pending.step3_seller.westernUnion", part); + else if (paymentAccountPayload instanceof MoneyGramAccountPayload) + message = message + Res.get("portfolio.pending.step3_seller.moneyGram", part); Optional optionalHolderName = getOptionalHolderName(); if (optionalHolderName.isPresent()) {