'use strict';
var analytics = require('../lib/analytics');
var assign = require('../lib/assign').assign;
var convertMethodsToError = require('../lib/convert-methods-to-error');
var generateGooglePayConfiguration = require('../lib/generate-google-pay-configuration');
var BraintreeError = require('../lib/braintree-error');
var errors = require('./errors');
var methods = require('../lib/methods');
var Promise = require('../lib/promise');
var wrapPromise = require('@braintree/wrap-promise');
/**
* @typedef {object} GooglePayment~tokenizePayload
* @property {string} nonce The payment method nonce.
* @property {object} details Additional account details.
* @property {string} details.cardType Type of card, ex: Visa, MasterCard.
* @property {string} details.lastFour Last four digits of card number.
* @property {string} details.lastTwo Last two digits of card number.
* @property {string} description A human-readable description.
* @property {string} type The payment method type, `CreditCard` or `AndroidPayCard`.
* @property {object} binData Information about the card based on the bin.
* @property {string} binData.commercial Possible values: 'Yes', 'No', 'Unknown'.
* @property {string} binData.countryOfIssuance The country of issuance.
* @property {string} binData.debit Possible values: 'Yes', 'No', 'Unknown'.
* @property {string} binData.durbinRegulated Possible values: 'Yes', 'No', 'Unknown'.
* @property {string} binData.healthcare Possible values: 'Yes', 'No', 'Unknown'.
* @property {string} binData.issuingBank The issuing bank.
* @property {string} binData.payroll Possible values: 'Yes', 'No', 'Unknown'.
* @property {string} binData.prepaid Possible values: 'Yes', 'No', 'Unknown'.
* @property {string} binData.productId The product id.
*/
/**
* @class GooglePayment
* @param {object} options Google Payment {@link module:braintree-web/google-payment.create create} options.
* @description <strong>Do not use this constructor directly. Use {@link module:braintree-web/google-payment.create|braintree-web.google-payment.create} instead.</strong>
* @classdesc This class represents a Google Payment component produced by {@link module:braintree-web/google-payment.create|braintree-web/google-payment.create}. Instances of this class have methods for initializing the Google Pay flow.
*/
function GooglePayment(options) {
this._client = options.client;
this._braintreeGeneratedPaymentRequestConfiguration = generateGooglePayConfiguration(this._client.getConfiguration());
}
/**
* Create a configuration object for use in the `loadPaymentData` method.
* @public
* @param {object} overrides The supplied parameters for creating the PaymentDataRequest object. Only required parameters are the `merchantId` provided by Google and a `transactionInfo` object, but any of the parameters in the PaymentDataRequest can be overwritten. See https://developers.google.com/pay/api/web/reference/object#PaymentDataRequest
* @param {string} merchantId The merchant id provided by registering with Google.
* @param {object} transactionInfo See https://developers.google.com/pay/api/web/reference/object#TransactionInfo for more information.
* @example
* var configuration = googlePaymentInstance.createPaymentDataRequest({
* merchantId: 'my-merchant-id-from-google',
* transactionInfo: {
* currencyCode: 'USD',
* totalPriceStatus: 'FINAL',
* totalPrice: '100.00'
* }
* });
* var paymentsClient = new google.payments.api.PaymentsClient({
* environment: 'TEST' // or 'PRODUCTION'
* })
*
* paymentsClient.loadPaymentData(paymentDataRequest).then(function (response) {
* // handle response with googlePaymentInstance.parseResponse
* // (see below)
* });
* @returns {object} Returns a configuration object for Google PaymentDataRequest.
*/
GooglePayment.prototype.createPaymentDataRequest = function (overrides) {
var overrideCardNetworks = overrides && overrides.cardRequirements && overrides.cardRequirements.allowedCardNetworks;
var defaultCardNetworks = this._braintreeGeneratedPaymentRequestConfiguration.cardRequirements.allowedCardNetworks;
var allowedCardNetworks = overrideCardNetworks || defaultCardNetworks;
var paymentDataRequest = assign({}, this._braintreeGeneratedPaymentRequestConfiguration, overrides);
// this way we can preserve allowedCardNetworks from default integration
// if merchant did not pass any in `cardRequirements`
paymentDataRequest.cardRequirements.allowedCardNetworks = allowedCardNetworks;
analytics.sendEvent(this._client, 'google-payment.createPaymentDataRequest');
return paymentDataRequest;
};
/**
* Parse the response from the tokenization.
* @public
* @param {object} response The response back from the Google Pay tokenization.
* @param {callback} [callback] The second argument, <code>data</code>, is a {@link GooglePay~tokenizePayload|tokenizePayload}. If no callback is provided, `parseResponse` returns a promise that resolves with a {@link GooglePayment~tokenizePayload|tokenizePayload}.
* @example with callback
* var paymentsClient = new google.payments.api.PaymentsClient({
* environment: 'TEST' // or 'PRODUCTION'
* })
*
* paymentsClient.loadPaymentData(paymentDataRequestFromCreatePaymentDataRequest).then(function (response) {
* googlePaymentInstance.parseResponse(response, function (err, data) {
* if (err) {
* // handle errors
* }
* // send parsedResponse.nonce to your server
* });
* });
* @example with promise
* var paymentsClient = new google.payments.api.PaymentsClient({
* environment: 'TEST' // or 'PRODUCTION'
* })
*
* paymentsClient.loadPaymentData(paymentDataRequestFromCreatePaymentDataRequest).then(function (response) {
* return googlePaymentInstance.parseResponse(response);
* }).then(function (parsedResponse) {
* // send parsedResponse.nonce to your server
* }).catch(function (err) {
* // handle errors
* });
* @returns {Promise|void} Returns a promise that resolves the parsed response if no callback is provided.
*/
GooglePayment.prototype.parseResponse = function (response) {
var client = this._client;
return Promise.resolve().then(function () {
var payload;
var parsedResponse = JSON.parse(response.paymentMethodToken.token);
var error = parsedResponse.error;
if (error) {
return Promise.reject(error);
}
payload = parsedResponse.androidPayCards[0];
analytics.sendEvent(client, 'google-payment.parseResponse.succeeded');
return Promise.resolve({
nonce: payload.nonce,
type: payload.type,
description: payload.description,
details: {
cardType: payload.details.cardType,
lastFour: payload.details.lastFour,
lastTwo: payload.details.lastTwo
},
binData: payload.binData
});
}).catch(function (error) {
analytics.sendEvent(client, 'google-payment.parseResponse.failed');
return Promise.reject(new BraintreeError({
code: errors.GOOGLE_PAYMENT_GATEWAY_ERROR.code,
message: errors.GOOGLE_PAYMENT_GATEWAY_ERROR.message,
type: errors.GOOGLE_PAYMENT_GATEWAY_ERROR.type,
details: {
originalError: error
}
}));
});
};
/**
* Cleanly tear down anything set up by {@link module:braintree-web/google-payment.create|create}.
* @public
* @param {callback} [callback] Called once teardown is complete. No data is returned if teardown completes successfully.
* @example
* googlePaymentInstance.teardown();
* @example <caption>With callback</caption>
* googlePaymentInstance.teardown(function () {
* // teardown is complete
* });
* @returns {Promise|void} Returns a promise if no callback is provided.
*/
GooglePayment.prototype.teardown = function () {
convertMethodsToError(this, methods(GooglePayment.prototype));
return Promise.resolve();
};
module.exports = wrapPromise.wrapPrototype(GooglePayment);