DocumentationRecipesAPI ReferenceChangelog
Documentation

Click2Pay

This guide is providing guidance on who to implement click2Pay on merchant payment page.

  1. Customer landing on merchant checkout page
  2. Merchant to send payment token API
  3. Merchant receive payment token response
  4. Merchant send Payment Option Detail API
  5. Merchant receive Payment Option Detail response with the CaptureContext value that is required for front-end JS
  6. Populate click2pay event() & button
  7. Customer proceed Payment with click2Pay
  8. click2pay drop-in UI to display
  9. Customer key in identity & card detail on click2pay drop-in UI and submit payment
  10. Click2pay service will return token
  11. Merchant send do payment API with token
  12. Merchant receive do payment response
  13. Redirect Customer to perform 3ds authentication
  14. Merchant receive payment result upon payment completed

Pre requisite

On the merchant payment page, it is required

  • add Cybersource js lib
  • add <div> used to populate click2pay button
<html>
  <body><div id="payment-container"></div> <!--to show click to pay button-->
	</body>
  <script src="https://testup.cybersource.com/uc/v1/assets/0.28.2/SecureAcceptance.js"></script>
  <!--Cybersource js
	prod url : https://up.cybersource.com/uc/v1/assets/0.28.3/SecureAcceptance.js
 -->
</html>


Payment Token Request

Request Payment Token API with CLICK2PAY payment channel code

{
    "merchantID": "JT01",
    "invoiceNo": "1523953661",
    "description": "item 1",
    "amount": 1000.00,
  	"currencyCode": "SGD",
		"paymentChannel": ["CLICK2PAY"]

}

Request CaptureContext via Payment Option Detail API

To specific request for click2pay, required to send

  • categoryCode : DPAY
  • groupCode : CWALLET
  • in HTTP header required to add merchant website domain.
    • This is required for click2pay service to whitelist when merchant website is populate the drop-in UI
    • The website domain provided MUST be same as the provided website when onboard with 2c2p
    • X-Merchant-Domain : <merchant-domain>
url --location 'https://sandbox-pgw.2c2p.com/payment/4.3/PaymentOptionDetails' \
--header 'X-Merchant-Domain: https://merhcantABC.com' \
--header 'Content-Type: application/json' \
--data '{"paymentToken": "kSAops9Zwhos8hSTSeLTUTndJJj51v8PCyu4uHoefMlPOgG39WOcgWgVfPAcQ9NRQHQBWvXl9q6OCvZBWzDoOBVQ24dKUIZ5slcL1Oo5TpQ=", "categoryCode" : "DPAY", "groupCode": "CWALLET"}'

Receive CaptureContext data from Channels[].payment.token

