blob: e14d8671ae8b78bcb694182add70772f340daca2 [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview JavaScript implementation of the Payment Request API. When
* loaded, installs the API onto the window object. Conforms
* to https://www.w3.org/TR/payment-request/. Note: This is a work in progress.
*/
/**
* This class implements the DOM level 2 EventTarget interface. The
* Implementation is copied form src/ui/webui/resources/js/cr/event_target.js.
* This code should be removed once there is a plan to move event_target.js out
* of WebUI and reuse in iOS.
* @constructor
* @implements {EventTarget}
*/
__gCrWeb.EventTarget =
function() {
this.listeners_ = null;
}
// Store EventTarget namespace object in a global __gCrWeb object referenced
// by a string, so it does not get renamed by closure compiler during the
// minification.
__gCrWeb['EventTarget'] = __gCrWeb.EventTarget;
/* Beginning of anonymous object. */
(function() {
__gCrWeb.EventTarget.prototype = {
/** @override */
addEventListener: function(type, handler) {
if (!this.listeners_)
this.listeners_ = Object.create(null);
if (!(type in this.listeners_)) {
this.listeners_[type] = [handler];
} else {
var handlers = this.listeners_[type];
if (handlers.indexOf(handler) < 0)
handlers.push(handler);
}
},
/** @override */
removeEventListener: function(type, handler) {
if (!this.listeners_)
return;
if (type in this.listeners_) {
var handlers = this.listeners_[type];
var index = handlers.indexOf(handler);
if (index >= 0) {
// Clean up if this was the last listener.
if (handlers.length == 1)
delete this.listeners_[type];
else
handlers.splice(index, 1);
}
}
},
/** @override */
dispatchEvent: function(event) {
var type = event.type;
var prevented = 0;
if (!this.listeners_)
return true;
// Override the DOM Event's 'target' property.
Object.defineProperty(event, 'target', {value: this});
if (type in this.listeners_) {
// Clone to prevent removal during dispatch
var handlers = this.listeners_[type].concat();
for (var i = 0, handler; handler = handlers[i]; i++) {
if (handler.handleEvent)
prevented |= handler.handleEvent.call(handler, event) === false;
else
prevented |= handler.call(this, event) === false;
}
}
return !prevented && !event.defaultPrevented;
}
};
}()); // End of anonymous object
/**
* PromiseResolver is a helper class that allows creating a Promise that will be
* fulfilled (resolved or rejected) some time later. The implementation is
* copied from src/ui/webui/resources/js/promise_resolver.js. This code should
* be removed once there is a plan to move promise_resolver.js out of WebUI and
* reuse in iOS.
* @constructor
* @template T
*/
__gCrWeb.PromiseResolver =
function() {
/** @private {function(T=): void} */
this.resolve_;
/** @private {function(*=): void} */
this.reject_;
/** @private {!Promise<T>} */
this.promise_ = new Promise(function(resolve, reject) {
this.resolve_ = resolve;
this.reject_ = reject;
}.bind(this));
}
// Store PromiseResolver namespace object in a global __gCrWeb object referenced
// by a string, so it does not get renamed by closure compiler during the
// minification.
__gCrWeb['PromiseResolver'] = __gCrWeb.PromiseResolver;
/* Beginning of anonymous object. */
(function() {
__gCrWeb.PromiseResolver.prototype = {
/** @return {!Promise<T>} */
get promise() { return this.promise_; },
/** @return {function(T=): void} */
get resolve() { return this.resolve_; },
/** @return {function(*=): void} */
get reject() { return this.reject_; },
};
}()); // End of anonymous object
/**
* A simple object representation of |window.PaymentRequest| meant for
* communication to the app side.
* @typedef {{
* methodData: !Array<!window.PaymentMethodData>,
* details: !window.PaymentDetails,
* options: (window.PaymentOptions|undefined)
* }}
*/
var SerializedPaymentRequest;
/**
* A simple object representation of |window.PaymentResponse| meant for
* communication to the app side.
* @typedef {{
* paymentRequestId: string,
* methodName: string,
* details: Object,
* shippingAddress: (!window.PaymentAddress|undefined),
* shippingOption: (string|undefined),
* payerName: (string|undefined),
* payerEmail: (string|undefined),
* payerPhone: (string|undefined)
* }}
*/
var SerializedPaymentResponse;
/* Beginning of anonymous object. */
(function() {
// Namespace for all PaymentRequest implementations. __gCrWeb must have
// already
// been defined.
__gCrWeb.paymentRequestManager = {};
/**
* Generates a random string identfier resembling a GUID.
* @return {string}
*/
__gCrWeb['paymentRequestManager'].guid = function() {
/**
* Generates a stringified random 4 digit hexadecimal number.
* @return {string}
*/
var s4 = function() {
return Math.floor((1 + Math.random()) * 0x10000)
.toString(16)
.substring(1);
};
return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() +
s4() + s4();
};
// Store paymentRequestManager namespace object in a global __gCrWeb object
// referenced by a string, so it does not get renamed by closure compiler
// during
// the minification.
__gCrWeb['paymentRequestManager'] = __gCrWeb.paymentRequestManager;
/**
* The PaymentRequest object, if any. This object is provided by the page and
* only updated by the app side.
* @type {window.PaymentRequest}
*/
__gCrWeb['paymentRequestManager'].pendingRequest = null;
/**
* The PromiseResolver object used to resolve or reject the promise returned
* by PaymentRequest.prototype.show, if any.
* @type {__gCrWeb.PromiseResolver}
*/
__gCrWeb['paymentRequestManager'].requestPromiseResolver = null;
/**
* The PromiseResolver object used to resolve or reject the promise returned
* by PaymentRequest.prototype.abort, if any.
* @type {__gCrWeb.PromiseResolver}
*/
__gCrWeb['paymentRequestManager'].abortPromiseResolver = null;
/**
* The PromiseResolver object used to resolve the promise returned by
* PaymentResponse.prototype.complete, if any.
* @type {window.PaymentRequest}
*/
__gCrWeb['paymentRequestManager'].responsePromiseResolver = null;
/**
* Parses |paymentResponseData| into a window.PaymentResponse object.
* @param {!SerializedPaymentResponse} paymentResponseData
* @return {window.PaymentResponse}
*/
__gCrWeb['paymentRequestManager'].parsePaymentResponseData = function(
paymentResponseData) {
var response = new window.PaymentResponse(
paymentResponseData['requestId'], paymentResponseData['methodName'],
paymentResponseData['details']);
if (paymentResponseData['shippingAddress'])
response.shippingAddress = paymentResponseData['shippingAddress'];
if (paymentResponseData['shippingOption'])
response.shippingOption = paymentResponseData['shippingOption'];
if (paymentResponseData['payerName'])
response.payerName = paymentResponseData['payerName'];
if (paymentResponseData['payerEmail'])
response.payerEmail = paymentResponseData['payerEmail'];
if (paymentResponseData['payerPhone'])
response.payerPhone = paymentResponseData['payerPhone'];
return response;
};
/**
* The event that enables the web page to update the details of the payment
* request in response to a user interaction.
* @type {Event}
*/
__gCrWeb['paymentRequestManager'].updateEvent = null;
/**
* Handles invocation of updateWith() on the updateEvent object. Updates the
* payment details. Throws an error if |detailsOrPromise| is not a valid
* instance of window.PaymentDetails or it is a promise that does not fulfill
* with a valid one.
* @param {!Promise<!window.PaymentDetails>|!window.PaymentDetails}
* detailsOrPromise
*/
__gCrWeb['paymentRequestManager'].updateWith = function(detailsOrPromise) {
// if |detailsOrPromise| is not an instance of a Promise, wrap it in a
// Promise that fulfills with |detailsOrPromise|.
if (!detailsOrPromise || !(detailsOrPromise.then instanceof Function) ||
!(detailsOrPromise.catch instanceof Function)) {
detailsOrPromise = Promise.resolve(detailsOrPromise);
}
detailsOrPromise
.then(function(paymentDetails) {
if (!paymentDetails)
throw new TypeError(
'An instance of PaymentDetails must be provided.');
var message = {
'command': 'paymentRequest.updatePaymentDetails',
'payment_details': paymentDetails,
};
__gCrWeb.message.invokeOnHost(message);
__gCrWeb['paymentRequestManager'].updateEvent = null;
})
.catch(function() {
var message = {
'command': 'paymentRequest.requestAbort',
};
__gCrWeb.message.invokeOnHost(message);
__gCrWeb['paymentRequestManager'].updateEvent = null;
});
};
/**
* Resolves the pending PaymentRequest.
* @param {!SerializedPaymentResponse} paymentResponseData The response to
* provide to the resolve function of the Promise.
*/
__gCrWeb['paymentRequestManager'].resolveRequestPromise = function(
paymentResponseData) {
if (!__gCrWeb['paymentRequestManager'].requestPromiseResolver) {
throw new Error('Internal PaymentRequest error: No Promise to resolve.');
}
if (!paymentResponseData) {
__gCrWeb['paymentRequestManager'].rejectRequestPromise(
'Internal PaymentRequest error: PaymentResponse missing.');
}
var paymentResponse = null;
try {
paymentResponse =
__gCrWeb['paymentRequestManager'].parsePaymentResponseData(
paymentResponseData);
} catch (e) {
__gCrWeb['paymentRequestManager'].rejectRequestPromise(
'Internal PaymentRequest error: failed to parse PaymentResponse.');
}
__gCrWeb['paymentRequestManager'].responsePromiseResolver =
new __gCrWeb.PromiseResolver();
__gCrWeb['paymentRequestManager'].requestPromiseResolver.resolve(
paymentResponse);
__gCrWeb['paymentRequestManager'].requestPromiseResolver = null;
__gCrWeb['paymentRequestManager'].pendingRequest = null;
__gCrWeb['paymentRequestManager'].updateEvent = null;
};
/**
* Rejects the pending PaymentRequest.
* @param {string} message An error message explaining why the Promise is
* being rejected.
*/
__gCrWeb['paymentRequestManager'].rejectRequestPromise = function(message) {
if (!__gCrWeb['paymentRequestManager'].requestPromiseResolver) {
throw new Error(
'Internal PaymentRequest error: No Promise to reject. ',
'Message was: ', message);
}
__gCrWeb['paymentRequestManager'].requestPromiseResolver.reject(message);
__gCrWeb['paymentRequestManager'].requestPromiseResolver = null;
__gCrWeb['paymentRequestManager'].pendingRequest = null;
__gCrWeb['paymentRequestManager'].updateEvent = null;
};
/**
* Resolves the promise returned by calling PaymentRequest.prototype.abort.
* This method also gets called when the request is aborted through rejecting
* the promise passed to PaymentRequestUpdateEvent.prototype.updateWith.
* Therefore, it does nothing if there is no abort promise to resolve.
*/
__gCrWeb['paymentRequestManager'].resolveAbortPromise = function() {
if (!__gCrWeb['paymentRequestManager'].abortPromiseResolver)
return;
__gCrWeb['paymentRequestManager'].abortPromiseResolver.resolve();
__gCrWeb['paymentRequestManager'].abortPromiseResolver = null;
};
/**
* Resolves the promise returned by calling canMakePayment on the current
* PaymentRequest.
* @param {boolean} value The response to provide to the resolve function of
* the Promise.
*/
__gCrWeb['paymentRequestManager'].resolveCanMakePaymentPromise = function(
value) {
if (!__gCrWeb['paymentRequestManager'].canMakePaymentPromiseResolver) {
throw new Error('Internal PaymentRequest error: No Promise to resolve.');
}
__gCrWeb['paymentRequestManager'].canMakePaymentPromiseResolver.resolve(
value);
__gCrWeb['paymentRequestManager'].canMakePaymentPromiseResolver = null;
};
/**
* Rejects the promise returned by calling canMakePayment on the current
* PaymentRequest.
* @param {string} message An error message explaining why the Promise is
* being rejected.
*/
__gCrWeb['paymentRequestManager'].rejectCanMakePaymentPromise = function(
message) {
if (!__gCrWeb['paymentRequestManager'].canMakePaymentPromiseResolver) {
throw new Error(
'Internal PaymentRequest error: No Promise to reject. ',
'Message was: ', message);
}
__gCrWeb['paymentRequestManager'].canMakePaymentPromiseResolver.reject(
message);
__gCrWeb['paymentRequestManager'].canMakePaymentPromiseResolver = null;
};
/**
* Serializes |paymentRequest| to a SerializedPaymentRequest object.
* @param {window.PaymentRequest} paymentRequest
* @return {SerializedPaymentRequest}
*/
__gCrWeb['paymentRequestManager'].serializePaymentRequest = function(
paymentRequest) {
var serialized = {
'id': paymentRequest.id,
'methodData': paymentRequest.methodData,
'details': paymentRequest.details,
};
if (paymentRequest.options)
serialized['options'] = paymentRequest.options;
return serialized;
};
/**
* Resolves the pending PaymentResponse.
*/
__gCrWeb['paymentRequestManager'].resolveResponsePromise = function() {
if (!__gCrWeb['paymentRequestManager'].responsePromiseResolver) {
throw new Error('Internal PaymentRequest error: No Promise to resolve.');
}
__gCrWeb['paymentRequestManager'].responsePromiseResolver.resolve();
__gCrWeb['paymentRequestManager'].responsePromiseResolver = null;
};
/**
* Updates the shipping_option property of the PaymentRequest object to
* |shippingOptionID| and dispatches a shippingoptionchange event.
* @param {string} shippingOptionID
*/
__gCrWeb['paymentRequestManager'].updateShippingOptionAndDispatchEvent =
function(shippingOptionID) {
if (!__gCrWeb['paymentRequestManager'].pendingRequest) {
__gCrWeb['paymentRequestManager'].rejectRequestPromise(
'Internal PaymentRequest error: No pending request.');
}
var pendingRequest = __gCrWeb['paymentRequestManager'].pendingRequest;
if (__gCrWeb['paymentRequestManager'].updateEvent) {
__gCrWeb['paymentRequestManager'].rejectRequestPromise(
'Internal PaymentRequest error: Only one update may take ' +
'place at a time.');
}
pendingRequest.shippingOption = shippingOptionID;
__gCrWeb['paymentRequestManager'].updateEvent = new Event(
'shippingoptionchange', {'bubbles': true, 'cancelable': false});
Object.defineProperty(__gCrWeb['paymentRequestManager'].updateEvent,
'updateWith', {value: __gCrWeb['paymentRequestManager'].updateWith});
// setTimeout() is used in order to return immediately. Otherwise the
// dispatchEvent call waits for all event handlers to return, which could
// cause a ReentryGuard failure.
window.setTimeout(function() {
pendingRequest.dispatchEvent(
__gCrWeb['paymentRequestManager'].updateEvent);
}, 0);
};
/**
* Updates the shipping_address property of the PaymentRequest object to
* |shippingAddress| and dispatches a shippingaddresschange event.
* @param {!window.PaymentAddress} shippingAddress
*/
__gCrWeb['paymentRequestManager'].updateShippingAddressAndDispatchEvent =
function(shippingAddress) {
if (!__gCrWeb['paymentRequestManager'].pendingRequest) {
__gCrWeb['paymentRequestManager'].rejectRequestPromise(
'Internal PaymentRequest error: No pending request.');
}
var pendingRequest = __gCrWeb['paymentRequestManager'].pendingRequest;
if (__gCrWeb['paymentRequestManager'].updateEvent) {
__gCrWeb['paymentRequestManager'].rejectRequestPromise(
'Internal PaymentRequest error: Only one update may take ' +
'place at a time.');
}
pendingRequest.shippingAddress = shippingAddress;
__gCrWeb['paymentRequestManager'].updateEvent = new Event(
'shippingaddresschange', {'bubbles': true, 'cancelable': false});
Object.defineProperty(__gCrWeb['paymentRequestManager'].updateEvent,
'updateWith', {value: __gCrWeb['paymentRequestManager'].updateWith});
// setTimeout() is used in order to return immediately. Otherwise the
// dispatchEvent call waits for all event handlers to return, which could
// cause a ReentryGuard failure.
window.setTimeout(function() {
pendingRequest.dispatchEvent(
__gCrWeb['paymentRequestManager'].updateEvent);
}, 0);
};
}()); // End of anonymous object
/**
* A request to make a payment.
* @param {!Array<!window.PaymentMethodData>} methodData Payment method
* identifiers for the payment methods that the web site accepts and any
* associated payment method specific data.
* @param {!window.PaymentDetails} details Information about the transaction
* that the user is being asked to complete such as the line items in an
* order.
* @param {window.PaymentOptions=} opt_options Information about what
* options the web page wishes to use from the payment request system.
* @constructor
* @implements {EventTarget}
* @extends {__gCrWeb.EventTarget}
*/
window.PaymentRequest = function(methodData, details, opt_options) {
__gCrWeb.EventTarget.call(this);
if (window.top != window.self) {
throw new Error(
'PaymentRequest can only be used in the top-level context.');
}
if (methodData.length == 0)
throw new Error('The length of the methodData parameter must be > 0.');
for (var i = 0; i < methodData.length; i++) {
if (methodData[i].supportedMethods.length == 0)
throw new Error(
'The length of the supportedMethods parameter must be > 0.');
}
// TODO(crbug.com/602666): Perform other validation per spec.
// TODO(crbug.com/602666): Process payment methods then set parsedMethodData
// instead of methodData on this instance.
// /**
// * @type {!Object<!Array<string>, ?string>}
// * @private
// */
// this.parsedMethodData = ...;
/**
* @type {!Array<!window.PaymentMethodData>}
* @private
*/
this.methodData = methodData;
/**
* @type {!window.PaymentDetails}
* @private
*/
this.details = details;
/**
* @type {?window.PaymentOptions}
* @private
*/
this.options = opt_options || null;
/**
* The state of this request, used to govern its lifecycle.
* TODO(crbug.com/602666): Implement state transitions per spec.
* @type {string}
* @private
*/
this.state = 'created';
/**
* True if there is a pending updateWith call to update the payment request
* and false otherwise.
* TODO(crbug.com/602666): Implement changes in the value of this property per
* spec.
* @type {boolean}
* @private
*/
this.updating = false;
/**
* A provided or generated ID for the this Payment Request instance.
* @type {string}
*/
this.id = details.id ? details.id : __gCrWeb['paymentRequestManager'].guid();
/**
* Shipping address selected by the user.
* @type {?window.PaymentAddress}
*/
this.shippingAddress = null;
/**
* Shipping option selected by the user.
* @type {?string}
*/
this.shippingOption = null;
/**
* Set to the value of shippingType property of |opt_options| if it is a valid
* PaymentShippingType. Otherwise set to PaymentShippingType.SHIPPING.
* @type {?PaymentShippingType}
*/
this.shippingType = null;
if (opt_options && opt_options.requestShipping) {
if (opt_options.shippingType != PaymentShippingType.SHIPPING &&
opt_options.shippingType != PaymentShippingType.DELIVERY &&
opt_options.shippingType != PaymentShippingType.PICKUP) {
this.shippingType = PaymentShippingType.SHIPPING;
}
}
var message = {
'command': 'paymentRequest.createPaymentRequest',
'payment_request':
__gCrWeb['paymentRequestManager'].serializePaymentRequest(this),
};
__gCrWeb.message.invokeOnHost(message);
};
window.PaymentRequest.prototype = {
__proto__: __gCrWeb.EventTarget.prototype
};
/**
* Presents the PaymentRequest UI to the user.
* @return {!Promise<window.PaymentResponse>} A promise to notify the caller
* whether the user accepted or rejected the request.
*/
window.PaymentRequest.prototype.show = function() {
if (__gCrWeb['paymentRequestManager'].pendingRequest) {
throw new Error('Only one PaymentRequest may be shown at a time.');
}
__gCrWeb['paymentRequestManager'].pendingRequest = this;
var message = {
'command': 'paymentRequest.requestShow',
'payment_request':
__gCrWeb['paymentRequestManager'].serializePaymentRequest(this),
};
__gCrWeb.message.invokeOnHost(message);
__gCrWeb['paymentRequestManager'].requestPromiseResolver =
new __gCrWeb.PromiseResolver();
return __gCrWeb['paymentRequestManager'].requestPromiseResolver.promise;
};
/**
* May be called if the web page wishes to tell the user agent to abort the
* payment request and to tear down any user interface that might be shown.
* @return {!Promise<undefined>} A promise to notify the caller whether the user
* agent was able to abort the payment request.
*/
window.PaymentRequest.prototype.abort = function() {
if (!__gCrWeb['paymentRequestManager'].pendingRequest) {
__gCrWeb['paymentRequestManager'].rejectRequestPromise(
'Internal PaymentRequest error: No pending request.');
}
var message = {
'command': 'paymentRequest.requestAbort',
};
__gCrWeb.message.invokeOnHost(message);
__gCrWeb['paymentRequestManager'].abortPromiseResolver =
new __gCrWeb.PromiseResolver();
return __gCrWeb['paymentRequestManager'].abortPromiseResolver.promise;
};
/**
* May be called before calling show() to determine if the PaymentRequest object
* can be used to make a payment.
* @return {!Promise<boolean>} A promise to notify the caller whether the
* PaymentRequest object can be used to make a payment.
*/
window.PaymentRequest.prototype.canMakePayment = function() {
// TODO(crbug.com/602666): return a promise rejected with InvalidStateError if
// |this.state| != 'created'.
var message = {
'command': 'paymentRequest.requestCanMakePayment',
'payment_request':
__gCrWeb['paymentRequestManager'].serializePaymentRequest(this),
};
__gCrWeb.message.invokeOnHost(message);
__gCrWeb['paymentRequestManager'].canMakePaymentPromiseResolver =
new __gCrWeb.PromiseResolver();
return __gCrWeb['paymentRequestManager'].canMakePaymentPromiseResolver
.promise;
};
/**
* @typedef {{
* supportedMethods: !Array<string>,
* data: (Object|undefined)
* }}
*/
window.PaymentMethodData;
/**
* @typedef {{
* currency: string,
* value: string,
* currencySystem: (string|undefined)
* }}
*/
window.PaymentCurrencyAmount;
/**
* @typedef {{
* id: (string|undefined),
* total: (window.PaymentItem|undefined),
* displayItems: (!Array<!window.PaymentItem>|undefined),
* shippingOptions: (!Array<!window.PaymentShippingOption>|undefined),
* modifiers: (!Array<!window.PaymentDetailsModifier>|undefined),
* error: (string|undefined)
* }}
*/
window.PaymentDetails;
/**
* @typedef {{
* supportedMethods: !Array<string>,
* total: (window.PaymentItem|undefined),
* additionalDisplayItems: (!Array<!window.PaymentItem>|undefined)
* }}
*/
window.PaymentDetailsModifier;
/**
* Contains the possible values for affecting the payment request user interface
* for gathering the shipping address if window.PaymentOptions.requestShipping
* is set to true.
* @enum {string}
*/
var PaymentShippingType = {
SHIPPING: 'shipping',
DELIVERY: 'delivery',
PICKUP: 'pickup'
};
/**
* @typedef {{
* requestPayerName: (boolean|undefined),
* requestPayerEmail: (boolean|undefined),
* requestPayerPhone: (boolean|undefined),
* requestShipping: (boolean|undefined),
* shippingType: (!PaymentShippingType|undefined)
* }}
*/
window.PaymentOptions;
/**
* @typedef {{
* label: string,
* amount: window.PaymentCurrencyAmount
* }}
*/
window.PaymentItem;
/**
* @typedef {{
* country: string,
* addressLine: !Array<string>,
* region: string,
* city: string,
* dependentLocality: string,
* postalCode: string,
* sortingCode: string,
* languageCode: string,
* organization: string,
* recipient: string,
* phone: string
* }}
*/
window.PaymentAddress;
/**
* @typedef {{
* id: string,
* label: string,
* amount: window.PaymentCurrencyAmount,
* selected: boolean
* }}
*/
window.PaymentShippingOption;
/**
* A response to a request to make a payment. Represents the choices made by the
* user and provided to the web page through the resolve function of the Promise
* returned by PaymentRequest.show().
* https://w3c.github.io/browser-payment-api/#paymentresponse-interface
* @param {string} methodName
* @param {Object} details
* @constructor
* @private
*/
window.PaymentResponse = function(requestId, methodName, details) {
/**
* The same identifier present in the original window.PaymentRequest.
* @type {string}
*/
this.requestId = requestId;
/**
* The payment method identifier for the payment method that the user selected
* to fulfil the transaction.
* @type {string}
*/
this.methodName = methodName;
/**
* An object that provides a payment method specific message used by the
* merchant to process the transaction and determine successful fund transfer.
* the payment request.
* @type {Object}
*/
this.details = details;
/**
* If the requestShipping flag was set to true in the window.PaymentOptions
* passed to the window.PaymentRequest constructor, this will be the full and
* final shipping address chosen by the user.
* @type {?window.PaymentAddress}
*/
this.shippingAddress = null;
/**
* If the requestShipping flag was set to true in the window.PaymentOptions
* passed to the window.PaymentRequest constructor, this will be the id
* attribute of the selected shipping option.
* @type {?string}
*/
this.shippingOption = null;
/**
* If the requestPayerName flag was set to true in the window.PaymentOptions
* passed to the window.PaymentRequest constructor, this will be the name
* provided by the user.
* @type {?string}
*/
this.payerName = null;
/**
* If the requestPayerEmail flag was set to true in the window.PaymentOptions
* passed to the window.PaymentRequest constructor, this will be the email
* address chosen by the user.
* @type {?string}
*/
this.payerEmail = null;
/**
* If the requestPayerPhone flag was set to true in the window.PaymentOptions
* passed to the window.PaymentRequest constructor, this will be the phone
* number chosen by the user.
* @type {?string}
*/
this.payerPhone = null;
};
/**
* Contains the possible values for the string argument accepted by
* window.PaymentResponse.prototype.complete.
* @enum {string}
*/
var PaymentComplete = {
SUCCESS: 'success',
FAIL: 'fail',
UNKNOWN: 'unknown'
};
/**
* Communicates the result of processing the payment.
* @param {PaymentComplete=} opt_result Indicates whether payment was
* successfully processed.
* @return {!Promise} A promise to notify the caller when the user interface has
* been closed.
*/
window.PaymentResponse.prototype.complete = function(opt_result) {
if (opt_result != PaymentComplete.UNKNOWN &&
opt_result != PaymentComplete.SUCCESS &&
opt_result != PaymentComplete.FAIL) {
opt_result = PaymentComplete.UNKNOWN;
}
if (!__gCrWeb['paymentRequestManager'].responsePromiseResolver) {
throw new Error('Internal PaymentRequest error: No Promise to return.');
}
var message = {
'command': 'paymentRequest.responseComplete',
'result': opt_result,
};
__gCrWeb.message.invokeOnHost(message);
return __gCrWeb['paymentRequestManager'].responsePromiseResolver.promise;
};