github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/mobile/mysterium/payment_orders.go (about) 1 /* 2 * Copyright (C) 2021 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 mysterium 19 20 import ( 21 "encoding/json" 22 "strings" 23 24 "github.com/mysteriumnetwork/node/identity" 25 "github.com/mysteriumnetwork/node/pilvytis" 26 "github.com/mysteriumnetwork/payments/exchange" 27 ) 28 29 // PaymentOrderResponse represents a payment order for mobile usage. 30 type PaymentOrderResponse struct { 31 ID string `json:"id"` 32 Status string `json:"status"` 33 IdentityAddress string `json:"identity"` 34 ChannelAddress string `json:"channel_address"` 35 Gateway string `json:"gateway"` 36 ReceiveMYST string `json:"receive_myst"` 37 PayAmount string `json:"pay_amount"` 38 PayCurrency string `json:"pay_currency"` 39 Country string `json:"country"` 40 Currency string `json:"currency"` 41 ItemsSubTotal string `json:"items_sub_total"` 42 TaxRate string `json:"tax_rate"` 43 TaxSubTotal string `json:"tax_sub_total"` 44 OrderTotal string `json:"order_total"` 45 PublicGatewayData json.RawMessage `json:"public_gateway_data"` 46 } 47 48 func newPaymentOrderResponse(r pilvytis.GatewayOrderResponse) PaymentOrderResponse { 49 return PaymentOrderResponse{ 50 ID: r.ID, 51 Status: r.Status.Status(), 52 IdentityAddress: r.Identity, 53 ChannelAddress: r.ChannelAddress, 54 Gateway: r.GatewayName, 55 ReceiveMYST: r.ReceiveMYST, 56 PayAmount: r.PayAmount, 57 PayCurrency: r.PayCurrency, 58 Country: r.Country, 59 Currency: r.Currency, 60 ItemsSubTotal: r.ItemsSubTotal, 61 TaxRate: r.TaxRate, 62 TaxSubTotal: r.TaxSubTotal, 63 OrderTotal: r.OrderTotal, 64 PublicGatewayData: r.PublicGatewayData, 65 } 66 } 67 68 // GetPaymentOrderRequest a request to get an order. 69 type GetPaymentOrderRequest struct { 70 IdentityAddress string 71 ID string 72 } 73 74 // GetPaymentGatewayOrder gets an order by ID. 75 func (mb *MobileNode) GetPaymentGatewayOrder(req *GetPaymentOrderRequest) ([]byte, error) { 76 order, err := mb.pilvytis.GetPaymentGatewayOrder(identity.FromAddress(req.IdentityAddress), req.ID) 77 if err != nil { 78 return nil, err 79 } 80 81 res := newPaymentOrderResponse(*order) 82 83 return json.Marshal(res) 84 } 85 86 // GetPaymentGatewayOrderInvoice gets the invoice for an order. 87 func (mb *MobileNode) GetPaymentGatewayOrderInvoice(req *GetPaymentOrderRequest) ([]byte, error) { 88 return mb.pilvytis.GetPaymentGatewayOrderInvoice(identity.FromAddress(req.IdentityAddress), req.ID) 89 } 90 91 // GatewaysResponse represents a respose which cointains gateways and their data. 92 type GatewaysResponse struct { 93 Name string `json:"name"` 94 OrderOptions PaymentOrderOptions `json:"order_options"` 95 Currencies []string `json:"currencies"` 96 } 97 98 // PaymentOrderOptions are the suggested and minimum myst amount options for a gateway. 99 type PaymentOrderOptions struct { 100 Minimum float64 `json:"minimum"` 101 Suggested []float64 `json:"suggested"` 102 } 103 104 func newGatewayReponse(g []pilvytis.GatewaysResponse) []GatewaysResponse { 105 result := make([]GatewaysResponse, len(g)) 106 for i, v := range g { 107 entry := GatewaysResponse{ 108 Name: v.Name, 109 OrderOptions: PaymentOrderOptions{ 110 Minimum: v.OrderOptions.Minimum, 111 Suggested: v.OrderOptions.Suggested, 112 }, 113 Currencies: v.Currencies, 114 } 115 result[i] = entry 116 } 117 return result 118 } 119 120 // GetGatewaysRequest request for GetGateways. 121 type GetGatewaysRequest struct { 122 OptionsCurrency string 123 } 124 125 // GetGateways returns possible payment gateways. 126 func (mb *MobileNode) GetGateways(req *GetGatewaysRequest) ([]byte, error) { 127 gateways, err := mb.pilvytis.GetPaymentGateways(exchange.Currency(req.OptionsCurrency)) 128 if err != nil { 129 return nil, err 130 } 131 132 return json.Marshal(gateways) 133 } 134 135 // CreatePaymentGatewayOrderReq is used to create a new order. 136 type CreatePaymentGatewayOrderReq struct { 137 IdentityAddress string 138 Gateway string 139 MystAmount string 140 AmountUSD string 141 PayCurrency string 142 Country string 143 State string 144 // GatewayCallerData is marshaled json that is accepting by the payment gateway. 145 GatewayCallerData []byte 146 } 147 148 // CreatePaymentGatewayOrder creates a payment order. 149 func (mb *MobileNode) CreatePaymentGatewayOrder(req *CreatePaymentGatewayOrderReq) ([]byte, error) { 150 if req.Country == "" { 151 org := mb.locationResolver.GetOrigin() 152 req.Country = strings.ToUpper(org.Country) 153 } 154 155 order, err := mb.pilvytisOrderIssuer.CreatePaymentGatewayOrder( 156 pilvytis.GatewayOrderRequest{Identity: identity.FromAddress(req.IdentityAddress), 157 Gateway: req.Gateway, 158 MystAmount: req.MystAmount, 159 AmountUSD: req.AmountUSD, 160 PayCurrency: req.PayCurrency, 161 Country: req.Country, 162 State: req.State, 163 CallerData: req.GatewayCallerData, 164 }, 165 ) 166 if err != nil { 167 return nil, err 168 } 169 170 res := newPaymentOrderResponse(*order) 171 172 return json.Marshal(res) 173 } 174 175 // ListOrdersRequest a request to list orders. 176 type ListOrdersRequest struct { 177 IdentityAddress string 178 } 179 180 // ListPaymentGatewayOrders lists all payment orders. 181 func (mb *MobileNode) ListPaymentGatewayOrders(req *ListOrdersRequest) ([]byte, error) { 182 orders, err := mb.pilvytis.GetPaymentGatewayOrders(identity.FromAddress(req.IdentityAddress)) 183 if err != nil { 184 return nil, err 185 } 186 187 res := make([]PaymentOrderResponse, len(orders)) 188 189 for i := range orders { 190 orderRes := newPaymentOrderResponse(orders[i]) 191 192 res[i] = orderRes 193 } 194 195 return json.Marshal(orders) 196 } 197 198 // GatewayClientCallbackReq is the payload for GatewayClientCallback. 199 type GatewayClientCallbackReq struct { 200 IdentityAddress string 201 Gateway string 202 GooglePurchaseToken string 203 GoogleProductID string 204 } 205 206 // GatewayClientCallback triggers payment callback for google from client side. 207 func (mb *MobileNode) GatewayClientCallback(req *GatewayClientCallbackReq) error { 208 payload := struct { 209 PurchaseToken string `json:"purchase_token"` 210 GoogleProductID string `json:"google_product_id"` 211 }{ 212 PurchaseToken: req.GooglePurchaseToken, 213 GoogleProductID: req.GoogleProductID, 214 } 215 return mb.pilvytis.GatewayClientCallback(identity.FromAddress(req.IdentityAddress), req.Gateway, payload) 216 } 217 218 // OrderUpdatedCallbackPayload is the payload of OrderUpdatedCallback. 219 type OrderUpdatedCallbackPayload struct { 220 OrderID string 221 Status string 222 PayAmount string 223 PayCurrency string 224 } 225 226 // OrderUpdatedCallback is a callback when order status changes. 227 type OrderUpdatedCallback interface { 228 OnUpdate(payload *OrderUpdatedCallbackPayload) 229 } 230 231 // RegisterOrderUpdatedCallback registers OrderStatusChanged callback. 232 func (mb *MobileNode) RegisterOrderUpdatedCallback(cb OrderUpdatedCallback) { 233 _ = mb.eventBus.SubscribeAsync(pilvytis.AppTopicOrderUpdated, func(e pilvytis.AppEventOrderUpdated) { 234 payload := OrderUpdatedCallbackPayload{} 235 payload.OrderID = e.ID 236 payload.Status = e.Status.Status() 237 payload.PayAmount = e.PayAmount 238 payload.PayCurrency = e.PayCurrency 239 cb.OnUpdate(&payload) 240 }) 241 } 242 243 // ExchangeRate returns MYST rate in quote currency. 244 func (mb *MobileNode) ExchangeRate(quote string) (float64, error) { 245 return mb.pilvytis.GetMystExchangeRateFor(quote) 246 }