前言
- 在ios应用内支付支付成功后,app端需要通知服务端给用户增加相应的商品。
- 为了保证支付的安全性,服务端需要验证支付信息的真实性,并且同一个支付信息只给用户增加一次商品
- 本文为原创,转载请注明:https://blog.xinpapa.com/2017/11/29/iosiap/
服务端验证支付信息
- app端需要对支付成功的凭证receipt进行base64编码,然后将base64编码后的 receipt 传给服务端,服务端进行验证,测试代码如下:
import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; import java.io.IOException; //测试类 public class Test { //测试方法如下 public static void main(String[] args) { //app提交给服务端的resultDate,resultDate的length大概有6000多,所以省略了 String resultDate = "省略..."; //请求的参数中加号会被替换成空格,这里需要将空格替换成加号 resultDate = resultDate.replaceAll(" ", "+"); //实际项目中得到的数据有回车,所以还要删掉\r和\n resultDate = resultDate.replaceAll("\r|\n", ""); //验证请求的url(测试环境和正式环境的url不一样) //测试环境下的url String url = "https://sandbox.itunes.apple.com/verifyReceipt"; //正式环境url // String url = "https://buy.itunes.apple.com/verifyReceipt"; //创建post请求 这里用的是 org.apache.http.client.methods.HttpPost; HttpPost request = new HttpPost(url); try { //receipt-data 必须以 json 格式发送。拼接json字符串时,记得拼接上引号,如下: StringEntity s = new StringEntity("{\"receipt-data\":\"" + resultDate + "\"}"); s.setContentEncoding("UTF-8");//编码格式 s.setContentType("application/json");//发送json数据需要设置contentType request.setEntity(s); HttpResponse response = HttpClients.createDefault().execute(request); if (response.getStatusLine().getStatusCode() == 200) {//请求成功 //获取请求回来的参数,如果有错误,则会返回错误码 String result = EntityUtils.toString(response.getEntity()); } } catch (IOException e) { e.getStackTrace(); } } }
- 如果请求参数错误,则返回错误代码,错误代码如下:
- 更多请参考 官方文档
错误码 | Description (描述) |
---|---|
21000 | App Store不能读取您提供的JSON对象。 |
21002 | receipt-data 的数据错误 |
21003 | receipt 无法通过验证 |
21004 | shared secret 和账号中的 shared secret 不匹配 |
21005 | receipt 服务器当前不可用 |
21006 | receipt合法,但是订阅已过期。服务器接收到这个状态码时,receipt数据仍然会解码并一起发送 |
21007 | receipt是Sandbox receipt,但却发送至生产系统的验证服务 |
21008 | receipt是生产receipt,但却发送至Sandbox环境的验证服务 |
21010 | receipt 不能被授权. |
21100-21199 | 内部数据访问错误。 |
- 如果 receipt-data 正确,则会返回购买的参数,格式如下:
- 参数解释请参考 官方文档
{ "status":0, "environment":"Sandbox", "receipt":{ "receipt_type":"ProductionSandbox", "adam_id":0, "app_item_id":0, "bundle_id":"com.hyx.test", "application_version":"1", "download_id":0, "version_external_identifier":0, "receipt_creation_date":"2017-11-28 02:16:38 Etc/GMT", "receipt_creation_date_ms":"1511835398000", "receipt_creation_date_pst":"2017-11-27 18:16:38 America/Los_Angeles", "request_date":"2017-11-28 03:31:49 Etc/GMT", "request_date_ms":"1511839909425", "request_date_pst":"2017-11-27 19:31:49 America/Los_Angeles", "original_purchase_date":"2013-08-01 07:00:00 Etc/GMT", "original_purchase_date_ms":"1375340400000", "original_purchase_date_pst":"2013-08-01 00:00:00 America/Los_Angeles", "original_application_version":"1.0", "in_app":[ { "quantity":"1", "product_id":"com.hyx.test.product8", "transaction_id":"1000000355292423", "original_transaction_id":"1000000355292423", "purchase_date":"2017-11-28 02:16:38 Etc/GMT", "purchase_date_ms":"1511835398000", "purchase_date_pst":"2017-11-27 18:16:38 America/Los_Angeles", "original_purchase_date":"2017-11-28 02:16:38 Etc/GMT", "original_purchase_date_ms":"1511835398000", "original_purchase_date_pst":"2017-11-27 18:16:38 America/Los_Angeles", "is_trial_period":"false" } ] } }
- 购买信息验证成功后,就可以执行相应的业务代码