Implemented paypal payments

This commit is contained in:
Eduard Urbach 2017-07-17 03:14:05 +02:00
parent d33b93d115
commit 4f9cea89df
8 changed files with 128 additions and 12 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 296 KiB

View File

@ -5,11 +5,18 @@ import (
"github.com/aerogo/aero" "github.com/aerogo/aero"
"github.com/animenotifier/arn" "github.com/animenotifier/arn"
"github.com/animenotifier/notify.moe/utils"
"github.com/logpacker/PayPal-Go-SDK" "github.com/logpacker/PayPal-Go-SDK"
) )
// CreatePayment ... // CreatePayment ...
func CreatePayment(ctx *aero.Context) string { func CreatePayment(ctx *aero.Context) string {
user := utils.GetUser(ctx)
if user == nil {
return ctx.Error(http.StatusUnauthorized, "Not logged in", nil)
}
c, err := arn.PayPal() c, err := arn.PayPal()
if err != nil { if err != nil {
@ -56,9 +63,9 @@ func CreatePayment(ctx *aero.Context) string {
Transactions: []paypalsdk.Transaction{paypalsdk.Transaction{ Transactions: []paypalsdk.Transaction{paypalsdk.Transaction{
Amount: &paypalsdk.Amount{ Amount: &paypalsdk.Amount{
Currency: "USD", Currency: "USD",
Total: "7.00", Total: "10.00",
}, },
Description: "Pro Account", Description: "Top Up Balance",
}}, }},
RedirectURLs: &paypalsdk.RedirectURLs{ RedirectURLs: &paypalsdk.RedirectURLs{
ReturnURL: "https://" + ctx.App.Config.Domain + "/paypal/success", ReturnURL: "https://" + ctx.App.Config.Domain + "/paypal/success",

View File

@ -1,17 +1,33 @@
package paypal package paypal
import ( import (
"errors"
"net/http" "net/http"
"strconv"
"github.com/aerogo/aero" "github.com/aerogo/aero"
"github.com/animenotifier/arn" "github.com/animenotifier/arn"
"github.com/animenotifier/notify.moe/components"
"github.com/animenotifier/notify.moe/utils"
) )
const adminID = "4J6qpK1ve"
// Success ... // Success ...
func Success(ctx *aero.Context) string { func Success(ctx *aero.Context) string {
user := utils.GetUser(ctx)
if user == nil {
return ctx.Error(http.StatusUnauthorized, "Not logged in", nil)
}
paymentID := ctx.Query("paymentId") paymentID := ctx.Query("paymentId")
// token := ctx.Query("token") token := ctx.Query("token")
// payerID := ctx.Query("PayerID") payerID := ctx.Query("PayerID")
if paymentID == "" || payerID == "" || token == "" {
return ctx.Error(http.StatusBadRequest, "Invalid parameters", errors.New("paymentId, token and PayerID are required"))
}
c, err := arn.PayPal() c, err := arn.PayPal()
@ -19,19 +35,63 @@ func Success(ctx *aero.Context) string {
return ctx.Error(http.StatusInternalServerError, "Could not initiate PayPal client", err) return ctx.Error(http.StatusInternalServerError, "Could not initiate PayPal client", err)
} }
_, err = c.GetAccessToken() c.SetAccessToken(token)
execute, err := c.ExecuteApprovedPayment(paymentID, payerID)
if err != nil { if err != nil {
return ctx.Error(http.StatusInternalServerError, "Could not get PayPal access token", err) return ctx.Error(http.StatusInternalServerError, "Error executing PayPal payment", err)
} }
payment, err := c.GetPayment(paymentID) if execute.State != "approved" {
return ctx.Error(http.StatusInternalServerError, "PayPal payment has not been approved", err)
}
sdkPayment, err := c.GetPayment(paymentID)
if err != nil { if err != nil {
return ctx.Error(http.StatusInternalServerError, "Could not retrieve payment information", err) return ctx.Error(http.StatusInternalServerError, "Could not retrieve payment information", err)
} }
arn.PrettyPrint(payment) arn.PrettyPrint(sdkPayment)
return ctx.HTML("success") transaction := sdkPayment.Transactions[0]
payment := &arn.PayPalPayment{
ID: paymentID,
PayerID: payerID,
UserID: user.ID,
Method: sdkPayment.Payer.PaymentMethod,
Amount: transaction.Amount.Total,
Currency: transaction.Amount.Currency,
Created: arn.DateTimeUTC(),
}
err = payment.Save()
if err != nil {
return ctx.Error(http.StatusInternalServerError, "Could not save payment in the database", err)
}
// Increase user's balance
user.Balance += payment.AnimeDollar()
// Save in DB
err = user.Save()
if err != nil {
return ctx.Error(http.StatusInternalServerError, "Could not save new balance", err)
}
// Notify admin
go func() {
admin, _ := arn.GetUser(adminID)
admin.SendNotification(&arn.Notification{
Title: user.Nick + " bought " + strconv.Itoa(payment.AnimeDollar()) + " AD",
Message: user.Nick + " paid " + payment.Amount + " " + payment.Currency + " making his new balance " + strconv.Itoa(user.Balance),
Icon: user.LargeAvatar(),
Link: "https://" + ctx.App.Config.Domain + "/api/paypalpayment/" + payment.ID,
})
}()
return ctx.HTML(components.PayPalSuccess(payment))
} }

10
pages/paypal/success.pixy Normal file
View File

@ -0,0 +1,10 @@
component PayPalSuccess(payment *arn.PayPalPayment)
h1 Thank you for your support!
.new-payment.mountable
span +
.new-payment-amount.count-up= payment.AnimeDollar()
span.new-payment-currency AD
p.mountable
img.new-payment-thank-you-image(src="/images/elements/thank-you.jpg", alt="Thank you!")

View File

@ -0,0 +1,12 @@
.new-payment
horizontal
margin 2rem auto
font-size 4rem
color green
.new-payment-currency
margin-left 1rem
margin-bottom content-padding
.new-payment-thank-you-image
width 683px

View File

@ -13,7 +13,7 @@ func Get(ctx *aero.Context) string {
user := utils.GetUser(ctx) user := utils.GetUser(ctx)
if user == nil { if user == nil {
return ctx.Error(http.StatusForbidden, "Not logged in", nil) return ctx.Error(http.StatusUnauthorized, "Not logged in", nil)
} }
return utils.AllowEmbed(ctx, ctx.HTML(components.Settings(user))) return utils.AllowEmbed(ctx, ctx.HTML(components.Settings(user)))

View File

@ -121,7 +121,8 @@ export class AnimeNotifier {
Promise.resolve().then(() => this.displayLocalDates()), Promise.resolve().then(() => this.displayLocalDates()),
Promise.resolve().then(() => this.setSelectBoxValue()), Promise.resolve().then(() => this.setSelectBoxValue()),
Promise.resolve().then(() => this.assignActions()), Promise.resolve().then(() => this.assignActions()),
Promise.resolve().then(() => this.updatePushUI()) Promise.resolve().then(() => this.updatePushUI()),
Promise.resolve().then(() => this.countUp())
]) ])
// Apply page title // Apply page title
@ -214,6 +215,32 @@ export class AnimeNotifier {
} }
} }
countUp() {
for(let element of findAll("count-up")) {
let final = parseInt(element.innerText)
let duration = 2000.0
let start = Date.now()
element.innerText = "0"
let callback = () => {
let progress = (Date.now() - start) / duration
if(progress > 1) {
progress = 1
}
element.innerText = String(Math.round(progress * final))
if(progress < 1) {
window.requestAnimationFrame(callback)
}
}
window.requestAnimationFrame(callback)
}
}
pushAnalytics() { pushAnalytics() {
if(!this.user) { if(!this.user) {
return return

View File

@ -94,7 +94,7 @@ self.addEventListener("message", (evt: any) => {
self.addEventListener("fetch", async (evt: FetchEvent) => { self.addEventListener("fetch", async (evt: FetchEvent) => {
let request = evt.request as Request let request = evt.request as Request
let isAuth = request.url.includes("/auth/") || request.url.includes("/logout") let isAuth = request.url.includes("/auth/") || request.url.includes("/logout")
let ignoreCache = request.url.includes("/api/") || request.url.includes("chrome-extension") let ignoreCache = request.url.includes("/api/") || request.url.includes("/paypal/") || request.url.includes("chrome-extension")
// Delete existing cache on authentication // Delete existing cache on authentication
if(isAuth) { if(isAuth) {