Skip to content

Commit

Permalink
Merge pull request #7255 from cparke2/create-sbp-payment-method
Browse files Browse the repository at this point in the history
Create payment method "Faster Payments System (SBP)" for Russian Ruble
  • Loading branch information
HenrikJannsen authored Sep 26, 2024
2 parents 2f665fc + 0bc6e63 commit b4c6963
Show file tree
Hide file tree
Showing 28 changed files with 634 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ public static PaymentAccount getPaymentAccount(PaymentMethod paymentMethod) {
return new BsqSwapAccount();
case PaymentMethod.MERCADO_PAGO_ID:
return new MercadoPagoAccount();
case PaymentMethod.SBP_ID:
return new SbpAccount();

// Cannot be deleted as it would break old trade history entries
case PaymentMethod.OK_PAY_ID:
Expand Down
2 changes: 2 additions & 0 deletions core/src/main/java/bisq/core/payment/PaymentAccountUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,8 @@ public static List<TradeCurrency> getTradeCurrencies(PaymentMethod paymentMethod
return VerseAccount.SUPPORTED_CURRENCIES;
case MERCADO_PAGO_ID:
return MercadoPagoAccount.SUPPORTED_CURRENCIES();
case SBP_ID:
return SbpAccount.SUPPORTED_CURRENCIES;
default:
return Collections.emptyList();
}
Expand Down
78 changes: 78 additions & 0 deletions core/src/main/java/bisq/core/payment/SbpAccount.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* 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.locale.FiatCurrency;
import bisq.core.locale.TradeCurrency;
import bisq.core.payment.payload.SbpAccountPayload;
import bisq.core.payment.payload.PaymentAccountPayload;
import bisq.core.payment.payload.PaymentMethod;

import java.util.List;

import lombok.EqualsAndHashCode;
import lombok.NonNull;

@EqualsAndHashCode(callSuper = true)
public final class SbpAccount extends PaymentAccount {

public static final List<TradeCurrency> SUPPORTED_CURRENCIES = List.of(new FiatCurrency("RUB"));

public SbpAccount() {
super(PaymentMethod.SBP);
setSingleTradeCurrency(SUPPORTED_CURRENCIES.get(0));
}

@Override
protected PaymentAccountPayload createPayload() {
return new SbpAccountPayload(paymentMethod.getId(), id);
}

@Override
public @NonNull List<TradeCurrency> getSupportedCurrencies() {
return SUPPORTED_CURRENCIES;
}

public String getMessageForAccountCreation() {
return "payment.sbp.info.account";
}

public void setMobileNumber(String mobileNumber) {
((SbpAccountPayload) paymentAccountPayload).setMobileNumber(mobileNumber);
}

public String getMobileNumber() {
return ((SbpAccountPayload) paymentAccountPayload).getMobileNumber();
}

public void setBankName(String bankName) {
((SbpAccountPayload) paymentAccountPayload).setBankName(bankName);
}

public String getBankName() {
return ((SbpAccountPayload) paymentAccountPayload).getBankName();
}

public void setHolderName(String holderName) {
((SbpAccountPayload) paymentAccountPayload).setHolderName(holderName);
}

public String getHolderName() {
return ((SbpAccountPayload) paymentAccountPayload).getHolderName();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ public final class PaymentMethod implements PersistablePayload, Comparable<Payme
public static final String DOMESTIC_WIRE_TRANSFER_ID = "DOMESTIC_WIRE_TRANSFER";
public static final String BSQ_SWAP_ID = "BSQ_SWAP";
public static final String MERCADO_PAGO_ID = "MERCADO_PAGO";
public static final String SBP_ID = "SBP";

// Cannot be deleted as it would break old trade history entries
@Deprecated
Expand Down Expand Up @@ -192,6 +193,7 @@ public final class PaymentMethod implements PersistablePayload, Comparable<Payme
public static PaymentMethod DOMESTIC_WIRE_TRANSFER;
public static PaymentMethod BSQ_SWAP;
public static PaymentMethod MERCADO_PAGO;
public static PaymentMethod SBP;

// Cannot be deleted as it would break old trade history entries
@Deprecated
Expand Down Expand Up @@ -280,6 +282,9 @@ public final class PaymentMethod implements PersistablePayload, Comparable<Payme
// Thailand
PROMPT_PAY = new PaymentMethod(PROMPT_PAY_ID, DAY, DEFAULT_TRADE_LIMIT_LOW_RISK),

// Russia
SBP = new PaymentMethod(SBP_ID, DAY, DEFAULT_TRADE_LIMIT_HIGH_RISK),

// Altcoins
BLOCK_CHAINS = new PaymentMethod(BLOCK_CHAINS_ID, DAY, DEFAULT_TRADE_LIMIT_VERY_LOW_RISK),
// Altcoins with 1 hour trade period
Expand Down
129 changes: 129 additions & 0 deletions core/src/main/java/bisq/core/payment/payload/SbpAccountPayload.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
/*
* 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 org.apache.commons.lang3.ArrayUtils;

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 SbpAccountPayload extends PaymentAccountPayload implements PayloadWithHolderName {
private String holderName = "";
private String mobileNumber = "";
private String bankName = "";

public SbpAccountPayload(String paymentMethod, String id) {
super(paymentMethod, id);
}


///////////////////////////////////////////////////////////////////////////////////////////
// PROTO BUFFER
///////////////////////////////////////////////////////////////////////////////////////////

private SbpAccountPayload(String paymentMethod,
String id,
String holderName,
String mobileNumber,
String bankName,
long maxTradePeriod,
Map<String, String> excludeFromJsonDataMap) {
super(paymentMethod,
id,
maxTradePeriod,
excludeFromJsonDataMap);

this.holderName = holderName;
this.mobileNumber = mobileNumber;
this.bankName = bankName;
}

@Override
public Message toProtoMessage() {
return getPaymentAccountPayloadBuilder()
.setSbpAccountPayload(protobuf.SbpAccountPayload.newBuilder()
.setHolderName(holderName)
.setMobileNumber(mobileNumber)
.setBankName(bankName))
.build();
}

public static SbpAccountPayload fromProto(protobuf.PaymentAccountPayload proto) {
return new SbpAccountPayload(proto.getPaymentMethodId(),
proto.getId(),
proto.getSbpAccountPayload().getHolderName(),
proto.getSbpAccountPayload().getMobileNumber(),
proto.getSbpAccountPayload().getBankName(),
proto.getMaxTradePeriod(),
new HashMap<>(proto.getExcludeFromJsonDataMap()));
}


///////////////////////////////////////////////////////////////////////////////////////////
// API
///////////////////////////////////////////////////////////////////////////////////////////

@Override
public String getPaymentDetails() {
return Res.get(paymentMethodId) + " - " +
Res.getWithCol("payment.account.owner.sbp") + " " + holderName + ", " +
Res.getWithCol("payment.mobile") + " " + mobileNumber + ", " +
Res.getWithCol("payment.bank.name") + " " + bankName;
}

@Override
public String getPaymentDetailsForTradePopup() {
return Res.getWithCol("payment.account.owner.sbp") + " " + holderName + "\n" +
Res.getWithCol("payment.mobile") + " " + mobileNumber + "\n" +
Res.getWithCol("payment.bank.name") + " " + bankName;
}

@Override
public byte[] getAgeWitnessInputData() {
// We don't add holderName because we don't want to break age validation if the user recreates an account with
// slight changes in holder name (e.g. add or remove middle name)
return super.getAgeWitnessInputData(
ArrayUtils.addAll(
mobileNumber.getBytes(StandardCharsets.UTF_8),
bankName.getBytes(StandardCharsets.UTF_8)
)
);
}

@Override
public String getOwnerId() {
return holderName;
}
}
3 changes: 3 additions & 0 deletions core/src/main/java/bisq/core/proto/CoreProtoResolver.java
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
import bisq.core.payment.payload.RtgsAccountPayload;
import bisq.core.payment.payload.SameBankAccountPayload;
import bisq.core.payment.payload.SatispayAccountPayload;
import bisq.core.payment.payload.SbpAccountPayload;
import bisq.core.payment.payload.SepaAccountPayload;
import bisq.core.payment.payload.SepaInstantAccountPayload;
import bisq.core.payment.payload.SpecificBanksAccountPayload;
Expand Down Expand Up @@ -236,6 +237,8 @@ public PaymentAccountPayload fromProto(protobuf.PaymentAccountPayload proto) {
return SwiftAccountPayload.fromProto(proto);
case BSQ_SWAP_ACCOUNT_PAYLOAD:
return BsqSwapAccountPayload.fromProto(proto);
case SBP_ACCOUNT_PAYLOAD:
return SbpAccountPayload.fromProto(proto);

// Cannot be deleted as it would break old trade history entries
case O_K_PAY_ACCOUNT_PAYLOAD:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,8 @@ enum PaymentMethodMapper {
TIKKIE,
TRANSFERWISE_USD,
ACH_TRANSFER,
DOMESTIC_WIRE_TRANSFER;
DOMESTIC_WIRE_TRANSFER,
SBP;

private static final PaymentMethodMapper[] values = values(); // cache for perf gain
}
Expand Down
14 changes: 14 additions & 0 deletions core/src/main/resources/i18n/displayStrings.properties
Original file line number Diff line number Diff line change
Expand Up @@ -820,6 +820,7 @@ portfolio.pending.step2_buyer.halCashInfo.msg=You need to send a text message wi
portfolio.pending.step2_buyer.fasterPaymentsHolderNameInfo=Some banks might verify the receiver's name. \
Faster Payments accounts created in old Bisq clients do not provide the receiver's name, \
so please use trade chat to obtain it (if needed).
portfolio.pending.step2_buyer.sbp=Please pay {0} via your bank''s SBP "Pay by Telephone Number" service using the seller''s information on the next screen.\n\n
portfolio.pending.step2_buyer.confirmStart.headline=Confirm that you have started the payment
portfolio.pending.step2_buyer.confirmStart.msg=Did you initiate the {0} payment to your trading partner?
portfolio.pending.step2_buyer.confirmStart.yes=Yes, I have started the payment
Expand Down Expand Up @@ -3720,6 +3721,7 @@ payment.account.userName=User name
payment.account.phoneNr=Phone number
payment.account.owner=Account owner full name
payment.account.owner.ask=[Ask trader to provide account name if needed]
payment.account.owner.sbp=Account owner name (first, middle, and initial of last name)
payment.account.fullName=Full name (first, middle, last)
payment.account.state=State/Province/Region
payment.account.city=City
Expand Down Expand Up @@ -4295,6 +4297,14 @@ payment.amazonGiftCard.info=To pay with Amazon eGift Card, you will need to send
- Amazon eGift Cards can only be redeemed on the Amazon website they were purchased on (e.g., a gift card purchased on amazon.it can only be redeemed on amazon.it)
payment.mercadoPago.holderId=UserID linked to financial institution. Like phone number or email or CVU.

payment.sbp.info.account=The Faster Payments System (SBP) is an inter-bank funds transfer service in RUSSIA that allows individuals \
to make personal payments using just a mobile phone number.\n\n\
1. The service is for payments and transfers between Russian bank accounts in Russian Rubles only.\n\n\
2. Only Russian carrier mobile numbers (+7 country code) can be registered for use with the service.\n\n\
3. You must create a separate Bisq account for each bank where you have an account and want to receive funds.\n\n\
4. SBP displays the receiver's first name, middle name, and initial letter of last name to verify that the phone number is correct. \
Therefore, you should enter the account owner's name on the Bisq account using the same style.

# We use constants from the code so we do not use our normal naming convention
# dynamic values are not recognized by IntelliJ

Expand Down Expand Up @@ -4423,6 +4433,8 @@ DOMESTIC_WIRE_TRANSFER=Domestic Wire Transfer
BSQ_SWAP=BSQ Swap
# suppress inspection "UnusedProperty"
MERCADO_PAGO=MercadoPago
# suppress inspection "UnusedProperty"
SBP=Faster Payments System (SBP)

# Deprecated: Cannot be deleted as it would break old trade history entries
# suppress inspection "UnusedProperty"
Expand Down Expand Up @@ -4521,6 +4533,8 @@ DOMESTIC_WIRE_TRANSFER_SHORT=Domestic Wire
BSQ_SWAP_SHORT=BSQ Swap
# suppress inspection "UnusedProperty"
MERCADO_PAGO_SHORT=MercadoPago
# suppress inspection "UnusedProperty"
SBP_SHORT=SBP

# Deprecated: Cannot be deleted as it would break old trade history entries
# suppress inspection "UnusedProperty"
Expand Down
14 changes: 14 additions & 0 deletions core/src/main/resources/i18n/displayStrings_cs.properties
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,7 @@ portfolio.pending.step2_buyer.westernUnionMTCNInfo.msg=Musíte odeslat MTCN (sle
portfolio.pending.step2_buyer.halCashInfo.headline=Pošlete HalCash kód
portfolio.pending.step2_buyer.halCashInfo.msg=Musíte odeslat jak textovou zprávu s kódem HalCash tak i obchodní ID ({0}) prodejci BTC.\nMobilní číslo prodejce je {1}.\n\nPoslali jste kód prodejci?
portfolio.pending.step2_buyer.fasterPaymentsHolderNameInfo=Některé banky mohou ověřovat jméno příjemce. Účty Faster Payments vytvořené u starých klientů Bisq neposkytují jméno příjemce, proto si jej (v případě potřeby) vyžádejte pomocí obchodního chatu.
portfolio.pending.step2_buyer.sbp=Please pay {0} via your bank''s SBP "Pay by Telephone Number" service using the seller''s information on the next screen.\n\n
portfolio.pending.step2_buyer.confirmStart.headline=Potvrďte, že jste zahájili platbu
portfolio.pending.step2_buyer.confirmStart.msg=Zahájili jste platbu {0} vašemu obchodnímu partnerovi?
portfolio.pending.step2_buyer.confirmStart.yes=Ano, zahájil jsem platbu
Expand Down Expand Up @@ -2946,6 +2947,7 @@ payment.account.userName=Uživatelské jméno
payment.account.phoneNr=Telefonní číslo
payment.account.owner=Celé jméno vlastníka účtu
payment.account.owner.ask=[Ask trader to provide account name if needed]
payment.account.owner.sbp=Account owner name (first, middle, and initial of last name)
payment.account.fullName=Celé jméno (křestní, střední, příjmení)
payment.account.state=Stát/Provincie/Region
payment.account.city=Město
Expand Down Expand Up @@ -3206,6 +3208,14 @@ payment.payid.info=PayID jako telefonní číslo, e-mailová adresa nebo austral
payment.amazonGiftCard.info=Chcete-li platit dárkovou kartou Amazon eGift, budete muset prodejci BTC poslat kartu Amazon eGift přes svůj účet Amazon.\n\nPro další detaily a rady viz wiki: [HYPERLINK:https://bisq.wiki/Amazon_eGift_card].\n\nZde jsou tři důležité poznámky:\n- Preferujte dárkové karty v hodnotě do 100 USD, protože Amazon může považovat nákupy karet s vyššími částkami jako podezřelé a zablokovat je.\n- Na kartě do zprávy pro příjemce můžete přidat i vlastní originální text (např. "Happy birthday Susan!"). V takovém případě o tom informujte protistranu pomocí obchodního chatu, aby mohli s jistotou ověřit, že obdržená dárková karta pochází od vás.\n- Karty Amazon eGift lze uplatnit pouze na té stránce Amazon, na které byly také koupeny (např. karta koupená na amazon.it může být uplatněna zase jen na amazon.it).
payment.mercadoPago.holderId=UserID linked to financial institution. Like phone number or email or CVU.

payment.sbp.info.account=The Faster Payments System (SBP) is an inter-bank funds transfer service in RUSSIA that allows individuals \
to make personal payments using just a mobile phone number.\n\n\
1. The service is for payments and transfers between Russian bank accounts in Russian Rubles only.\n\n\
2. Only Russian carrier mobile numbers (+7 country code) can be registered for use with the service.\n\n\
3. You must create a separate Bisq account for each bank where you have an account and want to receive funds.\n\n\
4. SBP displays the receiver's first name, middle name, and initial letter of last name to verify that the phone number is correct. \
Therefore, you should enter the account owner's name on the Bisq account using the same style.

# We use constants from the code so we do not use our normal naming convention
# dynamic values are not recognized by IntelliJ

Expand Down Expand Up @@ -3334,6 +3344,8 @@ DOMESTIC_WIRE_TRANSFER=Tuzemský bankovní převod
BSQ_SWAP=BSQ swap
# suppress inspection "UnusedProperty"
MERCADO_PAGO=MercadoPago
# suppress inspection "UnusedProperty"
SBP=Faster Payments System (SBP)

# Deprecated: Cannot be deleted as it would break old trade history entries
# suppress inspection "UnusedProperty"
Expand Down Expand Up @@ -3432,6 +3444,8 @@ DOMESTIC_WIRE_TRANSFER_SHORT=Tuzemský převod
BSQ_SWAP_SHORT=BSQ swap
# suppress inspection "UnusedProperty"
MERCADO_PAGO_SHORT=MercadoPago
# suppress inspection "UnusedProperty"
SBP_SHORT=SBP

# Deprecated: Cannot be deleted as it would break old trade history entries
# suppress inspection "UnusedProperty"
Expand Down
Loading

0 comments on commit b4c6963

Please sign in to comment.