From 2173d38fe8fde2726387de5fde645b584016912b Mon Sep 17 00:00:00 2001 From: Tom Collins Date: Wed, 2 Sep 2020 14:16:15 +1000 Subject: [PATCH 1/8] CH16478 add BraintreePaypalShopPaymentMethod --- .../payment_methods/shop_payment_methods.js | 4 +- .../braintree_paypal_shop_payment_method.js | 155 ++++++++++++++++++ 2 files changed, 158 insertions(+), 1 deletion(-) create mode 100644 src/checkout/payment_methods/shop_payment_methods/braintree_paypal_shop_payment_method.js diff --git a/src/checkout/payment_methods/shop_payment_methods.js b/src/checkout/payment_methods/shop_payment_methods.js index b48e3cb..1e3bef7 100644 --- a/src/checkout/payment_methods/shop_payment_methods.js +++ b/src/checkout/payment_methods/shop_payment_methods.js @@ -1,6 +1,7 @@ import { ShopPaymentMethod } from './shop_payment_methods/shop_payment_method'; import { BraintreeCreditCardShopPaymentMethod } from './shop_payment_methods/braintree_credit_card_shop_payment_method'; import { BraintreeApplePayShopPaymentMethod } from './shop_payment_methods/braintree_apple_pay_shop_payment_method'; +import { BraintreePaypalShopPaymentMethod } from './shop_payment_methods/braintree_paypal_shop_payment_method'; import { CybersourceCreditCardShopPaymentMethod } from './shop_payment_methods/cybersource_credit_card_shop_payment_method'; import { StripeCreditCardShopPaymentMethod } from './shop_payment_methods/stripe_credit_card_shop_payment_method'; import { KomojuCreditCardShopPaymentMethod } from './shop_payment_methods/komoju_credit_card_payment_method'; @@ -9,7 +10,8 @@ import { SubmarineBankTransferShopPaymentMethod } from './shop_payment_methods/s const SHOP_PAYMENT_METHODS = { braintree: { 'credit-card': BraintreeCreditCardShopPaymentMethod, - 'apple-pay': BraintreeApplePayShopPaymentMethod + 'apple-pay': BraintreeApplePayShopPaymentMethod, + 'paypal': BraintreePaypalShopPaymentMethod }, cybersource: { 'credit-card': CybersourceCreditCardShopPaymentMethod diff --git a/src/checkout/payment_methods/shop_payment_methods/braintree_paypal_shop_payment_method.js b/src/checkout/payment_methods/shop_payment_methods/braintree_paypal_shop_payment_method.js new file mode 100644 index 0000000..88f276c --- /dev/null +++ b/src/checkout/payment_methods/shop_payment_methods/braintree_paypal_shop_payment_method.js @@ -0,0 +1,155 @@ +import { ShopPaymentMethod } from './shop_payment_method'; + +export class BraintreePaypalShopPaymentMethod extends ShopPaymentMethod { + + setup() { + const that = this; + + this.deviceData = null; + this.paypalButtonReady = false; + this.billingAgreementNonce = null; + + this.$container = this.$('#braintree-paypal-container'); + this.$message = this.$container.find('.braintree-paypal-message'); + + submarine.api.generatePaymentProcessorClientToken('braintree', (client_token) => { + braintree.client.create({ + authorization: client_token.attributes.token + }, (error, clientInstance) => { + that.clientInstance = clientInstance; + + braintree.dataCollector.create({ + client: clientInstance, + paypal: true + }, (error, dataCollectorInstance) => { + that.deviceData = dataCollectorInstance.deviceData; + }); + + braintree.paypalCheckout.create({ + client: clientInstance + }, (error, paypalCheckoutInstance) => { + that.paypalCheckoutInstance = paypalCheckoutInstance; + window.paypalCheckoutInstance = paypalCheckoutInstance; + + paypalCheckoutInstance.loadPayPalSDK({ + vault: true + }, (error) => { + paypal.Buttons({ + fundingSource: paypal.FUNDING.PAYPAL, + createBillingAgreement: that.createBillingAgreement.bind(that), + onApprove: that.onApprove.bind(that), + onCancel: that.onCancel.bind(that), + onError: that.onError.bind(that) + }).render('#braintree-paypal-mount').then(() => { + that.paypalButtonReady = true; + }); + }); + }); + }); + }); + } + + createBillingAgreement() { + const that = this; + + this.setError(); + + return this.paypalCheckoutInstance.createPayment({ + flow: 'vault', + billingAgreementDescription: that.options.translations.billing_agreement_description, + enableShippingAddress: true, + shippingAddressEditable: false, + shippingAddressOverride: { + recipientName: that.options.shipping_address.name, + line1: that.options.shipping_address.address1, + line2: that.options.shipping_address.address2, + city: that.options.shipping_address.city, + countryCode: that.options.shipping_address.country_code, + postalCode: that.options.shipping_address.zip, + state: that.options.shipping_address.province_code, + phone: that.options.shipping_address.phone + } + }); + } + + onApprove(data, actions) { + const that = this; + + return this.paypalCheckoutInstance.tokenizePayment(data, (error, payload) => { + if (error) { + that.setError(this.options.translations.paypal_error_unknown); + return; + } + + that.setSuccess(); + that.billingAgreementNonce = payload.nonce; + }); + } + + onCancel(data) { + this.billingAgreementNonce = null; + } + + onError(error) { + this.billingAgreementNonce = null; + this.setError(this.options.translations.paypal_error_unknown); + } + + validate() { + if (!this.paypalButtonReady) { + return [this.setError(this.options.translations.paypal_error_not_ready)]; + } + + if (!this.billingAgreementNonce) { + return [this.setError(this.options.translations.paypal_error_not_approved)]; + } + + return []; + } + + setError(message) { + this.$container.removeClass('braintree-paypal--has-success'); + this.$container.toggleClass('braintree-paypal--has-error', !!message); + this.$message.text(message || this.options.translations.paypal_instructions); + return message; + } + + setSuccess() { + this.$container.removeClass('braintree-paypal--has-error'); + this.$container.addClass('braintree-paypal--has-success'); + this.$message.text(this.options.translations.paypal_success); + } + + process(callbacks) { + const that = this; + + setTimeout(() => { + if (!that.billingAgreementNonce) { + callbacks.error({ + message: that.setError(this.options.translations.paypal_error_not_approved) + }); + } else { + callbacks.success({ + customer_payment_method_id: null, + payment_nonce: that.billingAgreementNonce, + payment_method_type: 'paypal', + payment_processor: 'braintree', + additional_data: { + deviceData: that.deviceData + } + }); + } + }, 1); + } + + getRenderContext(html_templates) { + return { + id: this.data.id, + title: 'Paypal', + // subfields_content: renderHtmlTemplate({}, 'braintree_paypal_subfields_content', html_templates), + subfields_content: this.options.html_templates.braintree_paypal_subfields_content, + icons: 'icons_paypal' + } + } + +} From 566cbabf203725dc8a7788eca81a7b1995e9f47e Mon Sep 17 00:00:00 2001 From: Tom Collins Date: Wed, 2 Sep 2020 18:33:47 +1000 Subject: [PATCH 2/8] CH16478 re-arrange paypal translations --- .../braintree_paypal_shop_payment_method.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/checkout/payment_methods/shop_payment_methods/braintree_paypal_shop_payment_method.js b/src/checkout/payment_methods/shop_payment_methods/braintree_paypal_shop_payment_method.js index 88f276c..9281094 100644 --- a/src/checkout/payment_methods/shop_payment_methods/braintree_paypal_shop_payment_method.js +++ b/src/checkout/payment_methods/shop_payment_methods/braintree_paypal_shop_payment_method.js @@ -77,7 +77,7 @@ export class BraintreePaypalShopPaymentMethod extends ShopPaymentMethod { return this.paypalCheckoutInstance.tokenizePayment(data, (error, payload) => { if (error) { - that.setError(this.options.translations.paypal_error_unknown); + that.setError(this.translations.payment_methods.shop_payment_methods.paypal_error_unknown); return; } @@ -92,16 +92,16 @@ export class BraintreePaypalShopPaymentMethod extends ShopPaymentMethod { onError(error) { this.billingAgreementNonce = null; - this.setError(this.options.translations.paypal_error_unknown); + this.setError(this.translations.payment_methods.shop_payment_methods.paypal_error_unknown); } validate() { if (!this.paypalButtonReady) { - return [this.setError(this.options.translations.paypal_error_not_ready)]; + return [this.setError(this.translations.payment_methods.shop_payment_methods.paypal_error_not_ready)]; } if (!this.billingAgreementNonce) { - return [this.setError(this.options.translations.paypal_error_not_approved)]; + return [this.setError(this.translations.payment_methods.shop_payment_methods.paypal_error_not_approved)]; } return []; @@ -110,14 +110,14 @@ export class BraintreePaypalShopPaymentMethod extends ShopPaymentMethod { setError(message) { this.$container.removeClass('braintree-paypal--has-success'); this.$container.toggleClass('braintree-paypal--has-error', !!message); - this.$message.text(message || this.options.translations.paypal_instructions); + this.$message.text(message || this.translations.payment_methods.shop_payment_methods.paypal.paypal_instructions); return message; } setSuccess() { this.$container.removeClass('braintree-paypal--has-error'); this.$container.addClass('braintree-paypal--has-success'); - this.$message.text(this.options.translations.paypal_success); + this.$message.text(this.translations.payment_methods.shop_payment_methods.paypal_success); } process(callbacks) { From 68ae1a30a52ce8a5360b8435a53b30927d821ef8 Mon Sep 17 00:00:00 2001 From: Tom Collins Date: Wed, 2 Sep 2020 18:34:42 +1000 Subject: [PATCH 3/8] CH16478 tweak to how shipping address is referenced in braintree paypal --- .../braintree_paypal_shop_payment_method.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/checkout/payment_methods/shop_payment_methods/braintree_paypal_shop_payment_method.js b/src/checkout/payment_methods/shop_payment_methods/braintree_paypal_shop_payment_method.js index 9281094..68836ac 100644 --- a/src/checkout/payment_methods/shop_payment_methods/braintree_paypal_shop_payment_method.js +++ b/src/checkout/payment_methods/shop_payment_methods/braintree_paypal_shop_payment_method.js @@ -56,18 +56,18 @@ export class BraintreePaypalShopPaymentMethod extends ShopPaymentMethod { return this.paypalCheckoutInstance.createPayment({ flow: 'vault', - billingAgreementDescription: that.options.translations.billing_agreement_description, + billingAgreementDescription: that.translations.payment_methods.shop_payment_methods.paypal.paypal_billing_agreement_description, enableShippingAddress: true, shippingAddressEditable: false, shippingAddressOverride: { - recipientName: that.options.shipping_address.name, - line1: that.options.shipping_address.address1, - line2: that.options.shipping_address.address2, - city: that.options.shipping_address.city, - countryCode: that.options.shipping_address.country_code, - postalCode: that.options.shipping_address.zip, - state: that.options.shipping_address.province_code, - phone: that.options.shipping_address.phone + recipientName: that.options.checkout.shipping_address.name, + line1: that.options.checkout.shipping_address.address1, + line2: that.options.checkout.shipping_address.address2, + city: that.options.checkout.shipping_address.city, + countryCode: that.options.checkout.shipping_address.country_code, + postalCode: that.options.checkout.shipping_address.zip, + state: that.options.checkout.shipping_address.province_code, + phone: that.options.checkout.shipping_address.phone } }); } From 5b82c3245c63daec89c38a2d19d858aa79605933 Mon Sep 17 00:00:00 2001 From: Tom Collins Date: Thu, 3 Sep 2020 12:27:59 +1000 Subject: [PATCH 4/8] CH16478 implement before setup --- .../braintree_paypal_shop_payment_method.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/checkout/payment_methods/shop_payment_methods/braintree_paypal_shop_payment_method.js b/src/checkout/payment_methods/shop_payment_methods/braintree_paypal_shop_payment_method.js index 68836ac..a304e32 100644 --- a/src/checkout/payment_methods/shop_payment_methods/braintree_paypal_shop_payment_method.js +++ b/src/checkout/payment_methods/shop_payment_methods/braintree_paypal_shop_payment_method.js @@ -2,7 +2,13 @@ import { ShopPaymentMethod } from './shop_payment_method'; export class BraintreePaypalShopPaymentMethod extends ShopPaymentMethod { - setup() { + beforeSetup() { + this.$subfields = this.$( + `[data-subfields-for-payment-method="shop_payment_method_${this.data.id}"]` + ); + } + + setup(success, failure) { const that = this; this.deviceData = null; From defcd75eb0ca593f2405808cf2f5b66ac0e461c5 Mon Sep 17 00:00:00 2001 From: Tom Collins Date: Thu, 3 Sep 2020 12:29:01 +1000 Subject: [PATCH 5/8] CH16478 structure setup method correctly --- .../braintree_paypal_shop_payment_method.js | 74 +++++++++++-------- 1 file changed, 43 insertions(+), 31 deletions(-) diff --git a/src/checkout/payment_methods/shop_payment_methods/braintree_paypal_shop_payment_method.js b/src/checkout/payment_methods/shop_payment_methods/braintree_paypal_shop_payment_method.js index a304e32..0595e8c 100644 --- a/src/checkout/payment_methods/shop_payment_methods/braintree_paypal_shop_payment_method.js +++ b/src/checkout/payment_methods/shop_payment_methods/braintree_paypal_shop_payment_method.js @@ -18,41 +18,53 @@ export class BraintreePaypalShopPaymentMethod extends ShopPaymentMethod { this.$container = this.$('#braintree-paypal-container'); this.$message = this.$container.find('.braintree-paypal-message'); - submarine.api.generatePaymentProcessorClientToken('braintree', (client_token) => { - braintree.client.create({ - authorization: client_token.attributes.token - }, (error, clientInstance) => { - that.clientInstance = clientInstance; - - braintree.dataCollector.create({ - client: clientInstance, - paypal: true - }, (error, dataCollectorInstance) => { - that.deviceData = dataCollectorInstance.deviceData; - }); + // Start by generating a Braintree client token. + submarine.api // eslint-disable-line no-undef + .generatePaymentProcessorClientToken('braintree', client_token => { + // Then, create a Braintree client instance. + braintree.client // eslint-disable-line no-undef + .create({ + authorization: client_token.attributes.token + }) + .then(clientInstance => { + that.clientInstance = clientInstance; + + braintree.dataCollector.create({ + client: clientInstance, + paypal: true + }).then(dataCollectorInstance => { + that.deviceData = dataCollectorInstance.deviceData; + }); - braintree.paypalCheckout.create({ - client: clientInstance - }, (error, paypalCheckoutInstance) => { - that.paypalCheckoutInstance = paypalCheckoutInstance; - window.paypalCheckoutInstance = paypalCheckoutInstance; - - paypalCheckoutInstance.loadPayPalSDK({ - vault: true - }, (error) => { - paypal.Buttons({ - fundingSource: paypal.FUNDING.PAYPAL, - createBillingAgreement: that.createBillingAgreement.bind(that), - onApprove: that.onApprove.bind(that), - onCancel: that.onCancel.bind(that), - onError: that.onError.bind(that) - }).render('#braintree-paypal-mount').then(() => { - that.paypalButtonReady = true; + braintree.paypalCheckout.create({ + client: clientInstance + }).then(paypalCheckoutInstance => { + that.paypalCheckoutInstance = paypalCheckoutInstance; + window.paypalCheckoutInstance = paypalCheckoutInstance; + + paypalCheckoutInstance.loadPayPalSDK({ + vault: true + }, (error) => { + paypal.Buttons({ + fundingSource: paypal.FUNDING.PAYPAL, + createBillingAgreement: that.createBillingAgreement.bind(that), + onApprove: that.onApprove.bind(that), + onCancel: that.onCancel.bind(that), + onError: that.onError.bind(that) + }).render('#braintree-paypal-mount').then(() => { + that.paypalButtonReady = true; + success(); + }); + }); }); + }) + .catch(error => { + failure(error); }); - }); + }) + .catch(error => { + failure(error); }); - }); } createBillingAgreement() { From 1c9877ede12d3b8e3f469eb9089d186bfd6dbe0a Mon Sep 17 00:00:00 2001 From: Tom Collins Date: Thu, 3 Sep 2020 12:29:47 +1000 Subject: [PATCH 6/8] CH16478 structure process method correctly --- .../braintree_paypal_shop_payment_method.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/checkout/payment_methods/shop_payment_methods/braintree_paypal_shop_payment_method.js b/src/checkout/payment_methods/shop_payment_methods/braintree_paypal_shop_payment_method.js index 0595e8c..113ee3b 100644 --- a/src/checkout/payment_methods/shop_payment_methods/braintree_paypal_shop_payment_method.js +++ b/src/checkout/payment_methods/shop_payment_methods/braintree_paypal_shop_payment_method.js @@ -138,16 +138,16 @@ export class BraintreePaypalShopPaymentMethod extends ShopPaymentMethod { this.$message.text(this.translations.payment_methods.shop_payment_methods.paypal_success); } - process(callbacks) { + process(success, error) { const that = this; setTimeout(() => { if (!that.billingAgreementNonce) { - callbacks.error({ - message: that.setError(this.options.translations.paypal_error_not_approved) - }); + error(this.options.translations.paypal_error_not_approved); + return; } else { - callbacks.success({ + success({ + shop_payment_method_id: this.data.id, customer_payment_method_id: null, payment_nonce: that.billingAgreementNonce, payment_method_type: 'paypal', From 7f04008070b4be0dc73f062bc143372661395dca Mon Sep 17 00:00:00 2001 From: Tom Collins Date: Thu, 3 Sep 2020 12:30:12 +1000 Subject: [PATCH 7/8] CH16478 fix render context --- .../braintree_paypal_shop_payment_method.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/checkout/payment_methods/shop_payment_methods/braintree_paypal_shop_payment_method.js b/src/checkout/payment_methods/shop_payment_methods/braintree_paypal_shop_payment_method.js index 113ee3b..fa9476c 100644 --- a/src/checkout/payment_methods/shop_payment_methods/braintree_paypal_shop_payment_method.js +++ b/src/checkout/payment_methods/shop_payment_methods/braintree_paypal_shop_payment_method.js @@ -157,17 +157,17 @@ export class BraintreePaypalShopPaymentMethod extends ShopPaymentMethod { } }); } - }, 1); + }); } - getRenderContext(html_templates) { + getRenderContext() { return { id: this.data.id, title: 'Paypal', - // subfields_content: renderHtmlTemplate({}, 'braintree_paypal_subfields_content', html_templates), + value: this.getValue(), subfields_content: this.options.html_templates.braintree_paypal_subfields_content, - icons: 'icons_paypal' - } + icon: 'icons_paypal' + }; } } From 3219197a0ce36f70450dc97912cee229a2292f6f Mon Sep 17 00:00:00 2001 From: Tom Collins Date: Fri, 11 Sep 2020 10:15:39 +1000 Subject: [PATCH 8/8] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 45612e3..d74c084 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@discolabs/submarine-js", - "version": "0.2.2", + "version": "0.3.0", "description": "Javascript client library for Submarine.", "main": "index.js", "author": "Gavin Ballard",