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

Merge pull request #6181 from overleaf/jk-fix-sub-handler-xml-exception

[web] Catch XML errors in RecurlyWrapper

GitOrigin-RevId: bc20146b67e0ceac76f21b5d28ea2b36e2e97f0d
June Kelly 4 лет назад
Родитель
Сommit
02bb2f1c5a

+ 76 - 12
services/web/app/src/Features/Subscription/RecurlyWrapper.js

@@ -31,7 +31,14 @@ function updateAccountEmailAddress(accountId, newEmail, callback) {
   const data = {
     email: newEmail,
   }
-  const requestBody = RecurlyWrapper._buildXml('account', data)
+  let requestBody
+  try {
+    requestBody = RecurlyWrapper._buildXml('account', data)
+  } catch (error) {
+    return callback(
+      OError.tag(error, 'error building xml', { accountId, newEmail })
+    )
+  }
 
   RecurlyWrapper.apiRequest(
     {
@@ -123,7 +130,14 @@ const RecurlyWrapper = {
         last_name: user.last_name,
         address,
       }
-      const requestBody = RecurlyWrapper._buildXml('account', data)
+      let requestBody
+      try {
+        requestBody = RecurlyWrapper._buildXml('account', data)
+      } catch (error) {
+        return next(
+          OError.tag(error, 'error building xml', { user_id: user._id })
+        )
+      }
 
       return RecurlyWrapper.apiRequest(
         {
@@ -171,7 +185,14 @@ const RecurlyWrapper = {
         return next(new Error('no account code at createBillingInfo stage'))
       }
       const data = { token_id: recurlyTokenIds.billing }
-      const requestBody = RecurlyWrapper._buildXml('billing_info', data)
+      let requestBody
+      try {
+        requestBody = RecurlyWrapper._buildXml('billing_info', data)
+      } catch (error) {
+        return next(
+          OError.tag(error, 'error building xml', { user_id: user._id })
+        )
+      }
       return RecurlyWrapper.apiRequest(
         {
           url: `accounts/${accountCode}/billing_info`,
@@ -233,10 +254,18 @@ const RecurlyWrapper = {
       } catch (error) {
         return next(error)
       }
-      const requestBody = RecurlyWrapper._buildXml(
-        'billing_info',
-        addressAndCompanyBillingInfo
-      )
+
+      let requestBody
+      try {
+        requestBody = RecurlyWrapper._buildXml(
+          'billing_info',
+          addressAndCompanyBillingInfo
+        )
+      } catch (error) {
+        return next(
+          OError.tag(error, 'error building xml', { user_id: user._id })
+        )
+      }
 
       return RecurlyWrapper.apiRequest(
         {
@@ -288,7 +317,14 @@ const RecurlyWrapper = {
       if (customFields) {
         data.custom_fields = customFields
       }
-      const requestBody = RecurlyWrapper._buildXml('subscription', data)
+      let requestBody
+      try {
+        requestBody = RecurlyWrapper._buildXml('subscription', data)
+      } catch (error) {
+        return next(
+          OError.tag(error, 'error building xml', { user_id: user._id })
+        )
+      }
 
       return RecurlyWrapper.apiRequest(
         {
@@ -399,7 +435,14 @@ const RecurlyWrapper = {
     if (customFields) {
       data.custom_fields = customFields
     }
-    const requestBody = RecurlyWrapper._buildXml('subscription', data)
+    let requestBody
+    try {
+      requestBody = RecurlyWrapper._buildXml('subscription', data)
+    } catch (error) {
+      return callback(
+        OError.tag(error, 'error building xml', { user_id: user._id })
+      )
+    }
 
     return RecurlyWrapper.apiRequest(
       {
@@ -701,7 +744,14 @@ const RecurlyWrapper = {
       plan_code: options.plan_code,
       timeframe: options.timeframe,
     }
-    const requestBody = RecurlyWrapper._buildXml('subscription', data)
+    let requestBody
+    try {
+      requestBody = RecurlyWrapper._buildXml('subscription', data)
+    } catch (error) {
+      return callback(
+        OError.tag(error, 'error building xml', { subscriptionId })
+      )
+    }
 
     return RecurlyWrapper.apiRequest(
       {
@@ -737,7 +787,14 @@ const RecurlyWrapper = {
       applies_to_all_plans: false,
     }
     data.discount_in_cents[currencyCode] = discount_in_cents
-    const requestBody = RecurlyWrapper._buildXml('coupon', data)
+    let requestBody
+    try {
+      requestBody = RecurlyWrapper._buildXml('coupon', data)
+    } catch (error) {
+      return callback(
+        OError.tag(error, 'error building xml', { coupon_code, name })
+      )
+    }
 
     logger.log({ coupon_code, requestBody }, 'creating coupon')
     return RecurlyWrapper.apiRequest(
@@ -774,7 +831,14 @@ const RecurlyWrapper = {
       account_code,
       currency: 'USD',
     }
-    const requestBody = RecurlyWrapper._buildXml('redemption', data)
+    let requestBody
+    try {
+      requestBody = RecurlyWrapper._buildXml('redemption', data)
+    } catch (error) {
+      return callback(
+        OError.tag(error, 'error building xml', { account_code, coupon_code })
+      )
+    }
 
     logger.log(
       { account_code, coupon_code, requestBody },

+ 31 - 0
services/web/test/unit/src/Subscription/RecurlyWrapperTests.js

@@ -285,6 +285,37 @@ describe('RecurlyWrapper', function () {
     })
   })
 
+  describe('updateAccountEmailAddress, with invalid XML', function () {
+    beforeEach(function (done) {
+      this.recurlyAccountId = 'account-id-123'
+      this.newEmail = '\uD800@example.com'
+      this.apiRequest = sinon
+        .stub(this.RecurlyWrapper, 'apiRequest')
+        .callsFake((options, callback) => {
+          this.requestOptions = options
+          callback(null, {}, fixtures['accounts/104'])
+        })
+      done()
+    })
+
+    afterEach(function () {
+      return this.RecurlyWrapper.apiRequest.restore()
+    })
+
+    it('should produce an error', function (done) {
+      this.RecurlyWrapper.updateAccountEmailAddress(
+        this.recurlyAccountId,
+        this.newEmail,
+        (error, recurlyAccount) => {
+          expect(error).to.exist
+          expect(error.message.startsWith('Invalid character')).to.equal(true)
+          expect(this.apiRequest.called).to.equal(false)
+          done()
+        }
+      )
+    })
+  })
+
   describe('updateSubscription', function () {
     beforeEach(function (done) {
       this.recurlySubscriptionId = 'subscription-id-123'