Browse Source

svn move to git

master
robin 8 years ago
commit
2745f06caa
81 changed files with 4451 additions and 0 deletions
  1. +26
    -0
      BWP.ABCClient.sln
  2. +90
    -0
      BWP.ABCClient/B2B/FundTransferRequest.cs
  3. +32
    -0
      BWP.ABCClient/B2B/FundTransferResponse.cs
  4. +43
    -0
      BWP.ABCClient/B2B/QueryTrnxRequest.cs
  5. +34
    -0
      BWP.ABCClient/B2B/QueryTrnxResponse.cs
  6. +13
    -0
      BWP.ABCClient/B2B/TrxStatus.cs
  7. +17
    -0
      BWP.ABCClient/B2B/TrxType.cs
  8. +232
    -0
      BWP.ABCClient/B2C/OnlineRemits/OnlineRemitBaseRequest.cs
  9. +72
    -0
      BWP.ABCClient/B2C/OnlineRemits/OnlineRemitConfig.cs
  10. +25
    -0
      BWP.ABCClient/B2C/OnlineRemits/OnlineRemitException.cs
  11. +63
    -0
      BWP.ABCClient/B2C/OnlineRemits/OnlineRemitQueryResultRequest.cs
  12. +18
    -0
      BWP.ABCClient/B2C/OnlineRemits/OnlineRemitQueryResultResponse.cs
  13. +169
    -0
      BWP.ABCClient/B2C/OnlineRemits/OnlineRemitRequest.cs
  14. +38
    -0
      BWP.ABCClient/B2C/OnlineRemits/OnlineRemitRequest_Detail.cs
  15. +74
    -0
      BWP.ABCClient/B2C/OnlineRemits/OnlineRemitResponse.cs
  16. +18
    -0
      BWP.ABCClient/B2C/OrderContent.cs
  17. +64
    -0
      BWP.ABCClient/B2C/PaymentRequest.cs
  18. +32
    -0
      BWP.ABCClient/B2C/PaymentResponse.cs
  19. +43
    -0
      BWP.ABCClient/B2C/QueryOrderRequest.cs
  20. +26
    -0
      BWP.ABCClient/B2C/QueryOrderResponse.cs
  21. +50
    -0
      BWP.ABCClient/B2C/SettleRequest.cs
  22. +71
    -0
      BWP.ABCClient/B2C/SettleResponse.cs
  23. +16
    -0
      BWP.ABCClient/B2C/TrxType.cs
  24. +151
    -0
      BWP.ABCClient/BWP.ABCClient.csproj
  25. +58
    -0
      BWP.ABCClient/Businesses/B2BDealQuery.cs
  26. +62
    -0
      BWP.ABCClient/Businesses/B2BReceivingPayment.cs
  27. +53
    -0
      BWP.ABCClient/Businesses/B2COrderQuery.cs
  28. +56
    -0
      BWP.ABCClient/Businesses/B2CReceivingPayment.cs
  29. +50
    -0
      BWP.ABCClient/Businesses/B2CSettleByDate.cs
  30. +111
    -0
      BWP.ABCClient/Businesses/BusinessBase.cs
  31. +15
    -0
      BWP.ABCClient/Businesses/IReturnedResult.cs
  32. +65
    -0
      BWP.ABCClient/Businesses/MarketOrderApply.cs
  33. +49
    -0
      BWP.ABCClient/Businesses/MarketOrderPay.cs
  34. +54
    -0
      BWP.ABCClient/Businesses/MarketReceivingPayment.cs
  35. +51
    -0
      BWP.ABCClient/Businesses/MarketSignOff.cs
  36. +56
    -0
      BWP.ABCClient/Businesses/MarketSignUp.cs
  37. +46
    -0
      BWP.ABCClient/Businesses/ResultB2BReturned.cs
  38. +46
    -0
      BWP.ABCClient/Businesses/ResultB2CReturned.cs
  39. +43
    -0
      BWP.ABCClient/Businesses/Type/B2B.cs
  40. +43
    -0
      BWP.ABCClient/Businesses/Type/B2C.cs
  41. +24
    -0
      BWP.ABCClient/Businesses/Type/BusinessTypes.cs
  42. +15
    -0
      BWP.ABCClient/Businesses/Type/IBusinessType.cs
  43. +43
    -0
      BWP.ABCClient/Businesses/Type/Market.cs
  44. +118
    -0
      BWP.ABCClient/Businesses/XMLDocument.cs
  45. +165
    -0
      BWP.ABCClient/CertManager.cs
  46. +8
    -0
      BWP.ABCClient/Common/MerchantContent.cs
  47. +18
    -0
      BWP.ABCClient/Common/MessageBase.cs
  48. +27
    -0
      BWP.ABCClient/Common/PaymentURLResponse.cs
  49. +11
    -0
      BWP.ABCClient/Exceptions/CertException.cs
  50. +12
    -0
      BWP.ABCClient/Exceptions/HttpException.cs
  51. +20
    -0
      BWP.ABCClient/Exceptions/ResponseException.cs
  52. +61
    -0
      BWP.ABCClient/Log/AbcLog.cs
  53. +49
    -0
      BWP.ABCClient/Market/MarketResponse.cs
  54. +72
    -0
      BWP.ABCClient/Market/OrderApplyRequest.cs
  55. +44
    -0
      BWP.ABCClient/Market/OrderApplyResponse.cs
  56. +61
    -0
      BWP.ABCClient/Market/OrderPayRequest.cs
  57. +41
    -0
      BWP.ABCClient/Market/OrderPayResponse.cs
  58. +68
    -0
      BWP.ABCClient/Market/PayRequest.cs
  59. +69
    -0
      BWP.ABCClient/Market/SignOffRequest.cs
  60. +69
    -0
      BWP.ABCClient/Market/SignUpRequest.cs
  61. +108
    -0
      BWP.ABCClient/MsgUtil.cs
  62. +35
    -0
      BWP.ABCClient/Properties/AssemblyInfo.cs
  63. +74
    -0
      BWP.ABCClient/RSAService.cs
  64. +50
    -0
      BWP.ABCClient/Request.cs
  65. +57
    -0
      test/B2BReceivingPaymentTest.cs
  66. +97
    -0
      test/BusinessTest.cs
  67. +93
    -0
      test/CertManagerTest.cs
  68. BIN
      test/Certs/PDM.pfx
  69. BIN
      test/Certs/TrustPay.cer
  70. BIN
      test/Certs/TrustPayTest.cer
  71. BIN
      test/Certs/asB.pfx
  72. BIN
      test/Certs/asC.pfx
  73. +78
    -0
      test/LogTest.cs
  74. +86
    -0
      test/MockWebServer.cs
  75. +67
    -0
      test/MsgUtilTest.cs
  76. +35
    -0
      test/Properties/AssemblyInfo.cs
  77. +54
    -0
      test/RSAServiceTest.cs
  78. +27
    -0
      test/RequestTest.cs
  79. +57
    -0
      test/ResultReturnedTest.cs
  80. +153
    -0
      test/Test.cs
  81. +110
    -0
      test/test.csproj

+ 26
- 0
BWP.ABCClient.sln View File

@ -0,0 +1,26 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BWP.ABCClient", "BWP.ABCClient\BWP.ABCClient.csproj", "{22FEFA9B-1D58-4E8A-A1FF-49CEED62C355}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "test", "test\test.csproj", "{9299FD15-70F9-4E71-9AB8-DC0C081FB7B5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{22FEFA9B-1D58-4E8A-A1FF-49CEED62C355}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{22FEFA9B-1D58-4E8A-A1FF-49CEED62C355}.Debug|Any CPU.Build.0 = Debug|Any CPU
{22FEFA9B-1D58-4E8A-A1FF-49CEED62C355}.Release|Any CPU.ActiveCfg = Release|Any CPU
{22FEFA9B-1D58-4E8A-A1FF-49CEED62C355}.Release|Any CPU.Build.0 = Release|Any CPU
{9299FD15-70F9-4E71-9AB8-DC0C081FB7B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9299FD15-70F9-4E71-9AB8-DC0C081FB7B5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9299FD15-70F9-4E71-9AB8-DC0C081FB7B5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9299FD15-70F9-4E71-9AB8-DC0C081FB7B5}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

+ 90
- 0
BWP.ABCClient/B2B/FundTransferRequest.cs View File

@ -0,0 +1,90 @@
using System.Xml.Serialization;
using BWP.ABCClient.Common;
namespace BWP.ABCClient.B2B
{
[XmlRoot(ElementName = "MSG")]
public class FundTransferRequest : MessageBase
{
public MessageContent Message { get; set; }
public static FundTransferRequest New()
{
return new FundTransferRequest {
Message = new MessageContent {
Merchant = new MerchantContent {
ECMerchantType = "B2B",
MerchantID = string.Empty
},
TrxRequest = new TrxRequestContent {
TrxType = TrxType.FundTransfer,
MerchantTrnxNo = string.Empty,
TrnxAmount = "0",
TrnxDate = string.Empty,
TrnxTime = string.Empty,
AccountDB = new AccountDBContent {
AccountDBNo = string.Empty,
AccountDBName = string.Empty,
AccountDBBank = string.Empty
},
TrnxInfo = new TrnxInfoContent {
TrnxOpr = string.Empty
},
ResultNotifyURL = string.Empty,
MerchantRemarks = string.Empty
}
},
SignatureAlgorithm = "SHA1withRSA",
Signature = string.Empty
};
}
public class MessageContent
{
public MerchantContent Merchant { get; set; }
public TrxRequestContent TrxRequest { get; set; }
}
public class TrxRequestContent
{
public string TrxType { get; set; }
public string MerchantTrnxNo { get; set; }
public string TrnxAmount { get; set; }
public string TrnxDate { get; set; }
public string TrnxTime { get; set; }
public AccountDBContent AccountDB { get; set; }
public TrnxInfoContent TrnxInfo { get; set; }
public string ResultNotifyURL { get; set; }
public string MerchantRemarks { get; set; }
}
public class TrnxInfoContent
{
public string TrnxOpr { get; set; }
[XmlArrayItem(ElementName = "Remark")]
public TrnxRemark[] TrnxRemarks { get; set; }
public TrnxItem[] TrnxItems { get; set; }
}
public class TrnxRemark
{
public string Key { get; set; }
public string Value { get; set; }
}
public class TrnxItem
{
public string ProductID { get; set; }
public string ProductName { get; set; }
public string UnitPrice { get; set; }
public string Qty { get; set; }
}
public class AccountDBContent
{
public string AccountDBNo { get; set; }
public string AccountDBName { get; set; }
public string AccountDBBank { get; set; }
}
}
}

+ 32
- 0
BWP.ABCClient/B2B/FundTransferResponse.cs View File

@ -0,0 +1,32 @@
using System.Xml.Serialization;
using BWP.ABCClient.Common;
namespace BWP.ABCClient.B2B
{
[XmlRoot(ElementName = "MSG")]
public class FundTransferResponse : MessageBase
{
public MessageContent Message { get; set; }
public class MessageContent
{
public MerchantContent Merchant { get; set; }
public TrxResponseContent TrxResponse { get; set; }
}
public class TrxResponseContent
{
public string ReturnCode { get; set; }
public string ErrorMessage { get; set; }
public string TrnxType { get; set; }
public string TrnxAMT { get; set; }
public string MerchantTrnxNo { get; set; }
public string PaymentURL { get; set; }
}
}
}

+ 43
- 0
BWP.ABCClient/B2B/QueryTrnxRequest.cs View File

@ -0,0 +1,43 @@
using System.Xml.Serialization;
using BWP.ABCClient.Common;
namespace BWP.ABCClient.B2B
{
[XmlRoot(ElementName = "MSG")]
public class QueryTrnxRequest : MessageBase
{
public MessageContent Message { get; set; }
public static QueryTrnxRequest New()
{
return new QueryTrnxRequest {
Message = new MessageContent {
Merchant = new MerchantContent {
ECMerchantType = "B2B",
MerchantID = string.Empty
},
TrxRequest = new TrxRequestContent {
TrxType = TrxType.QueryTrnx,
MerchantTrnxNo = string.Empty,
MerchantRemarks = string.Empty
}
},
SignatureAlgorithm = "SHA1withRSA",
Signature = string.Empty
};
}
public class MessageContent
{
public MerchantContent Merchant { get; set; }
public TrxRequestContent TrxRequest { get; set; }
}
public class TrxRequestContent
{
public string TrxType { get; set; }
public string MerchantTrnxNo { get; set; }
public string MerchantRemarks { get; set; }
}
}
}

+ 34
- 0
BWP.ABCClient/B2B/QueryTrnxResponse.cs View File

@ -0,0 +1,34 @@
using System.Xml.Serialization;
using BWP.ABCClient.Common;
namespace BWP.ABCClient.B2B
{
[XmlRoot(ElementName = "MSG")]
public class QueryTrnxResponse : MessageBase
{
public MessageContent Message { get; set; }
public class MessageContent
{
public MerchantContent Merchant { get; set; }
public TrxResponseContent TrxResponse { get; set; }
}
public class TrxResponseContent
{
public string ReturnCode { get; set; }
public string ErrorMessage { get; set; }
public string TrnxType { get; set; }
public string TrnxAMT { get; set; }
public string MerchantTrnxNo { get; set; }
public string MerchantID { get; set; }
public string TrnxStatus { get; set; }
}
}
}

+ 13
- 0
BWP.ABCClient/B2B/TrxStatus.cs View File

@ -0,0 +1,13 @@
namespace BWP.ABCClient.B2B
{
public static class TrxStatus
{
public const string CANCEL = "5";
public const string CHECK = "1";
public const string FAILURE = "3";
public const string NO_RESPONSE = "9";
public const string ORIGINAL = "0";
public const string REJECT = "4";
public const string SUCCESS = "2";
}
}

+ 17
- 0
BWP.ABCClient/B2B/TrxType.cs View File

@ -0,0 +1,17 @@
namespace BWP.ABCClient.B2B
{
public static class TrxType
{
public static string DownloadTrnx = "DownloadTrnx";
public static string Freeze = "Freeze";
public static string FreezeResult = "FreezeResult";
public static string FreezeTransfer = "FreezeTransfer";
public static string FundTransfer = "FundTransfer";
public static string PartFreezeTransfer = "PartFreezeTransfer";
public static string PartUnFreeze = "PartUnFreeze";
public static string PayFee = "PayFee";
public static string QueryTrnx = "QueryTrnx";
public static string UnFreeze = "UnFreeze";
public static string UnFreezeResult = "UnFreezeResult";
}
}

+ 232
- 0
BWP.ABCClient/B2C/OnlineRemits/OnlineRemitBaseRequest.cs View File

@ -0,0 +1,232 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BWP.ABCClient.Businesses;
using System.Security.Cryptography;
using System.Net;
using System.IO;
using System.Security;
namespace BWP.ABCClient.B2C.OnlineRemits
{
public abstract class OnlineRemitBaseRequest
{
protected abstract void checkRequest();
protected abstract XmlDocument createMessage();
XmlDocument verifySign(XmlDocument aMessage)
{
XmlDocument document = aMessage.GetValue("Message");
if (document == null)
{
throw new OnlineRemitException("1301", "网上支付平台的响应报文不完整", "无[Message]段!");
}
if (aMessage.GetValueNoNull("Signature-Algorithm") == null)
{
throw new OnlineRemitException("1301", "网上支付平台的响应报文不完整", "无[Signature-Algorithm]段!");
}
string data = aMessage.GetValueNoNull("Signature");
if (data == null)
{
throw new OnlineRemitException("1301", "网上支付平台的响应报文不完整", "无[Signature]段!");
}
byte[] rgbSignature = Convert.FromBase64String(data);
try
{
SHA1Managed managed = new SHA1Managed();
byte[] rgbHash = managed.ComputeHash(Encoding.GetEncoding("gb2312").GetBytes(document.ToString()));
RSACryptoServiceProvider provider = new RSACryptoServiceProvider(new CspParameters { Flags = CspProviderFlags.UseMachineKeyStore });
//RSAParameters parameters = TrustpayCertificate.GetPublicKey().ExportParameters();
RSAParameters parameters = new RSAParameters() { Exponent = OnlineRemitConfig.GetCertificate().GetPublicKey() };
provider.ImportParameters(parameters);
bool flag = provider.VerifyHash(rgbHash, CryptoConfig.MapNameToOID("SHA1"), rgbSignature);
managed.Clear();
provider.Clear();
if (!flag)
{
throw new OnlineRemitException("1302", "网上支付平台的响应报文签名验证失败");
}
}
catch (OnlineRemitException exception)
{
throw exception;
}
catch (Exception exception2)
{
throw new OnlineRemitException("1302", "网上支付平台的响应报文签名验证失败 - " + exception2.Message);
}
return document;
}
string ECMerchantType = "B2C";
/// <summary>
/// 商户编号
/// </summary>
public string MerchantID { get; set; }
XmlDocument sendMessage(XmlDocument aMessage)
{
Exception exception;
string s = "<MSG>" + aMessage.ToString() + "</MSG>";
int length = 0;
try
{
length = Encoding.UTF8.GetBytes(s).Length;
}
catch (Exception exception1)
{
exception = exception1;
throw new OnlineRemitException("1999", "系统发生无法预期的错误", exception.Message);
}
HttpWebRequest request = null;
BufferedStream stream = null;
HttpWebResponse response = null;
string aXMLString = "";
XmlDocument document = null;
string str3 = OnlineRemitConfig.TrustPayConnectMethod + "://" + OnlineRemitConfig.TrustPayServerName;
if ((OnlineRemitConfig.TrustPayConnectMethod.Equals("https") && (OnlineRemitConfig.TrustPayServerPort != 0x1bb)) || (OnlineRemitConfig.TrustPayConnectMethod.Equals("http") && (OnlineRemitConfig.TrustPayServerPort != 80)))
{
str3 = str3 + ":" + OnlineRemitConfig.TrustPayServerPort;
}
try
{
request = (HttpWebRequest)WebRequest.Create(str3 + OnlineRemitConfig.TrustPayTrxURL);
request.Method = "POST";
request.ProtocolVersion = HttpVersion.Version10;
request.ContentType = "application/x-www-form-urlencoded";
//this.iLogWriter.log("成功");
//this.iLogWriter.logNewLine("提交交易报文:");
byte[] bytes = Encoding.UTF8.GetBytes(s);
request.ContentLength = bytes.Length;
stream = new BufferedStream(request.GetRequestStream());
if (!stream.CanWrite)
{
throw new OnlineRemitException("1201", "无法连线网上支付平台", "无法连线到[" + str3 + "]");
}
stream.Write(bytes, 0, bytes.Length);
stream.Flush();
stream.Close();
//this.iLogWriter.log("成功");
//this.iLogWriter.logNewLine("等待网上支付平台返回交易结果:");
response = (HttpWebResponse)request.GetResponse();
Stream responseStream = response.GetResponseStream();
Encoding encoding = Encoding.GetEncoding("gb2312");
StreamReader reader = new StreamReader(responseStream, encoding);
string str4 = null;
while ((str4 = reader.ReadLine()) != null)
{
aXMLString = aXMLString + str4;
if (str4.IndexOf("</MSG>") != -1)
{
break;
}
}
response.Close();
//this.iLogWriter.log("成功");
//this.iLogWriter.logNewLine("返回报文:");
//this.iLogWriter.log("\n" + aXMLString.ToString());
if (response.StatusCode != HttpStatusCode.OK)
{
throw new OnlineRemitException("1206", "网上支付平台服务暂时停止");
}
document = new XmlDocument(aXMLString).GetValue("MSG");
if (document == null)
{
throw new OnlineRemitException("1205", "无法辨识网上支付平台的响应报文", "无[MSG]段!");
}
}
catch (WebException exception2)
{
//this.iLogWriter.logNewLine(exception2.ToString());
throw new OnlineRemitException("1201", "无法连线网上支付平台", "无法连线到[" + str3 + "], " + exception2.Message);
}
catch (IOException exception3)
{
//this.iLogWriter.logNewLine(exception3.ToString());
throw new OnlineRemitException("1202", "提交交易时发生网络错误", "连线中断!");
}
catch (SecurityException exception4)
{
//this.iLogWriter.logNewLine(exception4.ToString());
throw new OnlineRemitException("1201", "无法连线网上支付平台", "进程权限太低!");
}
catch (OnlineRemitException exception5)
{
throw exception5;
}
catch (Exception exception10)
{
exception = exception10;
//this.iLogWriter.logNewLine(exception.StackTrace);
throw new OnlineRemitException("1201", "无法连线网上支付平台", exception.StackTrace);
}
finally
{
if (stream != null)
{
try
{
stream.Close();
}
catch (Exception)
{
}
}
if (response != null)
{
try
{
response.Close();
}
catch (Exception)
{
}
}
}
return document;
}
/// <summary>
/// 在消息头部加上商户信息
/// </summary>
/// <param name="aMessage"></param>
/// <returns></returns>
XmlDocument composeRequestMessage(XmlDocument aMessage)
{
return new XmlDocument("<Merchant><ECMerchantType>" + ECMerchantType + "</ECMerchantType><MerchantID>" + MerchantID + "</MerchantID></Merchant>" + aMessage.ToString());
}
/// <summary>
/// 加入签名信息
/// </summary>
/// <param name="aMessage"></param>
/// <returns></returns>
XmlDocument fileSignMessage(XmlDocument aMessage)
{
RSACryptoServiceProvider provider = OnlineRemitConfig.GetMerchantKey(MerchantID);
byte[] rgbHash = new SHA1Managed().ComputeHash(Encoding.UTF8.GetBytes(aMessage.ToString()));
byte[] data = provider.SignHash(rgbHash, CryptoConfig.MapNameToOID("SHA1"));
string str = Convert.ToBase64String(data);
return new XmlDocument("<Message>" + aMessage.ToString() + "</Message><Signature-Algorithm>SHA1withRSA</Signature-Algorithm><Signature>" + str + "</Signature>");
}
protected XmlDocument Send()
{
checkRequest();
var message = createMessage();
message = composeRequestMessage(message);
message = fileSignMessage(message);
message = sendMessage(message);
message = verifySign(message);
return message;
}
}
}

