feat(gateway): wire the wallet.order edge call for the direct rail
Add the WalletOrderRequest / WalletOrderResponse FlatBuffers messages and the wallet.order Connect op: the gateway decodes the order request, forwards it to the backend POST /wallet/order and returns the created order id plus the provider launch URL the client opens. Regenerate the committed Go and TS FlatBuffers code.
This commit is contained in:
@@ -396,6 +396,24 @@ func (c *Client) WalletBuy(ctx context.Context, userID, productID string) (Walle
|
|||||||
return out, err
|
return out, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// walletOrderBody is the POST body of an order: the chip pack to fund.
|
||||||
|
type walletOrderBody struct {
|
||||||
|
ProductID string `json:"product_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WalletOrderResp is a created order: its id and the provider launch URL the client opens.
|
||||||
|
type WalletOrderResp struct {
|
||||||
|
OrderID string `json:"order_id"`
|
||||||
|
RedirectURL string `json:"redirect_url"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WalletOrder opens a pending order to fund a chip pack and returns the provider launch URL.
|
||||||
|
func (c *Client) WalletOrder(ctx context.Context, userID, productID string) (WalletOrderResp, error) {
|
||||||
|
var out WalletOrderResp
|
||||||
|
err := c.do(ctx, http.MethodPost, "/api/v1/user/wallet/order", userID, "", walletOrderBody{ProductID: productID}, &out)
|
||||||
|
return out, err
|
||||||
|
}
|
||||||
|
|
||||||
// CatalogAtomResp is one atom line of a storefront product: the value type it grants and quantity.
|
// CatalogAtomResp is one atom line of a storefront product: the value type it grants and quantity.
|
||||||
type CatalogAtomResp struct {
|
type CatalogAtomResp struct {
|
||||||
AtomType string `json:"atom_type"`
|
AtomType string `json:"atom_type"`
|
||||||
|
|||||||
@@ -37,6 +37,19 @@ func encodeAck(ok bool) []byte {
|
|||||||
return b.FinishedBytes()
|
return b.FinishedBytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// encodeWalletOrder builds a WalletOrderResponse payload: the created order id and the provider
|
||||||
|
// launch URL the client opens.
|
||||||
|
func encodeWalletOrder(o backendclient.WalletOrderResp) []byte {
|
||||||
|
b := flatbuffers.NewBuilder(128)
|
||||||
|
oid := b.CreateString(o.OrderID)
|
||||||
|
url := b.CreateString(o.RedirectURL)
|
||||||
|
fb.WalletOrderResponseStart(b)
|
||||||
|
fb.WalletOrderResponseAddOrderId(b, oid)
|
||||||
|
fb.WalletOrderResponseAddRedirectUrl(b, url)
|
||||||
|
b.Finish(fb.WalletOrderResponseEnd(b))
|
||||||
|
return b.FinishedBytes()
|
||||||
|
}
|
||||||
|
|
||||||
// encodeDeleteRequestResult builds an AccountDeleteRequestResult payload reporting which
|
// encodeDeleteRequestResult builds an AccountDeleteRequestResult payload reporting which
|
||||||
// deletion step-up the account uses ("email" | "phrase").
|
// deletion step-up the account uses ("email" | "phrase").
|
||||||
func encodeDeleteRequestResult(method string) []byte {
|
func encodeDeleteRequestResult(method string) []byte {
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ const (
|
|||||||
MsgWalletGet = "wallet.get"
|
MsgWalletGet = "wallet.get"
|
||||||
MsgWalletCatalog = "wallet.catalog"
|
MsgWalletCatalog = "wallet.catalog"
|
||||||
MsgWalletBuy = "wallet.buy"
|
MsgWalletBuy = "wallet.buy"
|
||||||
|
MsgWalletOrder = "wallet.order"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request is one decoded Execute call.
|
// Request is one decoded Execute call.
|
||||||
@@ -111,6 +112,7 @@ func NewRegistry(backend *backendclient.Client, tg TelegramValidator, opts ...Op
|
|||||||
r.ops[MsgWalletGet] = Op{Handler: walletHandler(backend), Auth: true}
|
r.ops[MsgWalletGet] = Op{Handler: walletHandler(backend), Auth: true}
|
||||||
r.ops[MsgWalletCatalog] = Op{Handler: walletCatalogHandler(backend), Auth: true}
|
r.ops[MsgWalletCatalog] = Op{Handler: walletCatalogHandler(backend), Auth: true}
|
||||||
r.ops[MsgWalletBuy] = Op{Handler: walletBuyHandler(backend), Auth: true}
|
r.ops[MsgWalletBuy] = Op{Handler: walletBuyHandler(backend), Auth: true}
|
||||||
|
r.ops[MsgWalletOrder] = Op{Handler: walletOrderHandler(backend), Auth: true}
|
||||||
r.ops[MsgBlockStatus] = Op{Handler: blockStatusHandler(backend), Auth: true}
|
r.ops[MsgBlockStatus] = Op{Handler: blockStatusHandler(backend), Auth: true}
|
||||||
r.ops[MsgGameSubmitPlay] = Op{Handler: submitPlayHandler(backend), Auth: true}
|
r.ops[MsgGameSubmitPlay] = Op{Handler: submitPlayHandler(backend), Auth: true}
|
||||||
r.ops[MsgGameState] = Op{Handler: gameStateHandler(backend), Auth: true}
|
r.ops[MsgGameState] = Op{Handler: gameStateHandler(backend), Auth: true}
|
||||||
@@ -331,6 +333,17 @@ func walletBuyHandler(backend *backendclient.Client) Handler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func walletOrderHandler(backend *backendclient.Client) Handler {
|
||||||
|
return func(ctx context.Context, req Request) ([]byte, error) {
|
||||||
|
in := fb.GetRootAsWalletOrderRequest(req.Payload, 0)
|
||||||
|
o, err := backend.WalletOrder(ctx, req.UserID, string(in.ProductId()))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return encodeWalletOrder(o), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func blockStatusHandler(backend *backendclient.Client) Handler {
|
func blockStatusHandler(backend *backendclient.Client) Handler {
|
||||||
return func(ctx context.Context, req Request) ([]byte, error) {
|
return func(ctx context.Context, req Request) ([]byte, error) {
|
||||||
bs, err := backend.BlockStatus(ctx, req.UserID)
|
bs, err := backend.BlockStatus(ctx, req.UserID)
|
||||||
|
|||||||
@@ -873,6 +873,18 @@ table WalletBuyRequest {
|
|||||||
product_id:string;
|
product_id:string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WalletOrderRequest opens a money order to fund a chip pack: the pack to buy.
|
||||||
|
table WalletOrderRequest {
|
||||||
|
product_id:string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// WalletOrderResponse returns the created order id and the provider launch URL the client opens
|
||||||
|
// (the Robokassa hosted-payment page); chips are credited later, by the verified server callback.
|
||||||
|
table WalletOrderResponse {
|
||||||
|
order_id:string;
|
||||||
|
redirect_url:string;
|
||||||
|
}
|
||||||
|
|
||||||
// CatalogAtom is one atom line of a storefront product: the base value type it grants
|
// CatalogAtom is one atom line of a storefront product: the base value type it grants
|
||||||
// ("chips"/"hints"/"noads_days"/"tournament") and how many of it the product carries.
|
// ("chips"/"hints"/"noads_days"/"tournament") and how many of it the product carries.
|
||||||
table CatalogAtom {
|
table CatalogAtom {
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
// Code generated by the FlatBuffers compiler. DO NOT EDIT.
|
||||||
|
|
||||||
|
package scrabblefb
|
||||||
|
|
||||||
|
import (
|
||||||
|
flatbuffers "github.com/google/flatbuffers/go"
|
||||||
|
)
|
||||||
|
|
||||||
|
type WalletOrderRequest struct {
|
||||||
|
_tab flatbuffers.Table
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetRootAsWalletOrderRequest(buf []byte, offset flatbuffers.UOffsetT) *WalletOrderRequest {
|
||||||
|
n := flatbuffers.GetUOffsetT(buf[offset:])
|
||||||
|
x := &WalletOrderRequest{}
|
||||||
|
x.Init(buf, n+offset)
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
func FinishWalletOrderRequestBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) {
|
||||||
|
builder.Finish(offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetSizePrefixedRootAsWalletOrderRequest(buf []byte, offset flatbuffers.UOffsetT) *WalletOrderRequest {
|
||||||
|
n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
|
||||||
|
x := &WalletOrderRequest{}
|
||||||
|
x.Init(buf, n+offset+flatbuffers.SizeUint32)
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
func FinishSizePrefixedWalletOrderRequestBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) {
|
||||||
|
builder.FinishSizePrefixed(offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rcv *WalletOrderRequest) Init(buf []byte, i flatbuffers.UOffsetT) {
|
||||||
|
rcv._tab.Bytes = buf
|
||||||
|
rcv._tab.Pos = i
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rcv *WalletOrderRequest) Table() flatbuffers.Table {
|
||||||
|
return rcv._tab
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rcv *WalletOrderRequest) ProductId() []byte {
|
||||||
|
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
|
||||||
|
if o != 0 {
|
||||||
|
return rcv._tab.ByteVector(o + rcv._tab.Pos)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func WalletOrderRequestStart(builder *flatbuffers.Builder) {
|
||||||
|
builder.StartObject(1)
|
||||||
|
}
|
||||||
|
func WalletOrderRequestAddProductId(builder *flatbuffers.Builder, productId flatbuffers.UOffsetT) {
|
||||||
|
builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(productId), 0)
|
||||||
|
}
|
||||||
|
func WalletOrderRequestEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
|
||||||
|
return builder.EndObject()
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
// Code generated by the FlatBuffers compiler. DO NOT EDIT.
|
||||||
|
|
||||||
|
package scrabblefb
|
||||||
|
|
||||||
|
import (
|
||||||
|
flatbuffers "github.com/google/flatbuffers/go"
|
||||||
|
)
|
||||||
|
|
||||||
|
type WalletOrderResponse struct {
|
||||||
|
_tab flatbuffers.Table
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetRootAsWalletOrderResponse(buf []byte, offset flatbuffers.UOffsetT) *WalletOrderResponse {
|
||||||
|
n := flatbuffers.GetUOffsetT(buf[offset:])
|
||||||
|
x := &WalletOrderResponse{}
|
||||||
|
x.Init(buf, n+offset)
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
func FinishWalletOrderResponseBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) {
|
||||||
|
builder.Finish(offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetSizePrefixedRootAsWalletOrderResponse(buf []byte, offset flatbuffers.UOffsetT) *WalletOrderResponse {
|
||||||
|
n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
|
||||||
|
x := &WalletOrderResponse{}
|
||||||
|
x.Init(buf, n+offset+flatbuffers.SizeUint32)
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
func FinishSizePrefixedWalletOrderResponseBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) {
|
||||||
|
builder.FinishSizePrefixed(offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rcv *WalletOrderResponse) Init(buf []byte, i flatbuffers.UOffsetT) {
|
||||||
|
rcv._tab.Bytes = buf
|
||||||
|
rcv._tab.Pos = i
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rcv *WalletOrderResponse) Table() flatbuffers.Table {
|
||||||
|
return rcv._tab
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rcv *WalletOrderResponse) OrderId() []byte {
|
||||||
|
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
|
||||||
|
if o != 0 {
|
||||||
|
return rcv._tab.ByteVector(o + rcv._tab.Pos)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rcv *WalletOrderResponse) RedirectUrl() []byte {
|
||||||
|
o := flatbuffers.UOffsetT(rcv._tab.Offset(6))
|
||||||
|
if o != 0 {
|
||||||
|
return rcv._tab.ByteVector(o + rcv._tab.Pos)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func WalletOrderResponseStart(builder *flatbuffers.Builder) {
|
||||||
|
builder.StartObject(2)
|
||||||
|
}
|
||||||
|
func WalletOrderResponseAddOrderId(builder *flatbuffers.Builder, orderId flatbuffers.UOffsetT) {
|
||||||
|
builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(orderId), 0)
|
||||||
|
}
|
||||||
|
func WalletOrderResponseAddRedirectUrl(builder *flatbuffers.Builder, redirectUrl flatbuffers.UOffsetT) {
|
||||||
|
builder.PrependUOffsetTSlot(1, flatbuffers.UOffsetT(redirectUrl), 0)
|
||||||
|
}
|
||||||
|
func WalletOrderResponseEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
|
||||||
|
return builder.EndObject()
|
||||||
|
}
|
||||||
@@ -86,6 +86,8 @@ export { UpdateProfileRequest } from './scrabblefb/update-profile-request.js';
|
|||||||
export { VKLoginRequest } from './scrabblefb/vklogin-request.js';
|
export { VKLoginRequest } from './scrabblefb/vklogin-request.js';
|
||||||
export { Wallet } from './scrabblefb/wallet.js';
|
export { Wallet } from './scrabblefb/wallet.js';
|
||||||
export { WalletBuyRequest } from './scrabblefb/wallet-buy-request.js';
|
export { WalletBuyRequest } from './scrabblefb/wallet-buy-request.js';
|
||||||
|
export { WalletOrderRequest } from './scrabblefb/wallet-order-request.js';
|
||||||
|
export { WalletOrderResponse } from './scrabblefb/wallet-order-response.js';
|
||||||
export { WalletSegment } from './scrabblefb/wallet-segment.js';
|
export { WalletSegment } from './scrabblefb/wallet-segment.js';
|
||||||
export { WordCheckResult } from './scrabblefb/word-check-result.js';
|
export { WordCheckResult } from './scrabblefb/word-check-result.js';
|
||||||
export { YourTurnEvent } from './scrabblefb/your-turn-event.js';
|
export { YourTurnEvent } from './scrabblefb/your-turn-event.js';
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
// automatically generated by the FlatBuffers compiler, do not modify
|
||||||
|
|
||||||
|
import * as flatbuffers from 'flatbuffers';
|
||||||
|
|
||||||
|
export class WalletOrderRequest {
|
||||||
|
bb: flatbuffers.ByteBuffer|null = null;
|
||||||
|
bb_pos = 0;
|
||||||
|
__init(i:number, bb:flatbuffers.ByteBuffer):WalletOrderRequest {
|
||||||
|
this.bb_pos = i;
|
||||||
|
this.bb = bb;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
static getRootAsWalletOrderRequest(bb:flatbuffers.ByteBuffer, obj?:WalletOrderRequest):WalletOrderRequest {
|
||||||
|
return (obj || new WalletOrderRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||||
|
}
|
||||||
|
|
||||||
|
static getSizePrefixedRootAsWalletOrderRequest(bb:flatbuffers.ByteBuffer, obj?:WalletOrderRequest):WalletOrderRequest {
|
||||||
|
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
||||||
|
return (obj || new WalletOrderRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||||
|
}
|
||||||
|
|
||||||
|
productId():string|null
|
||||||
|
productId(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||||
|
productId(optionalEncoding?:any):string|Uint8Array|null {
|
||||||
|
const offset = this.bb!.__offset(this.bb_pos, 4);
|
||||||
|
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static startWalletOrderRequest(builder:flatbuffers.Builder) {
|
||||||
|
builder.startObject(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static addProductId(builder:flatbuffers.Builder, productIdOffset:flatbuffers.Offset) {
|
||||||
|
builder.addFieldOffset(0, productIdOffset, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static endWalletOrderRequest(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||||
|
const offset = builder.endObject();
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
static createWalletOrderRequest(builder:flatbuffers.Builder, productIdOffset:flatbuffers.Offset):flatbuffers.Offset {
|
||||||
|
WalletOrderRequest.startWalletOrderRequest(builder);
|
||||||
|
WalletOrderRequest.addProductId(builder, productIdOffset);
|
||||||
|
return WalletOrderRequest.endWalletOrderRequest(builder);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
// automatically generated by the FlatBuffers compiler, do not modify
|
||||||
|
|
||||||
|
import * as flatbuffers from 'flatbuffers';
|
||||||
|
|
||||||
|
export class WalletOrderResponse {
|
||||||
|
bb: flatbuffers.ByteBuffer|null = null;
|
||||||
|
bb_pos = 0;
|
||||||
|
__init(i:number, bb:flatbuffers.ByteBuffer):WalletOrderResponse {
|
||||||
|
this.bb_pos = i;
|
||||||
|
this.bb = bb;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
static getRootAsWalletOrderResponse(bb:flatbuffers.ByteBuffer, obj?:WalletOrderResponse):WalletOrderResponse {
|
||||||
|
return (obj || new WalletOrderResponse()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||||
|
}
|
||||||
|
|
||||||
|
static getSizePrefixedRootAsWalletOrderResponse(bb:flatbuffers.ByteBuffer, obj?:WalletOrderResponse):WalletOrderResponse {
|
||||||
|
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
||||||
|
return (obj || new WalletOrderResponse()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||||
|
}
|
||||||
|
|
||||||
|
orderId():string|null
|
||||||
|
orderId(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||||
|
orderId(optionalEncoding?:any):string|Uint8Array|null {
|
||||||
|
const offset = this.bb!.__offset(this.bb_pos, 4);
|
||||||
|
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
redirectUrl():string|null
|
||||||
|
redirectUrl(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||||
|
redirectUrl(optionalEncoding?:any):string|Uint8Array|null {
|
||||||
|
const offset = this.bb!.__offset(this.bb_pos, 6);
|
||||||
|
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static startWalletOrderResponse(builder:flatbuffers.Builder) {
|
||||||
|
builder.startObject(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static addOrderId(builder:flatbuffers.Builder, orderIdOffset:flatbuffers.Offset) {
|
||||||
|
builder.addFieldOffset(0, orderIdOffset, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static addRedirectUrl(builder:flatbuffers.Builder, redirectUrlOffset:flatbuffers.Offset) {
|
||||||
|
builder.addFieldOffset(1, redirectUrlOffset, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static endWalletOrderResponse(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||||
|
const offset = builder.endObject();
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
static createWalletOrderResponse(builder:flatbuffers.Builder, orderIdOffset:flatbuffers.Offset, redirectUrlOffset:flatbuffers.Offset):flatbuffers.Offset {
|
||||||
|
WalletOrderResponse.startWalletOrderResponse(builder);
|
||||||
|
WalletOrderResponse.addOrderId(builder, orderIdOffset);
|
||||||
|
WalletOrderResponse.addRedirectUrl(builder, redirectUrlOffset);
|
||||||
|
return WalletOrderResponse.endWalletOrderResponse(builder);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user