
How to trick Robocassa
More precisely, how to deceive compassionate individuals taking a commission for the purchase on themselves. Perhaps the title is too loud, maybe this is not an article at all (especially considering that I have never written articles before), but some kind of sketch of a sick brain that needs to finally get enough sleep, rather than finish this online store. Nevertheless, during the integration of Robokassa into the online store, an interesting feature was noticed that allows you to save on purchases at the expense of those who are trying to take obligations on the commission in favor of Robokassa to your account, and I would like to tell you about it.
I think many of you are familiar with such a payment service as Robokassa. This service, as usual, works with two types of customers: individuals and legal entities. An ordinary user, buying something in our online store, expects that he will be presented with an invoice for the amount indicated on the price tag. Obvious is the fact that requiring the user to cover a commission is also a straightforward way. This is where the question arises of how to shift the obligation to pay the share of the robocash desk to the online store itself.
It would seem that could be easier? Surely, such a setting is in your account on the site payment. There it was. Rather, it is. But only if you are a legal entity.
In my situation, the person to whom this store is being created is a physical person. The Robokassa administration prudently placed the issue of the commission in the sidebar of the personal account. Apparently, as the most relevant. In order not to be unfounded:

I will not go deep into details about how transactions work in Robokassa, the article is not about that a bit. If you are interested in technical documentation, it is chewed in detail on the official website.
I can only say that in the process of payments everything rests on several things:
Actually, any tricky change of one of the values included in the SignatureValue line will prevent the transaction from completing. By the way, you, as a developer, can add your own shp * parameters, which will survive the payment and will be sent back to your server. These parameters are also added to the transaction signature.
Now back to the topic of the article.
The solution offered by the employees of Robokassa is alarming right away. It looks like this:
Those. we are invited to calculate the amount so that, taking into account the commission, it is equal to the price of the goods. The store was written on rails, and therefore all additional parsing would take away several lines. Nevertheless, even with all our desire
Problems begin as soon as we want to use this “interface”. Let's say we wanted to calculate the amount for all payment methods. As the manual says:
Not. Not true. If you leave it empty, the server will return such a response (for example, the link merchant.roboxchange.com/WebService/Service.asmx/CalcOutSumm?MerchantLogin=demo&IncCurrLabel=&IncSum=3500 )
First thought: “Maybe I'm a fool and I'm doing something wrong. Maybe you need to omit the parameter wrong? ” But no, based on the same documentation (an example for another function, I only demonstrate the absence of a value):
We try to omit the parameter altogether:
Trouble. But we do not give up. What can be done in such a situation? Right! Suppose we will take the identifier of the payment method from the collection, calculate the payment amount for it separately and stuff it into the form on our website, then change outSum and recount the signature when the user selects another method.
It's good that I did not rush to implement this.
A little rough design showed that in reality everything will not be so rosy. What am I talking about? Let's take a closer look at the payment initialization interface .
Nothing guarded yet? Let's think about it. Robokassa offers us to consider the amount ourselves, based on the payment interface selected by the user. This same IncCurrLabel interface is not included in the signature. This is logical, because the user has the right to choose another method on the box office website. Nevertheless, the commission for each method is calculated on its own. Moreover, it is proposed to us to calculate it, on the side of our server. We get outSum from the same interface, push it into our form, consider the signature and send it for payment.
Again.
Robokassa offers us to deduct the amount of commission from our income, based on what payment method the user wants. At the same time, it allows you to change this very method of payment when we no longer have control over the payment process . What happens next?
And then everything is simple. The user selects the method with the largest commission on our website. In my memory - a bank card. We, like good uncles, deduct about 300 rubles from the price of our goods in order to remove the burden of commission from the buyer. He, having got to the Robokassa website, simply selects payment through some Yandex or WebMoney with a meager commission. The commission for the new method is calculated on the robocash desk website based on the "discount" price option sent by us. All.


And yet, the catch is that from the moment a payment is sent to the site, if the user pays for the order, we will receive “success” in payment. And nobody cares that we lost money on this, in fact. Such a simple scheme.
We can store the amount of our goods and the payment method specified by the user in the same shp * parameters. These parameters are protected from change, which means we will get them safe and sound. Having received them back, we recount the amount again and see how much we received and how much we should have. If you get less, it means that we were deceived and we can somehow influence the user.
The only problem here is that a typical buyer may, by pure chance, even if we write that you can’t change the method at the cash desk itself, do it your own way. We will not be able to return the full amount to him if he confirms such a transaction. So it’s hard to call it a way out.
Register at the checkout as a legal entity. Actually, in my case, the customer decided to do just that. In this case, you get one single switch that solves this problem once and for all.
The cash desk could make it possible to prohibit the user from changing the payment method after the payment is initialized. For example, enter the canChangeCurrLabel flag, and shove it into the transaction signature. Then the costing interface would make sense, and we would not lose money. What prevented is unknown.
Essence of the question
I think many of you are familiar with such a payment service as Robokassa. This service, as usual, works with two types of customers: individuals and legal entities. An ordinary user, buying something in our online store, expects that he will be presented with an invoice for the amount indicated on the price tag. Obvious is the fact that requiring the user to cover a commission is also a straightforward way. This is where the question arises of how to shift the obligation to pay the share of the robocash desk to the online store itself.
It would seem that could be easier? Surely, such a setting is in your account on the site payment. There it was. Rather, it is. But only if you are a legal entity.
In my situation, the person to whom this store is being created is a physical person. The Robokassa administration prudently placed the issue of the commission in the sidebar of the personal account. Apparently, as the most relevant. In order not to be unfounded:

