package com.demo.controller.web.app;

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.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map; import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.servlet.http.HttpServletRequest; import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody; import sun.misc.BASE64Decoder; import com.demo.common.Result;
import com.demo.common.util.StringUtils;
import com.demo.constant.Constant;
import com.demo.constant.Enums;
import com.demo.service.AppEspOrderService;
import com.demo.service.AppEspProductService;
import com.demo.service.AppUserInfoService;
import com.demo.service.AppVersionService;
import com.demo.service.UserService;
import com.demo.service.eshop.EspOrderLogService;
import com.demo.vo.AppEspOrder;
import com.demo.vo.AppEspProduct;
import com.demo.vo.AppUserInfo;
import com.demo.vo.AppVersion;
import com.demo.vo.EspOrderLog;
import com.demo.vo.User; import net.sf.json.JSONObject; @Controller
@RequestMapping("/app/*")
public class AstroCalendarIOSVerifyController {
private Logger log = Logger.getLogger(AstroCalendarIOSVerifyController.class);
@Autowired
private UserService userService;
@Autowired
private AppEspOrderService appEspOrderService;
@Autowired
private AppVersionService appVersionService;
@Autowired
private AppEspProductService appEspProductService;
@Autowired
private AppUserInfoService appUserInfoService;
@Autowired
private EspOrderLogService espOrderLogService; 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 String buyAppVerify(String receipt,String url,Map<String, String> map) {
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);
conn.setConnectTimeout(30*1000);//设置连接超时30秒
BufferedOutputStream hurlBufOus = new BufferedOutputStream(conn.getOutputStream()); String str = String.format(Locale.CHINA, "{\"receipt-data\":\""+ receipt + "\"}");
System.out.println("str:" + str);
hurlBufOus.write(str.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);
}
System.out.println(sb.toString());
return sb.toString();
} catch (Exception ex) {
log.error("系统异常"+ex);
map.put("orderStatus", "D");
// ex.printStackTrace();
}
return null;
} @RequestMapping("/app/validateOrder" + Constant.JSON)
@ResponseBody
public Map<String, String> validateOrder(HttpServletRequest request) {
long start = System.currentTimeMillis();
Map<String, String> map = new HashMap<String, String>();
User user = checkUserLogin(request);
AppUserInfo appUser = null;
if(user!=null){
appUser = new AppUserInfo();
appUser.setUserId(user.getUserId());
appUser = appUserInfoService.findByPk(appUser);
}
//判断app用户表里是否存在此用户
if(appUser == null){
map.put("loginStatus", "-1");
}else{
map.put("loginStatus", "0");
try {
String receipt = request.getParameter("receipt");
String orderMonths = request.getParameter("orderMonths");
String versionCode = request.getParameter("versionCode");
String appId = request.getParameter("appId");
String price = request.getParameter("price");
if(StringUtils.isBlank(appId) || StringUtils.isBlank(versionCode)){
map.put("orderStatus", "D");
return map;
}
Integer vCode = Integer.parseInt(versionCode);
Integer appID = Integer.parseInt(appId); AppEspOrder aeo = new AppEspOrder();
aeo.setReceipt(receipt);
List<AppEspOrder> list = appEspOrderService.freeFindAll(aeo);
if(list.size()==0){
//添加新订单
AppUserInfo aui = new AppUserInfo();
aui.setUserId(user.getUserId());
aui = appUserInfoService.findByPk(aui);
SimpleDateFormat osf = new SimpleDateFormat("yyMMddHH");
String orderId = Enums.OrderPrefix.NA + osf.format(new Date())+ StringUtils.getRandomSixNUM();
if(aui != null){
AppVersion version = new AppVersion();
version.setVersionCode(vCode);
int count = appVersionService.countFreeFind(version); AppEspProduct aep = new AppEspProduct();
aep.setAppId(appID);
aep = appEspProductService.findByPK(aep);
//检查appID,versionId是否合法
if(aep == null || count<0){
map.put("orderStatus", "C");
return map;
}
aeo.setAppId(aep.getAppId());
aeo.setAppName(aep.getAppName());
aeo.setVersionCode(vCode);
aeo.setUserId(aui.getUserId());
aeo.setNickName(aui.getNickName());
aeo.setEmail(aui.getEmail());
aeo.setOrderId(orderId);
aeo.setOrderMonths(orderMonths);
aeo.setSubtotal(new Long(price));
aeo.setIsFree("N");
aeo.setOrderStatus("A");//新订单
aeo.setCreateBy("system");
aeo.setCreateDt(new Date());
aeo.setPaidDate(new Date());
appEspOrderService.insert(aeo); //订单日志
EspOrderLog log = new EspOrderLog();
log.setRemark("生成新订单,已支付,等待验证...");
log.setChangeTime(new Date());
log.setChangeUser("system");
log.setIsMem("N");
log.setType("A");
log.setOrderId(orderId);
espOrderLogService.addOrderLog(log);
}
//向苹果服务器发起验证
Result result = validateAppleServler(map, receipt, url_verify, aeo, orderId);
if(result.isSuccess()==true){
validateAppleServler(map, receipt, url_sandbox, aeo, orderId);
}
}else{//如果该收据已经存在,判断收据的订单状态,再判断是用户及月份是否相同,防止盗用receipt
AppEspOrder order = list.get(0);
if("A".equals(order.getOrderStatus()) || "D".equals(order.getOrderStatus())){//新订单已经添加尚未验证或验证超时连接错误,需重新请求验证
Result result = validateAppleServler(map, order.getReceipt(), url_verify, order, order.getOrderId());
if(result.isSuccess()==true){
validateAppleServler(map, order.getReceipt(), url_sandbox, order, order.getOrderId());
}
}else if("B".equals(order.getOrderStatus())){
if(receipt.equals(order.getReceipt())&&user.getUserId().equals(order.getUserId())&&orderMonths.equals(order.getOrderMonths())){
map.put("orderStatus", "B");
}else{
map.put("orderStatus", "C");//验证失败
}
}else{
map.put("orderStatus", "C");//验证失败
}
}
} catch (Exception e) {
map.put("orderStatus", "D");
log.error("系统异常"+e);
e.printStackTrace();
}
}
long end = System.currentTimeMillis();
System.out.println("验证收据信息耗时:"+(end-start)+"毫秒");
return map;
}
//向苹果服务器发送验证请求
private Result validateAppleServler(Map<String, String> map, String receipt, String url, AppEspOrder aeo, String orderId) {
Result result = new Result().setSuccess(false);
String verifyResult = buyAppVerify(receipt,url,map);
if (verifyResult != null) {
JSONObject job = JSONObject.fromObject(verifyResult);
String status = job.getString("status");
if ("0".equals(status)){// 验证成功
aeo.setOrderStatus("B"); String r_receipt=job.getString("receipt");
System.out.println(r_receipt);
System.out.println("-------------------------------");
JSONObject returnJson = JSONObject.fromObject(r_receipt);
String product_id = returnJson.getString("product_id"); //产品ID
String quantity = returnJson.getString("quantity"); //数量
String transactionId = returnJson.getString("transaction_id");//交易id
System.out.println("产品id:"+product_id+"\t"+"数量"+quantity+"\t"+"交易id"+transactionId);
aeo.setProductId(product_id);
int total = 0;
if(!StringUtils.isBlank(quantity))
total = Integer.parseInt(quantity);
aeo.setQuantity(total);
aeo.setTransactionId(transactionId);
appEspOrderService.update(aeo); EspOrderLog log2 = new EspOrderLog();
log2.setRemark("向苹果服务器发送验证成功...");
log2.setChangeTime(new Date());
log2.setChangeUser("system");
log2.setIsMem("N");
log2.setType("B");
log2.setOrderId(orderId);
espOrderLogService.addOrderLog(log2);
map.put("orderStatus", "B");
}else if("21007".equals(status)){//重新验证,更改路径为正式环境的路径 EspOrderLog log1 = new EspOrderLog();
log1.setRemark("向苹果正式服务器发送验证失败,得到状态值为21007.");
log1.setChangeTime(new Date());
log1.setChangeUser("system");
log1.setIsMem("N");
log1.setType("A");
log1.setOrderId(orderId);
espOrderLogService.addOrderLog(log1);
result.setSuccess(true);
}else{//验证失败
aeo.setOrderStatus("C");
appEspOrderService.update(aeo); EspOrderLog log1 = new EspOrderLog();
log1.setRemark("向苹果服务器发送验证失败...");
log1.setChangeTime(new Date());
log1.setChangeUser("system");
log1.setIsMem("N");
log1.setType("A");
log1.setOrderId(orderId);
espOrderLogService.addOrderLog(log1);
map.put("orderStatus", "C");
}
}
return result;
}
private User checkUserLogin(HttpServletRequest request) {
String username = request.getParameter("username");
String password = request.getParameter("password");
if (StringUtils.isBlank(username) || StringUtils.isBlank(password)) {
return null;
}
User user = new User();
try {
user.setEmail(username);
user.setPassword(password);
user = userService.userLogin(user); } catch (Exception e) {
log.error("登录失败,用户名或密码错误!" + e);
}
return user;
}
}

  

