java 苹果支付(内购)

打印 上一主题 下一主题

主题 762|帖子 762|积分 2301

1、app配置苹果内购项目(iOS系统app端负责)

https://help.apple.com/app-store-connect/#/devb57be10e7


  • APP store 配置APP项目
  • 项目下添加内购项目
  • 添加沙盒测试账号
2.iOS-iOS内购流程(手把手图文教程)_CC__超的博客-CSDN博客_ios内购流程//这个地址有ios系统app申请账号权限等教程;
3.requestBody | Apple Developer Documentation//苹果内购官网验证接口请求参数
4.verifyReceipt | Apple Developer Documentation//苹果官网内购验证接口返回参数及调用地址
5.status | Apple Developer Documentation//官网状态码
一.苹果支付
 ①逻辑流程图



二,苹果支付流程介绍
①户在app端购买产品下发支付请求指令app;
②app获取用户购买的信息及指令请求苹果系统服务后台进行支付扣,;
③苹果系统服务器扣款成功后返回receipt_data加密数据和支付订单号order_id给app端;
④app端直接将返回的数据及订单号,请求java后台的验证接口;
⑤java后端直接通过HttpsURLConnection将app端携带来的参数以及验证地址url请求苹果系统服务器验证用户在app端支付的结果;(注:receipt_data加密数据不需要在java后台解密,直接传给苹果服务器)
⑥苹果系统服务器将验证的结果及订单产品信息返回给java后台服务器,java后台服务器根据返回的结果处理自己的业务;
⑦java后端处理后自己的业务后,将验证结果以及自己所要返回的内容返回给app端;
②app端在请求苹果系统服务器检查java服务端服务是否已经验证;
③苹果服务告知app端,java服务是否验证成功;
⑧app端根据苹果服务器返回的验证结果通知提示用户订单是否结束;

注:苹果支付内购,价格是以6的倍数定价,且产品订单是唯一的;
三.java代码
①调用验证工具类校验app端返回的结果是否正确
  1. /**
  2.      * TransactionID:苹果配置的产品id
  3.      * String receipt_data:需要客户端传过来的参数2
  4.      * 苹果内购支付
  5.      *
  6.      * @Title: doIosRequest
  7.      * @Description:Ios客户端内购支付
  8.      */
  9.     @RequestMapping("/applePay")
  10.     public Result doIosRequest(HttpServletRequest request, @RequestBody ApplePayVo applePayVo) {
  11.         Result ext = new Result();
  12.         String receipt_data = applePayVo.getReceipt_data();
  13.         String transactionID = applePayVo.getTransaction_id();
  14.         String verifyResult = iosVerifyUtil.buyAppVerify(receipt_data,applePayVo.getType());
  15.              //苹果服务器没有返回验证结果
  16.             if (verifyResult == null) {
  17.                 JSONObject jsonObject= new JSONObject();
  18.                 jsonObject.put("verify_status",-1);
  19.                 ext.setData(jsonObject);
  20.                 ext.setMessage("无订单信息!");
  21.                 ext.setCode(-1);
  22.                 return ext;
  23.             } else {
  24.                 // 苹果验证有返回结果
  25.                 //log.info("线上,苹果平台返回JSON:" + verifyResult);
  26.                 JSONObject job = JSONObject.parseObject(verifyResult);
  27.                 String states = job.getString("status");
  28.                 //获取苹果系统服务器验证结果数据处理自己的业务
  29.                 Result appPay = applePayService.getAppPay(states, job, transactionID, request, applePayVo);
  30.                 return appPay;
  31.             }
  32.         }
复制代码
②获取验证后的数据处理自己的业务逻辑
  1. /**
  2.      * 苹果支付验证后
  3.      **/
  4.     public Result getAppPay(String states, JSONObject job, String transactionID, HttpServletRequest request, ApplePayVo applePayVo) {
  5.         Result ext = new Result();
  6.         //log.info("苹果平台返回值:job" + job);
  7.         //判断是否验证成功
  8.         if ("0".equals(states)) {
  9.             //app端所提供的收据是有效的    验证成功
  10.             String r_receipt = job.getString("receipt");
  11.             JSONObject returnJson = JSONObject.parseObject(r_receipt);
  12.             String in_app = returnJson.getString("in_app");
  13.             JSONObject in_appJson = JSONObject.parseObject(in_app.substring(1, in_app.length() - 1));
  14.             String transactionId = in_appJson.getString("transaction_id");
  15.             //产品id
  16.             String productId = in_appJson.getString("product_id");
  17.             //苹果支付订单状态
  18.             String in_app_ownership_type = in_appJson.getString("in_app_ownership_type");
  19.             //如果获取验证后的支付订单单号与app端传来的支付订单号一致并且状态为已支付状态则处理自己的业务
  20.             if (transactionID.equals(transactionId) && in_app_ownership_type.equals("PURCHASED")) {
  21.             ===================处理自己的业务============================
  22.         }
  23. }
  24.         JSONObject jsonObject = new JSONObject();
  25.         jsonObject.put("verify_status", -1);
  26.         ext.setMessage("receipt数据有问题");
  27.         ext.setData(jsonObject);
  28.         ext.setCode(-1);
  29.         return ext;
  30. }
