support MoneyGram form api

This commit is contained in:
woodser 2022-06-17 09:14:15 -04:00
parent faeb9ca8db
commit c40938f438
9 changed files with 87 additions and 36 deletions

View File

@ -71,7 +71,8 @@ public final class PaymentAccountForm implements PersistablePayload {
CLEAR_X_CHANGE,
SWIFT,
F2F,
STRIKE;
STRIKE,
MONEY_GRAM;
public static PaymentAccountForm.FormId fromProto(protobuf.PaymentAccountForm.FormId formId) {
return ProtoUtil.enumFromProto(PaymentAccountForm.FormId.class, formId.name());
@ -108,6 +109,15 @@ public final class PaymentAccountForm implements PersistablePayload {
return new PaymentAccountForm(FormId.fromProto(proto.getId()), fields);
}
public String getValue(PaymentAccountFormField.FieldId fieldId) {
for (PaymentAccountFormField field : fields) {
if (field.getId() == fieldId) {
return field.getValue();
}
}
throw new IllegalArgumentException("Form does not contain field " + fieldId);
}
/**
* Get a structured form for the given payment method.
*/

View File

@ -21,6 +21,7 @@ import bisq.common.proto.ProtoUtil;
import bisq.common.proto.persistable.PersistablePayload;
import bisq.core.locale.Country;
import bisq.core.locale.TradeCurrency;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
@ -109,6 +110,7 @@ public final class PaymentAccountFormField implements PersistablePayload {
public enum Component {
TEXT,
TEXTAREA,
SELECT_ONE,
SELECT_MULTIPLE;
@ -133,6 +135,7 @@ public final class PaymentAccountFormField implements PersistablePayload {
private List<Country> supportedCountries;
private List<Country> supportedSepaEuroCountries;
private List<Country> supportedSepaNonEuroCountries;
private List<String> requiredForCountries;
public PaymentAccountFormField(FieldId id) {
this.id = id;
@ -152,6 +155,7 @@ public final class PaymentAccountFormField implements PersistablePayload {
Optional.ofNullable(supportedCountries).ifPresent(e -> builder.addAllSupportedCountries(ProtoUtil.collectionToProto(supportedCountries, protobuf.Country.class)));
Optional.ofNullable(supportedSepaEuroCountries).ifPresent(e -> builder.addAllSupportedSepaEuroCountries(ProtoUtil.collectionToProto(supportedSepaEuroCountries, protobuf.Country.class)));
Optional.ofNullable(supportedSepaNonEuroCountries).ifPresent(e -> builder.addAllSupportedSepaNonEuroCountries(ProtoUtil.collectionToProto(supportedSepaNonEuroCountries, protobuf.Country.class)));
Optional.ofNullable(requiredForCountries).ifPresent(builder::addAllRequiredForCountries);
return builder.build();
}
@ -165,6 +169,7 @@ public final class PaymentAccountFormField implements PersistablePayload {
formField.supportedCountries = proto.getSupportedCountriesList().isEmpty() ? null : proto.getSupportedCountriesList().stream().map(Country::fromProto).collect(Collectors.toList());
formField.supportedSepaEuroCountries = proto.getSupportedSepaEuroCountriesList().isEmpty() ? null : proto.getSupportedSepaEuroCountriesList().stream().map(Country::fromProto).collect(Collectors.toList());
formField.supportedSepaNonEuroCountries = proto.getSupportedSepaNonEuroCountriesList().isEmpty() ? null : proto.getSupportedSepaNonEuroCountriesList().stream().map(Country::fromProto).collect(Collectors.toList());
formField.requiredForCountries = proto.getRequiredForCountriesList() == null ? null : new ArrayList<String>(proto.getRequiredForCountriesList());
return formField;
}
}

View File

@ -20,7 +20,7 @@ package bisq.core.locale;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -264,18 +264,15 @@ public class BankUtil {
}
}
public static List<Country> getAllStateRequiredCountries() {
List<String> codes = List.of("US", "CA", "AU", "MY", "MX", "CN");
List<Country> list = CountryUtil.getCountries(codes);
list.sort((a, b) -> a.name.compareTo(b.name));
return list;
}
public static boolean isStateRequired(String countryCode) {
switch (countryCode) {
case "US":
case "CA":
case "AU":
case "MY":
case "MX":
case "CN":
return true;
default:
return false;
}
return getAllStateRequiredCountries().stream().map(country -> country.code).collect(Collectors.toList()).contains(countryCode);
}
public static boolean isNationalAccountIdRequired(String countryCode) {

View File

@ -41,6 +41,10 @@ public class CountryUtil {
return countries.stream().map(country -> country.code).collect(Collectors.toList());
}
public static Country getCountry(String code) {
return getCountries(List.of(code)).get(0);
}
public static List<Country> getCountries(List<String> codes) {
List<Country> countries = new ArrayList<Country>();
for (String code : codes) {

View File

@ -84,7 +84,7 @@ public final class F2FAccount extends CountryBasedPaymentAccount {
public String getExtraInfo() {
return ((F2FAccountPayload) paymentAccountPayload).getExtraInfo();
}
@Override
protected PaymentAccountFormField getEmptyFormField(PaymentAccountFormField.FieldId fieldId) {
var field = super.getEmptyFormField(fieldId);

View File

@ -40,6 +40,16 @@ public final class MoneyGramAccount extends PaymentAccount {
@Nullable
private Country country;
private static final List<PaymentAccountFormField.FieldId> INPUT_FIELD_IDS = List.of(
PaymentAccountFormField.FieldId.ACCOUNT_NAME,
PaymentAccountFormField.FieldId.COUNTRY,
PaymentAccountFormField.FieldId.STATE,
PaymentAccountFormField.FieldId.HOLDER_NAME,
PaymentAccountFormField.FieldId.EMAIL,
PaymentAccountFormField.FieldId.TRADE_CURRENCIES,
PaymentAccountFormField.FieldId.SALT
);
public static final List<TradeCurrency> SUPPORTED_CURRENCIES = List.of(
new FiatCurrency("AED"),
new FiatCurrency("ARS"),
@ -108,7 +118,7 @@ public final class MoneyGramAccount extends PaymentAccount {
@Override
public @NotNull List<PaymentAccountFormField.FieldId> getInputFieldIds() {
throw new RuntimeException("Not implemented");
return INPUT_FIELD_IDS;
}
@Nullable
@ -145,7 +155,14 @@ public final class MoneyGramAccount extends PaymentAccount {
return ((MoneyGramAccountPayload) paymentAccountPayload).getState();
}
public void setState(String email) {
((MoneyGramAccountPayload) paymentAccountPayload).setState(email);
public void setState(String state) {
((MoneyGramAccountPayload) paymentAccountPayload).setState(state);
}
@Override
protected PaymentAccountFormField getEmptyFormField(PaymentAccountFormField.FieldId fieldId) {
var field = super.getEmptyFormField(fieldId);
if (field.getId() == PaymentAccountFormField.FieldId.HOLDER_NAME) field.setLabel("Full name (first, middle, last)");
return field;
}
}

View File

@ -19,6 +19,7 @@ package bisq.core.payment;
import bisq.core.api.model.PaymentAccountForm;
import bisq.core.api.model.PaymentAccountFormField;
import bisq.core.locale.BankUtil;
import bisq.core.locale.Country;
import bisq.core.locale.CountryUtil;
import bisq.core.locale.CurrencyUtil;
@ -379,15 +380,15 @@ public abstract class PaymentAccount implements PersistablePayload {
checkNotEmpty(value);
break;
case COUNTRY:
List<Country> supportedCountries = ((CountryBasedPaymentAccount) this).getSupportedCountries();
if (supportedCountries == null || supportedCountries.isEmpty()) {
if (!CountryUtil.findCountryByCode(value).isPresent()) throw new IllegalArgumentException("Invalid country code: " + value);
} else {
System.out.println("BUT WE SUPPORT THESE COUNTRIES!");
System.out.println(supportedCountries);
List<String> supportedCountryCodes = CountryUtil.getCountryCodes(supportedCountries);
if (!supportedCountryCodes.contains(value)) throw new IllegalArgumentException("Country is not supported by " + getPaymentMethod().getId() + ": " + value);
if (this instanceof CountryBasedPaymentAccount) {
List<Country> supportedCountries = ((CountryBasedPaymentAccount) this).getSupportedCountries();
if (supportedCountries != null && !supportedCountries.isEmpty()) {
List<String> supportedCountryCodes = CountryUtil.getCountryCodes(supportedCountries);
if (!supportedCountryCodes.contains(value)) throw new IllegalArgumentException("Country is not supported by " + getPaymentMethod().getId() + ": " + value);
return;
}
}
if (!CountryUtil.findCountryByCode(value).isPresent()) throw new IllegalArgumentException("Invalid country code: " + value);
break;
case EMAIL:
checkNotEmpty(value);
@ -414,7 +415,7 @@ public abstract class PaymentAccount implements PersistablePayload {
case IFSC:
throw new IllegalArgumentException("Not implemented");
case INTERMEDIARY_COUNTRY_CODE:
if (!CountryUtil.findCountryByCode(value).isPresent()) throw new IllegalArgumentException("Invalid country code: " + value); // TODO: value must be within supported countries unless all countries supported
if (!CountryUtil.findCountryByCode(value).isPresent()) throw new IllegalArgumentException("Invalid country code: " + value);
break;
case MOBILE_NR:
throw new IllegalArgumentException("Not implemented");
@ -440,7 +441,17 @@ public abstract class PaymentAccount implements PersistablePayload {
case SPECIAL_INSTRUCTIONS:
break;
case STATE:
throw new IllegalArgumentException("Not implemented");
String countryCode = form.getValue(PaymentAccountFormField.FieldId.COUNTRY);
System.out.println("BACKEND RECEIVED STATE COUNTRY CODE: " + countryCode);
System.out.println("BACKEND RECEIVED STATE: " + value);
boolean isStateRequired = BankUtil.isStateRequired(countryCode);
System.out.println("IS STATE REQUIRED :" + isStateRequired);
if (value == null || value.isEmpty()) {
if (isStateRequired) throw new IllegalArgumentException("Must provide state for country " + countryCode);
} else {
if (!isStateRequired) throw new IllegalArgumentException("Must not provide state for country " + countryCode);
}
break;
case TRADE_CURRENCIES:
checkNotEmpty(value);
List<String> currencyCodes = commaDelimitedCodesToList.apply(value);
@ -497,7 +508,7 @@ public abstract class PaymentAccount implements PersistablePayload {
case BANK_ACCOUNT_TYPE:
throw new IllegalArgumentException("Not implemented");
case BANK_ADDRESS:
field.setComponent(PaymentAccountFormField.Component.TEXT);
field.setComponent(PaymentAccountFormField.Component.TEXTAREA);
field.setLabel("Receiving Bank address");
break;
case BANK_BRANCH:
@ -531,7 +542,7 @@ public abstract class PaymentAccount implements PersistablePayload {
field.setLabel("Account No. (or IBAN)");
break;
case BENEFICIARY_ADDRESS:
field.setComponent(PaymentAccountFormField.Component.TEXT);
field.setComponent(PaymentAccountFormField.Component.TEXTAREA);
field.setLabel("Beneficiary address");
break;
case BENEFICIARY_CITY:
@ -561,7 +572,7 @@ public abstract class PaymentAccount implements PersistablePayload {
case COUNTRY:
field.setComponent(PaymentAccountFormField.Component.SELECT_ONE);
field.setLabel("Country");
field.setSupportedCountries(((CountryBasedPaymentAccount) this).getSupportedCountries());
if (this instanceof CountryBasedPaymentAccount) field.setSupportedCountries(((CountryBasedPaymentAccount) this).getSupportedCountries());
break;
case EMAIL:
field.setComponent(PaymentAccountFormField.Component.TEXT);
@ -573,7 +584,7 @@ public abstract class PaymentAccount implements PersistablePayload {
field.setLabel("Email or mobile number");
break;
case EXTRA_INFO:
field.setComponent(PaymentAccountFormField.Component.TEXT);
field.setComponent(PaymentAccountFormField.Component.TEXTAREA);
field.setLabel("Optional additional information");
break;
case HOLDER_ADDRESS:
@ -595,7 +606,7 @@ public abstract class PaymentAccount implements PersistablePayload {
case IFSC:
throw new IllegalArgumentException("Not implemented");
case INTERMEDIARY_ADDRESS:
field.setComponent(PaymentAccountFormField.Component.TEXT);
field.setComponent(PaymentAccountFormField.Component.TEXTAREA);
field.setLabel("Intermediary Bank address");
break;
case INTERMEDIARY_BRANCH:
@ -641,7 +652,10 @@ public abstract class PaymentAccount implements PersistablePayload {
field.setLabel("Special instructions");
break;
case STATE:
throw new IllegalArgumentException("Not implemented");
field.setComponent(PaymentAccountFormField.Component.TEXT);
field.setLabel("State/Province/Region");
field.setRequiredForCountries(CountryUtil.getCountryCodes(BankUtil.getAllStateRequiredCountries()));
break;
case TRADE_CURRENCIES:
field.setComponent(PaymentAccountFormField.Component.SELECT_MULTIPLE);
field.setLabel("Supported currencies");

View File

@ -334,7 +334,8 @@ public final class PaymentMethod implements PersistablePayload, Comparable<Payme
CLEAR_X_CHANGE_ID,
SWIFT_ID,
F2F_ID,
STRIKE_ID);
STRIKE_ID,
MONEY_GRAM_ID);
return paymentMethods.stream().filter(paymentMethod -> paymentMethodIds.contains(paymentMethod.getId())).collect(Collectors.toList());
}

View File

@ -2081,6 +2081,7 @@ message PaymentAccountForm {
SWIFT = 4;
F2F = 5;
STRIKE = 6;
MONEY_GRAM = 7;
}
FormId id = 1;
repeated PaymentAccountFormField fields = 2;
@ -2149,8 +2150,9 @@ message PaymentAccountFormField {
}
enum Component {
TEXT = 0;
SELECT_ONE = 1;
SELECT_MULTIPLE = 2;
TEXTAREA = 1;
SELECT_ONE = 2;
SELECT_MULTIPLE = 3;
}
FieldId id = 1;
Component component = 2;
@ -2163,4 +2165,5 @@ message PaymentAccountFormField {
repeated Country supported_countries = 9;
repeated Country supported_sepa_euro_countries = 10;
repeated Country supported_sepa_non_euro_countries = 11;
repeated string required_for_countries = 12;
}