我正在尝试将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'],
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>
答案 0 :(得分:0)
您的商家资料是否获得了 google 的批准。因为这应该得到谷歌的批准。
答案 1 :(得分:0)
/**
* 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>