+ 72
- 0
BWP.ABCClient/B2C/OnlineRemits/OnlineRemitConfig.cs View File

@ -0,0 +1,72 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
namespace BWP.ABCClient.B2C.OnlineRemits
{
public class OnlineRemitConfig
{
/// <summary>
/// 网上支付平台通讯方式(http / https)
/// </summary>
public static string TrustPayConnectMethod
{
get
{
return "https";
}
}
/// <summary>
/// 网上支付平台服务器名
/// </summary>
public static string TrustPayServerName
{
get
{
return "www.95599.cn";
}
}
/// <summary>
/// 网上支付平台交易端口
/// </summary>
public static int TrustPayServerPort
{
get
{
return 443;
}
}
public static string TrustPayTrxURL
{
get
{
return "/b2c/trustpay/ReceiveMerchantTrxReqServlet";
}
}
/// <summary>
/// 得到商户的签名
/// </summary>
/// <param name="MerchantID"></param>
/// <returns></returns>
internal static RSACryptoServiceProvider GetMerchantKey(string MerchantID)
{
throw new NotImplementedException();
}
/// <summary>
/// 得到农行公钥
/// </summary>
/// <returns></returns>
internal static X509Certificate2 GetCertificate()
{
throw new NotImplementedException();
}
}
}

+ 25
- 0
BWP.ABCClient/B2C/OnlineRemits/OnlineRemitException.cs View File

@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BWP.ABCClient.B2C.OnlineRemits
{
public class OnlineRemitException : Exception
{
public string Code { get; set; }
public string DetailMessage { get; set; }
public OnlineRemitException(string code, string message, string detailMessage):base(string.Format("{0}:{1}",message,detailMessage))
{
Code = code;
DetailMessage = detailMessage;
}
public OnlineRemitException(string code, string message):this(code,message,"")
{
}
}
}

+ 63
- 0
BWP.ABCClient/B2C/OnlineRemits/OnlineRemitQueryResultRequest.cs View File

@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BWP.ABCClient.Businesses;
using System.Globalization;
namespace BWP.ABCClient.B2C.OnlineRemits
{
public class OnlineRemitQueryResultRequest:OnlineRemitBaseRequest
{
public string SerialNumber { get; set; }
public string ReceiveAccount { get; set; }
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
protected override void checkRequest()
{
if (string.IsNullOrEmpty(SerialNumber) && string.IsNullOrEmpty(ReceiveAccount))
{
throw new OnlineRemitException("1100", "商户提交的交易资料不合法", "付款流水号和收款方账号同时为空");
}
if (StartDate == null)
{
throw new OnlineRemitException("1101", "商户提交的交易资料不合法", "起始日期格式不正确");
}
if (EndDate == null)
{
throw new OnlineRemitException("1101", "商户提交的交易资料不合法", "截止日期格式不正确");
}
}
protected override XmlDocument createMessage()
{
return new XmlDocument(new StringBuilder("")
.Append("<TrxRequest>")
.Append("<TrxType>OnlineRmtQueryResult</TrxType>")
.AppendFormat("<SerialNumber>{0}</SerialNumber>",SerialNumber)
.AppendFormat("<ReceiveAccount>{0}</ReceiveAccount>",ReceiveAccount)
.AppendFormat("<StartTime>{0}</StartTime>",FormatDate(StartDate.Value))
.AppendFormat("<EndTime>{0}</EndTime>",FormatDate(EndDate.Value))
.Append("</TrxRequest>").ToString());
}
private string FormatDate(DateTime date)
{
return date.ToString("yyyy/MM/dd", CultureInfo.InvariantCulture);
}
public OnlineRemitQueryResultResponse GetResponse()
{
var message = base.Send();
return new OnlineRemitQueryResultResponse(message);
}
}
}

+ 18
- 0
BWP.ABCClient/B2C/OnlineRemits/OnlineRemitQueryResultResponse.cs View File

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BWP.ABCClient.Businesses;
namespace BWP.ABCClient.B2C.OnlineRemits
{
public class OnlineRemitQueryResultResponse
{
private XmlDocument mMessage;
public OnlineRemitQueryResultResponse(XmlDocument message)
{
mMessage = message;
}
}
}

+ 169
- 0
BWP.ABCClient/B2C/OnlineRemits/OnlineRemitRequest.cs View File

@ -0,0 +1,169 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BWP.ABCClient.Businesses;
using System.Security.Cryptography;
using System.Net;
using System.IO;
using System.Security;
using System.Security.Cryptography.X509Certificates;
namespace BWP.ABCClient.B2C.OnlineRemits
{
/// <summary>
/// 网付通,在线付款
/// </summary>
public class OnlineRemitRequest:OnlineRemitBaseRequest
{
/// <summary>
/// 总笔数
/// </summary>
public int TotalCount { get; set; }
/// <summary>
/// 总金额
/// </summary>
public double TotalAmount { get; set; }
/// <summary>
/// 序号
/// </summary>
public string SerialNumber { get; set; }
/// <summary>
/// 备注
/// </summary>
public string Remark { get; set; }
/// <summary>
/// 0:无需操作员确认直接付款;1:需要操作员在商户服务系统确认后付款
/// </summary>
public int CheckType { get; set; }
List<OnlineRemitRequest_Detail> mDetails = new List<OnlineRemitRequest_Detail>();
public List<OnlineRemitRequest_Detail> Details
{
get
{
return mDetails;
}
}
public OnlineRemitResponse GetResponse()
{
var message = base.Send();
OnlineRemitResponse response = new OnlineRemitResponse(message);
return response;
}
protected override XmlDocument createMessage()
{
StringBuilder builder = new StringBuilder("").Append("<TrxRequest>").Append("<TrxType>").Append("OnlineRemit").Append("</TrxType>")
.Append("<CheckType>").Append(CheckType).Append("</CheckType>")
.Append("<SerialNumber>").Append(SerialNumber).Append("</SerialNumber>")
.Append("<TotalCount>").Append(TotalCount).Append("</TotalCount>")
.Append("<TotalAmount>").Append(TotalAmount).Append("</TotalAmount>")
.Append("<Remark>").Append(Remark).Append("</Remark>");
builder.Append("<RemitData>");
foreach (var detail in this.Details)
{
builder.Append("<RemitDetail>")
.Append("<NO>").Append(detail.NO).Append("</NO>")
.Append("<CardNo>").Append(detail.CardNo).Append("</CardNo>")
.Append("<CardName>").Append(detail.CardName).Append("</CardName>")
.Append("<RemitAmount>").Append(detail.Amount).Append("</RemitAmount>")
.Append("<Purpose>").Append(detail.Purpose).Append("</Purpose>")
.Append("</RemitDetail>");
}
builder.Append("</RemitData>").Append("</TrxRequest>");
return new XmlDocument(builder.ToString());
}
public static bool isValidAmount(double aAmount, int aExp)
{
bool flag = false;
if (aExp >= 0)
{
string str = aAmount.ToString();
int index = str.IndexOf('.');
if (index == -1)
{
return true;
}
if (index >= ((str.Length - aExp) - 1))
{
flag = true;
}
}
return flag;
}
protected override void checkRequest()
{
if (TotalCount != Details.Count)
{
throw new OnlineRemitException("1101", "商户提交的交易资料不合法", "付款总笔数与明细笔数不一致!");
}
if (SerialNumber.Trim().Equals(""))
{
throw new OnlineRemitException("1101", "商户提交的交易资料不合法", "付款流水号不能为空!");
}
if (TotalCount <= 0)
{
throw new OnlineRemitException("1101", "商户提交的交易资料不合法", "付款交易总笔数不能小于1笔");
}
if (TotalCount > 100)
{
throw new OnlineRemitException("1101", "商户提交的交易资料不合法", "付款交易总笔数不能大于100笔");
}
if (TotalAmount <= 0.0)
{
throw new OnlineRemitException("1101", "商户提交的交易资料不合法", "付款交易总金额不合法!");
}
if (!(isValidAmount(TotalAmount, 2) && (TotalAmount > 0.0)))
{
throw new OnlineRemitException("1101", "商户提交的交易资料不合法", "付款交易总金额不合法!");
}
var noDic = new Dictionary<int, int>();
foreach (var detail in this.Details)
{
if (noDic.ContainsKey(detail.NO))
{
throw new OnlineRemitException("1101", "商户提交的交易资料不合法", "批次内序号重复");
}
else
{
noDic.Add(detail.NO, detail.NO);
}
if (detail.NO < 0 || detail.NO > 99999)
{
throw new OnlineRemitException("1101", "商户提交的交易资料不合法", "批次内序号需要在1至5位之间:" + detail.NO);
}
if (string.IsNullOrEmpty(detail.CardNo))
{
throw new OnlineRemitException("1101", "商户提交的交易资料不合法", "付款明细卡号不能为空!");
}
if (string.IsNullOrEmpty(detail.CardName))
{
throw new OnlineRemitException("1101", "商户提交的交易资料不合法", "付款明细收款人信息不能为空!");
}
if (!(isValidAmount(detail.Amount, 2) && (detail.Amount > 0.0)))
{
throw new OnlineRemitException("1101", "商户提交的交易资料不合法", "付款交易明细金额不合法:" + detail.Amount.ToString());
}
if (detail.Purpose.Length > 30)
{
throw new OnlineRemitException("1101", "商户提交的交易资料不合法", "明细内容不能超过30个字:" + detail.Purpose);
}
}
}
}
}

+ 38
- 0
BWP.ABCClient/B2C/OnlineRemits/OnlineRemitRequest_Detail.cs View File

@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BWP.ABCClient.B2C.OnlineRemits
{
public class OnlineRemitRequest_Detail
{
/// <summary>
/// 序号
/// </summary>
/// <remarks>
/// 格式化为3位
/// </remarks>
public int NO { get; set; }
/// <summary>
/// 收款方账号
/// </summary>
public string CardNo { get; set; }
/// <summary>
/// 收款方户名
/// </summary>
public string CardName { get; set; }
/// <summary>
/// 金额
/// </summary>
public double Amount { get; set; }
/// <summary>
/// 用途
/// </summary>
public string Purpose { get; set; }
}
}

+ 74
- 0
BWP.ABCClient/B2C/OnlineRemits/OnlineRemitResponse.cs View File

@ -0,0 +1,74 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BWP.ABCClient.Businesses;
namespace BWP.ABCClient.B2C.OnlineRemits
{
/// <summary>
/// 网付通返回
/// </summary>
public class OnlineRemitResponse
{
public string ErrorMessage
{
get;
private set;
}
public string ReturnCode
{
get;
private set;
}
XmlDocument mMessage = new XmlDocument("");
public const string RC_SUCCESS = "0000";
public OnlineRemitResponse(XmlDocument message)
{
mMessage = message;
}
protected internal OnlineRemitResponse()
{
}
public OnlineRemitResponse(string aReturnCode, string aErrorMessage)
{
ReturnCode = aReturnCode;
ErrorMessage = aErrorMessage;
}
void init(XmlDocument aXMLDocument)
{
XmlDocument returnCode = aXMLDocument.GetValue("ReturnCode");
if (returnCode == null)
{
throw new OnlineRemitException("1303", "无法辨识网上支付平台的交易结果", "无法取得[ReturnCode]!");
}
ReturnCode = returnCode.ToString();
if (!Success)
{
XmlDocument errorMessage = aXMLDocument.GetValue("ErrorMessage");
if (errorMessage != null)
{
ErrorMessage = errorMessage.ToString();
}
else
{
ErrorMessage = "未能返回错误信息";
}
}
}
public bool Success
{
get
{
return RC_SUCCESS.Equals(ReturnCode);
}
}
}
}

+ 18
- 0
BWP.ABCClient/B2C/OrderContent.cs View File

@ -0,0 +1,18 @@
namespace BWP.ABCClient.B2C
{
public class OrderContent
{
public string OrderNo { get; set; }
public string OrderAmount { get; set; }
public string OrderDesc { get; set; }
public string OrderDate { get; set; }
public string OrderTime { get; set; }
public string OrderURL { get; set; }
public string PayAmount { get; set; }
public string RefundAmount { get; set; }
public string OrderStatus { get; set; }
public OrderItem[] OrderItems { get; set; }
}
public class OrderItem { }
}

+ 64
- 0
BWP.ABCClient/B2C/PaymentRequest.cs View File

@ -0,0 +1,64 @@
using System.Xml.Serialization;
using BWP.ABCClient.Common;
namespace BWP.ABCClient.B2C
{
[XmlRoot(ElementName = "MSG")]
public class PaymentRequest : MessageBase
{
public MessageContent Message { get; set; }
public static PaymentRequest New()
{
return new PaymentRequest {
Message = new MessageContent {
Merchant = new MerchantContent {
ECMerchantType = "B2C",
MerchantID = string.Empty
},
TrxRequest = new TrxRequestContent {
TrxType = TrxType.PayReq,
Order = new OrderContent {
OrderNo = string.Empty,
OrderAmount = string.Empty,
OrderDesc = string.Empty,
OrderDate = string.Empty,
OrderTime = string.Empty,
OrderURL = string.Empty,
PayAmount = null,
RefundAmount = null,
OrderStatus = null,
OrderItems = new OrderItem[]{}
},
ProductType = "2",
PaymentType = "1",
NotifyType = "1",
ResultNotifyURL = string.Empty,
MerchantRemarks = string.Empty,
PaymentLinkType = "1"
}
},
SignatureAlgorithm = "SHA1withRSA",
Signature = string.Empty
};
}
public class MessageContent
{
public MerchantContent Merchant { get; set; }
public TrxRequestContent TrxRequest { get; set; }
}
public class TrxRequestContent
{
public string TrxType { get; set; }
public OrderContent Order { get; set; }
public string ProductType { get; set; }
public string PaymentType { get; set; }
public string NotifyType { get; set; }
public string ResultNotifyURL { get; set; }
public string MerchantRemarks { get; set; }
public string PaymentLinkType { get; set; }
}
}
}

+ 32
- 0
BWP.ABCClient/B2C/PaymentResponse.cs View File

@ -0,0 +1,32 @@
using System.Xml.Serialization;
using BWP.ABCClient.Common;
namespace BWP.ABCClient.B2C
{
[XmlRoot(ElementName = "MSG")]
public class PaymentResponse : MessageBase
{
public MessageContent Message { get; set; }
public class MessageContent
{
public MerchantContent Merchant { get; set; }
public TrxResponseContent TrxResponse { get; set; }
}
public class TrxResponseContent
{
public string ReturnCode { get; set; }
public string ErrorMessage { get; set; }
public string TrxType { get; set; }
public string OrderNo { get; set; }
public string PaymentURL { get; set; }
public string OrderAmount { get; set; }
}
}
}

+ 43
- 0
BWP.ABCClient/B2C/QueryOrderRequest.cs View File

@ -0,0 +1,43 @@
using System.Xml.Serialization;
using BWP.ABCClient.Common;
namespace BWP.ABCClient.B2C
{
[XmlRoot(ElementName = "MSG")]
public class QueryOrderRequest : MessageBase
{
public MessageContent Message { get; set; }
public static QueryOrderRequest New()
{
return new QueryOrderRequest {
Message = new MessageContent {
Merchant = new MerchantContent {
ECMerchantType = "B2C",
MerchantID = string.Empty
},
TrxRequest = new TrxRequestContent {
TrxType = TrxType.Query,
OrderNo = string.Empty,
QueryDetail = "false"
}
},
SignatureAlgorithm = "SHA1withRSA",
Signature = string.Empty
};
}
public class MessageContent
{
public MerchantContent Merchant { get; set; }
public TrxRequestContent TrxRequest { get; set; }
}
public class TrxRequestContent
{
public string TrxType { get; set; }
public string OrderNo { get; set; }
public string QueryDetail { get; set; }
}
}
}

+ 26
- 0
BWP.ABCClient/B2C/QueryOrderResponse.cs View File

@ -0,0 +1,26 @@
using System.Xml.Serialization;
using BWP.ABCClient.Common;
namespace BWP.ABCClient.B2C
{
[XmlRoot(ElementName = "MSG")]
public class QueryOrderResponse : MessageBase
{
public MessageContent Message { get; set; }
public class MessageContent
{
public MerchantContent Merchant { get; set; }
public TrxResponseContent TrxResponse { get; set; }
}
public class TrxResponseContent
{
public string ReturnCode { get; set; }
public string ErrorMessage { get; set; }
public OrderContent Order { get; set; }
}
}
}

+ 50
- 0
BWP.ABCClient/B2C/SettleRequest.cs View File

@ -0,0 +1,50 @@
using System;
using System.Xml.Serialization;
using BWP.ABCClient.Common;
namespace BWP.ABCClient.B2C
{
[XmlRoot(ElementName = "MSG")]
public class SettleRequest : MessageBase
{
public MessageContent Message { get; set; }
public static SettleRequest New()
{
return new SettleRequest {
Message = new MessageContent {
Merchant = new MerchantContent {
ECMerchantType = "B2C",
MerchantID = string.Empty
},
TrxRequest = new TrxRequestContent {
TrxType = TrxType.Settle,
SettleDate = string.Empty,
SettleStartHour = "false",
SettleEndHour = string.Empty,
SettleType = string.Empty,
ZIP = "YES"
}
},
SignatureAlgorithm = "SHA1withRSA",
Signature = string.Empty
};
}
public class MessageContent
{
public MerchantContent Merchant { get; set; }
public TrxRequestContent TrxRequest { get; set; }
}
public class TrxRequestContent
{
public string TrxType { get; set; }
public string SettleDate { get; set; }
public string SettleStartHour { get; set; }
public string SettleEndHour { get; set; }
public string SettleType { get; set; }
public string ZIP { get; set; }
}
}
}

+ 71
- 0
BWP.ABCClient/B2C/SettleResponse.cs View File

@ -0,0 +1,71 @@
using System;
using System.Collections.Generic;
using System.Xml.Serialization;
using BWP.ABCClient.Common;
namespace BWP.ABCClient.B2C
{
[XmlRoot(ElementName = "MSG")]
public class SettleResponse : MessageBase
{
public MessageContent Message { get; set; }
public class MessageContent
{
public MerchantContent Merchant { get; set; }
public TrxResponseContent TrxResponse { get; set; }
}
public class TrxResponseContent
{
public string ReturnCode { get; set; }
public string ErrorMessage { get; set; }
private string _zipDetailRecords;
public string ZIPDetailRecords
{
get { return _zipDetailRecords; }
set
{
_zipDetailRecords = value;
SetDetailRecords(value);
}
}
private void SetDetailRecords(string value)
{
if (string.IsNullOrEmpty(value)) {
return;
}
string innerXml = MsgUtil.DeCompress(value);
string xml = "<Records>" + innerXml + "</Records>";
var records = MsgUtil.GetMultiInnerXml(xml, "//Record");
var recordList = new List<Record>(records.Length);
foreach (var record in records) {
var recordCols = record.Split(new[] {','}, StringSplitOptions.None);
recordList.Add(new Record {
Sign = recordCols[0],
OrderNumber = recordCols[1],
Amount = recordCols[2],
DaySeqNo = recordCols[3],
Date = recordCols[4]
});
}
DetailRecords = recordList.ToArray();
}
public Record[] DetailRecords { get; set; }
}
}
public class Record
{
public string Sign { get; set; }
public string OrderNumber { get; set; }
public string Amount { get; set; }
public string DaySeqNo { get; set; }
public string Date { get; set; }
}
}