复制代码
③发送苹果系统服务器支付结果验证工具类
  1. package com.asftek.pay.common.utils;
  2. import org.springframework.beans.factory.annotation.Value;
  3. import org.springframework.stereotype.Component;
  4. import javax.net.ssl.*;
  5. import java.io.BufferedOutputStream;
  6. import java.io.BufferedReader;
  7. import java.io.InputStream;
  8. import java.io.InputStreamReader;
  9. import java.net.URL;
  10. import java.security.cert.CertificateException;
  11. import java.security.cert.X509Certificate;
  12. import java.util.Locale;
  13. @Component
  14. public class IosVerifyUtil {
  15.     private static class TrustAnyTrustManager implements X509TrustManager {
  16.         @Override
  17.         public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
  18.         }
  19.         @Override
  20.         public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
  21.         }
  22.         @Override
  23.         public X509Certificate[] getAcceptedIssuers() {
  24.             return new X509Certificate[]{};
  25.         }
  26.     }
  27.     private static class TrustAnyHostnameVerifier implements HostnameVerifier {
  28.         @Override
  29.         public boolean verify(String hostname, SSLSession session) {
  30.             return true;
  31.         }
  32.     }
  33.     @Value("${applepay.verifyUrl}")
  34.     private  String url_apple_pay;
  35.     @Value("${applepay.verifyTestUrl}")
  36.     private  String test_url_apple_pay;
  37.     /**
  38.      * 苹果服务器验证
  39.      *
  40.      * @param receipt 账单
  41.      * @return null 或返回结果 沙盒 https://sandbox.itunes.apple.com/verifyReceipt
  42.      * @url 要验证的地址
  43.      */
  44.     public  String buyAppVerify(String receipt,int type) {
  45.         //环境判断 线上/开发环境用不同的请求链接
  46.         try {
  47.             String url=null;
  48.             if (type==0){
  49.                  url=test_url_apple_pay; //沙盒环境,测试
  50.             }else {
  51.                 //生成
  52.                 url=url_apple_pay;
  53.             }
  54.             SSLContext sc = SSLContext.getInstance("SSL");
  55.             sc.init(null, new TrustManager[]{new TrustAnyTrustManager()}, new java.security.SecureRandom());
  56.             URL console = new URL(url);
  57.             HttpsURLConnection conn = (HttpsURLConnection) console.openConnection();
  58.             conn.setSSLSocketFactory(sc.getSocketFactory());
  59.             conn.setHostnameVerifier(new TrustAnyHostnameVerifier());
  60.             conn.setRequestMethod("POST");
  61.             conn.setRequestProperty("content-type", "text/json");
  62.             conn.setRequestProperty("Proxy-Connection", "Keep-Alive");
  63.             conn.setDoInput(true);
  64.             conn.setDoOutput(true);
  65.             conn.setConnectTimeout(3000);
  66.             BufferedOutputStream hurlBufOus = new BufferedOutputStream(conn.getOutputStream());
  67.             //拼成固定的格式传给平台
  68.             String str = String.format(Locale.CHINA, "{"receipt-data":"" + receipt + ""}");
  69.             // 直接将receipt当参数发到苹果验证就行,不用拼格
  70.            // String str = String.format(Locale.CHINA, receipt);
  71.             hurlBufOus.write(str.getBytes());
  72.             hurlBufOus.flush();
  73.             InputStream is = conn.getInputStream();
  74.             BufferedReader reader = new BufferedReader(new InputStreamReader(is));
  75.             String line = null;
  76.             StringBuilder sb = new StringBuilder();
  77.             while ((line = reader.readLine()) != null) {
  78.                 sb.append(line);
  79.             }
  80.             return sb.toString();
  81.         } catch (Exception ex) {
  82.             System.out.println("苹果服务器异常");
  83.             ex.printStackTrace();
  84.         }
  85.         return null;
  86.     }
  87. }
复制代码
④java调用验证后苹果系统服务器返回参数
 
  1. 新版IOS返回(7.0以后)
  2. {
  3.     "receipt": {
  4.         "receipt_type": "ProductionSandbox",
  5.         "adam_id": 0,
  6.         "app_item_id": 0,
  7.         "bundle_id": "com.xxxx.xxxx",
  8.         "application_version": "1",
  9.         "download_id": 0,
  10.         "version_external_identifier": 0,
  11.         "receipt_creation_date": "2021-11-01 09:20:51 Etc/GMT",
  12.         "receipt_creation_date_ms": "1635758451000",
  13.         "receipt_creation_date_pst": "2021-11-01 02:20:51 America/Los_Angeles",
  14.         "request_date": "2021-11-01 09:20:52 Etc/GMT",
  15.         "request_date_ms": "1635758452973",
  16.         "request_date_pst": "2021-11-01 02:20:52 America/Los_Angeles",
  17.         "original_purchase_date": "2013-08-01 07:00:00 Etc/GMT",
  18.         "original_purchase_date_ms": "1375340400000",
  19.         "original_purchase_date_pst": "2013-08-01 00:00:00 America/Los_Angeles",
  20.         "original_application_version": "1.0",
  21.         "in_app": [{
  22.             "quantity": "1",
  23.             "product_id": "",//唯一的
  24.             "transaction_id": "1000000901786189",
  25.             "original_transaction_id": "1000000901786189",
  26.             "purchase_date": "2021-11-01 09:13:33 Etc/GMT",
  27.             "purchase_date_ms": "1635758013000",
  28.             "purchase_date_pst": "2021-11-01 02:13:33 America/Los_Angeles",
  29.             "original_purchase_date": "2021-11-01 09:13:33 Etc/GMT",
  30.             "original_purchase_date_ms": "1635758013000",
  31.             "original_purchase_date_pst": "2021-11-01 02:13:33 America/Los_Angeles",
  32.             "is_trial_period": "false",
  33.             "in_app_ownership_type": "PURCHASED"
  34.         }]
  35.     },
  36.     "environment": "Sandbox",
  37.     "status": 0
  38. }
复制代码
⑤错误码




免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

大连全瓷种植牙齿制作中心

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表