From b60c954624cad811ccc14cb93293c4a3f43ce8a3 Mon Sep 17 00:00:00 2001 From: sanjid133 Date: Tue, 6 Aug 2019 17:22:41 +0600 Subject: [PATCH] Verfiy latest receipt --- appstore/model.go | 10 ++++++++++ appstore/validator.go | 28 ++++++++++++++-------------- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/appstore/model.go b/appstore/model.go index 0561631..789bc14 100644 --- a/appstore/model.go +++ b/appstore/model.go @@ -138,6 +138,16 @@ type ( IsRetryable bool `json:"is-retryable,omitempty"` } + // The IAPLatestResponse type has the response properties + // If you use latest_receipt as token to verify, response should be like following struct + IAPLatestResponse struct { + Status int `json:"status"` + Receipt InApp `json:"receipt"` + LatestReceiptInfo InApp `json:"latest_receipt_info,omitempty"` + LatestExpiredReceiptInfo InApp `json:"latest_expired_receipt_info,omitempty"` + LatestReceipt string `json:"latest_receipt,omitempty"` + } + // The HttpStatusResponse struct contains the status code returned by the store // Used as a workaround to detect when to hit the production appstore or sandbox appstore regardless of receipt type StatusResponse struct { diff --git a/appstore/validator.go b/appstore/validator.go index 4786f01..9b8698f 100644 --- a/appstore/validator.go +++ b/appstore/validator.go @@ -96,64 +96,64 @@ func NewWithClient(client *http.Client) *Client { } // Verify sends receipts and gets validation result -func (c *Client) Verify(ctx context.Context, reqBody IAPRequest, result interface{}) error { +func (c *Client) Verify(ctx context.Context, reqBody IAPRequest, result interface{}) (Environment, error) { b := new(bytes.Buffer) if err := json.NewEncoder(b).Encode(reqBody); err != nil { - return err + return "", err } req, err := http.NewRequest("POST", c.ProductionURL, b) if err != nil { - return err + return "", err } req.Header.Set("Content-Type", ContentType) req = req.WithContext(ctx) resp, err := c.httpCli.Do(req) if err != nil { - return err + return "", err } defer resp.Body.Close() return c.parseResponse(resp, result, ctx, reqBody) } -func (c *Client) parseResponse(resp *http.Response, result interface{}, ctx context.Context, reqBody IAPRequest) error { +func (c *Client) parseResponse(resp *http.Response, result interface{}, ctx context.Context, reqBody IAPRequest) (Environment, error) { // Read the body now so that we can unmarshal it twice buf, err := ioutil.ReadAll(resp.Body) if err != nil { - return err + return "", err } err = json.Unmarshal(buf, &result) if err != nil { - return err + return "", err } // https://developer.apple.com/library/content/technotes/tn2413/_index.html#//apple_ref/doc/uid/DTS40016228-CH1-RECEIPTURL var r StatusResponse err = json.Unmarshal(buf, &r) if err != nil { - return err + return "", err } if r.Status == 21007 { b := new(bytes.Buffer) if err := json.NewEncoder(b).Encode(reqBody); err != nil { - return err + return "", err } req, err := http.NewRequest("POST", c.SandboxURL, b) if err != nil { - return err + return "", err } req.Header.Set("Content-Type", ContentType) req = req.WithContext(ctx) resp, err := c.httpCli.Do(req) if err != nil { - return err + return "", err } defer resp.Body.Close() - - return json.NewDecoder(resp.Body).Decode(result) + // 21007 is found when the receipt is from the test environment + return Sandbox, json.NewDecoder(resp.Body).Decode(result) } - return nil + return Production, nil }