Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create payment method "Faster Payments System (SBP)" for Russian Ruble #7255

Merged
merged 3 commits into from
Sep 26, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -124,6 +124,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 @@ -188,6 +189,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 @@ -276,6 +278,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 mobileNumber = "";
private String holderName = "";
private String bankName = "";

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


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

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

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

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

public static SbpAccountPayload fromProto(protobuf.PaymentAccountPayload proto) {
return new SbpAccountPayload(proto.getPaymentMethodId(),
proto.getId(),
proto.getSbpAccountPayload().getMobileNumber(),
proto.getSbpAccountPayload().getHolderName(),
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
15 changes: 15 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 @@ -3721,6 +3722,7 @@ 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.fullName=Full name (first, middle, last)
payment.account.owner.sbp=Account owner name (first, middle, and initial of last name)
payment.account.state=State/Province/Region
payment.account.city=City
payment.account.address=Address
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 \
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why use all cap for Russia?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will merge it as it is, if you agree to use "Russia" instead just add it in a new PR...

Copy link
Contributor Author

@cparke2 cparke2 Sep 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One big concern in the discussion thread was that the name of this payment method (in English) is almost identical to the existing "Faster Payments" payment method. Added "(SBP)" to help it stand out in the list for people looking for it as SBP. Still, to emphasize to anyone clicking it intending for the other "Faster Payments" method, I used all caps so they'd understand quickly this is not what they're looking for.

I certainly can remove the emphasis of RUSSIA if it seems like overkill. Or, add some other text in the pop-up to clearly and unambiguously differentiate the two payment methods (perhaps on both payment methods?). Really wanted to get some input or response from @pazza83 in the discussion thread on this, but he's mostly avoided my pings to give a comment so I was left on my own.

I am working on adding Russian translations, so certainly could change this however the team feels appropriate.

Copy link
Collaborator

@HenrikJannsen HenrikJannsen Sep 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah ok. Yes I agree that both methods using a similar name might be confusing. I would though not do it by all caps for Russia, but rather to change the name of the payment method to maybe: SBP-Faster Payments System or Faster Payments System Russia (SBP)

Copy link
Contributor Author

@cparke2 cparke2 Sep 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another thought is to change the display name of the existing "Faster Payments" to "Faster Payments (UK)". I don't think that is a compatibility issue, as the Bisq1 accounts identify their associated payment method with an enumeration value, and once created, the display name is always a "custom name" so it won't change for anyone who already has it.

As for the new payment method from Russia, I was trying to avoid too many acronyms in the name, but "SBP" is definitely necessary in the English version or people might not realize that is what it is. English transliteration of the name in Russian is very cheesy too. Maybe to do that and still be consistent: "Faster Payments System-SBP (Russia)"?

There also is a strange set of payment methods prefixed with "India", so that is another approach that also could be used to differentiate the two systems.

I have no problem removing the all caps, that's fine. The existing Faster Payments has no informational pop-up message at all, and further as both payment methods are locked to their respective currencies, so someone choosing the wrong one isn't going to get far...

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes the display string should not have any impact on anything. So Faster Payments (UK) is ok as well.
"Faster Payments System-SBP (Russia)" - sounds ok to me.

...prefixed...

Yes I think that helps ppl to find quickly their relevant method.

...no informational pop-up...

Yes we use popups only if needed. Too many anyway....

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, so it's actually going to be (in English):

"Faster Payment System (UK)"
https://www.wearepay.uk/what-we-do/payment-systems/faster-payment-system/

"Faster Payments System-SBP (Russia)"
https://www.cbr.ru/eng/psystem/sfp/

I'll keep the SBP pop-up but remove the all caps RUSSIA since the naming convention already makes that pretty clear.

Separately, I am also adding some Russian translations currently missing.

The new pull requests should be ready in about a week. Any idea when the next release is scheduled?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know but I guess it will take a bit longer for the release. In doubt you can make smaller PRs so that we get in at least parts.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Faster Payments System-SBP (Russia) works for me also

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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,9 @@ 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 +4534,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_ru.properties
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,7 @@ portfolio.pending.step2_buyer.westernUnionMTCNInfo.msg=Вам необходим
portfolio.pending.step2_buyer.halCashInfo.headline=Отправить код HalCash
portfolio.pending.step2_buyer.halCashInfo.msg=Вам необходимо отправить сообщение с кодом HalCash и идентификатором сделки ({0}) продавцу BTC.\nНомер моб. тел. продавца: {1}\n\nВы отправили код продавцу?
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=Пожалуйста, оплатите {0} через услугу SBP «Оплата по номеру телефона» вашего банка, используя информацию продавца на следующем экране.\n\n
portfolio.pending.step2_buyer.confirmStart.headline=Подтвердите начало платежа
portfolio.pending.step2_buyer.confirmStart.msg=Вы начали платеж {0} своему контрагенту?
portfolio.pending.step2_buyer.confirmStart.yes=Да
Expand Down Expand Up @@ -2945,6 +2946,7 @@ payment.account.phoneNr=Phone number
payment.account.owner=Полное имя владельца счёта
payment.account.owner.ask=[Ask trader to provide account name if needed]
payment.account.fullName=Полное имя (имя, отчество, фамилия)
payment.account.owner.sbp=Имя владельца счёта (Имя, отчество, первая буква фамилии)
payment.account.state=Штат/Провинция/Область
payment.account.city=Город
payment.account.address=Адрес
Expand Down Expand Up @@ -3204,6 +3206,14 @@ payment.payid.info=A PayID like a phone number, email address or an Australian B
payment.amazonGiftCard.info=To pay with Amazon eGift Card, you will need to send an Amazon eGift Card to the BTC seller via your Amazon account. \n\nPlease see the wiki [HYPERLINK:https://bisq.wiki/Amazon_eGift_card] for further details and best practices. \n\nThree important notes:\n- try to send gift cards with amounts of 100 USD or smaller, as Amazon is known to flag larger gift cards as fraudulent\n- try to use creative, believable text for the gift card''s message (e.g., "Happy birthday Susan!") and use trader chat to tell your trading peer the reference text you picked so they can verify your payment\n- 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=Система быстрых платежей (СБП) — это межбанковский сервис денежных переводов в РОССИИ, позволяющий физическим лицам \
совершать личные платежи, используя только номер мобильного телефона.\n\n\
1. Сервис предназначен для платежей и переводов между российскими банковскими счетами только в российских рублях.\n\n\
2. Для использования сервиса можно зарегистрировать только номера мобильных операторов России (+7 код страны).\n\n\
3. Вам необходимо создать отдельную учетную запись Bisq для каждого банка, в котором у вас есть счет и вы хотите получать средства.\n\n\
4. СБП отображает имя, отчество и первую букву фамилии получателя для проверки правильности номера телефона. \
Поэтому вам следует ввести имя владельца учетной записи в учетной записи Bisq, используя тот же стиль.

# 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 @@ -3332,6 +3342,8 @@ DOMESTIC_WIRE_TRANSFER=Domestic Wire Transfer
BSQ_SWAP=BSQ Swap
# suppress inspection "UnusedProperty"
MERCADO_PAGO=MercadoPago
# suppress inspection "UnusedProperty"
SBP=Система быстрых платежей (СБП)

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

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