+ 16
- 0
BWP.ABCClient/B2C/TrxType.cs View File

@ -0,0 +1,16 @@
namespace BWP.ABCClient.B2C
{
public class TrxType
{
public const string FundPayReq = "FundPayReq";
public const string MobilePayReq = "MobilePayReq";
public const string MobilePayReg = "MobilePayReg";
public const string PayReq = "PayReq";
public const string PayResult = "PayResult";
public const string Query = "Query";
public const string Refund = "Refund";
public const string Settle = "Settle";
public const string VoidPay = "VoidPay";
public const string VoidRefund = "VoidRefund";
}
}

+ 151
- 0
BWP.ABCClient/BWP.ABCClient.csproj View File

@ -0,0 +1,151 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{22FEFA9B-1D58-4E8A-A1FF-49CEED62C355}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>BWP.ABCClient</RootNamespace>
<AssemblyName>BWP.ABCClient</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<KeyContainerName>BwpApp</KeyContainerName>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Forks.Utils, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7254430f49d10aae, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\tsref\Debug\Forks.Utils.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System">
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="System.Core">
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="System.Security">
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="System.Xml.Linq">
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="System.Data.DataSetExtensions">
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="Microsoft.CSharp">
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="System.Data">
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="System.Xml">
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="Wpf, Version=1.3.0.0, Culture=neutral, PublicKeyToken=a04fa581c0f74d43, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\tsref\Debug\Wpf.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Wpf.System, Version=1.3.0.0, Culture=neutral, PublicKeyToken=a04fa581c0f74d43, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\tsref\Debug\Wpf.System.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\..\..\version\tslib_version.cs">
<Link>tslib_version.cs</Link>
</Compile>
<Compile Include="B2C\OnlineRemits\OnlineRemitBaseRequest.cs" />
<Compile Include="B2C\OnlineRemits\OnlineRemitConfig.cs" />
<Compile Include="B2C\OnlineRemits\OnlineRemitQueryResultRequest.cs" />
<Compile Include="B2C\OnlineRemits\OnlineRemitQueryResultResponse.cs" />
<Compile Include="B2C\OnlineRemits\OnlineRemitRequest.cs" />
<Compile Include="B2C\OnlineRemits\OnlineRemitRequest_Detail.cs" />
<Compile Include="B2C\OnlineRemits\OnlineRemitResponse.cs" />
<Compile Include="B2C\OnlineRemits\OnlineRemitException.cs" />
<Compile Include="Businesses\MarketOrderPay.cs" />
<Compile Include="Businesses\XMLDocument.cs" />
<Compile Include="Businesses\MarketOrderApply.cs" />
<Compile Include="Businesses\IReturnedResult.cs" />
<Compile Include="Businesses\ResultB2CReturned.cs" />
<Compile Include="Businesses\ResultB2BReturned.cs" />
<Compile Include="B2B\QueryTrnxResponse.cs" />
<Compile Include="B2B\QueryTrnxRequest.cs" />
<Compile Include="B2B\TrxStatus.cs" />
<Compile Include="B2B\TrxType.cs" />
<Compile Include="B2C\SettleResponse.cs" />
<Compile Include="B2C\OrderContent.cs" />
<Compile Include="B2C\QueryOrderResponse.cs" />
<Compile Include="B2C\SettleRequest.cs" />
<Compile Include="B2C\QueryOrderRequest.cs" />
<Compile Include="B2C\TrxType.cs" />
<Compile Include="Businesses\B2BReceivingPayment.cs" />
<Compile Include="Businesses\B2BDealQuery.cs" />
<Compile Include="Businesses\B2CReceivingPayment.cs" />
<Compile Include="Businesses\B2COrderQuery.cs" />
<Compile Include="Businesses\B2CSettleByDate.cs" />
<Compile Include="Businesses\MarketReceivingPayment.cs" />
<Compile Include="Businesses\MarketSignOff.cs" />
<Compile Include="Businesses\MarketSignUp.cs" />
<Compile Include="Exceptions\ResponseException.cs" />
<Compile Include="Log\AbcLog.cs" />
<Compile Include="Market\OrderPayResponse.cs" />
<Compile Include="Market\OrderApplyResponse.cs" />
<Compile Include="Market\OrderApplyRequest.cs" />
<Compile Include="Market\MarketResponse.cs" />
<Compile Include="Businesses\Type\B2B.cs" />
<Compile Include="Businesses\BusinessBase.cs" />
<Compile Include="Businesses\Type\BusinessTypes.cs" />
<Compile Include="Businesses\Type\Market.cs" />
<Compile Include="Businesses\Type\B2C.cs" />
<Compile Include="Businesses\Type\IBusinessType.cs" />
<Compile Include="Exceptions\HttpException.cs" />
<Compile Include="Market\OrderPayRequest.cs" />
<Compile Include="Market\PayRequest.cs" />
<Compile Include="Market\SignOffRequest.cs" />
<Compile Include="Market\SignUpRequest.cs" />
<Compile Include="Request.cs" />
<Compile Include="B2B\FundTransferRequest.cs" />
<Compile Include="B2B\FundTransferResponse.cs" />
<Compile Include="B2C\PaymentRequest.cs" />
<Compile Include="B2C\PaymentResponse.cs" />
<Compile Include="Exceptions\CertException.cs" />
<Compile Include="CertManager.cs" />
<Compile Include="Common\MerchantContent.cs" />
<Compile Include="Common\MessageBase.cs" />
<Compile Include="MsgUtil.cs" />
<Compile Include="Common\PaymentURLResponse.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RSAService.cs" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

+ 58
- 0
BWP.ABCClient/Businesses/B2BDealQuery.cs View File

@ -0,0 +1,58 @@
using System;
using BWP.ABCClient.B2B;
using BWP.ABCClient.Businesses.Type;
using BWP.ABCClient.Exceptions;
namespace BWP.ABCClient.Businesses
{
public class B2BDealQuery : BusinessBase<QueryTrnxRequest, QueryTrnxResponse>
{
public B2BDealQuery() : base(BusinessTypes.B2B)
{
RequestObj = QueryTrnxRequest.New();
}
public string MerchantTrnxNo { get; set; }
public DealStatusEnum DealStatus { get; set; }
public bool DealIsSuccess { get; set; }
protected override void AfterRequest()
{
Log.AddNewLine(string.Format("交易结果:[{0}]", ResponseObj.Message.TrxResponse.ReturnCode));
Log.AddNewLine(string.Format("返回信息:[{0}]", ResponseObj.Message.TrxResponse.ErrorMessage));
if (ResponseObj.Message.TrxResponse.ReturnCode != "0000") {
Log.Commit();
throw new ResponseException(ResponseObj.Message.TrxResponse.ReturnCode, ResponseObj.Message.TrxResponse.ErrorMessage);
}
Log.Commit();
DealIsSuccess = ResponseObj.Message.TrxResponse.TrnxStatus == ((int)DealStatusEnum.).ToString();
DealStatusEnum dealStatus;
if (DealStatusEnum.TryParse(ResponseObj.Message.TrxResponse.TrnxStatus, out dealStatus)) {
DealStatus = dealStatus;
}
}
protected override void BeforeRequest()
{
if (string.IsNullOrEmpty(MerchantTrnxNo)) {
throw new Exception("查询的交易号不能为空,B2BGathering.MerchantTrnxNo");
}
RequestObj.Message.Merchant.MerchantID = MerchantID;
RequestObj.Message.TrxRequest.MerchantTrnxNo = MerchantTrnxNo;
RequestObj.Message.TrxRequest.MerchantRemarks = Remarks;
}
}
public enum DealStatusEnum
{
= 5,
= 1,
= 3,
= 9,
= 0,
= 4,
= 2
}
}

+ 62
- 0
BWP.ABCClient/Businesses/B2BReceivingPayment.cs View File

@ -0,0 +1,62 @@
using System;
using System.Globalization;
using BWP.ABCClient.B2B;
using BWP.ABCClient.Businesses.Type;
using BWP.ABCClient.Exceptions;
namespace BWP.ABCClient.Businesses
{
public class B2BReceivingPayment : BusinessBase<FundTransferRequest, FundTransferResponse>
{
public B2BReceivingPayment() : base(BusinessTypes.B2B)
{
RequestObj = FundTransferRequest.New();
}
public string AccountNo { get; set; }
public string AccountName { get; set; }
public string AccountBank { get; set; }
public string Operator { get; set; }
public string PaymentUrl { get; set; }
protected override void AfterRequest()
{
Log.AddNewLine(string.Format("交易结果:[{0}]", ResponseObj.Message.TrxResponse.ReturnCode));
Log.AddNewLine(string.Format("返回信息:[{0}]", ResponseObj.Message.TrxResponse.ErrorMessage));
if (ResponseObj.Message.TrxResponse.ReturnCode != "0000") {
Log.Commit();
throw new ResponseException(ResponseObj.Message.TrxResponse.ReturnCode, ResponseObj.Message.TrxResponse.ErrorMessage);
}
Log.Commit();
PaymentUrl = ResponseObj.Message.TrxResponse.PaymentURL;
}
protected override void BeforeRequest()
{
if (string.IsNullOrEmpty(SequenceNo)) {
throw new Exception("交易流水号不能为空,SequenceNo");
}
if (string.IsNullOrEmpty(ResultNotifyURL)) {
throw new Exception("接受交易结果信息Url不能为空,ResultNotifyURL");
}
if (AccountNo == null) {
throw new Exception("收款方帐号不能为空,AccountNo");
}
if (Date == null) {
throw new Exception("交易日期不能为空,Date");
}
RequestObj.Message.Merchant.MerchantID = MerchantID;
RequestObj.Message.TrxRequest.AccountDB.AccountDBNo = AccountNo;
RequestObj.Message.TrxRequest.AccountDB.AccountDBName = AccountName;
RequestObj.Message.TrxRequest.AccountDB.AccountDBBank = AccountBank;
RequestObj.Message.TrxRequest.TrnxDate = Date.Value.ToString("yyyy/MM/dd", DateTimeFormatInfo.InvariantInfo);
RequestObj.Message.TrxRequest.TrnxTime = Date.Value.ToString("HH:MM:ss", DateTimeFormatInfo.InvariantInfo);
RequestObj.Message.TrxRequest.TrnxAmount = Amount.ToString("f2");
RequestObj.Message.TrxRequest.MerchantTrnxNo = SequenceNo;
RequestObj.Message.TrxRequest.TrnxInfo.TrnxOpr = Operator;
RequestObj.Message.TrxRequest.ResultNotifyURL = ResultNotifyURL;
RequestObj.Message.TrxRequest.MerchantRemarks = Remarks;
}
}
}

+ 53
- 0
BWP.ABCClient/Businesses/B2COrderQuery.cs View File

@ -0,0 +1,53 @@
using System;
using BWP.ABCClient.B2C;
using BWP.ABCClient.Businesses.Type;
using BWP.ABCClient.Exceptions;
namespace BWP.ABCClient.Businesses
{
public class B2COrderQuery : BusinessBase<QueryOrderRequest, QueryOrderResponse>
{
public B2COrderQuery()
: base(BusinessTypes.B2C)
{
RequestObj = QueryOrderRequest.New();
}
public string OrderStatus { get; set; }
public bool OrderIsFinished { get; set; }
protected override void AfterRequest()
{
Log.AddNewLine(string.Format("交易结果:[{0}]", ResponseObj.Message.TrxResponse.ReturnCode));
Log.AddNewLine(string.Format("返回信息:[{0}]", ResponseObj.Message.TrxResponse.ErrorMessage));
if (ResponseObj.Message.TrxResponse.ReturnCode != "0000") {
Log.Commit();
throw new ResponseException(ResponseObj.Message.TrxResponse.ReturnCode, ResponseObj.Message.TrxResponse.ErrorMessage);
}
Log.Commit();
OrderStatus = ResponseObj.Message.TrxResponse.Order.OrderStatus;
OrderIsFinished = OrderStatus == OrderStatusEnum.PAY || OrderStatus == OrderStatusEnum.SETTLED;
}
protected override void BeforeRequest()
{
if (string.IsNullOrEmpty(SequenceNo)) {
throw new Exception("查询的交易号不能为空,SequenceNo");
}
RequestObj.Message.Merchant.MerchantID = MerchantID;
RequestObj.Message.TrxRequest.OrderNo = SequenceNo;
}
}
public class OrderStatusEnum
{
public const string CANCEL = "00";
public const string ISSUE = "99";
public const string NEW = "01";
public const string PAY = "03";
public const string REFUND = "05";
public const string SETTLED = "04";
public const string WAIT = "02";
}
}

+ 56
- 0
BWP.ABCClient/Businesses/B2CReceivingPayment.cs View File

@ -0,0 +1,56 @@
using System;
using System.Globalization;
using BWP.ABCClient.B2C;
using BWP.ABCClient.Businesses.Type;
using BWP.ABCClient.Exceptions;
namespace BWP.ABCClient.Businesses
{
public class B2CReceivingPayment : BusinessBase<PaymentRequest, PaymentResponse>
{
public B2CReceivingPayment() : base(BusinessTypes.B2C)
{
RequestObj = PaymentRequest.New();
}
public string OrderUrl { get; set; }
public string OrderRemarks { get; set; }
public string PaymentUrl { get; set; }
protected override void AfterRequest()
{
Log.AddNewLine(string.Format("交易结果:[{0}]", ResponseObj.Message.TrxResponse.ReturnCode));
Log.AddNewLine(string.Format("返回信息:[{0}]", ResponseObj.Message.TrxResponse.ErrorMessage));
if (ResponseObj.Message.TrxResponse.ReturnCode != "0000") {
Log.Commit();
throw new ResponseException(ResponseObj.Message.TrxResponse.ReturnCode, ResponseObj.Message.TrxResponse.ErrorMessage);
}
Log.Commit();
PaymentUrl = ResponseObj.Message.TrxResponse.PaymentURL;
}
protected override void BeforeRequest()
{
if (string.IsNullOrEmpty(SequenceNo)) {
throw new Exception("交易流水号不能为空,SequenceNo");
}
if (string.IsNullOrEmpty(ResultNotifyURL)) {
throw new Exception("接受交易结果信息Url不能为空,ResultNotifyURL");
}
if (Date == null) {
throw new Exception("交易日期不能为空,Date");
}
RequestObj.Message.Merchant.MerchantID = MerchantID;
RequestObj.Message.TrxRequest.Order.OrderNo = SequenceNo;
RequestObj.Message.TrxRequest.Order.OrderAmount = Amount.ToString("f2");
RequestObj.Message.TrxRequest.Order.OrderDesc = OrderRemarks;
RequestObj.Message.TrxRequest.Order.OrderDate = Date.Value.ToString("yyyy/MM/dd", DateTimeFormatInfo.InvariantInfo);
RequestObj.Message.TrxRequest.Order.OrderTime = Date.Value.ToString("HH:MM:ss", DateTimeFormatInfo.InvariantInfo);
RequestObj.Message.TrxRequest.Order.OrderURL = OrderUrl;
RequestObj.Message.TrxRequest.ResultNotifyURL = ResultNotifyURL;
RequestObj.Message.TrxRequest.MerchantRemarks = Remarks;
}
}
}

+ 50
- 0
BWP.ABCClient/Businesses/B2CSettleByDate.cs View File

@ -0,0 +1,50 @@
using System;
using System.Globalization;
using BWP.ABCClient.B2C;
using BWP.ABCClient.Businesses.Type;
using BWP.ABCClient.Exceptions;
namespace BWP.ABCClient.Businesses
{
public class B2CSettleByDate : BusinessBase<SettleRequest, SettleResponse>
{
public B2CSettleByDate()
: base(BusinessTypes.B2C)
{
RequestObj = SettleRequest.New();
}
public Record[] Records { get; set; }
public string RecordsHexString { get; set; }
protected override void AfterRequest()
{
Log.AddNewLine(string.Format("交易结果:[{0}]", ResponseObj.Message.TrxResponse.ReturnCode));
Log.AddNewLine(string.Format("返回信息:[{0}]", ResponseObj.Message.TrxResponse.ErrorMessage));
if (ResponseObj.Message.TrxResponse.ReturnCode != "0000") {
Log.Commit();
throw new ResponseException(ResponseObj.Message.TrxResponse.ReturnCode, ResponseObj.Message.TrxResponse.ErrorMessage);
}
Log.Commit();
Records = ResponseObj.Message.TrxResponse.DetailRecords;
RecordsHexString = ResponseObj.Message.TrxResponse.ZIPDetailRecords;
}
protected override void BeforeRequest()
{
if (Date == null) {
throw new Exception("查询的日期不能为空,Date");
}
RequestObj.Message.Merchant.MerchantID = MerchantID;
RequestObj.Message.TrxRequest.SettleDate = Date.Value.ToString("yyyy/MM/dd", CultureInfo.InvariantCulture);
RequestObj.Message.TrxRequest.SettleType = SettleType.TRX;
}
}
public class SettleType
{
public const string SETTLE = "SETTLE";
public const string TRX = "TRX";
public const string TRX_BYHOUR = "TRXBYHOUR";
}
}

+ 111
- 0
BWP.ABCClient/Businesses/BusinessBase.cs View File

@ -0,0 +1,111 @@
using System;
using System.Text;
using BWP.ABCClient.Businesses.Type;
using BWP.ABCClient.Common;
using BWP.ABCClient.Exceptions;
namespace BWP.ABCClient.Businesses
{
public class BusinessBase<T, T1>
where T : MessageBase
where T1 : MessageBase
{
private readonly IBusinessType _businessType;
public string MerchantID { get; set; }
public string RequestUrl { get; set; }
public bool IsTestState { get; set; }
public T RequestObj { get; set; }
public T1 ResponseObj { get; set; }
public DateTime? Date { get; set; }
public string SequenceNo { get; set; }
public decimal Amount { get; set; }
public string Remarks { get; set; }
public string ResultNotifyURL { get; set; }
protected AbcLog Log;
public BusinessBase(IBusinessType businessInfo)
{
_businessType = businessInfo;
Log = new AbcLog(businessInfo.Name);
}
public virtual void Request()
{
if (RequestObj == null) {
throw new Exception("RequestObj不能为空");
}
if (string.IsNullOrEmpty(RequestUrl)) {
throw new Exception("RequestUrl不能为空");
}
if (string.IsNullOrEmpty(MerchantID)) {
throw new Exception("MerchantID不能为空");
}
BeforeRequest();
RSAService.Sign(RequestObj, MerchantID, _businessType.SignEncoding, _businessType.IsMarket);
var request = new Request {
RequestEncoding = _businessType.RequestEncoding,
ResponseEncoding = _businessType.ResponseEncoding,
Url = RequestUrl,
Message = SendXml
};
Log.AddNewLine(string.Format("{0}交易开始:==========================", string.IsNullOrEmpty(SequenceNo) ? string.Empty : "流水号[" + SequenceNo + "]"));
if (_businessType.CompressEnabled) {
Log.AddNewLine("压缩前的报文");
Log.AddNewLine(MsgUtil.MsgToBareXml(RequestObj));
}
Log.AddNewLine("提交的报文:");
Log.AddNewLine(request.Message);
Log.AddNewLine(string.Format("连线网上支付平台:[{0}]", RequestUrl));
string result = request.Run();
string receivedXml = GetReceivedXml(result);
Log.AddNewLine("返回报文:");
Log.AddNewLine(receivedXml);
Verify(receivedXml);
ResponseObj = MsgUtil.ParseXmlToMsg<T1>(receivedXml);
AfterRequest();
}
protected void Verify(string receivedXml)
{
if (!RSAService.Verify(receivedXml, _businessType.VerifyEncoding, _businessType.IsMarket, IsTestState)) {
Log.AddNewLine("网上支付平台的响应报文签名验证失败");
Log.Commit();
throw new RSAException("网上支付平台的响应报文签名验证失败");
}
}
protected virtual void BeforeRequest() { }
protected virtual void AfterRequest() { }
private string GetReceivedXml(string result)
{
if (_businessType.CompressEnabled) {
result = MsgUtil.DeCompress(result);
}
return result;
}
public string SendXml
{
get
{
var result = MsgUtil.MsgToBareXml(RequestObj);
if (_businessType.CompressEnabled) {
result = MsgUtil.Compress(result);
}
return result;
}
}
}
}

