Continue button still disable Google Pay Integration

740 views Asked by At

I am trying to integrate the Google API buy button in my sample page and I just hosted in my server. Everything looks fine, after clicking "buy" button, a pop up with shipping options and amount to pay is showing but the button "Continue" is still disable so I can't proceed further. Seems there is no error is consoling.Can anyone help me to solve this.

// Global key for canMakepayment cache.
const canMakePaymentCache = 'canMakePaymentCache';

/**
 * Read data for supported instruments from input from.
 */
function readSupportedInstruments() {
  let formValue = {};
  formValue['pa'] = document.getElementById('pa').value;
  formValue['pn'] = document.getElementById('pn').value;
  formValue['tn'] = document.getElementById('tn').value;
  formValue['mc'] = document.getElementById('mc').value;
  formValue['tr'] = document.getElementById('tr').value;
  formValue['tid'] = document.getElementById('tid').value;
  formValue['url'] = document.getElementById('url').value;
  return formValue;
}

/**
 * Read the amount from input form.
 */
function readAmount() {
  return document.getElementById('amount').value;
}

/**
 * Launches payment request.
 */
function onBuyClicked() {
  debugger;
  if (!window.PaymentRequest) {
    console.log('Web payments are not supported in this browser.');
    return;
  }

  let formValue = readSupportedInstruments();

  const supportedInstruments = [
    {
      supportedMethods: ['https://pwp-server.appspot.com/pay-dev'],
      data: formValue,
    },
    {
      supportedMethods: ['https://google.com/pay'],
      data: formValue,
    },
  ];

  const details = {
    total: {
      label: 'Total',
      amount: {
        currency: 'INR',
        value: readAmount(),
      },
    },
    displayItems: [
      {
        label: 'Original amount',
        amount: {
          currency: 'INR',
          value: readAmount(),
        },
      },
    ],
  };

  const options = {
    requestShipping: true,
    requestPayerName: true,
    requestPayerPhone: true,
    requestPayerEmail: true,
    shippingType: 'shipping',
  };

  let request = null;
  try {
    request = new PaymentRequest(supportedInstruments, details, options);
  } catch (e) {
    console.log('Payment Request Error: ' + e.message);
    return;
  }
  if (!request) {
    console.log('Web payments are not supported in this browser.');
    return;
  }

  request.addEventListener('shippingaddresschange', function(evt) {
    evt.updateWith(new Promise(function(resolve) {
      fetch('/ship', {
        method: 'POST',
        headers: new Headers({'Content-Type': 'application/json'}),
        body: addressToJsonString(request.shippingAddress),
        credentials: 'include',
      })
          .then(function(options) {
            if (options.ok) {
              return options.json();
            }
            console.log('Unable to calculate shipping options.');
          })
          .then(function(optionsJson) {
            if (optionsJson.status === 'success') {
              updateShipping(details, optionsJson.shippingOptions, resolve);
            } else {
              console.log('Unable to calculate shipping options.');
            }
          })
          .catch(function(err) {
            console.log('Unable to calculate shipping options. ' + err);
          });
    }));
  });

  request.addEventListener('shippingoptionchange', function(evt) {
    evt.updateWith(new Promise(function(resolve) {
      for (let i in details.shippingOptions) {
        if ({}.hasOwnProperty.call(details.shippingOptions, i)) {
          details.shippingOptions[i].selected =
              (details.shippingOptions[i].id === request.shippingOption);
        }
      }

      updateShipping(details, details.shippingOptions, resolve);
    }));
  });

  var canMakePaymentPromise = checkCanMakePayment(request);
  canMakePaymentPromise
      .then((result) => {
        showPaymentUI(request, result);
      })
      .catch((err) => {
        console.log('Error calling checkCanMakePayment: ' + err);
      });
}

/**
 * Checks whether can make a payment with Tez on this device. It checks the
 * session storage cache first and uses the cached information if it exists.
 * Otherwise, it calls canMakePayment method from the Payment Request object and
 * returns the result. The result is also stored in the session storage cache
 * for future use.
 *
 * @private
 * @param {PaymentRequest} request The payment request object.
 * @return {Promise} a promise containing the result of whether can make payment.
 */
