Amazon payment fixes (#9562)

* Added custom amazon event, removed redundency, fixed variable names

* Fixed more variables and group plan data
This commit is contained in:
Keith Holliday
2017-11-21 14:02:40 -06:00
committed by GitHub
parent 3ffea4332e
commit 9eaa531f66
7 changed files with 91 additions and 138 deletions

View File

@@ -1,5 +1,6 @@
<template lang="pug"> <template lang="pug">
#app(:class='{"casting-spell": castingSpell}') #app(:class='{"casting-spell": castingSpell}')
amazon-payments-modal
snackbars snackbars
router-view(v-if="!isUserLoggedIn || isStaticPage") router-view(v-if="!isUserLoggedIn || isStaticPage")
template(v-else) template(v-else)
@@ -82,6 +83,7 @@ import BuyModal from './components/shops/buyModal.vue';
import SelectMembersModal from 'client/components/selectMembersModal.vue'; import SelectMembersModal from 'client/components/selectMembersModal.vue';
import notifications from 'client/mixins/notifications'; import notifications from 'client/mixins/notifications';
import { setup as setupPayments } from 'client/libs/payments'; import { setup as setupPayments } from 'client/libs/payments';
import amazonPaymentsModal from 'client/components/payments/amazonModal';
export default { export default {
mixins: [notifications], mixins: [notifications],
@@ -94,6 +96,7 @@ export default {
snackbars, snackbars,
BuyModal, BuyModal,
SelectMembersModal, SelectMembersModal,
amazonPaymentsModal,
}, },
data () { data () {
return { return {

View File

@@ -1,7 +1,6 @@
<template lang="pug"> <template lang="pug">
// @TODO: Move to group plans folder // @TODO: Move to group plans folder
div div
amazon-payments-modal(:amazon-payments-prop='amazonPayments')
div div
.header .header
h1.text-center Need more for your Group? h1.text-center Need more for your Group?
@@ -78,7 +77,7 @@ div
div Each Additional div Each Additional
div Member div Member
b-modal#group-plan-modal(title="Empty", size='md', hide-footer=true) b-modal#group-plan-modal(title="Select Payment", size='md', hide-footer=true)
.col-12(v-if='activePage === PAGES.CREATE_GROUP') .col-12(v-if='activePage === PAGES.CREATE_GROUP')
.form-group .form-group
label.control-label(for='new-group-name') Name label.control-label(for='new-group-name') Name
@@ -200,6 +199,9 @@ div
box-shadow: 0 2px 2px 0 rgba(26, 24, 29, 0.16), 0 1px 4px 0 rgba(26, 24, 29, 0.12); box-shadow: 0 2px 2px 0 rgba(26, 24, 29, 0.16), 0 1px 4px 0 rgba(26, 24, 29, 0.12);
padding: 2em; padding: 2em;
text-align: center; text-align: center;
display: inline-block !important;
vertical-align: bottom;
margin-right: 1em;
img { img {
margin: 0 auto; margin: 0 auto;
@@ -321,7 +323,6 @@ div
<script> <script>
import paymentsMixin from '../../mixins/payments'; import paymentsMixin from '../../mixins/payments';
import amazonPaymentsModal from '../payments/amazonModal';
import { mapState } from 'client/libs/store'; import { mapState } from 'client/libs/store';
import group from 'assets/svg/group.svg'; import group from 'assets/svg/group.svg';
import amazonpay from 'assets/svg/amazonpay.svg'; import amazonpay from 'assets/svg/amazonpay.svg';
@@ -329,9 +330,6 @@ import positiveIcon from 'assets/svg/positive.svg';
export default { export default {
mixins: [paymentsMixin], mixins: [paymentsMixin],
components: {
amazonPaymentsModal,
},
data () { data () {
return { return {
amazonPayments: {}, amazonPayments: {},
@@ -405,6 +403,7 @@ export default {
if (this.paymentMethod === this.PAYMENTS.STRIPE) { if (this.paymentMethod === this.PAYMENTS.STRIPE) {
this.showStripe(paymentData); this.showStripe(paymentData);
} else if (this.paymentMethod === this.PAYMENTS.AMAZON) { } else if (this.paymentMethod === this.PAYMENTS.AMAZON) {
paymentData.type = 'subscription';
this.amazonPaymentsInit(paymentData); this.amazonPaymentsInit(paymentData);
} }
}, },

View File

@@ -2,8 +2,8 @@
b-modal#amazon-payment(title="Amazon", :hide-footer="true", size='md') b-modal#amazon-payment(title="Amazon", :hide-footer="true", size='md')
h2.text-center Continue with Amazon h2.text-center Continue with Amazon
#AmazonPayButton #AmazonPayButton
#AmazonPayWallet(v-if="amazonLoggedIn", style="width: 400px; height: 228px;") #AmazonPayWallet(v-if="amazonPayments.loggedIn", style="width: 400px; height: 228px;")
#AmazonPayRecurring(v-if="amazonLoggedIn && amazonPayments.type === 'subscription'", #AmazonPayRecurring(v-if="amazonPayments.loggedIn && amazonPayments.type === 'subscription'",
style="width: 400px; height: 140px;") style="width: 400px; height: 140px;")
.modal-footer .modal-footer
.text-center .text-center
@@ -30,40 +30,35 @@ import { mapState } from 'client/libs/store';
const AMAZON_PAYMENTS = process.env.AMAZON_PAYMENTS; // eslint-disable-line const AMAZON_PAYMENTS = process.env.AMAZON_PAYMENTS; // eslint-disable-line
export default { export default {
props: ['amazonPaymentsProp'],
data () { data () {
return { return {
amazonPayments: {
modal: null,
type: null,
gift: null,
loggedIn: false,
paymentSelected: false,
billingAgreementId: '',
recurringConsent: false,
orderReferenceId: null,
subscription: null,
coupon: null,
},
OffAmazonPayments: {}, OffAmazonPayments: {},
isAmazonSetup: false, isAmazonSetup: false,
amazonButtonEnabled: false, amazonButtonEnabled: false,
amazonPaymentsbillingAgreementId: '',
amazonPaymentspaymentSelected: false,
amazonPaymentsrecurringConsent: 'false',
amazonLoggedIn: false,
}; };
}, },
computed: { computed: {
...mapState({user: 'user.data'}), ...mapState({user: 'user.data'}),
...mapState(['isAmazonReady']), ...mapState(['isAmazonReady']),
// @TODO: Eh, idk if we should move data props here or move these props to data. But we shouldn't have both
amazonPayments () {
let amazonPayments = {
type: 'single',
loggedIn: this.amazonLoggedIn,
};
amazonPayments = Object.assign({}, amazonPayments, this.amazonPaymentsProp);
return amazonPayments;
},
amazonPaymentsCanCheckout () { amazonPaymentsCanCheckout () {
if (this.amazonPayments.type === 'single') { if (this.amazonPayments.type === 'single') {
return this.amazonPaymentspaymentSelected === true; return this.amazonPayments.paymentSelected === true;
} else if (this.amazonPayments.type === 'subscription') { } else if (this.amazonPayments.type === 'subscription') {
return this.amazonPaymentspaymentSelected === true && return this.amazonPayments.paymentSelected && this.amazonPayments.recurringConsent;
// Mah.. one is a boolean the other a string...
this.amazonPaymentsrecurringConsent === 'true';
} else {
return false;
} }
return false;
}, },
}, },
mounted () { mounted () {
@@ -72,6 +67,21 @@ export default {
this.$store.watch(state => state.isAmazonReady, (isAmazonReady) => { this.$store.watch(state => state.isAmazonReady, (isAmazonReady) => {
if (isAmazonReady) return this.setupAmazon(); if (isAmazonReady) return this.setupAmazon();
}); });
this.$root.$on('habitica::pay-with-amazon', (amazonPaymentsData) => {
if (!amazonPaymentsData) return;
let amazonPayments = {
type: 'single',
loggedIn: false,
};
this.amazonPayments = Object.assign({}, amazonPayments, amazonPaymentsData);
this.$root.$emit('bv::show::modal', 'amazon-payment');
});
},
destroyed () {
this.$root.$off('habitica::pay-with-amazon');
}, },
methods: { methods: {
setupAmazon () { setupAmazon () {
@@ -90,25 +100,21 @@ export default {
color: 'Gold', color: 'Gold',
size: 'small', size: 'small',
agreementType: 'BillingAgreement', agreementType: 'BillingAgreement',
onSignIn: async (contract) => { onSignIn: async (contract) => {
this.amazonPaymentsbillingAgreementId = contract.getAmazonBillingAgreementId(); this.amazonPayments.billingAgreementId = contract.getAmazonBillingAgreementId();
this.amazonLoggedIn = true;
this.$set(this.amazonPayments, 'loggedIn', true); this.$set(this.amazonPayments, 'loggedIn', true);
if (this.amazonPayments.type === 'subscription') { if (this.amazonPayments.type === 'subscription') {
this.amazonPaymentsinitWidgets(); this.amazonInitWidgets();
} else { } else {
let url = '/amazon/createOrderReferenceId'; let url = '/amazon/createOrderReferenceId';
let response = await axios.post(url, { let response = await axios.post(url, {
billingAgreementId: this.amazonPaymentsbillingAgreementId, billingAgreementId: this.amazonPayments.billingAgreementId,
}); });
if (response.status <= 400) { if (response.status <= 400) {
this.amazonPayments.orderReferenceId = response.data.data.orderReferenceId; this.amazonPayments.orderReferenceId = response.data.data.orderReferenceId;
// @TODO: Clarify the deifference of these functions by renaming
this.amazonPaymentsinitWidgets();
this.amazonInitWidgets(); this.amazonInitWidgets();
return; return;
} }
@@ -116,7 +122,6 @@ export default {
alert(response.message); alert(response.message);
} }
}, },
authorization: () => { authorization: () => {
window.amazon.Login.authorize({ window.amazon.Login.authorize({
scope: 'payments:widget', scope: 'payments:widget',
@@ -131,7 +136,6 @@ export default {
}); });
}); });
}, },
onError: this.amazonOnError, onError: this.amazonOnError,
}); });
}, },
@@ -141,38 +145,29 @@ export default {
design: { design: {
designMode: 'responsive', designMode: 'responsive',
}, },
onPaymentSelect: this.amazonOnPaymentSelect,
onPaymentSelect: () => {
this.amazonPaymentspaymentSelected = true;
},
onError: this.amazonOnError, onError: this.amazonOnError,
}; };
// @TODO: Check if this is duplicated below
if (this.amazonPayments.type === 'subscription') { if (this.amazonPayments.type === 'subscription') {
walletParams.agreementType = 'BillingAgreement'; walletParams.agreementType = 'BillingAgreement';
walletParams.billingAgreementId = this.amazonPayments.billingAgreementId;
walletParams.billingAgreementId = this.amazonPaymentsbillingAgreementId;
walletParams.onReady = (billingAgreement) => { walletParams.onReady = (billingAgreement) => {
this.amazonPaymentsbillingAgreementId = billingAgreement.getAmazonBillingAgreementId(); this.amazonPayments.billingAgreementId = billingAgreement.getAmazonBillingAgreementId();
new this.OffAmazonPayments.Widgets.Consent({ new this.OffAmazonPayments.Widgets.Consent({
sellerId: AMAZON_PAYMENTS.SELLER_ID, sellerId: AMAZON_PAYMENTS.SELLER_ID,
amazonBillingAgreementId: this.amazonPaymentsbillingAgreementId, amazonBillingAgreementId: this.amazonPayments.billingAgreementId,
design: { design: {
designMode: 'responsive', designMode: 'responsive',
}, },
onReady: (consent) => { onReady: (consent) => {
let getConsent = consent.getConsentStatus; let getConsent = consent.getConsentStatus;
this.amazonPaymentsrecurringConsent = getConsent ? getConsent() : false; this.$set(this.amazonPayments, 'recurringConsent', getConsent ? Boolean(getConsent()) : false);
}, },
onConsent: (consent) => { onConsent: (consent) => {
this.amazonPaymentsrecurringConsent = consent.getConsentStatus(); this.$set(this.amazonPayments, 'recurringConsent', Boolean(consent.getConsentStatus()));
}, },
onError: this.amazonOnError, onError: this.amazonOnError,
}).bind('AmazonPayRecurring'); }).bind('AmazonPayRecurring');
}; };
@@ -191,7 +186,7 @@ export default {
let url = '/amazon/checkout'; let url = '/amazon/checkout';
let response = await axios.post(url, { let response = await axios.post(url, {
orderReferenceId: this.amazonPayments.orderReferenceId, orderReferenceId: this.amazonPayments.orderReferenceId,
gift: this.amazonPaymentsgift, gift: this.amazonPayments.gift,
}); });
if (response.status < 400) { if (response.status < 400) {
@@ -211,7 +206,7 @@ export default {
} }
let response = await axios.post(url, { let response = await axios.post(url, {
billingAgreementId: this.amazonPaymentsbillingAgreementId, billingAgreementId: this.amazonPayments.billingAgreementId,
subscription: this.amazonPayments.subscription, subscription: this.amazonPayments.subscription,
coupon: this.amazonPayments.coupon, coupon: this.amazonPayments.coupon,
groupId: this.amazonPayments.groupId, groupId: this.amazonPayments.groupId,
@@ -243,67 +238,26 @@ export default {
this.reset(); this.reset();
} }
}, },
amazonPaymentsinitWidgets () { amazonOnPaymentSelect () {
let walletParams = { this.$set(this.amazonPayments, 'paymentSelected', true);
sellerId: AMAZON_PAYMENTS.SELLER_ID,
design: {
designMode: 'responsive',
},
onPaymentSelect: () => {
this.amazonPayments.paymentSelected = true;
},
onError: this.amazonOnError,
};
if (this.amazonPayments.type === 'subscription') {
walletParams.agreementType = 'BillingAgreement';
walletParams.billingAgreementId = this.amazonPayments.billingAgreementId;
walletParams.onReady = (billingAgreement) => {
this.amazonPayments.billingAgreementId = billingAgreement.getAmazonBillingAgreementId();
new this.OffAmazonPayments.Widgets.Consent({
sellerId: AMAZON_PAYMENTS.SELLER_ID,
amazonBillingAgreementId: this.amazonPayments.billingAgreementId,
design: {
designMode: 'responsive',
},
onReady: (consent) => {
let getConsent = consent.getConsentStatus;
this.amazonPayments.recurringConsent = getConsent ? getConsent() : false;
},
onConsent: (consent) => {
this.amazonPayments.recurringConsent = consent.getConsentStatus();
},
onError: this.amazonOnError,
}).bind('AmazonPayRecurring');
};
} else {
walletParams.amazonOrderReferenceId = this.amazonPayments.orderReferenceId;
}
new this.OffAmazonPayments.Widgets.Wallet(walletParams).bind('AmazonPayWallet');
}, },
amazonOnError (error) { amazonOnError (error) {
alert(error.getErrorMessage()); alert(error.getErrorMessage());
this.reset(); this.reset();
}, },
reset () { reset () {
this.amazonPaymentsmodal = null; // @TODO: Ensure we are using all of these
// some vars are set in the payments mixin. We should try to edit in one place
this.amazonPayments.modal = null;
this.amazonPayments.type = null; this.amazonPayments.type = null;
this.amazonLoggedIn = false; this.amazonPayments.loggedIn = false;
this.amazonPaymentsgift = null; this.amazonPayments.gift = null;
this.amazonPaymentsbillingAgreementId = null; this.amazonPayments.billingAgreementId = null;
this.amazonPayments.orderReferenceId = null; this.amazonPayments.orderReferenceId = null;
this.amazonPaymentspaymentSelected = false; this.amazonPayments.paymentSelected = false;
this.amazonPaymentsrecurringConsent = false; this.amazonPayments.recurringConsent = false;
this.amazonPaymentssubscription = null; this.amazonPayments.subscription = null;
this.amazonPaymentscoupon = null; this.amazonPayments.coupon = null;
}, },
}, },
}; };

View File

@@ -7,7 +7,6 @@
.col-md-8.align-self-center .col-md-8.align-self-center
p=text p=text
div(v-if='user') div(v-if='user')
amazon-payments-modal(:amazon-payments-prop='amazonPayments')
b-modal(:hide-footer='true', :hide-header='true', :id='"buy-gems"', size='lg') b-modal(:hide-footer='true', :hide-header='true', :id='"buy-gems"', size='lg')
.container-fluid.purple-gradient .container-fluid.purple-gradient
.gemfall .gemfall
@@ -344,7 +343,6 @@
import markdown from 'client/directives/markdown'; import markdown from 'client/directives/markdown';
import planGemLimits from 'common/script/libs/planGemLimits'; import planGemLimits from 'common/script/libs/planGemLimits';
import paymentsMixin from 'client/mixins/payments'; import paymentsMixin from 'client/mixins/payments';
import amazonPaymentsModal from './amazonModal';
import checkIcon from 'assets/svg/check.svg'; import checkIcon from 'assets/svg/check.svg';
import creditCard from 'assets/svg/credit-card.svg'; import creditCard from 'assets/svg/credit-card.svg';
@@ -360,7 +358,6 @@
mixins: [paymentsMixin], mixins: [paymentsMixin],
components: { components: {
planGemLimits, planGemLimits,
amazonPaymentsModal,
}, },
computed: { computed: {
...mapState({user: 'user.data'}), ...mapState({user: 'user.data'}),

View File

@@ -5,7 +5,6 @@ b-modal#send-gems(:title="title", :hide-footer="true", size='lg')
:class="gift.type === 'gems' ? 'panel-primary' : 'transparent'", :class="gift.type === 'gems' ? 'panel-primary' : 'transparent'",
@click='gift.type = "gems"' @click='gift.type = "gems"'
) )
// @TODO the panel does not exists in Bootstrap 4
h3.panel-heading.clearfix h3.panel-heading.clearfix
.float-right .float-right
span(v-if='gift.gems.fromBalance') {{ $t('sendGiftGemsBalance', {number: userLoggedIn.balance * 4}) }} span(v-if='gift.gems.fromBalance') {{ $t('sendGiftGemsBalance', {number: userLoggedIn.balance * 4}) }}
@@ -51,26 +50,26 @@ b-modal#send-gems(:title="title", :hide-footer="true", size='lg')
</template> </template>
<style lang="scss"> <style lang="scss">
.panel { .panel {
margin-bottom: 4px; margin-bottom: 4px;
&.transparent {
.panel-body {
opacity: 0.7;
}
}
.panel-heading {
margin-top: 8px;
margin-bottom: 5px;
}
&.transparent {
.panel-body { .panel-body {
opacity: 0.7; padding: 8px;
border-radius: 2px;
border: 1px solid #C3C0C7;
} }
} }
.panel-heading {
margin-top: 8px;
margin-bottom: 5px;
}
.panel-body {
padding: 8px;
border-radius: 2px;
border: 1px solid #C3C0C7;
}
}
</style> </style>
<script> <script>

View File

@@ -1,7 +1,5 @@
<template lang="pug"> <template lang="pug">
.standard-page .standard-page
amazon-payments-modal(:amazon-payments-prop='amazonPayments')
h1 {{ $t('subscription') }} h1 {{ $t('subscription') }}
.row .row
.col-6 .col-6
@@ -82,9 +80,8 @@
a.purchase(:href='paypalPurchaseLink', :disabled='!subscription.key', target='_blank') a.purchase(:href='paypalPurchaseLink', :disabled='!subscription.key', target='_blank')
img(src='https://www.paypalobjects.com/webstatic/en_US/i/buttons/pp-acceptance-small.png', :alt="$t('paypal')") img(src='https://www.paypalobjects.com/webstatic/en_US/i/buttons/pp-acceptance-small.png', :alt="$t('paypal')")
.col-md-4 .col-md-4
a.btn.btn-secondary.purchase(@click="amazonPaymentsInit({type: 'subscription', subscription:subscription.key, coupon:subscription.coupon})") a.btn.btn-secondary.purchase(@click="payWithAmazon()")
img(src='https://payments.amazon.com/gp/cba/button', :alt="$t('amazonPayments')") img(src='https://payments.amazon.com/gp/cba/button', :alt="$t('amazonPayments')")
.row .row
.col-6 .col-6
h2 {{ $t('giftSubscription') }} h2 {{ $t('giftSubscription') }}
@@ -115,14 +112,10 @@ import { mapState } from 'client/libs/store';
import subscriptionBlocks from '../../../common/script/content/subscriptionBlocks'; import subscriptionBlocks from '../../../common/script/content/subscriptionBlocks';
import planGemLimits from '../../../common/script/libs/planGemLimits'; import planGemLimits from '../../../common/script/libs/planGemLimits';
import amazonPaymentsModal from '../payments/amazonModal';
import paymentsMixin from '../../mixins/payments'; import paymentsMixin from '../../mixins/payments';
export default { export default {
mixins: [paymentsMixin], mixins: [paymentsMixin],
components: {
amazonPaymentsModal,
},
data () { data () {
return { return {
gemCostTranslation: { gemCostTranslation: {
@@ -132,6 +125,7 @@ export default {
subscription: { subscription: {
key: 'basic_earned', key: 'basic_earned',
}, },
// @TODO: Remove the need for this or move it to mixin
amazonPayments: {}, amazonPayments: {},
paymentMethods: { paymentMethods: {
AMAZON_PAYMENTS: 'Amazon Payments', AMAZON_PAYMENTS: 'Amazon Payments',
@@ -247,6 +241,13 @@ export default {
}, },
}, },
methods: { methods: {
payWithAmazon () {
this.amazonPaymentsInit({
type: 'subscription',
subscription: this.subscription.key,
coupon: this.subscription.coupon,
});
},
async applyCoupon (coupon) { async applyCoupon (coupon) {
let response = await axios.get(`/api/v3/coupons/validate/${coupon}`); let response = await axios.get(`/api/v3/coupons/validate/${coupon}`);

View File

@@ -169,7 +169,7 @@ export default {
this.amazonPayments.gift = data.gift; this.amazonPayments.gift = data.gift;
this.amazonPayments.type = data.type; this.amazonPayments.type = data.type;
this.$root.$emit('bv::show::modal', 'amazon-payment'); this.$root.$emit('habitica::pay-with-amazon', this.amazonPayments);
}, },
async cancelSubscription (config) { async cancelSubscription (config) {
if (config && config.group && !confirm(this.$t('confirmCancelGroupPlan'))) return; if (config && config.group && !confirm(this.$t('confirmCancelGroupPlan'))) return;