{
  "totalChannel": 1,
  "name": null,
  "categoryCode": "DPAY",
  "groupCode": "CWALLET",
  "iconUrl": "https://d27uu9vmlo4gwh.cloudfront.net/images/v4/images/icon/wallet.png",
  "channels": [
    {
      "sequenceNo": 7,
      "name": "Click2Pay",
      "bankShortName": null,
      "currencyCodes": null,
      "iconUrl": "https://d27uu9vmlo4gwh.cloudfront.net/images/v4/images/icon/click2pay.png",
      "logoUrl": "https://d27uu9vmlo4gwh.cloudfront.net/images/v4/images/logo/click2pay.png",
      "payment": {
        "code": {
          "channelCode": "CLICK2PAY"
        },
        "input": {
          "name": "O",
          "email": "O",
          "customerNote": "I"
        },
        "validation": {
          "name": "^(?!\\s*$)[-a-zA-Z' ''.']{1,}$",
          "email": "^(([^<>()\\[\\]\\\\.,;:\\s@\"]+(\\.[^<>()\\[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$",
          "customerNote": "(.*?)"
        },
        "info": {
          "customData": [],
          "provider": {
            "id": "",
            "channels": [
              "MA",
              "VI",
              "UP",
              "MD"
            ],
            "merchantDetails": {
              "id": "458458000000000",
              "name": "SCCS",
              "countryCode": "MY"
            },
            "transactionDetails": {
              "amount": 10,
              "currencyCode": "MYR",
              "invoiceNo": "270226105906",
              "description": "V4 Test"
            },
            "termsConsent": false
          },
          "termsConsent": false,
          "token": "eyJraWQiOiJ3ZiIsImFsZyI6IlJTMjU2In0.eyJmbHgiOnsicGF0aCI6Ii9mbGV4L3YyL3Rva2VucyIsImRhdGEiOiJ4VU45YmY3bEh2QU0yRElWZWlCZFZHMTN6UVJoWlUwVnlQNVVRQlA4cUN4cHc1UElGNFF4UmZFY1hmWHM1V1JvdDFON1BrWnJlaTlJb3hQbVM5RHZxdnRBV1Roenl1LVV3dlJMeGh0bU5ZMUx0SmZ0S2ZfbTl1bEtOblVNa1NjRk0temVwd2o2RC00Ni1RWm11RldONUVaOWlydFJ2Y1d3NzQwS0hhRW92THBvS2RDMXhzZ1N5UWZUNG04ZVVpc2VJLWs3UTdCR1hqTjFycDdZQS1taUdMOUxqSDZsZzg0OGY1UFoiLCJvcmlnaW4iOiJodHRwczovL2ZsZXguY3liZXJzb3VyY2UuY29tIiwidHJhbnNpZW50VG9rZW5PcGVyYXRpb25zIjpbeyJzdWIiOiIyYzJwX2MycF9nbG9iYWwwMDEiLCJhdWQiOiIyYzJwX3BvcnRmb2xpbyIsImtpZCI6IjIwMjQxMjE4LTJjMnAtcHVibGljIiwidHlwZSI6IlNUT1JFIn1dLCJ0b2tlbnNVcmwiOiJodHRwczovL2ZsZXguY3liZXJzb3VyY2UuY29tL2ZsZXgvdjIvdG9rZW5zIiwiandrIjp7Imt0eSI6IlJTQSIsImUiOiJBUUFCIiwidXNlIjoiZW5jIiwibiI6ImwyV0xfYmRQdzJMekJ3RjYxZjgwZHJTdHp4SnJENUhtWkNHN0dRTFQ4VG5zTXN0bldhMmRVYTBPQWM2M0MxNUJlU0VPLWY1YTNuY0FsOUhMX3QyWGVNUFdmX2ZLSDhRMWdwRHB1OVM1SmNQMC1FNzI4WGJoT2FLaEVMa25UZUVjdVFiNWhhdUppbS1wMV9Sd2RVNlQxX09rSHJ5NjFPMmw2c1RYSUJIZVp6LWJWRTJacmtzUjdWNjhJaG5uaHViRnNkdEVEc182d1UtcTdHUjBlbXNUUDZldFNzMU5oYkFwUVpVdTE2SGJfaU4zX09idl9ObF93cmNmZVVfLUEwZGVoaFY1WHdST2pxODNjNHNkbkVGY1RiMGpwYUZzdFZYUzhtc1plZHc4V0dnMk5IMjRxSDV2ZUZDYXIwUW1KVC16T1dGZ0dqdS03RTB2dXl4VDBZdTZ4USIsImtpZCI6IjAzVzQxTG4wZWJJaE45NnZuRUxWNWQ3OGt1dWhFYmJmIn19LCJjdHgiOlt7ImRhdGEiOnsiYWxsb3dlZFBheW1lbnRUeXBlcyI6WyJDTElDS1RPUEFZIiwiUEFORU5UUlkiXSwib3JkZXJJbmZvcm1hdGlvbiI6eyJhbW91bnREZXRhaWxzIjp7InRvdGFsQW1vdW50IjoiMTAuMDAiLCJjdXJyZW5jeSI6Ik1ZUiJ9fSwiY2FwdHVyZU1hbmRhdGUiOnsic2hvd0NvbmZpcm1hdGlvblN0ZXAiOnRydWUsImJpbGxpbmdUeXBlIjoiTk9ORSIsInJlcXVlc3RFbWFpbCI6dHJ1ZSwicmVxdWVzdFBob25lIjpmYWxzZSwicmVxdWVzdFNoaXBwaW5nIjpmYWxzZSwic2hpcFRvQ291bnRyaWVzIjpbIk1ZIl0sInNob3dBY2NlcHRlZE5ldHdvcmtJY29ucyI6ZmFsc2V9LCJwYXltZW50Q29uZmlndXJhdGlvbnMiOnsiU1JDVklTQSI6eyJvcmlnaW4iOiJodHRwczovL2Fzc2V0cy5zZWN1cmUuY2hlY2tvdXQudmlzYS5jb20iLCJwYXRoIjoiL2NoZWNrb3V0LXdpZGdldC9yZXNvdXJjZXMvanMvc3JjLWktYWRhcHRlci92aXNhU2RrLmpzP3YyIiwicGFuRW5jcnlwdGlvbktleSI6eyJraWQiOiJaSFBRQlowVko4VTJKQlZRTjVaVzE0d2tPaXNOektkT1AtQjMxQXZLS0FYNENMeldFIiwiZSI6IkFRQUIiLCJuIjoia1B1andWSmpldklfb2Vad1pvQTJXanQ5NERGY012UkNhYjhpUmlFR3JHZktXdE5Dd1FZa3lseXVSb0I2MTVjWW0yQlZidm9LSDhZeXYwYUMzZHdhaDZVbU9kSnN6bUwwcFZfY2J4X3RYeldnWWczc1lOc3Awc0J4VUZjUTFBNkRWYnlPeHhKYm1ud2xIR0U1Zmt1ekpyLXFxdWwzUnN3c0NHLXZQcmhfLS0yX1JTaXBhOWxWcjlndmZJNEFiRkFCTFRxS2V0bzByV1BiSUJLZGhjR1E3Sk1QeHpxODIzOUtQVVpmU3lOdWVBY2RMLXlIQURpM0wyVlN6ZEY3dFM3c2kzdWVfSUZvWERwYmdnc0Z4dkV0NzlVbEJET0JzYWdjX21zOV9ac1lsSmFLQ1Q4Wmp3aGFrTW9fLVpkYzk3bXVkVmoxanoyX0w1bDRsX3ppYkY1cml3In0sInBhcmFtZXRlcnMiOnsic3JjSW5pdGlhdG9ySWQiOiJQVVBWVk1BTFNKUUdET0lKRDFQSTIxYTktdlpUbHFWV3FyNm13TkYzWTEyTllPR3lrIiwic3JjaURwYUlkIjoiNDdkOGEzYTYtZjExYS00MGJkLTkzMGQtYWMwYmEyMWQ1M2E4Iiwic3JjaVRyYW5zYWN0aW9uSWQiOiI4Y2MzYjc0Ny03ODhlLTRkY2ItYjUxMi03ZDcyMDIxNDcwNWIiLCJkcGFUcmFuc2FjdGlvbk9wdGlvbnMiOnsiZHBhTG9jYWxlIjoiZW4iLCJwYXlsb2FkVHlwZUluZGljYXRvciI6IkZVTEwiLCJyZXZpZXdBY3Rpb24iOiJjb250aW51ZSIsImRwYUFjY2VwdGVkQmlsbGluZ0NvdW50cmllcyI6W10sImRwYUFjY2VwdGVkU2hpcHBpbmdDb3VudHJpZXMiOlsiTVkiXSwiZHBhQmlsbGluZ1ByZWZlcmVuY2UiOiJOT05FIiwiZHBhU2hpcHBpbmdQcmVmZXJlbmNlIjoiTk9ORSIsImNvbnN1bWVyTmFtZVJlcXVlc3RlZCI6dHJ1ZSwiY29uc3VtZXJFbWFpbEFkZHJlc3NSZXF1ZXN0ZWQiOnRydWUsImNvbnN1bWVyUGhvbmVOdW1iZXJSZXF1ZXN0ZWQiOmZhbHNlLCJtZXJjaGFudENvdW50cnlDb2RlIjoiTVkiLCJjdXN0b21JbnB1dERhdGEiOnsiY2hlY2tvdXRPcmNoZXN0cmF0b3IiOiJtZXJjaGFudCJ9LCJ0cmFuc2FjdGlvbkFtb3VudCI6eyJ0cmFuc2FjdGlvbkFtb3VudCI6IjEwLjAwIiwidHJhbnNhY3Rpb25DdXJyZW5jeUNvZGUiOiJNWVIifSwicGF5bWVudE9wdGlvbnMiOnsiZHBhRHluYW1pY0RhdGFUdGxNaW51dGVzIjoxNSwiZHBhUGFuUmVxdWVzdGVkIjpmYWxzZSwiZHluYW1pY0RhdGFUeXBlIjoiQ0FSRF9BUFBMSUNBVElPTl9DUllQVE9HUkFNX0xPTkdfRk9STSJ9fX19LCJTUkNNQVNURVJDQVJEIjp7Im9yaWdpbiI6Imh0dHBzOi8vc3JjLm1hc3RlcmNhcmQuY29tIiwicGF0aCI6Ii9zZGsvc3Jjc2RrLm1hc3RlcmNhcmQuanMiLCJwYW5FbmNyeXB0aW9uS2V5Ijp7Imt0eSI6IlJTQSIsImUiOiJBUUFCIiwidXNlIjoiZW5jIiwia2lkIjoiMjAyMzAyMjcxMzU2MDMtcHJvZC1mcGFuLWVuY3J5cHRpb24tc3JjLW1hc3RlcmNhcmQtaW50Iiwia2V5X29wcyI6WyJlbmNyeXB0Iiwid3JhcEtleSJdLCJhbGciOiJSU0EtT0FFUC0yNTYiLCJuIjoienh3SHF1elJKRnlfRkhXS2xaeDNxZkhNSElLS1dJaklSZnJDOWV0dVZPN2RDOHYyUlgxbG1wRmdpQTZKeHRiU20tZGFpbTc5U2ZrNnJQc05mUHVKT3VlbzlRYlgxUWlWZVJ3NmR1VU5OeTdtZ0w4bHpuaHRBNWhoOF9WZngxYXduR3E2TFUxX3lfeXd2QXhkcm0zS0djTVp2VUFKYS0wVUFoTFBJTF8tT1c1TjVlSVFQVGczbklyaVlNY0RZMXBENTRGQVRJYnFQQU5NVUVybVN6VVJtRktPdTZUblJnVTFueDg4czBRR0p5eU00SC1qUnh3N0g4OWV0UjlUeERwUjI0OE5WTmZURXczWXpIUmE1WnZkcTNpVHVGWk9YcmxkRGFsNGhIYzY2WkZTclc1STc2MHllQ3gxMVRTdUlxaDhnS2VIN2ZEdmRlNG9ibmdqNkx4MmJ3In0sInBhcmFtZXRlcnMiOnsic3JjaVRyYW5zYWN0aW9uSWQiOiI4Y2MzYjc0Ny03ODhlLTRkY2ItYjUxMi03ZDcyMDIxNDcwNWIiLCJzcmNpRHBhSWQiOiI0N2Q4YTNhNi1mMTFhLTQwYmQtOTMwZC1hYzBiYTIxZDUzYTgiLCJzcmNJbml0aWF0b3JJZCI6IjVmMDg4ODA1LTU4Y2ItNDBlYi05MTdiLWFiOWIxM2ZhYjIxYSIsImRwYVRyYW5zYWN0aW9uT3B0aW9ucyI6eyJ0cmFuc2FjdGlvblR5cGUiOiJQVVJDSEFTRSIsImRwYUxvY2FsZSI6ImVuIiwiZHBhQWNjZXB0ZWRTaGlwcGluZ0NvdW50cmllcyI6WyJNWSJdLCJjb25zdW1lckVtYWlsQWRkcmVzc1JlcXVlc3RlZCI6dHJ1ZSwiY29uc3VtZXJQaG9uZU51bWJlclJlcXVlc3RlZCI6ZmFsc2UsInRyYW5zYWN0aW9uQW1vdW50Ijp7InRyYW5zYWN0aW9uQW1vdW50IjoiMTAuMDAiLCJ0cmFuc2FjdGlvbkN1cnJlbmN5Q29kZSI6Ik1ZUiJ9LCJkcGFBY2NlcHRlZEJpbGxpbmdDb3VudHJpZXMiOltdLCJkcGFCaWxsaW5nUHJlZmVyZW5jZSI6Ik5PTkUiLCJkcGFTaGlwcGluZ1ByZWZlcmVuY2UiOiJOT05FIiwiY29uc3VtZXJOYW1lUmVxdWVzdGVkIjp0cnVlLCJwYXlsb2FkVHlwZUluZGljYXRvciI6IkZVTEwiLCJwYXltZW50T3B0aW9ucyI6eyJkeW5hbWljRGF0YVR5cGUiOiJDQVJEX0FQUExJQ0FUSU9OX0NSWVBUT0dSQU1fU0hPUlRfRk9STSJ9fX19fSwidGFyZ2V0T3JpZ2lucyI6WyJodHRwczovL3Bndy11aS4yYzJwLmNvbSJdLCJpZnJhbWVzIjp7Im1jZSI6Ii9tY2UvbWNlLmh0bWwiLCJidXR0b25zIjoiL2J1dHRvbmxpc3QvYnV0dG9ubGlzdC5odG1sIiwic3JjIjoiL3NlY3VyZS1yZW1vdGUtY29tbWVyY2Uvc3JjLmh0bWwiLCJjdHAiOiIvY3RwL2N0cC5odG1sIiwiZ29vZ2xlcGF5IjoiL2dvb2dsZXBheS9nb29nbGVwYXkuaHRtbCIsImFwcGxlcGF5IjoiL2FwcGxlcGF5L2FwcGxlcGF5Lmh0bWwiLCJwYXplIjoiL3BhemUvcGF6ZS5odG1sIiwiY2hlY2siOiIvY2hlY2svY2hlY2suaHRtbCIsImdhIjoiL2dhL2dhLmh0bWwiLCJvcmMiOiIvb3JjL29yYy5odG1sIiwidG0iOiIvdG0vdG0uaHRtbCIsImFwbSI6Ii9hcG0vYXBtLmh0bWwifSwiY2xpZW50VmVyc2lvbiI6IjAuMjgiLCJjb3VudHJ5IjoiTVkiLCJsb2NhbGUiOiJlbiIsImFsbG93ZWRDYXJkTmV0d29ya3MiOlsiTUFTVEVSQ0FSRCIsIlZJU0EiXSwiYW5hbHl0aWNzIjp7Imdvb2dsZSI6eyJzY3JpcHQiOiJodHRwczovL3d3dy5nb29nbGV0YWdtYW5hZ2VyLmNvbS9ndGFnL2pzIiwiaWQiOiJHLVBUMlJZOFYxNkQifSwiZXZlbnRHcm91cElkIjoiMWNOWktDRGtaTFYxSDNjdVFXMEpRektqS0xGNXE0ZEN3VElIN1ZFQXpfLXZsbFphTnd5LTVtNWxUUzJ3Xy1RIn0sImNyIjoib0RwN1ZhXzFOUWtWa3ZIS08wRFduY3Vsd2gwcHlnWURJRGtOaVgxZnRBbWRwcHFLNGtYYVpiQk05N2UxSkFabVktXzE2WkpPMlA3cW9BMkx5cnFVWklDZVJmakIzWl9oSVdONXVMMV9KX2RwNDZsUE93UnBWVUc1amxBblIyYUtQUHF1ZlM3d3Y3R1RJeEUiLCJzZXJ2aWNlT3JpZ2luIjoiaHR0cHM6Ly91cC5jeWJlcnNvdXJjZS5jb20iLCJjbGllbnRMaWJyYXJ5IjoiaHR0cHM6Ly91cC5jeWJlcnNvdXJjZS5jb20vdWMvdjEvYXNzZXRzLzAuMjguMy9TZWN1cmVBY2NlcHRhbmNlLmpzIiwibG9nZ2luZ1BhdGgiOiIvdWMvdjEvbG9nLWV2ZW50cyIsImFzc2V0c1BhdGgiOiIvdWMvdjEvYXNzZXRzLzAuMjguMyIsImNsaWVudExpYnJhcnlJbnRlZ3JpdHkiOiJzaGEyNTYtM3Z4M2dXamwreEphOUpaYS9lS0E5VTFFRTVMWE5qMGxHN3JXUW12cS9uUVx1MDAzZCJ9LCJ0eXBlIjoiZ2RhLTAuMTAuMCJ9XSwiaXNzIjoiRmxleCBBUEkiLCJleHAiOjE3NzIxNjU3MTYsImlhdCI6MTc3MjE2NDgxNiwianRpIjoiY0NVVjRVVnBxSzZMY3NVTCJ9.mMdzEKmwvdHVDEtAKfUubGax4981z0m1CHKDDtGzhrfUWh8Y3nJ1uLL50ny1KaA6JFx8mqtf6yFnSdH3XZxbbOFzaob5beXqtSQnHuBjWOJ75kgHVjtxxg7pAsdZASnW5bBfcmavkiPZas1K7V5HJvh9XEivM5kYr_6q3iMZKMk7M6QD-ts2gcTItfoYX-29wUiUCZABwqkPQj3aQLSVmnDP1vU_j7nPaW9xlUAyW01_yOMqcyWHpHS4ZhQ19tG3JoCbsleasFj2drzm9Tf5XYvGxPRDMmkPXRSeMYxX-ieVd4vEXBwoLN_Zk07BwABO3D_ETZr1-2dAiWdIJolW8g",
          "srcUrl": "https://testup.cybersource.com/uc/v1/assets/0.28.3/SecureAcceptance.js"
        },
        "isDown": false,
        "CheckEligibleOption": false,
        "ippProviderCode": null,
        "registrationStatus": null,
        "partnerMerchantRefID": null,
        "displayProcessingAmount": false,
        "supportsTokenization": false,
        "clickToPayEnabled": false,
        "requiredTxnStatusInquiry": false,
        "SupportPaySimulate": false
      }
    }
  ],
  "validation": null,
  "configuration": {
    "payment": {
      "tokenize": false,
      "tokenizeOnly": false,
      "cardTokenOnly": false,
      "immediatePayment": true,
      "fx": {}
    },
    "notification": {
      "facebook": false,
      "whatsApp": false,
      "line": false
    }
  },
  "respCode": "0000",
  "respDesc": "Success"
}

