add Nequi payment method

Signed-off-by: jmacxx <47253594+jmacxx@users.noreply.github.com>
This commit is contained in:
jmacxx 2021-09-24 10:57:03 -05:00
parent 9e5a1c2fd4
commit f792db98d0
No known key found for this signature in database
GPG key ID: 155297BABFE94A1B
11 changed files with 303 additions and 1 deletions

View file

@ -0,0 +1,56 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package bisq.core.payment;
import bisq.core.payment.payload.PaymentAccountPayload;
import bisq.core.payment.payload.PaymentMethod;
import bisq.core.payment.payload.NequiAccountPayload;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
public final class NequiAccount extends CountryBasedPaymentAccount {
public NequiAccount() {
super(PaymentMethod.NEQUI);
}
@Override
protected PaymentAccountPayload createPayload() {
return new NequiAccountPayload(paymentMethod.getId(), id);
}
public void setMobileNr(String mobileNr) {
((NequiAccountPayload) paymentAccountPayload).setMobileNr(mobileNr);
}
public String getMobileNr() {
return ((NequiAccountPayload) paymentAccountPayload).getMobileNr();
}
public String getMessageForBuyer() {
return "payment.nequi.info.buyer";
}
public String getMessageForSeller() {
return "payment.nequi.info.seller";
}
public String getMessageForAccountCreation() {
return "payment.nequi.info.account";
}
}

View file

