mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
start testing the paypal workflow.
This commit is contained in:
parent
3bf8da3e83
commit
709f8f2bea
2 changed files with 253 additions and 153 deletions
|
@ -18,160 +18,178 @@ module.exports = RecurlyWrapper =
|
|||
resultString += "</billing_info>\n"
|
||||
return resultString
|
||||
|
||||
_paypal:
|
||||
checkAccountExists: (cache, next) ->
|
||||
user = cache.user
|
||||
recurly_token_id = cache.recurly_token_id
|
||||
subscriptionDetails = cache.subscriptionDetails
|
||||
logger.log {user_id: user._id, recurly_token_id}, "checking if recurly account exists for user"
|
||||
RecurlyWrapper.apiRequest({
|
||||
url: "accounts/#{user._id}"
|
||||
method: "GET"
|
||||
}, (error, response, responseBody) ->
|
||||
if error
|
||||
if response.statusCode == 404 # actually not an error in this case, just no existing account
|
||||
cache.userExists = false
|
||||
return next(null, cache)
|
||||
logger.error {error, user_id: user._id, recurly_token_id}, "error response from recurly while checking account"
|
||||
return next(error)
|
||||
logger.log {user_id: user._id, recurly_token_id}, "user appears to exist in recurly"
|
||||
RecurlyWrapper._parseAccountXml responseBody, (err, account) ->
|
||||
if err
|
||||
logger.error {err, user_id: user._id, recurly_token_id}, "error parsing account"
|
||||
return next(err)
|
||||
cache.account = account
|
||||
return next(null, cache)
|
||||
)
|
||||
createAccount: (cache, next) ->
|
||||
user = cache.user
|
||||
recurly_token_id = cache.recurly_token_id
|
||||
subscriptionDetails = cache.subscriptionDetails
|
||||
if cache.userExists
|
||||
logger.log {user_id: user._id, recurly_token_id}, "user already exists in recurly"
|
||||
return next(null, cache)
|
||||
logger.log {user_id: user._id, recurly_token_id}, "creating user in recurly"
|
||||
address = subscriptionDetails.address
|
||||
if !address
|
||||
return next(new Error('no address in subscriptionDetails at createAccount stage'))
|
||||
requestBody = """
|
||||
<account>
|
||||
<account_code>#{user._id}</account_code>
|
||||
<email>#{user.email}</email>
|
||||
<first_name>#{user.first_name}</first_name>
|
||||
<last_name>#{user.last_name}</last_name>
|
||||
<address>
|
||||
<address1>#{address.address1}</address1>
|
||||
<address2>#{address.address2}</address2>
|
||||
<city>#{address.city || ''}</city>
|
||||
<state>#{address.state || ''}</state>
|
||||
<zip>#{address.zip || ''}</zip>
|
||||
<country>#{address.country}</country>
|
||||
</address>
|
||||
</account>
|
||||
"""
|
||||
RecurlyWrapper.apiRequest({
|
||||
url : "accounts"
|
||||
method : "POST"
|
||||
body : requestBody
|
||||
}, (error, response, responseBody) =>
|
||||
if error
|
||||
logger.error {error, user_id: user._id, recurly_token_id}, "error response from recurly while creating account"
|
||||
return next(error)
|
||||
RecurlyWrapper._parseAccountXml responseBody, (err, account) ->
|
||||
if err
|
||||
logger.error {err, user_id: user._id, recurly_token_id}, "error creating account"
|
||||
return next(err)
|
||||
cache.account = account
|
||||
return next(null, cache)
|
||||
)
|
||||
createBillingInfo: (cache, next) ->
|
||||
user = cache.user
|
||||
recurly_token_id = cache.recurly_token_id
|
||||
subscriptionDetails = cache.subscriptionDetails
|
||||
logger.log {user_id: user._id, recurly_token_id}, "creating billing info in recurly"
|
||||
accountCode = cache?.account?.account_code
|
||||
if !accountCode
|
||||
return next(new Error('no account code at createBillingInfo stage'))
|
||||
requestBody = """
|
||||
<billing_info>
|
||||
<token_id>#{recurly_token_id}</token_id>
|
||||
</billing_info>
|
||||
"""
|
||||
RecurlyWrapper.apiRequest({
|
||||
url: "accounts/#{accountCode}/billing_info"
|
||||
method: "POST"
|
||||
body: requestBody
|
||||
}, (error, response, responseBody) =>
|
||||
if error
|
||||
logger.error {error, user_id: user._id, recurly_token_id}, "error response from recurly while creating billing info"
|
||||
return next(error)
|
||||
RecurlyWrapper._parseBillingInfoXml responseBody, (err, billingInfo) ->
|
||||
if err
|
||||
logger.error {err, user_id: user._id, accountCode, recurly_token_id}, "error creating billing info"
|
||||
return next(err)
|
||||
cache.billingInfo = billingInfo
|
||||
return next(null, cache)
|
||||
)
|
||||
|
||||
setAddress: (cache, next) ->
|
||||
user = cache.user
|
||||
recurly_token_id = cache.recurly_token_id
|
||||
subscriptionDetails = cache.subscriptionDetails
|
||||
logger.log {user_id: user._id, recurly_token_id}, "setting billing address in recurly"
|
||||
accountCode = cache?.account?.account_code
|
||||
if !accountCode
|
||||
return next(new Error('no account code at setAddress stage'))
|
||||
address = subscriptionDetails.address
|
||||
if !address
|
||||
return next(new Error('no address in subscriptionDetails at setAddress stage'))
|
||||
requestBody = RecurlyWrapper._addressToXml(address)
|
||||
RecurlyWrapper.apiRequest({
|
||||
url: "accounts/#{accountCode}/billing_info"
|
||||
method: "PUT"
|
||||
body: requestBody
|
||||
}, (error, response, responseBody) =>
|
||||
if error
|
||||
logger.error {error, user_id: user._id, recurly_token_id}, "error response from recurly while setting address"
|
||||
return next(error)
|
||||
RecurlyWrapper._parseBillingInfoXml responseBody, (err, billingInfo) ->
|
||||
if err
|
||||
logger.error {err, user_id: user._id, recurly_token_id}, "error updating billing info"
|
||||
return next(err)
|
||||
cache.billingInfo = billingInfo
|
||||
return next(null, cache)
|
||||
)
|
||||
createSubscription: (cache, next) ->
|
||||
user = cache.user
|
||||
recurly_token_id = cache.recurly_token_id
|
||||
subscriptionDetails = cache.subscriptionDetails
|
||||
logger.log {user_id: user._id, recurly_token_id}, "creating subscription in recurly"
|
||||
requestBody = """
|
||||
<subscription>
|
||||
<plan_code>#{subscriptionDetails.plan_code}</plan_code>
|
||||
<currency>#{subscriptionDetails.currencyCode}</currency>
|
||||
<coupon_code>#{subscriptionDetails.coupon_code}</coupon_code>
|
||||
<account>
|
||||
<account_code>#{user._id}</account_code>
|
||||
</account>
|
||||
</subscription>
|
||||
""" # TODO: check account details and billing
|
||||
RecurlyWrapper.apiRequest({
|
||||
url : "subscriptions"
|
||||
method : "POST"
|
||||
body : requestBody
|
||||
}, (error, response, responseBody) =>
|
||||
if error
|
||||
logger.error {error, user_id: user._id, recurly_token_id}, "error response from recurly while creating subscription"
|
||||
return next(error)
|
||||
RecurlyWrapper._parseSubscriptionXml responseBody, (err, subscription) ->
|
||||
if err
|
||||
logger.error {err, user_id: user._id, recurly_token_id}, "error creating subscription"
|
||||
return next(err)
|
||||
cache.subscription = subscription
|
||||
return next(null, cache)
|
||||
)
|
||||
|
||||
_createPaypalSubscription: (user, subscriptionDetails, recurly_token_id, callback) ->
|
||||
logger.log {user_id: user._id, recurly_token_id}, "starting process of creating paypal subscription"
|
||||
cache = {user, recurly_token_id, subscriptionDetails}
|
||||
Async.waterfall([
|
||||
(next) -> # check if account exists
|
||||
logger.log {user_id: user._id, recurly_token_id}, "checking if recurly account exists for user"
|
||||
RecurlyWrapper.apiRequest({
|
||||
url: "accounts/#{user._id}"
|
||||
method: "GET"
|
||||
}, (error, response, responseBody) ->
|
||||
result = {userExists: true}
|
||||
if error
|
||||
if response.statusCode == 404 # actually not an error in this case, just no existing account
|
||||
result.userExists = false
|
||||
return next(null, result)
|
||||
logger.error {error, user_id: user._id, recurly_token_id}, "error response from recurly while checking account"
|
||||
return next(error)
|
||||
logger.log {user_id: user._id, recurly_token_id}, "user appears to exist in recurly"
|
||||
RecurlyWrapper._parseAccountXml responseBody, (err, account) ->
|
||||
if err
|
||||
logger.error {err, user_id: user._id, recurly_token_id}, "error parsing account"
|
||||
return next(err)
|
||||
result.account = account
|
||||
return next(null, result)
|
||||
)
|
||||
|
||||
, (result, next) -> # create account
|
||||
if result.userExists
|
||||
logger.log {user_id: user._id, recurly_token_id}, "user already exists in recurly"
|
||||
return next(null, result)
|
||||
logger.log {user_id: user._id, recurly_token_id}, "creating user in recurly"
|
||||
address = subscriptionDetails.address
|
||||
if !address
|
||||
return next(new Error('no address in subscriptionDetails at createAccount stage'))
|
||||
requestBody = """
|
||||
<account>
|
||||
<account_code>#{user._id}</account_code>
|
||||
<email>#{user.email}</email>
|
||||
<first_name>#{user.first_name}</first_name>
|
||||
<last_name>#{user.last_name}</last_name>
|
||||
<address>
|
||||
<address1>#{address.address1}</address1>
|
||||
<address2>#{address.address2}</address2>
|
||||
<city>#{address.city || ''}</city>
|
||||
<state>#{address.state || ''}</state>
|
||||
<zip>#{address.zip || ''}</zip>
|
||||
<country>#{address.country}</country>
|
||||
</address>
|
||||
</account>
|
||||
"""
|
||||
RecurlyWrapper.apiRequest({
|
||||
url : "accounts"
|
||||
method : "POST"
|
||||
body : requestBody
|
||||
}, (error, response, responseBody) =>
|
||||
if error
|
||||
logger.error {error, user_id: user._id, recurly_token_id}, "error response from recurly while creating account"
|
||||
return next(error)
|
||||
RecurlyWrapper._parseAccountXml responseBody, (err, account) ->
|
||||
if err
|
||||
logger.error {err, user_id: user._id, recurly_token_id}, "error creating account"
|
||||
return next(err)
|
||||
result.account = account
|
||||
return next(null, result)
|
||||
)
|
||||
|
||||
, (result, next) -> # create billing info
|
||||
logger.log {user_id: user._id, recurly_token_id}, "creating billing info in recurly"
|
||||
accountCode = result?.account?.account_code
|
||||
if !accountCode
|
||||
return next(new Error('no account code at createBillingInfo stage'))
|
||||
requestBody = """
|
||||
<billing_info>
|
||||
<token_id>#{recurly_token_id}</token_id>
|
||||
</billing_info>
|
||||
"""
|
||||
RecurlyWrapper.apiRequest({
|
||||
url: "accounts/#{accountCode}/billing_info"
|
||||
method: "POST"
|
||||
body: requestBody
|
||||
}, (error, response, responseBody) =>
|
||||
if error
|
||||
logger.error {error, user_id: user._id, recurly_token_id}, "error response from recurly while creating billing info"
|
||||
return next(error)
|
||||
RecurlyWrapper._parseBillingInfoXml responseBody, (err, billingInfo) ->
|
||||
if err
|
||||
logger.error {err, user_id: user._id, accountCode, recurly_token_id}, "error creating billing info"
|
||||
return next(err)
|
||||
result.billingInfo = billingInfo
|
||||
return next(null, result)
|
||||
)
|
||||
|
||||
, (result, next) -> # set address
|
||||
logger.log {user_id: user._id, recurly_token_id}, "setting billing address in recurly"
|
||||
accountCode = result?.account?.account_code
|
||||
if !accountCode
|
||||
return next(new Error('no account code at setAddress stage'))
|
||||
address = subscriptionDetails.address
|
||||
if !address
|
||||
return next(new Error('no address in subscriptionDetails at setAddress stage'))
|
||||
requestBody = RecurlyWrapper._addressToXml(address)
|
||||
RecurlyWrapper.apiRequest({
|
||||
url: "accounts/#{accountCode}/billing_info"
|
||||
method: "PUT"
|
||||
body: requestBody
|
||||
}, (error, response, responseBody) =>
|
||||
if error
|
||||
logger.error {error, user_id: user._id, recurly_token_id}, "error response from recurly while setting address"
|
||||
return next(error)
|
||||
RecurlyWrapper._parseBillingInfoXml responseBody, (err, billingInfo) ->
|
||||
if err
|
||||
logger.error {err, user_id: user._id, recurly_token_id}, "error updating billing info"
|
||||
return next(err)
|
||||
result.billingInfo = billingInfo
|
||||
return next(null, result)
|
||||
)
|
||||
|
||||
, (result, next) -> # create subscription
|
||||
logger.log {user_id: user._id, recurly_token_id}, "creating subscription in recurly"
|
||||
requestBody = """
|
||||
<subscription>
|
||||
<plan_code>#{subscriptionDetails.plan_code}</plan_code>
|
||||
<currency>#{subscriptionDetails.currencyCode}</currency>
|
||||
<coupon_code>#{subscriptionDetails.coupon_code}</coupon_code>
|
||||
<account>
|
||||
<account_code>#{user._id}</account_code>
|
||||
</account>
|
||||
</subscription>
|
||||
""" # TODO: check account details and billing
|
||||
RecurlyWrapper.apiRequest({
|
||||
url : "subscriptions"
|
||||
method : "POST"
|
||||
body : requestBody
|
||||
}, (error, response, responseBody) =>
|
||||
if error
|
||||
logger.error {error, user_id: user._id, recurly_token_id}, "error response from recurly while creating subscription"
|
||||
return next(error)
|
||||
RecurlyWrapper._parseSubscriptionXml responseBody, (err, subscription) ->
|
||||
if err
|
||||
logger.error {err, user_id: user._id, recurly_token_id}, "error creating subscription"
|
||||
return next(err)
|
||||
result.subscription = subscription
|
||||
return next(null, result)
|
||||
)
|
||||
|
||||
], (err, result) ->
|
||||
if err
|
||||
logger.error {err, user_id: user._id, recurly_token_id}, "error in paypal subscription creation process"
|
||||
return callback(err)
|
||||
if !result.subscription
|
||||
err = new Error('no subscription object in result')
|
||||
logger.error {err, user_id: user._id, recurly_token_id}, "error in paypal subscription creation process"
|
||||
return callback(err)
|
||||
logger.log {user_id: user._id, recurly_token_id}, "done creating paypal subscription for user"
|
||||
callback(null, result.subscription)
|
||||
Async.apply(RecurlyWrapper._paypal.checkAccountExists, cache),
|
||||
RecurlyWrapper._paypal.createAccount,
|
||||
RecurlyWrapper._paypal.createBillingInfo,
|
||||
RecurlyWrapper._paypal.setAddress,
|
||||
RecurlyWrapper._paypal.createSubscription,
|
||||
], (err, result) ->
|
||||
if err
|
||||
logger.error {err, user_id: user._id, recurly_token_id}, "error in paypal subscription creation process"
|
||||
return callback(err)
|
||||
if !result.subscription
|
||||
err = new Error('no subscription object in result')
|
||||
logger.error {err, user_id: user._id, recurly_token_id}, "error in paypal subscription creation process"
|
||||
return callback(err)
|
||||
logger.log {user_id: user._id, recurly_token_id}, "done creating paypal subscription for user"
|
||||
callback(null, result.subscription)
|
||||
)
|
||||
|
||||
_createCreditCardSubscription: (user, subscriptionDetails, recurly_token_id, callback) ->
|
||||
|
|
|
@ -516,6 +516,16 @@ describe "RecurlyWrapper", ->
|
|||
expect(sub).to.equal @subscription
|
||||
done()
|
||||
|
||||
it 'should call apiRequest', (done) ->
|
||||
@call (err, sub) =>
|
||||
@apiRequest.callCount.should.equal 1
|
||||
done()
|
||||
|
||||
it 'should call _parseSubscriptionXml', (done) ->
|
||||
@call (err, sub) =>
|
||||
@_parseSubscriptionXml.callCount.should.equal 1
|
||||
done()
|
||||
|
||||
describe 'when api request produces an error', ->
|
||||
|
||||
beforeEach ->
|
||||
|
@ -526,6 +536,16 @@ describe "RecurlyWrapper", ->
|
|||
expect(err).to.be.instanceof Error
|
||||
done()
|
||||
|
||||
it 'should call apiRequest', (done) ->
|
||||
@call (err, sub) =>
|
||||
@apiRequest.callCount.should.equal 1
|
||||
done()
|
||||
|
||||
it 'should not _parseSubscriptionXml', (done) ->
|
||||
@call (err, sub) =>
|
||||
@_parseSubscriptionXml.callCount.should.equal 0
|
||||
done()
|
||||
|
||||
describe 'when parse xml produces an error', ->
|
||||
|
||||
beforeEach ->
|
||||
|
@ -539,7 +559,69 @@ describe "RecurlyWrapper", ->
|
|||
describe '_createPaypalSubscription', ->
|
||||
|
||||
beforeEach ->
|
||||
@checkAccountExists = sinon.stub(@RecurlyWrapper._paypal, 'checkAccountExists')
|
||||
@createAccount = sinon.stub(@RecurlyWrapper._paypal, 'createAccount')
|
||||
@createBillingInfo = sinon.stub(@RecurlyWrapper._paypal, 'createBillingInfo')
|
||||
@setAddress = sinon.stub(@RecurlyWrapper._paypal, 'setAddress')
|
||||
@createSubscription = sinon.stub(@RecurlyWrapper._paypal, 'createSubscription')
|
||||
@user =
|
||||
_id: 'some_id'
|
||||
email: 'user@example.com'
|
||||
@subscriptionDetails =
|
||||
currencyCode: "EUR"
|
||||
plan_code: "some_plan_code"
|
||||
coupon_code: ""
|
||||
isPaypal: true
|
||||
address:
|
||||
address1: "addr_one"
|
||||
address2: "addr_two"
|
||||
country: "some_country"
|
||||
state: "some_state"
|
||||
zip: "some_zip"
|
||||
@subscription = {}
|
||||
@recurly_token_id = "a-token-id"
|
||||
|
||||
describe 'when all goes well', ->
|
||||
# set up data callbacks
|
||||
user = @user
|
||||
subscriptionDetails = @subscriptionDetails
|
||||
recurly_token_id = @recurly_token_id
|
||||
|
||||
beforeEach ->
|
||||
@checkAccountExists.callsArgWith(1, null,
|
||||
{user, subscriptionDetails, recurly_token_id,
|
||||
userExists: false, account: {accountCode: 'xx'}}
|
||||
)
|
||||
|
||||
@createAccount.callsArgWith(1, null,
|
||||
{user, subscriptionDetails, recurly_token_id,
|
||||
userExists: false, account: {accountCode: 'xx'}}
|
||||
)
|
||||
|
||||
@createBillingInfo.callsArgWith(1, null,
|
||||
{user, subscriptionDetails, recurly_token_id,
|
||||
userExists: false, account: {accountCode: 'xx'}, billingInfo: {token_id: 'abc'}}
|
||||
)
|
||||
|
||||
@setAddress.callsArgWith(1, null,
|
||||
{user, subscriptionDetails, recurly_token_id,
|
||||
userExists: false, account: {accountCode: 'xx'}, billingInfo: {token_id: 'abc'}}
|
||||
)
|
||||
|
||||
@createSubscription.callsArgWith(1, null,
|
||||
{user, subscriptionDetails, recurly_token_id,
|
||||
userExists: false, account: {accountCode: 'xx'}, billingInfo: {token_id: 'abc'}, subscription: {}}
|
||||
)
|
||||
|
||||
@call = (callback) =>
|
||||
@RecurlyWrapper._createPaypalSubscription @user, @subscriptionDetails, @recurly_token_id, callback
|
||||
|
||||
afterEach ->
|
||||
@checkAccountExists.restore()
|
||||
@createAccount.restore()
|
||||
@createBillingInfo.restore()
|
||||
@setAddress.restore()
|
||||
@createSubscription.restore()
|
||||
|
||||
it 'should not produce an error', (done) ->
|
||||
@call (err, sub) =>
|
||||
expect(err).to.not.be.instanceof Error
|
||||
done()
|
||||
|
|
Loading…
Reference in a new issue