In-App Purchases验证
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验证的更多相关文章
- 安卓APP测试验证点总结
最近较懒,加之闺女出生后记忆没完全恢复,总是忘东忘西,关于安卓APP测试的验证点还是总结一下,方便设计测试用例时查阅,也给各位博友参考! 1.除APP的正常功能点外,还有以下验证点: 安装/卸载(考虑 ...
- In App Purchases(IAP 应用程序內购买): 完全攻略
原文: http://troybrant.net/blog/2010/01/in-app-purchases-a-full-walkthrough/ 参考: http://www.cocoachina ...
- in App Purchases一个注意事项
在completeTransaction中通过transaction.originalTransaction.payment.productIdentifier得到的productIdentifier ...
- [IPA]IOS In App Purchase(内购)验证
参考我之前的笔记 苹果内购笔记,在客户端向苹果购买成功之后,我们需要进行二次验证. 二次验证 IOS在沙箱环境下购买成功之后,向苹果进行二次验证,确认用户是否购买成功. 当应用向Apple服务器请求购 ...
- 苹果开发——App内购以及验证store的收据(二)
原地址:http://zengwu3915.blog.163.com/blog/static/2783489720137605156966?suggestedreading 三. 客户端使用Store ...
- ris'In App Purchase总结
原地址:http://www.cocoachina.com/bbs/read.php?tid=38555&page=1 In App Purchase属于iPhone SDK3.0的新特性,用 ...
- In App Purchase翻译
一.In App Purchase概览 Store Kit代表App和App Store之间进行通信.程序将从App Store接收那些你想要提供的产品的信息,并将它们显示出来供用户购买.当用户需要购 ...
- App Store内购
一.In App Purchase概览 Store Kit代表App和App Store之间进行通信.程序将从App Store接收那些你想要提供的产品的信息,并将它们显示出来供用户购买.当用户需要购 ...
- AppStore苹果应用支付开发(In App Purchase)翻译
http://yarin.blog.51cto.com/1130898/549141 一.In App Purchase概览 Store Kit代表App和App Store之间进行通信.程序将从Ap ...
随机推荐
- iOS开发中的错误整理,线程之间通信练习,加载图片的练习中出现的错误 -- Http请求错误
控制台打印:Application Transport Security has blocked a cleartext HTTP (http://) resource load since it i ...
- 【转】pageX、clientX、screenX、offsetX、layerX、x
参考:http://www.cnblogs.com/xesam/archive/2011/12/08/2280509.html chrome: e.pageX——相对整个页面的坐标e.layerX—— ...
- GMM算法k-means算法的比较
1.EM算法 GMM算法是EM算法族的一个具体例子. EM算法解决的问题是:要对数据进行聚类,假定数据服从杂合的几个概率分布,分布的具体参数未知,涉及到的随机变量有两组,其中一组可观测另一组不可观测. ...
- 解决SSH无密码登陆后又需要密码登陆
主节点CentOS_Master 从节点Slave_1. 我想着可能是 /etc/ssh/sshd_config下的那个公钥文件路径不对,看了下home/hxsyl/.ssh/authorized_k ...
- NOIP2005提高组 过河
题目描述 在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧.在桥上有一些石子,青蛙很讨厌踩在这些石子上.由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青蛙可能到达的点看成数 ...
- udp 内网穿透 互发消息
还差实现内网终端,向服务器发送请求,要对方的内网连接自己,实现打洞.在同一网段,或者公网运行,可以相互聊天. 没有实现检测客户端下线功能. 1,服务器代码 package router; import ...
- 轻量级应用开发之(02)UIView
一 控件 1.屏幕上的所有UI元素都叫做控件(也有叫做视图.组件)比如按钮(UIButton).文本(UILabel)都是控件. 2.控件的共同属性有哪些? 尺寸,位置,背景色 3. 苹果将控件的共同 ...
- linux桌面应用开发之折腾
1 起因 需要开发一个wifi定位的应用,最先在android下搞,后来因为多网卡的原因要换平台,经历了windows,最终选择用kaili linux.debian系的linux,开发桌面应用怎么办 ...
- ci连贯操作的limit两个参数和sql是相反的
ci连贯操作的limit两个参数和sql是相反的 db->where("name =",'mary')->ge() name后面要有个空格否则报错当为一个字段 -> ...
- 2个比较经典的PHP加密解密函数分享
项目中有时我们需要使用PHP将特定的信息进行加密,也就是通过加密算法生成一个加密字符串,这个加密后的字符串可以通过解密算法进行解密,便于程序对解密后的信息进行处理. 最常见的应用在用户登录以及一些AP ...