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. iOS开发中的错误整理,线程之间通信练习,加载图片的练习中出现的错误 -- Http请求错误

    控制台打印:Application Transport Security has blocked a cleartext HTTP (http://) resource load since it i ...

  2. 【转】pageX、clientX、screenX、offsetX、layerX、x

    参考:http://www.cnblogs.com/xesam/archive/2011/12/08/2280509.html chrome: e.pageX——相对整个页面的坐标e.layerX—— ...

  3. GMM算法k-means算法的比较

    1.EM算法 GMM算法是EM算法族的一个具体例子. EM算法解决的问题是:要对数据进行聚类,假定数据服从杂合的几个概率分布,分布的具体参数未知,涉及到的随机变量有两组,其中一组可观测另一组不可观测. ...

  4. 解决SSH无密码登陆后又需要密码登陆

    主节点CentOS_Master 从节点Slave_1. 我想着可能是 /etc/ssh/sshd_config下的那个公钥文件路径不对,看了下home/hxsyl/.ssh/authorized_k ...

  5. NOIP2005提高组 过河

    题目描述 在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧.在桥上有一些石子,青蛙很讨厌踩在这些石子上.由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青蛙可能到达的点看成数 ...

  6. udp 内网穿透 互发消息

    还差实现内网终端,向服务器发送请求,要对方的内网连接自己,实现打洞.在同一网段,或者公网运行,可以相互聊天. 没有实现检测客户端下线功能. 1,服务器代码 package router; import ...

  7. 轻量级应用开发之(02)UIView

    一 控件 1.屏幕上的所有UI元素都叫做控件(也有叫做视图.组件)比如按钮(UIButton).文本(UILabel)都是控件. 2.控件的共同属性有哪些? 尺寸,位置,背景色 3. 苹果将控件的共同 ...

  8. linux桌面应用开发之折腾

    1 起因 需要开发一个wifi定位的应用,最先在android下搞,后来因为多网卡的原因要换平台,经历了windows,最终选择用kaili linux.debian系的linux,开发桌面应用怎么办 ...

  9. ci连贯操作的limit两个参数和sql是相反的

    ci连贯操作的limit两个参数和sql是相反的 db->where("name =",'mary')->ge() name后面要有个空格否则报错当为一个字段 -> ...

  10. 2个比较经典的PHP加密解密函数分享

    项目中有时我们需要使用PHP将特定的信息进行加密,也就是通过加密算法生成一个加密字符串,这个加密后的字符串可以通过解密算法进行解密,便于程序对解密后的信息进行处理. 最常见的应用在用户登录以及一些AP ...