Populate click2pay event() & button

To populate click2pay event and button, captureContextToken data is required

 <script>
function loadClick2PayButton(captureContextToken){
    var captureContextToken =
          const click2PayWindow = window;
    if (!click2PayWindow.Accept) {
        console.error("Accept() not found. UC script not loaded.");
        return;
      }

    click2PayWindow.Accept(captureContextToken)
        .then(function (accept) {
        return accept.unifiedPayments();
      })
        .then(function (up) {
        return up.show(showArgs);
      })
        .then(function (result) {

        // call do payment api with return token
        submitPayment(result);
      })
        .catch(function (err) {
        console.error("UC error", err);
      });
}

//control the click2pay button   
const showArgs = {
	  containers: {
		paymentSelection: "#payment-container"
	  },
	  locale: "en_US"
};
</script>

Submit Payment via Do Payment API

To specific request for click2pay, required to send

  • payment.data.token : token from click2pay
  • payment.code.channelCode : CLICK2PAY
{
  "payment": {
    "data": {
      "token": "eyJraWQiOiIwOGFxd2JkeXJOU0RIbHh3MFZCMGp2Z2Z3ZU00MFhzayIsImFsZyI6IlJTMjU2In0.eyJtZXRhZGF0YSI6eyJjYXJkaG9sZGVyQXV0aGVudGljYXRpb25TdGF0dXMiOmZhbHNlLCJwYXltZW50VHlwZSI6IlBBTkVOVFJZIn0sImlzcyI6IkZsZXgvMDgiLCJwYXltZW50Q3JlZGVudGlhbHNSZWZlcmVuY2UiOnsiMmMycF9zYW5kYm94IjoiRU1keS12UGlSd2JrYTR3TTVaY1h2In0sImV4cCI6MTc3MjE3MzM3OCwidHlwZSI6ImdkYS0wLjEwLjAiLCJpYXQiOjE3NzIxNzI0NzgsImp0aSI6IjFFMDJYMVA4U09ZSlg3Rk5ONEFGT0dKSjI2UFo5SDhPS1o3OVE5VUJKWkRYUEhOQ0RZRTA2OUExMzg0Mjc5MjQiLCJjb250ZW50Ijp7Im9yZGVySW5mb3JtYXRpb24iOnsiYmlsbFRvIjp7ImNvdW50cnkiOnt9LCJsYXN0TmFtZSI6e30sImZpcnN0TmFtZSI6e30sImVtYWlsIjp7fX0sImFtb3VudERldGFpbHMiOnsidG90YWxBbW91bnQiOnt9LCJjdXJyZW5jeSI6e319fSwicGF5bWVudEluZm9ybWF0aW9uIjp7ImNhcmQiOnsiZXhwaXJhdGlvblllYXIiOnsidmFsdWUiOiIyMDI4In0sIm51bWJlciI6eyJtYXNrZWRWYWx1ZSI6IlhYWFhYWFhYWFhYWDExMTEiLCJiaW4iOiI0MTExMTEifSwic2VjdXJpdHlDb2RlIjp7fSwiZXhwaXJhdGlvbk1vbnRoIjp7InZhbHVlIjoiMDMifSwidHlwZVNlbGVjdGlvbkluZGljYXRvciI6eyJ2YWx1ZSI6IjEifSwidHlwZSI6eyJ2YWx1ZSI6IjAwMSJ9fX19fQ.OK5xYmXAFEWJw-YWBKcb70J1d7KIJxZB_l0wFtGsP8LdGvMG_ihQ53siiFuqUvH72PBVX0OoQDrL9clg-J72ivTTnH5G-qlpZIRXh7qzFll3gcw0xb_lKUf4rLUVOa33HcXfV9QJCWx3tBJyqZ_Mx-eGMS0A_sAx2l1uC4P_taJ9dXJrDN7AOaH1qQRMWr_m0jBujhVVWYBFlE7Rx5mHcNWGZ1BuxJF9Pn8NR0O2WLHdub4VFm_lWgLZK-a-fbjfBkc635qjgUivLeAGiNdQu2ywwA6TtkxzZ1y-TEWliqqkwjx6YcnKGmEpWhBP_tWYOL0XczNpErA1wFb8O1VEYg"
    },
    "code": {
      "channelCode": "CLICK2PAY"
    }
  },
  "paymentToken": "kSAops9Zwhos8hSTSeLTUZ/goBdhnDMvyGuHBEHQqL2GuUEfQDEVxQ4gc+Fovrclau1BRVuOSSK9njQZCzgFJtPIMtNDBsADV76rcWV75eVvVj3cbNFhfIYADvw0rF4eQjS0a09AoemPBOFO+X9cvw=="
}