+ 15
- 0
BWP.ABCClient/Businesses/IReturnedResult.cs View File

@ -0,0 +1,15 @@
namespace BWP.ABCClient.Businesses
{
public interface IReturnedResult
{
bool IsValid { get; set; }
string ReturnCode { get; set; }
string ErrorMessage { get; set; }
bool IsSuccess { get; set; }
string SequenceNo { get; set; }
}
}

+ 65
- 0
BWP.ABCClient/Businesses/MarketOrderApply.cs View File

@ -0,0 +1,65 @@
using System;
using BWP.ABCClient.Businesses.Type;
using BWP.ABCClient.Exceptions;
using BWP.ABCClient.Market;
namespace BWP.ABCClient.Businesses
{
public class MarketOrderApply : BusinessBase<OrderApplyRequest, OrderApplyResponse>
{
public MarketOrderApply()
: base(BusinessTypes.Market)
{
RequestObj = OrderApplyRequest.New();
}
public string BuyerCustomer { get; set; }
public string BuyerCustName { get; set; }
public string SalerCustomer { get; set; }
public string SalerCustName { get; set; }
public string PaymentUrl { get; set; }
protected override void AfterRequest()
{
var errorMessage = ResponseObj.Message.Control.ReturnMessage ?? string.Empty ;
Log.AddNewLine(string.Format("交易结果:[{0}]", ResponseObj.Message.Control.ReturnCode));
Log.AddNewLine(string.Format("返回信息:[{0}]", errorMessage));
Log.Commit();
if (ResponseObj.Message.Control.ReturnCode != "0000") {
throw new ResponseException(ResponseObj.Message.Control.ReturnCode, errorMessage);
}
PaymentUrl=ResponseObj.Message.Parameters.ReturnURL;
}
protected override void BeforeRequest()
{
if (string.IsNullOrEmpty(SequenceNo)) {
throw new Exception("交易流水号不能为空,SequenceNo");
}
if (string.IsNullOrEmpty(BuyerCustomer)) {
throw new Exception("付款帐户不能为空,BuyerCustomer");
}
if (string.IsNullOrEmpty(BuyerCustName)) {
throw new Exception("付款人不能为空,BuyerCustName");
}
if (string.IsNullOrEmpty(SalerCustomer)) {
throw new Exception("收款帐户不能为空,SalerCustomer");
}
if (string.IsNullOrEmpty(SalerCustName)) {
throw new Exception("收款人不能为空,SalerCustName");
}
RequestObj.Message.Control.MerchantID = MerchantID;
RequestObj.Message.Control.MerchantTrxNo = SequenceNo;
RequestObj.Message.Parameters.OrderNo = SequenceNo;
RequestObj.Message.Parameters.BuyerCustName = BuyerCustName;
RequestObj.Message.Parameters.BuyerCustomer = BuyerCustomer;
RequestObj.Message.Parameters.SalerCustName = SalerCustName;
RequestObj.Message.Parameters.SalerCustomer = SalerCustomer;
RequestObj.Message.Parameters.PayAmount = Amount.ToString("f2");
}
}
}

+ 49
- 0
BWP.ABCClient/Businesses/MarketOrderPay.cs View File

@ -0,0 +1,49 @@
using System;
using BWP.ABCClient.Businesses.Type;
using BWP.ABCClient.Exceptions;
using BWP.ABCClient.Market;
namespace BWP.ABCClient.Businesses
{
public class MarketOrderPay : BusinessBase<OrderPayRequest, OrderPayResponse>
{
public MarketOrderPay()
: base(BusinessTypes.Market)
{
RequestObj = OrderPayRequest.New();
}
public string OrderNo { get; set; }
public string CustSignInfo { get; set; }
public string CustSignInfo2 { get; set; }
protected override void AfterRequest()
{
var errorMessage = ResponseObj.Message.Control.ReturnMessage ?? string.Empty;
Log.AddNewLine(string.Format("交易结果:[{0}]", ResponseObj.Message.Control.ReturnCode));
Log.AddNewLine(string.Format("返回信息:[{0}]", errorMessage));
Log.Commit();
if (ResponseObj.Message.Control.ReturnCode != "0000") {
throw new ResponseException(ResponseObj.Message.Control.ReturnCode, errorMessage);
}
}
protected override void BeforeRequest()
{
if (string.IsNullOrEmpty(SequenceNo)) {
throw new Exception("交易流水号不能为空,SequenceNo");
}
if (string.IsNullOrEmpty(OrderNo)) {
throw new Exception("订单号不能为空,OrderNo");
}
RequestObj.Message.Control.MerchantID = MerchantID;
RequestObj.Message.Control.MerchantTrxNo = SequenceNo;
RequestObj.Message.Parameters.OrderNo = OrderNo;
RequestObj.Message.Parameters.PayAmount = Amount.ToString("f2");
RequestObj.Message.Parameters.CustSignInfo = CustSignInfo;
RequestObj.Message.Parameters.CustSignInfo2 = CustSignInfo2;
}
}
}

+ 54
- 0
BWP.ABCClient/Businesses/MarketReceivingPayment.cs View File

@ -0,0 +1,54 @@
using System;
using BWP.ABCClient.Businesses.Type;
using BWP.ABCClient.Exceptions;
using BWP.ABCClient.Market;
namespace BWP.ABCClient.Businesses
{
public class MarketReceivingPayment : BusinessBase<PayRequest, MarketResponse>
{
public MarketReceivingPayment()
: base(BusinessTypes.Market)
{
RequestObj = PayRequest.New();
}
public string CustomerSignInfo { get; set; }
public string CustomerNo { get; set; }
public string OrderMessage { get; set; }
protected override void AfterRequest()
{
var errorMessage = (ResponseObj.Message.Control.ReturnMessage ?? string.Empty) + (ResponseObj.Message.Control.ErrorMessage ?? string.Empty);
Log.AddNewLine(string.Format("交易结果:[{0}]", ResponseObj.Message.Control.ReturnCode));
Log.AddNewLine(string.Format("返回信息:[{0}]", errorMessage));
if (ResponseObj.Message.Control.ReturnCode != "0000") {
Log.Commit();
throw new ResponseException(ResponseObj.Message.Control.ReturnCode, errorMessage);
}
Log.Commit();
}
protected override void BeforeRequest()
{
if (string.IsNullOrEmpty(SequenceNo)) {
throw new Exception("交易流水号不能为空,SequenceNo");
}
if (string.IsNullOrEmpty(CustomerSignInfo)) {
throw new Exception("客户签名不能为空,CustomerSignInfo");
}
if (string.IsNullOrEmpty(CustomerNo)) {
throw new Exception("客户号不能为空,CustomerSignInfo");
}
RequestObj.Message.Control.MerchantID = MerchantID;
RequestObj.Message.Control.MerchantTrxNo = SequenceNo;
RequestObj.Message.Parameters.CustomerNo = CustomerNo;
RequestObj.Message.Parameters.CustSignInfo = CustomerSignInfo;
RequestObj.Message.Parameters.CustSignInfo2 = CustomerSignInfo;
RequestObj.Message.Parameters.PayAmount = Amount.ToString("f2");
RequestObj.Message.Parameters.OrderMg = OrderMessage;
}
}
}

+ 51
- 0
BWP.ABCClient/Businesses/MarketSignOff.cs View File

@ -0,0 +1,51 @@
using System;
using BWP.ABCClient.Businesses.Type;
using BWP.ABCClient.Exceptions;
using BWP.ABCClient.Market;
namespace BWP.ABCClient.Businesses
{
public class MarketSignOff : BusinessBase<SignOffRequest, MarketResponse>
{
public MarketSignOff() : base(BusinessTypes.Market)
{
RequestObj = SignOffRequest.New();
}
public string MerchantName { get; set; }
public string CustomerSignInfo { get; set; }
public string CustomerName { get; set; }
public string CustomerNo { get; set; }
protected override void AfterRequest()
{
var errorMessage = ResponseObj.Message.Control.ReturnMessage ?? string.Empty + ResponseObj.Message.Control.ErrorMessage ?? string.Empty;
Log.AddNewLine(string.Format("交易结果:[{0}]", ResponseObj.Message.Control.ReturnCode));
Log.AddNewLine(string.Format("返回信息:[{0}]", errorMessage));
if (ResponseObj.Message.Control.ReturnCode != "0000") {
Log.Commit();
throw new ResponseException(ResponseObj.Message.Control.ReturnCode, errorMessage);
}
Log.Commit();
}
protected override void BeforeRequest()
{
if (string.IsNullOrEmpty(SequenceNo)) {
throw new Exception("交易流水号不能为空,SequenceNo");
}
if (string.IsNullOrEmpty(CustomerSignInfo)) {
throw new Exception("客户签名不能为空,CustmerSignInfo");
}
RequestObj.Message.Control.MerchantID = MerchantID;
RequestObj.Message.Control.MerchantTrxNo = SequenceNo;
RequestObj.Message.Parameters.CustName = CustomerName;
RequestObj.Message.Parameters.CustSignInfo = CustomerSignInfo;
RequestObj.Message.Parameters.MerchantName = MerchantName;
RequestObj.Message.Parameters.CustomerNo = CustomerNo;
}
}
}

+ 56
- 0
BWP.ABCClient/Businesses/MarketSignUp.cs View File

@ -0,0 +1,56 @@
using System;
using BWP.ABCClient.Businesses.Type;
using BWP.ABCClient.Exceptions;
using BWP.ABCClient.Market;
namespace BWP.ABCClient.Businesses
{
public class MarketSignUp : BusinessBase<SignUpRequest, MarketResponse>
{
public MarketSignUp()
: base(BusinessTypes.Market)
{
RequestObj = SignUpRequest.New();
NeedTwoCheck = null;
}
public string MerchantName { get; set; }
public string CustomerSignInfo { get; set; }
public string CustomerName { get; set; }
public string NeedTwoCheck { get; set; }
protected override void AfterRequest()
{
var errorMessage = ResponseObj.Message.Control.ReturnMessage ?? string.Empty + ResponseObj.Message.Control.ErrorMessage ?? string.Empty;
Log.AddNewLine(string.Format("交易结果:[{0}]", ResponseObj.Message.Control.ReturnCode));
Log.AddNewLine(string.Format("返回信息:[{0}]", errorMessage));
if (ResponseObj.Message.Control.ReturnCode != "0000") {
Log.Commit();
throw new ResponseException(ResponseObj.Message.Control.ReturnCode, errorMessage + MsgUtil.MsgToBareXml(RequestObj));
}
Log.Commit();
}
protected override void BeforeRequest()
{
if (string.IsNullOrEmpty(SequenceNo)) {
throw new Exception("交易流水号不能为空,SequenceNo");
}
if (string.IsNullOrEmpty(CustomerSignInfo)) {
throw new Exception("客户签名不能为空,CustmerSignInfo");
}
if (string.IsNullOrEmpty(MerchantName)) {
throw new Exception("商户名不能为空,MerchantName");
}
RequestObj.Message.Control.MerchantID = MerchantID;
RequestObj.Message.Control.MerchantTrxNo = SequenceNo;
RequestObj.Message.Parameters.CustName = CustomerName;
RequestObj.Message.Parameters.CustSignInfo = CustomerSignInfo;
RequestObj.Message.Parameters.NeedTwoCheck = NeedTwoCheck;
RequestObj.Message.Parameters.MerchantName = MerchantName;
}
}
}

+ 46
- 0
BWP.ABCClient/Businesses/ResultB2BReturned.cs View File

@ -0,0 +1,46 @@
using BWP.ABCClient.Businesses.Type;
namespace BWP.ABCClient.Businesses
{
public class ResultB2BReturned : IReturnedResult
{
private readonly string _xml;
public ResultB2BReturned(string base64string)
{
var log = new AbcLog("b2bReturn");
log.AddNewLine("TrustPayClient ASP V2.0.1 交易开始==========================");
log.AddNewLine("接收到的支付结果通知:\n[" + base64string + "]");
_xml = MsgUtil.FromBase64StringToXml(base64string);
log.AddNewLine("经过Base64解码后的支付结果通知:\n[" + _xml + "]");
log.AddNewLine("验证支付结果通知的签名:");
IsValid = RSAService.Verify(_xml, BusinessTypes.B2B.VerifyEncoding, false, false);
if (IsValid)
log.AddNewLine("验证通过!\n 经过验证的支付结果通知:\n[" + _xml + "]");
else
log.AddNewLine("验证失败!");
log.Commit();
ReturnCode = MsgUtil.GetInnerXml(_xml, "ReturnCode");
ErrorMessage = MsgUtil.GetInnerXml(_xml, "ErrorMessage");
IsSuccess = ReturnCode == "0000" ;
SequenceNo = MsgUtil.GetInnerXml(_xml, "MerchantTrnxNo");
}
public string Xml
{
get { return _xml; }
}
public bool IsValid { get; set; }
public string ReturnCode { get; set; }
public string ErrorMessage { get; set; }
public bool IsSuccess { get; set; }
public string SequenceNo { get; set; }
}
}

+ 46
- 0
BWP.ABCClient/Businesses/ResultB2CReturned.cs View File

@ -0,0 +1,46 @@
using BWP.ABCClient.Businesses.Type;
namespace BWP.ABCClient.Businesses
{
public class ResultB2CReturned : IReturnedResult
{
private readonly string _xml;
public ResultB2CReturned(string base64string)
{
var log = new AbcLog("b2cReturn");
log.AddNewLine("TrustPayClient ASP V2.0.1 交易开始==========================");
log.AddNewLine("接收到的支付结果通知:\n[" + base64string + "]");
_xml = MsgUtil.FromBase64StringToXml(base64string);
log.AddNewLine("经过Base64解码后的支付结果通知:\n[" + _xml + "]");
log.AddNewLine("验证支付结果通知的签名:");
IsValid = RSAService.Verify(_xml, BusinessTypes.B2C.VerifyEncoding, false, false);
if (IsValid)
log.AddNewLine("验证通过!\n 经过验证的支付结果通知:\n[" + _xml + "]");
else
log.AddNewLine("验证失败!");
log.Commit();
ReturnCode = MsgUtil.GetInnerXml(_xml, "ReturnCode");
ErrorMessage = MsgUtil.GetInnerXml(_xml, "ErrorMessage");
IsSuccess = ReturnCode == "0000";
SequenceNo = MsgUtil.GetInnerXml(_xml, "OrderNo");
}
public string Xml
{
get { return _xml; }
}
public bool IsValid { get; set; }
public string ReturnCode { get; set; }
public string ErrorMessage { get; set; }
public bool IsSuccess { get; set; }
public string SequenceNo { get; set; }
}
}

+ 43
- 0
BWP.ABCClient/Businesses/Type/B2B.cs View File

@ -0,0 +1,43 @@
using System;
using System.Text;
namespace BWP.ABCClient.Businesses.Type
{
public class B2B : IBusinessType
{
public Encoding RequestEncoding
{
get { return Encoding.UTF8; }
}
public Encoding ResponseEncoding
{
get { return Encoding.UTF8; }
}
public Encoding SignEncoding
{
get { return Encoding.UTF8; }
}
public Encoding VerifyEncoding
{
get { return Encoding.UTF8; }
}
public bool CompressEnabled
{
get { return false; }
}
public bool IsMarket
{
get { return false; }
}
public string Name
{
get { return "b2b"; }
}
}
}

+ 43
- 0
BWP.ABCClient/Businesses/Type/B2C.cs View File

@ -0,0 +1,43 @@
using System;
using System.Text;
namespace BWP.ABCClient.Businesses.Type
{
public class B2C : IBusinessType
{
public Encoding RequestEncoding
{
get { return Encoding.UTF8; }
}
public Encoding ResponseEncoding
{
get { return Encoding.GetEncoding("GB2312"); }
}
public Encoding SignEncoding
{
get { return Encoding.UTF8; }
}
public Encoding VerifyEncoding
{
get { return Encoding.GetEncoding("GB2312"); }
}
public bool CompressEnabled
{
get { return false; }
}
public bool IsMarket
{
get { return false; }
}
public string Name
{
get { return "b2c"; }
}
}
}

+ 24
- 0
BWP.ABCClient/Businesses/Type/BusinessTypes.cs View File

@ -0,0 +1,24 @@
namespace BWP.ABCClient.Businesses.Type
{
public static class BusinessTypes
{
private static IBusinessType _b2bInfo;
private static IBusinessType _b2cInfo;
private static IBusinessType _marketInfo;
public static IBusinessType B2B
{
get { return _b2bInfo ?? (_b2bInfo = new Type.B2B() ); }
}
public static IBusinessType B2C
{
get { return _b2cInfo ?? (_b2cInfo = new Type.B2C()); }
}
public static IBusinessType Market
{
get { return _marketInfo ?? (_marketInfo = new Market()); }
}
}
}

+ 15
- 0
BWP.ABCClient/Businesses/Type/IBusinessType.cs View File

@ -0,0 +1,15 @@
using System.Text;
namespace BWP.ABCClient.Businesses.Type
{
public interface IBusinessType
{
Encoding RequestEncoding { get; }
Encoding ResponseEncoding { get; }
Encoding SignEncoding { get; }
Encoding VerifyEncoding { get; }
bool CompressEnabled { get; }
bool IsMarket { get; }
string Name { get; }
}
}

+ 43
- 0
BWP.ABCClient/Businesses/Type/Market.cs View File

@ -0,0 +1,43 @@
using System;
using System.Text;
namespace BWP.ABCClient.Businesses.Type
{
public class Market : IBusinessType
{
public Encoding RequestEncoding
{
get { return Encoding.GetEncoding("GB2312"); }
}
public Encoding ResponseEncoding
{
get { return Encoding.GetEncoding("GB2312"); }
}
public Encoding SignEncoding
{
get { return Encoding.GetEncoding("GB2312"); }
}
public Encoding VerifyEncoding
{
get { return Encoding.GetEncoding("GB2312"); }
}
public bool CompressEnabled
{
get { return true; }
}
public bool IsMarket
{
get { return true; }
}
public string Name
{
get { return "market"; }
}
}
}

+ 118
- 0
BWP.ABCClient/Businesses/XMLDocument.cs View File

@ -0,0 +1,118 @@
using System.Collections;
namespace BWP.ABCClient.Businesses
{
public class XmlDocument
{
private string _xmlString;
public XmlDocument()
{
_xmlString = "";
}
public XmlDocument(string xmlString)
{
_xmlString = "";
Init(xmlString);
}
public XmlDocument DeleteFirstTagDocument()
{
string str = GetFirstTagName();
int index = _xmlString.IndexOf("<" + str + ">");
int num2 = _xmlString.IndexOf("</" + str + ">");
if (num2 > index) {
_xmlString = _xmlString.Substring((num2 + str.Length) + 3);
}
return this;
}
public ArrayList GetDocuments(string aTag)
{
string xmlString = _xmlString;
var list = new ArrayList();
while (true) {
int index = xmlString.IndexOf("<" + aTag.Trim() + ">");
int num2 = xmlString.IndexOf("</" + aTag.Trim() + ">");
if (((index == -1) || (num2 == -1)) || (index > num2)) {
return list;
}
var document = new XmlDocument(xmlString.Substring(index, ((num2 + aTag.Length) + 3) - index));
list.Add(document);
xmlString = xmlString.Substring(num2 + 1);
}
}
public string GetFirstTagName()
{
string str = null;
int index = _xmlString.IndexOf('<');
int num2 = _xmlString.IndexOf('>');
if (num2 > index) {
str = _xmlString.Substring(index + 1, num2 - (index + 1));
}
return str;
}
public XmlDocument GetFormatDocument(string aSpace)
{
return GetFormatDocument(0, aSpace);
}
private XmlDocument GetFormatDocument(int aLevel, string aSpace)
{
string str2;
string str = aSpace;
for (int i = 0; i < aLevel; i++) {
str = str + aSpace;
}
if (GetFirstTagName() == null) {
return this;
}
string xmlString = "\n";
for (var document = new XmlDocument(_xmlString); (str2 = document.GetFirstTagName()) != null; document = document.DeleteFirstTagDocument()) {
var document2 = document.GetValue(str2);
var str4 = "";
if (document2.GetFirstTagName() != null) {
str4 = str;
}
xmlString = string.Concat(new object[] { xmlString, str, "<", str2, ">", document2.GetFormatDocument(aLevel + 1, aSpace), str4, "</", str2, ">\n" });
}
return new XmlDocument(xmlString);
}
public XmlDocument GetValue(string aTag)
{
XmlDocument document = null;
int index = _xmlString.IndexOf("<" + aTag.Trim() + ">");
int num2 = _xmlString.IndexOf("</" + aTag.Trim() + ">");
if (((index >= 0) && (num2 >= 0)) && (index < num2)) {
document = new XmlDocument(_xmlString.Substring((index + aTag.Length) + 2, num2 - ((index + aTag.Length) + 2)));
}
return document;
}
public virtual string GetValueNoNull(string aTag)
{
var str = "";
var document = GetValue(aTag);
if (document != null) {
str = document.ToString();
}
return str;
}
public XmlDocument Init(string xmlString)
{
_xmlString = xmlString;
return this;
}
public override string ToString()
{
return _xmlString;
}
}
}