I will not go deep into details about how transactions work in Robokassa, the article is not about that a bit. If you are interested in technical documentation, it is chewed in detail on the official website.
I can only say that in the process of payments everything rests on several things:
- MerchantLogin - your login in the system
- InvId - invoice ID
- OutSum - the amount we want to receive
- MerchantPass1 - technical password No. 1 for transactions (there are two in total, the second one is for receiving information about payment status)
- SignatureValue - md5 hash of a string like "sMerchantLogin: nOutSum: nInvId: sMerchantPass1"
Actually, any tricky change of one of the values included in the SignatureValue line will prevent the transaction from completing. By the way, you, as a developer, can add your own shp * parameters, which will survive the payment and will be sent back to your server. These parameters are also added to the transaction signature.
Now back to the topic of the article.
Solution of the problem
The solution offered by the employees of Robokassa is alarming right away. It looks like this:
For these purposes, a special XML interface has been created:
CalcOutSumm — Method for calculating the amount to be received by the store Method
description: Allows you to calculate the amount to be received based on the current ROBOKASSA rates based on the amount that the user pays.
Method parameters: MerchantLogin - store identifier (string), IncCurrLabel - currency label (string) for which you want to calculate the amount. If you leave it empty, then the calculation will be made for all available currencies, IncSum - the amount that the user must pay.
Request format: merchant.roboxchange.com/WebService/Service.asmx/CalcOutSumm?MerchantLogin=string&IncCurrLabel=string&IncSum=string
Those. we are invited to calculate the amount so that, taking into account the commission, it is equal to the price of the goods. The store was written on rails, and therefore all additional parsing would take away several lines. Nevertheless, even with all our desire
Where is the dog buried?
Problems begin as soon as we want to use this “interface”. Let's say we wanted to calculate the amount for all payment methods. As the manual says:
IncCurrLabel - currency label (string) for which you want to calculate the amount. If left blank, the calculation will be made for all available currencies
Not. Not true. If you leave it empty, the server will return such a response (for example, the link merchant.roboxchange.com/WebService/Service.asmx/CalcOutSumm?MerchantLogin=demo&IncCurrLabel=&IncSum=3500 )
6
Переданы некорректные значения параметров. 0
First thought: “Maybe I'm a fool and I'm doing something wrong. Maybe you need to omit the parameter wrong? ” But no, based on the same documentation (an example for another function, I only demonstrate the absence of a value):
HTTP GET request example:
merchant.roboxchange.com/WebService/Service.asmx/GetRates?MerchantLogin=demo & IncCurrLabel = & OutSum = 10.45 & Language = en
We try to omit the parameter altogether:
Missing parameter: IncCurrLabel.
Trouble. But we do not give up. What can be done in such a situation? Right! Suppose we will take the identifier of the payment method from the collection, calculate the payment amount for it separately and stuff it into the form on our website, then change outSum and recount the signature when the user selects another method.
It's good that I did not rush to implement this.
A little rough design showed that in reality everything will not be so rosy. What am I talking about? Let's take a closer look at the payment initialization interface .
sIncCurrLabel
- proposed payment currency. The user can change it during the payment process.
Nothing guarded yet? Let's think about it. Robokassa offers us to consider the amount ourselves, based on the payment interface selected by the user. This same IncCurrLabel interface is not included in the signature. This is logical, because the user has the right to choose another method on the box office website. Nevertheless, the commission for each method is calculated on its own. Moreover, it is proposed to us to calculate it, on the side of our server. We get outSum from the same interface, push it into our form, consider the signature and send it for payment.
The essence of the whole article
Again.
Robokassa offers us to deduct the amount of commission from our income, based on what payment method the user wants. At the same time, it allows you to change this very method of payment when we no longer have control over the payment process . What happens next?
And then everything is simple. The user selects the method with the largest commission on our website. In my memory - a bank card. We, like good uncles, deduct about 300 rubles from the price of our goods in order to remove the burden of commission from the buyer. He, having got to the Robokassa website, simply selects payment through some Yandex or WebMoney with a meager commission. The commission for the new method is calculated on the robocash desk website based on the "discount" price option sent by us. All.


And yet, the catch is that from the moment a payment is sent to the site, if the user pays for the order, we will receive “success” in payment. And nobody cares that we lost money on this, in fact. Such a simple scheme.
What can still be done?
Exit number times
Brutal
We can store the amount of our goods and the payment method specified by the user in the same shp * parameters. These parameters are protected from change, which means we will get them safe and sound. Having received them back, we recount the amount again and see how much we received and how much we should have. If you get less, it means that we were deceived and we can somehow influence the user.
The only problem here is that a typical buyer may, by pure chance, even if we write that you can’t change the method at the cash desk itself, do it your own way. We will not be able to return the full amount to him if he confirms such a transaction. So it’s hard to call it a way out.
Exit number two
Only
Register at the checkout as a legal entity. Actually, in my case, the customer decided to do just that. In this case, you get one single switch that solves this problem once and for all.
Exit number three
Nonexistent
The cash desk could make it possible to prohibit the user from changing the payment method after the payment is initialized. For example, enter the canChangeCurrLabel flag, and shove it into the transaction signature. Then the costing interface would make sense, and we would not lose money. What prevented is unknown.