Added paypal processor skeleton

parents
paypal
config.json
log
{
"API": {
"BaseURL": "http://localhost:9991",
"PathPrefix": "v1/",
"Bind": ":9991",
"SwaggerAPIPath": "/apidocs.json",
"SwaggerPath": "/apidocs/",
"SwaggerFilePath": "/home/ubuntu/swagger-ui/dist",
"ImageFilePath": "/home/ubuntu/sangha_images"
},
"Connections": {
"PostgreSQLConnection": {
"Host": "localhost",
"DbName": "sangha",
"User": "user",
"Password": "password",
"Port": 5432,
"SslMode": "disable"
},
"AMQPConnection": {
"Host": "localhost",
"User": "user",
"Password": "password",
"Port": 5672,
"Broker": "rabbit",
"Queue": "payments"
}
},
"PaymentProviders": {
"PayPal": {
"ClientID": "clientid",
"Secret": "secret"
}
},
"Web": {
"BaseURL": "http://localhost:4200/"
}
}
package main
import (
"fmt"
"math/big"
"net/http"
"os"
"os/signal"
"github.com/davecgh/go-spew/spew"
swagger "github.com/emicklei/go-restful-swagger12"
"github.com/kr/pretty"
"github.com/logpacker/PayPal-Go-SDK"
"github.com/muesli/smolder"
log "github.com/sirupsen/logrus"
"gitlab.techcultivation.org/sangha/mq"
"gitlab.techcultivation.org/sangha/payments/paypal/resources/payments"
"gitlab.techcultivation.org/sangha/sangha/config"
"gitlab.techcultivation.org/sangha/sangha/db"
)
func handleSignals() (chan int, bool) {
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, os.Interrupt, os.Kill)
shutdownGracefully := false
requestIncChan := make(chan int)
go func() {
boldGreen := string(byte(27)) + "[1;32m"
boldRed := string(byte(27)) + "[1;31m"
boldEnd := string(byte(27)) + "[0m"
pendingRequests := 0
for {
select {
case sig := <-sigChan:
if !shutdownGracefully {
shutdownGracefully = true
fmt.Printf(boldGreen+"\nGot %s signal, shutting down gracefully. Press Ctrl-C again to stop now.\n\n"+boldEnd, sig.String())
if pendingRequests == 0 {
os.Exit(0)
}
} else {
fmt.Printf(boldRed+"\nGot %s signal, shutting down now!\n\n"+boldEnd, sig.String())
os.Exit(0)
}
case inc := <-requestIncChan:
pendingRequests += inc
if shutdownGracefully {
log.Infoln("Pending requests:", pendingRequests)
if pendingRequests == 0 {
os.Exit(0)
}
}
}
}
}()
return requestIncChan, shutdownGracefully
}
func paypal() {
// Create a client instance
c, err := paypalsdk.NewClient(config.Settings.PaymentProviders.PayPal.ClientID,
config.Settings.PaymentProviders.PayPal.Secret,
paypalsdk.APIBaseSandBox)
if err != nil {
panic(err)
}
logf, err := os.Create("./log/paypal.log")
if err != nil {
panic(err)
}
defer logf.Close()
c.SetLog(logf)
_, err = c.GetAccessToken()
if err != nil {
panic(err)
}
payments, err := c.GetPayments()
if err != nil {
panic(err)
}
for _, payment := range payments {
if len(payment.Transactions) == 0 {
spew.Dump(payment)
panic("No transactions found for payment!")
}
if len(payment.Transactions) > 1 {
spew.Dump(payment)
panic("Too many transactions found for payment!")
}
value, ab, err := big.ParseFloat(payment.Transactions[0].Amount.Total, 10, 2, big.ToNearestEven)
if err != nil {
spew.Dump(payment)
panic("Can't parse value of this transaction")
}
if ab != 10 {
spew.Dump(payment)
panic("Actual base of transaction value is not 10")
}
// spew.Dump(payment)
p := mq.Payment{
Name: fmt.Sprintf("%s %s", payment.Payer.PayerInfo.FirstName, payment.Payer.PayerInfo.LastName),
Address: []string{
payment.Payer.PayerInfo.ShippingAddress.RecipientName,
payment.Payer.PayerInfo.ShippingAddress.Line1,
},
City: payment.Payer.PayerInfo.ShippingAddress.City,
ZIP: payment.Payer.PayerInfo.ShippingAddress.PostalCode,
Country: payment.Payer.PayerInfo.ShippingAddress.CountryCode,
Phone: payment.Payer.PayerInfo.Phone,
Email: payment.Payer.PayerInfo.Email,
DateTime: *payment.Transactions[0].RelatedResources[0].Sale.CreateTime,
Amount: value,
AmountS: payment.Transactions[0].Amount.Total,
Currency: payment.Transactions[0].Amount.Currency,
TransactionCode: payment.Transactions[0].Custom,
Description: payment.Transactions[0].Description,
Source: "paypal",
SourceID: payment.ID,
SourcePayerID: payment.Payer.PayerInfo.PayerID,
SourceTransactionID: payment.Transactions[0].RelatedResources[0].Sale.ID,
}
/* ac := accounting.Accounting{Symbol: "E", Precision: 2}
fmt.Println(ac.FormatMoneyBigFloat(p.Value)) */
pretty.Println(p)
err = p.Process()
if err != nil {
panic(err)
}
}
}
func main() {
ch, shutdownGracefully := handleSignals()
config.ParseSettings()
db.SetupPostgres(config.Settings.Connections.PostgreSQLConnection)
context := &db.APIContext{
Config: *config.Settings,
}
// Setup web-service
smolderConfig := smolder.APIConfig{
BaseURL: config.Settings.API.BaseURL,
PathPrefix: config.Settings.API.PathPrefix,
}
wsContainer := smolder.NewSmolderContainer(smolderConfig, &shutdownGracefully, ch)
func(resources ...smolder.APIResource) {
for _, r := range resources {
r.Register(wsContainer, smolderConfig, context)
}
}(
&payments.PaymentResource{},
)
if config.Settings.API.SwaggerFilePath != "" {
wsConfig := swagger.Config{
WebServices: wsContainer.RegisteredWebServices(),
WebServicesUrl: config.Settings.API.BaseURL,
ApiPath: config.Settings.API.SwaggerAPIPath,
SwaggerPath: config.Settings.API.SwaggerPath,
SwaggerFilePath: config.Settings.API.SwaggerFilePath,
}
swagger.RegisterSwaggerService(wsConfig, wsContainer)
}
// GlobalLog("Starting web-api...")
server := &http.Server{Addr: config.Settings.API.Bind, Handler: wsContainer}
log.Fatal(server.ListenAndServe())
}
package payments
import (
"github.com/emicklei/go-restful"
"github.com/muesli/smolder"
)
// PaymentResource is the resource responsible for /payments
type PaymentResource struct {
smolder.Resource
}
var (
_ smolder.GetIDSupported = &PaymentResource{}
_ smolder.GetSupported = &PaymentResource{}
)
// Register this resource with the container to setup all the routes
func (r *PaymentResource) Register(container *restful.Container, config smolder.APIConfig, context smolder.APIContextFactory) {
r.Name = "PaymentResource"
r.TypeName = "payment"
r.Endpoint = "payments"
r.Doc = "Manage payments"
r.Config = config
r.Context = context
r.Init(container, r)
}
// Returns returns the model that will be returned
func (r *PaymentResource) Returns() interface{} {
return PaymentResponse{}
}
package payments
import (
"fmt"
"math/big"
"os"
"github.com/davecgh/go-spew/spew"
"github.com/emicklei/go-restful"
"github.com/kr/pretty"
"github.com/logpacker/PayPal-Go-SDK"
"github.com/muesli/smolder"
"gitlab.techcultivation.org/sangha/mq"
"gitlab.techcultivation.org/sangha/sangha/db"
)
// GetAuthRequired returns true because all requests need authentication
func (r *PaymentResource) GetAuthRequired() bool {
return false
}
// GetByIDsAuthRequired returns true because all requests need authentication
func (r *PaymentResource) GetByIDsAuthRequired() bool {
return false
}
// GetDoc returns the description of this API endpoint
func (r *PaymentResource) GetDoc() string {
return "retrieve payments"
}
// GetParams returns the parameters supported by this API endpoint
func (r *PaymentResource) GetParams() []*restful.Parameter {
params := []*restful.Parameter{}
return params
}
func paypal(context smolder.APIContext, id string) {
ctx := context.(*db.APIContext)
// Create a client instance
c, err := paypalsdk.NewClient(ctx.Config.PaymentProviders.PayPal.ClientID,
ctx.Config.PaymentProviders.PayPal.Secret,
paypalsdk.APIBaseSandBox)
if err != nil {
panic(err)
}
c.SetLog(os.Stdout)
_, err = c.GetAccessToken()
if err != nil {
panic(err)
}
payment, err := c.GetPayment(id)
if err != nil {
panic(err)
}
if len(payment.Transactions) == 0 {
spew.Dump(payment)
panic("No transactions found for payment!")
}
if len(payment.Transactions) > 1 {
spew.Dump(payment)
panic("Too many transactions found for payment!")
}
value, ab, err := big.ParseFloat(payment.Transactions[0].Amount.Total, 10, 2, big.ToNearestEven)
if err != nil {
spew.Dump(payment)
panic("Can't parse value of this transaction")
}
if ab != 10 {
spew.Dump(payment)
panic("Actual base of transaction value is not 10")
}
// spew.Dump(payment)
p := mq.Payment{
Name: fmt.Sprintf("%s %s", payment.Payer.PayerInfo.FirstName, payment.Payer.PayerInfo.LastName),
Address: []string{
payment.Payer.PayerInfo.ShippingAddress.RecipientName,
payment.Payer.PayerInfo.ShippingAddress.Line1,
},
City: payment.Payer.PayerInfo.ShippingAddress.City,
ZIP: payment.Payer.PayerInfo.ShippingAddress.PostalCode,
Country: payment.Payer.PayerInfo.ShippingAddress.CountryCode,
Phone: payment.Payer.PayerInfo.Phone,
Email: payment.Payer.PayerInfo.Email,
DateTime: *payment.Transactions[0].RelatedResources[0].Sale.CreateTime,
Amount: value,
AmountS: payment.Transactions[0].Amount.Total,
Currency: payment.Transactions[0].Amount.Currency,
TransactionCode: payment.Transactions[0].Custom,
Description: payment.Transactions[0].Description,
Source: "paypal",
SourceID: payment.ID,
SourcePayerID: payment.Payer.PayerInfo.PayerID,
SourceTransactionID: payment.Transactions[0].RelatedResources[0].Sale.ID,
}
pretty.Println(p)
}
// GetByIDs sends out all items matching a set of IDs
func (r *PaymentResource) GetByIDs(context smolder.APIContext, request *restful.Request, response *restful.Response, ids []string) {
resp := PaymentResponse{}
resp.Init(context)
/*
TransactionCode: "CMKDCFMS",
Source: "paypal",
SourceID: "PAY-21W04903AN1610217LG5ERHA",
SourcePayerID: "CKEWRNHKLJLEN",
SourceTransactionID: "1N943492GW328524E",
*/
for _, id := range ids {
fmt.Println("ID", id)
paypal(context, id)
// resp.AddPayment(&payment)
}
resp.Send(response)
}
// Get sends out items matching the query parameters
func (r *PaymentResource) Get(context smolder.APIContext, request *restful.Request, response *restful.Response, params map[string][]string) {
resp := PaymentResponse{}
resp.Init(context)
resp.Send(response)
}
package payments
import (
"gitlab.techcultivation.org/sangha/sangha/db"
"github.com/muesli/smolder"
)
// PaymentResponse is the common response to 'payment' requests
type PaymentResponse struct {
smolder.Response
Payments []paymentInfoResponse `json:"payments,omitempty"`
payments []db.Payment
}
type paymentInfoResponse struct {
ID int64 `json:"id"`
Payment string `json:"payment"`
}
// Init a new response
func (r *PaymentResponse) Init(context smolder.APIContext) {
r.Parent = r
r.Context = context
r.Payments = []paymentInfoResponse{}
}
// AddPayment adds a payment to the response
func (r *PaymentResponse) AddPayment(payment *db.Payment) {
r.payments = append(r.payments, *payment)
r.Payments = append(r.Payments, preparePaymentResponse(r.Context, payment))
}
// EmptyResponse returns an empty API response for this endpoint if there's no data to respond with
func (r *PaymentResponse) EmptyResponse() interface{} {
if len(r.payments) == 0 {
var out struct {
Payments interface{} `json:"payments"`
}
out.Payments = []paymentInfoResponse{}
return out
}
return nil
}
func preparePaymentResponse(context smolder.APIContext, payment *db.Payment) paymentInfoResponse {
resp := paymentInfoResponse{
ID: payment.ID,
Payment: "",
}
return resp
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment