More precisely, how to deceive compassionate individuals who take a commission for the purchase of themselves. Perhaps the title is too loud, perhaps this is not an article at all (especially considering that I have never written articles before), but some essay on a sick brain, which is time to finally get enough sleep, not to finish this online store. And yet, during the integration of Robokassa into the online store, an interesting feature was noted that allows you to save on the purchase at the expense of those who are trying to commit commitments to the commission in favor of Robokassa on your account, and I would like to tell you about it.
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 clients: individuals and legal entities. An ordinary user, buying something in our online store, expects to be billed for the amount indicated on the price tag. The fact is obvious that to demand from the user to cover also the commission is a direct road to nowhere. This is where the question arises, how to shift the responsibility of paying the robot box to its share on the online store itself.
')
It would seem, what could be easier? Surely, this setting is in your account on the site of payment. It was not there. Rather, it is. But only if you are a legal entity.
In my situation, the person to whom this store is created is a physical person. The administration of the robocash desk 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 the details of how transactions work in Robokassa, the article is a little about that. If you are interested in technical documentation, it is chewed on the official
site in detail
.Let me just say that in the process of payments, everything is based on several things:
- MerchantLogin - your login in the system
- InvId - billing ID
- OutSum - the amount we want to receive.
- MerchantPass1 - technical password No. 1 for transactions (there are a total of two, the second is for receiving information on payment status)
- SignatureValue - md5 hash of the string "sMerchantLogin: nOutSum: nInvId: sMerchantPass1"
Actually, any tricky change of one of the values ​​included in the SignatureValue string will not allow the transaction to take place. By the way, you, as a developer, can add your own shp * type parameters, which will “survive” the payment and will be sent back to your server. These parameters are also added to the signature of the transaction.
Now back to the topic of the article.
Solution of the problem
The solution offered by the employees of Robokassa is alarming immediately. It looks like this:
For these purposes, a special XML interface has been created:
The method of calculating the amount received by the store - CalcOutSumm
Description of the method: Allows you to calculate the amount receivable, based on current rates ROBOKASSA, the amount that the user will pay.
Method parameters: MerchantLogin — store identifier (string), IncCurrLabel — currency label (string) for which the amount must be calculated. If you leave it empty, 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 would equal the price of the goods. The store was written on rails, and therefore all the additional parsing would take away a few lines. And yet, even with all our desire
Where is the dog buried?
Problems begin as soon as we want to use this “interface”. Suppose we want to calculate the amount for all payment methods. As the guide says:
IncCurrLabel - currency label (string) for which you need to calculate the amount. If you leave it empty, the calculation will be made for all available currencies.
Not. Not true. If you leave it empty, the server will return this response (using the
merchant.roboxchange.com/WebService/Service.asmx/CalcOutSumm?MerchantLogin=demo&IncCurrLabel=&IncSum=3500 link as an example.
<CalcSummsResponseData> <Result> <Code>6</Code> <Description> .</Description> </Result> <OutSum>0</OutSum> </CalcSummsResponseData>
My first thought: “Maybe I'm a fool and do something wrong. Maybe you need to omit the parameter wrong? ". But no, based on the same
documentation (an example for another function, just showing the absence of meaning):
Sample request using HTTP GET:
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 this situation? For sure! Suppose we take the payment method identifier from the collection, count the payment amount for it separately and stuff it into a form on our website, then change outSum and recalculate the signature when the user chooses another method.
Well, I did not rush to implement it.A bit of rough design showed that in reality everything would not be so rosy. What am I talking about? Let's take a closer look at
the payment initialization interface .
sIncCurrLabel
- the proposed currency of payment. The user can change it in the process of payment.
Nothing has alarmed yet? Let's think about it. Robokassa invites us to calculate the amount ourselves, based on the user-selected payment interface. This interface IncCurrLabel is not included in the signature. This is logical, because the user has the right to choose a different method on the checkout site However, the commission for each method is calculated. Moreover, it is offered to calculate it, on the side of our server. We receive outSum from that interface, we push in our form, we consider the signature and we send for payment.
The essence of the whole article
Again.
Robokassa offers us to deduct the amount of the commission from our income, based on what method of payment the user wants. At the same time, it gives this method of payment to change when we no
longer have control over the payment process. What happens next?
And then everything is simple. The user chooses on our site the method with the largest commission. In my memory - a bank card. We, as good uncles, deduct about 300 rubles from the price of our goods in order to remove the burden of the commission from the buyer. He, having got on the site of Robokassa, simply chooses payment through some Yandex or WebMoney with a meager commission. The commission in a new way will be calculated on the site of the robocash desk based on the “discount” price sent by us.
Everything.

And yet, the snag is that from the moment the bills arrive at the site, if the user pays for the order, the “success” of payment will return to us. And nobody cares that we lost money on this, in fact. Such is the simple scheme.
What can you do?
Exit number once
Brutal
We can store the amount of our product and method of payment specified by the user in the very shp * parameters. These parameters are protected from change, which means we will get them intact and safe. Having received them back, we recalculate the amount again and see how much we received and how much we should have. If we received less, then we were deceived and we can somehow influence the user.
The problem here is only that a typical buyer can, by pure chance, even if we write that it is impossible to change the way in the checkout itself, to act on our own. We will not be able to return the money in full to him if he confirms such a transaction. So it's difficult 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 become available a single switch that solves this problem once and for all.
Exit number three
Nonexistent
Robokassa could make it possible to prohibit the user to change the method of payment after the initialization of payment. For example, enter the canChangeCurrLabel flag and push it into the transaction signature. Then the costing interface would make sense, and we would not lose money. What prevented - is unknown.