java对接苹果支付

转自:https://www.jianshu.com/p/976fc6090cfa

官方验证文档地址:Apple Developer Documentation

进行代码前,首先使用postman将收据发送给苹果服务器,熟悉一下返回的数据结构

java对接苹果支付_第1张图片

 工具类


import javax.net.ssl.*;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Locale;

/**
 * 苹果IAP内购验证工具类
 * Created by wangqichang on 2019/2/26.
 */
public class IosVerifyUtil {
    private static class TrustAnyTrustManager implements X509TrustManager {

        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        }

        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        }

        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[] {};
        }
    }

    private static class TrustAnyHostnameVerifier implements HostnameVerifier {
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    }

    private static final String url_sandbox = "https://sandbox.itunes.apple.com/verifyReceipt";
    private static final String url_verify = "https://buy.itunes.apple.com/verifyReceipt";

    /**
     * 苹果服务器验证
     *
     * @param receipt
     *            账单
     * @url 要验证的地址
     * @return null 或返回结果 沙盒 https://sandbox.itunes.apple.com/verifyReceipt
     *
     */
    public static String buyAppVerify(String receipt,int type) {
        //环境判断 线上/开发环境用不同的请求链接
        String url = "";
        if(type==0){
            url = url_sandbox; //沙盒测试
        }else{
            url = url_verify; //线上测试
        }
        //String url = EnvUtils.isOnline() ?url_verify : url_sandbox;

        try {
            SSLContext sc = SSLContext.getInstance("SSL");
            sc.init(null, new TrustManager[] { new TrustAnyTrustManager() }, new java.security.SecureRandom());
            URL console = new URL(url);
            HttpsURLConnection conn = (HttpsURLConnection) console.openConnection();
            conn.setSSLSocketFactory(sc.getSocketFactory());
            conn.setHostnameVerifier(new TrustAnyHostnameVerifier());
            conn.setRequestMethod("POST");
            conn.setRequestProperty("content-type", "text/json");
            conn.setRequestProperty("Proxy-Connection", "Keep-Alive");
            conn.setDoInput(true);
            conn.setDoOutput(true);
            BufferedOutputStream hurlBufOus = new BufferedOutputStream(conn.getOutputStream());

            JSONObject obj = new JSONObject();
            obj.put("receipt-data", receipt);
            //自动续费产品加上password
            // obj.put("password", "**************");
            hurlBufOus.write(obj.toString().getBytes());
            hurlBufOus.flush();

            InputStream is = conn.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(is));
            String line = null;
            StringBuffer sb = new StringBuffer();
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }

            return sb.toString();
        } catch (Exception ex) {
            System.out.println("苹果服务器异常");
            ex.printStackTrace();
        }
        return null;
    }
}

代码JSON包用的hutool的包,需要自行引入或调整代码

public R applePayOrderNotifyCallBack(String transactionId, String payload) {
        //1.先线上测试    发送平台验证
        String verifyResult = IosVerifyUtil.buyAppVerify(payload, 1);
        //苹果服务器没有返回验证结果
        if (verifyResult == null) {
            logger.info("无订单信息!");
            R.fail("无订单信息");
        }
        // 苹果验证有返回结果
        logger.info("线上,苹果平台返回JSON:" + verifyResult);
        JSON job = JSONUtil.parse(verifyResult);
        String states = job.getByPath("status").toString();
        //0 正常
        //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环境的验证服务
        if ("21007".equals(states)) { //是沙盒环境,应沙盒测试,否则执行下面
            //2.再沙盒测试  发送平台验证
            verifyResult = IosVerifyUtil.buyAppVerify(payload, 0);
            logger.info("沙盒环境,苹果平台返回JSON:" + verifyResult);
            job = JSONUtil.parse(verifyResult);
            states = job.getByPath("status").toString();
        }
        logger.info("苹果平台返回值:job" + job);
        if (states.equals("0")) { // 前端所提供的收据是有效的    验证成功
            JSON inAppJson = JSONUtil.parse(JSONUtil.getByPath(job, "receipt.in_app"));
            List jsons = JSONUtil.toList(inAppJson.toString(), JSON.class);
            //所有支付成功的订单号
            List transaction_id =
                    jsons.stream().map(t -> t.getByPath("transaction_id").toString())
                            .distinct().collect(Collectors.toList());
            if(transaction_id.contains(transactionId)){
                return R.ok();
            }
            return R.fail();
        } else {
            return R.fail("receipt数据有问题");
        }
    }

你可能感兴趣的:(java)