@ -96,6 +96,8 @@ public class PaymentAccountFactory {
return new UpiAccount();
case PaymentMethod.PAYTM_ID:
return new PaytmAccount();
case PaymentMethod.NEQUI_ID:
return new NequiAccount();
case PaymentMethod.AMAZON_GIFT_CARD_ID:
return new AmazonGiftCardAccount();
case PaymentMethod.BLOCK_CHAINS_INSTANT_ID:

View file

@ -0,0 +1,99 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package bisq.core.payment.payload;
import bisq.core.locale.Res;
import com.google.protobuf.Message;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
@EqualsAndHashCode(callSuper = true)
@ToString
@Setter
@Getter
@Slf4j
public final class NequiAccountPayload extends CountryBasedPaymentAccountPayload {
private String mobileNr = "";
public NequiAccountPayload(String paymentMethod, String id) {
super(paymentMethod, id);
}
private NequiAccountPayload(String paymentMethod,
String id,
String countryCode,
String mobileNr,
long maxTradePeriod,
Map<String, String> excludeFromJsonDataMap) {
super(paymentMethod,
id,
countryCode,
maxTradePeriod,
excludeFromJsonDataMap);
this.mobileNr = mobileNr;
}
@Override
public Message toProtoMessage() {
protobuf.NequiAccountPayload.Builder builder = protobuf.NequiAccountPayload.newBuilder()
.setMobileNr(mobileNr);
final protobuf.CountryBasedPaymentAccountPayload.Builder countryBasedPaymentAccountPayload = getPaymentAccountPayloadBuilder()
.getCountryBasedPaymentAccountPayloadBuilder()
.setNequiAccountPayload(builder);
return getPaymentAccountPayloadBuilder()
.setCountryBasedPaymentAccountPayload(countryBasedPaymentAccountPayload)
.build();
}
public static NequiAccountPayload fromProto(protobuf.PaymentAccountPayload proto) {
protobuf.CountryBasedPaymentAccountPayload countryBasedPaymentAccountPayload = proto.getCountryBasedPaymentAccountPayload();
protobuf.NequiAccountPayload paytmAccountPayloadPB = countryBasedPaymentAccountPayload.getNequiAccountPayload();
return new NequiAccountPayload(proto.getPaymentMethodId(),
proto.getId(),
countryBasedPaymentAccountPayload.getCountryCode(),
paytmAccountPayloadPB.getMobileNr(),
proto.getMaxTradePeriod(),
new HashMap<>(proto.getExcludeFromJsonDataMap()));
}
@Override
public String getPaymentDetails() {
return Res.get(paymentMethodId) + " - " + Res.getWithCol("payment.mobile") + " " + mobileNr;
}
@Override
public String getPaymentDetailsForTradePopup() {
return getPaymentDetails();
}
@Override
public byte[] getAgeWitnessInputData() {
return super.getAgeWitnessInputData(mobileNr.getBytes(StandardCharsets.UTF_8));
}
}

View file

@ -103,6 +103,7 @@ public final class PaymentMethod implements PersistablePayload, Comparable<Payme
public static final String IMPS_ID = "IMPS";
public static final String UPI_ID = "UPI";
public static final String PAYTM_ID = "PAYTM";
public static final String NEQUI_ID = "NEQUI";
public static final String AMAZON_GIFT_CARD_ID = "AMAZON_GIFT_CARD";
public static final String BLOCK_CHAINS_INSTANT_ID = "BLOCK_CHAINS_INSTANT";
public static final String CASH_BY_MAIL_ID = "CASH_BY_MAIL";
@ -154,6 +155,7 @@ public final class PaymentMethod implements PersistablePayload, Comparable<Payme
public static PaymentMethod IMPS;
public static PaymentMethod UPI;
public static PaymentMethod PAYTM;
public static PaymentMethod NEQUI;
public static PaymentMethod AMAZON_GIFT_CARD;
public static PaymentMethod BLOCK_CHAINS_INSTANT;
public static PaymentMethod CASH_BY_MAIL;
@ -218,6 +220,7 @@ public final class PaymentMethod implements PersistablePayload, Comparable<Payme
IMPS = new PaymentMethod(IMPS_ID, DAY, DEFAULT_TRADE_LIMIT_HIGH_RISK),
UPI = new PaymentMethod(UPI_ID, DAY, Coin.parseCoin("0.05")),
PAYTM = new PaymentMethod(PAYTM_ID, DAY, Coin.parseCoin("0.05")),
NEQUI = new PaymentMethod(NEQUI_ID, DAY, DEFAULT_TRADE_LIMIT_HIGH_RISK),
CAPITUAL = new PaymentMethod(CAPITUAL_ID, DAY, DEFAULT_TRADE_LIMIT_HIGH_RISK),
CELPAY = new PaymentMethod(CELPAY_ID, DAY, DEFAULT_TRADE_LIMIT_HIGH_RISK),
SWIFT = new PaymentMethod(SWIFT_ID, 7 * DAY, DEFAULT_TRADE_LIMIT_MID_RISK),

View file

@ -44,6 +44,7 @@ import bisq.core.payment.payload.MoneyBeamAccountPayload;
import bisq.core.payment.payload.MoneyGramAccountPayload;
import bisq.core.payment.payload.NationalBankAccountPayload;
import bisq.core.payment.payload.NeftAccountPayload;
import bisq.core.payment.payload.NequiAccountPayload;
import bisq.core.payment.payload.OKPayAccountPayload;
import bisq.core.payment.payload.PaxumAccountPayload;
import bisq.core.payment.payload.PaymentAccountPayload;
@ -128,6 +129,8 @@ public class CoreProtoResolver implements ProtoResolver {
return UpiAccountPayload.fromProto(proto);
case PAYTM_ACCOUNT_PAYLOAD:
return PaytmAccountPayload.fromProto(proto);
case NEQUI_ACCOUNT_PAYLOAD:
return NequiAccountPayload.fromProto(proto);
case IFSC_BASED_ACCOUNT_PAYLOAD:
final protobuf.IfscBasedAccountPayload.MessageCase messageCaseIfsc = proto.getCountryBasedPaymentAccountPayload().getIfscBasedAccountPayload().getMessageCase();
switch (messageCaseIfsc) {

View file

@ -162,7 +162,8 @@ public final class TradeStatistics3 implements ProcessOncePersistableNetworkPayl
IMPS,
UPI,
PAYTM,
CELPAY
CELPAY,
NEQUI
}
@Getter

View file

@ -3614,6 +3614,22 @@ CelPay supports multiple stablecoins:\n\n\
BTC Sellers should expect to receive any matching currency stablecoin from the BTC Buyer. It is possible for the BTC Buyer to send any matching currency stablecoin.
payment.celpay.supportedCurrenciesForReceiver=Supported currencies (please note: all the currencies below are supported stable coins within the Celcius app. Trades are for stable coins, not fiat.)
payment.nequi.info.account=Please make sure to include your phone number that is associated with your Nequi account.\n\n\
When users set up a Nequi account payment limits are set to a maximum of ~ 7,000,000 COP that can be sent per month.\n\n\
If you intend to trade amount of over 7,000,000 COP per trade you will need to complete KYC with Bancolombia and pay a fee \
of around 15,000 COP. After this all transactions will incur a 0.4% of tax. Please ensure you are aware of the latest taxes.\n\n\
Users should also be aware of account limits. Trades above Nequi account limits will likely have to be cancelled.
payment.nequi.info.buyer=Please send payment only to the phone number provided in the BTC Seller's Bisq account.\n\n\
When users set up a Nequi account, payment limits are set to a maximum of ~ 7,000,000 COP that can be sent per month.\n\n\
If you intend to trade amount of over 7,000,000 COP per trade you will need to complete KYC with Bancolombia and pay a fee \
of around 15,000 COP. After this all transactions will incur a 0.4% of tax. Please ensure you are aware of the latest taxes.\n\n\
Users should also be aware of account limits. Trades above Nequi account limits will likely have to be cancelled.
payment.nequi.info.seller=Please check that the payment received matches the phone number provided in the BTC Buyer's Bisq account.\n\n\
When users set up a Nequi account, payment limits are set to a maximum of ~ 7,000,000 COP that can be sent per month.\n\n\
If you intend to trade amount of over 7,000,000 COP per trade you will need to complete KYC with Bancolombia and pay a fee \
of around 15,000 COP. After this all transactions will incur a 0.4% of tax. Please ensure you are aware of the latest taxes.\n\n\
Users should also be aware of account limits. Trades above Nequi account limits will likely have to be cancelled.
payment.usPostalMoneyOrder.info=Trading using US Postal Money Orders (USPMO) on Bisq requires that you understand the following:\n\
\n\
- BTC buyers must write the BTC Sellers name in both the Payer and the Payees fields & take a high-resolution photo of the USPMO and envelope with proof of tracking before sending.\n\
@ -3791,6 +3807,8 @@ UPI=India/UPI
# suppress inspection "UnusedProperty"
PAYTM=India/PayTM
# suppress inspection "UnusedProperty"
NEQUI=Nequi
# suppress inspection "UnusedProperty"
AMAZON_GIFT_CARD=Amazon eGift Card
# suppress inspection "UnusedProperty"
BLOCK_CHAINS_INSTANT=Altcoins Instant
@ -3863,6 +3881,8 @@ UPI_SHORT=UPI
# suppress inspection "UnusedProperty"
PAYTM_SHORT=PayTM
# suppress inspection "UnusedProperty"
NEQUI_SHORT=Nequi
# suppress inspection "UnusedProperty"
AMAZON_GIFT_CARD_SHORT=Amazon eGift Card
# suppress inspection "UnusedProperty"
BLOCK_CHAINS_INSTANT_SHORT=Altcoins Instant

View file

@ -0,0 +1,106 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package bisq.desktop.components.paymentmethods;
import bisq.desktop.components.InputTextField;
import bisq.desktop.util.FormBuilder;
import bisq.desktop.util.Layout;
import bisq.core.account.witness.AccountAgeWitnessService;
import bisq.core.locale.CountryUtil;
import bisq.core.locale.FiatCurrency;
import bisq.core.locale.Res;
import bisq.core.payment.PaymentAccount;
import bisq.core.payment.NequiAccount;
import bisq.core.payment.payload.PaymentAccountPayload;
import bisq.core.payment.payload.NequiAccountPayload;
import bisq.core.util.coin.CoinFormatter;
import bisq.core.util.validation.InputValidator;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import static bisq.desktop.util.FormBuilder.addCompactTopLabelTextField;
import static bisq.desktop.util.FormBuilder.addTopLabelTextField;
import static bisq.desktop.util.FormBuilder.addTopLabelTextFieldWithCopyIcon;
public class NequiForm extends PaymentMethodForm {
private final NequiAccount account;
private InputTextField mobileNrInputTextField;
public static int addFormForBuyer(GridPane gridPane, int gridRow,
PaymentAccountPayload paymentAccountPayload) {
addTopLabelTextFieldWithCopyIcon(gridPane, gridRow, 1, Res.get("payment.mobile"),
((NequiAccountPayload) paymentAccountPayload).getMobileNr(), Layout.COMPACT_FIRST_ROW_AND_GROUP_DISTANCE);
return gridRow;
}
public NequiForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService,
InputValidator inputValidator, GridPane gridPane,
int gridRow, CoinFormatter formatter) {
super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter);
this.account = (NequiAccount) paymentAccount;
}
@Override
public void addFormForAddAccount() {
// this payment method is only for Columbia/COP
account.setSingleTradeCurrency(new FiatCurrency("COP"));
CountryUtil.findCountryByCode("CO").ifPresent(c -> account.setCountry(c));
gridRowFrom = gridRow + 1;
mobileNrInputTextField = FormBuilder.addInputTextField(gridPane, ++gridRow, Res.get("payment.mobile"));
mobileNrInputTextField.setValidator(inputValidator);
mobileNrInputTextField.textProperty().addListener((ov, oldValue, newValue) -> {
account.setMobileNr(newValue.trim());
updateFromInputs();
});
addTopLabelTextField(gridPane, ++gridRow, Res.get("shared.currency"), account.getSingleTradeCurrency().getNameAndCode());
addTopLabelTextField(gridPane, ++gridRow, Res.get("shared.country"), account.getCountry().name);
addLimitations(false);
addAccountNameTextFieldWithAutoFillToggleButton();
}
@Override
protected void autoFillNameTextField() {
setAccountNameWithString(mobileNrInputTextField.getText());
}
@Override
public void addFormForDisplayAccount() {
gridRowFrom = gridRow;
addTopLabelTextField(gridPane, gridRow, Res.get("payment.account.name"),
account.getAccountName(), Layout.FIRST_ROW_AND_GROUP_DISTANCE);
addCompactTopLabelTextField(gridPane, ++gridRow, Res.get("shared.paymentMethod"),
Res.get(account.getPaymentMethod().getId()));
TextField field = addCompactTopLabelTextField(gridPane, ++gridRow, Res.get("payment.mobile"),
account.getMobileNr()).second;
field.setMouseTransparent(false);
addCompactTopLabelTextField(gridPane, ++gridRow, Res.get("shared.currency"), account.getSingleTradeCurrency().getNameAndCode());
addCompactTopLabelTextField(gridPane, ++gridRow, Res.get("shared.country"), account.getCountry().name);
addLimitations(true);
}
@Override
public void updateAllInputsValid() {
allInputsValid.set(isAccountNameValid()
&& inputValidator.validate(account.getMobileNr()).isValid);
}
}