+ 165
- 0
BWP.ABCClient/CertManager.cs View File

@ -0,0 +1,165 @@
using System;
using System.IO;
using System.Security.Cryptography.X509Certificates;
using System.Security.Permissions;
using System.Threading;
using BWP.ABCClient.Exceptions;
using TSingSoft.WebPluginFramework.TimerTasks;
namespace BWP.ABCClient
{
public class CertManager
{
public static CertManager MainSystemCertManager
{
get
{
return new CertManager("MainSystemABCCerts");
}
}
CertManager(string storeName)
{
_store = new X509Store(storeName, StoreLocation.LocalMachine);
new StorePermission(StorePermissionFlags.AllFlags).Assert();
}
private readonly X509Store _store;
public CertManager():this("ABCCerts")
{
}
volatile static object _lockObj = new object();
public void SetupPfx(Stream stream, string password)
{
if (!Monitor.TryEnter(_lockObj))
{
throw new ApplicationException("另一名操作员正在导入证书,请稍后再试");
}
try
{
_store.Open(OpenFlags.ReadWrite);
using (var binaryReader = new BinaryReader(stream))
{
var bytes = binaryReader.ReadBytes((int)stream.Length);
var cert = new X509Certificate2(bytes, password);
if (_store.Certificates.Find(X509FindType.FindBySerialNumber, cert.SerialNumber, false).Count == 0)
{
_store.Add(new X509Certificate2(bytes, password, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet));
}
}
_store.Close();
}
finally
{
Monitor.Exit(_lockObj);
}
}
public void SetupPfx(string fileName, string password)
{
using (var stream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
{
SetupPfx(stream, password);
}
}
public X509Certificate2 Fetch(string merchantID)
{
return Fetch(X509FindType.FindBySubjectName, merchantID);
}
public X509Certificate2 Fetch(X509FindType findType, string findValue)
{
_store.Open(OpenFlags.ReadOnly);
var certs = _store.Certificates.Find(findType, findValue, false);
_store.Close();
if (certs.Count == 0) {
throw new RSAException("找不到商户号对应的证书");
}
if (certs.Count > 1) {
throw new RSAException("同一个商户号有多张证书");
}
return certs[0];
}
public bool TryFetch(string merchantID, out X509Certificate2 cert)
{
cert = null;
_store.Open(OpenFlags.ReadOnly);
var certs = _store.Certificates.Find(X509FindType.FindBySubjectName, merchantID, false);
_store.Close();
if (certs.Count == 0) {
return false;
}
cert = certs[0];
return true;
}
public void Remove(string merchantID)
{
var cert = Fetch(merchantID);
_store.Open(OpenFlags.ReadWrite);
_store.Remove(cert);
_store.Close();
}
public void Remove(X509Certificate2 cert)
{
_store.Open(OpenFlags.ReadWrite);
_store.Remove(cert);
_store.Close();
}
public void ClearAll()
{
_store.Open(OpenFlags.ReadWrite);
_store.RemoveRange(_store.Certificates);
_store.Close();
}
public X509Certificate2Collection FetchAll()
{
_store.Open(OpenFlags.ReadWrite);
var certs = _store.Certificates;
_store.Close();
return certs;
}
public void Export(string merchantID, string password, Stream stream)
{
var cert = Fetch(merchantID);
var bytes = cert.Export(X509ContentType.Pfx, password);
stream.Write(bytes, 0, bytes.Length);
}
public void SetupABCPubKey(string fileName)
{
_store.Open(OpenFlags.ReadWrite);
_store.Add(new X509Certificate2(fileName));
_store.Close();
}
public X509Certificate2 GetABCPubKey()
{
_store.Open(OpenFlags.ReadOnly);
var certs = _store.Certificates.Find(X509FindType.FindBySerialNumber, "7b97ca10275a0000d99d", false);
if (certs.Count == 0) {
throw new RSAException("找不到农行公钥");
}
return certs[0];
}
public X509Certificate2 GetABCTestPubKey()
{
_store.Open(OpenFlags.ReadOnly);
var certs = _store.Certificates.Find(X509FindType.FindBySerialNumber, "50 3a ca 10 53 5b 00 00 02 7f", false);
if (certs.Count == 0) {
throw new RSAException("找不到农行公钥");
}
return certs[0];
}
}
}

+ 8
- 0
BWP.ABCClient/Common/MerchantContent.cs View File

@ -0,0 +1,8 @@
namespace BWP.ABCClient.Common
{
public class MerchantContent
{
public string ECMerchantType { get; set; }
public string MerchantID { get; set; }
}
}

+ 18
- 0
BWP.ABCClient/Common/MessageBase.cs View File

@ -0,0 +1,18 @@
using System.Xml.Serialization;
namespace BWP.ABCClient.Common
{
public class MessageBase
{
[XmlElement(ElementName = "Signature-Algorithm")]
public string SignatureAlgorithm { get; set; }
/// <summary>
/// 签名
/// </summary>
/// <remarks>
/// 使用私钥加密消息后得到的一个签名
/// </remarks>
public string Signature { get; set; }
}
}

+ 27
- 0
BWP.ABCClient/Common/PaymentURLResponse.cs View File

@ -0,0 +1,27 @@
using System.Xml.Serialization;
namespace BWP.ABCClient.Common
{
[XmlRoot(ElementName = "MSG")]
public class PaymentURLResponse : MessageBase
{
public MessageContent Message { get; set; }
public class MessageContent
{
public MerchantContent Merchant { get; set; }
public TrxResponseContent TrxResponse { get; set; }
}
public class TrxResponseContent
{
public string ReturnCode { get; set; }
public string ErrorMessage { get; set; }
public string TrnxType { get; set; }
public string PaymentURL { get; set; }
}
}
}

+ 11
- 0
BWP.ABCClient/Exceptions/CertException.cs View File

@ -0,0 +1,11 @@
using System;
namespace BWP.ABCClient.Exceptions
{
public class RSAException : Exception
{
public RSAException(string message) : base(message)
{
}
}
}

+ 12
- 0
BWP.ABCClient/Exceptions/HttpException.cs View File

@ -0,0 +1,12 @@
using System;
namespace BWP.ABCClient.Exceptions
{
public class HttpException : Exception
{
public HttpException(string message) : base(message)
{
}
}
}

+ 20
- 0
BWP.ABCClient/Exceptions/ResponseException.cs View File

@ -0,0 +1,20 @@
using System;
namespace BWP.ABCClient.Exceptions
{
public class ResponseException : Exception
{
private readonly string _errorCode;
public ResponseException(string errorCode, string message)
: base(errorCode + ":" + message)
{
_errorCode = errorCode;
}
public string ErrorCode
{
get { return _errorCode; }
}
}
}

+ 61
- 0
BWP.ABCClient/Log/AbcLog.cs View File

@ -0,0 +1,61 @@
using System;
using System.IO;
using System.Text;
using Forks.Utils.IO;
using TSingSoft.WebPluginFramework;
namespace BWP.ABCClient
{
public class AbcLog
{
private readonly string _filePath;
private readonly StringBuilder _msg = new StringBuilder();
public AbcLog(string type)
{
#if DEBUG
_filePath = Path.Combine("../../abclog/", DateTime.Today.ToString("yyyyMMdd") + type + "log.txt");
#else
_filePath = Path.Combine(Wpf.Settings.ConfigFolder + "../../abclog/", DateTime.Today.ToString("yyyyMMdd") + type + "log.txt");
#endif
if (!FS.FileExists(_filePath))
FS.CreateDirectory(Path.GetDirectoryName(_filePath));
}
public void Add(string msg)
{
_msg.Append(msg);
}
public void AddNewLine(string msg)
{
_msg.AppendLine();
_msg.Append(string.Format("{0} {1}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), msg));
}
public void Commit()
{
try {
File.AppendAllText(_filePath, _msg.ToString(), Encoding.UTF8);
_msg.Clear();
} catch (Exception)
{ }
}
public string Load()
{
return File.ReadAllText(_filePath, Encoding.UTF8);
}
public void Clear()
{
FS.WriteAllText(_filePath, string.Empty);
}
}
}

+ 49
- 0
BWP.ABCClient/Market/MarketResponse.cs View File

@ -0,0 +1,49 @@
using System.Xml.Serialization;
using BWP.ABCClient.Common;
namespace BWP.ABCClient.Market
{
[XmlRoot(ElementName = "MSG")]
public class MarketResponse : MessageBase
{
public MessageContent Message { get; set; }
public class MessageContent
{
public ControlContent Control { get; set; }
public ParametersContent Parameters { get; set; }
public string Resultsets { get; set; }
}
public class ControlContent
{
public string MerchantTrxNo { get; set; }
public string Version { get; set; }
public string ChannelType { get; set; }
public string BusinessID { get; set; }
public string FunctionID { get; set; }
public string MerchantID { get; set; }
public string ReturnCode { get; set; }
public string ReturnMessage { get; set; }
public string ErrorMessage { get; set; }
public string ClientIP { get; set; }
}
public class ParametersContent
{
public string OrderMg { get; set; }
public string CustomerNo { get; set; }
public string CustSignInfo2 { get; set; }
public string PayAmount { get; set; }
public string CustSignInfo { get; set; }
}
}
}

+ 72
- 0
BWP.ABCClient/Market/OrderApplyRequest.cs View File

@ -0,0 +1,72 @@
using System.Xml.Serialization;
using BWP.ABCClient.Common;
namespace BWP.ABCClient.Market
{
[XmlRoot(ElementName = "MSG")]
public class OrderApplyRequest : MessageBase
{
public MessageContent Message { get; set; }
public static OrderApplyRequest New()
{
return new OrderApplyRequest {
Message = new MessageContent {
Control = new ControlContent {
MerchantTrxNo = string.Empty,
Version = "Java_V1.0",
ChannelType = "01",
BusinessID = "MARKET",
FunctionID = "0025",
MerchantID = string.Empty
},
Parameters = new ParametersContent {
OrderMg = "http://127.0.0.1:18080/marketclientCS/MerchantResult.jsp",
FeeFlag = "0",
OrderType = "C",
PayAmount = string.Empty,
OrderNo = string.Empty,
BuyerCustName = string.Empty,
BuyerCustomer = string.Empty,
SalerCustName = string.Empty,
SalerCustomer = string.Empty
},
Resultsets = string.Empty
},
SignatureAlgorithm = "SHA1withRSA",
Signature = string.Empty
};
}
public class MessageContent
{
public ControlContent Control { get; set; }
public ParametersContent Parameters { get; set; }
public string Resultsets { get; set; }
}
public class ControlContent
{
public string MerchantTrxNo { get; set; }
public string Version { get; set; }
public string ChannelType { get; set; }
public string BusinessID { get; set; }
public string FunctionID { get; set; }
public string MerchantID { get; set; }
}
public class ParametersContent
{
public string FeeFlag { get; set; }
public string BuyerCustomer { get; set; }
public string OrderMg { get; set; }
public string PayAmount { get; set; }
public string OrderType { get; set; }
public string OrderNo { get; set; }
public string SalerCustomer { get; set; }
public string SalerCustName { get; set; }
public string BuyerCustName { get; set; }
}
}
}

+ 44
- 0
BWP.ABCClient/Market/OrderApplyResponse.cs View File

@ -0,0 +1,44 @@
using System.Xml.Serialization;
using BWP.ABCClient.Common;
namespace BWP.ABCClient.Market
{
[XmlRoot(ElementName = "MSG")]
public class OrderApplyResponse : MessageBase
{
public MessageContent Message { get; set; }
public class MessageContent
{
public ControlContent Control { get; set; }
public ParametersContent Parameters { get; set; }
public string Resultsets { get; set; }
}
public class ControlContent
{
public string MerchantTrxNo { get; set; }
public string Version { get; set; }
public string ChannelType { get; set; }
public string BusinessID { get; set; }
public string FunctionID { get; set; }
public string MerchantID { get; set; }
public string ReturnCode { get; set; }
public string ReturnMessage { get; set; }
}
public class ParametersContent
{
public string OrderDate { get; set; }
public string ReturnURL { get; set; }
}
}
}

+ 61
- 0
BWP.ABCClient/Market/OrderPayRequest.cs View File

@ -0,0 +1,61 @@
using System.Xml.Serialization;
using BWP.ABCClient.Common;
namespace BWP.ABCClient.Market
{
[XmlRoot(ElementName = "MSG")]
public class OrderPayRequest : MessageBase
{
public MessageContent Message { get; set; }
public static OrderPayRequest New()
{
return new OrderPayRequest {
Message = new MessageContent {
Control = new ControlContent {
MerchantTrxNo = string.Empty,
Version = "Java_V1.0",
ChannelType = "01",
BusinessID = "MARKET",
FunctionID = "0026",
MerchantID = string.Empty
},
Parameters = new ParametersContent {
PayAmount = string.Empty,
OrderNo = string.Empty,
CustSignInfo = string.Empty,
CustSignInfo2 = string.Empty,
},
Resultsets = string.Empty
},
SignatureAlgorithm = "SHA1withRSA",
Signature = string.Empty
};
}
public class MessageContent
{
public ControlContent Control { get; set; }
public ParametersContent Parameters { get; set; }
public string Resultsets { get; set; }
}
public class ControlContent
{
public string MerchantTrxNo { get; set; }
public string Version { get; set; }
public string ChannelType { get; set; }
public string BusinessID { get; set; }
public string FunctionID { get; set; }
public string MerchantID { get; set; }
}
public class ParametersContent
{
public string CustSignInfo2 { get; set; }
public string PayAmount { get; set; }
public string OrderNo { get; set; }
public string CustSignInfo { get; set; }
}
}
}

+ 41
- 0
BWP.ABCClient/Market/OrderPayResponse.cs View File

@ -0,0 +1,41 @@
using System.Xml.Serialization;
using BWP.ABCClient.Common;
namespace BWP.ABCClient.Market
{
[XmlRoot(ElementName = "MSG")]
public class OrderPayResponse : MessageBase
{
public MessageContent Message { get; set; }
public class MessageContent
{
public ControlContent Control { get; set; }
public string Parameters { get; set; }
public string Resultsets { get; set; }
}
public class ControlContent
{
public string MerchantTrxNo { get; set; }
public string ReturnMessage { get; set; }
public string ChannelType { get; set; }
public string Version { get; set; }
public string ClientIP { get; set; }
public string BusinessID { get; set; }
public string FunctionID { get; set; }
public string ReturnCode { get; set; }
public string MerchantID { get; set; }
}
}
}

+ 68
- 0
BWP.ABCClient/Market/PayRequest.cs View File

@ -0,0 +1,68 @@
using System.Xml.Serialization;
using BWP.ABCClient.Common;
namespace BWP.ABCClient.Market
{
[XmlRoot(ElementName = "MSG")]
public class PayRequest : MessageBase
{
public MessageContent Message { get; set; }
public static PayRequest New()
{
return new PayRequest {
Message = new MessageContent {
Control = new ControlContent {
MerchantTrxNo = string.Empty,
Version = "Java_V1.0",
ChannelType = "01",
BusinessID = "MARKET",
FunctionID = "0009",
MerchantID = string.Empty
},
Parameters = new ParametersContent {
OrderMg = "实时支付",
CustomerNo = string.Empty,
CustSignInfo2 = null,
PayAmount = string.Empty,
CustSignInfo = string.Empty
},
Resultsets = string.Empty
},
SignatureAlgorithm = "SHA1withRSA",
Signature = string.Empty
};
}
public class MessageContent
{
public ControlContent Control { get; set; }
public ParametersContent Parameters { get; set; }
public string Resultsets { get; set; }
}
public class ControlContent
{
public string MerchantTrxNo { get; set; }
public string Version { get; set; }
public string ChannelType { get; set; }
public string BusinessID { get; set; }
public string FunctionID { get; set; }
public string MerchantID { get; set; }
}
public class ParametersContent
{
public string OrderMg { get; set; }
public string CustomerNo { get; set; }
public string CustSignInfo2 { get; set; }
public string PayAmount { get; set; }
public string CustSignInfo { get; set; }
}
}
}

+ 69
- 0
BWP.ABCClient/Market/SignOffRequest.cs View File

@ -0,0 +1,69 @@
using System.Xml.Serialization;
using BWP.ABCClient.Common;
namespace BWP.ABCClient.Market
{
[XmlRoot(ElementName = "MSG")]
public class SignOffRequest : MessageBase
{
public MessageContent Message { get; set; }
public static SignOffRequest New()
{
return new SignOffRequest {
Message = new MessageContent {
Control = new ControlContent {
MerchantTrxNo = string.Empty,
Version = "Java_V1.0",
ChannelType = "01",
BusinessID = "MARKET",
FunctionID = "0001",
MerchantID = string.Empty
},
Parameters = new ParametersContent {
CustName = string.Empty,
MerchantName = string.Empty,
CustomerNo = string.Empty,
CustSignInfo = string.Empty
},
Resultsets = string.Empty
},
SignatureAlgorithm = "SHA1withRSA",
Signature = string.Empty
};
}
public class MessageContent
{
public ControlContent Control { get; set; }
public ParametersContent Parameters { get; set; }
public string Resultsets { get; set; }
}
public class ControlContent
{
public string MerchantTrxNo { get; set; }
public string Version { get; set; }
public string ChannelType { get; set; }
public string BusinessID { get; set; }
public string FunctionID { get; set; }
public string MerchantID { get; set; }
}
public class ParametersContent
{
public string CustName { get; set; }
public string MerchantName { get; set; }
public string CustSignInfo { get; set; }
public string CustomerNo { get; set; }
}
}
}

+ 69
- 0
BWP.ABCClient/Market/SignUpRequest.cs View File

@ -0,0 +1,69 @@
using System.Xml.Serialization;
using BWP.ABCClient.Common;
namespace BWP.ABCClient.Market
{
[XmlRoot(ElementName = "MSG")]
public class SignUpRequest : MessageBase
{
public MessageContent Message { get; set; }
public static SignUpRequest New()
{
return new SignUpRequest {
Message = new MessageContent {
Control = new ControlContent {
MerchantTrxNo = string.Empty,
Version = "Java_V1.0",
ChannelType = "01",
BusinessID = "MARKET",
FunctionID = "0000",
MerchantID = string.Empty
},
Parameters = new ParametersContent {
CustName = string.Empty,
MerchantName = string.Empty,
CustSignInfo = string.Empty,
NeedTwoCheck = null
},
Resultsets = string.Empty
},
SignatureAlgorithm = "SHA1withRSA",
Signature = string.Empty
};
}
public class MessageContent
{
public ControlContent Control { get; set; }
public ParametersContent Parameters { get; set; }
public string Resultsets { get; set; }
}
public class ControlContent
{
public string MerchantTrxNo { get; set; }
public string Version { get; set; }
public string ChannelType { get; set; }
public string BusinessID { get; set; }
public string FunctionID { get; set; }
public string MerchantID { get; set; }
}
public class ParametersContent
{
public string CustName { get; set; }
public string MerchantName { get; set; }
public string CustSignInfo { get; set; }
public string NeedTwoCheck { get; set; }
}
}
}

+ 108
- 0
BWP.ABCClient/MsgUtil.cs View File

@ -0,0 +1,108 @@
using System;
using System.IO;
using System.IO.Compression;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using XmlDocument = BWP.ABCClient.Businesses.XmlDocument;
namespace BWP.ABCClient
{
public class MsgUtil
{
public class BareXmlTextWriter : XmlTextWriter
{
public BareXmlTextWriter(TextWriter writer) : base(writer) {}
public override void WriteStartDocument() {}
public override void WriteStartDocument(bool bare) {}
public override void WriteEndElement()
{
WriteFullEndElement();
}
}
public static string MsgToBareXml(object obj)
{
return MsgToBareXml(obj, Formatting.None, char.MinValue);
}
public static string MsgToBareXml(object obj, Formatting formatting, char indentChar)
{
StringBuilder sb = new StringBuilder();
using (var stringWriter = new StringWriter(sb)) {
using (BareXmlTextWriter writer = new BareXmlTextWriter(stringWriter)) {
writer.Formatting = formatting;
writer.IndentChar = indentChar;
var ns = new XmlSerializerNamespaces();
ns.Add(string.Empty, string.Empty);
new XmlSerializer(obj.GetType()).Serialize(writer, obj, ns);
}
}
return sb.ToString();
}
public static T ParseXmlToMsg<T>(string xml)
{
using (TextReader reader = new StringReader(xml)) {
return (T)new XmlSerializer(typeof(T)).Deserialize(reader);
}
}
public static string GetInnerXml(string xml, string xpath)
{
var aMessage = new XmlDocument(xml);
return aMessage.GetValueNoNull(xpath);
}
public static string Compress(string uncompressedString)
{
byte[] byteData = Encoding.GetEncoding("GB18030").GetBytes(uncompressedString);
using (MemoryStream srcStream = new MemoryStream(byteData)) {
using (var destStream = new MemoryStream()) {
using (GZipStream compress = new GZipStream(destStream, CompressionMode.Compress)) {
srcStream.CopyTo(compress);
}
return Convert.ToBase64String(destStream.ToArray());
}
}
}
public static string DeCompress(string comppressedString)
{
byte[] byteInput = Convert.FromBase64String(comppressedString);
using (var srcStream = new MemoryStream(byteInput)) {
using (var destStream = new MemoryStream()) {
using (GZipStream decompress = new GZipStream(srcStream, CompressionMode.Decompress)) {
decompress.CopyTo(destStream);
var resultBytes = destStream.ToArray();
return Encoding.GetEncoding("GB18030").GetString(resultBytes, 0, resultBytes.Length);
}
}
}
}
public static string[] GetMultiInnerXml(string xml, string xpath)
{
var xmlDoc = new System.Xml.XmlDocument();
xmlDoc.LoadXml(xml);
var nodes = xmlDoc.SelectNodes(xpath);
if (nodes == null) {
return null;
}
var result = new string[nodes.Count];
for (int i = 0; i < result.Length; i++) {
result[i] = nodes[i].InnerXml;
}
return result;
}
public static string FromBase64StringToXml(string msg)
{
byte[] bytes = Convert.FromBase64String(msg);
return Encoding.GetEncoding("gb2312").GetString(bytes, 0, bytes.Length);
}
}
}

+ 35
- 0
BWP.ABCClient/Properties/AssemblyInfo.cs View File

@ -0,0 +1,35 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("BWP.ABCClient")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("BWP.ABCClient")]
[assembly: AssemblyCopyright("Copyright © BWP 2011")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("49a33933-5a6f-4d22-98aa-b462f5a974d0")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]

+ 74
- 0
BWP.ABCClient/RSAService.cs View File

@ -0,0 +1,74 @@
using System;
using System.Security.Cryptography;
using System.Text;
using BWP.ABCClient.Common;
namespace BWP.ABCClient
{
public static class RSAService
{
public static void Sign(MessageBase msgObj, string merchantID, Encoding msgEncoding, bool isMarket)
{
string xml = MsgUtil.MsgToBareXml(msgObj);
var message = MsgUtil.GetInnerXml(xml, "Message");
message = isMarket ? string.Format("<Message>{0}</Message>", message) : message;
msgObj.Signature = Sign(message, merchantID, msgEncoding);
}
public static string Sign(string msg, string merchantID)
{
return Sign(msg, merchantID, Encoding.Default);
}
public static string Sign(string msg, string merchantID, Encoding msgEncoding)
{
var cert = new CertManager().Fetch(merchantID);
var privateKey = (RSACryptoServiceProvider)cert.PrivateKey;
if (privateKey == null)
{
throw new Exception("商户的证书中没有私钥,请上传有效的证书");
}
byte[] rgbHash = new SHA1Managed().ComputeHash(msgEncoding.GetBytes(msg));
byte[] data = privateKey.SignHash(rgbHash, cert.SignatureAlgorithm.Value);
return Convert.ToBase64String(data);
}
public static bool Verify(string returnMsg, string abcSign)
{
return Verify(returnMsg, abcSign, Encoding.Default, false);
}
public static bool Verify(string returnMsg, string abcSign, Encoding msgEncoding, bool isTest)
{
var certMgr = new CertManager();
var cert = isTest ? certMgr.GetABCTestPubKey() : certMgr.GetABCPubKey();
var publicKey = (RSACryptoServiceProvider)cert.PublicKey.Key;
var singature = Convert.FromBase64String(abcSign);
var msgHash = new SHA1Managed().ComputeHash(msgEncoding.GetBytes(returnMsg));
return publicKey.VerifyHash(msgHash, cert.SignatureAlgorithm.Value, singature);
}
public static bool Verify(string receivedXml, Encoding msgEncoding, bool isMarket, bool isTest)
{
string message = MsgUtil.GetInnerXml(receivedXml, "Message");
message = isMarket ? string.Format("<Message>{0}</Message>", message) : message;
string signature = MsgUtil.GetInnerXml(receivedXml, "Signature");
return Verify(message, signature, msgEncoding, isTest);
}
public static bool TestVerify(string returnMsg, string abcSign)
{
return TestVerify(returnMsg, abcSign, Encoding.Default);
}
public static bool TestVerify(string returnMsg, string abcSign, Encoding msgEncoding)
{
var cert = new CertManager().GetABCTestPubKey();
var publicKey = (RSACryptoServiceProvider)cert.PublicKey.Key;
var singature = Convert.FromBase64String(abcSign);
var msgHash = new SHA1Managed().ComputeHash(msgEncoding.GetBytes(returnMsg));
return publicKey.VerifyHash(msgHash, cert.SignatureAlgorithm.Value, singature);
}
}
}

+ 50
- 0
BWP.ABCClient/Request.cs View File

@ -0,0 +1,50 @@
using System.IO;
using System.Net;
using System.Text;
using BWP.ABCClient.Exceptions;
namespace BWP.ABCClient
{
public class Request
{
public string Message { get; set; }
public string Url { get; set; }
public Encoding RequestEncoding { get; set; }
public Encoding ResponseEncoding { get; set; }
public string ProxyIP { get; set; }
public int ProxyPort { get; set; }
public string Run()
{
ServicePointManager.ServerCertificateValidationCallback = delegate {
return true;
};
var request = (HttpWebRequest)WebRequest.Create(Url);
if (!string.IsNullOrEmpty(ProxyIP) && ProxyPort != 0) {
request.Proxy = new WebProxy(ProxyIP, ProxyPort);
}
request.Method = "POST";
request.ProtocolVersion = HttpVersion.Version10;
request.ContentType = "application/x-www-form-urlencoded";
byte[] bytes = RequestEncoding.GetBytes(Message);
request.ContentLength = bytes.Length;
using (var stream = request.GetRequestStream()) {
stream.Write(bytes, 0, bytes.Length);
}
var response = (HttpWebResponse)request.GetResponse();
if (response.StatusCode != HttpStatusCode.OK) {
throw new HttpException("网上支付平台服务暂时停止 " + response.StatusCode);
}
using (var responseStream = response.GetResponseStream()) {
using (var reader = new StreamReader(responseStream, ResponseEncoding)) {
return reader.ReadToEnd();
}
}
}
}
}

+ 57
- 0
test/B2BReceivingPaymentTest.cs View File

@ -0,0 +1,57 @@
using System;
using System.Text;
using BWP.ABCClient.Businesses;
using NUnit.Framework;
namespace BWP.ABCClient
{
[TestFixture]
public class B2BReceivingPaymentTest
{
[Test]
public void AssignValue()
{
EnsureCertsExists();
B2BReceivingPayment collections = new B2BReceivingPayment();
collections.MerchantID = "337100000000066";
collections.Date = DateTime.Now;
collections.Amount = 234.5m;
collections.AccountNo = "622587263489712639846";
collections.AccountName = string.Empty;
collections.AccountBank = string.Empty;
collections.ResultNotifyURL = "http://a.b.c.d";
collections.Remarks = string.Empty;
collections.Operator = string.Empty;
collections.SequenceNo = "209329384902834";
collections.RequestUrl = "http://localhost:5000/B2B/";
using (new MockWebServer("http://localhost:5000/B2B/", Encoding.UTF8, Encoding.UTF8, false)) {
collections.Request();
}
}
[Test]
public void ReturnValue()
{
EnsureCertsExists();
B2BReceivingPayment collections = new B2BReceivingPayment();
collections.MerchantID = "337100000000066";
collections.Date = DateTime.Now;
collections.Amount = 234.5m;
collections.AccountNo = "622587263489712639846";
collections.ResultNotifyURL = "http://a.b.c.d";
collections.SequenceNo = "209329384902834";
collections.RequestUrl = "http://localhost:5000/B2B/";
using (new MockWebServer("http://localhost:5000/B2B/", Encoding.UTF8, Encoding.UTF8, false)) {
collections.Request();
}
Assert.AreEqual("https://easyabc.95599.cn/b2b/NotCheckStatus/PaymentModeAct.ebf?TOKEN=12975716546177309876", collections.PaymentUrl);
}
public static void EnsureCertsExists()
{
var certManager = new CertManager();
certManager.SetupPfx("Certs/asB.pfx", "14814622");
certManager.SetupABCPubKey("Certs/TrustPay.cer");
}
}
}

+ 97
- 0
test/BusinessTest.cs View File

@ -0,0 +1,97 @@
using System;
using System.Text;
using BWP.ABCClient.B2B;
using BWP.ABCClient.B2C;
using BWP.ABCClient.Businesses;
using BWP.ABCClient.Businesses.Type;
using BWP.ABCClient.Common;
using BWP.ABCClient.Market;
using NUnit.Framework;
namespace BWP.ABCClient
{
[TestFixture]
public class BusinessTest
{
[Test]
public void B2CRequest()
{
EnsureCertsExists();
using (new MockWebServer("http://localhost:5000/B2C/", Encoding.UTF8, Encoding.GetEncoding("GB2312"), false)) {
var business = new BusinessBase<PaymentRequest, PaymentURLResponse>(BusinessTypes.B2C);
business.MerchantID = "103452083980419";
business.RequestUrl = "http://localhost:5000/B2C/";
business.RequestObj = PaymentRequest.New();
business.Request();
var responseObj = business.ResponseObj;
Assert.AreEqual("https://easyabc.95599.cn/b2c/NotCheckStatus/PaymentModeAct.ebf?TOKEN=12977496798933397376", responseObj.Message.TrxResponse.PaymentURL);
}
}
[Test]
public void B2BRequest()
{
EnsureCertsExists();
using (new MockWebServer("http://localhost:5000/B2B/", Encoding.UTF8, Encoding.UTF8, false)) {
var business = new BusinessBase<FundTransferRequest, PaymentURLResponse>(BusinessTypes.B2B);
business.MerchantID = "337100000000066";
business.RequestUrl = "http://localhost:5000/B2B/";
business.RequestObj = FundTransferRequest.New();
business.Request();
var responseObj = business.ResponseObj;
Assert.AreEqual("https://easyabc.95599.cn/b2b/NotCheckStatus/PaymentModeAct.ebf?TOKEN=12975716546177309876", responseObj.Message.TrxResponse.PaymentURL);
}
}
[Test]
public void MarketRequest()
{
EnsureCertsExists();
Encoding gb2312Encoding = Encoding.GetEncoding("GB2312");
using (new MockWebServer("http://localhost:5000/Market/", gb2312Encoding, gb2312Encoding, true)) {
var business = new BusinessBase<PayRequest, MarketResponse>(BusinessTypes.Market);
business.MerchantID = "337100000000066";
business.RequestUrl = "http://localhost:5000/Market/";
business.RequestObj = PayRequest.New();
business.Request();
var responseObj = business.ResponseObj;
Assert.AreEqual("337199901033E01", responseObj.Message.Control.MerchantID);
}
}
[Test]
public void MarketOrderApplyRequest()
{
EnsureCertsExists();
Encoding gb2312Encoding = Encoding.GetEncoding("GB2312");
var orderApplyRequest=OrderApplyRequest.New();
orderApplyRequest.Message.Control.MerchantTrxNo = "Req110607008";
orderApplyRequest.Message.Control.MerchantID = "337199901033E01";
orderApplyRequest.Message.Parameters.BuyerCustomer = "84000471247";
orderApplyRequest.Message.Parameters.PayAmount = "0.01";
orderApplyRequest.Message.Parameters.OrderNo = "00000000011";
orderApplyRequest.Message.Parameters.SalerCustomer = "84003761702";
orderApplyRequest.Message.Parameters.SalerCustName = "张冠群";
orderApplyRequest.Message.Parameters.BuyerCustName = "宋元华";
using (new MockWebServer("http://localhost:5000/MarketOrderApply/", gb2312Encoding, gb2312Encoding, true)) {
var business = new BusinessBase<OrderApplyRequest, OrderApplyResponse>(BusinessTypes.Market);
business.MerchantID = "337199901033E01";
business.RequestUrl = "http://localhost:5000/MarketOrderApply/";
business.RequestObj = orderApplyRequest;
business.Request();
var responseObj = business.ResponseObj;
Console.WriteLine(MsgUtil.MsgToBareXml(orderApplyRequest));
Assert.AreEqual("337199901033E01", responseObj.Message.Control.MerchantID);
}
}
private void EnsureCertsExists() {
var certManager = new CertManager();
certManager.SetupPfx("Certs/asC.pfx", "14814622");
certManager.SetupPfx("Certs/asB.pfx", "14814622");
certManager.SetupABCPubKey("Certs/TrustPay.cer");
certManager.SetupABCPubKey("Certs/TrustPayTest.cer");
}
}
}

+ 93
- 0
test/CertManagerTest.cs View File

@ -0,0 +1,93 @@
using System;
using System.IO;
using System.Security.Cryptography;
using System.Xml.Serialization;
using NUnit.Framework;
namespace BWP.ABCClient
{
[TestFixture]
public class CertManagerTest
{
[SetUp]
public void Setup()
{
var manager = new CertManager();
manager.ClearAll();
}
[Test]
public void SetupLocation()
{
var manager = new CertManager();
const string fileName = "Certs/asB.pfx";
const string password = "14814622";
manager.SetupPfx(fileName, password);
var cert = manager.Fetch("337100000000066");
var rsa = cert.PrivateKey as RSACryptoServiceProvider;
}
[Test]
public void ClearAll()
{
var manager = new CertManager();
const string fileName = "Certs/asB.pfx";
const string password = "14814622";
manager.SetupPfx(fileName, password);
manager.ClearAll();
var certs = manager.FetchAll();
Assert.IsTrue(certs.Count == 0);
}
[Test]
public void SetupPfxFile()
{
var manager = new CertManager();
const string fileName = "Certs/asB.pfx";
const string password = "14814622";
manager.SetupPfx(fileName, password);
var cert = manager.Fetch("337100000000066");
Assert.AreEqual("7B97CA10275A0121D1B9", cert.SerialNumber);
}
[Test]
public void Remove()
{
var manager = new CertManager();
const string fileName = "Certs/asB.pfx";
const string password = "14814622";
manager.SetupPfx(fileName, password);
manager.Remove("337100000000066");
try {
manager.Fetch("337100000000066");
Assert.Fail("error");
} catch (Exception e) {
Assert.AreEqual("找不到商户号对应的证书", e.Message);
}
}
[Test]
public void SetupPfxStream()
{
var manager = new CertManager();
using (var stream = File.OpenRead("Certs/asB.pfx")) {
const string password = "14814622";
manager.SetupPfx(stream, password);
}
var cert = manager.Fetch("337100000000066");
Assert.AreEqual("7B97CA10275A0121D1B9", cert.SerialNumber);
}
[Test]
public void ExportCert()
{
var manager = new CertManager();
const string fileName = "Certs/asB.pfx";
const string password = "14814622";
manager.SetupPfx(fileName, password);
using (var stream = File.OpenWrite("Certs/asBclone.pfx")) {
manager.Export("337100000000066", password, stream);
}
}
}
}

BIN
test/Certs/PDM.pfx View File


BIN
test/Certs/TrustPay.cer View File


BIN
test/Certs/TrustPayTest.cer View File


BIN
test/Certs/asB.pfx View File


BIN
test/Certs/asC.pfx View File


+ 78
- 0
test/LogTest.cs View File

@ -0,0 +1,78 @@
using System;
using System.Text;
using System.Threading;
using BWP.ABCClient.Businesses;
using BWP.ABCClient.Businesses.Type;
using NUnit.Framework;
namespace BWP.ABCClient
{
[TestFixture]
public class LogTest
{
[Test]
public void CommitAndLoadTest()
{
var log = new AbcLog("test");
log.Clear();
log.AddNewLine("开始交易:");
log.AddNewLine("检查配置:");
log.Add("正确");
log.Commit();
Assert.AreEqual(string.Format("\r\n{0} 开始交易:\r\n{0} 检查配置:正确", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")), log.Load());
}
[Test]
public void ThreadTest()
{
new AbcLog("test").Clear();
var t = new Thread(ThreadProc);
t.Start();
for (int i = 0; i < 9; i++) {
var log = new AbcLog("test");
log.AddNewLine("接受农行回馈:" + i);
log.Add("正确");
log.Commit();
Thread.Sleep(1);
}
t.Join();
Console.WriteLine(new AbcLog("test").Load());
}
static void ThreadProc()
{
for (var i = 0; i < 10; i++) {
var log = new AbcLog("test");
log.AddNewLine("开始交易:" + i);
log.AddNewLine("检查配置:");
log.Add("正确");
log.Commit();
Thread.Sleep(1);
}
}
[Test]
public void B2BLogTest()
{
var log = new AbcLog(BusinessTypes.B2B.Name);
log.Clear();
B2BReceivingPaymentTest.EnsureCertsExists();
var collections = new B2BReceivingPayment();
collections.MerchantID = "337100000000066";
collections.Date = DateTime.Now;
collections.Amount = 234.5m;
collections.AccountNo = "622587263489712639846";
collections.ResultNotifyURL = "http://a.b.c.d";
collections.SequenceNo = "209329384902834";
collections.RequestUrl = "http://localhost:5000/B2B/";
using (new MockWebServer("http://localhost:5000/B2B/", Encoding.UTF8, Encoding.UTF8, false)) {
collections.Request();
;
}
Console.WriteLine(log.Load());
}
}
}

+ 86
- 0
test/MockWebServer.cs View File

@ -0,0 +1,86 @@
using System;
using System.IO;
using System.Text;
using System.Net;
using System.Threading;
namespace BWP.ABCClient
{
public sealed class MockWebServer : IDisposable
{
private readonly HttpListener _listener;
private readonly Thread _thread;
private readonly Encoding _reqEncoding;
private Encoding _respEncoding;
private readonly bool _compressResp;
public MockWebServer() : this("http://localhost:5000/", Encoding.UTF8, Encoding.UTF8, false)
{
}
public MockWebServer(string prefix, Encoding reqEncoding, Encoding respEncoding, bool compressResp)
{
try {
_listener = new HttpListener();
_listener.Prefixes.Add(prefix);
_listener.Start();
Console.WriteLine("MockWebServer Listening... ");
_thread = new Thread(Listen);
_thread.Start();
} catch (Exception e) {
Console.WriteLine(e);
}
_reqEncoding = reqEncoding;
_respEncoding = respEncoding;
_compressResp = compressResp;
}
private void Listen()
{
while (true) {
HttpListenerContext context = _listener.GetContext();
HttpListenerRequest request = context.Request;
string receivedData;
using (var inputStream = request.InputStream) {
using (var inputReader = new StreamReader(inputStream, _reqEncoding)) {
receivedData = inputReader.ReadToEnd();
}
}
Console.WriteLine("ReceivedData:");
Console.WriteLine(receivedData);
string responseStr = string.Empty;
if (request.RawUrl.Contains("B2C")) {
responseStr = "<MSG><Message><Merchant><ECMerchantType>B2C</ECMerchantType><MerchantID>103452083980410</MerchantID></Merchant><TrxResponse><ReturnCode>0000</ReturnCode><ErrorMessage>交易成功</ErrorMessage><TrxType>PayReq</TrxType><OrderNo>634333749713468745</OrderNo><PaymentURL>https://easyabc.95599.cn/b2c/NotCheckStatus/PaymentModeAct.ebf?TOKEN=12977496798933397376</PaymentURL><OrderAmount>170940.8</OrderAmount></TrxResponse></Message><Signature-Algorithm>SHA1withRSA</Signature-Algorithm><Signature>eAy2xu/VmFnkHEY5sAxwmV/NfbXUDRzLH3IJa7oXOMuGGHHkXfYlwFfe2HesKq6gQgfFcfIsNs0bEc8r6EDkzZVETuiVviQxahqnqr0+GRnfly5OwNELtFCbtJ5PdzuWjme6SbNPSTqMUN6bRWzgr/UXrkuo3uyJOIIyCFGsFbs=</Signature></MSG>";
_respEncoding = Encoding.GetEncoding("gb2312");
}
if (request.RawUrl.Contains("B2B")) {
responseStr = "<MSG><Message><Merchant><ECMerchantType>B2B</ECMerchantType><MerchantID>337100000000066</MerchantID></Merchant><TrxResponse><ReturnCode>0000</ReturnCode><ErrorMessage>交易成功</ErrorMessage><TrnxType>FundTransfer</TrnxType><TrnxAMT>.1</TrnxAMT><MerchantTrnxNo>634331972002042500</MerchantTrnxNo><PaymentURL>https://easyabc.95599.cn/b2b/NotCheckStatus/PaymentModeAct.ebf?TOKEN=12975716546177309876</PaymentURL></TrxResponse></Message><Signature-Algorithm>SHA1withRSA</Signature-Algorithm><Signature>977AkRZUxtHflGP4fyvfNFpcmjuD0goKvRWD+w5g/bx45ZiCkGIki3wDwtgSNBA+QDBs/cyYAsR6AxuIs9CC0obMeSMrMBbixKJgJkNKO0UPlIU4seJ5rSlYKT1HX7tNE1SI7/VEmsv9i0r110hQjkSjzFhVrv9jRlMhNxSopbg=</Signature></MSG>";
}
if (request.RawUrl.Contains("Market")) {
responseStr = "<MSG><Message><Control><MerchantTrxNo>RSU110406001</MerchantTrxNo><ChannelType>01</ChannelType><Version>Java_V1.0</Version><ClientIP>187.61.1.1</ClientIP><BusinessID>MARKET</BusinessID><FunctionID>0000</FunctionID><ReturnCode>0000</ReturnCode><MerchantID>337199901033E01</MerchantID></Control><Parameters></Parameters><Resultsets></Resultsets></Message><Signature-Algorithm>SHA1withRSA</Signature-Algorithm><Signature>evJk/wQM5BjR72vHSCd1wgXSK8ZSRCVHbKv15faI1dY5kr4oz7ThBftaqcKqV7548QoDrMT0M3nITOffUU2CkLqb4TJcLAFZm+UVX2p/+1J2VPR0pBOnVLde8F6ADtnSV4IvqOCSkRi1Zoymr6UQ1gVw9p1Mh+TgOd6K85Zhitk=</Signature></MSG>";
}
if (request.RawUrl.Contains("MarketOrderApply")) {
responseStr = "<MSG><Message><Control><MerchantTrxNo>Req110607008</MerchantTrxNo><ReturnMessage>交易成功</ReturnMessage><ChannelType>01</ChannelType><Version>Java_V1.0</Version><BusinessID>MARKET</BusinessID><FunctionID>0025</FunctionID><ReturnCode>0000</ReturnCode><MerchantID>337199901033E01</MerchantID></Control><Parameters><OrderDate>2011-06-07 11:13:18</OrderDate><ReturnURL>https://www.95599.cn/market/MarketOrderPay.ebf?token=13074163984216493171</ReturnURL></Parameters><Resultsets></Resultsets></Message><Signature-Algorithm>SHA1withRSA</Signature-Algorithm><Signature>MI99KF8wCoZR9DDBVEZWPFPJqJJFHV4Eci7/LJKP46fmaK3N4y9nWXPhJ+STnAZ5xwvjpRrgZqzcwVEY4acI0EqaUfADvzVV5jIgXatFG8gO1UhL3YpfK7HJX5lXdBcSN72QNuJA1M9ZbaH6KDhs3V/fWYrlLfTrdHnfjKssxMY=</Signature></MSG>";
}
if (_compressResp) {
responseStr = MsgUtil.Compress(responseStr);
}
HttpListenerResponse response = context.Response;
byte[] buffer = _respEncoding.GetBytes(responseStr);
response.ContentLength64 = buffer.Length;
using (Stream output = response.OutputStream) {
output.Write(buffer, 0, buffer.Length);
}
}
}
public void Dispose()
{
_thread.Abort();
_listener.Stop();
}
}
}

+ 67
- 0
test/MsgUtilTest.cs View File

@ -0,0 +1,67 @@
using System;
using BWP.ABCClient.B2B;
using NUnit.Framework;
namespace BWP.ABCClient
{
[TestFixture]
public class MsgUtilTest
{
[Test]
public void ParseReturnMsg()
{
string msg = "PE1TRz48TWVzc2FnZT48VHJ4UmVzcG9uc2U+PFJldHVybkNvZGU+MDAwMDwvUmV0dXJuQ29kZT48RXJyb3JNZXNzYWdlPjwvRXJyb3JNZXNzYWdlPjxFQ01lcmNoYW50VHlwZT5CMkM8L0VDTWVyY2hhbnRUeXBlPjxNZXJjaGFudElEPjEwMzQ1MjA4Mzk4MDQwNDwvTWVyY2hhbnRJRD48VHJ4VHlwZT5QYXlSZXN1bHQ8L1RyeFR5cGU+PE9yZGVyTm8+VGVzdE9yZGVyPC9PcmRlck5vPjxBbW91bnQ+MTAwLjA8L0Ftb3VudD48QmF0Y2hObz4wMDAwMDE8L0JhdGNoTm8+PFZvdWNoZXJObz4xMjM0NTY8L1ZvdWNoZXJObz48SG9zdERhdGU+MjAwOS8wOS8wODwvSG9zdERhdGU+PEhvc3RUaW1lPjEwOjU1OjUwPC9Ib3N0VGltZT48TWVyY2hhbnRSZW1hcmtzPlRoaXMgaXMgdGVzdCE8L01lcmNoYW50UmVtYXJrcz48UGF5VHlwZT5QQVkwMTwvUGF5VHlwZT48Tm90aWZ5VHlwZT4wPC9Ob3RpZnlUeXBlPjwvVHJ4UmVzcG9uc2U+PC9NZXNzYWdlPjxTaWduYXR1cmUtQWxnb3JpdGhtPlNIQTF3aXRoUlNBPC9TaWduYXR1cmUtQWxnb3JpdGhtPjxTaWduYXR1cmU+SVE4Z2pFSlRvK0FXQWxqWGVhcVVwdW43Z1JCNnNWdEhRSS9pNFdqUTNISExqZmphMTF3RE5VRVUyVzBVRUNsQnp5RFZuc0tRUHE2MmliM21YRjgrSnJZTWdpYW53WDNBNlRJbkxXMXJQTldVV1AwNGl5UVIvTUxuMHNaTjJ1S2JFbU5SWXRURjNPQ0lsTHFEblppYk1tSEZPTzhnektneVBxeEtaUkRRaHRZPTwvU2lnbmF0dXJlPjwvTVNHPg==";
Console.WriteLine(MsgUtil.FromBase64StringToXml(msg));
}
[Test]
public void SelectMultiNode()
{
string str = "<Records><Record>123</Record><Record>134</Record><Record>456</Record></Records>";
string[] values = MsgUtil.GetMultiInnerXml(str, "//Record");
Assert.AreEqual("123", values[0]);
Assert.AreEqual("134", values[1]);
Assert.AreEqual("456", values[2]);
}
[Test]
public void MsgToXml()
{
var msg = FundTransferRequest.New();
var xml = MsgUtil.MsgToBareXml(msg);
Console.WriteLine(xml);
msg = MsgUtil.ParseXmlToMsg<FundTransferRequest>(xml);
Console.WriteLine(msg.Message.Merchant.ECMerchantType);
var response = new FundTransferResponse();
response.Message = new FundTransferResponse.MessageContent();
response.Message.TrxResponse = new FundTransferResponse.TrxResponseContent();
response.Message.TrxResponse.ReturnCode = "0000";
xml = MsgUtil.MsgToBareXml(response);
Console.WriteLine(xml);
var obj = MsgUtil.ParseXmlToMsg<FundTransferResponse>(xml);
Assert.AreEqual("0000", obj.Message.TrxResponse.ReturnCode);
}
[Test]
public void GetInnerXml()
{
var msg = "<MSG><Message><Merchant><ECMerchantType>B2C</ECMerchantType><MerchantID>103452083980409</MerchantID></Merchant><TrxRequest><TrxType>PayReq</TrxType><Order><OrderNo>634333823922218745</OrderNo><OrderAmount>254011</OrderAmount><OrderDesc></OrderDesc><OrderDate>2011/02/15</OrderDate><OrderTime>16:02:29</OrderTime><OrderURL>http://119.167.225.52/B2/InternetSale/Pub/B2CReceive.aspx?id=10821</OrderURL><OrderItems></OrderItems></Order><ProductType>2</ProductType><PaymentType>1</PaymentType><NotifyType>1</NotifyType><ResultNotifyURL>http://119.167.225.52/B2/InternetSale/Pub/B2CReceive.aspx</ResultNotifyURL><MerchantRemarks></MerchantRemarks><PaymentLinkType>1</PaymentLinkType></TrxRequest></Message><Signature-Algorithm>SHA1withRSA</Signature-Algorithm><Signature>Nj7TTt4jyHTH93TekdWXr98tFKbjz/aRx3PBaE0SA6ns4bwqLbpI/27ljN90tElzqVnZWyHIKjDjo25SpPkgXlCsQGHtQcLbA6ZVXVqH18SjLxc4baUyEokMlnpbPYHAiOufOG3Ss8bI3/QlCbESV+7aeOwBfkQESAYvzsZWSWE=</Signature></MSG>";
var expectmsg = "<Merchant><ECMerchantType>B2C</ECMerchantType><MerchantID>103452083980409</MerchantID></Merchant><TrxRequest><TrxType>PayReq</TrxType><Order><OrderNo>634333823922218745</OrderNo><OrderAmount>254011</OrderAmount><OrderDesc></OrderDesc><OrderDate>2011/02/15</OrderDate><OrderTime>16:02:29</OrderTime><OrderURL>http://119.167.225.52/B2/InternetSale/Pub/B2CReceive.aspx?id=10821</OrderURL><OrderItems></OrderItems></Order><ProductType>2</ProductType><PaymentType>1</PaymentType><NotifyType>1</NotifyType><ResultNotifyURL>http://119.167.225.52/B2/InternetSale/Pub/B2CReceive.aspx</ResultNotifyURL><MerchantRemarks></MerchantRemarks><PaymentLinkType>1</PaymentLinkType></TrxRequest>";
Assert.AreEqual(expectmsg, MsgUtil.GetInnerXml(msg, "Message"));
expectmsg = "Nj7TTt4jyHTH93TekdWXr98tFKbjz/aRx3PBaE0SA6ns4bwqLbpI/27ljN90tElzqVnZWyHIKjDjo25SpPkgXlCsQGHtQcLbA6ZVXVqH18SjLxc4baUyEokMlnpbPYHAiOufOG3Ss8bI3/QlCbESV+7aeOwBfkQESAYvzsZWSWE=";
Assert.AreEqual(expectmsg, MsgUtil.GetInnerXml(msg, "Signature"));
}
[Test]
public void CompressDeCompress()
{
string str = "<Merchant><ECMerchantType>B2C</ECMerchantType><MerchantID>103452083980409</MerchantID></Merchant><TrxResponse><ReturnCode>0000</ReturnCode><ErrorMessage>交易成功</ErrorMessage><TrxType>PayReq</TrxType><OrderNo>634333823922218745</OrderNo><PaymentURL>https://easyabc.95599.cn/b2c/NotCheckStatus/PaymentModeAct.ebf?TOKEN=12977568750460430844</PaymentURL><OrderAmount>254011</OrderAmount></TrxResponse>";
Assert.AreEqual(str, MsgUtil.DeCompress(MsgUtil.Compress(str)));
}
}
}

+ 35
- 0
test/Properties/AssemblyInfo.cs View File

@ -0,0 +1,35 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("test")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("test")]
[assembly: AssemblyCopyright("Copyright © 2011")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("38052bef-0132-48b6-a766-0e3b52f90baf")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]

+ 54
- 0
test/RSAServiceTest.cs View File

@ -0,0 +1,54 @@
using System;
using System.Text;
using BWP.ABCClient.Businesses.Type;
using NUnit.Framework;
namespace BWP.ABCClient
{
[TestFixture]
public class RSAServiceTest
{
[SetUp]
public void Setup()
{
new CertManager().ClearAll();
}
[Test]
public void Sign()
{
string msg = "<Merchant><ECMerchantType>B2C</ECMerchantType><MerchantID>103452083980409</MerchantID></Merchant><TrxRequest><TrxType>PayReq</TrxType><Order><OrderNo>634333823922218745</OrderNo><OrderAmount>254011</OrderAmount><OrderDesc></OrderDesc><OrderDate>2011/02/15</OrderDate><OrderTime>16:02:29</OrderTime><OrderURL>http://119.167.225.52/B2/InternetSale/Pub/B2CReceive.aspx?id=10821</OrderURL><OrderItems></OrderItems></Order><ProductType>2</ProductType><PaymentType>1</PaymentType><NotifyType>1</NotifyType><ResultNotifyURL>http://119.167.225.52/B2/InternetSale/Pub/B2CReceive.aspx</ResultNotifyURL><MerchantRemarks></MerchantRemarks><PaymentLinkType>1</PaymentLinkType></TrxRequest>";
string sign = "yGt5aaDrHmWBFb5Lk5WZlLmpuJXe4B25/t4FJzvQlAeKA+cqegiddcpfjGbv3AmspoRqZYNTEfnyLSOjZ8iz9L1U5nl415CzNml2uTLx1aiX4SpHSQASlu6fGqgO2yl2PrABslo+/njsy1tkzwFGm+y1gpjPNykkOWpaYyUjnfw=";
var certManager = new CertManager();
certManager.SetupPfx("Certs/asC.pfx", "14814622");
var signedMsg = RSAService.Sign(msg, "103452083980419");
Console.WriteLine(signedMsg);
Assert.AreEqual(sign, signedMsg);
}
[Test]
public void Verify()
{
string returnMsg = "<Merchant><ECMerchantType>B2C</ECMerchantType><MerchantID>103452083980409</MerchantID></Merchant><TrxResponse><ReturnCode>0000</ReturnCode><ErrorMessage>交易成功</ErrorMessage><TrxType>PayReq</TrxType><OrderNo>634333823922218745</OrderNo><PaymentURL>https://easyabc.95599.cn/b2c/NotCheckStatus/PaymentModeAct.ebf?TOKEN=12977568750460430844</PaymentURL><OrderAmount>254011</OrderAmount></TrxResponse>";
string abcSign = "3+0sE/7PTfYfHYqHUwWoFzUVvr0h2HUaXpq5pr+r3+DhyvufhVUPq1We9a0E+DzqzwnW3ZD5EYLhA204o4oRiLauEzM1cj8ddXZJGAtk5ftv1OGVCV+bvts/Ei9FQp8ws5b7pNqAvIyoSbIToartR7AJ42RJsT5DxXBtFy0Y2oQ=";
var certManager = new CertManager();
certManager.SetupABCPubKey("Certs/TrustPay.cer");
var pass = RSAService.Verify(returnMsg, abcSign);
Assert.IsTrue(pass);
}
[Test]
public void MarketVerify()
{
string returnMsg = "<Message><Control><MerchantTrxNo>1301643918078</MerchantTrxNo><ReturnMessage>商户状态不允许交易!</ReturnMessage><ChannelType>01</ChannelType><Version>Java_V1.0</Version><ClientIP>187.61.1.1</ClientIP><BusinessID>MARKET</BusinessID><FunctionID>0000</FunctionID><ReturnCode>500105</ReturnCode><MerchantID>337199901033E01</MerchantID></Control><Parameters></Parameters><Resultsets></Resultsets></Message>";
string abcSign = "0m9ZR3zXZPKNa7z7Tr3DqHSoDx8NzgHeI0UCmlnpCqBGZS/YcGNZ+UThdVgfBacC27ELhtnRQaAzduQ0zzROs/Cpqm6h8BXfbhaU6Qr+Pp7Qfsu13XuBGr0iCfesFY5yoUlBnedUxCz6GOt9hGhVpPGsROvXU1cKIyafEGtpn9k=";
var certManager = new CertManager();
certManager.SetupABCPubKey("Certs/TrustPay.cer");
var pass = RSAService.Verify(returnMsg, abcSign );
Assert.IsTrue(pass);
}
}
}

+ 27
- 0
test/RequestTest.cs View File

@ -0,0 +1,27 @@
using System;
using System.Text;
using NUnit.Framework;
namespace BWP.ABCClient
{
[TestFixture]
public class RequestTest
{
private const string MSG = "<MSG><Signature-Algorithm>SHA1withRSA</Signature-Algorithm><Signature></Signature><Message><Merchant><ECMerchantType>B2B</ECMerchantType><MerchantID></MerchantID></Merchant><TrxRequest><TrxType>FundTransfer</TrxType><MerchantTrnxNo></MerchantTrnxNo><TrnxAmount>0</TrnxAmount><TrnxDate></TrnxDate><TrnxTime></TrnxTime><AccountDB><AccountDBNo></AccountDBNo><AccountDBName></AccountDBName><AccountDBBank></AccountDBBank></AccountDB><TrnxInfo><TrnxOpr></TrnxOpr><TrnxRemarks><Remark><Key>充值时间</Key><Value></Value></Remark></TrnxRemarks><TrnxItems><TrnxItem><ProductID></ProductID><ProductName>人民币</ProductName><UnitPrice>0</UnitPrice><Qty>1</Qty></TrnxItem></TrnxItems></TrnxInfo><ResultNotifyURL></ResultNotifyURL><MerchantRemarks></MerchantRemarks></TrxRequest></Message></MSG>";
[Test]
public void Request()
{
using (new MockWebServer()) {
var request = new Request {
Url = "http://localhost:5000/",
RequestEncoding = Encoding.UTF8,
ResponseEncoding = Encoding.UTF8,
Message = MSG
};
string receivedMsg = request.Run();
Console.WriteLine("client received:" + receivedMsg);
}
}
}
}

+ 57
- 0
test/ResultReturnedTest.cs View File

@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BWP.ABCClient.Businesses;
using NUnit.Framework;
namespace BWP.ABCClient
{
[TestFixture]
public class ResultReturnedTest
{
[Test]
public void B2BTest()
{
const string msg = "PE1TRz48TWVzc2FnZT48VHJ4UmVzcG9uc2U+PE1lcmNoYW50SUQ+MzM3MTAwMDAwMDAwMDU2PC9NZXJjaGFudElEPjxDb3Jwb3JhdGlvbkN1c3RvbWVyTm8+Mzc5OTk2NzE5NjU8L0NvcnBvcmF0aW9uQ3VzdG9tZXJObz48TWVyY2hhbnRUcm54Tm8+NjM0Mzc0MTU0NDI5MzE3NTAwPC9NZXJjaGFudFRybnhObz48VHJueFNOPjwvVHJueFNOPjxUcm54VHlwZT5GVU5EX1RSQU5TRkVSPC9Ucm54VHlwZT48VHJueEFNVD4xODU3MTIxLjAwPC9Ucm54QU1UPjxPcmdpbmFsRnJlZXplTm8+PC9PcmdpbmFsRnJlZXplTm8+PEZyZWV6ZU5vPjwvRnJlZXplTm8+PEFjY291bnRObz48L0FjY291bnRObz48QWNjb3VudE5hbWU+PC9BY2NvdW50TmFtZT48QWNjb3VudEJhbms+PC9BY2NvdW50QmFuaz48QWNjb3VudERCTm8+MTUtNDkxMTAxMDQwMDIwNTIzPC9BY2NvdW50REJObz48QWNjb3VudERCTmFtZT7Busm9wfm6zb7FwPvKs8a309DP3rmry748L0FjY291bnREQk5hbWU+PEFjY291bnREQkJhbms+MzQyNzc8L0FjY291bnREQkJhbms+PFRybnhUaW1lPjIwMTEtMDQtMDMgMDg6MTg6NTI8L1RybnhUaW1lPjxUcm54U3RhdHVzPjA8L1RybnhTdGF0dXM+PFJldHVybkNvZGU+PC9SZXR1cm5Db2RlPjwvVHJ4UmVzcG9uc2U+PC9NZXNzYWdlPjxTaWduYXR1cmUtQWxnb3JpdGhtPlNIQTF3aXRoUlNBPC9TaWduYXR1cmUtQWxnb3JpdGhtPjxTaWduYXR1cmU+Y2sra3V6Mk9KRVpwTWlhLzBva3JPOTAvZWdVTnZDeUN2cjdZRXN0SXA3aGtYeGEzbDJDWVNMd1NpczlHU0p3OVYrQitlVHkrRGRZUDF0cWZlaHRRZmEyZWQxMENRR2Z0eTViL3F4R2VRL3ZrR1NTOUNOTWxDNjdOV1VMTnhCaVdxNkFVQkwybndUbkVmRzV3VXZjZ3BrTHE2VWF6MklUekhBTWZselBmU1ZJPTwvU2lnbmF0dXJlPjwvTVNHPg==";
var certManager = new CertManager();
certManager.SetupABCPubKey("Certs/TrustPay.cer");
var result = new ResultB2BReturned(msg);
Console.WriteLine(result.Xml);
Assert.IsTrue(result.IsValid);
Assert.AreEqual(@"<MSG><Message><TrxResponse><MerchantID>337100000000056</MerchantID><CorporationCustomerNo>37999671965</CorporationCustomerNo><MerchantTrnxNo>634374154429317500</MerchantTrnxNo><TrnxSN></TrnxSN><TrnxType>FUND_TRANSFER</TrnxType><TrnxAMT>1857121.00</TrnxAMT><OrginalFreezeNo></OrginalFreezeNo><FreezeNo></FreezeNo><AccountNo></AccountNo><AccountName></AccountName><AccountBank></AccountBank><AccountDBNo>15-491101040020523</AccountDBNo><AccountDBName>梁山六和九利食品有限公司</AccountDBName><AccountDBBank>34277</AccountDBBank><TrnxTime>2011-04-03 08:18:52</TrnxTime><TrnxStatus>0</TrnxStatus><ReturnCode></ReturnCode></TrxResponse></Message><Signature-Algorithm>SHA1withRSA</Signature-Algorithm><Signature>ck+kuz2OJEZpMia/0okrO90/egUNvCyCvr7YEstIp7hkXxa3l2CYSLwSis9GSJw9V+B+eTy+DdYP1tqfehtQfa2ed10CQGfty5b/qxGeQ/vkGSS9CNMlC67NWULNxBiWq6AUBL2nwTnEfG5wUvcgpkLq6Uaz2ITzHAMflzPfSVI=</Signature></MSG>", result.Xml);
}
[Test]
public void B2BTest2()
{
const string msg = "PE1TRz48TWVzc2FnZT48VHJ4UmVzcG9uc2U+PE1lcmNoYW50SUQ+MzM3MTAwMDAwMDAwMDc1PC9NZXJjaGFudElEPjxDb3Jwb3JhdGlvbkN1c3RvbWVyTm8+MzM5OTkwODc1NDA8L0NvcnBvcmF0aW9uQ3VzdG9tZXJObz48TWVyY2hhbnRUcm54Tm8+NjM0NDUzNzMwNTA3NDI3NTAwPC9NZXJjaGFudFRybnhObz48VHJueFNOPjkwMTEwNzA0MTA0OTQ5NDA1NzE8L1RybnhTTj48VHJueFR5cGU+RlVORF9UUkFOU0ZFUjwvVHJueFR5cGU+PFRybnhBTVQ+MTUwMDAwMDwvVHJueEFNVD48T3JnaW5hbEZyZWV6ZU5vPiA8L09yZ2luYWxGcmVlemVObz48RnJlZXplTm8+IDwvRnJlZXplTm8+PEFjY291bnRObz4xOS0wODAyMDEwNDAwNTc5MzQ8L0FjY291bnRObz48QWNjb3VudE5hbWU+urzW3c/owPvT8Mje1sbGt9PQz965q8u+PC9BY2NvdW50TmFtZT48QWNjb3VudEJhbms+1eO9rbfW0NA8L0FjY291bnRCYW5rPjxBY2NvdW50REJObz4xNS03NDA4MDEwNDAwMDE3MzM8L0FjY291bnREQk5vPjxBY2NvdW50REJOYW1lPrH11t3B+brNwqG078WpxMHT0M/euavLvjwvQWNjb3VudERCTmFtZT48QWNjb3VudERCQmFuaz7Jvbart9bQ0DwvQWNjb3VudERCQmFuaz48VHJueFRpbWU+MjAxMS03LTQgMTA6NDk6NDk8L1RybnhUaW1lPjxUcm54U3RhdHVzPjI8L1RybnhTdGF0dXM+PFJldHVybkNvZGU+MDAwMDwvUmV0dXJuQ29kZT48L1RyeFJlc3BvbnNlPjwvTWVzc2FnZT48U2lnbmF0dXJlLUFsZ29yaXRobT5TSEExd2l0aFJTQTwvU2lnbmF0dXJlLUFsZ29yaXRobT48U2lnbmF0dXJlPndBdHJYWFVMYkkvZDdvSWhma25KNm1sb1YzL2tEdFBFWWROd2h6R0swL2VtTUZxTGlTckgvbS93d3FiakNKZnNLajUxdW1NazI0TUY1QXY0Ui94YUZnYVJlQUNwYStET0x6SE9RTjlCV3ByWUF0SDJ6VjBub1BablJQU1hIQkVpSXowYTYwTFptZkc0emVNbE82Z045bWJGYXA2dzh3VWFnOGFNR3VBYmRGOD08L1NpZ25hdHVyZT48L01TRz4=";
var certManager = new CertManager();
certManager.SetupABCPubKey("Certs/TrustPay.cer");
var result = new ResultB2BReturned(msg);
Console.WriteLine(result.Xml);
Assert.IsTrue(result.IsValid);
Assert.AreEqual(@"<MSG><Message><TrxResponse><MerchantID>337100000000075</MerchantID><CorporationCustomerNo>33999087540</CorporationCustomerNo><MerchantTrnxNo>634453730507427500</MerchantTrnxNo><TrnxSN>9011070410494940571</TrnxSN><TrnxType>FUND_TRANSFER</TrnxType><TrnxAMT>1500000</TrnxAMT><OrginalFreezeNo> </OrginalFreezeNo><FreezeNo> </FreezeNo><AccountNo>19-080201040057934</AccountNo><AccountName>杭州翔利羽绒制品有限公司</AccountName><AccountBank>浙江分行</AccountBank><AccountDBNo>15-740801040001733</AccountDBNo><AccountDBName>滨州六和隆达农牧有限公司</AccountDBName><AccountDBBank>山东分行</AccountDBBank><TrnxTime>2011-7-4 10:49:49</TrnxTime><TrnxStatus>2</TrnxStatus><ReturnCode>0000</ReturnCode></TrxResponse></Message><Signature-Algorithm>SHA1withRSA</Signature-Algorithm><Signature>wAtrXXULbI/d7oIhfknJ6mloV3/kDtPEYdNwhzGK0/emMFqLiSrH/m/wwqbjCJfsKj51umMk24MF5Av4R/xaFgaReACpa+DOLzHOQN9BWprYAtH2zV0noPZnRPSXHBEiIz0a60LZmfG4zeMlO6gN9mbFap6w8wUag8aMGuAbdF8=</Signature></MSG>", result.Xml);
}
[Test]
public void B2CTest()
{
const string msg = "PE1TRz48TWVzc2FnZT48VHJ4UmVzcG9uc2U+PFJldHVybkNvZGU+MDAwMDwvUmV0dXJuQ29kZT48RXJyb3JNZXNzYWdlPjwvRXJyb3JNZXNzYWdlPj" + "xFQ01lcmNoYW50VHlwZT5CMkM8L0VDTWVyY2hhbnRUeXBlPjxNZXJjaGFudElEPjEwMzQ1MjA4Mzk4MDQwNDwvTWVyY2hhbnRJRD48VHJ4VHlwZT5QYXlSZXN1bHQ8L1RyeFR5" + "cGU+PE9yZGVyTm8+VGVzdE9yZGVyPC9PcmRlck5vPjxBbW91bnQ+MTAwLjA8L0Ftb3VudD48QmF0Y2hObz4wMDAwMDE8L0JhdGNoTm8+PFZvdWNoZXJObz4xMjM0NTY8L1ZvdW" + "NoZXJObz48SG9zdERhdGU+MjAwOS8wOS8wODwvSG9zdERhdGU+PEhvc3RUaW1lPjEwOjU1OjUwPC9Ib3N0VGltZT48TWVyY2hhbnRSZW1hcmtzPlRoaXMgaXMgdGVzdCE8L01l" + "cmNoYW50UmVtYXJrcz48UGF5VHlwZT5QQVkwMTwvUGF5VHlwZT48Tm90aWZ5VHlwZT4wPC9Ob3RpZnlUeXBlPjwvVHJ4UmVzcG9uc2U+PC9NZXNzYWdlPjxTaWduYXR1cmUtQWx" + "nb3JpdGhtPlNIQTF3aXRoUlNBPC9TaWduYXR1cmUtQWxnb3JpdGhtPjxTaWduYXR1cmU+SVE4Z2pFSlRvK0FXQWxqWGVhcVVwdW43Z1JCNnNWdEhRSS9pNFdqUTNISExqZmphMT" + "F3RE5VRVUyVzBVRUNsQnp5RFZuc0tRUHE2MmliM21YRjgrSnJZTWdpYW53WDNBNlRJbkxXMXJQTldVV1AwNGl5UVIvTUxuMHNaTjJ1S2JFbU5SWXRURjNPQ0lsTHFEblppYk1tS" + "EZPTzhnektneVBxeEtaUkRRaHRZPTwvU2lnbmF0dXJlPjwvTVNHPg==";
;
var certManager = new CertManager();
certManager.SetupABCPubKey("Certs/TrustPay.cer");
var result = new ResultB2CReturned(msg);
Assert.IsTrue(result.IsValid);
Console.WriteLine(result.Xml);
Assert.AreEqual(@"<MSG><Message><TrxResponse><ReturnCode>0000</ReturnCode><ErrorMessage></ErrorMessage><ECMerchantType>B2C</ECMerchantType><MerchantID>103452083980404</MerchantID><TrxType>PayResult</TrxType><OrderNo>TestOrder</OrderNo><Amount>100.0</Amount><BatchNo>000001</BatchNo><VoucherNo>123456</VoucherNo><HostDate>2009/09/08</HostDate><HostTime>10:55:50</HostTime><MerchantRemarks>This is test!</MerchantRemarks><PayType>PAY01</PayType><NotifyType>0</NotifyType></TrxResponse></Message><Signature-Algorithm>SHA1withRSA</Signature-Algorithm><Signature>IQ8gjEJTo+AWAljXeaqUpun7gRB6sVtHQI/i4WjQ3HHLjfja11wDNUEU2W0UEClBzyDVnsKQPq62ib3mXF8+JrYMgianwX3A6TInLW1rPNWUWP04iyQR/MLn0sZN2uKbEmNRYtTF3OCIlLqDnZibMmHFOO8gzKgyPqxKZRDQhtY=</Signature></MSG>", result.Xml);
}
}
}

+ 153
- 0
test/Test.cs View File

@ -0,0 +1,153 @@
using System;
using System.IO;
using System.IO.Compression;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading;
using NUnit.Framework;
namespace BWP.ABCClient
{
[TestFixture]
public class Test
{
[Test]
public void B2BMockWebServer()
{
new MockWebServer("http://localhost:5000/", Encoding.UTF8, Encoding.UTF8, false);
Thread.Sleep(300000);
}
[Test]
public void RSASendReveive()
{
const string original = "message that will be sent";
Sender mySender = new Sender();
Receiver myReceiver = new Receiver();
byte[] toEncrypt = Encoding.Default.GetBytes(original);
byte[] encrypted = mySender.EncryptData(myReceiver.PublicKey, toEncrypt);
byte[] signature = mySender.HashAndSign(encrypted);
Console.WriteLine("Original: {0}", original);
if (myReceiver.VerifyHash(mySender.PublicKey, encrypted, signature)) {
myReceiver.DecryptData(encrypted);
} else {
Console.WriteLine("Invalid signature");
}
}
[Test]
public void TryReadPfx()
{
try {
X509Store store = new X509Store("MY", StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
X509Certificate2Collection collection = store.Certificates;
X509Certificate2Collection fcollection = collection.Find(X509FindType.FindByTimeValid, DateTime.Now, false);
X509Certificate2Collection scollection = X509Certificate2UI.SelectFromCollection(fcollection, "Test Certificate Select", "Select a certificate from the following list to get information on that certificate", X509SelectionFlag.MultiSelection);
Console.WriteLine("Number of certificates: {0}{1}", scollection.Count, Environment.NewLine);
foreach (X509Certificate2 x509 in scollection) {
byte[] rawdata = x509.RawData;
Console.WriteLine("Content Type: {0}{1}", X509Certificate2.GetCertContentType(rawdata), Environment.NewLine);
Console.WriteLine("Friendly Name: {0}{1}", x509.FriendlyName, Environment.NewLine);
Console.WriteLine("Certificate Verified?: {0}{1}", x509.Verify(), Environment.NewLine);
Console.WriteLine("颁发给: {0}{1}", x509.Subject, Environment.NewLine);
Console.WriteLine("Simple Name: {0}{1}", x509.GetNameInfo(X509NameType.SimpleName, true), Environment.NewLine);
Console.WriteLine("Signature Algorithm: {0}{1}", x509.SignatureAlgorithm.FriendlyName, Environment.NewLine);
Console.WriteLine("Private Key: {0}{1}", x509.PrivateKey.ToXmlString(false), Environment.NewLine);
Console.WriteLine("Public Key: {0}{1}", x509.PublicKey.Key.ToXmlString(false), Environment.NewLine);
Console.WriteLine("Certificate Archived?: {0}{1}", x509.Archived, Environment.NewLine);
Console.WriteLine("Length of Raw Data: {0}{1}", x509.RawData.Length, Environment.NewLine);
X509Certificate2UI.DisplayCertificate(x509);
x509.Reset();
}
store.Close();
} catch (CryptographicException) {
Console.WriteLine("Information could not be written out for this certificate.");
}
}
[Test]
public void VerifySignedByABC()
{
string returnMsg = "<Merchant><ECMerchantType>B2C</ECMerchantType><MerchantID>103452083980409</MerchantID></Merchant><TrxResponse><ReturnCode>0000</ReturnCode><ErrorMessage>交易成功</ErrorMessage><TrxType>PayReq</TrxType><OrderNo>634333823922218745</OrderNo><PaymentURL>https://easyabc.95599.cn/b2c/NotCheckStatus/PaymentModeAct.ebf?TOKEN=12977568750460430844</PaymentURL><OrderAmount>254011</OrderAmount></TrxResponse>";
string ABCSignature = "3+0sE/7PTfYfHYqHUwWoFzUVvr0h2HUaXpq5pr+r3+DhyvufhVUPq1We9a0E+DzqzwnW3ZD5EYLhA204o4oRiLauEzM1cj8ddXZJGAtk5ftv1OGVCV+bvts/Ei9FQp8ws5b7pNqAvIyoSbIToartR7AJ42RJsT5DxXBtFy0Y2oQ=";
var cert = new X509Certificate2("Certs/TrustPay.cer");
var publicKey = (RSACryptoServiceProvider)cert.PublicKey.Key;
var singature = Convert.FromBase64String(ABCSignature);
var msgHash = new SHA1Managed().ComputeHash(Encoding.Default.GetBytes(returnMsg));
Assert.IsTrue(publicKey.VerifyHash(msgHash, cert.SignatureAlgorithm.Value, singature));
}
}
internal class Sender
{
private readonly RSACryptoServiceProvider _privateKey;
private readonly RSACryptoServiceProvider _publicKey;
public RSACryptoServiceProvider PublicKey
{
get { return _publicKey; }
}
public Sender()
{
var cert = new X509Certificate2("Certs/asB.pfx", "14814622");
_privateKey = (RSACryptoServiceProvider)cert.PrivateKey;
_publicKey = (RSACryptoServiceProvider)cert.PublicKey.Key;
}
public byte[] HashAndSign(byte[] encryptedData)
{
byte[] hashedData = new SHA1Managed().ComputeHash(encryptedData);
return _privateKey.SignHash(hashedData, CryptoConfig.MapNameToOID("SHA1"));
}
public byte[] EncryptData(RSACryptoServiceProvider receiverPublicKey, byte[] toEncrypt)
{
return receiverPublicKey.Encrypt(toEncrypt, false);
}
}
internal class Receiver
{
private readonly RSACryptoServiceProvider _privateKey;
private readonly RSACryptoServiceProvider _publicKey;
public RSACryptoServiceProvider PublicKey
{
get { return _publicKey; }
}
public Receiver()
{
var cert = new X509Certificate2("Certs/asC.pfx", "14814622");
_privateKey = (RSACryptoServiceProvider)cert.PrivateKey;
_publicKey = (RSACryptoServiceProvider)cert.PublicKey.Key;
}
//Manually performs hash and then verifies hashed value.
public bool VerifyHash(RSACryptoServiceProvider senderPublicKey, byte[] encryptedData, byte[] signature)
{
byte[] hashedData = new SHA1Managed().ComputeHash(encryptedData);
return senderPublicKey.VerifyHash(hashedData, CryptoConfig.MapNameToOID("SHA1"), signature);
}
//Decrypt using the private key data.
public void DecryptData(byte[] encryptedData)
{
byte[] fromEncrypt = _privateKey.Decrypt(encryptedData, false);
string roundTrip = Encoding.Default.GetString(fromEncrypt);
Console.WriteLine("RoundTrip: {0}", roundTrip);
}
}
}

+ 110
- 0
test/test.csproj View File

@ -0,0 +1,110 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{9299FD15-70F9-4E71-9AB8-DC0C081FB7B5}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>BWP.ABCClient</RootNamespace>
<AssemblyName>test</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<KeyContainerName>BwpApp</KeyContainerName>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="nunit.framework, Version=2.5.7.10213, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="System">
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="System.Core">
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="System.Security">
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="System.Xml.Linq">
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="System.Data.DataSetExtensions">
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="Microsoft.CSharp">
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="System.Data">
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="System.Xml">
<SpecificVersion>False</SpecificVersion>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\..\..\version\tslib_version.cs">
<Link>tslib_version.cs</Link>
</Compile>
<Compile Include="B2BReceivingPaymentTest.cs" />
<Compile Include="BusinessTest.cs" />
<Compile Include="LogTest.cs" />
<Compile Include="ResultReturnedTest.cs" />
<Compile Include="RequestTest.cs" />
<Compile Include="CertManagerTest.cs" />
<Compile Include="MockWebServer.cs" />
<Compile Include="MsgUtilTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RSAServiceTest.cs" />
<Compile Include="Test.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\BWP.ABCClient\BWP.ABCClient.csproj">
<Project>{22FEFA9B-1D58-4E8A-A1FF-49CEED62C355}</Project>
<Name>BWP.ABCClient</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="Certs\asB.pfx">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="Certs\asC.pfx">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="Certs\PDM.pfx">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="Certs\TrustPay.cer">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="Certs\TrustPayTest.cer">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

Loading…
Cancel
Save