using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using Aop.Api.Parser;
using Aop.Api.Request;
using Aop.Api.Util;
namespace Aop.Api
{
///
/// AOP客户端。
///
public class DefaultAopClient : IAopClient
{
public const string APP_ID = "app_id";
public const string FORMAT = "format";
public const string METHOD = "method";
public const string TIMESTAMP = "timestamp";
public const string VERSION = "version";
public const string SIGN_TYPE = "sign_type";
public const string ACCESS_TOKEN = "auth_token";
public const string SIGN = "sign";
public const string TERMINAL_TYPE = "terminal_type";
public const string TERMINAL_INFO = "terminal_info";
public const string PROD_CODE = "prod_code";
public const string NOTIFY_URL = "notify_url";
public const string CHARSET = "charset";
private string version;
private string format;
private string serverUrl;
private string appId;
private string privateKeyPem;
private string signType = "RSA";
private string charset;
private string alipayPublicKey;
private WebUtils webUtils;
//public string PrivateKeyPem
//{
// get { return privateKeyPem; }
// set { privateKeyPem = value; }
//}
//public string AlipayPublicKey
//{
// get { return alipayPublicKey; }
// set { alipayPublicKey = value; }
//}
public string Version
{
get { return version != null ? version : "1.0"; }
set { version = value; }
}
public string Format
{
get { return format != null ? format : "json"; }
set { format = value; }
}
public string AppId
{
get { return appId; }
set { appId = value; }
}
#region DefaultAopClient Constructors
public DefaultAopClient(string serverUrl, string appId, string privateKeyPem)
{
this.appId = appId;
this.privateKeyPem = privateKeyPem;
this.serverUrl = serverUrl;
this.webUtils = new WebUtils();
}
public DefaultAopClient(string serverUrl, string appId, string privateKeyPem, string format)
{
this.appId = appId;
this.privateKeyPem = privateKeyPem;
this.serverUrl = serverUrl;
this.format = format;
this.webUtils = new WebUtils();
}
public DefaultAopClient(string serverUrl, string appId, string privateKeyPem, string format, string charset)
: this(serverUrl, appId, privateKeyPem, format)
{
this.charset = charset;
}
public DefaultAopClient(string serverUrl, string appId, string privateKeyPem, string format, string version, string signType)
: this(serverUrl, appId, privateKeyPem)
{
this.format = format;
this.version = version;
this.signType = signType;
}
public DefaultAopClient(string serverUrl, string appId, string privateKeyPem, string format, string version, string signType, string alipayPulicKey)
: this(serverUrl, appId, privateKeyPem, format, version, signType)
{
this.alipayPublicKey = alipayPulicKey;
}
public DefaultAopClient(string serverUrl, string appId, string privateKeyPem, string format, string version, string signType, string alipayPulicKey, string charset)
: this(serverUrl, appId, privateKeyPem, format, version, signType, alipayPulicKey)
{
this.charset = charset;
}
public void SetTimeout(int timeout)
{
webUtils.Timeout = timeout;
}
#endregion
#region IAopClient Members
public async Task Execute(IAopRequest request) where T : AopResponse
{
return await Execute(request, null);
}
public async Task Execute(IAopRequest request, string accessToken) where T : AopResponse
{
if (string.IsNullOrEmpty(this.charset))
{
this.charset = "utf-8";
}
string apiVersion = null;
if (!string.IsNullOrEmpty(request.GetApiVersion()))
{
apiVersion = request.GetApiVersion();
}
else
{
apiVersion = Version;
}
// 添加协议级请求参数
AopDictionary txtParams = new AopDictionary(request.GetParameters());
txtParams.Add(METHOD, request.GetApiName());
txtParams.Add(VERSION, apiVersion);
txtParams.Add(APP_ID, appId);
txtParams.Add(FORMAT, format);
txtParams.Add(TIMESTAMP, DateTime.Now);
txtParams.Add(ACCESS_TOKEN, accessToken);
txtParams.Add(SIGN_TYPE, signType);
txtParams.Add(TERMINAL_TYPE, request.GetTerminalType());
txtParams.Add(TERMINAL_INFO, request.GetTerminalInfo());
txtParams.Add(PROD_CODE, request.GetProdCode());
txtParams.Add(NOTIFY_URL, request.GetNotifyUrl());
txtParams.Add(CHARSET, charset);
// 添加签名参数
txtParams.Add(SIGN, AopUtils.SignAopRequest(txtParams, privateKeyPem, charset));
// 是否需要上传文件
string body;
if (request is IAopUploadRequest)
{
IAopUploadRequest uRequest = (IAopUploadRequest)request;
IDictionary fileParams = AopUtils.CleanupDictionary(uRequest.GetFileParameters());
body = await webUtils.DoPost(this.serverUrl + "?" + CHARSET + "=" + this.charset, txtParams, fileParams, this.charset);
}
else
{
body = await webUtils.DoPost(this.serverUrl + "?" + CHARSET + "=" + this.charset, txtParams, this.charset);
}
T rsp = null;
IAopParser parser = null;
if ("xml".Equals(format))
{
parser = new AopXmlParser();
rsp = parser.Parse(body, charset);
}
else
{
parser = new AopJsonParser();
rsp = parser.Parse(body, charset);
}
CheckResponseSign(request, rsp, parser, alipayPublicKey, this.charset);
return rsp;
}
public static void CheckResponseSign(IAopRequest request, T tRsp, IAopParser parser, string alipayPublicKey, string charset) where T : AopResponse
{
if (string.IsNullOrEmpty(alipayPublicKey) || string.IsNullOrEmpty(charset))
{
return;
}
SignItem signItem = parser.GetSignItem(request, tRsp);
if (signItem == null)
{
throw new AopException("sign check fail: Body is Empty!");
}
if (!tRsp.IsError ||
(tRsp.IsError && !string.IsNullOrEmpty(signItem.Sign)))
{
bool rsaCheckContent = AlipaySignature.RSACheckContent(signItem.SignSourceDate, signItem.Sign, alipayPublicKey, charset);
if (!rsaCheckContent)
{
if (!string.IsNullOrEmpty(signItem.SignSourceDate) && signItem.SignSourceDate.Contains("\\/"))
{
string srouceData = signItem.SignSourceDate.Replace("\\/", "/");
bool jsonCheck = AlipaySignature.RSACheckContent(srouceData, signItem.Sign, alipayPublicKey, charset);
if (!jsonCheck)
{
throw new AopException(
"sign check fail: check Sign and Data Fail JSON also");
}
}
else
{
throw new AopException(
"sign check fail: check Sign and Data Fail!");
}
}
}
}
#endregion
}
}