View file

@ -39,6 +39,7 @@ import bisq.desktop.components.paymentmethods.MoneyBeamForm;
import bisq.desktop.components.paymentmethods.MoneyGramForm;
import bisq.desktop.components.paymentmethods.NationalBankForm;
import bisq.desktop.components.paymentmethods.NeftForm;
import bisq.desktop.components.paymentmethods.NequiForm;
import bisq.desktop.components.paymentmethods.PaymentMethodForm;
import bisq.desktop.components.paymentmethods.PaytmForm;
import bisq.desktop.components.paymentmethods.PerfectMoneyForm;
@ -562,6 +563,8 @@ public class FiatAccountsView extends PaymentAccountsView<GridPane, FiatAccounts
return new UpiForm(paymentAccount, accountAgeWitnessService, inputValidator, root, gridRow, formatter);
case PaymentMethod.PAYTM_ID:
return new PaytmForm(paymentAccount, accountAgeWitnessService, inputValidator, root, gridRow, formatter);
case PaymentMethod.NEQUI_ID:
return new NequiForm(paymentAccount, accountAgeWitnessService, inputValidator, root, gridRow, formatter);
case PaymentMethod.AMAZON_GIFT_CARD_ID:
return new AmazonGiftCardForm(paymentAccount, accountAgeWitnessService, inputValidator, root, gridRow, formatter);
case PaymentMethod.CAPITUAL_ID:

