Few points to discuss regarding the API


#1

Hi All,
Here are some points that I came across while doing the integration and I think might need to be considered.

1. Signature verification failed
When polling the system to check for payments, I kept getting “Signature verification failed” for some time although I was pretty sure that the signature was correct! After some debugging time, I started to think of what could be an unexpected cause. It turned out to be the last thing I expected.
As you know, the signature is represented as a string with a large hexadecimal number; 64 digits. My code was using some standard .Net functions that returned the signature using upper case digits (ABCDF) while the API is expecting a hex string with lower case digits (abcdef).

So, the valid signature:
0CA7DA24229F1A974FE9AD44BEEEA9C5EA1B876538876B3D39578E607B948A1A
was rejected while this one:
0ca7da24229f1a974fe9ad44beeea9c5ea1b876538876b3d39578e607b948a1a
was accepted, although it is the same hex number.

Since hex numbers are the same regardless of the case of the digits, I think we should either make the comparison case-insensitive or state it clearly in the API usage guide that the API expects lower case hex digits. This will save developers a lot of time.

2. Double Payment (not double spending)
When you have a successful payment with some payment id, you can scan the same QR code again from the App and send the same payment again with the same payment id. It gets accepted and processed.
Although this is not the fault of the API, I think it might cause a lot of trouble and support issues in life retail environment. More often than not, for some reason a customer will think the payment did not succeed, will scan the code again and the amount will be deducted twice, or even more! Or the customer will scan the wrong code, or due to a bug, the POS software will display an old code of a previous transaction. The possibilities are endless.
It would be great if the API will validate the payment request coming from the App to make sure that this payment has not been paid before. This will eliminate a lot of issues. Of course the payment id should be unique only on the vendor level or whatever.

3.Payment Id Uniqueness
This one is not an issue but might be considered as “nice to have”.
In more complicated retail environments with many physical stores with each store containing maybe tens of points of sale, it will be very difficult for people to generate a globally unique (and meaningful) payment id.
They might generate it from random numbers, or invent a local structure for the payment id string like the first two characters denoting the store, then 2 or 3 chars denoting the POS then a serial for the transaction? Or they will need to be connected to a central server where these payment ids are centrally managed (And this will be unacceptable in most cases, plus POS machines need to work even if the LAN is not available).
In all cases, it will be the responsibility of the retailers to generate unique payment ids, and I assure you, conflicts will occur much more than you might expect.
One idea to make their lives easier, is to add an additional field to the payment string and the payment checking request. It might be called PosId or whatever. And the payment id should be unique only for every POS which is way easier for them to achieve.
Since in retail environments, each POS normally have a unique id, this will make the developer’s lives much easier and will eliminate a lot of problems. A retailer will only need to number their points of sale from 1 to even 10000, and forget about duplicate payment ids forever.
What do you think?!

4.Dual screen availability
This one is not actually related to the API but, I thought I can mention it here, maybe someone comes up with a good idea.
Most of the retailers will not have dual monitors attached to the POS. They will have a hard time generating a dynamic QR code and showing it to the customer. Any ideas?! Use their mobile phones somehow?

Sorry for this lengthy post and thank you for reading.
Regards
Mohamed Afifi


Need help in WEBHOOK Javascript/Nodejs integration
#2

@Egg
I appreciate your kind input sir!


#3

Thank you for testing so thoughtfully!


#4

I completely agree on #1 !!!
Thankfully all languages have a “to lowercase” string conversion function :grinning:

#2 is an issue, but can be mostly avoided by the sellers code closing the webpage / screen featuring the qr code on acceptance. Or just setting the field to hidden.

#3 I agree. I’d also like the ability to search my app payments based on tx id, and order by date / tx_id
Currently I generate them based off an mssql primary key in a “temp sales data” table. As soon as a new sale is opened, a new row and new tx-id is created and locked to that device. Its just the last I’d + 1

#4 yup. Mobile phones / tablets.
My pos idea might be buggy, and in its infancy.
But youve just nailed it’s reason for existence right there. A small, portable screen for making contact phone-to-phone immediate sales.
Desktop pos systems are old news :wink:
Alternatively, a small monitor on a swivel, or a specialised micro screen and complicated POS code to output the qr code to this :rofl:

Good thoughts.


#5

Yes, retailer developers can deal with all the issues from their side. But I do not want to assume this because more often than not, they won’t!
It would be much better if the API is designed defensively and try to anticipate and prevent potential issues.


