@@ -25,6 +25,7 @@ const (
25
25
// IAPClient is an interface to call validation API in App Store
26
26
type IAPClient interface {
27
27
Verify (ctx context.Context , reqBody IAPRequest , resp interface {}) error
28
+ VerifyWithStatus (ctx context.Context , reqBody IAPRequest , resp interface {}) (int , error )
28
29
}
29
30
30
31
// Client implements IAPClient
@@ -109,69 +110,79 @@ func NewWithClient(client *http.Client) *Client {
109
110
110
111
// Verify sends receipts and gets validation result
111
112
func (c * Client ) Verify (ctx context.Context , reqBody IAPRequest , result interface {}) error {
113
+ _ , err := c .verify (ctx , reqBody , result )
114
+ return err
115
+ }
116
+
117
+ // VerifyWithStatus sends receipts and gets validation result with status code
118
+ func (c * Client ) VerifyWithStatus (ctx context.Context , reqBody IAPRequest , result interface {}) (int , error ) {
119
+ return c .verify (ctx , reqBody , result )
120
+ }
121
+
122
+ func (c * Client ) verify (ctx context.Context , reqBody IAPRequest , result interface {}) (int , error ) {
112
123
b := new (bytes.Buffer )
113
124
if err := json .NewEncoder (b ).Encode (reqBody ); err != nil {
114
- return err
125
+ return 0 , err
115
126
}
116
127
117
128
req , err := http .NewRequest ("POST" , c .ProductionURL , b )
118
129
if err != nil {
119
- return err
130
+ return 0 , err
120
131
}
121
132
req .Header .Set ("Content-Type" , ContentType )
122
133
req = req .WithContext (ctx )
123
134
resp , err := c .httpCli .Do (req )
124
135
if err != nil {
125
- return err
136
+ return 0 , err
126
137
}
127
138
defer resp .Body .Close ()
128
139
if resp .StatusCode >= 500 {
129
- return fmt .Errorf ("Received http status code %d from the App Store: %w" , resp .StatusCode , ErrAppStoreServer )
140
+ return 0 , fmt .Errorf ("Received http status code %d from the App Store: %w" , resp .StatusCode , ErrAppStoreServer )
130
141
}
131
142
return c .parseResponse (resp , result , ctx , reqBody )
132
143
}
133
144
134
- func (c * Client ) parseResponse (resp * http.Response , result interface {}, ctx context.Context , reqBody IAPRequest ) error {
145
+ func (c * Client ) parseResponse (resp * http.Response , result interface {}, ctx context.Context , reqBody IAPRequest ) ( int , error ) {
135
146
// Read the body now so that we can unmarshal it twice
136
147
buf , err := ioutil .ReadAll (resp .Body )
137
148
if err != nil {
138
- return err
149
+ return 0 , err
139
150
}
140
151
141
152
err = json .Unmarshal (buf , & result )
142
153
if err != nil {
143
- return err
154
+ return 0 , err
144
155
}
145
156
146
157
// https://developer.apple.com/library/content/technotes/tn2413/_index.html#//apple_ref/doc/uid/DTS40016228-CH1-RECEIPTURL
147
158
var r StatusResponse
148
159
err = json .Unmarshal (buf , & r )
149
160
if err != nil {
150
- return err
161
+ return 0 , err
151
162
}
152
163
if r .Status == 21007 {
153
164
b := new (bytes.Buffer )
154
165
if err := json .NewEncoder (b ).Encode (reqBody ); err != nil {
155
- return err
166
+ return 0 , err
156
167
}
157
168
158
169
req , err := http .NewRequest ("POST" , c .SandboxURL , b )
159
170
if err != nil {
160
- return err
171
+ return 0 , err
161
172
}
162
173
req .Header .Set ("Content-Type" , ContentType )
163
174
req = req .WithContext (ctx )
164
175
resp , err := c .httpCli .Do (req )
165
176
if err != nil {
166
- return err
177
+ return 0 , err
167
178
}
168
179
defer resp .Body .Close ()
169
180
if resp .StatusCode >= 500 {
170
- return fmt .Errorf ("Received http status code %d from the App Store Sandbox: %w" , resp .StatusCode , ErrAppStoreServer )
181
+ return resp . StatusCode , fmt .Errorf ("Received http status code %d from the App Store Sandbox: %w" , resp .StatusCode , ErrAppStoreServer )
171
182
}
172
183
173
- return json .NewDecoder (resp .Body ).Decode (result )
184
+ return r . Status , json .NewDecoder (resp .Body ).Decode (result )
174
185
}
175
186
176
- return nil
187
+ return r . Status , nil
177
188
}
0 commit comments