PBgo: A Mini RPC/REST/Grpc-Gateway Framework Based on Protobuf

pbgo: mini rpc/rest framework based on Protobuf  

Features

  • protoc plugin generate code
  • define rpc api with Protobuf, generate stub code, work with standard net/rpc framework
  • define rest api with Protobuf, and generate service and client code
  • work with grpc framework

Install

  1. install protoc at first: http://github.com/google/protobuf/releases
  2. go get github.com/chai2010/pbgo
  3. go get github.com/chai2010/pbgo/protoc-gen-pbgo
  4. go run hello.go

Example (net/rpc)

create proto file:

syntax = "proto3";
package hello_pb;

message String {
    string value = 1;
}
message Message {
    string value = 1;
}

service HelloService {
    rpc Hello (String) returns (String);
    rpc Echo (Message) returns (Message);
}

generate rpc code:

$ protoc -I=. -I=$GOPATH/src --pbgo_out=. hello.proto

use generate code:

package main

import (
    "fmt"
    "log"
    "net"
    "net/rpc"

    "github.com/chai2010/pbgo/examples/hello.pb"
)

type HelloService struct{}

func (p *HelloService) Hello(request *hello_pb.String, reply *hello_pb.String) error {
    reply.Value = "hello:" + request.GetValue()
    return nil
}
func (p *HelloService) Echo(request *hello_pb.Message, reply *hello_pb.Message) error {
    *reply = *request
    return nil
}

func startRpcServer() {
    hello_pb.RegisterHelloService(rpc.DefaultServer, new(HelloService))

    listener, err := net.Listen("tcp", ":1234")
    if err != nil {
        log.Fatal("ListenTCP error:", err)
    }

    for {
        conn, err := listener.Accept()
        if err != nil {
            log.Fatal("Accept error:", err)
        }

        go rpc.ServeConn(conn)
    }
}

func tryRpcClient() {
    client, err := hello_pb.DialHelloService("tcp", "localhost:1234")
    if err != nil {
        log.Fatal(err)
    }

    reply, err := client.Hello(&hello_pb.String{Value: "gopher"})
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(reply.GetValue())
}

func main() {
    go startRpcServer()
    tryRpcClient()
}

Example (rest api)

create proto file:

syntax = "proto3";
package hello_pb;

import "github.com/chai2010/pbgo/pbgo.proto";

message String {
    string value = 1;
}

message Message {
    string value = 1;
    repeated int32 array = 2;
    map<string,string> dict = 3;
    String subfiled = 4;
}

message StaticFile {
    string content_type = 1;
    bytes content_body = 2;
}

service HelloService {
    rpc Hello (String) returns (String) {
        option (pbgo.rest_api) = {
            get: "/hello/:value"
            post: "/hello"

            additional_bindings {
                method: "DELETE"; url: "/hello"
            }
            additional_bindings {
                method: "PATCH"; url: "/hello"
            }
        };
    }
    rpc Echo (Message) returns (Message) {
        option (pbgo.rest_api) = {
            get: "/echo/:subfiled.value"
        };
    }
    rpc Static(String) returns (StaticFile) {
        option (pbgo.rest_api) = {
            additional_bindings {
                method: "GET";
                url: "/static/:value";
                content_type: ":content_type";
                content_body: ":content_body"
            }
        };
    }
}

generate rpc/rest code:

$ protoc -I=. -I=$GOPATH/src --pbgo_out=. hello.proto

use generate code:

package main

import (
    "io/ioutil"
    "log"
    "mime"
    "net/http"
    "time"

    "github.com/chai2010/pbgo/examples/hello.pb"
)

type HelloService struct{}

func (p *HelloService) Hello(request *hello_pb.String, reply *hello_pb.String) error {
    reply.Value = "hello:" + request.GetValue()
    return nil
}
func (p *HelloService) Echo(request *hello_pb.Message, reply *hello_pb.Message) error {
    *reply = *request
    return nil
}
func (p *HelloService) Static(request *hello_pb.String, reply *hello_pb.StaticFile) error {
    data, err := ioutil.ReadFile("./testdata/" + request.Value)
    if err != nil {
        return err
    }

    reply.ContentType = mime.TypeByExtension(request.Value)
    reply.ContentBody = data
    return nil
}

func someMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(wr http.ResponseWriter, r *http.Request) {
        timeStart := time.Now()
        defer func() {
            timeElapsed := time.Since(timeStart)
            log.Println(r.Method, r.URL, timeElapsed)
        }()

        next.ServeHTTP(wr, r)
    })
}

func main() {
    router := hello_pb.HelloServiceHandler(new(HelloService))
    log.Fatal(http.ListenAndServe(":8080", someMiddleware(router)))
}

Go client:

func main() {
    var reply hello_pb.Message
    err := pbgo.HttpDo("GET", "http://127.0.0.1:8080/echo/xx",
        &hello_pb.Message{
            Value: "chai2010",
            Array: []int32{1, 2, 3},
        },
        &reply,
    )
    if err != nil {
        println("aaa")
        log.Fatal(err)
    }

    // {chai2010 [1 2 3] map[] value:"xx"  {} [] 0}
    fmt.Println(reply)
}

CURL client:

$ curl localhost:8080/hello/gopher
{"value":"hello:gopher"}
$ curl "localhost:8080/hello/gopher?value=vgo"
{"value":"hello:vgo"}
$ curl localhost:8080/hello -X POST --data '{"value":"cgo"}'
{"value":"hello:cgo"}

$ curl localhost:8080/echo/gopher
{"subfiled":{"value":"gopher"}}
$ curl "localhost:8080/echo/gopher?array=123&array=456"
{"array":[123,456],"subfiled":{"value":"gopher"}}
$ curl "localhost:8080/echo/gopher?dict%5Babc%5D=123"
{"dict":{"abc":"123"},"subfiled":{"value":"gopher"}}

$ curl localhost:8080/static/gopher.png
$ curl localhost:8080/static/hello.txt

Rest Client

https://github.com/chubin/wttr.in

$ curl http://wttr.in/wuhan?format=j1
$ curl http://wttr.in/武汉?format=j1
func main() {
    var reply struct {
        CurrentCondition []struct {
            FeelsLikeC       string `json:"FeelsLikeC"`
            FeelsLikeF       string `json:"FeelsLikeF"`
            Cloudcover       string `json:"cloudcover"`
            Humidity         string `json:"humidity"`
            LocalObsDateTime string `json:"localObsDateTime"`
            Observation_time string `json:"observation_time"`
        } `json:"current_condition"`
    }

    err := pbgo.HttpGet("http://wttr.in/wuhan?format=j1", nil, &reply)
    if err != nil {
        log.Fatal(err)
    }

    json, err := json.MarshalIndent(reply, "", "  ")
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(string(json))
}

Form Example

Create example/form_pb/comment.proto:

syntax = "proto3";
package form_pb;

message Comment {
    string user = 1;
    string email = 2;
    string url = 3;
    string text = 4;
    string next = 5; // redirect
}

generate proto code:

$ protoc -I=. --go_out=. comment.proto

create web server:

package main

import (
    "github.com/chai2010/pbgo"
    "github.com/chai2010/pbgo/examples/form_pb"
    "github.com/julienschmidt/httprouter"
)

func main() {
    router := httprouter.New()

    // http://localhost:8080
    router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
        w.Header().Add("Content-Type", "text/html; charset=utf-8")

        fmt.Fprint(w, `
            <form method="POST" action="/api/comment">
                <input type="text" name="user" value="user name">
                <input type="email" name="email" value="123@gmail.com">
                <input name="url" value="http://chai2010.cn"></textarea>
                <textarea name="text" value="text">www</textarea>
                <input type="text" name="next" value="/thanks">
                <button type="submit">Send Test</button>
            </form>
        `)
    })

    router.GET("/thanks", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
        fmt.Fprintln(w, "Thanks")
    })

    // curl -d "user=chai&email=11@qq.com&text=hello&next=http://github.com" localhost:8080/api/comment
    router.POST("/api/comment", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
        var form form_pb.Comment
        if err := pbgo.BindForm(r, &form); err != nil {
            http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
            log.Println("err:", err)
            return
        }

        if form.Next != "" {
            http.Redirect(w, r, form.Next, http.StatusFound)
        }

        log.Println("form:", form)
    })

    log.Fatal(http.ListenAndServe(":8080", router))
}
$ curl -d "user=chai&email=11@qq.com&text=hello&next=http://github.com" localhost:8080/api/comment-form
{"user":"chai","email":"11@qq.com","text":"hello","next":"http://github.com"}

