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. 虚拟机去混杂模式与 vlan in vxlan 特性

    1. 去混杂模式 1.1 背景 混杂模式(Promiscuous Mode)是指一台机器能够接收所有经过它的数据流,而不论其目的地址是否是它.是相对于通常模式(又称“非混杂模式”)而言的. 这被网络管 ...

  2. ovs-agent流程

    1. 代码流程分析 neutron/plugins/openvswitch/agent/ovs_neutron_agent.py:main() plugin = OVSNeutronAgent(**a ...

  3. 表单脚本api_contenteditable

    <html> <head></head> <body> <form> <div contenteditable>ssadas&l ...

  4. Erlang练习题----shopping

    直接就上代码了: -module(shop). -export([cost/1,total/1]). cost(orange) -> 5; cost(newspaper) -> 8; co ...

  5. POJ1753Flip Game(DFS + 枚举)

    Flip Game Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 37050   Accepted: 16122 Descr ...

  6. kaili linux中文乱码

    install kaili 用了kali,安装的英文版,一切都很爽,没有乱码 install chrome 不要用apt安装,也不要用chromium, 直接去网上找chrom的deb文件下来安装,注 ...

  7. 初学JDBC,调用存储过程

    在JDBC简单封装的基础上实现 public class UserDao{ public static void testGetUser(String userName) throws Excepti ...

  8. eclipse 左边目录结构下五referenced library解决办法

    没有referenced library,加入多个jar包,导致项目看上去庞大 解决办法: 在Package Explorer窗口中会出现Referenced Libraries,但Java EE 透 ...

  9. 锋利的jQuery-1--end()

    1.导航菜单:选中后显示当前标签下的子标签并且高亮,并且隐藏其他同级标签,(一行级联操作即完成),主要看end()函数用法. end(): 回到最近的一个"破坏性"操作之前.就是指 ...

  10. Windows 下配置使用MemCached(转载)

    工具: memcached-1.2.6-win32-bin.zip     MemCached服务端程序(for win) Memcached Manager             win下的Mem ...