From de3246178725a264f94f54b596185e8cd45cc490 Mon Sep 17 00:00:00 2001 From: Matteo Pagliazzi Date: Sun, 5 Jul 2015 20:49:42 +0200 Subject: [PATCH 1/4] feat(amazon-payments): WIP add donations --- website/src/controllers/payments/amazon.js | 40 ++++++++++++---------- website/src/controllers/payments/index.js | 1 + website/src/routes/payments.js | 1 + website/views/shared/modals/buy-gems.jade | 2 +- 4 files changed, 25 insertions(+), 19 deletions(-) diff --git a/website/src/controllers/payments/amazon.js b/website/src/controllers/payments/amazon.js index 14fa7e6417..95ba846453 100644 --- a/website/src/controllers/payments/amazon.js +++ b/website/src/controllers/payments/amazon.js @@ -29,15 +29,34 @@ exports.verifyAccessToken = function(req, res, next){ }); }; +exports.createOrderReferenceId = function(req, res, next){ + if(!req.body || !req.body.billingAgreementId){ + return res.json(400, {err: 'Billing Agreement Id not supplied.'}); + } + + amzPayment.offAmazonPayments.createOrderReferenceForId({ + Id: req.body.billingAgreementId, + IdType: 'BillingAgreement' + }, function(err, response){ + if(err) return next(err); + if(!response.OrderReferenceDetails || !response.OrderReferenceDetails.AmazonOrderReferenceId){ + return next(new Error('Missing attributes in Amazon response.')); + } + + res.json({ + orderReferenceId: response.OrderReferenceDetails.AmazonOrderReferenceId + }); + }); +}; + exports.checkout = function(req, res, next){ - if(!req.body || !req.body['billingAgreementId']){ + if(!req.body || !req.body.orderReferenceId){ return res.json(400, {err: 'Billing Agreement Id not supplied.'}); } var gift = req.body.gift; var user = res.locals.user; - var billingAgreementId = req.body.billingAgreementId; - var orderReferenceId; + var orderReferenceId = req.body.orderReferenceId; var amount = 5; if(gift){ @@ -49,21 +68,6 @@ exports.checkout = function(req, res, next){ } async.series({ - createOrderReferenceForId: function(cb){ - amzPayment.offAmazonPayments.createOrderReferenceForId({ - Id: billingAgreementId, - IdType: 'BillingAgreement' - }, function(err, response){ - if(err) return cb(err); - if(!response.OrderReferenceDetails || !response.OrderReferenceDetails.AmazonOrderReferenceId){ - return cb('Missing attributes in Amazon response.'); - } - - orderReferenceId = response.OrderReferenceDetails.AmazonOrderReferenceId; - return cb(); - }); - }, - setOrderReferenceDetails: function(cb){ amzPayment.offAmazonPayments.setOrderReferenceDetails({ AmazonOrderReferenceId: orderReferenceId, diff --git a/website/src/controllers/payments/index.js b/website/src/controllers/payments/index.js index 8f1144cbcc..6206bfe187 100644 --- a/website/src/controllers/payments/index.js +++ b/website/src/controllers/payments/index.js @@ -174,6 +174,7 @@ exports.paypalCheckoutSuccess = paypal.executePayment; exports.paypalIPN = paypal.ipn; exports.amazonVerifyAccessToken = amazon.verifyAccessToken; +exports.amazonCreateOrderReferenceId = amazon.createOrderReferenceId; exports.amazonCheckout = amazon.checkout; exports.amazonSubscribe = amazon.subscribe; exports.amazonSubscribeCancel = amazon.subscribeCancel; diff --git a/website/src/routes/payments.js b/website/src/routes/payments.js index 210240314e..3583f96adc 100644 --- a/website/src/routes/payments.js +++ b/website/src/routes/payments.js @@ -18,6 +18,7 @@ router.post("/stripe/subscribe/edit", auth.auth, i18n.getUserLanguage, payments. router.get("/stripe/subscribe/cancel", auth.authWithUrl, i18n.getUserLanguage, payments.stripeSubscribeCancel); router.post('/amazon/verifyAccessToken', auth.auth, i18n.getUserLanguage, payments.amazonVerifyAccessToken); +router.post('/amazon/createOrderReferenceId', auth.auth, i18n.getUserLanguage, payments.amazonCreateOrderReferenceId); router.post('/amazon/checkout', auth.auth, i18n.getUserLanguage, payments.amazonCheckout); router.post('/amazon/subscribe', auth.auth, i18n.getUserLanguage, payments.amazonSubscribe); router.get('/amazon/subscribe/cancel', auth.authWithUrl, i18n.getUserLanguage, payments.amazonSubscribeCancel); diff --git a/website/views/shared/modals/buy-gems.jade b/website/views/shared/modals/buy-gems.jade index 33885a451c..aaa88d89c9 100644 --- a/website/views/shared/modals/buy-gems.jade +++ b/website/views/shared/modals/buy-gems.jade @@ -22,7 +22,7 @@ script(id='modals/buyGems.html', type='text/ng-template') small.muted=env.t('paymentMethods') .btn.btn-primary(ng-click='Payments.showStripe({})')=env.t('card') a.btn.btn-warning(href='/paypal/checkout?_id={{user._id}}&apiToken={{user.apiToken}}') PayPal - //.btn.btn-default(ng-click="Payments.amazonPayments.init({type: 'donation'})") Amazon Payments + .btn.btn-default(ng-click="Payments.amazonPayments.init({type: 'donation'})") Amazon Payments div(ng-include="'partials/options.settings.subscription.html'") From bade139b4b830511a1e7ec9e8659fcb45b84a321 Mon Sep 17 00:00:00 2001 From: Matteo Pagliazzi Date: Sun, 12 Jul 2015 23:43:10 +0200 Subject: [PATCH 2/4] wip amazon payments donation --- website/public/js/services/paymentServices.js | 5 +++-- website/src/controllers/payments/amazon.js | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/website/public/js/services/paymentServices.js b/website/public/js/services/paymentServices.js index a2d6f6599f..1d21721034 100644 --- a/website/public/js/services/paymentServices.js +++ b/website/public/js/services/paymentServices.js @@ -152,7 +152,7 @@ function($rootScope, User, $http, Content) { }else{ return false; } - }, + } Payments.amazonPayments.initWidgets = function(){ var walletParams = { @@ -193,6 +193,7 @@ function($rootScope, User, $http, Content) { onPaymentSelect: function() { $rootScope.$apply(function(){ + console.log('Payment plan selected') Payments.amazonPayments.paymentSelected = true; }); }, @@ -205,7 +206,7 @@ function($rootScope, User, $http, Content) { Payments.amazonPayments.checkout = function(){ if(Payments.amazonPayments.type === 'donation'){ - var url = '/amazon/checkout' + var url = '/amazon/createOrderReferenceId' $http.post(url, { billingAgreementId: Payments.amazonPayments.billingAgreementId, gift: Payments.amazonPayments.gift diff --git a/website/src/controllers/payments/amazon.js b/website/src/controllers/payments/amazon.js index 95ba846453..1ffb0c4683 100644 --- a/website/src/controllers/payments/amazon.js +++ b/website/src/controllers/payments/amazon.js @@ -36,7 +36,8 @@ exports.createOrderReferenceId = function(req, res, next){ amzPayment.offAmazonPayments.createOrderReferenceForId({ Id: req.body.billingAgreementId, - IdType: 'BillingAgreement' + IdType: 'BillingAgreement', + ConfirmNow: false }, function(err, response){ if(err) return next(err); if(!response.OrderReferenceDetails || !response.OrderReferenceDetails.AmazonOrderReferenceId){ From ecc98411c711144d5f888ab890a516eac53ffdde Mon Sep 17 00:00:00 2001 From: Matteo Pagliazzi Date: Wed, 15 Jul 2015 16:15:00 +0200 Subject: [PATCH 3/4] refactor amazon payments and add one time purchases once again --- website/public/js/services/paymentServices.js | 110 ++++++++++-------- website/src/controllers/payments/amazon.js | 10 +- website/views/shared/modals/buy-gems.jade | 2 +- website/views/shared/modals/members.jade | 2 +- 4 files changed, 75 insertions(+), 49 deletions(-) diff --git a/website/public/js/services/paymentServices.js b/website/public/js/services/paymentServices.js index 1d21721034..b56ce8bcb7 100644 --- a/website/public/js/services/paymentServices.js +++ b/website/public/js/services/paymentServices.js @@ -72,15 +72,12 @@ function($rootScope, User, $http, Content) { Payments.amazonPayments.reset = function(){ Payments.amazonPayments.modal.close(); - // TODO this is needed because if we do not logout - // users then if they use donation & then subscription - // the billing agreement will be wrong - amazon.Login.logout(); Payments.amazonPayments.modal = null; Payments.amazonPayments.type = null; Payments.amazonPayments.loggedIn = false; Payments.amazonPayments.gift = null; Payments.amazonPayments.billingAgreementId = null; + Payments.amazonPayments.orderReferenceId = null; Payments.amazonPayments.paymentSelected = false; Payments.amazonPayments.recurringConsent = false; Payments.amazonPayments.subscription = null; @@ -90,11 +87,11 @@ function($rootScope, User, $http, Content) { // Needs to be called everytime the modal/router is accessed Payments.amazonPayments.init = function(data){ if(!isAmazonReady) return; - if(data.type !== 'donation' && data.type !== 'subscription') return; + if(data.type !== 'single' && data.type !== 'subscription') return; if(data.gift){ if(data.gift.gems && data.gift.gems.amount && data.gift.gems.amount <= 0) return; - gift.uuid = data.giftedTo; + data.gift.uuid = data.giftedTo; } if(data.subscription){ @@ -118,6 +115,27 @@ function($rootScope, User, $http, Content) { type: 'PwA', color: 'Gold', size: 'small', + agreementType: 'BillingAgreement', + + onSignIn: function(contract){ + Payments.amazonPayments.billingAgreementId = contract.getAmazonBillingAgreementId(); + + if(Payments.amazonPayments.type === 'subscription'){ + Payments.amazonPayments.loggedIn = true; + Payments.amazonPayments.initWidgets(); + }else{ + var url = '/amazon/createOrderReferenceId' + $http.post(url, { + billingAgreementId: Payments.amazonPayments.billingAgreementId + }).success(function(data){ + Payments.amazonPayments.loggedIn = true; + Payments.amazonPayments.orderReferenceId = data.orderReferenceId; + Payments.amazonPayments.initWidgets(); + }).error(function(res){ + alert(res.err); + }); + } + }, authorization: function(){ amazon.Login.authorize({ @@ -127,10 +145,7 @@ function($rootScope, User, $http, Content) { if(response.error) return alert(response.error); var url = '/amazon/verifyAccessToken' - $http.post(url, response).success(function(){ - Payments.amazonPayments.loggedIn = true; - Payments.amazonPayments.initWidgets(); - }).error(function(res){ + $http.post(url, response).error(function(res){ alert(res.err); }); }); @@ -143,7 +158,7 @@ function($rootScope, User, $http, Content) { } Payments.amazonPayments.canCheckout = function(){ - if(Payments.amazonPayments.type === 'donation'){ + if(Payments.amazonPayments.type === 'single'){ return Payments.amazonPayments.paymentSelected === true; }else if(Payments.amazonPayments.type === 'subscription'){ return Payments.amazonPayments.paymentSelected === true && @@ -160,55 +175,58 @@ function($rootScope, User, $http, Content) { design: { designMode: 'responsive' }, - agreementType: 'BillingAgreement', - - onReady: function(billingAgreement){ - Payments.amazonPayments.billingAgreementId = billingAgreement.getAmazonBillingAgreementId(); - - if(Payments.amazonPayments.type === 'subscription'){ - new OffAmazonPayments.Widgets.Consent({ - sellerId: window.env.AMAZON_PAYMENTS.SELLER_ID, - amazonBillingAgreementId: Payments.amazonPayments.billingAgreementId, - design: { - designMode: 'responsive' - }, - - onReady: function(consent){ - $rootScope.$apply(function(){ - var getConsent = consent.getConsentStatus - Payments.amazonPayments.recurringConsent = getConsent ? getConsent() : false; - }); - }, - - onConsent: function(consent){ - $rootScope.$apply(function(){ - Payments.amazonPayments.recurringConsent = consent.getConsentStatus(); - }); - }, - - onError: amazonOnError - }).bind('AmazonPayRecurring'); - } - }, onPaymentSelect: function() { $rootScope.$apply(function(){ - console.log('Payment plan selected') Payments.amazonPayments.paymentSelected = true; }); }, onError: amazonOnError - }; + } + + if(Payments.amazonPayments.type === 'subscription'){ + walletParams.agreementType = 'BillingAgreement'; + console.log(Payments.amazonPayments.billingAgreementId); + walletParams.billingAgreementId = Payments.amazonPayments.billingAgreementId; + walletParams.onReady = function(billingAgreement){ + Payments.amazonPayments.billingAgreementId = billingAgreement.getAmazonBillingAgreementId(); + + new OffAmazonPayments.Widgets.Consent({ + sellerId: window.env.AMAZON_PAYMENTS.SELLER_ID, + amazonBillingAgreementId: Payments.amazonPayments.billingAgreementId, + design: { + designMode: 'responsive' + }, + + onReady: function(consent){ + $rootScope.$apply(function(){ + var getConsent = consent.getConsentStatus + Payments.amazonPayments.recurringConsent = getConsent ? getConsent() : false; + }); + }, + + onConsent: function(consent){ + $rootScope.$apply(function(){ + Payments.amazonPayments.recurringConsent = consent.getConsentStatus(); + }); + }, + + onError: amazonOnError + }).bind('AmazonPayRecurring'); + } + }else{ + walletParams.amazonOrderReferenceId = Payments.amazonPayments.orderReferenceId; + } new OffAmazonPayments.Widgets.Wallet(walletParams).bind('AmazonPayWallet'); } Payments.amazonPayments.checkout = function(){ - if(Payments.amazonPayments.type === 'donation'){ - var url = '/amazon/createOrderReferenceId' + if(Payments.amazonPayments.type === 'single'){ + var url = '/amazon/checkout'; $http.post(url, { - billingAgreementId: Payments.amazonPayments.billingAgreementId, + orderReferenceId: Payments.amazonPayments.orderReferenceId, gift: Payments.amazonPayments.gift }).success(function(){ Payments.amazonPayments.reset(); diff --git a/website/src/controllers/payments/amazon.js b/website/src/controllers/payments/amazon.js index 1ffb0c4683..9d0fdef8df 100644 --- a/website/src/controllers/payments/amazon.js +++ b/website/src/controllers/payments/amazon.js @@ -103,7 +103,15 @@ exports.checkout = function(req, res, next){ SellerAuthorizationNote: 'HabitRPG Payment', TransactionTimeout: 0, CaptureNow: true - }, cb); + }, function(err, res){ + if(err) return cb(err); + + if(res.AuthorizationDetails.AuthorizationStatus.State === 'Declined'){ + return cb(new Error('The payment was not successfull.')); + } + + return cb(); + }); }, closeOrderReference: function(cb){ diff --git a/website/views/shared/modals/buy-gems.jade b/website/views/shared/modals/buy-gems.jade index aaa88d89c9..0555250322 100644 --- a/website/views/shared/modals/buy-gems.jade +++ b/website/views/shared/modals/buy-gems.jade @@ -22,7 +22,7 @@ script(id='modals/buyGems.html', type='text/ng-template') small.muted=env.t('paymentMethods') .btn.btn-primary(ng-click='Payments.showStripe({})')=env.t('card') a.btn.btn-warning(href='/paypal/checkout?_id={{user._id}}&apiToken={{user.apiToken}}') PayPal - .btn.btn-default(ng-click="Payments.amazonPayments.init({type: 'donation'})") Amazon Payments + .btn.btn-default(ng-click="Payments.amazonPayments.init({type: 'single'})") Amazon Payments div(ng-include="'partials/options.settings.subscription.html'") diff --git a/website/views/shared/modals/members.jade b/website/views/shared/modals/members.jade index c730265936..3a22a8ebff 100644 --- a/website/views/shared/modals/members.jade +++ b/website/views/shared/modals/members.jade @@ -97,7 +97,7 @@ script(type='text/ng-template', id='modals/send-gift.html') button.btn.btn-primary(ng-show=fromBal, ng-click='sendGift(profile._id, gift)')=env.t("send") a.btn.btn-primary(ng-hide=fromBal, ng-click='Payments.showStripe({gift:gift, uuid:profile._id})')=env.t('card') a.btn.btn-warning(ng-hide=fromBal, href='/paypal/checkout?_id={{::user._id}}&apiToken={{::user.apiToken}}&gift={{Payments.encodeGift(profile._id, gift)}}') PayPal - .btn.btn-default(ng-hide="true", ng-click="Payments.amazonPayments.init({type: gift.type == 'gems' ? 'donation' : 'subscription', gift: gift, giftedTo: profile._id})") Amazon Payments + .btn.btn-default(ng-hide=fromBal, ng-click="Payments.amazonPayments.init({type: 'single', gift: gift, giftedTo: profile._id})") Amazon Payments button.btn.btn-default(ng-click='$close()')=env.t('cancel') script(type='text/ng-template', id='modals/abuse-flag.html') From e0bfd60eb1ed5c4250cd4a1380fe540967b4c710 Mon Sep 17 00:00:00 2001 From: Matteo Pagliazzi Date: Wed, 15 Jul 2015 19:39:13 +0200 Subject: [PATCH 4/4] amazon payments: switch to green button --- website/views/options/settings.jade | 2 +- website/views/shared/modals/buy-gems.jade | 2 +- website/views/shared/modals/members.jade | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/website/views/options/settings.jade b/website/views/options/settings.jade index 6b179f823f..2edba07672 100644 --- a/website/views/options/settings.jade +++ b/website/views/options/settings.jade @@ -337,7 +337,7 @@ script(id='partials/options.settings.subscription.html',type='text/ng-template') h3(ng-if='(user.purchased.plan.customerId && user.purchased.plan.dateTerminated)')= env.t("resubscribe") a.btn.btn-primary(ng-click='Payments.showStripe({subscription:_subscription.key, coupon:_subscription.coupon})', ng-disabled='!_subscription.key')= env.t('card') a.btn.btn-warning(href='/paypal/subscribe?_id={{user._id}}&apiToken={{user.apiToken}}&sub={{_subscription.key}}{{_subscription.coupon ? "&coupon="+_subscription.coupon : ""}}', ng-disabled='!_subscription.key') PayPal - a.btn.btn-default(ng-click="Payments.amazonPayments.init({type: 'subscription', subscription:_subscription.key, coupon:_subscription.coupon})") Amazon Payments + a.btn.btn-success(ng-click="Payments.amazonPayments.init({type: 'subscription', subscription:_subscription.key, coupon:_subscription.coupon})") Amazon Payments div(ng-if='user.purchased.plan.customerId') .btn.btn-primary(ng-if='!user.purchased.plan.dateTerminated && user.purchased.plan.paymentMethod=="Stripe"', ng-click='Payments.showStripeEdit()')=env.t('subUpdateCard') .btn.btn-sm.btn-danger(ng-if='!user.purchased.plan.dateTerminated', ng-click='Payments.cancelSubscription()')=env.t('cancelSub') diff --git a/website/views/shared/modals/buy-gems.jade b/website/views/shared/modals/buy-gems.jade index 0555250322..97b9c8d5ef 100644 --- a/website/views/shared/modals/buy-gems.jade +++ b/website/views/shared/modals/buy-gems.jade @@ -22,7 +22,7 @@ script(id='modals/buyGems.html', type='text/ng-template') small.muted=env.t('paymentMethods') .btn.btn-primary(ng-click='Payments.showStripe({})')=env.t('card') a.btn.btn-warning(href='/paypal/checkout?_id={{user._id}}&apiToken={{user.apiToken}}') PayPal - .btn.btn-default(ng-click="Payments.amazonPayments.init({type: 'single'})") Amazon Payments + .btn.btn-success(ng-click="Payments.amazonPayments.init({type: 'single'})") Amazon Payments div(ng-include="'partials/options.settings.subscription.html'") diff --git a/website/views/shared/modals/members.jade b/website/views/shared/modals/members.jade index 3a22a8ebff..40c395dfb6 100644 --- a/website/views/shared/modals/members.jade +++ b/website/views/shared/modals/members.jade @@ -97,7 +97,7 @@ script(type='text/ng-template', id='modals/send-gift.html') button.btn.btn-primary(ng-show=fromBal, ng-click='sendGift(profile._id, gift)')=env.t("send") a.btn.btn-primary(ng-hide=fromBal, ng-click='Payments.showStripe({gift:gift, uuid:profile._id})')=env.t('card') a.btn.btn-warning(ng-hide=fromBal, href='/paypal/checkout?_id={{::user._id}}&apiToken={{::user.apiToken}}&gift={{Payments.encodeGift(profile._id, gift)}}') PayPal - .btn.btn-default(ng-hide=fromBal, ng-click="Payments.amazonPayments.init({type: 'single', gift: gift, giftedTo: profile._id})") Amazon Payments + .btn.btn-success(ng-hide=fromBal, ng-click="Payments.amazonPayments.init({type: 'single', gift: gift, giftedTo: profile._id})") Amazon Payments button.btn.btn-default(ng-click='$close()')=env.t('cancel') script(type='text/ng-template', id='modals/abuse-flag.html')