function checkCanMakePayment(request) {
  // Checks canMakePayment cache, and use the cache result if it exists.
  if (sessionStorage.hasOwnProperty(canMakePaymentCache)) {
    return Promise.resolve(JSON.parse(sessionStorage[canMakePaymentCache]));
  }

  // If canMakePayment() isn't available, default to assuming that the method is
  // supported.
  var canMakePaymentPromise = Promise.resolve(true);

  // Feature detect canMakePayment().
  if (request.canMakePayment) {
    canMakePaymentPromise = request.canMakePayment();
  }

  return canMakePaymentPromise
      .then((result) => {
        // Store the result in cache for future usage.
        sessionStorage[canMakePaymentCache] = result;
        return result;
      })
      .catch((err) => {
        console.log('Error calling canMakePayment: ' + err);
      });
}

/**
 * Show the payment request UI.
 *
 * @private
 * @param {PaymentRequest} request The payment request object.
 * @param {Promise} canMakePayment The promise for whether can make payment.
 */
function showPaymentUI(request, canMakePayment) {
  // Redirect to play store if can't make payment.
  if (!canMakePayment) {
    redirectToPlayStore();
    return;
  }

  // Set payment timeout.
  let paymentTimeout = window.setTimeout(function() {
    window.clearTimeout(paymentTimeout);
    request.abort()
        .then(function() {
          console.log('Payment timed out after 20 minutes.');
        })
        .catch(function() {
          console.log('Unable to abort, user is in the process of paying.');
        });
  }, 20 * 60 * 1000); /* 20 minutes */

  request.show()
      .then(function(instrument) {
        window.clearTimeout(paymentTimeout);
        processResponse(instrument);  // Handle response from browser.
      })
      .catch(function(err) {
        console.log(err);
      });
}

/**
 * Process the response from browser.
 *
 * @private
 * @param {PaymentResponse} instrument The payment instrument that was authed.
 */
function processResponse(instrument) {
  var instrumentString = instrumentToJsonString(instrument);
  console.log(instrumentString);

  fetch('/buy', {
    method: 'POST',
    headers: new Headers({'Content-Type': 'application/json'}),
    body: instrumentString,
    credentials: 'include',
  })
      .then(function(buyResult) {
        if (buyResult.ok) {
          return buyResult.json();
        }
        console.log('Error sending instrument to server.');
      })
      .then(function(buyResultJson) {
        completePayment(
            instrument, buyResultJson.status, buyResultJson.message);
      })
      .catch(function(err) {
        console.log('Unable to process payment. ' + err);
      });
}

/**
 * Notify browser that the instrument authorization has completed.
 *
 * @private
 * @param {PaymentResponse} instrument The payment instrument that was authed.
 * @param {string} result Whether the auth was successful. Should be either
 * 'success' or 'fail'.
 * @param {string} msg The message to log in console.
 */
function completePayment(instrument, result, msg) {
  instrument.complete(result)
      .then(function() {
        console.log('Payment completes.');
        console.log(msg);
        document.getElementById('inputSection').style.display = 'none'
        document.getElementById('outputSection').style.display = 'block'
        document.getElementById('response').innerHTML =
            JSON.stringify(instrument, undefined, 2);
      })
      .catch(function(err) {
        console.log(err);
      });
}

/** Redirect to PlayStore. */
function redirectToPlayStore() {
  if (confirm('Tez not installed, go to play store and install?')) {
    window.location.href =
        'https://play.google.com/store/apps/details?id=com.google.android.apps.nbu.paisa.user.alpha'
  };
}

/**
 * Converts the shipping address into a JSON string.
 *
 * @private
 * @param {PaymentAddress} address The address to convert.
 * @return {string} The string representation of the address.
 */
function addressToJsonString(address) {
  var addressDictionary = address.toJSON ? address.toJSON() : {
    recipient: address.recipient,
    organization: address.organization,
    addressLine: address.addressLine,
    dependentLocality: address.dependentLocality,
    city: address.city,
    region: address.region,
    postalCode: address.postalCode,
    sortingCode: address.sortingCode,
    country: address.country,
    phone: address.phone,
  };
  return JSON.stringify(addressDictionary, undefined, 2);
}

/**
 * Converts the payment instrument into a JSON string.
 *
 * @private
 * @param {PaymentResponse} instrument The instrument to convert.
 * @return {string} The string representation of the instrument.
 */
function instrumentToJsonString(instrument) {
  // PaymentResponse is an interface, JSON.stringify works only on dictionaries.
  var instrumentDictionary = {
    methodName: instrument.methodName,
    details: instrument.details,
    shippingAddress: addressToJsonString(instrument.shippingAddress),
    shippingOption: instrument.shippingOption,
    payerName: instrument.payerName,
    payerPhone: instrument.payerPhone,
    payerEmail: instrument.payerEmail,
  };
  return JSON.stringify(instrumentDictionary, undefined, 2);
}

