Просмотр исходного кода

Merge pull request #2015 from overleaf/ta-recurly-upgrade

Upgrade Recurly

GitOrigin-RevId: 9a7c4804d2fafa31ea634498359dbfd95416b2ae
Timothée Alby 7 лет назад
Родитель
Сommit
b9ab0edf69

+ 2 - 1
services/web/app/src/Features/Subscription/RecurlyWrapper.js

@@ -415,7 +415,8 @@ module.exports = RecurlyWrapper = {
         'base64'
       )}`,
       Accept: 'application/xml',
-      'Content-Type': 'application/xml; charset=utf-8'
+      'Content-Type': 'application/xml; charset=utf-8',
+      'X-Api-Version': Settings.apis.recurly.apiVersion
     }
     const { expect404 } = options
     delete options.expect404

+ 24 - 20
services/web/app/views/layout.pug

@@ -117,29 +117,33 @@ html(
 			include scribtex-modal
 
 		block requirejs
-			script(type='text/javascript').
-				// minimal requirejs configuration (can be extended/overridden)
-				window.requirejs = {
-					"paths" : {
-						"moment": "libs/#{lib('moment')}",
-						"fineuploader": "libs/#{lib('fineuploader')}",
-						"main": "#{buildJsPath('main.js', {hashedPath:settings.useMinifiedJs, removeExtension:true})}",
-						"libraries": "#{buildJsPath('libraries.js', {hashedPath:settings.useMinifiedJs, removeExtension:true})}",
-					},
-					"config":{
-						"moment":{
-							"noGlobal": true
+			block requirejs-config
+				script(type='text/javascript').
+					// minimal requirejs configuration (can be extended/overridden)
+					window.requirejs = {
+						"paths" : {
+							"moment": "libs/#{lib('moment')}",
+							"fineuploader": "libs/#{lib('fineuploader')}",
+							"main": "#{buildJsPath('main.js', {hashedPath:settings.useMinifiedJs, removeExtension:true})}",
+							"libraries": "#{buildJsPath('libraries.js', {hashedPath:settings.useMinifiedJs, removeExtension:true})}",
+							"recurly": "https://js.recurly.com/v4/recurly.js"
+						},
+						"config":{
+							"moment":{
+								"noGlobal": true
+							}
 						}
-					}
-				};
-			script(
-				data-main=buildJsPath('main.js', {hashedPath:false}),
-				baseurl=fullJsPath,
-				src=buildJsPath('libs/require.js', {hashedPath:true})
-			)
+					};
+
+			block requirejs-init
+				script(
+					data-main=buildJsPath('main.js', {hashedPath:false}),
+					baseurl=fullJsPath,
+					src=buildJsPath('libs/require.js', {hashedPath:true})
+				)
 
 		!= moduleIncludes("contactModal", locals)
 		include v1-tooltip
 		include sentry
-		
+
 

+ 8 - 1
services/web/app/views/subscriptions/dashboard.pug

@@ -2,6 +2,13 @@ extends ../layout
 
 include ./dashboard/_team_name_mixin
 
+block requirejs-init
+	script(
+		data-main=buildJsPath("main-recurly.js", {hashedPath:false}),
+		baseurl=fullJsPath,
+		src=buildJsPath('libs/require.js', {hashedPath:true})
+	)
+
 block content
 	.content.content-alt(ng-cloak)
 		.container
@@ -12,7 +19,7 @@ block content
 							p You already have a subscription
 					.card
 						.page-header
-							h1 #{translate("your_subscription")} 
+							h1 #{translate("your_subscription")}
 
 						-var hasDisplayedSubscription = false
 						-if (personalSubscription)

+ 6 - 4
services/web/app/views/subscriptions/dashboard/_personal_subscription_recurly.pug

@@ -1,4 +1,3 @@
-script(src="https://js.recurly.com/v3/recurly.js")
 script(type='text/javascript').
 	window.recurlyApiKey = "!{settings.apis.recurly.publicKey}"
 	window.subscription = !{StringHelper.stringifyJsonForScript(personalSubscription)}
@@ -8,7 +7,7 @@ div(ng-controller="RecurlySubscriptionController")
 	div(ng-show="!showCancellation")
 		case personalSubscription.recurly.state
 			when "active"
-				p !{translate("currently_subscribed_to_plan", {planName:"<strong>" + personalSubscription.plan.name + "</strong>"})} 
+				p !{translate("currently_subscribed_to_plan", {planName:"<strong>" + personalSubscription.plan.name + "</strong>"})}
 					a(href, ng-click="switchToChangePlanView()", ng-if="showChangePlanButton") !{translate("change_plan")}.
 				-if (personalSubscription.recurly.trialEndsAtFormatted && personalSubscription.recurly.trial_ends_at > Date.now())
 					p You're on a free trial which ends on <strong ng-non-bindable>#{personalSubscription.recurly.trialEndsAtFormatted}</strong>
@@ -18,7 +17,7 @@ div(ng-controller="RecurlySubscriptionController")
 				p
 					a(href=personalSubscription.recurly.billingDetailsLink, target="_blank").btn.btn-info #{translate("update_your_billing_details")}
 					| &nbsp;
-					a(href, ng-click="switchToCancellationView()").btn.btn-primary !{translate("cancel_your_subscription")}
+					a(href, ng-click="switchToCancellationView()", ng-hide="recurlyLoadError").btn.btn-primary !{translate("cancel_your_subscription")}
 			when "canceled"
 				p !{translate("currently_subscribed_to_plan", {planName:"<strong>" + personalSubscription.plan.name + "</strong>"})}
 				p !{translate("subscription_canceled_and_terminate_on_x", {terminateDate:"<strong>" + personalSubscription.recurly.nextPaymentDueAt + "</strong>"})}
@@ -26,11 +25,14 @@ div(ng-controller="RecurlySubscriptionController")
 					input(type="hidden", name="_csrf", value=csrfToken)
 					input(type="submit",value="Reactivate your subscription").btn.btn-success
 			when "expired"
-				p !{translate("your_subscription_has_expired")}	
+				p !{translate("your_subscription_has_expired")}
 					a(href="/user/subscription/plans") !{translate("create_new_subscription")}
 			default
 				p !{translate("problem_with_subscription_contact_us")}
 
+		.alert.alert-warning(ng-show="recurlyLoadError")
+			strong #{translate('payment_provider_unreachable_error')}
+
 	include ./_change_plans_mixins
 	div(ng-show="showChangePlan", ng-cloak)
 		h2 !{translate("change_plan")}

+ 37 - 28
services/web/app/views/subscriptions/new.pug

@@ -1,5 +1,12 @@
 extends ../layout
 
+block requirejs-init
+	script(
+		data-main=buildJsPath("main-recurly.js", {hashedPath:false}),
+		baseurl=fullJsPath,
+		src=buildJsPath('libs/require.js', {hashedPath:true})
+	)
+
 block scripts
 	script(type='text/javascript').
 		window.countryCode = '#{countryCode}'
@@ -15,7 +22,9 @@ block content
 			.row.card-group
 				.col-md-5.col-md-push-4
 					.card.card-highlighted.card-border
-						.page-header
+						.alert.alert-danger(ng-show="recurlyLoadError")
+							strong #{translate('payment_provider_unreachable_error')}
+						.page-header(ng-hide="recurlyLoadError")
 							.row
 								.col-xs-9
 									h2 {{planName}}
@@ -26,13 +35,13 @@ block content
 											data-toggle="dropdown",
 											dropdown-toggle
 										)
-											| {{currencyCode}} ({{allCurrencies[currencyCode]['symbol']}}) 
+											| {{currencyCode}} ({{allCurrencies[currencyCode]['symbol']}})
 											span.caret
 										ul.dropdown-menu(role="menu")
 											li(ng-repeat="(currency, value) in availableCurrencies")
 												a(
 													ng-click="changeCurrency(currency)",
-												) {{currency}} ({{value['symbol']}}) 
+												) {{currency}} ({{value['symbol']}})
 							.row(ng-if="planCode == 'student-annual' || planCode == 'student-monthly' || planCode == 'student_free_trial_7_days'")
 								.col-xs-12
 									p.student-disclaimer #{translate('student_disclaimer')}
@@ -40,16 +49,16 @@ block content
 							hr.thin
 							.row
 								.col-md-12.text-center
-									div(ng-if="trialLength") 
+									div(ng-if="trialLength")
 										span !{translate("first_few_days_free", {trialLen:'{{trialLength}}'})}
 										span(ng-if="discountMonths && discountRate") &nbsp; -  {{discountMonths}} #{translate("month")}s {{discountRate}}% Off
 									div(ng-if="price")
-										strong {{availableCurrencies[currencyCode]['symbol']}}{{price.next.total}} 
+										strong {{availableCurrencies[currencyCode]['symbol']}}{{price.next.total}}
 										span(ng-if="monthlyBilling")  #{translate("every")} #{translate("month")}
 										span(ng-if="!monthlyBilling")  #{translate("every")} #{translate("year")}
 									div(ng-if="normalPrice")
 										span.small Normally {{availableCurrencies[currencyCode]['symbol']}}{{normalPrice}}
-						.row
+						.row(ng-hide="recurlyLoadError")
 							div()
 								.col-md-12()
 									form(
@@ -57,7 +66,7 @@ block content
 										novalidate
 									)
 
-										
+
 										div.payment-method-toggle
 											a.payment-method-toggle-switch(
 												href
@@ -77,7 +86,7 @@ block content
 											)
 												i.fa.fa-cc-paypal.fa-2x(aria-hidden="true")
 												span.sr-only Pay with PayPal
-										
+
 										.alert.alert-warning.small(ng-show="genericError")
 											strong {{genericError}}
 
@@ -132,7 +141,7 @@ block content
 															name="year"
 															data-recurly="year"
 														)
-							
+
 												.col-xs-6
 													.form-group.has-feedback(ng-class="validation.errorFields.cvv ? 'has-external-error' : ''")
 														label #{translate("security_code")}
@@ -184,14 +193,14 @@ block content
 														ng-blur="applyCoupon()"
 														ng-model="data.coupon"
 													)
-											
+
 											p(ng-if="paymentMethod.value === 'paypal'") #{translate("paypal_upgrade")}
-											
+
 											div.price-breakdown(ng-if="price.next.tax !== '0.00'")
 												hr.thin
-												span Total: 
-												strong {{availableCurrencies[currencyCode]['symbol']}}{{price.next.total}} 
-												span ({{availableCurrencies[currencyCode]['symbol']}}{{price.next.subtotal}} + {{availableCurrencies[currencyCode]['symbol']}}{{price.next.tax}} tax) 
+												span Total:
+												strong {{availableCurrencies[currencyCode]['symbol']}}{{price.next.total}}
+												span ({{availableCurrencies[currencyCode]['symbol']}}{{price.next.subtotal}} + {{availableCurrencies[currencyCode]['symbol']}}{{price.next.tax}} tax)
 												span(ng-if="monthlyBilling") #{translate("every")} #{translate("month")}
 												span(ng-if="!monthlyBilling") #{translate("every")} #{translate("year")}
 												hr.thin
@@ -199,9 +208,9 @@ block content
 											div.payment-submit
 												button.btn.btn-success.btn-block(
 													ng-click="submit()"
-													ng-disabled="processing  || !isFormValid(simpleCCForm);" 
-												) 
-													span(ng-show="processing") 
+													ng-disabled="processing  || !isFormValid(simpleCCForm);"
+												)
+													span(ng-show="processing")
 														i.fa.fa-spinner.fa-spin(aria-hidden="true")
 														span.sr-only #{translate('processing')}
 														| &nbsp;
@@ -215,13 +224,13 @@ block content
 						a.btn-primary.btn.plansPageStudentLink(
 							href,
 							ng-click="switchToStudent()"
-						) #{translate("half_price_student")} 
+						) #{translate("half_price_student")}
 
 					.card.card-first
 						.paymentPageFeatures
 							h3 #{translate("unlimited_projects")}
 							p #{translate("create_unlimited_projects")}
-						
+
 							h3
 								if plan.features.collaborators == -1
 									- var collaboratorCount = 'Unlimited'
@@ -229,21 +238,21 @@ block content
 									- var collaboratorCount = plan.features.collaborators
 								| #{translate("collabs_per_proj", {collabcount:collaboratorCount})}
 							p #{translate("work_on_single_version")}. #{translate("view_collab_edits")} in real time.
-							
+
 							h3 #{translate("full_doc_history")}
-							p #{translate("see_what_has_been")} 
-								span.added #{translate("added")} 
-								| #{translate("and")} 
-								span.removed #{translate("removed")}. 
+							p #{translate("see_what_has_been")}
+								span.added #{translate("added")}
+								| #{translate("and")}
+								span.removed #{translate("removed")}.
 								| #{translate("restore_to_any_older_version")}.
-							
+
 							h3 #{translate("sync_to_dropbox")}
 							p
-								| #{translate("acces_work_from_anywhere")}. 
+								| #{translate("acces_work_from_anywhere")}.
 								| #{translate("work_offline_and_sync_with_dropbox")}.
-								
+
 							hr
-								
+
 							p.small.text-center(ng-non-bindable) We're confident that you'll love #{settings.appName}, but if not you can cancel anytime. We'll give you your money back, no questions asked, if you let us know within 30 days.
 
 

+ 1 - 0
services/web/config/settings.defaults.coffee

@@ -136,6 +136,7 @@ module.exports = settings =
 			url: "http://#{process.env['GITHUB_SYNC_HOST'] or 'localhost'}:3022"
 		recurly:
 			apiKey: process.env['RECURLY_API_KEY'] or ''
+			apiVersion: process.env['RECURLY_API_VERSION']
 			subdomain: process.env['RECURLY_SUBDOMAIN'] or ''
 			publicKey: process.env['RECURLY_PUBLIC_KEY'] or ''
 		geoIpLookup:

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
services/web/public/js/libs/recurly-4.8.5.js


+ 8 - 0
services/web/public/src/main-recurly.js

@@ -0,0 +1,8 @@
+// main bundle plus recurly (loaded externaly from CDN) and all files requiring
+// Recurly JS
+define([
+  'main',
+  'recurly',
+  'main/subscription-dashboard',
+  'main/new-subscription'
+], function() {})

+ 0 - 2
services/web/public/src/main.js

@@ -22,8 +22,6 @@ define([
   'main/bonus',
   'main/system-messages',
   'main/translations',
-  'main/subscription-dashboard',
-  'main/new-subscription',
   'main/annual-upgrade',
   'main/announcements',
   'main/register-users',

+ 5 - 3
services/web/public/src/main/new-subscription.js

@@ -4,7 +4,7 @@
     no-return-assign
 */
 /* global recurly,_,define */
-define(['base', 'directives/creditCards', 'libs/recurly-4.8.5'], App =>
+define(['base', 'directives/creditCards'], App =>
   App.controller('NewSubscriptionController', function(
     $scope,
     MultiCurrencyPricing,
@@ -12,10 +12,12 @@ define(['base', 'directives/creditCards', 'libs/recurly-4.8.5'], App =>
     event_tracking,
     ccUtils
   ) {
-    if (typeof recurly === 'undefined') {
-      throw new Error('Recurly API Library Missing.')
+    if (typeof recurly === 'undefined' || !recurly) {
+      $scope.recurlyLoadError = true
+      return
     }
 
+    $scope.recurlyLoadError = false
     $scope.currencyCode = MultiCurrencyPricing.currencyCode
     $scope.allCurrencies = MultiCurrencyPricing.plans
     $scope.availableCurrencies = {}

+ 1 - 1
services/web/public/src/main/plans.js

@@ -3,7 +3,7 @@
     max-len
 */
 /* global define,history */
-define(['base', 'libs/recurly-4.8.5'], function(App, recurly) {
+define(['base'], function(App) {
   App.factory('MultiCurrencyPricing', function() {
     const currencyCode = window.recomendedCurrency
 

+ 10 - 4
services/web/public/src/main/subscription-dashboard.js

@@ -19,8 +19,11 @@ define(['base'], function(App) {
   const SUBSCRIPTION_URL = '/user/subscription/update'
 
   const ensureRecurlyIsSetup = _.once(() => {
-    if (!recurly) return
+    if (typeof recurly === 'undefined' || !recurly) {
+      return false
+    }
     recurly.configure(window.recurlyApiKey)
+    return true
   })
 
   App.controller('MetricsEmailController', function($scope, $http) {
@@ -60,7 +63,7 @@ define(['base'], function(App) {
   App.factory('RecurlyPricing', function($q, MultiCurrencyPricing) {
     return {
       loadDisplayPriceWithTax: function(planCode, currency, taxRate) {
-        ensureRecurlyIsSetup()
+        if (!ensureRecurlyIsSetup()) return
         const currencySymbol = MultiCurrencyPricing.plans[currency].symbol
         const pricing = recurly.Pricing()
         return $q(function(resolve, reject) {
@@ -89,7 +92,7 @@ define(['base'], function(App) {
     $modal,
     RecurlyPricing
   ) {
-    ensureRecurlyIsSetup()
+    if (!ensureRecurlyIsSetup()) return
 
     $scope.changePlan = () =>
       $modal.open({
@@ -164,7 +167,9 @@ define(['base'], function(App) {
   })
 
   App.controller('RecurlySubscriptionController', function($scope) {
-    $scope.showChangePlanButton = !subscription.groupPlan
+    const recurlyIsSetup = ensureRecurlyIsSetup()
+    $scope.showChangePlanButton = recurlyIsSetup && !subscription.groupPlan
+    $scope.recurlyLoadError = !recurlyIsSetup
 
     $scope.switchToDefaultView = () => {
       $scope.showCancellation = false
@@ -188,6 +193,7 @@ define(['base'], function(App) {
     RecurlyPricing,
     $http
   ) {
+    if (!ensureRecurlyIsSetup()) return
     const subscription = window.subscription
     const sevenDaysTime = new Date()
     sevenDaysTime.setDate(sevenDaysTime.getDate() + 7)

Некоторые файлы не были показаны из-за большого количества измененных файлов