QR Ph API

How do I integrate QR Ph into my online checkout? How do I generate QR Ph codes for in-store use?

🚧

Account activation and configuration is required before development

We need to configure your account before your developers can start testing and integration. Kindly message [email protected] to request for key configuration.

Overview

QR Ph is the Philippine's QR code standard supervised by the BSP and aims to provide a quick and secure way to accept payments from multiple banks and e-wallets, all using one QR Ph code.


Supported Banks, E-Wallets, Issuers

BankE-Wallets & Other Issuers
Asia United Bank Corporation (AUB)GCash (G-Xchange, Inc.)
Bank of the Philippine Islands (BPI)Maya Philippines, Inc.
BDO Unibank IncShopeePay Philippines, Inc.
Metropolitan Bank and Trust Company (MetroBank)GrabPay (Gpay Network PH, Inc.)
Philippine National Bank (PNB)PPS-PEPP Financial Services Corporation
Rizal Commercial Banking Corporation (RCBC)Starpay Corporation
Robinsons Bank CorporationTayoCash, Inc.
Security Bank CorporationTraxion Pay, Inc.
Union Bank of the Philippines (UBP)USSC Money Services, Inc.
China Banking CorporationZybi Tech, Inc.
Land Bank of the PhilippinesCIS Bayad Center, Inc.
AllBank (A Thrift Bank), Inc.DCPAY Philippines, Inc.
Queen City Development Bank, Inc. or QueenBank, A Thrift Bank
Sterling Bank of Asia, Inc. (A Savings Bank)
Philippine Savings Bank
Cebuana Lhuillier Rural Bank, Inc.
Rural Bank of Guinobatan, Inc.
SeaBank Philippines Inc. (A Rural Bank)
GoTyme Bank Corporation

Integrating QR Ph through the Payment Intent Workflow

The payment intent workflow is the main workflow used to make payments via PayMongo. Before getting started with integrating QR Ph, make sure that you are familiar with the payment intent workflow. To enable QR Ph, a few additional steps just needs to be added to the existing workflow.

Enabling QR Ph as a payment method for online use-case

1. Create a Payment Intent and include qrph under the payment_method_allowed array.

