ios支付比普通的支付要麻烦许多,由于要走内购,并且像支付宝,微信那种还能够给回调,Apple PAY根被不会回调啊,因此要么找第三方的支付平台,要么自行接入,本篇是直接接入的,applepay的支付手续费是总金额的30%,因此业务逻辑要自行改变。java
流程是这样的:ios
1,IOS传过来的参数通过非空校验及验证码重复校验后先要判断验证码的重复,验证码是手机端向apple请求后,apple返回的data通过MD5加密存库,留个备份,每次验证的时候判断一下重复。web
2.向apple请求,参数是地址,IOS的data,订单ID,换取status,bid,productId,订单ID微信
public static Map verifyReceipt(String reqUrl, String receiptDataJson, String appTransactionId) throws Exception{ reqUrl=https://buy.itunes.apple.com/verifyReceipt int status = -1; String bid = ""; String productId = ""; String transactionId = ""; //This is the URL of the REST webservice in iTunes App Store URL url = new URL(reqUrl); //make connection, use post mode HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); connection.setRequestMethod("POST"); connection.setDoOutput(true); connection.setAllowUserInteraction(false); //Write the JSON query object to the connection output stream PrintStream ps = new PrintStream(connection.getOutputStream()); ps.print(receiptDataJson); ps.close(); //Call the service BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream())); //Extract response String str; StringBuffer sb = new StringBuffer(); while ((str = br.readLine()) != null) { sb.append(str); } br.close(); String response = sb.toString(); //System.out.println("AppleAppStoreVerifyRequest----response:"+response); JSONObject resutl = JSON.parseObject(response); status = resutl.containsKey("status") ? resutl.getInteger("status") : status; JSONObject receipt = resutl.containsKey("receipt") ? resutl.getJSONObject("receipt") : null; if(receipt != null && !StringUtils.isBlank(receipt.toString())){ bid = receipt.containsKey("bundle_id") ? receipt.getString("bundle_id") : bid; JSONArray inApp = receipt.getJSONArray("in_app"); if(inApp != null && !StringUtils.isBlank(inApp.toString())) { if(StringUtils.isBlank(appTransactionId)) { //若是未给订单号,则默认获取第一个 JSONObject inAppJSONObjectTemp = inApp.getJSONObject(0); if (inAppJSONObjectTemp != null && !inAppJSONObjectTemp.isEmpty()) { productId = inAppJSONObjectTemp.containsKey("product_id") ? inAppJSONObjectTemp.getString("product_id") : productId; transactionId = inAppJSONObjectTemp.containsKey("transaction_id") ? inAppJSONObjectTemp.getString("transaction_id") : transactionId; } } else { //若是APP已给定订单号时用订单号进行查找 for(int i=0; i<inApp.size(); i++) { JSONObject inAppJSONObjectTemp = inApp.getJSONObject(i); if (inAppJSONObjectTemp != null && !inAppJSONObjectTemp.isEmpty()) { String transactionIdTemp = inAppJSONObjectTemp.containsKey("transaction_id") ? inAppJSONObjectTemp.getString("transaction_id") : transactionId; if(appTransactionId.equals(transactionIdTemp)) { productId = inAppJSONObjectTemp.containsKey("product_id") ? inAppJSONObjectTemp.getString("product_id") : productId; transactionId = transactionIdTemp; } } } } } } Map resMap = new HashMap(); resMap.put("status",status); resMap.put("bid",bid); resMap.put("productId",productId); resMap.put("transactionId",transactionId); resMap.put("resutl",resutl == null ?"":resutl.toJSONString()); return resMap; }
3.而后去验证返回的status是否合法:app
int resultStauts = Integer.valueOf(String.valueOf(verifyMap.get("status"))); if (resultStauts == 21007) { //本次支付为沙盒支付 if (!"165".equals(thridPartyNotifyVo.getUserId())) { //非苹果审批帐号 沙盒进行充值不进行饭票增长 return false; } }
判断bid,productId是否合法,这一步必定要验,要不会出现替换充值的bug:post
String bid = String.valueOf(verifyMap.get("bid")); String productId = String.valueOf(verifyMap.get("productId")); transactionId = String.valueOf(verifyMap.get("transactionId")); if(!"申请的bid".equals(bid)) {//苹果内购支付使用的iPhone程序的bundle标识是否合法 return false } if(StringUtils.isBlank(productId) || StringUtils.isBlank(transactionId)) { //是否返回商品信息 return false }
4.最后进行下面的业务逻辑,更余额,把加密好的data存库留底,改状态。加密
注意:productID必定要给IOS,并且不能对错,6元的商品对应com.starunion.xxxxxx_Purchase_6Yuan.url
去IOS请求后的bid,必定要验。由于不是IOS给的回调验证必定要当心谨慎,code