├── LICENSE ├── README.md ├── ServerDemo_Java ├── OauthLoginDemo │ ├── Login.java │ └── authLogin.jsp └── PayNotifyDemo │ ├── Demo.java │ ├── Screenshot.png │ ├── Usage.txt │ └── com │ └── chukong │ └── anysdk │ └── PayNotify.java ├── ServerDemo_NodeJS ├── OauthLoginDemo │ └── login.js └── PayNotifyDemo │ └── paynotice.js ├── ServerDemo_Python ├── OauthLoginDemo │ └── anysdk_login_python_demo.py └── PayNotifyDemo │ └── anysdk_pay_notice_python_demo.py ├── ServerDemo_c# ├── AnySDK_Demo.sln └── AnySDK_Demo │ ├── AnySDK_Demo.csproj │ ├── Login.aspx │ ├── Login.aspx.cs │ ├── Login.aspx.designer.cs │ ├── Payment.aspx │ ├── Payment.aspx.cs │ ├── Payment.aspx.designer.cs │ ├── Properties │ └── AssemblyInfo.cs │ ├── Web.Debug.config │ ├── Web.Release.config │ └── Web.config ├── archived ├── ServerDemo_NodeJS │ ├── OauthLoginDemo │ │ └── login.js │ └── PayNotifyDemo │ │ └── paynotice.js └── ServerDemo_PHP │ ├── OauthLoginDemo │ ├── Login.php │ └── classes │ │ └── HttpHelper.php │ └── PayNotifyDemo │ ├── PayNotice.php │ └── checkSign.php └── php ├── AnySDK.Sdk.class.php ├── AnySDK.config.php ├── READMD.md └── demo ├── adtracking.php ├── login.php └── payNotice.php /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 AnySDK 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Sample_Server 2 | ============= 3 | 4 | 目录结构说明 5 | ===== 6 | 7 | | 目录 | 说明 | 8 | | :----- | :----- | 9 | | archived | 老版本demo归档 | 10 | | php | 新版php sdk和demo | 11 | | ServerDemo_Java | Java demo | 12 | | ServerDemo_NodeJS | NodeJS demo | 13 | | ServerDemo_Python | Python demo | 14 | 15 | 变更记录 16 | ===== 17 | 18 | ### 2016-01-22 19 | 为php和nodejs提供了新版的服务端SDK和demo; 20 | SDK及其配置文件模板可以直接应用于项目中; 21 | demo仅作为服务端SDK的示例代码,不建议直接作为实际项目代码使用。 22 | 23 | -------------------------------------------------------------------------------- /ServerDemo_Java/OauthLoginDemo/Login.java: -------------------------------------------------------------------------------- 1 | package com.anysdk.auth; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.BufferedWriter; 5 | import java.io.InputStream; 6 | import java.io.OutputStream; 7 | import java.io.OutputStreamWriter; 8 | import java.io.PrintWriter; 9 | import java.net.HttpURLConnection; 10 | import java.net.URL; 11 | import java.util.Map; 12 | 13 | import javax.servlet.http.HttpServletRequest; 14 | import javax.servlet.http.HttpServletResponse; 15 | 16 | /** 17 | * 18 | * 登录验证处理类 19 | * @author zhangjunfei 20 | * @date 2014-5-26 上午11:31:10 21 | * @version 1.0 22 | */ 23 | public class Login { 24 | 25 | /** 26 | * anysdk统一登录地址 27 | */ 28 | private String loginCheckUrl = "http://oauth.anysdk.com/api/User/LoginOauth/"; 29 | 30 | /** 31 | * connect time out 32 | * 33 | * @var int 34 | */ 35 | private int connectTimeOut = 30 * 1000; 36 | 37 | /** 38 | * time out second 39 | * 40 | * @var int 41 | */ 42 | private int timeOut = 30 * 1000; 43 | 44 | /** 45 | * user agent 46 | * 47 | * @var string 48 | */ 49 | private static final String userAgent = "px v1.0"; 50 | 51 | /** 52 | * 检查登录合法性及返回sdk返回的用户id或部分用户信息 53 | * @param request 54 | * @param response 55 | * @return 验证合法 返回true 不合法返回 false 56 | */ 57 | public boolean check( HttpServletRequest request, HttpServletResponse response ) { 58 | 59 | try{ 60 | Map params = request.getParameterMap(); 61 | //检测必要参数 62 | if(parametersIsset( params )) { 63 | sendToClient( response, "parameter not complete" ); 64 | return false; 65 | } 66 | 67 | String queryString = getQueryString( request ); 68 | 69 | URL url = new URL( loginCheckUrl ); 70 | HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 71 | conn.setRequestProperty( "User-Agent", userAgent ); 72 | conn.setReadTimeout(timeOut); 73 | conn.setConnectTimeout(connectTimeOut); 74 | conn.setRequestMethod("POST"); 75 | conn.setDoInput(true); 76 | conn.setDoOutput(true); 77 | 78 | OutputStream os = conn.getOutputStream(); 79 | BufferedWriter writer = new BufferedWriter( new OutputStreamWriter(os, "UTF-8") ); 80 | writer.write( queryString ); 81 | writer.flush(); 82 | tryClose( writer ); 83 | tryClose( os ); 84 | conn.connect(); 85 | 86 | InputStream is = conn.getInputStream(); 87 | String result = stream2String( is ); 88 | sendToClient( response, result ); 89 | return true; 90 | } catch( Exception e ) { 91 | e.printStackTrace(); 92 | } 93 | sendToClient( response, "Unknown error!" ); 94 | return false; 95 | } 96 | 97 | 98 | public void setLoginCheckUrl(String loginCheckUrl) { 99 | this.loginCheckUrl = loginCheckUrl; 100 | } 101 | 102 | /** 103 | * 设置连接超时 104 | * @param connectTimeOut 105 | */ 106 | public void setConnectTimeOut(int connectTimeOut) { 107 | this.connectTimeOut = connectTimeOut; 108 | } 109 | 110 | /** 111 | * 设置超时时间 112 | * @param timeOut 113 | */ 114 | public void setTimeOut(int timeOut) { 115 | this.timeOut = timeOut; 116 | } 117 | 118 | 119 | /** 120 | * check needed parameters isset 检查必须的参数 channel 121 | * uapi_key:渠道提供给应用的app_id或app_key(标识应用的id) 122 | * uapi_secret:渠道提供给应用的app_key或app_secret(支付签名使用的密钥) 123 | * 124 | * @param params 125 | * @return boolean 126 | */ 127 | private boolean parametersIsset(Map params) { 128 | return !(params.containsKey("channel") && params.containsKey("uapi_key") 129 | && params.containsKey("uapi_secret")); 130 | } 131 | 132 | /** 133 | * 获取查询字符串 134 | * @param request 135 | * @return 136 | */ 137 | private String getQueryString( HttpServletRequest request ) { 138 | Map params = request.getParameterMap(); 139 | String queryString = ""; 140 | for (String key : params.keySet()) { 141 | String[] values = params.get(key); 142 | for (int i = 0; i < values.length; i++) { 143 | String value = values[i]; 144 | queryString += key + "=" + value + "&"; 145 | } 146 | } 147 | queryString = queryString.substring(0, queryString.length() - 1); 148 | return queryString; 149 | } 150 | 151 | /** 152 | * 获取流中的字符串 153 | * @param is 154 | * @return 155 | */ 156 | private String stream2String( InputStream is ) { 157 | BufferedReader br = null; 158 | try{ 159 | br = new BufferedReader( new java.io.InputStreamReader( is )); 160 | String line = ""; 161 | StringBuilder sb = new StringBuilder(); 162 | while( ( line = br.readLine() ) != null ) { 163 | sb.append( line ); 164 | } 165 | return sb.toString(); 166 | } catch( Exception e ) { 167 | e.printStackTrace(); 168 | } finally { 169 | tryClose( br ); 170 | } 171 | return ""; 172 | } 173 | 174 | /** 175 | * 向客户端应答结果 176 | * @param response 177 | * @param content 178 | */ 179 | private void sendToClient( HttpServletResponse response, String content ) { 180 | response.setContentType( "text/plain;charset=utf-8"); 181 | try{ 182 | PrintWriter writer = response.getWriter(); 183 | writer.write( content ); 184 | writer.flush(); 185 | } catch( Exception e ) { 186 | e.printStackTrace(); 187 | } 188 | } 189 | /** 190 | * 关闭输出流 191 | * @param os 192 | */ 193 | private void tryClose( OutputStream os ) { 194 | try{ 195 | if( null != os ) { 196 | os.close(); 197 | os = null; 198 | } 199 | } catch( Exception e ) { 200 | e.printStackTrace(); 201 | } 202 | } 203 | 204 | /** 205 | * 关闭writer 206 | * @param writer 207 | */ 208 | private void tryClose( java.io.Writer writer ) { 209 | try{ 210 | if( null != writer ) { 211 | writer.close(); 212 | writer = null; 213 | } 214 | } catch( Exception e ) { 215 | e.printStackTrace(); 216 | } 217 | } 218 | 219 | /** 220 | * 关闭Reader 221 | * @param reader 222 | */ 223 | private void tryClose( java.io.Reader reader ) { 224 | try{ 225 | if( null != reader ) { 226 | reader.close(); 227 | reader = null; 228 | } 229 | } catch( Exception e ) { 230 | e.printStackTrace(); 231 | } 232 | } 233 | } 234 | -------------------------------------------------------------------------------- /ServerDemo_Java/OauthLoginDemo/authLogin.jsp: -------------------------------------------------------------------------------- 1 | <%@ page language="java" contentType="text/html; charset=utf-8" 2 | pageEncoding="utf-8"%> 3 | <%@ page import="com.anysdk.auth.Login" %> 4 | <% 5 | Login login = new Login(); 6 | login.check( request, response ); 7 | %> 8 | -------------------------------------------------------------------------------- /ServerDemo_Java/PayNotifyDemo/Demo.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnySDK/Sample_Server/97c14ddb636ec5540fb6ade838dafa61bda9a92e/ServerDemo_Java/PayNotifyDemo/Demo.java -------------------------------------------------------------------------------- /ServerDemo_Java/PayNotifyDemo/Screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnySDK/Sample_Server/97c14ddb636ec5540fb6ade838dafa61bda9a92e/ServerDemo_Java/PayNotifyDemo/Screenshot.png -------------------------------------------------------------------------------- /ServerDemo_Java/PayNotifyDemo/Usage.txt: -------------------------------------------------------------------------------- 1 | javac Demo.java 2 | java Demo -------------------------------------------------------------------------------- /ServerDemo_Java/PayNotifyDemo/com/chukong/anysdk/PayNotify.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnySDK/Sample_Server/97c14ddb636ec5540fb6ade838dafa61bda9a92e/ServerDemo_Java/PayNotifyDemo/com/chukong/anysdk/PayNotify.java -------------------------------------------------------------------------------- /ServerDemo_NodeJS/OauthLoginDemo/login.js: -------------------------------------------------------------------------------- 1 | var http = require('http'); 2 | var qs = require('querystring'); 3 | var oauth_host = "oauth.anysdk.com"; 4 | var oauth_path = "/api/User/LoginOauth/"; 5 | var resJson = null; 6 | var checkLogin = function(postData, callback){ 7 | var options={ 8 | host:oauth_host, 9 | path:oauth_path, 10 | method:"post", 11 | headers:{ 12 | "Content-Type":"application/x-www-form-urlencoded; charset=UTF-8", 13 | "Content-Length":postData.length, 14 | // "User-Agent":"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; BOIE9;ZHCN)" 15 | } 16 | }; 17 | 18 | console.log("#post url:\n"+oauth_host+oauth_path) 19 | console.log("#post data:\n"+postData) 20 | var reqToAnysdk=require("http").request(options,function(resFromAnysdk){ 21 | resFromAnysdk.setEncoding("utf8"); 22 | resFromAnysdk.on("data",function(data){ 23 | console.log("#return data:\n"+data); 24 | resJson = JSON.parse(data); 25 | if (resJson && (resJson.status=="ok")) { 26 | resJson.ext = "登陆验证成功"; 27 | callback(JSON.stringify(resJson)); 28 | }else{ 29 | callback(JSON.stringify(resJson)); 30 | } 31 | }); 32 | 33 | }); 34 | 35 | reqToAnysdk.write(postData); 36 | reqToAnysdk.end(); 37 | 38 | } 39 | var login = function(req, res){ 40 | var info =''; 41 | req.addListener('data', function(chunk){ 42 | info += chunk; 43 | }); 44 | req.addListener('end', function(){ 45 | checkLogin(info, function(msg){ 46 | res.write(msg); 47 | res.end(); 48 | }); 49 | }); 50 | } 51 | var server = http.createServer(login); 52 | server.listen(8888); 53 | -------------------------------------------------------------------------------- /ServerDemo_NodeJS/PayNotifyDemo/paynotice.js: -------------------------------------------------------------------------------- 1 | /** 2 | nodejs 接收anysdk支付通知demo 3 | 注意:根据自己游戏及代码要求进行代码优化调整 4 | */ 5 | 6 | var http = require('http'); 7 | var querystring = require('querystring'); 8 | var util = require('util'); 9 | var crypto = require('crypto'); 10 | 11 | //anysdk privatekey 12 | var private_key = 'EDFD9E563A3D9639BDBD1D1FA5E6E603'; 13 | //anysdk 增强密钥 14 | var enhanced_key = 'N2VlYzQ1MWQ3ZDhhOTYyYmE5YTk'; 15 | 16 | //md5 17 | var my_md5 = function(data){ 18 | //中文字符处理 19 | data = new Buffer(data).toString("binary"); 20 | return crypto.createHash('md5').update(data, "binary").digest('hex').toLowerCase(); 21 | } 22 | 23 | //通用验签 24 | var check_sign = function(post,private_key){ 25 | var source_sign = post.sign; 26 | delete post.sign; 27 | var new_sign = get_sign(post,private_key); 28 | 29 | if(source_sign == new_sign){ 30 | return true; 31 | } 32 | return false; 33 | } 34 | 35 | //增强验签 36 | var check_enhanced_sign = function(post,enhanced_key){ 37 | var source_enhanced_sign = post.enhanced_sign; 38 | delete post.enhanced_sign; 39 | delete post.sign; 40 | var new_sign = get_sign(post,enhanced_key); 41 | 42 | if(source_enhanced_sign == new_sign){ 43 | return true; 44 | } 45 | return false; 46 | } 47 | 48 | //获取签名 49 | var get_sign = function(post,sign_key){ 50 | var keys = []; 51 | 52 | for(key in post){ 53 | console.log("Key:"+key+"\tVaule:"+post[key]); 54 | keys.push(key); 55 | 56 | } 57 | keys = keys.sort(); 58 | var paramString = ''; 59 | for(i in keys){ 60 | if( !post[keys[i]] ) { 61 | continue; 62 | } 63 | paramString += post[keys[i]]; 64 | } 65 | console.log("拼接的字符串:"+paramString); 66 | console.log("第一次md5:"+my_md5(paramString)); 67 | console.log("加入密钥:"+my_md5(paramString)+sign_key); 68 | console.log("第二次md5:"+my_md5(my_md5(paramString)+sign_key)); 69 | 70 | return my_md5(my_md5(paramString)+sign_key); 71 | } 72 | 73 | //接收支付通知 74 | var notice = function(req, res){ 75 | var post =''; 76 | req.addListener('data', function(chunk){ 77 | post += chunk; 78 | }); 79 | req.addListener('end', function(){ 80 | console.log(post+"\n"); 81 | post = querystring.parse(post); 82 | if(check_sign(post,private_key) && check_enhanced_sign(post,enhanced_key)){ 83 | //if(check_enhanced_sign(post,enhanced_key)){ 84 | //异步处理游戏支付发放道具逻辑 85 | res.end('ok'); 86 | }else{ 87 | res.end(util.inspect(post)); 88 | } 89 | 90 | }); 91 | } 92 | 93 | 94 | var server = http.createServer(notice); 95 | server.listen(8889); 96 | 97 | -------------------------------------------------------------------------------- /ServerDemo_Python/OauthLoginDemo/anysdk_login_python_demo.py: -------------------------------------------------------------------------------- 1 | import httplib 2 | 3 | def login_game_xxx(request): 4 | #contributed by 杜可夫 duke.cliff@icloud.com 5 | html = '' 6 | ret = 'login failed' 7 | 8 | private_key = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' 9 | #loginCheckUrl = 'http://oauth.anysdk.com/api/User/LoginOauth/' 10 | 11 | if request.method == 'POST': 12 | post_key = request.POST.get('private_key', '') 13 | if post_key == private_key: 14 | post_data = {} 15 | post_data = request.POST 16 | 17 | anysdk_conn = httplib.HTTPConnection('oauth.anysdk.com') 18 | headers = {"Content-Type": "application/x-www-form-urlencoded"} 19 | 20 | post_str = '' 21 | first = True 22 | for key, value in post_data.items(): 23 | if not first: 24 | post_str += '&' 25 | first = False 26 | post_str += key + '=' + value 27 | 28 | anysdk_conn.request("POST", '/api/User/LoginOauth/', post_str, headers) 29 | 30 | response = anysdk_conn.getresponse() 31 | 32 | if response.status == 200: 33 | content = response.read() 34 | print "any_sdk login result:", content 35 | resp_dict = json.loads(content) 36 | resp_dict['ext'] = 'game_tag' 37 | ret = resp_dict 38 | 39 | html = simplejson.dumps(ret, ensure_ascii=False) 40 | response = HttpResponse(html) 41 | 42 | return response -------------------------------------------------------------------------------- /ServerDemo_Python/PayNotifyDemo/anysdk_pay_notice_python_demo.py: -------------------------------------------------------------------------------- 1 | import hashlib 2 | 3 | def anysdk_payment(request): 4 | 5 | ''' 6 | 7 | contributed by 杜可夫 (duke.cliff@icloud.com) 8 | 9 | ''' 10 | 11 | html = 'ok' 12 | 13 | if request.method == 'POST': 14 | 15 | #private_data may be refererd to as your own tracking number 16 | 17 | private_data = request.POST.get('private_data', '') 18 | 19 | server_id = request.POST.get('server_id', '') 20 | 21 | trade_status = request.POST.get('pay_status', '') 22 | 23 | channel = request.POST.get('channel_number', '') 24 | 25 | user_id = request.POST.get('user_id', '') 26 | 27 | total_fee = float(request.POST.get('amount', '0.0')) 28 | 29 | sign = request.POST.get('sign', '') 30 | 31 | 32 | 33 | private_key = 'xxxxxxxxxxxxxxxx' 34 | 35 | 36 | 37 | if trade_status == '1': 38 | 39 | validated_order = False 40 | 41 | temp_list = [] 42 | 43 | for key, value in request.POST.items(): 44 | 45 | if key != 'sign': 46 | 47 | temp_list.append([key, value]) 48 | 49 | temp_list = sorted(temp_list, cmp=lambda x,y: cmp(x[0], y[0])) 50 | 51 | raw_str = '' 52 | 53 | for item in temp_list: 54 | 55 | raw_str = raw_str + item[1] 56 | 57 | 58 | 59 | md5_raw_str = hashlib.md5(raw_str).hexdigest().lower() 60 | 61 | local_sign = hashlib.md5(md5_raw_str + private_key).hexdigest().lower() 62 | 63 | 64 | 65 | if local_sign == sign: 66 | 67 | validated_order = True 68 | 69 | 70 | 71 | if validated_order: 72 | 73 | #支付完成,并且合法,更新支付状态信息或者通知游戏服务器更新数据... 74 | 75 | pass 76 | 77 | 78 | 79 | html = 'ok' 80 | 81 | response = HttpResponse(html) 82 | 83 | return response 84 | -------------------------------------------------------------------------------- /ServerDemo_c#/AnySDK_Demo.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AnySDK_Demo", "AnySDK_Demo\AnySDK_Demo.csproj", "{738864F2-9FB8-419C-8789-1CAF4B1D6F86}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Any CPU = Debug|Any CPU 9 | Release|Any CPU = Release|Any CPU 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {738864F2-9FB8-419C-8789-1CAF4B1D6F86}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 13 | {738864F2-9FB8-419C-8789-1CAF4B1D6F86}.Debug|Any CPU.Build.0 = Debug|Any CPU 14 | {738864F2-9FB8-419C-8789-1CAF4B1D6F86}.Release|Any CPU.ActiveCfg = Release|Any CPU 15 | {738864F2-9FB8-419C-8789-1CAF4B1D6F86}.Release|Any CPU.Build.0 = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /ServerDemo_c#/AnySDK_Demo/AnySDK_Demo.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | 8 | 9 | 2.0 10 | {738864F2-9FB8-419C-8789-1CAF4B1D6F86} 11 | {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} 12 | Library 13 | Properties 14 | AnySDK_Demo 15 | AnySDK_Demo 16 | v4.5 17 | true 18 | 19 | 20 | 21 | 22 | 23 | 24 | true 25 | full 26 | false 27 | bin\ 28 | DEBUG;TRACE 29 | prompt 30 | 4 31 | 32 | 33 | pdbonly 34 | true 35 | bin\ 36 | TRACE 37 | prompt 38 | 4 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | Login.aspx 67 | ASPXCodeBehind 68 | 69 | 70 | Login.aspx 71 | 72 | 73 | Payment.aspx 74 | ASPXCodeBehind 75 | 76 | 77 | Payment.aspx 78 | 79 | 80 | 81 | 82 | 83 | Web.config 84 | 85 | 86 | Web.config 87 | 88 | 89 | 90 | 10.0 91 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | True 101 | True 102 | 0 103 | / 104 | http://localhost:8954/ 105 | False 106 | False 107 | 108 | 109 | False 110 | 111 | 112 | 113 | 114 | 121 | -------------------------------------------------------------------------------- /ServerDemo_c#/AnySDK_Demo/Login.aspx: -------------------------------------------------------------------------------- 1 | <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Login.aspx.cs" Inherits="AnySDK_Demo.Login" %> 2 | -------------------------------------------------------------------------------- /ServerDemo_c#/AnySDK_Demo/Login.aspx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.Specialized; 4 | using System.Text; 5 | using System.IO; 6 | using System.Net; 7 | using System.Configuration; 8 | using System.Web; 9 | using System.Web.Script.Serialization; 10 | using System.Web.UI; 11 | using System.Web.UI.WebControls; 12 | 13 | namespace AnySDK_Demo 14 | { 15 | public partial class Login : System.Web.UI.Page 16 | { 17 | //登陆地址 18 | string loginCheckUrl = "http://oauth.anysdk.com/api/User/LoginOauth/"; 19 | 20 | //连接超时 21 | int connectTimeOut = 3000; 22 | 23 | protected void Page_Load(object sender, EventArgs e) 24 | { 25 | string strMsg = ""; 26 | try 27 | { 28 | strMsg = postLogin(); 29 | 30 | JavaScriptSerializer serializer = new JavaScriptSerializer(); 31 | Dictionary dicMsg = serializer.Deserialize>(strMsg); 32 | if (dicMsg["status"].ToString() == "ok") 33 | { 34 | //这里可以做数据验证等其他操作 35 | //Dictionary common = (Dictionary)rets["common"]; 36 | dicMsg["ext"] = "test"; 37 | strMsg = serializer.Serialize(dicMsg); 38 | } 39 | } 40 | catch (Exception ex) 41 | { 42 | strMsg = ex.ToString(); 43 | } 44 | Response.Write(strMsg); 45 | } 46 | 47 | string postLogin() 48 | { 49 | HttpWebRequest requester = WebRequest.Create(new Uri(loginCheckUrl)) as HttpWebRequest; 50 | requester.Method = "POST"; 51 | requester.Timeout = connectTimeOut; 52 | requester.ContentType = "application/x-www-form-urlencoded"; 53 | byte[] bs = Encoding.UTF8.GetBytes(getQueryString()); 54 | requester.ContentLength = bs.Length; 55 | using (Stream reqStream = requester.GetRequestStream()) 56 | { 57 | reqStream.Write(bs, 0, bs.Length); 58 | } 59 | 60 | HttpWebResponse responser = requester.GetResponse() as HttpWebResponse; 61 | using (StreamReader reader = new StreamReader(responser.GetResponseStream(), Encoding.UTF8)) 62 | { 63 | return reader.ReadToEnd(); 64 | } 65 | } 66 | 67 | string getQueryString() 68 | { 69 | NameValueCollection req = Request.Form; 70 | string args = ""; 71 | foreach (string key in req.AllKeys) 72 | { 73 | args += key + "=" + req[key] + "&"; 74 | } 75 | args = args.Substring(0, args.Length - 1); 76 | return args; 77 | } 78 | } 79 | } -------------------------------------------------------------------------------- /ServerDemo_c#/AnySDK_Demo/Login.aspx.designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // <自动生成> 3 | // 此代码由工具生成。 4 | // 5 | // 对此文件的更改可能会导致不正确的行为,并且如果 6 | // 重新生成代码,这些更改将会丢失。 7 | // 8 | //------------------------------------------------------------------------------ 9 | 10 | namespace AnySDK_Demo { 11 | 12 | 13 | public partial class Login { 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ServerDemo_c#/AnySDK_Demo/Payment.aspx: -------------------------------------------------------------------------------- 1 | <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Payment.aspx.cs" Inherits="AnySDK_Demo.Payment" %> 2 | -------------------------------------------------------------------------------- /ServerDemo_c#/AnySDK_Demo/Payment.aspx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Web; 4 | using System.Web.UI; 5 | using System.Web.UI.WebControls; 6 | using System.Security.Cryptography; 7 | using System.Text; 8 | using System.Collections.Specialized; 9 | using System.Configuration; 10 | 11 | namespace AnySDK_Demo 12 | { 13 | public partial class Payment : System.Web.UI.Page 14 | { 15 | protected void Page_Load(object sender, EventArgs e) 16 | { 17 | string strMsg = "ok"; 18 | try 19 | { 20 | var data = getData(); 21 | if (data["sign"].ToString() == getSignForAnyValid() && data["pay_status"].ToString() == "1") 22 | { 23 | //支付成功的处理 24 | //注意判断金额,客户端可能被修改从而使用低金额购买高价值道具 25 | 26 | } 27 | } 28 | catch (Exception ex) 29 | { 30 | //错误处理 31 | strMsg = ex.ToString(); 32 | } 33 | 34 | Response.Write(strMsg); 35 | } 36 | 37 | Dictionary getData() 38 | { 39 | Dictionary data = new Dictionary(); 40 | foreach (string key in Request.Form) 41 | { 42 | data[key] = Request.Form[key]; 43 | } 44 | return data; 45 | } 46 | 47 | //获得anysdk支付通知 sign,将该函数返回的值与any传过来的sign进行比较验证 48 | string getSignForAnyValid() 49 | { 50 | NameValueCollection requestParams = Request.Form;//获得所有的参数名 51 | List ps = new List(); 52 | foreach (string key in requestParams) 53 | { 54 | ps.Add(key); 55 | } 56 | 57 | sortParamNames(ps);// 将参数名从小到大排序,结果如:adfd,bcdr,bff,zx 58 | 59 | string paramValues = ""; 60 | foreach (string param in ps) 61 | {//拼接参数值 62 | if (param == "sign") 63 | { 64 | continue; 65 | } 66 | string paramValue = requestParams[param]; 67 | if (paramValue != null) 68 | { 69 | paramValues += paramValue; 70 | } 71 | } 72 | string md5Values = MD5Encode(paramValues); 73 | md5Values = MD5Encode(md5Values.ToLower() + ConfigurationManager.AppSettings["AnySDK_Key"].ToString()).ToLower(); 74 | return md5Values; 75 | } 76 | 77 | //MD5编码 78 | static string MD5Encode(string sourceStr) 79 | { 80 | MD5 md5 = new MD5CryptoServiceProvider(); 81 | byte[] src = Encoding.UTF8.GetBytes(sourceStr); 82 | byte[] res = md5.ComputeHash(src, 0, src.Length); 83 | return BitConverter.ToString(res).ToLower().Replace("-", ""); 84 | } 85 | //将参数名从小到大排序,结果如:adfd,bcdr,bff,zx 86 | static void sortParamNames(List paramNames) 87 | { 88 | paramNames.Sort((string str1, string str2) => { return str1.CompareTo(str2); }); 89 | } 90 | } 91 | } -------------------------------------------------------------------------------- /ServerDemo_c#/AnySDK_Demo/Payment.aspx.designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // <自动生成> 3 | // 此代码由工具生成。 4 | // 5 | // 对此文件的更改可能会导致不正确的行为,并且如果 6 | // 重新生成代码,这些更改将会丢失。 7 | // 8 | //------------------------------------------------------------------------------ 9 | 10 | namespace AnySDK_Demo { 11 | 12 | 13 | public partial class Payment { 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ServerDemo_c#/AnySDK_Demo/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的常规信息通过下列特性集 6 | // 控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle("AnySDK_Demo")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("AnySDK_Demo")] 13 | [assembly: AssemblyCopyright("版权所有(C) 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // 将 ComVisible 设置为 false 会使此程序集中的类型 18 | // 对 COM 组件不可见。如果需要从 COM 访问此程序集中的某个类型, 19 | // 请针对该类型将 ComVisible 特性设置为 true。 20 | [assembly: ComVisible(false)] 21 | 22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 23 | [assembly: Guid("b712cbd9-4e1e-441a-b0ed-657d1e0818a1")] 24 | 25 | // 程序集的版本信息由下列四个值组成: 26 | // 27 | // 主版本 28 | // 次版本 29 | // 内部版本号 30 | // 修订号 31 | // 32 | // 可以指定所有这些值,也可以使用“修订号”和“内部版本号”的默认值, 33 | // 方法是按如下所示使用“*”: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /ServerDemo_c#/AnySDK_Demo/Web.Debug.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 30 | 31 | -------------------------------------------------------------------------------- /ServerDemo_c#/AnySDK_Demo/Web.Release.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 31 | 32 | -------------------------------------------------------------------------------- /ServerDemo_c#/AnySDK_Demo/Web.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /archived/ServerDemo_NodeJS/OauthLoginDemo/login.js: -------------------------------------------------------------------------------- 1 | var http = require('http'); 2 | var qs = require('querystring'); 3 | var oauth_host = "oauth.anysdk.com"; 4 | var oauth_path = "/api/User/LoginOauth/"; 5 | var resJson = null; 6 | var checkLogin = function(postData, callback){ 7 | var options={ 8 | host:oauth_host, 9 | path:oauth_path, 10 | method:"post", 11 | headers:{ 12 | "Content-Type":"application/x-www-form-urlencoded; charset=UTF-8", 13 | "Content-Length":postData.length, 14 | // "User-Agent":"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; BOIE9;ZHCN)" 15 | } 16 | }; 17 | 18 | console.log("#post url:\n"+oauth_host+oauth_path) 19 | console.log("#post data:\n"+postData) 20 | var reqToAnysdk=require("http").request(options,function(resFromAnysdk){ 21 | resFromAnysdk.setEncoding("utf8"); 22 | resFromAnysdk.on("data",function(data){ 23 | console.log("#return data:\n"+data); 24 | resJson = JSON.parse(data); 25 | if (resJson && (resJson.status=="ok")) { 26 | resJson.ext = "登陆验证成功"; 27 | callback(JSON.stringify(resJson)); 28 | }else{ 29 | callback(JSON.stringify(resJson)); 30 | } 31 | }); 32 | 33 | }); 34 | 35 | reqToAnysdk.write(postData); 36 | reqToAnysdk.end(); 37 | 38 | } 39 | var login = function(req, res){ 40 | var info =''; 41 | req.addListener('data', function(chunk){ 42 | info += chunk; 43 | }); 44 | req.addListener('end', function(){ 45 | checkLogin(info, function(msg){ 46 | res.write(msg); 47 | res.end(); 48 | }); 49 | }); 50 | } 51 | var server = http.createServer(login); 52 | server.listen(8888); 53 | -------------------------------------------------------------------------------- /archived/ServerDemo_NodeJS/PayNotifyDemo/paynotice.js: -------------------------------------------------------------------------------- 1 | /** 2 | nodejs 接收anysdk支付通知demo 3 | 注意:根据自己游戏及代码要求进行代码优化调整 4 | */ 5 | 6 | var http = require('http'); 7 | var querystring = require('querystring'); 8 | var util = require('util'); 9 | var crypto = require('crypto'); 10 | 11 | //anysdk privatekey 12 | var private_key = 'EDFD9E563A3D9639BDBD1D1FA5E6E603'; 13 | //anysdk 增强密钥 14 | var enhanced_key = 'N2VlYzQ1MWQ3ZDhhOTYyYmE5YTk'; 15 | 16 | //md5 17 | var my_md5 = function(data){ 18 | //中文字符处理 19 | data = new Buffer(data).toString("binary"); 20 | return crypto.createHash('md5').update(data).digest('hex').toLowerCase(); 21 | } 22 | 23 | //通用验签 24 | var check_sign = function(post,private_key){ 25 | var source_sign = post.sign; 26 | delete post.sign; 27 | var new_sign = get_sign(post,private_key); 28 | 29 | if(source_sign == new_sign){ 30 | return true; 31 | } 32 | return false; 33 | } 34 | 35 | //增强验签 36 | var check_enhanced_sign = function(post,enhanced_key){ 37 | var source_enhanced_sign = post.enhanced_sign; 38 | delete post.enhanced_sign; 39 | delete post.sign; 40 | var new_sign = get_sign(post,enhanced_key); 41 | 42 | if(source_enhanced_sign == new_sign){ 43 | return true; 44 | } 45 | return false; 46 | } 47 | 48 | //获取签名 49 | var get_sign = function(post,sign_key){ 50 | var keys = []; 51 | 52 | for(key in post){ 53 | console.log("Key:"+key+"\tVaule:"+post[key]); 54 | keys.push(key); 55 | 56 | } 57 | keys = keys.sort(); 58 | var paramString = ''; 59 | for(i in keys){ 60 | paramString += post[keys[i]]; 61 | } 62 | console.log("拼接的字符串:"+paramString); 63 | console.log("第一次md5:"+my_md5(paramString)); 64 | console.log("加入密钥:"+my_md5(paramString)+sign_key); 65 | console.log("第二次md5:"+my_md5(my_md5(paramString)+sign_key)); 66 | 67 | return my_md5(my_md5(paramString)+sign_key); 68 | } 69 | 70 | //接收支付通知 71 | var notice = function(req, res){ 72 | var post =''; 73 | req.addListener('data', function(chunk){ 74 | post += chunk; 75 | }); 76 | req.addListener('end', function(){ 77 | console.log(post+"\n"); 78 | post = querystring.parse(post); 79 | if(check_sign(post,private_key) && check_enhanced_sign(post,enhanced_key)){ 80 | //if(check_enhanced_sign(post,enhanced_key)){ 81 | //异步处理游戏支付发放道具逻辑 82 | res.end('ok'); 83 | }else{ 84 | res.end(util.inspect(post)); 85 | } 86 | 87 | }); 88 | } 89 | 90 | 91 | var server = http.createServer(notice); 92 | server.listen(8889); 93 | 94 | -------------------------------------------------------------------------------- /archived/ServerDemo_PHP/OauthLoginDemo/Login.php: -------------------------------------------------------------------------------- 1 | check(); 16 | 17 | /** 18 | * End 测试执行代码 19 | */ 20 | 21 | 22 | class Login { 23 | /** 24 | * debug 模式 25 | */ 26 | 27 | const DEBUG_MODE = TRUE; 28 | 29 | /** 30 | * anysdk统一登录地址 31 | * @var string 32 | */ 33 | private $_loginCheckUrl = 'http://oauth.anysdk.com/api/User/LoginOauth/'; 34 | 35 | /** 36 | * check login 37 | * 检查登录合法性及返回sdk返回的用户id或部分用户信息 38 | */ 39 | public function check() { 40 | //http请求中所有请求参数数组 41 | $params = $_REQUEST; 42 | 43 | //检测必要参数 44 | if (!$this->parametersIsset($params)) { 45 | echo 'parameter not complete'; 46 | exit; 47 | } 48 | 49 | //模拟http请求 50 | include_once './classes/HttpHelper.php'; 51 | $http = new HttpHelper(); 52 | //这里建议使用post方式提交请求,避免客户端提交的参数再次被urlencode导致部分渠道token带有特殊符号验证失败 53 | $result = $http->post($this->_loginCheckUrl, $params); 54 | //@todo在这里处理游戏逻辑,在服务器注册用户信息等 55 | echo $result; 56 | //$result如: {"status":"ok","data":{--渠道服务器返回的信息--},"common":{"channel":"渠道标识","uid":"用户标识"}} 57 | 58 | //输出anysdk统一登录返回 59 | if (self::DEBUG_MODE) { 60 | $logFile = '/tmp/game.server.login.check.log'; 61 | file_put_contents($logFile, "#" . date('Y-m-d H:i:s') . "\n", FILE_APPEND); 62 | file_put_contents($logFile, "#URL:\n" . print_r($http->getUrl(), TRUE) . "\n", FILE_APPEND); 63 | file_put_contents($logFile, "#RESULT:\n" . print_r($result, TRUE) . "\n", FILE_APPEND); 64 | file_put_contents($logFile, "#DECODE:\n" . print_r(json_decode($result, true), TRUE) . "\n", FILE_APPEND); 65 | } 66 | } 67 | 68 | /** 69 | * check needed parameters isset 70 | * 检查必须的参数 channel uapi_key:渠道提供给应用的app_id或app_key(标识应用的id) uapi_secret:渠道提供给应用的app_key或app_secret(支付签名使用的密钥) 71 | * @param type $params 72 | * @return boolean 73 | */ 74 | private function parametersIsset($params) { 75 | if (!(isset($params['channel']) && isset($params['uapi_key']) && isset($params['uapi_secret']))) { 76 | return false; 77 | } 78 | return TRUE; 79 | } 80 | 81 | } 82 | 83 | ?> 84 | -------------------------------------------------------------------------------- /archived/ServerDemo_PHP/OauthLoginDemo/classes/HttpHelper.php: -------------------------------------------------------------------------------- 1 | _connectTimeOut = $time; 40 | return $this; 41 | } 42 | 43 | /** 44 | * set CURLOPT_TIMEOUT - s 45 | * @param type $time 46 | * @return \HttpHelper 47 | */ 48 | public function setTimeOut($time = 30) { 49 | $this->_timeOut = $time; 50 | return $this; 51 | } 52 | 53 | /** 54 | * request url 55 | * @return type 56 | */ 57 | public function getUrl() { 58 | return $this->_url; 59 | } 60 | 61 | /** 62 | * Make an POST request. 63 | * @param string $url url like "http://example.com". 64 | * @param array $data An array to make query string like "example1=&example2=" . 65 | * @return mixed 66 | */ 67 | public function post($url, $data = array()) { 68 | $this->_url = $url; 69 | $query = $this->buildHttpQuery($data, 'POST'); 70 | 71 | $response = $this->makeRequest($this->_url, 'POST', $query); 72 | return $response; 73 | } 74 | 75 | /** 76 | * Make an GET request. 77 | * @param string $url url like "http://example.com". 78 | * @param array $data An array to make query string like "example1=&example2=" . 79 | * @return mixed 80 | */ 81 | public function get($url, $data = array()) { 82 | $this->_url = $url; 83 | if (!empty($data)) { 84 | $this->_url .= "?" . $this->buildHttpQuery($data); 85 | } 86 | $response = $this->makeRequest($this->_url, 'GET'); 87 | return $response; 88 | } 89 | 90 | /** 91 | * Make an HTTP request. 92 | * @param string $url url like "http://example.com/xxxx?example1=&example2=". 93 | * @param string $method Request method is "GET" or "POST". 94 | * @param string $postfields A query string post to $url. 95 | * @param bool $multi. 96 | * @return mixed 97 | */ 98 | public function makeRequest($url, $method, $postfields = NULL) { 99 | $ch = curl_init(); 100 | curl_setopt($ch, CURLOPT_URL, $url); 101 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 102 | curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:')); 103 | if ('POST' === $method) { 104 | curl_setopt($ch, CURLOPT_POST, 1); 105 | if (!empty($postfields)) { 106 | curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields); 107 | } 108 | } 109 | curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->_connectTimeOut); 110 | curl_setopt($ch, CURLOPT_TIMEOUT, $this->_timeOut); 111 | curl_setopt($ch, CURLOPT_USERAGENT, $this->_userAgent); 112 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 113 | curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); 114 | $output = curl_exec($ch); 115 | curl_close($ch); 116 | return $output; 117 | } 118 | 119 | /** 120 | * Build HTTP Query. 121 | * @param array $params Name => value array of parameters. 122 | * @return string HTTP query. 123 | */ 124 | public function buildHttpQuery(array $params, $method = 'GET') { 125 | if (empty($params)) { 126 | return ''; 127 | } 128 | 129 | if ('GET' == $method) { 130 | $keys = $this->urlencode(array_keys($params)); 131 | $values = $this->urlencode(array_values($params)); 132 | } else { 133 | $keys = array_keys($params); 134 | $values = array_values($params); 135 | } 136 | 137 | $params = array_combine($keys, $values); 138 | 139 | uksort($params, 'strcmp'); 140 | 141 | $pairs = array(); 142 | foreach ($params as $key => $value) { 143 | $pairs[] = $key . '=' . $value; 144 | } 145 | 146 | return implode('&', $pairs); 147 | } 148 | 149 | /** 150 | * URL Encode. 151 | * @param mixed $item string or array of items to url encode. 152 | * @return mixed url encoded string or array of strings. 153 | */ 154 | public function urlencode($item) { 155 | static $search = array('%7E'); 156 | static $replace = array('~'); 157 | 158 | if (is_array($item)) { 159 | return array_map(array(&$this, 'urlencode'), $item); 160 | } 161 | 162 | if (is_scalar($item) === false) { 163 | return $item; 164 | } 165 | 166 | return str_replace($search, $replace, rawurlencode($item)); 167 | } 168 | 169 | /** 170 | * URL Decode. 171 | * @param mixed $item Item to url decode. 172 | * @return string URL decoded string. 173 | */ 174 | public function urldecode($item) { 175 | if (is_array($item)) { 176 | return array_map(array(&$this, 'urldecode'), $item); 177 | } 178 | 179 | return urldecode($item); 180 | } 181 | 182 | } 183 | 184 | ?> 185 | -------------------------------------------------------------------------------- /archived/ServerDemo_PHP/PayNotifyDemo/PayNotice.php: -------------------------------------------------------------------------------- 1 | $value) { 18 | // $params[$key] = urldecode($value); 19 | //} 20 | 21 | //注意:如果没有增强密钥的游戏只需要通用验签即可,即只需要checkSign 22 | //if (checkSign($params, $privateKey)) { 23 | if (checkSign($params, $privateKey) && checkEnhancedSign($params, $enhancedKey)) { 24 | checkAmount($params); 25 | // @todo 验证成功,游戏服务器处理逻辑 26 | echo "ok"; 27 | } else { 28 | //@todo 29 | echo "Wrong signature."; 30 | } 31 | exit; 32 | 33 | 34 | /** 35 | * anysdk 支付通知白名单判断 36 | */ 37 | function checkAnySDKSever() { 38 | $AnySDKServerIps = array('211.151.20.126', '211.151.20.127'); 39 | $remoteIp = $_SERVER['REMOTE_ADDR']; 40 | if (!in_array($remoteIp, $AnySDKServerIps)) { 41 | echo "remote address is illegal."; 42 | exit; 43 | } 44 | } 45 | 46 | /** 47 | * 检测道具金额与实际金额是否一致,开发者根据实际情况自己实现判断方式 48 | * @param type $params 49 | */ 50 | function checkAmount($params) { 51 | if (getProductAmount($params['product_id']) != $params['amount']) { 52 | echo 'Purchase is illegal. order_id:' . $params['order_id']; 53 | exit; 54 | } 55 | } 56 | 57 | /** 58 | * 获取道具在服务器上的金额 59 | * @param type $productId 60 | * @return int 单位元 61 | */ 62 | function getProductAmount($productId) { 63 | //get amount by productId 64 | return 1; 65 | } 66 | 67 | /** 68 | * 通用验签 69 | * @param array $data 接收到的所有请求参数数组,通过$_POST可以获得。注意data数据如果服务器没有自动解析,请做一次urldecode(参考rfc1738标准)处理 70 | * @param array $privateKey AnySDK分配的游戏privateKey 71 | * @return bool 72 | */ 73 | function checkSign($data, $privateKey) { 74 | if (empty($data) || !isset($data['sign']) || empty($privateKey)) { 75 | return false; 76 | } 77 | $sign = $data['sign']; 78 | //sign 不参与签名 79 | unset($data['sign']); 80 | $_sign = getSign($data, $privateKey); 81 | if ($_sign != $sign) { 82 | return false; 83 | } 84 | return true; 85 | } 86 | 87 | /** 88 | * 增强验签 89 | * @param type $data 90 | * @param type $enhancedKey 91 | * @return boolean 92 | */ 93 | function checkEnhancedSign($data, $enhancedKey) { 94 | if (empty($data) || !isset($data['enhanced_sign']) || empty($enhancedKey)) { 95 | return false; 96 | } 97 | $enhancedSign = $data['enhanced_sign']; 98 | //sign及enhanced_sign 不参与签名 99 | unset($data['sign'], $data['enhanced_sign']); 100 | $_enhancedSign = getSign($data, $enhancedKey); 101 | if ($_enhancedSign != $enhancedSign) { 102 | return false; 103 | } 104 | return true; 105 | } 106 | 107 | /** 108 | * 计算签名 109 | * @param array $data 110 | * @param string $key 111 | * @return string 112 | */ 113 | function getSign($data, $key) { 114 | file_put_contents(LOG_FILE, "#\n#原始数组:\n" . print_r($data, true) . "\n", FILE_APPEND); 115 | 116 | //数组按key升序排序 117 | ksort($data); 118 | file_put_contents(LOG_FILE, "#\n#参数数组按key升序:\n" . print_r($data, true) . "\n", FILE_APPEND); 119 | 120 | //将数组中的值不加任何分隔符合并成字符串 121 | $string = implode('', $data); 122 | file_put_contents(LOG_FILE, "#\n#将数组值连接成字符串:\n" . print_r($string, true) . "\n", FILE_APPEND); 123 | 124 | //第一次md5并转换成小写 125 | $theFirstMd5String = strtolower(md5($string)); 126 | file_put_contents(LOG_FILE, "#\n#第一次md5并小写:\n" . print_r($theFirstMd5String, true) . "\n", FILE_APPEND); 127 | 128 | //追加privatekey 129 | $addPrivateKeyString = $theFirstMd5String . $key; 130 | file_put_contents(LOG_FILE, "#\n#追加密钥后:\n" . print_r($addPrivateKeyString, true) . "\n", FILE_APPEND); 131 | 132 | //第二次md5并转换成小写 133 | $theLastMd5String = strtolower(md5($addPrivateKeyString)); 134 | file_put_contents(LOG_FILE, "#\n#最后一次md5并小写(签名):\n" . print_r($theLastMd5String, true) . "\n", FILE_APPEND); 135 | 136 | return $theLastMd5String; 137 | // return strtolower(md5(strtolower(md5($string)) . $privateKey)); 138 | } 139 | 140 | /** 141 | * 获取HTTP请求原文 调试使用 142 | * @return string 143 | */ 144 | function get_http_raw() { 145 | $raw = ''; 146 | 147 | // (1) 请求行 148 | $raw .= $_SERVER['REQUEST_METHOD'] . ' ' . $_SERVER['REQUEST_URI'] . ' ' . $_SERVER['SERVER_PROTOCOL'] . "\n"; 149 | 150 | // (2) 请求Headers 151 | foreach ($_SERVER as $key => $value) { 152 | if (substr($key, 0, 5) === 'HTTP_') { 153 | $key = substr($key, 5); 154 | $key = str_replace('_', '-', $key); 155 | 156 | $raw .= $key . ': ' . $value . "\n"; 157 | } 158 | } 159 | 160 | // (3) 空行 161 | $raw .= "\n"; 162 | 163 | // (4) 请求Body 164 | $raw .= file_get_contents('php://input'); 165 | 166 | return $raw; 167 | } 168 | 169 | ?> 170 | -------------------------------------------------------------------------------- /archived/ServerDemo_PHP/PayNotifyDemo/checkSign.php: -------------------------------------------------------------------------------- 1 | $value) { 12 | $data[$key] = urldecode($value); 13 | } 14 | * */ 15 | $privateKey = "481946CEC51BEDE79ED72391F42B4CAF"; 16 | $enhancedKey = 'OGM3ODFkNDRhYjUzYjM4ZmUzZjk'; 17 | //注意:如果没有增强密钥的游戏只需要通用验签即可,即只需要checkSign 18 | //if (checkSign($data, $privateKey)) { 19 | if (checkSign($data, $privateKey) && checkEnhancedSign($data, $enhancedKey)) { 20 | // @todo 验证成功,游戏服务器处理逻辑 21 | echo "ok"; 22 | } else { 23 | //@todo 24 | echo "failed"; 25 | } 26 | 27 | /** 28 | * 通用验签 29 | * @param array $data 接收到的所有请求参数数组,通过$_POST可以获得。注意data数据如果服务器没有自动解析,请做一次urldecode(参考rfc1738标准)处理 30 | * @param array $privateKey AnySDK分配的游戏privateKey 31 | * @return bool 32 | */ 33 | function checkSign($data, $privateKey) { 34 | if (empty($data) || !isset($data['sign']) || empty($privateKey)) { 35 | return false; 36 | } 37 | $sign = $data['sign']; 38 | //sign 不参与签名 39 | unset($data['sign']); 40 | $_sign = getSign($data, $privateKey); 41 | if ($_sign != $sign) { 42 | return false; 43 | } 44 | return true; 45 | } 46 | 47 | /** 48 | * 增强验签 49 | * @param type $data 50 | * @param type $enhancedKey 51 | * @return boolean 52 | */ 53 | function checkEnhancedSign($data, $enhancedKey) { 54 | if (empty($data) || !isset($data['enhanced_sign']) || empty($enhancedKey)) { 55 | return false; 56 | } 57 | $enhancedSign = $data['enhanced_sign']; 58 | //sign及enhanced_sign 不参与签名 59 | unset($data['sign'], $data['enhanced_sign']); 60 | $_enhancedSign = getSign($data, $enhancedKey); 61 | if ($_enhancedSign != $enhancedSign) { 62 | return false; 63 | } 64 | return true; 65 | } 66 | 67 | /** 68 | * 计算签名 69 | * @param array $data 70 | * @param string $key 71 | * @return string 72 | */ 73 | function getSign($data, $key) { 74 | //数组按key升序排序 75 | ksort($data); 76 | //将数组中的值不加任何分隔符合并成字符串 77 | $string = implode('', $data); 78 | //做一次md5并转换成小写,末尾追加游戏的privateKey,最后再次做md5并转换成小写 79 | return strtolower(md5(strtolower(md5($string)) . $key)); 80 | } 81 | 82 | ?> 83 | -------------------------------------------------------------------------------- /php/AnySDK.Sdk.class.php: -------------------------------------------------------------------------------- 1 | 7 | * @date 2016-01-11 8 | * @version 2.1.0 9 | * @link http://docs.anysdk.com/OauthLogin 统一登录验证 10 | * @link http://docs.anysdk.com/PaymentNotice 订单支付通知 11 | * @link http://docs.anysdk.com/AdTracking 广告效果追踪 12 | */ 13 | class Sdk_AnySDK { 14 | 15 | const DEBUG_MODE_ON = TRUE; 16 | const DEBUG_MODE_OFF = FALSE; 17 | 18 | /** 19 | * 支付通知检查所有签名 20 | */ 21 | const PAYMENT_SIGN_CHECK_MODE_BOTH = 1; 22 | 23 | /** 24 | * 支付通知仅检查增强签名 enhanced_sign,此项为默认值 25 | */ 26 | const PAYMENT_SIGN_CHECK_MODE_ENHANCED = 2; 27 | 28 | /** 29 | * 各种过期时间的默认值10秒 30 | */ 31 | const TIMEOUT_SECONDS_DEFAULT = 10; 32 | 33 | /** 34 | * AnySDK登录验证url 35 | * @var String 36 | */ 37 | const LOGIN_CHECK_URL = 'http://oauth.anysdk.com/api/User/LoginOauth/'; 38 | 39 | /** 40 | * AnySDK广告效果追踪数据报送接口 41 | * @var String 42 | */ 43 | const ADTRACKING_REPORT_URL = 'http://pay.anysdk.com/v5/AdTracking/Submit/'; 44 | 45 | /** 46 | * =================================================================================== 47 | * 将字符常量定义成代码常量 48 | * 主要是一些字段名称 49 | */ 50 | const FIELD_TOKEN = 'token'; 51 | const FIELD_METHOD = 'method'; 52 | const FIELD_STATUS = 'status'; 53 | const FIELD_COMMON = 'common'; 54 | const FIELD_COMMON_CHANNEL = 'channel'; 55 | const FIELD_COMMON_USER_SDK = 'user_sdk'; 56 | const FIELD_COMMON_UID = 'uid'; 57 | const FIELD_COMMON_SERVER_ID = 'server_id'; 58 | const FIELD_COMMON_PLUGIN_ID = 'plugin_id'; 59 | const FIELD_DATA = 'data'; 60 | const FIELD_EXT = 'ext'; 61 | const FIELD_PRIVATE_KEY = 'private_key'; 62 | const FIELD_SIGN = 'sign'; 63 | const FIELD_ENHANCED_SIGN = 'enhanced_sign'; 64 | const FIELD_CHANNEL = 'channel'; 65 | const FIELD_UAPI_KEY = 'uapi_key'; 66 | const FIELD_UAPI_SECRET = 'uapi_secret'; 67 | const FIELD_ORDER_ID = 'order_id'; 68 | const FIELD_PRODUCT_COUNT = 'product_count'; 69 | const FIELD_AMOUNT = 'amount'; 70 | const FIELD_PAY_STATUS = 'pay_status'; 71 | const FIELD_PAY_TIME = 'pay_time'; 72 | const FIELD_USER_ID = 'user_id'; 73 | const FIELD_ORDER_TYPE = 'order_type'; 74 | const FIELD_GAME_USER_ID = 'game_user_id'; 75 | const FIELD_SERVER_ID = 'server_id'; 76 | const FIELD_PRODUCT_NAME = 'product_name'; 77 | const FIELD_PRODUCT_ID = 'product_id'; 78 | const FIELD_PRIVATE_DATA = 'private_data'; 79 | const FIELD_CHANNEL_PRODUCT_ID = 'channel_product_id'; 80 | const FIELD_CHANNEL_ORDER_ID = 'channel_order_id'; 81 | const FIELD_CHANNEL_NUMBER = 'channel_number'; 82 | const FIELD_SOURCE = 'source'; 83 | 84 | /** 85 | * 将字符常量定义成代码常量结束 86 | * =================================================================================== 87 | */ 88 | const LOGIN_STATUS_OK = 'ok'; 89 | const LOGIN_STATUS_FAIL = 'fail'; 90 | const PAYMENT_RESPONSE_OK = 'ok'; 91 | const PAYMENT_RESPONSE_FAIL = 'fail.'; 92 | const PAYMENT_STATUS_SUCCESS = 1; 93 | const ADTRACKING_REPORT_STATUS_OK = 'ok'; 94 | const ADTRACKING_REPORT_STATUS_FAIL = 'fail'; 95 | const HTTP_METHOD_POST = 'POST'; 96 | const HTTP_METHOD_GET = 'GET'; 97 | 98 | /** 99 | * 广告效果追踪报送接口常量 100 | * @var String 101 | */ 102 | const ADTRACKING_METHOD_PAYMENT = 'Payment'; 103 | 104 | private $_debugMode = self::DEBUG_MODE_OFF; 105 | private $_loginCheckUrl = self::LOGIN_CHECK_URL; 106 | private $_adTrackingReportUrl = self::ADTRACKING_REPORT_URL; 107 | private $_lastError = ''; 108 | private $_privateKey = ''; 109 | private $_enhancedKey = ''; 110 | private $_httpConnectTimeout = 10; 111 | private $_httpTimeout = 10; 112 | private $_usePrivateKeyForLoginForward = FALSE; 113 | 114 | /** 115 | * 登录验证结果 116 | * 117 | * @var type 118 | */ 119 | private $_loginStatus = FALSE; 120 | 121 | /** 122 | * 广告效果追踪报送结果 123 | * 124 | * @var type 125 | */ 126 | private $_adTrackingReportStatus = FALSE; 127 | 128 | /** 129 | * 登录验证成功之后将验证结果以数组形式存储起来 130 | * @var Array 131 | */ 132 | private $_loginResponse = array(); 133 | 134 | /** 135 | * 默认只检查增强签名 136 | * @var type 137 | */ 138 | private $_paymentSignCheckMode = self::PAYMENT_SIGN_CHECK_MODE_ENHANCED; 139 | 140 | /** 141 | * 调试信息 142 | * @var Array 143 | */ 144 | private $_debugInfo = array(); 145 | 146 | /** 147 | * ip白名单 148 | */ 149 | private $_ipWhiteList = array('211.151.20.126', '211.151.20.127', '117.121.57.82', '::1', '127.0.0.1'); 150 | 151 | /** 152 | * 支付通知验签成功后将参数保存起来 153 | * 154 | * @var Array 155 | */ 156 | private $_paymentParams = array(); 157 | 158 | /** 159 | * 构造方法,优先设置debug模式以便构造方法接下来也可以记录_debugInfo 160 | * 161 | * @param type $enhancedKey 162 | * @param type $privateKey 163 | * @param type $loginCheckUrl 164 | * @param type $debugMode 165 | */ 166 | public function __construct($enhancedKey = '', $privateKey = '', $loginCheckUrl = self::LOGIN_CHECK_URL, $debugMode = self::DEBUG_MODE_OFF) { 167 | $this->_debugMode = $debugMode; 168 | $this->_appendDebugInfo(__METHOD__ . ': init _debugMode = ' . $this->_debugMode); 169 | 170 | $this->_enhancedKey = $enhancedKey; 171 | $this->_appendDebugInfo(__METHOD__ . ': init _enhancedKey = ' . $this->_enhancedKey); 172 | 173 | $this->_privateKey = $privateKey; 174 | $this->_appendDebugInfo(__METHOD__ . ': init _privateKey = ' . $this->_privateKey); 175 | 176 | $this->_loginCheckUrl = $loginCheckUrl; 177 | $this->_appendDebugInfo(__METHOD__ . ': init _loginCheckUrl = ' . $this->_loginCheckUrl); 178 | } 179 | 180 | public function __destruct() { 181 | ; 182 | } 183 | 184 | /** 185 | * 设置debug模式 186 | * 187 | * @param Boolean $debugMode 188 | */ 189 | public function setDebugMode($debugMode = self::DEBUG_MODE_ON) { 190 | $this->_debugMode = $debugMode; 191 | $this->_appendDebugInfo(__METHOD__ . ': init _debugMode = ' . $this->_debugMode); 192 | } 193 | 194 | /** 195 | * 获取调试信息 196 | * 197 | * @param String $separator 传递null将会以数组形式返回,否则将以$separator连接调试信息为字符串后返回 198 | * @return Mixed String/Array 199 | */ 200 | public function getDebugInfo($separator = PHP_EOL) { 201 | if (is_null($separator)) { 202 | return $this->_debugInfo; 203 | } 204 | 205 | return implode($separator, $this->_debugInfo); 206 | } 207 | 208 | /** 209 | * 获取登录状态 210 | * 211 | * @return Boolean 212 | */ 213 | public function getLoginStatus() { 214 | return $this->_loginStatus; 215 | } 216 | 217 | /** 218 | * 获取登录返回结果的common/channel字段 219 | * @return boolean|string 220 | */ 221 | public function getLoginChannel() { 222 | if (isset($this->_loginResponse[self::FIELD_COMMON][self::FIELD_COMMON_CHANNEL])) { 223 | return $this->_loginResponse[self::FIELD_COMMON][self::FIELD_COMMON_CHANNEL]; 224 | } 225 | 226 | return FALSE; 227 | } 228 | 229 | /** 230 | * 获取登录返回结果的common/user_sdk字段 231 | * @return boolean|string 232 | */ 233 | public function getLoginUserSdk() { 234 | if (isset($this->_loginResponse[self::FIELD_COMMON][self::FIELD_COMMON_USER_SDK])) { 235 | return $this->_loginResponse[self::FIELD_COMMON][self::FIELD_COMMON_USER_SDK]; 236 | } 237 | 238 | return FALSE; 239 | } 240 | 241 | /** 242 | * 获取登录结果的common/server_id字段 243 | * @return boolean|string 244 | */ 245 | public function getLoginServerId() { 246 | if (isset($this->_loginResponse[self::FIELD_COMMON][self::FIELD_COMMON_SERVER_ID])) { 247 | return $this->_loginResponse[self::FIELD_COMMON][self::FIELD_COMMON_SERVER_ID]; 248 | } 249 | 250 | return FALSE; 251 | } 252 | 253 | /** 254 | * 获取登录结果的common/uid字段 255 | * @return boolean|string 256 | */ 257 | public function getLoginUid() { 258 | if (isset($this->_loginResponse[self::FIELD_COMMON][self::FIELD_COMMON_UID])) { 259 | return $this->_loginResponse[self::FIELD_COMMON][self::FIELD_COMMON_UID]; 260 | } 261 | 262 | return FALSE; 263 | } 264 | 265 | /** 266 | * 获取登录结果的common/plugin_id字段 267 | * 268 | * @return boolean|string 269 | */ 270 | public function getLoginPluginId() { 271 | if (isset($this->_loginResponse[self::FIELD_COMMON][self::FIELD_COMMON_PLUGIN_ID])) { 272 | return $this->_loginResponse[self::FIELD_COMMON][self::FIELD_COMMON_PLUGIN_ID]; 273 | } 274 | 275 | return FALSE; 276 | } 277 | 278 | /** 279 | * 获取登录结果的data字段,也就是渠道返回的原始参数 280 | * @return mixed 281 | */ 282 | public function getLoginData() { 283 | if (isset($this->_loginResponse[self::FIELD_DATA])) { 284 | return $this->_loginResponse[self::FIELD_DATA]; 285 | } 286 | 287 | return FALSE; 288 | } 289 | 290 | /** 291 | * 292 | * @return boolean 293 | */ 294 | public function getLoginExt() { 295 | if (isset($this->_loginResponse[self::FIELD_EXT])) { 296 | return $this->_loginResponse[self::FIELD_EXT]; 297 | } 298 | 299 | return FALSE; 300 | } 301 | 302 | /** 303 | * 获取登录结果数组,通常用于设置完ext后获取结果返回给请求发起方 304 | * 305 | * @return Array 306 | */ 307 | public function getLoginResponse() { 308 | return $this->_loginResponse; 309 | } 310 | 311 | /** 312 | * 支付通知参数 313 | * 314 | * @return type 315 | */ 316 | public function getPaymentParams() { 317 | return $this->_paymentParams; 318 | } 319 | 320 | /** 321 | * 设置登录结果的ext字段 322 | * @param type $ext 323 | */ 324 | public function setLoginExt($ext) { 325 | $this->_loginResponse[self::FIELD_EXT] = $ext; 326 | } 327 | 328 | /** 329 | * 订单状态 330 | * 331 | * @return boolean 332 | */ 333 | public function getPaymentStatus() { 334 | if (isset($this->_paymentParams[self::FIELD_PAY_STATUS])) { 335 | return $this->_paymentParams[self::FIELD_PAY_STATUS]; 336 | } 337 | 338 | return FALSE; 339 | } 340 | 341 | /** 342 | * AnySDK订单id 343 | * @return boolean 344 | */ 345 | public function getPaymentOrderId() { 346 | if (isset($this->_paymentParams[self::FIELD_ORDER_ID])) { 347 | return $this->_paymentParams[self::FIELD_ORDER_ID]; 348 | } 349 | 350 | return FALSE; 351 | } 352 | 353 | /** 354 | * 订单金额 355 | * @return boolean 356 | */ 357 | public function getPaymentAmount() { 358 | if (isset($this->_paymentParams[self::FIELD_AMOUNT])) { 359 | return $this->_paymentParams[self::FIELD_AMOUNT]; 360 | } 361 | 362 | return FALSE; 363 | } 364 | 365 | /** 366 | * 订单类型 367 | * 368 | * @return boolean 369 | */ 370 | public function getPaymentOrderType() { 371 | if (isset($this->_paymentParams[self::FIELD_ORDER_TYPE])) { 372 | return $this->_paymentParams[self::FIELD_ORDER_TYPE]; 373 | } 374 | 375 | return FALSE; 376 | } 377 | 378 | /** 379 | * 渠道号 380 | * 381 | * @return boolean 382 | */ 383 | public function getPaymentChannelNumber() { 384 | if (isset($this->_paymentParams[self::FIELD_CHANNEL_NUMBER])) { 385 | return $this->_paymentParams[self::FIELD_CHANNEL_NUMBER]; 386 | } 387 | 388 | return FALSE; 389 | } 390 | 391 | /** 392 | * 自定义参数,透传字段 393 | * 394 | * @return boolean 395 | */ 396 | public function getPaymentPrivateData() { 397 | if (isset($this->_paymentParams[self::FIELD_PRIVATE_DATA])) { 398 | return $this->_paymentParams[self::FIELD_PRIVATE_DATA]; 399 | } 400 | 401 | return FALSE; 402 | } 403 | 404 | /** 405 | * 渠道通知原始参数 406 | * 407 | * @return boolean 408 | */ 409 | public function getPaymentSource() { 410 | if (isset($this->_paymentParams[self::FIELD_SOURCE])) { 411 | return $this->_paymentParams[self::FIELD_SOURCE]; 412 | } 413 | 414 | return FALSE; 415 | } 416 | 417 | /** 418 | * 在AnySDK配置的商品id 419 | * 420 | * @return boolean 421 | */ 422 | public function getPaymentProductId() { 423 | if (isset($this->_paymentParams[self::FIELD_PRODUCT_ID])) { 424 | return $this->_paymentParams[self::FIELD_PRODUCT_ID]; 425 | } 426 | 427 | return FALSE; 428 | } 429 | 430 | /** 431 | * 商品数量 432 | * 433 | * @return boolean 434 | */ 435 | public function getPaymentProductCount() { 436 | if (isset($this->_paymentParams[self::FIELD_PRODUCT_COUNT])) { 437 | return $this->_paymentParams[self::FIELD_PRODUCT_COUNT]; 438 | } 439 | 440 | return FALSE; 441 | } 442 | 443 | /** 444 | * 通知时间 445 | * 446 | * @return boolean 447 | */ 448 | public function getPaymentTime() { 449 | if (isset($this->_paymentParams[self::FIELD_PAY_TIME])) { 450 | return $this->_paymentParams[self::FIELD_PAY_TIME]; 451 | } 452 | 453 | return FALSE; 454 | } 455 | 456 | /** 457 | * 用户id 458 | * 459 | * @return boolean 460 | */ 461 | public function getPaymentUserId() { 462 | if (isset($this->_paymentParams[self::FIELD_USER_ID])) { 463 | return $this->_paymentParams[self::FIELD_USER_ID]; 464 | } 465 | 466 | return FALSE; 467 | } 468 | 469 | /** 470 | * 游戏用户id 471 | * 472 | * @return boolean 473 | */ 474 | public function getPaymentGameUserId() { 475 | if (isset($this->_paymentParams[self::FIELD_GAME_USER_ID])) { 476 | return $this->_paymentParams[self::FIELD_GAME_USER_ID]; 477 | } 478 | 479 | return FALSE; 480 | } 481 | 482 | /** 483 | * 服务器id 484 | * 485 | * @return boolean 486 | */ 487 | public function getPaymentServerId() { 488 | if (isset($this->_paymentParams[self::FIELD_SERVER_ID])) { 489 | return $this->_paymentParams[self::FIELD_SERVER_ID]; 490 | } 491 | 492 | return FALSE; 493 | } 494 | 495 | /** 496 | * 商品名 497 | * 498 | * @return boolean 499 | */ 500 | public function getPaymentProductName() { 501 | if (isset($this->_paymentParams[self::FIELD_PRODUCT_NAME])) { 502 | return $this->_paymentParams[self::FIELD_PRODUCT_NAME]; 503 | } 504 | 505 | return FALSE; 506 | } 507 | 508 | /** 509 | * 渠道订单号 510 | * 511 | * @return boolean 512 | */ 513 | public function getPaymentChannelOrderId() { 514 | if (isset($this->_paymentParams[self::FIELD_CHANNEL_ORDER_ID])) { 515 | return $this->_paymentParams[self::FIELD_CHANNEL_ORDER_ID]; 516 | } 517 | 518 | return FALSE; 519 | } 520 | 521 | /** 522 | * 渠道商品id 523 | * 524 | * @return boolean 525 | */ 526 | public function getPaymentChannelProductId() { 527 | if (isset($this->_paymentParams[self::FIELD_CHANNEL_PRODUCT_ID])) { 528 | return $this->_paymentParams[self::FIELD_CHANNEL_PRODUCT_ID]; 529 | } 530 | 531 | return FALSE; 532 | } 533 | 534 | /** 535 | * 设置AnySDK提供的private_key 536 | * 537 | * @param type $privateKey 538 | */ 539 | public function setPrivateKey($privateKey) { 540 | $this->_privateKey = $privateKey; 541 | $this->_appendDebugInfo(__METHOD__ . ': init _privateKey = ' . $this->_privateKey); 542 | } 543 | 544 | /** 545 | * 设置AnySDK提供的enhanced_key 546 | * 547 | * @param type $enhancedKey 548 | */ 549 | public function setEnhancedKey($enhancedKey) { 550 | $this->_enhancedKey = $enhancedKey; 551 | $this->_appendDebugInfo(__METHOD__ . ': init _enhancedKey = ' . $this->_enhancedKey); 552 | } 553 | 554 | /** 555 | * 自定义 curl CURLOPT_CONNECTTIMEOUT 556 | * 557 | * @param type $httpConnectTimeout 558 | */ 559 | public function setHttpConnectTimeout($httpConnectTimeout = self::TIMEOUT_SECONDS_DEFAULT) { 560 | $this->_httpConnectTimeout = $httpConnectTimeout; 561 | $this->_appendDebugInfo(__METHOD__ . ': init _httpConnectTimeout = ' . $this->_httpConnectTimeout); 562 | } 563 | 564 | /** 565 | * 自定义 curl CURLOPT_TIMEOUT 566 | * 567 | * @param type $httpTimeout 568 | */ 569 | public function setHttpTimeout($httpTimeout = self::TIMEOUT_SECONDS_DEFAULT) { 570 | $this->_httpTimeout = $httpTimeout; 571 | $this->_appendDebugInfo(__METHOD__ . ': init _httpTimeout = ' . $this->_httpTimeout); 572 | } 573 | 574 | /** 575 | * 设置验签模式,1为检查sign和enhanced_sign, 2为仅检查enhanced_sign,2为默认 576 | * 577 | * @param type $paymentSignCheckMode 578 | */ 579 | public function setPaymentSignCheckMode($paymentSignCheckMode = self::PAYMENT_SIGN_CHECK_MODE_BOTH) { 580 | $this->_paymentSignCheckMode = $paymentSignCheckMode; 581 | $this->_appendDebugInfo(__METHOD__ . ': init _paymentSignCheckMode = ' . $this->_paymentSignCheckMode); 582 | } 583 | 584 | /** 585 | * 设置登录验证地址 586 | * 587 | * @param type $loginCheckUrl 588 | */ 589 | public function setLoginCheckUrl($loginCheckUrl = self::LOGIN_CHECK_URL) { 590 | $this->_loginCheckUrl = $loginCheckUrl; 591 | $this->_appendDebugInfo(__METHOD__ . ': init _loginCheckUrl = ' . $this->_loginCheckUrl); 592 | } 593 | 594 | /** 595 | * 设置广告效果追踪数据报送地址 596 | */ 597 | public function setAdTrackingReportUrl ($adTrackingReportUrl = self::ADTRACKING_REPORT_URL) { 598 | $this->_adTrackingReportUrl = $adTrackingReportUrl; 599 | $this->_appendDebugInfo(__METHOD__ . ': init _adTrackingReportUrl = ' . $this->_adTrackingReportUrl); 600 | } 601 | 602 | /** 603 | * 登录转发的时候注入private_key参数 604 | */ 605 | public function usePrivateKeyForLoginForward() { 606 | $this->_usePrivateKeyForLoginForward = TRUE; 607 | $this->_appendDebugInfo(__METHOD__ . ': init _usePrivateKeyForLoginForward = ' . (int) $this->_usePrivateKeyForLoginForward); 608 | } 609 | 610 | /** 611 | * 最后一条错误信息 612 | */ 613 | public function getLastError() { 614 | return $this->_lastError; 615 | } 616 | 617 | /** 618 | * 将一个ip地址添加到白名单列表 619 | * 620 | * @param type $ip 621 | */ 622 | public function pushIpToWhiteList($ip) { 623 | $this->_ipWhiteList[] = $ip; 624 | } 625 | 626 | /** 627 | * 清空ip白名单 628 | * 如果你不想使用SDK已经内置的白名单ip,您可以将其清空 629 | */ 630 | public function clearIpWhiteList() { 631 | $this->_ipWhiteList = array(); 632 | } 633 | 634 | /** 635 | * 检查ip白名单 636 | * 637 | * @param type $ip 638 | * @return boolean 639 | */ 640 | public function checkIpWhiteList($ip = '') { 641 | if (empty($ip)) { 642 | $ip = $_SERVER['REMOTE_ADDR']; 643 | } 644 | 645 | if (!in_array($ip, $this->_ipWhiteList)) { 646 | return FALSE; 647 | } 648 | 649 | return TRUE; 650 | } 651 | 652 | /** 653 | * 执行登录验证请求转发 654 | * 655 | * @param array $params 客户端请求参数,如果不传递此参数,此方法将自动使用$_REQUEST 656 | * @return boolean|string 657 | */ 658 | public function loginForward(Array $params = array()) { 659 | if (empty($params)) { 660 | $params = $_REQUEST; 661 | } 662 | 663 | if (!$this->_parametersIsset($params)) { 664 | $this->_lastError = __METHOD__ . ': missing parameters(channel, uapi_key, uapi_secret)'; 665 | $this->_appendDebugInfo(__METHOD__ . ': check _parametersIsset failed'); 666 | return FALSE; 667 | } 668 | 669 | if ($this->_usePrivateKeyForLoginForward) { 670 | $params[self::FIELD_PRIVATE_KEY] = $this->_privateKey; 671 | } 672 | 673 | $http_response = $this->_httpRequest($this->_loginCheckUrl, $params); 674 | 675 | if (empty($http_response)) { 676 | return FALSE; 677 | } 678 | 679 | $res_arr = json_decode($http_response, TRUE); 680 | 681 | if (empty($res_arr)) { 682 | $msg = __METHOD__ . ': anysdk server response non-json data'; 683 | $this->_lastError = $msg; 684 | $this->_appendDebugInfo($msg); 685 | return FALSE; 686 | } 687 | 688 | /** 689 | * 设置验证结果状态,保存验证结果数组 690 | */ 691 | if (isset($res_arr[self::FIELD_STATUS]) && $res_arr[self::FIELD_STATUS] === self::LOGIN_STATUS_OK) { 692 | $this->_loginStatus = TRUE; 693 | $this->_loginResponse = $res_arr; 694 | } 695 | 696 | return $http_response; 697 | } 698 | 699 | /** 700 | * 广告效果追踪数据报送结果 701 | * @return boolean 702 | */ 703 | public function getAdTrackingReportStatus () { 704 | return $this->_adTrackingReportStatus; 705 | } 706 | 707 | /** 708 | * 执行广告效果追踪数据报送 709 | * @param array $data 710 | * @param type $method 711 | * @return Mixed String/Boolean 712 | */ 713 | public function adTrackingReport (Array $data = array(), $method = '') { 714 | if (empty($method)) { 715 | $msg = __METHOD__ . ': need paramter $method for report'; 716 | $this->_lastError = $msg; 717 | $this->_appendDebugInfo($msg); 718 | 719 | return FALSE; 720 | } 721 | 722 | $data_encrypt = urlencode(base64_encode(json_encode($data))); 723 | $token = $this->getAdTrackingToken($data, ANYSDK_PRIVATE_KEY); 724 | 725 | $postFields = array( 726 | self::FIELD_DATA => $data_encrypt, 727 | self::FIELD_TOKEN => $token, 728 | self::FIELD_METHOD => $method 729 | ); 730 | 731 | $http_response = $this->_httpRequest($this->_adTrackingReportUrl, $postFields); 732 | 733 | if (empty($http_response)) { 734 | $msg = __METHOD__ . ': remote server response empty. url: ' . $this->_adTrackingReportUrl; 735 | $this->_lastError = $msg; 736 | $this->_appendDebugInfo($msg); 737 | 738 | return FALSE; 739 | } 740 | 741 | $res_arr = json_decode($http_response, TRUE); 742 | 743 | if (empty($res_arr)) { 744 | $msg = __METHOD__ . ': remote server response non-json data'; 745 | $this->_lastError = $msg; 746 | $this->_appendDebugInfo($msg); 747 | return FALSE; 748 | } 749 | 750 | /** 751 | * 设置验证结果状态,保存验证结果数组 752 | */ 753 | if (isset($res_arr[self::FIELD_STATUS]) && $res_arr[self::FIELD_STATUS] === self::ADTRACKING_REPORT_STATUS_OK) { 754 | $this->_adTrackingReportStatus = TRUE; 755 | $this->_adTrackingReportResponse = $res_arr; 756 | } 757 | 758 | return $http_response; 759 | } 760 | 761 | /** 762 | * 计算AdTracking签名 763 | * 764 | * @param type $data 765 | * @return string 签名 766 | */ 767 | protected function getAdTrackingToken ($data, $key) { 768 | //数组按key升序排序 769 | ksort($data); 770 | //将数组中的值不加任何分隔符合并成字符串 771 | $string = implode('', $data); 772 | //做一次md5并转换成小写,末尾追加游戏的privateKey,最后再次做md5并转换成小写 773 | return strtolower(md5(strtolower(md5($string)) . $key)); 774 | } 775 | 776 | /** 777 | * 验证支付通知签名 778 | * 779 | * @param array $params 780 | * @return Boolean 781 | */ 782 | public function checkPaymentSign(Array $params = array()) { 783 | if (empty($params)) { 784 | $params = $_REQUEST; 785 | } 786 | 787 | if ($this->_paymentSignCheckMode === self::PAYMENT_SIGN_CHECK_MODE_ENHANCED) { 788 | $checkResult = $this->_checkEnhancedSign($params); 789 | } elseif ($this->_paymentSignCheckMode === self::PAYMENT_SIGN_CHECK_MODE_BOTH) { 790 | $checkResult = $this->_checkSign($params) && $this->_checkEnhancedSign($params); 791 | } 792 | 793 | if ($checkResult) { 794 | $this->_paymentParams = $params; 795 | return TRUE; 796 | } 797 | 798 | return FALSE; 799 | } 800 | 801 | /** 802 | * http请求客户端 803 | * 804 | * @param type $url 805 | * @param type $params 806 | * @param type $method 807 | * @return boolean|string 808 | */ 809 | private function _httpRequest($url, $params, $method = self::HTTP_METHOD_POST) { 810 | $ch = curl_init(); 811 | curl_setopt($ch, CURLOPT_URL, $url); 812 | $this->_appendDebugInfo(__METHOD__ . ': curl url(' . $url . ')'); 813 | 814 | curl_setopt($ch, CURLOPT_USERAGENT, 'AnySDK.Sdk.class.php.v2.1.0'); 815 | curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->_httpConnectTimeout); 816 | curl_setopt($ch, CURLOPT_TIMEOUT, $this->_httpTimeout); 817 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); 818 | curl_setopt($ch, CURLOPT_HTTPHEADER, array("Except:")); 819 | 820 | if (strtoupper($method) === self::HTTP_METHOD_POST) { 821 | curl_setopt($ch, CURLOPT_POST, TRUE); 822 | if (!is_scalar($params)) { 823 | $params = http_build_query($params); 824 | } 825 | $this->_appendDebugInfo(__METHOD__ . ': curl post fields(' . $params . ')'); 826 | if (!empty($params)) { 827 | curl_setopt($ch, CURLOPT_POSTFIELDS, $params); 828 | } 829 | } 830 | 831 | $result = curl_exec($ch); 832 | if (empty($result)) { 833 | $this->_lastError = __METHOD__ . ': ' . curl_error($ch); 834 | curl_close($ch); 835 | return FALSE; 836 | } 837 | 838 | curl_close($ch); 839 | return $result; 840 | } 841 | 842 | /** 843 | * 检查必要的参数是否存在,包括channel, uapi_key, uapi_secret, private_key 844 | * 845 | * @param array $params 846 | * @return boolean 847 | */ 848 | private function _parametersIsset(Array $params) { 849 | $paramsCheck = isset($params[self::FIELD_CHANNEL]) && isset($params[self::FIELD_UAPI_KEY]) && isset($params[self::FIELD_UAPI_SECRET]); 850 | if (!$paramsCheck) { 851 | $this->_appendDebugInfo(__METHOD__ . ': check _parametersIsset failed'); 852 | return FALSE; 853 | } 854 | 855 | return TRUE; 856 | } 857 | 858 | /** 859 | * 计算并验证普通签名 860 | * 861 | * @param array $params 862 | * @return boolean 863 | */ 864 | private function _checkSign(Array $params) { 865 | if (empty($params) || !isset($params[self::FIELD_SIGN])) { 866 | $this->_appendDebugInfo(__METHOD__ . ': check params failed'); 867 | return FALSE; 868 | } 869 | 870 | $sign = $params[self::FIELD_SIGN]; 871 | // sign 字段不参与签名 872 | unset($params[self::FIELD_SIGN]); 873 | $_sign = $this->_getSign($params, $this->_privateKey); 874 | if ($sign != $_sign) { 875 | $this->_appendDebugInfo(__METHOD__ . ': check sign failed with sign(' . $_sign . '|' . $sign . '), private_key(' . $this->_privateKey . ')'); 876 | return FALSE; 877 | } 878 | 879 | return TRUE; 880 | } 881 | 882 | private function _checkEnhancedSign(Array $params) { 883 | if (empty($params) || !isset($params[self::FIELD_ENHANCED_SIGN])) { 884 | $this->_appendDebugInfo(__METHOD__ . ': check params failed'); 885 | return FALSE; 886 | } 887 | 888 | $enhancedSign = $params[self::FIELD_ENHANCED_SIGN]; 889 | // sign 和 enhanced_sign 不参与签名 890 | unset($params[self::FIELD_SIGN], $params[self::FIELD_ENHANCED_SIGN]); 891 | $_enhancedSign = $this->_getSign($params, $this->_enhancedKey); 892 | if ($enhancedSign != $_enhancedSign) { 893 | $this->_appendDebugInfo(__METHOD__ . ': check enhanced_sign failed with sign(' . $_enhancedSign . '|' . $enhancedSign . '), enhanced_key(' . $this->_enhancedKey . ')'); 894 | return FALSE; 895 | } 896 | 897 | return TRUE; 898 | } 899 | 900 | /** 901 | * 计算签名 902 | * 903 | * @param array $params 904 | * @param type $key 905 | * @return type 906 | */ 907 | private function _getSign(Array $params, $key) { 908 | // 数组按key排序 909 | ksort($params); 910 | // 将数组中的值不加任何分割字符拼接成字符串 911 | $string = implode('', $params); 912 | $this->_appendDebugInfo(__METHOD__ . ': sign string(' . $string . ')'); 913 | // 做一次md5并转换成小写,末尾追加key再做一次md5并转换成小写 914 | $md5_first = strtolower(md5($string)); 915 | $sign = strtolower(md5($md5_first . $key)); 916 | return $sign; 917 | } 918 | 919 | /** 920 | * 追加调试信息 921 | * 922 | * @param type $msg 923 | */ 924 | private function _appendDebugInfo($msg) { 925 | if ($this->_debugMode) { 926 | $this->_debugInfo[] = $msg; 927 | } 928 | } 929 | 930 | } 931 | -------------------------------------------------------------------------------- /php/AnySDK.config.php: -------------------------------------------------------------------------------- 1 | 6 | * @date 2016-01-11 7 | * @version 2.0.0 8 | * 9 | * @author 李播 10 | * @date 2016-04-14 11 | * @version 2.1.0 12 | * 13 | * @link http://docs.anysdk.com/OauthLogin 统一登录验证 14 | * @link http://docs.anysdk.com/PaymentNotice 订单支付通知 15 | * @link http://docs.anysdk.com/AdTracking 广告效果追踪 16 | */ 17 | defined('LOGIN_CHECK_URL') or define('LOGIN_CHECK_URL', 'http://oauth.anysdk.com/api/User/LoginOauth/'); 18 | defined('ADTRACKING_REPORT_URL') or define('ADTRACKING_REPORT_URL', 'http://pay.anysdk.com/v5/AdTracking/Submit/'); 19 | defined('DEBUG_MODE') or define('DEBUG_MODE', FALSE); 20 | 21 | // 游戏ID 前往dev.anysdk.com => 游戏列表 获取 22 | defined('ANYSDK_GAME_ID') or define('ANYSDK_GAME_ID', 0); 23 | // 增强密钥 前往dev.anysdk.com => 游戏列表 获取,此参数请严格保密 24 | defined('ANYSDK_ENHANCED_KEY') or define('ANYSDK_ENHANCED_KEY', ''); 25 | // private_key 前往dev.anysdk.com => 游戏列表 获取 26 | defined('ANYSDK_PRIVATE_KEY') or define('ANYSDK_PRIVATE_KEY', ''); 27 | -------------------------------------------------------------------------------- /php/READMD.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## 2.1.0 4 | 5 | 2016年04月14日 SDK增加广告追踪功能,并增加demo代码 6 | 7 | ## 2.0.0 8 | 9 | 2016年01月11日 将服务端PHP Sample重构为AnySDK服务端SDK for PHP -------------------------------------------------------------------------------- /php/demo/adtracking.php: -------------------------------------------------------------------------------- 1 | setAdTrackingReportUrl(ADTRACKING_REPORT_URL); 17 | 18 | $timestamp = time(); 19 | $order_id = ''; 20 | $channel_id = ''; 21 | 22 | $data_to_report = array( 23 | 'game_id' => ANYSDK_GAME_ID, // AnySDK游戏ID,必填 24 | 'channel_number' => $channel_id, // AnySDK渠道号,必填 25 | 'amount' => '', // 单位为元,必填 26 | 'order_id' => $order_id, // AnySDK订单号,必填 27 | 'imei' => '', // 移动设备国际身份码 28 | 'imsi' => '', // 国际移动用户识别码 29 | 'idfv' => '', // 厂商标识符 30 | 'idfa' => '', // 广告标识符 31 | 'payment_type' => '支付宝', // 支付方式 32 | 'currency' => 'CNY', // 货币类型,使用ISO 4217中规范的3位字母代码标记货币类型 33 | 'user_account' => '', // 用户账号 34 | 'mac' => '', // 设备mac地址 35 | 'timestamp' => $timestamp, // 时间戳 36 | 'ip' => '', // IPv4地址 37 | 'os_version' => '', // 操作系统版本 38 | 'msg_id' => md5(ANYSDK_GAME_ID . $channel_id . $order_id . $timestamp), // 该条数据的 ID,由开发者自行定义; 39 | 'operators' => '', // 运营商 40 | 'network' => '', // 网络类型 41 | 'device_name' => '', // 设备名称,例如:"XXX 的 iPhone" 42 | 'gpid' => '', // GooglePlay ID 43 | 'manufacturer' => '', // 制造商 44 | 'device_model' => '', // 设备类型 45 | 'android_id' => '', // Android ID 46 | ); 47 | 48 | /** 49 | * 第二个参数是广告追踪提交数据类型,目前只支持payment 50 | */ 51 | $response = $anysdk->adTrackingReport($data_to_report, Sdk_AnySDK::ADTRACKING_METHOD_PAYMENT); 52 | 53 | if ($anysdk->getAdTrackingReportStatus()) { 54 | echo "success\n"; 55 | } else { 56 | echo "fail\n"; 57 | } 58 | -------------------------------------------------------------------------------- /php/demo/login.php: -------------------------------------------------------------------------------- 1 | setLoginCheckUrl(LOGIN_CHECK_URL); 15 | */ 16 | 17 | /** 18 | * 如果接入的是AnySDK for H5,则需要在此处将private_key传给AnySDK服务器 19 | * 20 | $anysdk->setPrivateKey(ANYSDK_PRIVATE_KEY); 21 | $anysdk->usePrivateKeyForLoginForward(); 22 | */ 23 | 24 | $response = $anysdk->loginForward($login_params); 25 | 26 | // 登录验证成功 27 | if ($anysdk->getLoginStatus()) { 28 | 29 | // 获取登录结果的一些字段 30 | $channel = $anysdk->getLoginChannel(); 31 | $uid = $anysdk->getLoginUid(); 32 | $user_sdk = $anysdk->getLoginUserSdk(); 33 | $plugin_id = $anysdk->getLoginPluginId(); 34 | $server_id = $anysdk->getLoginServerId(); 35 | $data = $anysdk->getLoginData(); // 获取登录验证渠道返回的原始内容 36 | // 获取登录结果字段值示例结束 37 | 38 | } 39 | 40 | /** 41 | * 可在此处往ext字段加入一些内容以便传递给客户端 42 | * 43 | $resp_arr = json_decode($response, TRUE); 44 | $resp_arr['ext'] = ''; 45 | $response = json_encode($resp_arr); 46 | */ 47 | 48 | echo is_scalar($response)? $response: json_encode($response); 49 | -------------------------------------------------------------------------------- /php/demo/payNotice.php: -------------------------------------------------------------------------------- 1 | setDebugMode(Sdk_AnySDK::DEBUG_MODE_ON); 20 | 21 | /** 22 | * ip白名单检查 23 | * 24 | $anysdk->pushIpToWhiteList('127.0.0.1'); 25 | $anysdk->checkIpWhiteList() or die(Sdk_AnySDK::PAYMENT_RESPONSE_FAIL . 'ip'); 26 | */ 27 | 28 | /** 29 | * SDK默认只检查增强签名,如果要检查普通签名和增强签名,则需要此设置 30 | * 31 | */ 32 | $anysdk->setPaymentSignCheckMode(Sdk_AnySDK::PAYMENT_SIGN_CHECK_MODE_BOTH); 33 | $check_sign = $anysdk->checkPaymentSign($payment_params); 34 | if (!$check_sign) { 35 | echo $anysdk->getDebugInfo(), "\n=====我是分割线=====\n"; 36 | die(Sdk_AnySDK::PAYMENT_RESPONSE_FAIL . 'sign_error'); 37 | } 38 | 39 | /** 40 | * 检查订单状态,1为成功 41 | */ 42 | if (intval($anysdk->getPaymentStatus()) !== Sdk_AnySDK::PAYMENT_STATUS_SUCCESS) { 43 | die(Sdk_AnySDK::PAYMENT_RESPONSE_OK); 44 | } 45 | 46 | /** 47 | * 获取支付通知详细参数 48 | * 49 | $amount = $anysdk->getPaymentAmount(); 50 | $product_id = $anysdk->getPaymentProductId(); 51 | $product_name = $anysdk->getPaymentProductName(); 52 | $product_count = $anysdk->getPaymentProductCount(); 53 | $channel_product_id = $anysdk->getPaymentChannelProductId(); 54 | $user_id = $anysdk->getPaymentUserId(); 55 | $game_user_id = $anysdk->getPaymentGameUserId(); 56 | $order_id = $anysdk->getPaymentOrderId(); 57 | $channel_order_id = $anysdk->getPaymentChannelOrderId(); 58 | $private_data = $anysdk->getPaymentPrivateData(); 59 | */ 60 | 61 | echo $anysdk->getDebugInfo(), "\n=====我是分割线=====\n"; 62 | echo Sdk_AnySDK::PAYMENT_RESPONSE_OK; 63 | --------------------------------------------------------------------------------