View file

@ -41,6 +41,7 @@ import bisq.desktop.components.paymentmethods.MoneyBeamForm;
import bisq.desktop.components.paymentmethods.MoneyGramForm;
import bisq.desktop.components.paymentmethods.NationalBankForm;
import bisq.desktop.components.paymentmethods.NeftForm;
import bisq.desktop.components.paymentmethods.NequiForm;
import bisq.desktop.components.paymentmethods.PaxumForm;
import bisq.desktop.components.paymentmethods.PayseraForm;
import bisq.desktop.components.paymentmethods.PaytmForm;
@ -352,6 +353,9 @@ public class BuyerStep2View extends TradeStepView {
case PaymentMethod.PAYTM_ID:
gridRow = PaytmForm.addFormForBuyer(gridPane, gridRow, paymentAccountPayload);
break;
case PaymentMethod.NEQUI_ID:
gridRow = NequiForm.addFormForBuyer(gridPane, gridRow, paymentAccountPayload);
break;
case PaymentMethod.AMAZON_GIFT_CARD_ID:
gridRow = AmazonGiftCardForm.addFormForBuyer(gridPane, gridRow, paymentAccountPayload);
break;

View file

@ -1035,6 +1035,7 @@ message CountryBasedPaymentAccountPayload {
UpiAccountPayload upi_account_payload = 9;
PaytmAccountPayload paytm_account_payload = 10;
IfscBasedAccountPayload ifsc_based_account_payload = 11;
NequiAccountPayload nequi_account_payload = 12;
}
}
@ -1269,6 +1270,10 @@ message CelPayAccountPayload {
string email = 1;
}
message NequiAccountPayload {
string mobile_nr = 1;
}
message SwiftAccountPayload {
string beneficiary_name = 1;
string beneficiary_account_nr = 2;