github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/tequilapi/endpoints/pilvytis.go (about)

     1  /*
     2   * Copyright (C) 2020 The "MysteriumNetwork/node" Authors.
     3   *
     4   * This program is free software: you can redistribute it and/or modify
     5   * it under the terms of the GNU General Public License as published by
     6   * the Free Software Foundation, either version 3 of the License, or
     7   * (at your option) any later version.
     8   *
     9   * This program is distributed in the hope that it will be useful,
    10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12   * GNU General Public License for more details.
    13   *
    14   * You should have received a copy of the GNU General Public License
    15   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    16   */
    17  
    18  package endpoints
    19  
    20  import (
    21  	"encoding/json"
    22  	"strings"
    23  
    24  	"github.com/mysteriumnetwork/go-rest/apierror"
    25  	"github.com/mysteriumnetwork/node/core/location/locationstate"
    26  	"github.com/mysteriumnetwork/node/identity"
    27  	"github.com/mysteriumnetwork/node/pilvytis"
    28  	"github.com/mysteriumnetwork/node/tequilapi/contract"
    29  	"github.com/mysteriumnetwork/node/tequilapi/utils"
    30  	"github.com/mysteriumnetwork/payments/exchange"
    31  
    32  	"github.com/gin-gonic/gin"
    33  )
    34  
    35  type api interface {
    36  	GetPaymentGatewayOrder(id identity.Identity, oid string) (*pilvytis.GatewayOrderResponse, error)
    37  	GetPaymentGatewayOrderInvoice(id identity.Identity, oid string) ([]byte, error)
    38  	GetPaymentGatewayOrders(id identity.Identity) ([]pilvytis.GatewayOrderResponse, error)
    39  	GetPaymentGateways(optionsCurrency exchange.Currency) ([]pilvytis.GatewaysResponse, error)
    40  	GetRegistrationPaymentStatus(id identity.Identity) (*pilvytis.RegistrationPaymentResponse, error)
    41  	GatewayClientCallback(id identity.Identity, gateway string, payload any) error
    42  }
    43  
    44  type paymentsIssuer interface {
    45  	CreatePaymentGatewayOrder(cgo pilvytis.GatewayOrderRequest) (*pilvytis.GatewayOrderResponse, error)
    46  }
    47  
    48  type paymentLocationFallback interface {
    49  	GetOrigin() locationstate.Location
    50  }
    51  
    52  type pilvytisEndpoint struct {
    53  	api api
    54  	pt  paymentsIssuer
    55  	lf  paymentLocationFallback
    56  }
    57  
    58  // NewPilvytisEndpoint returns pilvytis endpoints.
    59  func NewPilvytisEndpoint(pil api, pt paymentsIssuer, lf paymentLocationFallback) *pilvytisEndpoint {
    60  	return &pilvytisEndpoint{
    61  		api: pil,
    62  		pt:  pt,
    63  		lf:  lf,
    64  	}
    65  }
    66  
    67  // GetPaymentGateways returns data about supported payment gateways.
    68  //
    69  // swagger:operation GET /v2/payment-order-gateways Order getPaymentGateways
    70  //
    71  //	---
    72  //	summary: Get payment gateway configuration.
    73  //	description: Returns gateway configuration including supported currencies, minimum amounts, etc.
    74  //	parameters:
    75  //	- name: options_currency
    76  //	  in: query
    77  //	  description: Currency for payment order options
    78  //	  type: string
    79  //	  required: false
    80  //	  default: MYST
    81  //	responses:
    82  //	  200:
    83  //	    description: List of payment gateways
    84  //	    schema:
    85  //	      type: "array"
    86  //	      items:
    87  //	        "$ref": "#/definitions/GatewaysResponse"
    88  //	  500:
    89  //	    description: Internal server error
    90  //	    schema:
    91  //	      "$ref": "#/definitions/APIError"
    92  func (e *pilvytisEndpoint) GetPaymentGateways(c *gin.Context) {
    93  	optionsCurrency := exchange.Currency(strings.ToUpper(c.DefaultQuery("options_currency", "MYST")))
    94  	resp, err := e.api.GetPaymentGateways(optionsCurrency)
    95  	if err != nil {
    96  		utils.ForwardError(c, err, apierror.Internal("Failed to list payment gateways", contract.ErrCodePaymentListGateways))
    97  		return
    98  	}
    99  
   100  	utils.WriteAsJSON(contract.ToGatewaysReponse(resp), c.Writer)
   101  }
   102  
   103  // GetPaymentGatewayOrders returns a list of payment orders.
   104  //
   105  // swagger:operation GET /v2/identities/{id}/payment-order Order getPaymentGatewayOrders
   106  //
   107  //	---
   108  //	summary: Get all orders for identity
   109  //	description: Gets all orders for a given identity from the pilvytis service
   110  //	parameters:
   111  //	- name: id
   112  //	  in: path
   113  //	  description: Identity for which to get orders
   114  //	  type: string
   115  //	  required: true
   116  //	responses:
   117  //	  200:
   118  //	    description: List of payment orders
   119  //	    schema:
   120  //	      type: "array"
   121  //	      items:
   122  //	        "$ref": "#/definitions/PaymentOrderResponse"
   123  //	  500:
   124  //	    description: Internal server error
   125  //	    schema:
   126  //	      "$ref": "#/definitions/APIError"
   127  func (e *pilvytisEndpoint) GetPaymentGatewayOrders(c *gin.Context) {
   128  	resp, err := e.api.GetPaymentGatewayOrders(identity.FromAddress(c.Param("id")))
   129  	if err != nil {
   130  		utils.ForwardError(c, err, apierror.Internal("Failed to list orders", contract.ErrCodePaymentList))
   131  		return
   132  	}
   133  
   134  	utils.WriteAsJSON(contract.NewPaymentOrdersResponse(resp), c.Writer)
   135  }
   136  
   137  // GetPaymentGatewayOrder returns a payment order which maches a given ID and identity.
   138  //
   139  // swagger:operation GET /v2/identities/{id}/payment-order/{order_id} Order getPaymentGatewayOrder
   140  //
   141  //	---
   142  //	summary: Get order
   143  //	description: Gets an order for a given identity and order id combo from the pilvytis service
   144  //	parameters:
   145  //	- name: id
   146  //	  in: path
   147  //	  description: Identity for which to get an order
   148  //	  type: string
   149  //	  required: true
   150  //	- name: order_id
   151  //	  in: path
   152  //	  description: Order id
   153  //	  type: integer
   154  //	  required: true
   155  //	responses:
   156  //	  200:
   157  //	    description: Order object
   158  //	    schema:
   159  //	      "$ref": "#/definitions/PaymentOrderResponse"
   160  //	  500:
   161  //	    description: Internal server error
   162  //	    schema:
   163  //	      "$ref": "#/definitions/APIError"
   164  func (e *pilvytisEndpoint) GetPaymentGatewayOrder(c *gin.Context) {
   165  	resp, err := e.api.GetPaymentGatewayOrder(
   166  		identity.FromAddress(c.Param("id")),
   167  		c.Param("order_id"),
   168  	)
   169  	if err != nil {
   170  		utils.ForwardError(c, err, apierror.Internal("Failed to get payment order", contract.ErrCodePaymentGet))
   171  		return
   172  	}
   173  
   174  	utils.WriteAsJSON(contract.NewPaymentOrderResponse(resp), c.Writer)
   175  }
   176  
   177  // GetPaymentGatewayOrderInvoice returns an invoice for payment order matching the given ID and identity.
   178  //
   179  // swagger:operation GET /v2/identities/{id}/payment-order/{order_id}/invoice Order getPaymentGatewayOrderInvoice
   180  //
   181  //	---
   182  //	summary: Get invoice
   183  //	description: Gets an invoice for payment order matching the given ID and identity
   184  //	parameters:
   185  //	- name: id
   186  //	  in: path
   187  //	  description: Identity for which to get an order invoice
   188  //	  type: string
   189  //	  required: true
   190  //	- name: order_id
   191  //	  in: path
   192  //	  description: Order id
   193  //	  type: integer
   194  //	  required: true
   195  //	responses:
   196  //	  200:
   197  //	    description: Invoice PDF (binary)
   198  //	  500:
   199  //	    description: Internal server error
   200  //	    schema:
   201  //	      "$ref": "#/definitions/APIError"
   202  func (e *pilvytisEndpoint) GetPaymentGatewayOrderInvoice(c *gin.Context) {
   203  	resp, err := e.api.GetPaymentGatewayOrderInvoice(
   204  		identity.FromAddress(c.Param("id")),
   205  		c.Param("order_id"),
   206  	)
   207  	if err != nil {
   208  		utils.ForwardError(c, err, apierror.Internal("Failed to get invoice", contract.ErrCodePaymentGetInvoice))
   209  		return
   210  	}
   211  
   212  	c.Data(200, "application/pdf", resp)
   213  }
   214  
   215  // CreatePaymentGatewayOrder creates a new payment order.
   216  //
   217  // swagger:operation POST /v2/identities/{id}/{gw}/payment-order Order createPaymentGatewayOrder
   218  //
   219  //	---
   220  //	summary: Create order
   221  //	description: Takes the given data and tries to create a new payment order in the pilvytis service.
   222  //	parameters:
   223  //	- name: id
   224  //	  in: path
   225  //	  description: Identity for which to create an order
   226  //	  type: string
   227  //	  required: true
   228  //	- name: gw
   229  //	  in: path
   230  //	  description: Gateway for which a payment order is created
   231  //	  type: string
   232  //	  required: true
   233  //	- in: body
   234  //	  name: body
   235  //	  description: Required data to create a new order
   236  //	  schema:
   237  //	    $ref: "#/definitions/PaymentOrderRequest"
   238  //	responses:
   239  //	  200:
   240  //	    description: Payment order
   241  //	    schema:
   242  //	      "$ref": "#/definitions/PaymentOrderResponse"
   243  //	  500:
   244  //	    description: Internal server error
   245  //	    schema:
   246  //	      "$ref": "#/definitions/APIError"
   247  func (e *pilvytisEndpoint) CreatePaymentGatewayOrder(c *gin.Context) {
   248  	var req contract.PaymentOrderRequest
   249  	if err := json.NewDecoder(c.Request.Body).Decode(&req); err != nil {
   250  		c.Error(apierror.ParseFailed())
   251  		return
   252  	}
   253  
   254  	rid := identity.FromAddress(c.Param("id"))
   255  
   256  	resp, err := e.pt.CreatePaymentGatewayOrder(req.GatewayOrderRequest(rid, c.Param("gw")))
   257  	if err != nil {
   258  		utils.ForwardError(c, err, apierror.Internal("Failed to create payment order", contract.ErrCodePaymentCreate))
   259  		return
   260  	}
   261  
   262  	utils.WriteAsJSON(contract.NewPaymentOrderResponse(resp), c.Writer)
   263  }
   264  
   265  // GetRegistrationPaymentStatus returns a whether a registration order has been paid.
   266  //
   267  // swagger:operation GET /v2/identities/{id}/registration-payment Order getRegistrationPaymentStatus
   268  //
   269  //	---
   270  //	summary: Check for registration payment
   271  //	description: Checks if a registration payment order for an identity has been paid in pilvytis.
   272  //	parameters:
   273  //	- name: id
   274  //	  in: path
   275  //	  description: Identity for which to check
   276  //	  type: string
   277  //	  required: true
   278  //	responses:
   279  //	  200:
   280  //	    description: Registration order status
   281  //	    schema:
   282  //	      "$ref": "#/definitions/RegistrationPaymentResponse"
   283  //	  500:
   284  //	    description: Internal server error
   285  //	    schema:
   286  //	      "$ref": "#/definitions/APIError"
   287  func (e *pilvytisEndpoint) GetRegistrationPaymentStatus(c *gin.Context) {
   288  	resp, err := e.api.GetRegistrationPaymentStatus(identity.FromAddress(c.Param("id")))
   289  	if err != nil {
   290  		utils.ForwardError(c, err, apierror.Internal("Failed to get registration payment status", contract.ErrCodePaymentList))
   291  		return
   292  	}
   293  
   294  	utils.WriteAsJSON(contract.NewRegistrationPaymentResponse(resp), c.Writer)
   295  }
   296  
   297  // AddRoutesForPilvytis adds the pilvytis routers to the given router.
   298  func AddRoutesForPilvytis(pilvytis api, pt paymentsIssuer, lf paymentLocationFallback) func(*gin.Engine) error {
   299  	pil := NewPilvytisEndpoint(pilvytis, pt, lf)
   300  	return func(e *gin.Engine) error {
   301  		idGroupV2 := e.Group("/v2/identities")
   302  		{
   303  			idGroupV2.POST("/:id/:gw/payment-order", pil.CreatePaymentGatewayOrder)
   304  			idGroupV2.GET("/:id/payment-order/:order_id", pil.GetPaymentGatewayOrder)
   305  			idGroupV2.GET("/:id/payment-order/:order_id/invoice", pil.GetPaymentGatewayOrderInvoice)
   306  			idGroupV2.GET("/:id/payment-order", pil.GetPaymentGatewayOrders)
   307  			idGroupV2.GET("/:id/registration-payment", pil.GetRegistrationPaymentStatus)
   308  		}
   309  		e.GET("/v2/payment-order-gateways", pil.GetPaymentGateways)
   310  		return nil
   311  	}
   312  }