苹果支付成功后,JAVA服务端二次验证

原理简述:

 苹果客户端在完成应用购买,下单后支付,苹果后台会给客户端返回信息,用来验证支付结果;
 客户端在拿到返回值后,将指定返回值,通过接口形式请求应用服务器,应用服务器根据这个值调用苹果服务器进行验证
应用服务器根据验证结果,来通知客户端支付成功与否。

需要客户端传的值:

{"receipt-data" : "MIIaYAYJKoZIhvcNAQcC……"}具体未知见附件图片


支付信息验证地址:

#苹果支付沙箱验证地址 :https://sandbox.itunes.apple.com/verifyReceipt
#苹果支付正式验证地址:https://buy.itunes.apple.com/verifyReceipt

验证成功返回值样例:

后台可以通过判断返回的JSON传中status的值来简单判断支付成功与否,当然复杂一点可以加入价格校验
{
  "status": 0,
  "environment": "Sandbox",
  "receipt": {
    "receipt_type": "ProductionSandbox",
    "adam_id": 0,
    "app_item_id": 0,
    "bundle_id": "com.platomix.MicroBusinessManage",
    "application_version": "2.0.0",
    "download_id": 0,
    "version_external_identifier": 0,
    "receipt_creation_date": "2017-06-06 06:35:27 Etc/GMT",
    "receipt_creation_date_ms": "1496730927000",
    "receipt_creation_date_pst": "2017-06-05 23:35:27 America/Los_Angeles",
    "request_date": "2017-06-06 07:13:26 Etc/GMT",
    "request_date_ms": "1496733206549",
    "request_date_pst": "2017-06-06 00:13:26 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": []
 }
}

验证失败返回值说明:

 服务器二次验证代码
         * 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环境的验证服务

服务端源码:

/** 
	 * 向指定 URL 发送POST方法的请求 
	 *  
	 * @param url 
	 *            发送请求的 URL 
	 * @param param 
	 *            请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 
	 * @return 所代表远程资源的响应结果 
	 */  
	public static  synchronized JSONObject sendPost(String url, JSONObject param) { 
		
		 
	    StringBuilder sb = new StringBuilder();  
	    PrintWriter out = null;  
	    BufferedReader in = null;  
	    try {  
	        URL realUrl = new URL(url);  
	        // 打开和URL之间的连接  
	        URLConnection conn = realUrl.openConnection();  
	        // 设置通用的请求属性  
	        conn.setRequestProperty("accept", "*/*");  
	        conn.setRequestProperty("connection", "Keep-Alive");  
	        conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");  
	        // 发送POST请求必须设置如下两行  
	        conn.setDoOutput(true);  
	        conn.setDoInput(true);  
	        // 获取URLConnection对象对应的输出流  
	        out = new PrintWriter(conn.getOutputStream());  
	        // 发送请求参数  
	        out.print(param);  
	        // flush输出流的缓冲  
	        out.flush();  
	        // 定义BufferedReader输入流来读取URL的响应  
	        in = new BufferedReader(new InputStreamReader(conn.getInputStream()));  
	        String line;  
	        sb = new StringBuilder(); 
	        
	        while ((line = in.readLine()) != null) 
	        {
	        	sb.append(line);  
	        }  
	    } catch (Exception e) {  
	       // System.out.println("发送 POST 请求出现异常!"+e);  
	        e.printStackTrace();  
	    }  
	    //使用finally块来关闭输出流、输入流  
	    finally{  
	        try{  
	            if(out!=null){  
	                out.close();  
	            }  
	            if(in!=null){  
	                in.close();  
	            }  
	        }  
	        catch(IOException ex){  
	            ex.printStackTrace();  
	        }  
	    }  
	    return JSON.parseObject((String) sb.toString());  
	}   

请求样例:(POST)

{
    "receipt-data": "MIIaYAYJKoZIhvcNAQcCoIIaUTCCGk0CAQExCzAJBgUrDgMCGgUAMIIKAQYJKoZIhvcNAQcBoIIJ8gSCCe4xggnqMAoCAQgCAQEEAhYAMAoCARQCAQEEAgwAMAsCAQECAQEEAwIBADALAgELAgEBBAMCAQAwCwIBDwIBAQQDAgEAMAsCARACAQEEAwIBADALAgEZAgEBBAMCAQMwDAI……}
需要注意的是,必须安装上面的入参样例 "receipt-data“ 注意是中横线,具体请求,我做了截图,详见附件










版权声明:本文为wjsshhx原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。