Documentation
¶
Overview ¶
Package native implements the order package's v2 routes in the package itself, on the kernel's v2_order and v2_coupon tables adopted in place (kernel.storage.adopt). Legacy handlers and native routes share the tables, so a route can switch between them at any time; the kernel keeps writing v2_order from the payment callbacks (paid, completed) and reads it for statistics. Responses are byte-compatible with the legacy handlers (internal/tests/ordercompat).
Other domains are read through kernel views only: the plan catalog (kapi_plan_catalog_v1) and the subscription groups a plan grants (kapi_plan_subscription_group_v1) for pricing and completing an order, the plan names (kapi_plan_name_v1) for the order lists and details, and the user directory (kapi_user_directory_v1) for the buyer's current plan and, in an administrator's order answers, the buyer's e-mail. Completing an order grants its plan through the kernel's KernelSubscriber contract (kernel.subscriber.entitlements.v1): the package never writes v2_user. Completion pays no commission and sends no notification, in the kernel as here.
The order list and detail answers carry the order, its plan's id and name and, for an administrator, its buyer's id and e-mail; never the buyer's subscription token or UUID, which no kernel view exposes.
Index ¶
- Constants
- Variables
- func CompleteRequestID(orderID uint) string
- type Buyer
- type CatalogPlan
- type Coupon
- type DirectoryUser
- type Order
- type OrderList
- type OrderView
- type PlanGroup
- type PlanName
- type Service
- func (s *Service) AdminCancelOrder(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
- func (s *Service) AdminCoupons(ctx context.Context, _ pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
- func (s *Service) AdminCreateCoupon(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
- func (s *Service) AdminDeleteCoupon(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
- func (s *Service) AdminMarkOrderPaid(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
- func (s *Service) AdminOrder(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
- func (s *Service) AdminOrderStats(ctx context.Context, _ pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
- func (s *Service) AdminOrders(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
- func (s *Service) AdminUpdateOrderStatus(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
- func (s *Service) CheckCoupon(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
- func (s *Service) Handlers() map[string]pluginhostsdk.NativeHandler
- func (s *Service) SaveOrder(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
- func (s *Service) UserOrder(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
- func (s *Service) UserOrders(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
- type Subscriber
Constants ¶
const ( AdminOrdersRouteID = "order.admin.orders.get" AdminOrderRouteID = "order.admin.orders.id.get" UserOrdersRouteID = "order.user.order.get" UserOrderRouteID = "order.user.order.id.get" )
Order list and detail routes, by route id.
const MarkPaidRouteID = "order.admin.orders.id.paid.post"
MarkPaidRouteID marks an order paid and completes it.
const OrderSortTiebreaker = "id DESC"
OrderSortTiebreaker orders orders that share a sorted value, so pages neither repeat nor skip an order.
Variables ¶
var OrderSortColumns = map[string]v2compat.SortColumn{ "id": {Expr: "id", Unique: true}, "trade_no": {Expr: "trade_no", Unique: true}, "status": {Expr: "status"}, "type": {Expr: "type"}, "total_amount": {Expr: "total_amount"}, "created_at": {Expr: "created_at"}, "paid_at": {Expr: "paid_at", Nullable: true}, }
OrderSortColumns are the columns the administrator's order list sorts by: the keys and the meaning of the kernel's service.OrderSortColumns. The buyer's e-mail and the plan's name are other tables' and are not sortable; an unpaid order (NULL paid_at) sorts last ascending.
Functions ¶
func CompleteRequestID ¶
CompleteRequestID names an order's completion in the kernel's subscriber request ledger, as the kernel's completion (OrderService.Complete and the payment callbacks) does, so an order's plan is granted once whichever side completes it.
Types ¶
type Buyer ¶
Buyer is the part of a kapi_user_directory_v1 row an administrator's order answer shows as its buyer.
type CatalogPlan ¶
type CatalogPlan struct {
ID uint `gorm:"primaryKey"`
GroupID uint
TransferEnable int64 // GiB
SpeedLimit *int64
DeviceLimit *int
MonthPrice *int64
QuarterPrice *int64
HalfYearPrice *int64
YearPrice *int64
TwoYearPrice *int64
ThreeYearPrice *int64
OnetimePrice *int64
}
CatalogPlan is a row of kapi_plan_catalog_v1: what an order needs of a plan.
type Coupon ¶
type Coupon struct {
ID uint `gorm:"primaryKey" json:"id"`
Code string `gorm:"size:32;uniqueIndex" json:"code"`
Name string `gorm:"size:255" json:"name"`
Type int `gorm:"default:1" json:"type"` // 1: percentage, 2: fixed amount
Value int `json:"value"` // percentage (0-100) or amount in cents
LimitUse *int `json:"limit_use"` // null or -1 = unlimited
LimitUseWith *uint `gorm:"index" json:"limit_use_with"` // limit to specific plan ID
LimitPeriod *string `gorm:"size:20" json:"limit_period"` // limit to specific period
UseCount int `gorm:"default:0" json:"use_count"` // how many times used
StartedAt int64 `json:"started_at"` // unix timestamp
EndedAt int64 `json:"ended_at"` // unix timestamp
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
Coupon is a v2_coupon row, with the kernel model's fields and tags.
type DirectoryUser ¶
DirectoryUser is the part of a kapi_user_directory_v1 row an order reads.
func (DirectoryUser) TableName ¶
func (DirectoryUser) TableName() string
TableName is the kernel view.
type Order ¶
type Order struct {
ID uint `gorm:"primaryKey" json:"id"`
InviteUserID *uint `gorm:"index" json:"invite_user_id"`
UserID uint `gorm:"index" json:"user_id"`
PlanID uint `gorm:"index" json:"plan_id"`
CouponID *uint `gorm:"index" json:"coupon_id"`
PaymentID *uint `gorm:"index" json:"payment_id"`
Type int `json:"type"` // 1: new, 2: renew, 3: upgrade, 4: reset
Period string `gorm:"size:20" json:"period"`
TradeNo string `gorm:"size:36;uniqueIndex" json:"trade_no"`
CallbackNo *string `gorm:"size:255" json:"callback_no"`
TotalAmount int64 `json:"total_amount"`
DiscountAmount *int64 `json:"discount_amount"`
SurplusAmount *int64 `json:"surplus_amount"`
RefundAmount *int64 `json:"refund_amount"`
Balance *int64 `json:"balance"`
SurplusOrder *string `gorm:"type:text" json:"surplus_order"`
Status int `gorm:"default:0" json:"status"` // 0: pending, 1: paid, 2: cancelled, 3: completed, 4: discounted
CommissionStatus int `gorm:"default:0" json:"commission_status"`
CommissionBalance int64 `gorm:"default:0" json:"commission_balance"`
PaidAt *int64 `json:"paid_at"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
Order is a v2_order row. Its fields and tags match the kernel model without its relations, which the native routes never load, so answers are the same.
type OrderView ¶
type OrderView struct {
Order
User *Buyer `json:"user,omitempty"`
Plan *PlanName `json:"plan,omitempty"`
}
OrderView is an order as the list and detail routes answer it, as the kernel's service.OrderView: the order's columns, its plan's id and name, and for an administrator its buyer's id and e-mail. A plan or buyer that no longer exists is left out.
type PlanGroup ¶
PlanGroup is a row of kapi_plan_subscription_group_v1: a subscription group a plan grants.
type PlanName ¶
PlanName is a row of kapi_plan_name_v1: a plan's id and name, which an order answer shows as its plan.
type Service ¶
type Service struct {
// Open returns the package's storage connection, on which the adopted
// tables and the granted views are visible.
Open func(ctx context.Context) (*gorm.DB, error)
// Subscriber is the kernel's KernelSubscriber; without it the route
// that completes an order has no native handler and stays legacy.
Subscriber Subscriber
// Now defaults to time.Now.
Now func() time.Time
}
Service holds what the native routes need.
func (*Service) AdminCancelOrder ¶
func (s *Service) AdminCancelOrder(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
AdminCancelOrder is POST /api/v2/admin/orders/:id/cancel.
func (*Service) AdminCoupons ¶
func (s *Service) AdminCoupons(ctx context.Context, _ pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
AdminCoupons is GET /api/v2/admin/coupon: every coupon, newest first, with an unlimited use count shown as -1 and the creation time in Unix seconds.
func (*Service) AdminCreateCoupon ¶
func (s *Service) AdminCreateCoupon(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
AdminCreateCoupon is POST /api/v2/admin/coupon. A coupon starts now and ends in 30 days unless the request says otherwise.
func (*Service) AdminDeleteCoupon ¶
func (s *Service) AdminDeleteCoupon(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
AdminDeleteCoupon is DELETE /api/v2/admin/coupon/:id.
func (*Service) AdminMarkOrderPaid ¶
func (s *Service) AdminMarkOrderPaid(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
AdminMarkOrderPaid is POST /api/v2/admin/orders/:id/paid: the order is marked paid, then completed, as the kernel's handler does.
func (*Service) AdminOrder ¶
func (s *Service) AdminOrder(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
AdminOrder is GET /api/v2/admin/orders/:id: the order with its plan and buyer.
func (*Service) AdminOrderStats ¶
func (s *Service) AdminOrderStats(ctx context.Context, _ pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
AdminOrderStats is GET /api/v2/admin/orders/stats. Today starts at midnight UTC.
func (*Service) AdminOrders ¶
func (s *Service) AdminOrders(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
AdminOrders is GET /api/v2/admin/orders: every order, newest first unless sort and order say otherwise (the columns of OrderSortColumns), each with its plan and buyer, filtered by buyer, status, type, trade number or part of the buyer's e-mail. A filter that does not parse filters by what strconv returns, as in the kernel.
func (*Service) AdminUpdateOrderStatus ¶
func (s *Service) AdminUpdateOrderStatus(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
AdminUpdateOrderStatus is PUT /api/v2/admin/orders/:id/status. Setting "completed" this way grants nothing, as in the kernel.
func (*Service) CheckCoupon ¶
func (s *Service) CheckCoupon(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
CheckCoupon is POST /api/v2/user/coupon/check: whether a code is usable now. Coupons apply to every plan.
func (*Service) Handlers ¶
func (s *Service) Handlers() map[string]pluginhostsdk.NativeHandler
Handlers returns the native handlers by route id.
func (*Service) SaveOrder ¶
func (s *Service) SaveOrder(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
SaveOrder is POST /api/v2/user/order/save: the caller orders a plan for a period, optionally with a coupon. An order for the plan the caller holds is a renewal, for another plan an upgrade, else a new purchase.
func (*Service) UserOrder ¶
func (s *Service) UserOrder(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
UserOrder is GET /api/v2/user/order/:id: the caller's own order with its plan. Another user's order is not found, as an unknown one.
func (*Service) UserOrders ¶
func (s *Service) UserOrders(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
UserOrders is GET /api/v2/user/order: the caller's own orders, newest first, each with its plan. A request with no caller lists nothing.
type Subscriber ¶
type Subscriber interface {
ApplyEntitlement(ctx context.Context, in *kernelsubscriberv1.ApplyEntitlementRequest, opts ...grpc.CallOption) (*kernelsubscriberv1.ApplyEntitlementResponse, error)
}
Subscriber is the part of KernelSubscriber the native routes call.