In-App Purchases验证的更多相关文章

  1. 安卓APP测试验证点总结

    最近较懒,加之闺女出生后记忆没完全恢复,总是忘东忘西,关于安卓APP测试的验证点还是总结一下,方便设计测试用例时查阅,也给各位博友参考! 1.除APP的正常功能点外,还有以下验证点: 安装/卸载(考虑 ...

  2. In App Purchases(IAP 应用程序內购买): 完全攻略

    原文: http://troybrant.net/blog/2010/01/in-app-purchases-a-full-walkthrough/ 参考: http://www.cocoachina ...

  3. in App Purchases一个注意事项

    在completeTransaction中通过transaction.originalTransaction.payment.productIdentifier得到的productIdentifier ...

  4. [IPA]IOS In App Purchase(内购)验证

    参考我之前的笔记 苹果内购笔记,在客户端向苹果购买成功之后,我们需要进行二次验证. 二次验证 IOS在沙箱环境下购买成功之后,向苹果进行二次验证,确认用户是否购买成功. 当应用向Apple服务器请求购 ...

  5. 苹果开发——App内购以及验证store的收据(二)

    原地址:http://zengwu3915.blog.163.com/blog/static/2783489720137605156966?suggestedreading 三. 客户端使用Store ...

  6. ris'In App Purchase总结

    原地址:http://www.cocoachina.com/bbs/read.php?tid=38555&page=1 In App Purchase属于iPhone SDK3.0的新特性,用 ...

  7. In App Purchase翻译

    一.In App Purchase概览 Store Kit代表App和App Store之间进行通信.程序将从App Store接收那些你想要提供的产品的信息,并将它们显示出来供用户购买.当用户需要购 ...

  8. App Store内购

    一.In App Purchase概览 Store Kit代表App和App Store之间进行通信.程序将从App Store接收那些你想要提供的产品的信息,并将它们显示出来供用户购买.当用户需要购 ...

  9. AppStore苹果应用支付开发(In App Purchase)翻译

    http://yarin.blog.51cto.com/1130898/549141 一.In App Purchase概览 Store Kit代表App和App Store之间进行通信.程序将从Ap ...

随机推荐

  1. java.lang.NoSuchFieldError: deferredExpression

    处理:遇到这个异常的时候是用jstl标签,是版本问题,由于MyEclipse添加Java EE5,其中自动包括了jstl1.2的版本,lib中又存在一个jstl1.1.2的jar包,把旧版本的删掉就可 ...

  2. iOS开发中的错误整理,启动图片设置了没有效果;单独创建xib需要注意的事项;图片取消系统渲染的快捷方式

    一.启动图片设置了没有效果 解决方案:缓存啊!卸了程序重新安装吧!!!!! 二.单独创建xib需要注意的事项 三.图片取消系统渲染的快捷方式

  3. 【codevs 1296】营业额统计 水~~

    今天下午先写一个Splay水题来复习一下Splay模板.是不是有点太水了做这种水题我有点良心不安. 可笑的是一开始我竟然WA了一组,看来是我低估水题的数据范围了,我是空节点直接返回inf或-inf,明 ...

  4. 石子合并 区间DP (经典)

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1021 设sum[i][j]为从第i为开始,长度为j的区间的值得和.dp[ ...

  5. poj1308 并查集

    比较恶心 1: 0 0 空树是一棵树 2: 1 1 0 0 不是树 3: 1 2 1 2 0 0 不是树... 4: 1 2 2 3 4 5 不是树 森林不算是树 5: 1 2 2 3 3 4 4 5 ...

  6. HashMap和Hashtable及HashSet的区别

    相关文章1:HashSet,TreeSet和LinkedHashSet的区别 相关文章2:HashSet和TreeSet的区别 Hashtable类     Hashtable继承Map接口,实现一个 ...

  7. 【CodeForces 227A】Where do I Turn?叉积

    题意 ABC的位置关系只有三种可能: 1.在一条直线上,输出TOWARDS A--B--C 2.AB 和BC垂直,B为直角顶点,AB左侧是C,输出LEFT C--B | A 3.AB 和BC垂直,B为 ...

  8. BZOJ-1228 E&D 博弈SG+找啊找啊找规律

    讨厌博弈,找规律找半天还是错的.... 1228: [SDOI2009]E&D Time Limit: 10 Sec Memory Limit: 162 MB Submit: 666 Solv ...

  9. (Beta)Let's-Beta阶段展示博客

    康家华:http://www.cnblogs.com/AmazingMax/ 马阿姨:http://www.cnblogs.com/oushihuahua/ 刘彦熙:http://www.cnblog ...

  10. 洛谷P2015 二叉苹果树

    题目描述 有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点) 这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1. 我们用一根树枝两端连接的结点的编号来 ...