Implemented paypal payments
This commit is contained in:
parent
d33b93d115
commit
4f9cea89df
BIN
images/elements/thank-you.jpg
Normal file
BIN
images/elements/thank-you.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 296 KiB |
@ -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",
|
||||||
|
@ -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
10
pages/paypal/success.pixy
Normal 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!")
|
12
pages/paypal/success.scarlet
Normal file
12
pages/paypal/success.scarlet
Normal 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
|
@ -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)))
|
||||||
|
@ -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
|
||||||
|
@ -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) {
|
||||||
|
Loading…
Reference in New Issue
Block a user