Cannot get stripe charge work with app engine Golang - google-app-engine

So here is my problem, i have been following the github readme for app engine users in order to implement stripe into my app but the thing is that i can’t make it work as it seems that the http.DefaultTransport and http.DefaultClient are not available in App Engine.
I have seen that in the readme you show us how to initialize the Stripe client with app engine but i cannot find any charge card example so this is why i have come to this implementation.
I am used to this problem, since i have been working with app engine for a long time but for some reason i still get this akward error :
cannot use stripe.BackendConfiguration literal (type stripe.BackendConfiguration) as type stripe.Backend in assignment: stripe.BackendConfiguration does not implement stripe.Backend (Call method has pointer receiver)
Here is the code :
func setStripeChargeClient(context context.Context, key string) *charge.Client {
c := &charge.Client{}
var b stripe.Backend
b = stripe.BackendConfiguration{
stripe.APIBackend,
"https://api.stripe.com/v1",
urlfetch.Client(context),
}
c.Key = key
c.B = b
return c
}
Getting the error on that b assignation …
What i can’t figure it out is why this example seems to work all around the web and does not work in my app, if you could please enlighten me on this one, i would be in your debt hahaha
and then calling it this way
stripeClient := setStripeChargeClient(context, "sk_live_key »)

The error message tells you the problem. The stripe.BackendConfiguration type does not implement stripe.Backend interface. The error message also gives the helpful hint that the missing Call method is on the pointer receiver.
The fix is to use a pointer value:
b = &stripe.BackendConfiguration{ // note the &
stripe.APIBackend,
"https://api.stripe.com/v1",
urlfetch.Client(context),
}
See the specification regarding method sets. The method set of a value receiver does not include the pointer receiver methods.

Ok finally got the solution by doing so :
func setStripeChargeClient(context context.Context, key string) *charge.Client {
c := &charge.Client{}
//SETTING THE CLIENT WITH URL FETCH PROPERLY
fetch := &http.Client{
Transport: &urlfetch.Transport{
Context: context,
},
}
//USE SetHTTPClient method to switch httpClient
stripe.SetHTTPClient(fetch)
var b stripe.Backend
b = &stripe.BackendConfiguration{stripe.APIBackend,
"https://api.stripe.com/v1",fetch}
c.Key = key
c.B = b
return c
}

This was my solution as per Stripe's GAE recommendations:
func myHandler(w http.ResponseWriter, r *http.Request) {
c := appengine.NewContext(r)
myStripeKey := "pk_test_ABCDEF..."
httpClient := urlfetch.Client(c)
stripeClient := client.New(myStripeKey, stripe.NewBackends(httpClient))
chargeParams := &stripe.ChargeParams{
Amount: uint64(totalCents),
Currency: "usd",
Desc: description,
Email: email,
Statement: "MyCompany",
}
chargeParams.SetSource(token)
charge, chargeErr := stripeClient.Charges.New(chargeParams)

Related

Quick and Easy Post to Slack Webhook from Golang AppEngine

Not so much a question as help for others having this problem. Took a fair amount of beating my head against a wall to make this work. (as much I as love golang, you do have think a little differently) - This will also work as a generic way to do any sort of post to an outside source in AppEngine.
Here is the function I am using to post simple messages to a slack channel via webhook. (assumes you know how to set up a webhook in slack - very easy to do - https://get.slack.help/hc/en-us/articles/115005265063-Incoming-WebHooks-for-Slack ) - NOTE: while there are a fair # of additional parameters you can pass in the json message (see link above) simple things like email addresses and image urls / web addresses will be automatically parsed by slack if passed in the 'text' parameter.
import (
"bytes"
"google.golang.org/appengine"
"google.golang.org/appengine/urlfetch"
"net/http"
)
func postSlackBetaSignup(req *http.Request, msg string) string {
ctx := appengine.NewContext(req);
request := urlfetch.Client(ctx);
data := []byte("{'text': '" + msg + "'}");
body := bytes.NewReader(data);
resp, err := request.Post("https://hooks.slack.com/services/<<<YOUR WEBHOOK HERE>>>", "application/json", body);
if err != nil {
return err.Error();
} else {
return resp.Status;
}
}
import (
"bytes"
"google.golang.org/appengine"
"google.golang.org/appengine/urlfetch"
"net/http"
)
func postSlackBetaSignup(req *http.Request, msg string) string {
ctx := appengine.NewContext(req);
request := urlfetch.Client(ctx);
data := []byte("{'text': '" + msg + "'}");
body := bytes.NewReader(data);
resp, err := request.Post("https://hooks.slack.com/services/<<<YOUR WEBHOOK HERE>>>", "application/json", body);
if err != nil {
return err.Error();
} else {
return resp.Status;
}
}

Querying with an array of arbitrary keys on Google datastore in Golang

A continuation from this question:
Doing a "IN Array" query on google app engine datastore with golang
Right now, I am following the suggestion from the previous question on querying with an array of keys/ids ids []int64. These IDs may or may not actually exist (they have been deleted, but the reference on other instances have not been removed).
My method of trying to obtain these instances looks like so:
var keys []*datastore.Key
for _, id := range ids {
keys = append(keys, datastore.NewKey(c, "Category", "", id, nil))
}
categories := make([]Category, len(keys))
err := datastore.GetMulti(c, keys, categories)
if err != nil {
return nil, err
}
for i := 0; i < len(categories); i++ {
categories[i].Id = keys[i].IntID()
}
However, it errors out throwing me:
datastore: no such entity
I could on the other hand grab each one individually, but is there a more efficient way to approach this?
You need to type assert the error to an appengine.MultiError. This way you can get access to the errors for an individual entity.
if me, ok := err.(appengine.MultiError); ok {
for i, e := range me {
// e != nil if entity i failed
}
} else {
// something else went wrong (timeout, etc).
}
See the docs for MultiError here

Kindless Queries in App Engine Go

In Python it's
q = db.Query()
q.ancestor(ancestor_key)
I tried:
q := datastore.NewQuery("")
q.Ancestor(ancestor_key)
I get the error "datastore: empty kind" when running GetAll
I also tried:
q := &datastore.Query{}
q.Ancestor(ancestor_key)
I get the error "datastore: empty query kind"
Thanks in advance for any help with this matter.
func NewQuery
func NewQuery(kind string) *Query
NewQuery creates a new Query for a specific entity kind. The kind must
be non-empty.
In your code,
q := datastore.NewQuery("")
the kind is empty.
Rich Churcher's comment seems to be right, at least at this point in time.
I don't think the Python kindless ancestor query is supported in Go.
For a moment there I thought you could use the ancestor key's Kind()
method, then I had some more coffee and came to my senses.
GetAll doesn't seem to work, but you can do kindless queries.
ctx := appengine.NewContext(r)
q := datastore.NewQuery("")
for it := q.Run(ctx); ; {
key, err := t.Next(nil)
if err == datastore.Done {
break
}
if err != nil {
break
}
fmt.Printf("%v\n", key)
}

Trouble with Queries/Datastore in Google App Engine - Go API

I'm playing with Google App Engine using the Go APIs and despite everything I've tried I can't get the Queries to return data that is in the datastore. I can see that Put() works as expected, and the entities are listable/accessible from inspection of the Admin Console available from dev_appserver.py
The struct I'm storing is defined this way:
type TweetData struct {
Id int64 `datastore:",noindex" json:"id"`
Text string `datastore:",noindex" json:"text"`
Screen_name string `json:"screen_name"`
}
And my calls to query it are such:
func getDatastoreTweets(c appengine.Context, twitterUser string) []*TweetData {
q := datastore.NewQuery("TweetData").Filter("Screen_name =", twitterUser).Order("-Id").Limit(10)
var oldTweets []*TweetData
if _, err := q.GetAll(c, &oldTweets); err != nil {
fmt.Printf("Getall had non-nil error! %v\n", err)
}
return oldTweets
}
For this query, err is never non-nil, but always returns 0 results, even when the Console tells me there are many. I've tried it without the Filter call as well, after the guestbook example the SDK provides, to no avail.
In case it's an issue with keys (unlikely if I understand correctly, because I'm querying on a property), the call to Put is as follows:
// tweetData passed in via parameter...
key := datastore.NewIncompleteKey(c, "TweetData", nil)
_, err := datastore.Put(c, key, &tweetData)
Any help would be appreciated, thanks! ^_^
The query ask for ordering by Id desc, while the index field is un-indexed, you should either:
rewrite the TweetData annotation to index Id field:
Id int64 `json:"id"`
Remove the Order clause of your query:
q := datastore.NewQuery("TweetData").Filter("Screen_name =", twitterUser).Limit(10)

Golang GAE - intID in struct for mustache

Here is an Example of the app. The essential code is in: golang-code/handler/handler.go (After the subject should appear an ID!)
Im trying to build a little blog system in Golang on Google Appengine and use Mustache as template engine.
So, i have a struct:
type Blogposts struct {
PostTitle string
PostPreview string
Content string
Creator string
Date time.Time
}
The data is passed to GAE via
datastore.Put(c, datastore.NewIncompleteKey(c, "Blogposts", nil), &blogposts)
So, GAE assigns automatically a intID (int64).
Now I tried to get the latest blogposts
// Get the latest blogposts
c := appengine.NewContext(r)
q := datastore.NewQuery("Blogposts").Order("-Date").Limit(10)
var blogposts []Blogposts
_, err := q.GetAll(c, &blogposts)
Until there all things works fine, but when I try to access intID (or stringID, whatever) I dont have access to this :-(
<h3>{{{PostTitle}}}</h3>
(PostTitle works, intID not, i've tried thousand of things, nothing worked :-( )
Anyone an idea? This would be great!
Edit:
I use mustache.
http://mustache.github.com/
In the code I use:
x["Blogposts"] = blogposts
data := mustache.RenderFile("templates/about.mustache", x)
sendData(w, data) // Equivalent to fmt.Fprintf
And then the data can be accessed in the .mustache template with {{{Content}}} or {{{PostTitle}}} etc.
As hyperslug pointed out, the id field of an entity is on the key, not the struct it gets read into.
Another way around this is to add an id field to your struct and tell datastore to ignore it, eg:
type Blogposts struct {
PostTitle string
PostPreview string
Content string
Creator string
Date time.Time
Id int64 `datastore:"-"`
}
You can then populate the Id field manually after a call to GetAll() like so
keys, err := q.GetAll(c, &blogposts)
if err != nil {
// handle the error
return
}
for i, key := range keys {
blogposts[i].Id = key.IntID()
}
This has the benefit of not introducing an extra type.
intID is an internal property of a Key not the struct, and is accessible through a getter:
id := key.IntID()
GetAll returns []*Key, which you're not using:
_, err := q.GetAll(c, &blogposts)
One way to get around this is to create a viewmodel struct that has both your post and key info (untested, but this is the gist of it):
//... handler code ...
keys, err := q.GetAll(c, &blogposts)
if err != nil {
http.Error(w, "Problem fetching posts.", http.StatusInternalServerError)
return
}
models := make([]BlogPostVM, len(blogposts))
for i := 0; i < len(blogposts); i++ {
models[i].Id = keys[i].IntID()
models[i].Title = blogposts[i].Title
models[i].Content = blogposts[i].Content
}
//... render with mustache ...
}
type BlogPostVM struct {
Id int
Title string
Content string
}
I know this question is a couple years old, but the following article was very helpful to me in this regard: Golang basics with Google Datastore.
In the article, the author provides a nice example of how you can run a query that gets an entity by its ID...
func GetCategory(c appengine.Context, id int64) (*Category, error) {
var category Category
category.Id = id
k := category.key(c)
err := datastore.Get(c, k, &category)
if err != nil {
return nil, err
}
category.Id = k.IntID()
return &category, nil
}
...as well as getting a list/collection of entities with their associated ID:
func GetCategories(c appengine.Context) ([]Category, error) {
q := datastore.NewQuery("Category").Order("Name")
var categories []Category
keys, err := q.GetAll(c, &categories)
if err != nil {
return nil, err
}
// you'll see this a lot because instances
// do not have this by default
for i := 0; i < len(categories); i++ {
categories[i].Id = keys[i].IntID()
}
return categories, nil
}
The snippet above is very close to the helpful answer by #koz.
AFAICS, the Blogposts struct has no field intID, but it has a field PostTitle. I guess that could be the reason why the former doesn't and the later does get rendered, though I've never used Mustache...

Resources