Full Sample Code

<!DOCTYPE html>
<html>
<body>

<button id="paysubmit" onClick="initialPay()">Submit</button>
<div id="payment-container"></div> <!--to show click to pay button-->

<script src="https://testup.cybersource.com/uc/v1/assets/0.28.2/SecureAcceptance.js"></script>
<script>
	var endpoint = "https://sandbox-pgw.2c2p.com";
	var merchantDomain = "https://www.2c2p.com";
	var click2Paytoken;

	function initialPay(){

		//Call Payment token API

		//Dummy payment token just for testing
		var paymentToken = "kSAops9Zwhos8hSTSeLTUdidclqi6ZtWWFG8cIOIXZvc+Gxmk0gyH6NhQPROKBAWtwaXFypz7QdPjPohVr63ar4Qu3tpOJc90ugyQS9nqP+1GshjNKo1i8CuZ3PI3s25Boz1W8oIVezuY/trNtBF5g==";
		onSubmitCaptureContext(paymentToken);

	}


	function onSubmitCaptureContext(paymentToken){
	
		const headers = {
			"Content-Type": "application/json"
		};
		headers["X-Merchant-Domain"] = merchantDomain;
	
		fetch(`${endpoint}/payment/4.3/PaymentOptionDetails`, {
			method: "POST",
			headers,
			body: JSON.stringify({
				paymentToken: paymentToken,
				categoryCode: "DPAY",
				groupCode: "CWALLET"
				})
			})
			.then(res => res.json())
			.then(data => {

				//Retrieve token, use loop to find channelCode=CLICK2PAY
				for(var i=0; i< data.channels.length; i++ ){
					if(data.channels[i].payment.code.channelCode == "CLICK2PAY"){
						click2Paytoken = data.channels[i].payment.info.token;
					}
				}
				loadClick2PayButton(click2Paytoken);
			})
			.catch(err => {
				console.error("Payment error:", err);
			});
	}

	
	function submitPayment(transientToken){
		var returnUrl = "https://sandbox-pgw-ui.2c2p.com/payment/4.3/#/info/";
		
		const payload = {
			paymentToken,
			responseReturnUrl: returnUrl,
			payment: {
			  code: {
				channelCode: "CLICK2PAY"
			  },
			  data: {
				token: transientToken
			  }
			}
		};
	  
		try {
			const res = fetch(`${endpoint}/payment/4.3/payment`, {
			  method: "POST",
			  headers: {
				"Content-Type": "application/json"
			  },
			  body: JSON.stringify(payload)
			})
			.then(res => res.json())
			.then(res => {
				console.log("Payment response:", res);
				if (
					res.respCode === "1001" ||
					res.respCode === "1002" ||
					res.respCode === "1004"
				 ) {
					window.open(res.data, "_self");
				 }
			});
		} catch (err) {
			console.error("Payment error:", err);
		}
	}
  
  //control the click2pay button 
	const showArgs = {
	  containers: {
		paymentSelection: "#payment-container"
	  },
	  locale: "en_US"
	};

	function loadClick2PayButton(captureContextToken){
	
		const click2PayWindow = window;
		if (!click2PayWindow.Accept) {
		console.error("Accept() not found. UC script not loaded.");
		return;
		}

		click2PayWindow.Accept(captureContextToken)
		.then(function (accept) {
			return accept.unifiedPayments();
		})
		.then(function (up) {
			return up.show(showArgs);
		})
		.then(function (result) {
			submitPayment(result);
		})
		.catch(function (err) {
			console.error("UC error", err);
		});
	}

</script>
</body>
</html>