/**
 * Update order details with shipping information.
 *
 * @private
 * @param {PaymentDetails} details The details for payment.
 * @param {Array} shippingOptions The shipping options.
 * @param {function} callback The callback to invoke.
 */
function updateShipping(details, shippingOptions, callback) {
  let selectedShippingOption;
  for (let i in shippingOptions) {
    if (shippingOptions[i].selected) {
      selectedShippingOption = shippingOptions[i];
    }
  }

  var total = parseFloat(readAmount());
  if (selectedShippingOption) {
    let shippingPrice = Number(selectedShippingOption.amount.value);
    total = total + shippingPrice;
  }

  details.shippingOptions = shippingOptions;
  details.total.amount.value = total.toFixed(2);
  if (selectedShippingOption) {
    details.displayItems.splice(
        1, details.displayItems.length == 1 ? 0 : 1, selectedShippingOption);
  }

  callback(details);
}
<html lang="en">
<head><meta charset="us-ascii"><meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Web Payment Test</title>
    <link href="favicon.ico" rel="icon" type="image/png" />
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
<div class="container">
<h2>Web Payment Test</h2>

<p>This page is for testing web payment.</p>

<div id="inputSection">
<form class="form-horizontal">
<div class="form-group row"><label class="control-label col-xs-3" for="amount">Amount:</label>

<div class="col-xs-9"><input class="form-control" id="amount" type="number" value="10.01" /></div>
</div>

<div class="form-group row"><label class="control-label col-xs-3" for="pa">Payee VPA (pa):</label>

<div class="col-xs-9"><input class="form-control" id="pa" type="text" value="xxxxxx@bank" /></div>
</div>

<div class="form-group row"><label class="control-label col-xs-3" for="pn">Payee Name (pn):</label>

<div class="col-xs-9"><input class="form-control" id="pn" type="text" value="" /></div>
</div>

<div class="form-group row"><label class="control-label col-xs-3" for="tn">Txn Note (tn):</label>

<div class="col-xs-9"><input class="form-control" id="tn" type="text" value="test note" /></div>
</div>

<div class="form-group row"><label class="control-label col-xs-3" for="mc">Merchant Code (mc):</label>

<div class="col-xs-9"><input class="form-control" id="mc" type="text" value="" /></div>
</div>

<div class="form-group row"><label class="control-label col-xs-3" for="tid">Txn ID (tid):</label>

<div class="col-xs-9"><input class="form-control" id="tid" type="text" value="hhbvg5454554" /></div>
</div>

<div class="form-group row"><label class="control-label col-xs-3" for="tr">Txn Ref ID (tr):</label>

<div class="col-xs-9"><input class="form-control" id="tr" type="text" value="juhuhuhuhuvcrc" /></div>
</div>

<div class="form-group row"><label class="control-label col-xs-3" for="url">Ref URL (url):</label>

<div class="col-xs-9"><input class="form-control" id="url" type="url" value="https://teztytreats.com/demo" /></div>
</div>
</form>

<div class="form-group row clearfix">
<div class="col-xs-12"><button class="btn btn-info pull-right" onclick="onBuyClicked()">Buy</button></div>
</div>
</div>

<div id="outputSection" style="display:none">
<pre id="response">

</pre>
</div>

</div>
<script src="demo.js"></script></body>
</html>

2

There are 2 answers

0
sushil kumar pani On

Is your Business profile approved by google. Because this should be approved by google.

1
sushil kumar pani On

/**
 * Read the amount from input form.
 */
function readAmount() {
    // return parseFloat(document.getElementById('amount').value);
    return 1;
}

