InstaPay or P2P QRPh? What is it?

In my previous post, I voiced my opinion that many merchants use their personal GCash account to accept payments. At that time, I was thinking of the proprietary GCash QR code that would only work for customers who use their GCash wallets. More recently, I noticed personal QR codes that seem to work with all e-wallets and mobile banking applications. I tested this specifically with the BPI banking application and the GCash wallet.

Have I found the P2P QRPh?

In this post, I am analyzing the data and the formatting that is used for the P2P QR code. If you are curious, you can also run your own QR codes through my QR Decoder.

EMV, QRPh, INstapay, GCash, Proprietary - What is it?

I first thought that this must be the QRPh P2P part I was missing when I wrote about QRPH. But the QR codes carry the InstaPay logo instead of the QRPh one. This could simply be a design decision to separate P2M from P2P payments though. In any case, it indicates that the account-to-account transfer mechanism that powers the instantaneous money transfer is based on the InstaPay system.

Firstly, I need to point out that there is no EMV standard for presenting personal account numbers to another person. It is true that EMVCo created a standard for customer-presented QR codes, but this standard insists on using track 2 magstripe data or a 16-digit account number. The standard is also meant for merchant payments. The EMV standard for merchant-presented QR codes is a bit more flexible, but has all the flaws pointed out in this post.

Presented with two bad choices, whoever designed the InstaPay QR code chose the "merchant-presented" standard and made it worse.

The P2P QR Code Presented by a Merchant

At a coffeeshop near where I live, the owner decided to limit the payment choices to cash and GCash. It is funny how "GCash" has become the generic name for QR payments. The name "QRPh" is rarely used by anybody.

I took a picture of the QR code and ran it through my decode, and this is what I found:

T:0x00/APPSP/S,0   L:0x02,2   Payload Format Indicator   => Version 1
T:0x01/APPSP/S,1   L:0x02,2   Point of Initiation Method => Static
T:0x1B/APPSP/C,27  L:0x53,83  Proprietary Merchant Account Information
    T:0x00/APPSP/S,0   L:0x0C,12  Globally Unique Identifier => com.p2pqrpay (1)
    T:0x01/APPSP/S,1   L:0x0B,11  Account SWIFT code         => GXCHPHM2XXX
    T:0x02/APPSP/S,2   L:0x08,8   InstaPay proprietary       => 99964403 (2)
    T:0x03/APPSP/S,3   L:0x0F,15  Account Number (maybe)     => 000000000000000 (3)
    T:0x04/APPSP/S,4   L:0x11,17  User ID                    => XXXXXXXXXXXXXXXXX (3)
T:0x34/APPSP/S,52  L:0x04,4   Merchant Category Code     => Error: 2 (4)
T:0x35/APPSP/S,53  L:0x03,3   Transaction Currency       => PHP
T:0x3A/APPSP/S,58  L:0x02,2   Country Code               => Philippines (the)
T:0x3B/APPSP/S,59  L:0x09,9   Merchant Name              => ****** *. (5)
T:0x3C/APPSP/S,60  L:0x0A,10  Merchant City              => Camachiles
T:0x3D/APPSP/S,61  L:0x04,4   Postal Code                => 1234 (6)
T:0x3F/APPSP/S,63  L:0x04,4   CRC                        => Actual: b346 / Computed: b346
1 In one of my previous posts, I predicted that the financial industry will not use future-proof unique identifiers. And I was right. The unique identifier "com.p2pqrpay" is not guaranteed to be unique, especially since the domain is not even registered. If QR payments are supposed to work cross-border in the future, there is a good chance that another scheme had the same brilliant ide to use the same identifier.
2 This number seems to be the same, regardless of which participating service provider generates the QR code.
3 It looks like the User ID is the number that is unique to the receiving account. Some QR c odes use tag 4 only.
4 There is no merchant category code for person receiving money. All QR codes I looked at use "6016", which does not exist. Why anybody felt the need to include a merchant category code in a P2P QR codes is unclear. I assume it is because the MCC is mandated by the EMV standard.
5 The merchant name is the name of the person receiving the money. It is obfuscated with just enough characters left to reliably compare the name on the mobile phone screen with the name on the QR counter tent card.
6 The postal code is optional. Since they did not bother putting in a real postal code anyway, why include it here?

P2P QR Code Created by a Mobile Banking App

T:0x00/APPSP/S,0   L:0x02,2   Payload Format Indicator   => Version 1
T:0x01/APPSP/S,1   L:0x02,2   Point of Initiation Method => Dynamic
T:0x1B/APPSP/C,27  L:0x3D,61  Proprietary Merchant Account Information
    T:0x00/APPSP/S,0   L:0x0C,12  Globally Unique Identifier => com.p2pqrpay
    T:0x01/APPSP/S,1   L:0x0B,11  Account SWIFT code         => BOPIPHMMXXX
    T:0x02/APPSP/S,2   L:0x08,8   InstaPay proprietary       => 99964403
    T:0x04/APPSP/S,4   L:0x0E,14  User ID                    => 00000000000000
T:0x34/APPSP/S,52  L:0x04,4   Merchant Category Code     => Error: 2
T:0x35/APPSP/S,53  L:0x03,3   Transaction Currency       => PHP
T:0x36/APPSP/S,54  L:0x05,5   Transaction Amount         => PHP 12.34
T:0x3A/APPSP/S,58  L:0x02,2   Country Code               => Philippines (the)
T:0x3B/APPSP/S,59  L:0x04,4   Merchant Name              => Ingo (1)
T:0x3C/APPSP/S,60  L:0x0B,11  Merchant City              => Makati City
T:0x3F/APPSP/S,63  L:0x04,4   CRC                        => Actual: e0ff / Computed: e0ff
1 Everything is very similar to the QR code generated by GCash. I noticed, however, that the customer can choose their own "Merchant Name". I’ll leave it to the reader to work out the risk of generating a QR code tent that contains my account number and an arbitrary name.

What I would have done

  1. Don’t try to force P2P payment into the EMV standard. It is not suitable for P2P payments.

  2. Use the general ideas from the EMV standard and forget about mandated data elements such as account numbers.

  3. Use BER encoding. Define tags according to the ASN.1 specification.

  4. Make it future-proof. Use global unique identifiers that are actually unique. I suggest OIDs that are under a properly registered subtree.

  5. Do not allow pull-payments. Account information conveyed by QR codes should only be good for receiving money, never to send it!

  6. Even better - in dynamic QR codes use one-time use reference numbers instead of account numbers. Allow the inclusion of creation date and validity periods.

  7. Do not offer the option to generate QR codes with an arbitrary name.

  8. Include cryptographic checksums rather than just a CRC. This would prevent the change of data within the QR code, for instance, it would be impossible to change the name without invalidating the cryptographic checksum.

  9. And …​ Forget about EMV.

References