My SMM panel
Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 
 
 
 

166 wiersze
5.2 KiB

  1. <template>
  2. <section v-if="!complete" class="select-credits">
  3. <div class="credits-pane"><h2>10 Credits</h2>
  4. <h3>$10.99</h3><div><span>Qty</span><input min="0" max="1000" v-model="packs.credits10" type="number"></div>
  5. </div>
  6. <div class="credits-pane"><div><h2>50 Credits</h2><span>+5 Free Credits</span></div>
  7. <h3>$54.99 </h3><div><span>Qty</span><input min="0" max="1000" v-model="packs.credits50" type="number"></div>
  8. </div>
  9. <div class="credits-pane"><div><h2>100 Credits</h2><span>+10 Free Credits</span></div>
  10. <h3>$109.99</h3> <div><span>Qty</span><input min="0" max="1000" v-model="packs.credits100" type="number"></div>
  11. </div>
  12. <div class="credits-pane"><div><h2>1000 Credits</h2><span>+150 Free Credits</span></div>
  13. <h3>$1010.00</h3> <div><span>Qty</span><input min="0" max="1000" v-model="packs.credits1000" type="number"></div>
  14. </div>
  15. <h3>Total: ${{total.toLocaleString('en')}}</h3>
  16. <div id="credits-errors"></div>
  17. </section>
  18. <section v-if="!complete" id="payment-section">
  19. <h4>Select a payment method</h4>
  20. <div class="sliding-menu">
  21. <a @click="selectSaved = true" :class="{selected: selectSaved}">Saved Card</a>
  22. <a @click="selectSaved = false" :class="{selected: !selectSaved}">New Card</a>
  23. <div :class="{right: !selectSaved}" class="menu-slider"><div></div></div>
  24. </div>
  25. <saved-cards :preferred="preferred" v-model:picked-card="picked" :cards="cards"
  26. :token="token" v-if="selectSaved"></saved-cards>
  27. <payment-card @set-card="(c) => {card = c}" @card-valid="(val) => {cardValid = val}"
  28. @update-billing-name="billingName = $event.target.value" :stripe="stripe"
  29. v-if="!selectSaved">
  30. </payment-card>
  31. <div>
  32. <input type="checkbox"><label>I have read and agree to the<a
  33. href="/terms-and-policy">Terms and Policy</a></label>
  34. <div class="info-grey">
  35. <span>A chargeback will result in a ban. Contact <a
  36. href="#contact">support</a>if you have any problems of concerns.</span>
  37. </div>
  38. <div id="payment-error"></div>
  39. </div>
  40. </section>
  41. <section v-if="!complete" class="credits-confirm">
  42. <button @click="pay" :disabled="!ready"
  43. class="brand-btn">Buy<loading v-if="loading"></loading></button>
  44. </section>
  45. <PurchaseCompleted v-if="complete"></PurchaseCompleted>
  46. </template>
  47. <script>
  48. import Loading from '../icons/loading.vue'
  49. import PaymentCard from './payment-card.vue'
  50. import SavedCards from './saved-cards.vue'
  51. import PurchaseCompleted from './purchase-completed.vue'
  52. function total() {
  53. return this.packs.credits10*10.99 + this.packs.credits50*54.99
  54. + this.packs.credits100*109.99 + this.packs.credits1000*1010
  55. }
  56. //Gets the secret key specific to chosen payment amount and user
  57. function getSecret() {
  58. document.getElementById('credits-errors').textContent = ''
  59. this.loading = true
  60. return fetch('/panel/secret', {
  61. method: 'POST',
  62. headers: {'Content-Type': 'application/json',
  63. 'Accept': 'application/json',
  64. 'X-XSRF-TOKEN': this.token},
  65. body: JSON.stringify({'packs': this.packs})
  66. }).then((response) => {
  67. if (response.ok) {
  68. return response.text()
  69. } else {
  70. document.getElementById('credits-errors').textContent =
  71. `${response.status}: ${response.statusText}`
  72. }
  73. }).then(secret => {
  74. this.loading = false
  75. return secret
  76. })
  77. }
  78. //Gets key from the server then sends it with stripe
  79. //Maybe it should asl attach the user's receipt email
  80. function pay() {
  81. this.getSecret().then(secret => {
  82. if (!secret) {return}
  83. this.loading = true
  84. if (!this.selectSaved) {
  85. return this.stripe.confirmCardPayment(secret, {
  86. payment_method: {
  87. card: this.card,
  88. billing_details: {name:
  89. document.getElementById('billing-name').value},
  90. },
  91. setup_future_usage: document.querySelector(
  92. "#save-card input").value == 'on' ? 'off_session' : null
  93. })
  94. } else {
  95. return this.stripe.confirmCardPayment(secret, {
  96. payment_method: this.picked
  97. })
  98. }
  99. }).then(result => {
  100. if (result.error) {
  101. document.getElementById('payment-error').textContent =
  102. result.error.message
  103. } else if (result.paymentIntent.status === 'succeeded') {
  104. setTimeout(() => {this.$emit('purchaseComplete')}, 4000)
  105. setTimeout(() => {this.$emit('purchaseComplete')}, 10000)
  106. this.complete = true
  107. } else {
  108. document.getElementById('payment-error').textContent =
  109. 'An unknown error occured'
  110. }
  111. this.loading = false
  112. })
  113. }
  114. function getCards() {
  115. fetch('/panel/cards', {
  116. method: 'GET',
  117. headers: {'Content-Type': 'application/json',
  118. 'Accept': 'application/json',
  119. 'X-XSRF-TOKEN': this.token}
  120. }).then((response) => {response.json().then(data => {
  121. this.cards = data.data
  122. if (this.cards && this.cards.length > 0) {
  123. this.picked = this.cards[0].id
  124. }
  125. })})
  126. }
  127. function ready() {
  128. return this.total != 0 && !this.loading && ((this.cardValid &&
  129. this.billingName) || this.picked)
  130. }
  131. export default {
  132. components:{Loading, PaymentCard, SavedCards, PurchaseCompleted},
  133. data() {
  134. return {packs: {credits10: 0, credits50: 0,
  135. credits100: 0, credits1000: 0}, loading: false, stripe:
  136. window.Stripe(process.env.VUE_APP_STRIPE_KEY), card:
  137. null, billingName: null, selectSaved: true, cardValid: false, cards:
  138. null, picked: null, complete: false
  139. }
  140. },
  141. computed: {total, ready},
  142. methods: {getSecret, pay, getCards},
  143. props: ['preferred', 'token'],
  144. emits: ['purchaseComplete'],
  145. created() {
  146. this.getCards()
  147. }
  148. }
  149. </script>