/** Launches payment request flow when user taps on buy button. */
function onBuyClicked() {
    if (!window.PaymentRequest) {
        console.log('Web payments are not supported in this browser.');
        return;
    }else{
      var pa  =  document.getElementById('pa').value;alert(pa);
      var pn  =  document.getElementById('pn').value;
      var tn  =  document.getElementById('tn').value;
      var mc  =  document.getElementById('mc').value;
      var tr  =  document.getElementById('tr').value;
      var tid =  document.getElementById('tid').value;
      var url =  document.getElementById('url').value;
    }

    const supportedInstruments = [{
        supportedMethods: ['https://tez.google.com/pay'],
        data: {
            pa : pa,
            pn : pn,
            tn : tn,
            mc : mc,
            tr : (Math.random().toString(10).slice(2)).toString()+'UPI',
            tid : (Math.random().toString(10).slice(2)).toString(),
            url : url,
        },
    }];

    const details = {
        total: {
            label: 'Total',
            amount: {
                currency: 'INR',
                value: new Number(String(readAmount())),
            },
        },
        displayItems: [{
            label: 'Original Amount',
            amount: {
                currency: 'INR',
                value: new Number(String(readAmount())),
            },
        }],
    };

    const options = {
        requestShipping: false,
        requestPayerName: false,
        requestPayerPhone: false,
        requestPayerEmail: false,
        shippingType: 'shipping',
      };

    let request = null;
    try {
        request = new PaymentRequest(supportedInstruments, details, options);
    } catch (e) {
        console.log('Payment Request Error: ' + e.message);
        return;
    }
    if (!request) {
        console.log('Web payments are not supported in this browser.');
        return;
    }

    var canMakePaymentPromise = checkCanMakePayment(request);
    canMakePaymentPromise
        .then((result) => {
            showPaymentUI(request, result);
        })
        .catch((err) => {
            console.log('Error calling checkCanMakePayment: ' + err);
        });
}

/**
 * Show the payment request UI.
 *
 * @private
 * @param {PaymentRequest} request The payment request object.
 * @param {Promise} canMakePayment The promise for whether can make payment.
 */
function showPaymentUI(request, canMakePayment) {
    if (!canMakePayment) {
        handleNotReadyToPay();
        return;
    }

    // Set payment timeout.
    let paymentTimeout = window.setTimeout(function () {
        window.clearTimeout(paymentTimeout);
        request.abort()
            .then(function () {
                console.log('Payment timed out after 20 minutes.');
            })
            .catch(function () {
                console.log('Unable to abort, user is in the process of paying.');
            });
    }, 20 * 60 * 1000); /* 20 minutes */

    request.show()
        .then(function (instrument) {
            window.clearTimeout(paymentTimeout);
            processResponse(instrument); // Handle response from browser.
        })
        .catch(function (err) {
            console.log(err);
        });
}

/** Handle Google Pay not ready to pay case. */
function handleNotReadyToPay() {
    alert('Google Pay is not ready to pay.');
}

/* Converts the payment response into a JSON string.
 *
 * @private
 * @param {PaymentResponse} paymentResponse The payment response to convert.
 * @return {string} The string representation of the payment response.
 */
function paymentResponseToJsonString(paymentResponse) {
    // PaymentResponse is an interface, JSON.stringify works only on dictionaries.
    var paymentResponseDictionary = {
        methodName: paymentResponse.methodName,
        details: paymentResponse.details,
        shippingAddress: addressToJsonString(paymentResponse.shippingAddress),
        shippingOption: paymentResponse.shippingOption,
        payerName: paymentResponse.payerName,
        payerPhone: paymentResponse.payerPhone,
        payerEmail: paymentResponse.payerEmail,
    };
    return JSON.stringify(paymentResponseDictionary, undefined, 2);
}

/**
 * Process the response from browser.
 *
 * @private
 * @param {PaymentResponse} instrument The payment instrument that was authed.
 */
function processResponse(instrument) {
    var instrumentString = instrumentToJsonString(instrument);
    console.log(instrumentString);

    fetch('/buy', {
            method: 'POST',
            headers: new Headers({
                'Content-Type': 'application/json'
            }),
            body: instrumentString,
        })
        .then(function (buyResult) {
            if (buyResult.ok) {
                return buyResult.json();
            }
            console.log('Error sending instrument to server.');
        })
        .then(function (buyResultJson) {
            completePayment(instrument, buyResultJson.status, buyResultJson.message);

        })
        .catch(function (err) {
            console.log('Unable to process payment. ' + err);
        });
}

/**
 * Notify browser that the instrument authorization has completed.
 *
 * @private
 * @param {PaymentResponse} instrument The payment instrument that was authed.
 * @param {string} result Whether the auth was successful. Should be either
 * 'success' or 'fail'.
 * @param {string} msg The message to log in console.
 */
function completePayment(instrument, result, msg) {
    instrument.complete(result)
        .then(function () {
            console.log('Payment completes.');
            console.log(msg);
            document.getElementById('inputSection').style.display = 'none'
            document.getElementById('outputSection').style.display = 'block'
            document.getElementById('response').innerHTML =
            JSON.stringify(instrument, undefined, 2);
        })
        .catch(function (err) {
            console.log(err);
        });
}

// Global key for canMakepayment cache.
const canMakePaymentCache = 'canMakePaymentCache';

/**
 * Check whether can make payment with Google Pay or not. It will check session storage
 * cache first and use the cache directly if it exists. Otherwise, it will call
 * canMakePayment method from PaymentRequest object and return the result, the
 * result will also be stored in the session storage cache for future usage.
 *
 * @private
 * @param {PaymentRequest} request The payment request object.
 * @return {Promise} a promise containing the result of whether can make payment.
 */
function checkCanMakePayment(request) {
    // Check canMakePayment cache, use cache result directly if it exists.
    if (sessionStorage.hasOwnProperty(canMakePaymentCache)) {
        return Promise.resolve(JSON.parse(sessionStorage[canMakePaymentCache]));
    }

    // If canMakePayment() isn't available, default to assume the method is
    // supported.
    var canMakePaymentPromise = Promise.resolve(true);

    // Feature detect canMakePayment().
    if (request.canMakePayment) {
        canMakePaymentPromise = request.canMakePayment();
    }

    return canMakePaymentPromise
        .then((result) => {
            // Store the result in cache for future usage.
            sessionStorage[canMakePaymentCache] = result;
            return result;
        })
        .catch((err) => {
            console.log('Error calling canMakePayment: ' + err);
        });
}
<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Web Payment Test</title>
    <link rel="icon" type="image/png" href="favicon.ico">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
</head>

<body>
<div class="container">
    <h2>Booking Web Payment</h2>
   

    <div id="inputSection">

        <form class="form-horizontal" action="">
            <div class="form-group row">
                <label class="control-label col-xs-3" for="amount">Amount:</label>
                <div class="col-xs-9">
                    <input class="form-control" type="number" id="amount" value="1.00">
                </div>
            </div>

            <div class="form-group row">
                <label class="control-label col-xs-3" for="pa">Payee VPA (pa):</label>
                <div class="col-xs-9">
                    <input class="form-control" type="text" id="pa" value="example@ybl">
                </div>
            </div>

            <div class="form-group row">
                <label class="control-label col-xs-3" for="pn">Payee Name (pn):</label>
                <div class="col-xs-9">
                    <input class="form-control" type="text" id="pn" value="Tours And Travels">
                </div>
            </div>

            <div class="form-group row">
                <label class="control-label col-xs-3" for="tn">Txn Note (tn):</label>
                <div class="col-xs-9">
                    <input class="form-control" type="text" id="tn" value="Payment For Car, Flight Booking & Hotel Booking">
                </div>
            </div>

            <div class="form-group row">
                <label class="control-label col-xs-3" for="mc">Merchant Code (mc):</label>
                <div class="col-xs-9">
                    <input class="form-control" type="text" id="mc" value="4722">
                </div>
            </div>

            <div class="form-group row">
                <label class="control-label col-xs-3" for="tid">Txn ID (tid):</label>
                <div class="col-xs-9">
                    <input class="form-control" type="text" id="tid" value="">
                </div>
            </div>
            <?php $trffid = rand(00000,99999);$trffid = 'PAT'.$trffid; ?>
            <div class="form-group row">
                <label class="control-label col-xs-3" for="tr">Txn Ref ID (tr):</label>
                <div class="col-xs-9">
                    <input class="form-control" type="text" id="tr" value="PAT23232">
                </div>
            </div>

            <div class="form-group row">
                <label class="control-label col-xs-3" for="url">Ref URL (url):</label>
                <div class="col-xs-9">
                    <input class="form-control" type="url" id="url" value="https://teztytreats.com/demo"><!-- https://teztytreats.com/demo -->
                </div>
            </div>

            <div class="form-group row">
                <label class="control-label col-xs-3" for="url">Currency:</label>
                <div class="col-xs-9">
                    <input class="form-control" type="type" id="cu" value="INR">
                </div>
            </div>
        </form>

        <div class="form-group row clearfix">
            <div class="col-xs-12">
                <button class="btn btn-info pull-right" onclick="onBuyClicked()">Buy</button>
            </div>
        </div>
    </div>

    <div id="outputSection" >
        <pre id="response"></pre>
    </div>
</div>

<script src="demo.js"></script>
</body>
</html>