Pārlūkot izejas kodu

Process and handle payeer payments

The vue components relevant to stripe were replaced with payeer's
components. A function was added to the user's controller to ease
transaction completion logic. Storing the paying state in the database is
more provider agnostic and avoids having to learn the request parameters
of payeer's redirects.
master
Immanuel Onyeka pirms 3 gadiem
vecāks
revīzija
0d977507f7
9 mainītis faili ar 128 papildinājumiem un 41 dzēšanām
  1. +49
    -7
      app/Http/Controllers/BillingController.php
  2. +10
    -0
      app/Http/Controllers/UserController.php
  3. +5
    -5
      resources/js/panel/credits.vue
  4. +12
    -2
      resources/js/panel/panel.vue
  5. +0
    -9
      resources/js/panel/purchase-completed.vue
  6. +19
    -16
      resources/js/panel/services.vue
  7. +28
    -0
      resources/js/panel/transaction-endpoint.vue
  8. +3
    -0
      resources/scss/main.scss
  9. +2
    -2
      resources/views/home.blade.php

+ 49
- 7
app/Http/Controllers/BillingController.php Parādīt failu

@@ -91,15 +91,9 @@ class BillingController extends Controller
$event = \Stripe\Event::constructFrom($request->all());
$charge = $event->data->object;
$transaction = Transaction::where('intent_id', $charge->payment_intent)->first();
$user = $transaction->user;

if ($event->type == 'charge.succeeded') {
$user->credits = $user->credits + $transaction->credits + $transaction->credits_extra;
$transaction->status = 'completed';
$transaction->completed = true;
$user->save();
$transaction->save();

$this->creditUser($transaction->id)
} else {
$transaction->status = $charge->status;
$transaction->save();
@@ -159,6 +153,54 @@ class BillingController extends Controller
$transaction->charge/100, 'description' => $description ];
}

//This needs to check the ip of the sender
public function processPayeer(Request $request) {
$secret = config('services.payeer.secret');
$arHash = [$request->m_operation_id,
$request->m_operation_ps,
$request->m_operation_day,
$request->m_operation_pay_date,
$request->m_shop,
$request->m_orderid,
$request->m_amount,
$request->m_curr,
$request->m_desc,
$request->m_status
];
if (isset($request->m_params)) {
$arHash[] = $request->m_params;
}

$arHash[] = $secret;

$signature = strtoupper(hash('sha256', implode(':', $arHash)));
if ($signature == $request->m_sign && $request->m_status == 'success')
{
$this->creditUser((int) $request->m_orderid)
return $request->m_orderid.'|success';
} else {
return $request->m_orderid.'|error';
$transaction = Transaction::find($request->orderid);
$transaction->status = 'error';
$transaction->save();
}
}

//Credits the user of a given transaction id
public function creditUser($transaction_id) {
$transaction = Transaction::find($transaction_id);

if ($transaction->completed) {
return;
}

$user = $transaction->user;
$user->credits = $user->credits + $transaction->credits +
$transaction->credits_extra;
$transaction->status = 'completed';
$transaction->completed = true;

$user->save();
$transaction->save();
}
}

+ 10
- 0
app/Http/Controllers/UserController.php Parādīt failu

@@ -77,6 +77,7 @@ class UserController extends Controller
//This should probably be changed to not return a page
if (Auth::attempt($credentials)) {
$request->session()->regenerate();
$this->clearPaying();
} else {
abort(401);
}
@@ -155,4 +156,13 @@ class UserController extends Controller
$user->password = Hash::make($request->password);
$user->save();
}

public function clearPaying() {
$user = Auth::user();
if ($user->paying) {
$user->paying = false;
$user->save();
}
}

}

+ 5
- 5
resources/js/panel/credits.vue Parādīt failu

@@ -1,5 +1,5 @@
<template>
<section v-if="!complete" class="select-credits">
<section class="select-credits">
<div class="credits-pane"><h2>10 Credits</h2>
<h3>$10.99</h3><div><span>Qty</span><input min="0" max="1000" v-model="packs.credits10" type="number"></div>
</div>
@@ -19,7 +19,7 @@
<div id="credits-errors"></div>
</section>

<section v-if="!complete" id="payment-section">
<section id="payment-section">
<h4>Select a payment method</h4>

<div class="sliding-menu">
@@ -42,12 +42,12 @@

<div id="agreement-check">
<input v-model="agreed" type="checkbox"><label>I have read and agree to the <a
href="/terms-and-policy">Terms and Policy</a> and will not pursue a fraudulent dispute or chargeback.</label>
href="/terms-and-policy">Terms and Policy</a> and will not pursue a dispute or chargeback.</label>
<div id="payment-error"></div>
</div>
</section>

