1 // 1111.cpp: 定义控制台应用程序的入口点。 2 // 3 4 #include "stdafx.h" 5 #include <cstdlib> 6 #include <iostream> 7 #include <boost/bind.hpp> 8 #include <boost/asio.hpp> 9 #include <boost/asio/ssl.hpp> 10 11 enum { max_length = 1024 }; 12 13 class client 14 { 15 public: 16 client(boost::asio::io_service& io_service, 17 boost::asio::ssl::context& context, 18 boost::asio::ip::tcp::resolver::iterator endpoint_iterator) 19 : socket_(io_service, context) 20 { 21 //socket_.set_verify_mode(boost::asio::ssl::verify_peer); 22 socket_.set_verify_mode(boost::asio::ssl::context::verify_none); 23 socket_.set_verify_callback( 24 boost::bind(&client::verify_certificate, this, _1, _2)); 25 26 boost::asio::async_connect(socket_.lowest_layer(), endpoint_iterator, 27 boost::bind(&client::handle_connect, this, 28 boost::asio::placeholders::error)); 29 } 30 31 bool verify_certificate(bool preverified, 32 boost::asio::ssl::verify_context& ctx) 33 { 34 // The verify callback can be used to check whether the certificate that is 35 // being presented is valid for the peer. For example, RFC 2818 describes 36 // the steps involved in doing this for HTTPS. Consult the OpenSSL 37 // documentation for more details. Note that the callback is called once 38 // for each certificate in the certificate chain, starting from the root 39 // certificate authority. 40 41 // In this example we will simply print the certificate's subject name. 42 char subject_name[256]; 43 X509* cert = X509_STORE_CTX_get_current_cert(ctx.native_handle()); 44 X509_NAME_oneline(X509_get_subject_name(cert), subject_name, 256); 45 std::cout << "Verifying " << subject_name << "\n"; 46 47 return preverified; 48 } 49 50 void handle_connect(const boost::system::error_code& error) 51 { 52 if (!error) 53 { 54 socket_.async_handshake(boost::asio::ssl::stream_base::client, 55 boost::bind(&client::handle_handshake, this, 56 boost::asio::placeholders::error)); 57 } 58 else 59 { 60 std::cout << "Connect failed: " << error.message() << "\n"; 61 } 62 } 63 64 void handle_handshake(const boost::system::error_code& error) 65 { 66 if (!error) 67 { 68 std::cout << "Enter message: "; 69 // std::cin.getline(request_, max_length); 70 size_t request_length = strlen(request_); 71 72 std::stringstream ss; 73 ss << "POST " << " https://sandbox.itunes.apple.com/verifyReceipt HTTP/1.1\r\n"; 74 ss << "User-Agent: Fiddler\r\n"; 75 ss << "Host: sandbox.itunes.apple.com\r\n"; 76 ss << "Accept: */*\r\n"; 77 ss << "Connection: close\r\n\r\n"; 78 79 std::string str = ss.str(); 80 81 boost::asio::async_write(socket_, 82 boost::asio::buffer(str, str.length()), 83 boost::bind(&client::handle_write, this, 84 boost::asio::placeholders::error, 85 boost::asio::placeholders::bytes_transferred)); 86 } 87 else 88 { 89 std::cout << "Handshake failed: " << error.message() << "\n"; 90 } 91 } 92 93 void handle_write(const boost::system::error_code& error, 94 size_t bytes_transferred) 95 { 96 if (!error) 97 { 98 /*boost::asio::async_read(socket_, 99 boost::asio::buffer(reply_, bytes_transferred), 100 boost::bind(&client::handle_read, this, 101 boost::asio::placeholders::error, 102 boost::asio::placeholders::bytes_transferred));*/ 103 boost::asio::streambuf response; 104 boost::asio::read_until(socket_, response, "\r\n"); 105 std::istream response_stream(&response); 106 std::string http_version; 107 response_stream >> http_version; 108 unsigned int status_code; 109 response_stream >> status_code; 110 std::string status_message; 111 std::getline(response_stream, status_message); 112 if (!response_stream || http_version.substr(0, 5) != "HTTP/") 113 { 114 std::cout << "Invalid response\n"; 115 return ; 116 } 117 if (status_code != 200) 118 { 119 std::cout << "Response returned with status code " << status_code << "\n"; 120 return ; 121 } 122 123 // Read the response headers, which are terminated by a blank line. 124 boost::asio::read_until(socket_, response, "\r\n\r\n"); 125 126 // Process the response headers. 127 std::string header; 128 while (std::getline(response_stream, header) && header != "\r") 129 std::cout << header << "\n"; 130 std::cout << "\n"; 131 132 // Write whatever content we already have to output. 133 if (response.size() > 0) 134 std::cout << &response; 135 136 137 try{ // Read until EOF, writing data to output as we go. 138 boost::system::error_code error; 139 char buf[500] = { 0 }; 140 while ( socket_.read_some(boost::asio::buffer(buf, 500), error)>0 ) 141 { 142 boost::system::error_code tmp = error; 143 std::cout << buf; 144 } 145 146 if (error != boost::asio::error::eof) 147 throw boost::system::system_error(error); 148 /** 149 * 21000 App Store不能读取你提供的JSON对象 150 * 21002 receipt-data域的数据有问题 151 * 21003 receipt无法通过验证 152 * 21004 提供的shared secret不匹配你账号中的shared secret 153 * 21005 receipt服务器当前不可用 154 * 21006 receipt合法,但是订阅已过期。服务器接收到这个状态码时,receipt数据仍然会解码并一起发送 155 * 21007 receipt是Sandbox receipt,但却发送至生产系统的验证服务 156 * 21008 receipt是生产receipt,但却发送至Sandbox环境的验证服务 157 */ 158 std::cout << "\r\n\nfinished !!\r\n"; 159 } 160 catch (std::exception& e) 161 { 162 std::cout << "Exception: " << e.what() << "\n"; 163 return; 164 } 165 166 167 } 168 else 169 { 170 std::cout << "Write failed: " << error.message() << "\n"; 171 } 172 } 173 174 void handle_read(const boost::system::error_code& error, 175 size_t bytes_transferred) 176 { 177 if (!error) 178 { 179 std::cout << "Reply: "; 180 std::cout.write(reply_, bytes_transferred); 181 std::cout << "\n"; 182 } 183 else 184 { 185 std::cout << "Read failed: " << error.message() << "\n"; 186 } 187 } 188 189 private: 190 boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket_; 191 char request_[max_length]; 192 char reply_[max_length]; 193 }; 194 195 int main(int argc, char* argv[]) 196 { 197 try 198 { 199 200 boost::asio::io_service io_service; 201 202 boost::asio::ip::tcp::resolver resolver(io_service); 203 boost::asio::ip::tcp::resolver::query query("buy.itunes.apple.com", "443"); 204 boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query); 205 206 boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23); 207 ctx.set_verify_mode(boost::asio::ssl::context::verify_none); 208 //ctx.load_verify_file("ca.pem"); 209 210 client c(io_service, ctx, iterator); 211 212 io_service.run(); 213 } 214 catch (std::exception& e) 215 { 216 std::cerr << "Exception: " << e.what() << "\n"; 217 } 218 219 return 0; 220 }