#6

Awesome work on the testing @MohamedAfifi keep up the good work :open_mouth:


#7

That’s a great opening post - very detailed and someone official at Electroneum should be thanking you for your detailed but equally concise input and test findings.


#8

Very valid points! Thanks for pointing this out…

#Issue 1
Very good suggestion. Although it would be easy to just change case on your end, I agree that the API should be designed defensively, as you said, to anticipate these problems and solve them before they appear.

I had a similar problem with getting repeated “Signature verification failed” errors while polling for payment. The error turned out to be the order that the payload contents were being put together before being converted to a JSON string. Electroneum’s example code on Github was coded to include the vendor address in front of the payment ID in the payload array (@Egg, you should put this on your to-do list to fix).
The correct method was to include the payment ID before the vendor address, which would produce the correct signature when hashed.

Issue #2
It is important to guard against double payments. It can get particularly messy if some systems show an immediate payment confirmation while others are not that sophisticated and require a page reload to show confirmation. People could get used to the immediate confirmation on some sites and therefore try to pay again if they don’t get similar behavior on other sites. This is partially why I leave the “I’ve Made the Payment” button on the Woocommerce plugin, although it checks for payment using AJAX, just in case some vendor forgets to insert the correct webhook URL on his vendor page.

A simple solution could be to alert the user with a notification in the Electroneum app/web wallet before processing the second payment. Something like “You’ve already made a payment of [xx.xx] ETN to [vendor_name] within the last [timeframe]. Are you sure you want to continue?” And probably include the vendor’s contact details should the customer want to pursue the matter. Many online banking software have similar features. Oftentimes you DO want to send another identical payment, but other times you would like to be alerted in case you forget, or in case technology fails between you and the vendor.

Issue #3
I guess you could create a vendor outlet for each of your POS, which would greatly reduce the odds of payment ID conflicts. This would, however, become very cumbersome at large-scale installations.


#9

Hi, good post to begin with.

(I might edit for grammar errors)

Issue 2 - Double spending by double scan.

That should be “no brainer” imo. Anything that can avoid a possible mistake.

Issue 3 - Unique Identifier

I have also been missing this. This a good for tractability, especially if you have more POS terminals than one. And of you have 100 locations with 10 pos at each place. Well then you get a bit of an head ache with the current solution (just stating a fact).

Btw…
In the environments I’ve installed, it’s not granted that the POS terminal (client) has direct access to the Internet. It does communicate in this way to make sure transactions work any way.

client API (terminal) -> server daemon (local) -> internet -> payment service provider

Currently, you would be need to write a software that handle this that would proxy the transactions and the daemon

The simplest solution is that you have a deamon, which you request a fully random (or incremental) payment_id based on (location, pos_id) and that daemon keeps tracks of it all.

A more advanced solution is that the daemon also proxies the transactions to ETN IP system, still keeping track of everything.

Then there is more of course…

(Perhaps there is such a solution on its way?)

Issue 4 - Dual Screen

Correct that not many POS devices has dual screen as standard and that is an add-on that sometimes is not always easy to implement due to

  • cost
    -maybe not in all cases but in some, you will need to change the whole terminal = showstopper for fast adoptaion
  • hardware availability
    -sometimes hard to find the correct part or its not available
  • support by software
    -the software house would require to update their software to support dual screen, not att all impossible. but could be showstopper.
  • limited space
    -it could be so that its not viable to have a secondary screen installed that’s integratged to the POS system.
  1. First solution, Android Tab

Solution could be that you have an Android Tab device, and it is being sent information via some protocol (or polls via HTTP, whatever) of what to display on it.

It could be cheaper and much faster development and it would be solution works better.

The app would have one sole purpose, display information that the POS terminal want’s it to show. I think this could be faster to implement and it would be a cost that is reasonable and works for everyone. This could be an app that Electroneum supplies, or you make your own.

  1. Second solution - Reverse auth / QR barcode scanner.

Well lets make the payment in reverse! Let’s say you have 2D scanner. A reverse authorization QR code (generated as a token by ETN IP system) could be displayed on the CUSTOMERS mobile phone screen, which the operator then scan and supply to ETN IP system and then the transactions goes through.

  1. User enters amount of ETN to pay.
  2. Request sent to ETN IP system
  3. Token return (ie. “8FMJ83NF8NHF8JC8NAKVM94”)
  4. Money reserved at ETN for 60 seconds.
  5. Token displayed as QR code on phone
  6. Merchant scans it (or types it in)
  7. Verification and complete transaction with ETN IP system.
  8. Done.