<section v-if="!complete" class="credits-confirm">
<section class="credits-confirm">
<button @click="pay" :disabled="!ready"
class="brand-btn">Buy<loading v-if="loading"></loading></button>
</section>
@@ -151,7 +151,7 @@ export default {
data() {
return {packs: {credits10: 0, credits50: 0,
credits100: 0, credits1000: 0}, loading: false, method: 'payeer',
complete: false, agreed: false
agreed: false
}
},
computed: {total, ready},


+ 12
- 2
resources/js/panel/panel.vue Parādīt failu

@@ -37,7 +37,15 @@
<a href="/logout">Logout</a>
</section>
</div>
<settings :token="token" :user="user" class="settings-page" id="main" v-else-if="active === '#settings'"></settings>

<settings :token="token" :user="user" class="settings-page" id="main"
v-else-if="active === '#settings'">
</settings>

<transaction-end :token="token" :user="user" :active="active" v-else-if="active ==
'#transaction-complete' || active == '#transaction-failed'">
</transaction-end>

</transition>
</template>
</template>
@@ -47,6 +55,7 @@ import Sidebar from './sidebar.vue'
import Settings from './settings.vue'
import PastOrders from './orders.vue'
import NewOrder from './services.vue'
import TransactionEnd from './transaction-endpoint.vue'

function getServices() {
return fetch("/panel/services", {
@@ -87,7 +96,8 @@ function getOrders() {

export default {
components: {
Sidebar, Settings, PastOrders, NewOrder,
Sidebar, Settings, PastOrders, NewOrder,
TransactionEnd
},
data() {
return {active: window.location.hash, user: null,


+ 0
- 9
resources/js/panel/purchase-completed.vue Parādīt failu

@@ -1,9 +0,0 @@
<template>
<div class="status-dialog">
<img class="icon" src="../../images/checked2.svg" alt=""/>
<h3>Purchase complete. A receipt will be emailed to you.</h3>
</div>
</template>

<script>
</script>

+ 19
- 16
resources/js/panel/services.vue Parādīt failu

@@ -14,9 +14,14 @@
</div>

<ServicePane :site="'youtube'" :services="services"
@select="select"></ServicePane> <ServicePane :site="'instagram'"
:services="services" @select="select"></ServicePane> <ServicePane
:site="'twitter'" :services="services" @select="select"></ServicePane>
@select="select"></ServicePane>

<ServicePane :site="'instagram'" :services="services"
@select="select"></ServicePane>

<ServicePane :site="'twitter'" :services="services"
@select="select"></ServicePane>

<ServicePane :site="'tiktok'" :services="services"
@select="select"></ServicePane>

@@ -68,7 +73,7 @@
<div><input required type="url" id="url" v-model="url"></div>
<button @click="buyService" :disabled="paying">Submit<loading
v-if="paying"></loading></button>
<p id="overlay-error"></p>
<p id="overlay-error">{{errorText}}</p>
</div>

<div class="overlay-item" v-else-if="completed">
@@ -100,8 +105,9 @@ function select(service) {
if (this.amount > service.maximum){
this.amount = service.maximum;
}

this.selected = service
document.getElementById('overlay-error').textContent = ''
this.errorText = ''
}

function cost() {
@@ -110,15 +116,13 @@ function cost() {

function buyService() {
if (!this.url) {
document.getElementById('overlay-error').textContent = "You must provide a URL."
this.errorText = "You must provide a URL."
return
} else if (Math.ceil(this.cost > this.credits)) {
document.getElementById('overlay-error').textContent =
'Insuficient Credits'
this.errorText = 'Insuficient Credits'
return
} else if (this.amount < this.selected.minimum || this.amount > this.selected.maximum) {
document.getElementById('overlay-error').textContent =
'Invalid amount'
this.errorText = 'Invalid amount'
return
}

@@ -142,16 +146,15 @@ function buyService() {
'quantity': this.amount, 'url': this.url, 'note': note}), }).then(
response => {
if (response.ok) {
document.getElementById('overlay-error').textContent = `Success!`
this.errorText = `Success!`
this.completed = true
this.$emit('updateUser')
this.$emit('updateOrders')
} else if (response.status == 520) {
document.getElementById('overlay-error').textContent =
'Insuficient Credits'
this.errorText = 'Insuficient Credits'
} else {
document.getElementById('overlay-error').textContent = `Error
${response.status}: ${response.statusText}`
this.errorText = `Error ${response.status}:
${response.statusText}`
}

this.paying = false
@@ -172,7 +175,7 @@ function page() {
export default {
data() {
return {servicePane: true, services: null, selected: null, amount: 0,
paying: false, url: '', completed: false}
paying: false, url: '', completed: false, errorText: ''}
},
components: {ServicePane, Loading, Credits},
props: ['token', 'credits', 'active', 'preferred'],


+ 28
- 0
resources/js/panel/transaction-endpoint.vue Parādīt failu

@@ -0,0 +1,28 @@
<template>
<div id="main">

<div v-once v-if="active == '#transaction-complete' && user.paying" class="status-dialog">
<img class="icon" src="../../images/checked2.svg" alt=""/>
<h3>Purchase complete.</h3>
</div>

<div v-once v-if="active == '#transaction-failed' && user.paying" class="status-dialog">
<img class="icon" src="../../images/warning-colored.svg" alt=""/>
<h3>Purchase failed.</h3>
</div>

</div>
</template>

<script>
export default {
props: ['token', 'user', 'active'],

//Should check that user is actualling in the paying state. If so, send get
//request to panel/transaction-end. It's then() should emit a payment
//complete to panel for a user state refresh.
mounted() {
}
}
</script>

+ 3
- 0
resources/scss/main.scss Parādīt failu

@@ -1267,8 +1267,11 @@ div#card-errors {
}

.status-dialog {
position: relative;
top: 15%;
margin: auto;
max-width: 20em;
text-align: center;

img {
margin: auto;


+ 2
- 2
resources/views/home.blade.php Parādīt failu

@@ -193,8 +193,8 @@
</p></div></div>
<div class="collapsible"><button>How can I pay?</button>
<div class="content"><p>
We accept Bitcoin, Litecoin, and other cryptocurrencies through our
Payeer and Perfect Money payment providers.
We accept Bitcoin, Litecoin, and other cryptocurrencies, as well as USD
through our Payeer and Perfect Money payment providers.
</p></div></div>

</div>


Notiek ielāde…
Atcelt
Saglabāt