{
     "data": {
          "attributes": {
               "amount": 10000,
               "payment_method_allowed": [
                    "card",
                    "dob",
                    "paymaya",
                    "qrph" # add this

               ],
               # ...
          }
     }

  • In this step, set qrph as type in the request body. When using qrph, you only need to provide the address (optional), name, email, and phone (optional) under billing .

3. Attach the payment method to the created payment intent as normal. Once the Payment Method is attached, the Payment Intent status transitions from awaiting_payment_method to awaiting_next_action 

4. Display the dynamic QRPH code on your front-end or checkout. The QRPH image_url is a base-64 image string and is available on the /attach response under next_action.

{  
    "data": {  
        "id": "pi_uv6817kG7JbbvqJnSwE2uXsc",  
        "type": "payment_intent",  
        "attributes": {  
            "amount": 100000,  
            # ...  
            "payment_method_allowed": [  
                "qrph"  
            ],  
            "payments": \[],  
            "next_action": {  
                "code": {  
                    "id": "code_UKixJpQNzEfMm9T7NahbcXNe",  
                    "amount": 100000,  
                    "image_url": "data:image/png;base64,iVBORw0KG...CYII=",  
                    "label": "Test Paymongo"  
                },  
                "type": "consume_qr"  
            },  
            # ...  
        }  
    }  
}

5. Once the customer has successfully paid, the payment intent status will transition to succeeded.

  • To determine if the QR Ph payment has already been paid, a webhook call will be made to the nominated and registered webhook endpoint subscribed to the payment.paid event. You may refer to our Webhook API to learn more. You may also check the status of the payment intent through the Retrieve a Payment Intent API
{
    "data": {
        "id": "pay_Haq1UQKf4p7b4cDRcxRrnF8j",
        "type": "payment",
        "attributes": {
            "access_url": null,
            "amount": 2000,
            "balance_transaction_id": "bal_txn_wWWuZhjS4N45b5YYLS38cXTR",
            "billing": {
                "address": {
                    "city": "",
                    "country": "",
                    "line1": "",
                    "line2": "",
                    "postal_code": "",
                    "state": ""
                },
                "email": "[email protected]",
                "name": "test1",
                "phone": ""
            },
            "currency": "PHP",
            "description": "test 1",
            "disputed": false,
            "external_reference_number": "SBuAjs2",
            "fee": 400,
            "instant_settlement": null,
            "livemode": true,
            "net_amount": 1600,
            "origin": "links",
            "payment_intent_id": "pi_EXpLFBparajBVHFiU78NKdY3",
            "payout": null,
            "source": {
                "id": "qrph_Xp5eLQKwhJZd4njwa4EFXfa1",
                "type": "qrph",
                "provider": {
                    "id": "333444",
                    "code_id": "code_6K7HdrvrCrH937BSpJ6K4T5i"
                }
            },
            "statement_descriptor": "Test",
            "status": "paid",
            "tax_amount": 0,
            "metadata": {
                "pm_reference_number": "SBuAjs2"
            },
            "refunds": [],
            "taxes": [
                {
                    "amount": 43,
                    "currency": "PHP",
                    "inclusive": true,
                    "name": "VAT",
                    "type": "vat",
                    "value": "1200_bps"
                }
            ],
            "available_at": 1721984400,
            "created_at": 1721812323,
            "credited_at": 1722416400,
            "paid_at": 1721812322,
            "updated_at": 1721812323
        }
    }
}
{
    "data": {
        "id": "pi_EXpLFBparajBVHFiU78NKdY3",
        "type": "payment_intent",
        "attributes": {
            "amount": 2000,
            "capture_type": "automatic",
            "client_key": "pi_EXpLFBparajBVHFiU78NKdY3_client_412VZQwShMeZDZLFwZmXmiyE",
            "currency": "PHP",
            "description": "test 1",
            "livemode": true,
            "statement_descriptor": "test",
            "status": "succeeded",
            "last_payment_error": null,
            "payment_method_allowed": [
                "paymaya",
                "brankas",
                "qrph",
                "dob",
                "gcash",
                "grab_pay"
            ],
            "payments": [
                {
                    "id": "pay_Haq1UQKf4p7b4cDRcxRrnF8j",
                    "type": "payment",
                    "attributes": {
                        "access_url": null,
                        "amount": 2000,
                        "balance_transaction_id": "bal_txn_wWWuZhjS4N45b5YYLS38cXTR",
                        "billing": {
                            "address": {
                                "city": "",
                                "country": "",
                                "line1": "",
                                "line2": "",
                                "postal_code": "",
                                "state": ""
                            },
                            "email": "[email protected]",
                            "name": "test1",
                            "phone": ""
                        },
                        "currency": "PHP",
                        "description": "test 1",
                        "disputed": false,
                        "external_reference_number": "SBuAjs2",
                        "fee": 400,
                        "instant_settlement": null,
                        "livemode": true,
                        "net_amount": 1600,
                        "origin": "links",
                        "payment_intent_id": "pi_EXpLFBparajBVHFiU78NKdY3",
                        "payout": null,
                        "source": {
                            "id": "qrph_Xp5eLQKwhJZd4njwa4EFXfa1",
                            "type": "qrph",
                            "provider": {
                                "id": "333444",
                                "code_id": "code_6K7HdrvrCrH937BSpJ6K4T5i"
                            }
                        },
                        "statement_descriptor": "test",
                        "status": "paid",
                        "tax_amount": 0,
                        "metadata": {
                            "pm_reference_number": "SBuAjs2"
                        },
                        "refunds": [],
                        "taxes": [
                            {
                                "amount": 43,
                                "currency": "PHP",
                                "inclusive": true,
                                "name": "VAT",
                                "type": "vat",
                                "value": "1200_bps"
                            }
                        ],
                        "available_at": 1721984400,
                        "created_at": 1721812323,
                        "credited_at": 1722416400,
                        "paid_at": 1721812322,
                        "updated_at": 1721812323
                    }
                }
            ],
            "next_action": null,
            "payment_method_options": null,
            "metadata": {
                "pm_reference_number": "SBuAjs2"
            },
            "setup_future_usage": null,
            "created_at": 1721812019,
            "updated_at": 1721812323
        }
    }
}

  • If the QR Ph payment failed or the QR Ph code is expired (not paid within 30 mins from the time the QR Ph image URL was generated), the payment intent will revert back to awaiting_payment_method. You may create a new payment method resource and attach it to the payment intent to generate a new QR Ph code.

    • For failed QR Ph payments, a webhook call will be made to the nominated and registered webhook endpoint subscribed to the payment.failed event. You may also check the status of the payment intent through the Retrieve a Payment Intent API
    • For expired QR Ph codes, a webhook call will be made to the nominated and registered webhook endpoint subscribed to the qrph.expired event.
{
    "data": {
        "id": "pay_kVjqqErX7nJatqtdJnTGdXs5",
        "type": "payment",
        "attributes": {
            "access_url": null,
            "amount": 2000,
            "balance_transaction_id": null,
            "billing": {
                "address": {
                    "city": "",
                    "country": "",
                    "line1": "",
                    "line2": "",
                    "postal_code": "",
                    "state": ""
                },
                "email": "[email protected]",
                "name": "test",
                "phone": ""
            },
            "currency": "PHP",
            "description": "test 2",
            "disputed": false,
            "external_reference_number": "FVFYMiG",
            "failed_code": "RJCT",
            "failed_message": "Unknown processing error.",
            "fee": 0,
            "instant_settlement": null,
            "livemode": true,
            "net_amount": 0,
            "origin": "links",
            "payment_intent_id": "pi_cufYwN1b9mzrvKpXXQLknRiB",
            "payout": null,
            "source": {
                "id": "qrph_SprjmBZcaJKKHryvJvs3FoEL",
                "type": "qrph",
                "provider": {
                    "id": "444555",
                    "code_id": "code_xBF4wAhRSp3uagh3c8K3zB7i"
                }
            },
            "statement_descriptor": "Test",
            "status": "failed",
            "tax_amount": 0,
            "metadata": null,
            "refunds": [],
            "taxes": [],
            "created_at": 1721814835,
            "credited_at": null,
            "paid_at": 1721814834,
            "updated_at": 1721814835
        }
    }
}
{
    "data": {
        "id": "pi_cufYwN1b9mzrvKpXXQLknRiB",
        "type": "payment_intent",
        "attributes": {
            "amount": 2000,
            "capture_type": "automatic",
            "client_key": "pi_cufYwN1b9mzrvKpXXQLknRiB_client_NyzkVvzEKsb9QtaBj3fexFsq",
            "currency": "PHP",
            "description": "test 2",
            "livemode": true,
            "statement_descriptor": "Test",
            "status": "awaiting_payment_method",
            "last_payment_error": null,
            "payment_method_allowed": [
                "gcash",
                "paymaya",
                "grab_pay",
                "brankas",
                "qrph",
                "dob"
            ],
            "payments": [
                {
                    "id": "pay_kVjqqErX7nJatqtdJnTGdXs5",
                    "type": "payment",
                    "attributes": {
                        "access_url": null,
                        "amount": 2000,
                        "balance_transaction_id": null,
                        "billing": {
                            "address": {
                                "city": "",
                                "country": "",
                                "line1": "",
                                "line2": "",
                                "postal_code": "",
                                "state": ""
                            },
                            "email": "[email protected]",
                            "name": "test",
                            "phone": ""
                        },
                        "currency": "PHP",
                        "description": "test 2",
                        "disputed": false,
                        "external_reference_number": "FVFYMiG",
                        "failed_code": "RJCT",
                        "failed_message": "Unknown processing error.",
                        "fee": 0,
                        "instant_settlement": null,
                        "livemode": true,
                        "net_amount": 0,
                        "origin": "links",
                        "payment_intent_id": "pi_cufYwN1b9mzrvKpXXQLknRiB",
                        "payout": null,
                        "source": {
                            "id": "qrph_SprjmBZcaJKKHryvJvs3FoEL",
                            "type": "qrph",
                            "provider": {
                                "id": "444555",
                                "code_id": "code_xBF4wAhRSp3uagh3c8K3zB7i"
                            }
                        },
                        "statement_descriptor": "Test",
                        "status": "failed",
                        "tax_amount": 0,
                        "metadata": null,
                        "refunds": [],
                        "taxes": [],
                        "created_at": 1721814835,
                        "credited_at": null,
                        "paid_at": 1721814834,
                        "updated_at": 1721814835
                    }
                }
            ],
            "next_action": null,
            "payment_method_options": null,
            "metadata": {
                "pm_reference_number": "FVFYMiG"
            },
            "setup_future_usage": null,
            "created_at": 1721814680,
            "updated_at": 1721814835
        }
    }
}
{
  "id": "qrph_aL7hsQR8pELLo7rCZDfySZVu",
  "type": "qrph",
  "attributes": {
    "code_id": "code_upsGYVymftz6mNyCrRWBL4BK",
    "livemode": true,
    "organization_id": "org_hQBQmY5mDBPCpFmGSBfKJV2w",
    "created_at": "2024-01-10T18:23:34.463+08:00",
    "source_id": "src_oaH17sD38656G3WtA9SrFa2T",
    "source_status": "expired"
  }
}

🚧

QR Ph codes generated using the Payment Intent flow and not paid within 30 minutes will expire and should not be used anymore. Once the QR Ph code is expired, the customer won't be able to pay anymore. These QR Ph codes are also designed to be one-time use only.



Generating Reusable QR Ph Codes

📘

Currently only supports the generation of Static QR Ph Codes. For Static QR Ph codes, customers input the payment amount after scanning the QR Ph code. These reusable QR Ph Codes can be used primarily for in-store use and displayed at your store's point of purchase in the form of a standee or digital display.

QR Ph Code Resource

{
    "data": {
        "id": "code_rmDbeEY1oxyPRU9zuKHEEX5y", #unique ID assigned to each QR Ph code
        "type": "code",
        "attributes": {
            "mobile_number": "+639191234567",
            "qr_image": "data:image/png;base64,iVB...mCC",
            "name": "Paymongo Test"
        }
    }
}
AttributeDescription
qr_imageBase64-encoded, data/image URL of the QR image generated using the generated QR string.
mobile_numberRecipient of the SMS notification we send out for every payment made using the code
nameStore name that will appear when scanning the QRPH code. Applies to all providers

Creating a Static QR Ph Code

Generates QR Ph codes and creates a code record for it via API.

1. Call the API Endpoint using your Live API Keys, which can be found on your PayMongo dashboard once activated.

  • It's important to note that each QR Code will have a unique QR Code ID which can be used to reference each generated QR Code.

Payload

{
    "data": {
        "attributes": {
            "kind": "instore",
            "mobile_number": "+639191234567"
        }
    }
ParameterDescriptionValidationValue
mobile_numberMobile number that will receive the SMS confirmation on a successful payment

Note: If no mobile_number is added, no SMS notification will be sent for successful QR Ph payments
Optional
mobile_number
+639191234567
kindKind of QR Ph code to generateRequired'instore'
notesAdditional notes to be used to identify the generated code (for your internal use, does not get displayed to the customer)Optional
String
'Main Branch'
'Cashier 1'

2. Convert the Base-64-encoded string from the API response into an image.

  • The QR Ph image will be in the API response under data.attributes.qr_image as a Base64-encoded string. You can use any Base-64 to Image Converter to convert the QR Image string into an actual image.
{
    "data": {
        "id": "code_Yk3HN6HvWddSrNwhM3dKkYeA",
        "type": "code",
        "attributes": {
            "mobile_number": "+639191234567",
            "qr_image": "data:image/png;base64,iVBO...ggg==", #This is the base-64-enconded string
            "name": "Paymongo Test"
        }
    }
}

3. Start accepting payments with your static QR Ph code!

  • Once you have converted the string into an image, you can now print out or display this QR Ph code in your store.

4. Finish

  • To determine if the QR Ph payment has already been paid, a webhook call will be made to the nominated and registered webhook endpoint subscribed to the payment.paid event.