Defintly an idea. at least :smiley: But it’s perhaps a bit silly. But good for this who needs it. :smiley:

Actually… The token could be locked for X days, so if the merchant has lost internet access, then it could supply it to ETN IP system when internet access has been restored.

I do not consider this to be a plausible or practical idea in a larger environment as you say.

I have actually spent some time thinking this through and I have come up with a version of an API (pseudo function) that could be a possible solution for more “advanced” merchants, giving them a solution for their needs. I’m thinking about publishing it in the thread or create a new one. It could possibly solve all (at least many) issues but it would require a “version 2” or an “advanced api” version. At least, it could give some ideas and insight.

It would cover locations, pos id, cashiers, reports, traceability, currency, alerts, logs, refunds, double spending and security as a conceptual idea. Perhaps a solution is on it’s way already…

But, if you’re interested.


#10

I totally agree with @PHXInvestors, Awesome work on the testing @MohamedAfifi keep up the good work


#11

Hi @MohamedAfifi,

Thanks for the discussion, and others for their input.

  1. Signature verification failed
    FIXED - this is now live
    You’re quite right, different programming languages use different cases on hexadecimals (there is no standard to state if this should be lower or upper case). This has been updated on the payment poll URL to be case insensitive - no updates required by users or vendors, they can send either case and we’ll convert it before processing.

  2. Double Payment (not double spending)
    CONFIRMED - to be included in the next update
    A QR code should be removed/hidden from the customer by the vendor once payment confirmation is received (just like a traditional vendor should not ask for payment twice). To help protect users and vendors, the user payment will fail if a payment id has been recently used for the given vendor. I will emphasise this is not a double spend issue, but protection from the same QR code being scanned more than once.

  3. Payment Id Uniqueness
    The payment id needs to be generated by, and to be (recently) unique to, the vendor. As the vendor generates this, they know if this is unique to them or not. The 10 character payment id offers 1.1 trillion payment id combinations per vendor; we can increase this further as required through the BETA programme - although our intention is to keep strings (and so the QR code) as short as possible while ensuring high entropy.

  4. Dual screen availability
    The BETA programme requires the vendor to have the facility to share a QR code for a customer to scan or for the customer to click if via a website.

Feedback during the BETA programme will reveal how we need to adjust our vision of the vendor API so I encourage you all to keep the responses coming :slight_smile:

I hope this helps.

Egg


#12

Hi Egg,

How about this as an idea.

To instigate at transaction the POS system sends to following to the ETN Payment Gateway

Sent as JSON

* country_id
* site_id
* pos_id
* cashier_id
* amount_local_curreny
* currency
* (more)

This information would be good to have if you plan to have a report functions for the vendors.

Returned as JSON

* transaction_id 
* token_id
* etn_to_be_debited
* payment_id
* (more)

The transaction_id would be a uuid and would be good for tractability and could be stored in the POS system.

The payment_id is the same as you use today for the blockchain. But the ETN IPS generates it randomly or incremently. Good for traceability. Could also be used as reference by a customer if the have questions about a transaction and it would at least be easier to find the main transaction_id if support is offered over the phone.

The token_id would be a random code containing alphanumerical letters i.e “etnpay::ab38GOYaB7” that would be valid for X seconds. After that it would not be valid, meaning the code could be reused in the future. Using 10 upper/lower case letters and 0-9 would give 62^10 combinations per X second period. Very high entropy.

The amount to be debited could be calculated by your system.

The token_id is what’s displayed on the the display and it is whats scanned by the ETN App on the phone. The app connects to ETN Payment Gateway and submits the token and check if it’s legit and retrieves

* vendor_name
* etn_to_be_debited
* amount_local_currency
* amount_home_currency
* (more)

This is displayed on screen and the payment process continues as normal.

Benefits would be…

  • Short QR code, good for small screens and if phone has bad optics.
  • Gives no room for errors in calculations, ETN IPS sets the exchange rate.
  • Reports could be built online for vendors.
  • Each POS could take out a report for how much was charged on that station.
  • (More)

Best regards,
Will


#13

Awesome !

I’m loving the whole ‘detect if tx id has already been used’ approach

And the non case specific hexadecimal issue did catch me out initially, but I didn’t know why it was failing. I just fluked it by mucking around with the strings :rofl: