继续按钮仍禁用Google Pay集成

问题描述

我正在尝试将Google Api购买按钮集成到示例页面中,而我刚刚托管在服务器中。一切看起来都很好,单击“购买”按钮后,将显示一个弹出窗口,显示运输选项和付款金额,但“继续”按钮仍处于禁用状态,因此我无法继续进行操作。似乎没有任何错误可安慰。有人可以帮助我解决这个问题。

// 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'],];

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

  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',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);
      });
}

/** 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,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,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>

解决方法

您的商家资料是否获得了 google 的批准。因为这应该得到谷歌的批准。

,

/**
 * 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',}],};

    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,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>