gRPC & Rest Example

See https://github.com/chai2010/pbgo-grpc

BUGS

Report bugs to chaishushan@gmail.com.

Thanks!

Author: Chai2010
Source Code: https://github.com/chai2010/pbgo 
License: BSD-3-Clause license

#go #golang #rest 

What is GEEK

Buddha Community

PBgo: A Mini RPC/REST/Grpc-Gateway Framework Based on Protobuf
Lets Cms

Lets Cms

1652251528

Opencart REST API extensions - V3.x | Rest API Integration, Affiliate

Opencart REST API extensions - V3.x | Rest API Integration : OpenCart APIs is fully integrated with the OpenCart REST API. This is interact with your OpenCart site by sending and receiving data as JSON (JavaScript Object Notation) objects. Using the OpenCart REST API you can register the customers and purchasing the products and it provides data access to the content of OpenCart users like which is publicly accessible via the REST API. This APIs also provide the E-commerce Mobile Apps.

Opencart REST API 
OCRESTAPI Module allows the customer purchasing product from the website it just like E-commerce APIs its also available mobile version APIs.

Opencart Rest APIs List 
Customer Registration GET APIs.
Customer Registration POST APIs.
Customer Login GET APIs.
Customer Login POST APIs.
Checkout Confirm GET APIs.
Checkout Confirm POST APIs.


If you want to know Opencart REST API Any information, you can contact us at -
Skype: jks0586,
Email: letscmsdev@gmail.com,
Website: www.letscms.com, www.mlmtrees.com
Call/WhatsApp/WeChat: +91–9717478599.

Download : https://www.opencart.com/index.php?route=marketplace/extension/info&extension_id=43174&filter_search=ocrest%20api
View Documentation : https://www.letscms.com/documents/api/opencart-rest-api.html
More Information : https://www.letscms.com/blog/Rest-API-Opencart
VEDIO : https://vimeo.com/682154292  

#opencart_api_for_android #Opencart_rest_admin_api #opencart_rest_api #Rest_API_Integration #oc_rest_api #rest_api_ecommerce #rest_api_mobile #rest_api_opencart #rest_api_github #rest_api_documentation #opencart_rest_admin_api #rest_api_for_opencart_mobile_app #opencart_shopping_cart_rest_api #opencart_json_api

Lets Cms

Lets Cms

1652251629

Unilevel MLM Wordpress Rest API FrontEnd | UMW Rest API Woocommerce

Unilevel MLM Wordpress Rest API FrontEnd | UMW Rest API Woocommerce Price USA, Philippines : Our API’s handle the Unilevel MLM woo-commerce end user all functionalities like customer login/register. You can request any type of information which is listed below, our API will provide you managed results for your all frontend needs, which will be useful for your applications like Mobile App etc.
Business to Customer REST API for Unilevel MLM Woo-Commerce will empower your Woo-commerce site with the most powerful Unilevel MLM Woo-Commerce REST API, you will be able to get and send data to your marketplace from other mobile apps or websites using HTTP Rest API request.
Our plugin is used JWT authentication for the authorization process.

REST API Unilevel MLM Woo-commerce plugin contains following APIs.
User Login Rest API
User Register Rest API
User Join Rest API
Get User info Rest API
Get Affiliate URL Rest API 
Get Downlines list Rest API
Get Bank Details Rest API
Save Bank Details Rest API
Get Genealogy JSON Rest API
Get Total Earning Rest API
Get Current Balance Rest API
Get Payout Details Rest API
Get Payout List Rest API
Get Commissions List Rest API
Withdrawal Request Rest API
Get Withdrawal List Rest API

If you want to know more information and any queries regarding Unilevel MLM Rest API Woocommerce WordPress Plugin, you can contact our experts through 
Skype: jks0586, 
Mail: letscmsdev@gmail.com,
Website: www.letscms.com, www.mlmtrees.com,
Call/WhatsApp/WeChat: +91-9717478599.  

more information : https://www.mlmtrees.com/product/unilevel-mlm-woocommerce-rest-api-addon

Visit Documentation : https://letscms.com/documents/umw_apis/umw-apis-addon-documentation.html

#Unilevel_MLM_WooCommerce_Rest_API's_Addon #umw_mlm_rest_api #rest_api_woocommerce_unilevel #rest_api_in_woocommerce #rest_api_woocommerce #rest_api_woocommerce_documentation #rest_api_woocommerce_php #api_rest_de_woocommerce #woocommerce_rest_api_in_android #woocommerce_rest_api_in_wordpress #Rest_API_Woocommerce_unilevel_mlm #wp_rest_api_woocommerce

Ahebwe  Oscar

Ahebwe Oscar

1623185400

Permissions in Django Rest Framework

This article looks at how permissions work in Django REST Framework (DRF).

Objectives

By the end of this article, you should be able to explain:

  1. How DRF permissions work
  2. The similarities and differences between has_permission and has_object_permission
  3. When to use has_permission and has_object_permission

DRF Permissions

In DRF, permissions, along with authentication and throttling, are used to grant or deny access for different classes of users to different parts of an API.

Authentication and authorization work hand in hand. Authentication is always executed before authorization.

While authentication is the process of checking a user’s identity (the user the request came from, the token that it was signed with), authorization is a process of checking if the request user has the necessary permissions for executing the request (are they a super user, are they the creators of the object).

The authorization process in DRF is covered by permissions.

#permissions in django rest framework #django rest framework #permissions #rest #rest framework #django

PBgo: A Mini RPC/REST/Grpc-Gateway Framework Based on Protobuf

pbgo: mini rpc/rest framework based on Protobuf  

Features

  • protoc plugin generate code
  • define rpc api with Protobuf, generate stub code, work with standard net/rpc framework
  • define rest api with Protobuf, and generate service and client code
  • work with grpc framework

Install

  1. install protoc at first: http://github.com/google/protobuf/releases
  2. go get github.com/chai2010/pbgo
  3. go get github.com/chai2010/pbgo/protoc-gen-pbgo
  4. go run hello.go

Example (net/rpc)

create proto file:

syntax = "proto3";
package hello_pb;

message String {
    string value = 1;
}
message Message {
    string value = 1;
}

service HelloService {
    rpc Hello (String) returns (String);
    rpc Echo (Message) returns (Message);
}

generate rpc code:

$ protoc -I=. -I=$GOPATH/src --pbgo_out=. hello.proto

use generate code:

package main

import (
    "fmt"
    "log"
    "net"
    "net/rpc"

    "github.com/chai2010/pbgo/examples/hello.pb"
)

type HelloService struct{}

func (p *HelloService) Hello(request *hello_pb.String, reply *hello_pb.String) error {
    reply.Value = "hello:" + request.GetValue()
    return nil
}
func (p *HelloService) Echo(request *hello_pb.Message, reply *hello_pb.Message) error {
    *reply = *request
    return nil
}

func startRpcServer() {
    hello_pb.RegisterHelloService(rpc.DefaultServer, new(HelloService))

    listener, err := net.Listen("tcp", ":1234")
    if err != nil {
        log.Fatal("ListenTCP error:", err)
    }

    for {
        conn, err := listener.Accept()
        if err != nil {
            log.Fatal("Accept error:", err)
        }

        go rpc.ServeConn(conn)
    }
}

func tryRpcClient() {
    client, err := hello_pb.DialHelloService("tcp", "localhost:1234")
    if err != nil {
        log.Fatal(err)
    }

    reply, err := client.Hello(&hello_pb.String{Value: "gopher"})
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(reply.GetValue())
}

func main() {
    go startRpcServer()
    tryRpcClient()
}

Example (rest api)

create proto file:

syntax = "proto3";
package hello_pb;

import "github.com/chai2010/pbgo/pbgo.proto";

message String {
    string value = 1;
}

message Message {
    string value = 1;
    repeated int32 array = 2;
    map<string,string> dict = 3;
    String subfiled = 4;
}

message StaticFile {
    string content_type = 1;
    bytes content_body = 2;
}

service HelloService {
    rpc Hello (String) returns (String) {
        option (pbgo.rest_api) = {
            get: "/hello/:value"
            post: "/hello"

            additional_bindings {
                method: "DELETE"; url: "/hello"
            }
            additional_bindings {
                method: "PATCH"; url: "/hello"
            }
        };
    }
    rpc Echo (Message) returns (Message) {
        option (pbgo.rest_api) = {
            get: "/echo/:subfiled.value"
        };
    }
    rpc Static(String) returns (StaticFile) {
        option (pbgo.rest_api) = {
            additional_bindings {
                method: "GET";
                url: "/static/:value";
                content_type: ":content_type";
                content_body: ":content_body"
            }
        };
    }
}

generate rpc/rest code:

$ protoc -I=. -I=$GOPATH/src --pbgo_out=. hello.proto

use generate code:

package main

import (
    "io/ioutil"
    "log"
    "mime"
    "net/http"
    "time"

    "github.com/chai2010/pbgo/examples/hello.pb"
)

type HelloService struct{}

func (p *HelloService) Hello(request *hello_pb.String, reply *hello_pb.String) error {
    reply.Value = "hello:" + request.GetValue()
    return nil
}
func (p *HelloService) Echo(request *hello_pb.Message, reply *hello_pb.Message) error {
    *reply = *request
    return nil
}
func (p *HelloService) Static(request *hello_pb.String, reply *hello_pb.StaticFile) error {
    data, err := ioutil.ReadFile("./testdata/" + request.Value)
    if err != nil {
        return err
    }

    reply.ContentType = mime.TypeByExtension(request.Value)
    reply.ContentBody = data
    return nil
}

func someMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(wr http.ResponseWriter, r *http.Request) {
        timeStart := time.Now()
        defer func() {
            timeElapsed := time.Since(timeStart)
            log.Println(r.Method, r.URL, timeElapsed)
        }()

        next.ServeHTTP(wr, r)
    })
}

func main() {
    router := hello_pb.HelloServiceHandler(new(HelloService))
    log.Fatal(http.ListenAndServe(":8080", someMiddleware(router)))
}

Go client:

func main() {
    var reply hello_pb.Message
    err := pbgo.HttpDo("GET", "http://127.0.0.1:8080/echo/xx",
        &hello_pb.Message{
            Value: "chai2010",
            Array: []int32{1, 2, 3},
        },
        &reply,
    )
    if err != nil {
        println("aaa")
        log.Fatal(err)
    }

    // {chai2010 [1 2 3] map[] value:"xx"  {} [] 0}
    fmt.Println(reply)
}

CURL client:

$ curl localhost:8080/hello/gopher
{"value":"hello:gopher"}
$ curl "localhost:8080/hello/gopher?value=vgo"
{"value":"hello:vgo"}
$ curl localhost:8080/hello -X POST --data '{"value":"cgo"}'
{"value":"hello:cgo"}

$ curl localhost:8080/echo/gopher
{"subfiled":{"value":"gopher"}}
$ curl "localhost:8080/echo/gopher?array=123&array=456"
{"array":[123,456],"subfiled":{"value":"gopher"}}
$ curl "localhost:8080/echo/gopher?dict%5Babc%5D=123"
{"dict":{"abc":"123"},"subfiled":{"value":"gopher"}}

$ curl localhost:8080/static/gopher.png
$ curl localhost:8080/static/hello.txt

Rest Client

https://github.com/chubin/wttr.in

$ curl http://wttr.in/wuhan?format=j1
$ curl http://wttr.in/武汉?format=j1
func main() {
    var reply struct {
        CurrentCondition []struct {
            FeelsLikeC       string `json:"FeelsLikeC"`
            FeelsLikeF       string `json:"FeelsLikeF"`
            Cloudcover       string `json:"cloudcover"`
            Humidity         string `json:"humidity"`
            LocalObsDateTime string `json:"localObsDateTime"`
            Observation_time string `json:"observation_time"`
        } `json:"current_condition"`
    }

    err := pbgo.HttpGet("http://wttr.in/wuhan?format=j1", nil, &reply)
    if err != nil {
        log.Fatal(err)
    }

    json, err := json.MarshalIndent(reply, "", "  ")
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(string(json))
}

Form Example

Create example/form_pb/comment.proto:

syntax = "proto3";
package form_pb;

message Comment {
    string user = 1;
    string email = 2;
    string url = 3;
    string text = 4;
    string next = 5; // redirect
}

generate proto code:

$ protoc -I=. --go_out=. comment.proto

create web server:

package main

import (
    "github.com/chai2010/pbgo"
    "github.com/chai2010/pbgo/examples/form_pb"
    "github.com/julienschmidt/httprouter"
)

func main() {
    router := httprouter.New()

    // http://localhost:8080
    router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
        w.Header().Add("Content-Type", "text/html; charset=utf-8")

        fmt.Fprint(w, `
            <form method="POST" action="/api/comment">
                <input type="text" name="user" value="user name">
                <input type="email" name="email" value="123@gmail.com">
                <input name="url" value="http://chai2010.cn"></textarea>
                <textarea name="text" value="text">www</textarea>
                <input type="text" name="next" value="/thanks">
                <button type="submit">Send Test</button>
            </form>
        `)
    })

    router.GET("/thanks", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
        fmt.Fprintln(w, "Thanks")
    })

    // curl -d "user=chai&email=11@qq.com&text=hello&next=http://github.com" localhost:8080/api/comment
    router.POST("/api/comment", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
        var form form_pb.Comment
        if err := pbgo.BindForm(r, &form); err != nil {
            http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
            log.Println("err:", err)
            return
        }

        if form.Next != "" {
            http.Redirect(w, r, form.Next, http.StatusFound)
        }

        log.Println("form:", form)
    })

    log.Fatal(http.ListenAndServe(":8080", router))
}
$ curl -d "user=chai&email=11@qq.com&text=hello&next=http://github.com" localhost:8080/api/comment-form
{"user":"chai","email":"11@qq.com","text":"hello","next":"http://github.com"}

gRPC & Rest Example

See https://github.com/chai2010/pbgo-grpc

BUGS

Report bugs to chaishushan@gmail.com.

Thanks!

Author: Chai2010
Source Code: https://github.com/chai2010/pbgo 
License: BSD-3-Clause license

#go #golang #rest 

Lets Cms

Lets Cms

1652251974

Affiliate B2C REST API, Business to Customer, WooCommerce, Price USA

B2C Custom Policy with REST API | Business to Customer Rest API Price USA, Philippines : Business to Customer REST API for Woo-Commerce will empower your Woo-commerce site with the most powerful Woo-Commerce REST API, you will be able to get and send data to your marketplace from other mobile apps or websites using HTTP Rest API request.
Our API’s handle the woo-commerce frontend all functionalities like customer login/register. You can request for any type of information which is listed below, our API will provide you managed results for your all frontend needs, which will be useful for your applications like Mobile App etc.
Our plugin is used JWT authentication to authorization process.

If you want to know more information and any queries regarding Business to Customer Rest API Woocommerce WordPress Plugin, you can contact our experts through.
Skype: jks0586,
Email: letscmsdev@gmail.com,
Website: www.letscms.com, www.mlmtrees.com,
Call/WhatsApp/WeChat: +91-9717478599.

more information : https://www.mlmtrees.com/product/woocommerce-b2c-rest-api

Vedio : https://www-ccv.adobe.io/v1/player/ccv/Uxr7n4K9GQW/embed?api_key=behance1&bgcolor=%23191919
 

#b2c_rest_api #rest_api #rest_api_Woocommerce #Genealogy #Rest_API #Restful_API #Rest_API_Plugin #b2c #business_to_customer_api #Frontend_for_REST_API #b2c_rest_api #woocommerce_api #woo_rest_api #wp_rest_api #WordPress_rest_api #lets_woo_apis_is_fully_integrated