继续我们的Unity 1.2使用初探,在上节"Unity 1.2使用初探(1"中,我们主要编码的形式展示了Unity的编码方式实现。下面我们讲讨论使用配置文件实现。

这里我们继续使用上节的代码:

namespace DailyPractice.UnityEx

{

public interface ILogService

{

void Write(string message);

}

 

public class CnsLogService: ILogService

{

#region ILogService 成员

 

public void Write(string message) {

Console.WriteLine(String.Format("Cns-exception msg:{0}", message));

}

#endregion

}

 

public class DataLogService:ILogService

{

#region ILogService 成员

 

public void Write(string message) {

DailyPractice.Utility.Log.AddLog(message);

}

#endregion

}

}

 

namespace DailyPractice.Utility

{

public class Log

{

public static void AddLog(string message) {

//insert into Log(message) values(@message)

Console.WriteLine(String.Format("Data-exception msg:{0}", message));

}

}

}

这段代码主要实现了ILogService接口,然后我们以配置文件去实现,编写如下的配置文件:

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

<configSections>

<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />

</configSections>

 

<unity>

<containers>

<container name="One">

<types>

<type type="DailyPractice.UnityEx.ILogService, DailyPractice.UnityEx"

mapTo="DailyPractice.UnityEx.DataLogService, DailyPractice.UnityEx"/>

</types>

</container>

</containers>

</unity>

</configuration>

这里我进行相关的说明,configSections配置节的是unity固定配置,通过配置文件实现Unity,先要进行此配置:

<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />

然后,我们在看<unity>里面的配置:

<containers>是必须元素,其内可有多container个元素,container元素就是每一个容器的配置,它有一个可选的 name属性,用于指定容器的名称。

container元素有下列子元素: types元素 ,instances元素, extensions元素。

这里主要说type元素,在文档中有这么一句:

The type element defines a type mapping for the Unity container. If you specify a name, that name is used for the type mapping. If you do not specify a name, it creates a default mapping for the specified types. You can specify a lifetime manager for each mapping. If no explicit lifetime manager is configured for a type, transient lifetime management is exercised.

大致的意思就是或type元素定义了一个指向的type,如果你指定了一个name,那么就以你指定的来mapping,否则则创建一个一个默认的mapping for the specified types,你还可以指定lifetime manager,如果你不指定,将应用transient lifetime management

mapTo是: The actual Type object for the mapTo element in the configuration file.

所以根据以上,可以知道我们是在以 DataLogService 进行 container映射。

 

然后就是代码实现了:

namespace DailyPractice.UnityEx

{

public class UnityConfigEx

{

public static void Main() {

IUnityContainer myContainer = new UnityContainer();

UnityConfigurationSection section

= (UnityConfigurationSection)ConfigurationManager.GetSection("unity");

section.Containers[0].Configure(myContainer);

 

ILogService myServiceInstance = myContainer.Resolve<ILogService>();

myServiceInstance.Write("oh,exception occured!");

}

}

}

执行结果为:

如果我们这样更改配置节:

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

<configSections>

<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />

</configSections>

 

<unity>

<containers>

<container name="One">

<types>

<type type="DailyPractice.UnityEx.ILogService, DailyPractice.UnityEx"

mapTo="DailyPractice.UnityEx.CnsLogService, DailyPractice.UnityEx"/>

<!--<type type="DailyPractice.UnityEx.ILogService, DailyPractice.UnityEx"

mapTo="DailyPractice.UnityEx.DataLogService, DailyPractice.UnityEx"/>-->

</types>

<instances></instances>

<extensions></extensions>

</container>

</containers>

</unity>

</configuration>

执行结果为:

如果两个都配置呢?那么我们更改配置文件:

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

<configSections>

<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />

</configSections>

 

<unity>

<containers>

<container name="One">

<types>

<type type="DailyPractice.UnityEx.ILogService, DailyPractice.UnityEx" name="cnslogger"

mapTo="DailyPractice.UnityEx.CnsLogService, DailyPractice.UnityEx"/>

<type type="DailyPractice.UnityEx.ILogService, DailyPractice.UnityEx" name="datalogger"

mapTo="DailyPractice.UnityEx.DataLogService, DailyPractice.UnityEx"/>

</types>

<instances></instances>

<extensions></extensions>

</container>

</containers>

</unity>

</configuration>

修改程序代码:

namespace DailyPractice.UnityEx

{

public class UnityConfigEx

{

public static void Main() {

IUnityContainer myContainer = new UnityContainer();

UnityConfigurationSection section

= (UnityConfigurationSection)ConfigurationManager.GetSection("unity");

section.Containers[0].Types[0].Configure(myContainer);

section.Containers[0].Types[1].Configure(myContainer);

 

IEnumerable<ILogService> myServiceInstances = myContainer.ResolveAll<ILogService>();

foreach (ILogService myServiceInstance in myServiceInstances) {

myServiceInstance.Write("haha, you have an exception 了吧!");

}

myContainer.Dispose();

}

}

}

运行结果:

这里我强调一下:配置节name="cnslogger",在刚刚开始,我没有指定了,结果报错如下

The entry ':DailyPractice.UnityEx.ILogService, DailyPractice.UnityEx' has already been added. (D:\Project\ProjectEx\DailyPractice\UnityEx\bin\Debug\DailyPractice.UnityEx.vshost.exe.config line 22)

因为Unity有以下源码

protected override object GetElementKey(ConfigurationElement element)

{

UnityTypeElement typeElement = (UnityTypeElement)element;

if (typeElement.Name == null)

{

return typeElement.TypeName;

}

 

return typeElement.Name + ":" + typeElement.TypeName;

}

如果不指定name,那么两个type在循环时就会导致GetElementKey都返回了':DailyPractice.UnityEx.ILogService, DailyPractice.UnityEx'结果,导致实例化UnityConfigurationSection异常。

指定name,那么这两次实例化分别是:

cnslogger:DailyPractice.UnityEx.ILogService, DailyPractice.UnityEx

datalogger:DailyPractice.UnityEx.ILogService, DailyPractice.UnityEx

UnityConfigurationSection即可实现正确实例化。

 

本节到此。

欢迎各位指教~~,谢谢

posted @ 2009-03-15 15:15 Kevin Zhou 阅读(1756) 评论(1) 编辑

最近赋闲在家,突然想看一点东西。

以前都有用Enterprise Library,对于PolicyInject可使项目辅助功Log,Auth等以更优雅的方式,叹其巧妙。现在微软出了Unity1.2注入容器,但是我在使用这个框架上还是个新手,所以在此学习如何应用。(下载地址: http://www.codeplex.com/unity )

下面是我的一些初步使用,主要参照在 UnityDocs,路过的各位高手哪位有比较完好的中午资料,请是否可共享一下~~;

1,第一个Demo;

以下是一个Demo:首先定义1个接口,1个实现:

 

public interface ILogService

{

void Write(string message);

}

 

public class CnsLogService: ILogService

{

#region ILogService 成员

 

public void Write(string message) {

Console.WriteLine(String.Format("Cns-exception msg:{0}", message));

}

 

#endregion

}

 

然后我们可以这样应用Unity:

public static void Main(string[] args) {

 

IUnityContainer myContainer = new UnityContainer();

myContainer.RegisterType<ILogService, CnsLogService>();

ILogService myServiceInstance = myContainer.Resolve<ILogService>();

myServiceInstance.Write("oh,exception occured!");

}

运行结果如下图:

 

2, 注入链

发现文档有这样一段内容

大体意思就是你可以注册一连串的类型。代码如上所示:

那么来实现一下:

先再实现一次ILogService

public class DataLogService:ILogService

{

#region ILogService 成员

 

public void Write(string message) {

DailyPractice.Utility.Log.AddLog(message);

}

 

#endregion

}

 

namespace DailyPractice.Utility

{

public class Log

{

public static void AddLog(string message) {

//insert into Log(message) values(@message)

Console.WriteLine(String.Format("Data-exception msg:{0}", message));

}

}

}

 

然后实现一下注册:

public static void Main(string[] args) {

IUnityContainer myContainer = new UnityContainer();

myContainer.RegisterType<ILogService, CnsLogService>()

.RegisterType<ILogService, DataLogService>();

ILogService myServiceInstance = myContainer.Resolve<ILogService>();

myServiceInstance.Write("oh,exception occured!");

 

}

结果执行为:

非常意外: CnsLogService并没有执行

然后把代码改成

public static void Main(string[] args) {

IUnityContainer myContainer = new UnityContainer();

myContainer.RegisterType<ILogService, CnsLogService>()

.RegisterType<ILogService, DataLogService>();

IEnumerable<ILogService> myServiceInstances = myContainer.ResolveAll<ILogService>();

foreach (ILogService myServiceInstance in myServiceInstances) { myServiceInstance.Write("haha, you have an exception 了吧!"); }

}

执行结果是:

什么都没有执行???

看过terrylee的blog:http://www.cnblogs.com/terrylee/archive/2008/02/21/unity-application-block-part1.html

发现还有一种实现方式,先看代码:

public static void Main(string[] args) {

IUnityContainer myContainer = new UnityContainer();

myContainer.RegisterType<ILogService, CnsLogService>("CnsLogService")

.RegisterType<ILogService, DataLogService>("DataLogService");

IEnumerable<ILogService> myServiceInstances = myContainer.ResolveAll<ILogService>();

foreach (ILogService myServiceInstance in myServiceInstances) { myServiceInstance.Write("haha, you have an exception 了吧!"); }

}

执行结果是:

执行结果正常,

所以现在就来找原因:terrylee's blog有这么一段

    除了可以获取单个对象实例之外,我们还可以一次获取容器中所有与某一接口映射的所有对象实例,但是需要依赖于在注册映射时提供的名称,如果没有指定名称,通过GetAll方法不会被获取到。

 

本次先到这里。

 

posted @ 2009-03-12 15:28 Kevin Zhou 阅读(2108) 评论(2) 编辑

上节“在线支付平台设计之Order.do (上)”中,我对Order.do的设计思想进行了初步分析,我也觉得对于Order.do来讲我谈到的内容还是很少,毕竟我的最终的目标还是希望大家能够通过我谈到到这些内容能设计一个简单的支付接口。

因为上节已经谈到Order.do的设计思想,所以这节我主要谈怎么实现,原理部分我就不在这里赘述了。

一:为什么是Order.do?

谈到Order.do,其实asp.net程序员都知道再.net下实现.do不是什么困难的事情,只需要再项目里引用URLRewriter就可以了,这里主要基于两方面的考虑:

1)Order.do掩盖了真实的.aspx扩展名,在安全性上加了一层“套”(当然这样并不能掩盖完全aspx,经过稍微检测还是可以发现真正的脚本语言~~)

2)由于URLRewriter再url重写方面对效率的影响几乎可以忽略不计,又能在安全性再加一层套,不用白不用(~~)。

3)附加谈一下URLRewriter的用法:

首先下载dll: download.microsoft.com/download/0/4/6/0463611e-a3f9-490d-a08c-877a83b797cf/MSDNURLRewriting.msi

安装并在所需要的项目里引用URLRewriter.dll

然后在web.config里配置如下

  <configSections>
    <section name="RewriterConfig" type="URLRewriter.Config.RewriterConfigSerializerSectionHandler, URLRewriter"/>    
  </configSections>

 

<RewriterConfig>
  <Rules>
    <RewriterRule>
      <LookFor>Order.do</LookFor>
      <SendTo>Order.aspx</SendTo>
    </RewriterRule>   
  </Rules>
</RewriterConfig>

 

    <httpHandlers>
      <add verb="*" path="*.do" type="URLRewriter.RewriterFactoryHandler, URLRewriter" />
    </httpHandlers>

 

然后在网站打开后访问Order.do,执行的即是Order.aspx的代码

二:接受参数是用Get、Post或者双兼容?

首先我们看一下他们之间的区别:

  1. get是从服务器上获取数据,post是向服务器传送数据。
  2. get是把参数数据队列加到提交表单的ACTION属性所指的URL中,值和表单内各个字段一一对应,在URL中可以看到。post是通过HTTP post机制,将表单内各个字段与其内容放置在HTML HEADER内一起传送到ACTION属性所指的URL地址。用户看不到这个过程。
  3. 对于get方式,服务器端用Request.QueryString获取变量的值,对于post方式,服务器端用Request.Form获取提交的数据。
  4. get传送的数据量较小,不能大于2KB。post传送的数据量较大,一般被默认为不受限制。但理论上,IIS4中最大量为80KB,IIS5中为100KB。
  5. get安全性非常低,post安全性较高。

看到get与post的区别,最后还是决定用双兼容的方式来接受数据, asp.net提供的方式是:

object obj = Request["partner_no"];

这种方式,不管对方是htm,还是jsp,抑或asp,即使php,我们都是可以兼容get与post两种方式,完善代码如下:

这里添加一个函数SaftRequest,其作用是当Request的结果为NULL的时候,返回String.Empty,否则我们直接obj.ToString()可能会报异常.

private string SafeRequest(object obj)
{
    try
    {
        return obj.ToString();
    }
    catch (Exception ex)
    {   //Log.Write(ex.GetType + ex.Message);
        return String.Empty;
    }
}

 

那么我们的Request就可以改为

string partnerNo = SafeRequest(Request["partner_no"]);

 

 三:加密需要多兼容?
 
不得不说,现在很多支付网关也好,银行也好,有些会在接口开发文档有这样一句话:“本接口暂时只支持MD5加密方式”。我想既然做支付平台,
这里我们假设是支付终端(对于支付网关多一个跳转到支付终端,然后接受支付终端的结果,最后再返回给支付方的过程),当然要再数据安全的基础上,
还要考虑平台兼容性,现在主流平台也就无非asp,asp.net,jsp,php,所以再斟酌加密类型要考虑是否各个平台是否都能实现。这里我设计的时候,
要是以MD5为主,其他的为预留。
加密:
using System.Security.Cryptography;
public abstract class Encryption
{
    public abstract string Encrypt(string oriData);
}
public class MD5Encryption : Encryption
{
    //MD5 Hash
    public override string Encrypt(string oriData)
    {
        MD5 md5 = MD5.Create();
        byte[] data = md5.ComputeHash(Encoding.Default.GetBytes(oriData));

        StringBuilder sBuilder = new StringBuilder();
        foreach (byte pd in data)
        {
            sBuilder.Append(pd.ToString("x2"));
        }
        return sBuilder.ToString();
    }
}
public class RSAEncryption : Encryption
{

    public override string Encrypt(string oriData)
    {
        //reference: ms-help://MS.MSDNQTR.v90.chs/fxref_mscorlib
        //                   /html/dcb50ce1-fd47-b47f-be48-d716093c1359.htm            
        return String.Empty;
    }
}
 

实例化

public class EncryptFactory
    {
        static Encryption encryption;

        public EncryptFactory() { }

        //Instance Factory
        public static Encryption GetEncryptInstance(string encryptType)
        {
            if (String.Compare(encryptType, "MD5", true) == 0)
            { encryption = new MD5Encryption(); }
            else if (String.Compare(encryptType, "RSA", true) == 0)
            { encryption = new RSAEncryption(); }
            else
            { encryption = null; }

            return encryption;
        }
    }

 

用法:

 protected void Page_Load(object sender, EventArgs e)
 {
     string orderNo = SafeRequest(Request["order_no"]);
     string money = SafeRequest(Request["money"]);
     string orderDate = SafeRequest(Request["order_date"]);
      string signType = SafeRequest(Request["sign_type"]);
    //...
     //参数验证(参看:四,参数合法性该如何验证?)
    string oriData = ParamsHandle(orderNo, money, orderDate, signType
        //,这里我们只需要其Bubble Sort部分
        )
        //ParamsHandle 函数在: http://www.cnblogs.com/enquan/archive/2008/12/26/1363168.html

    Encryption encryption = EncryptFactory.GetEncryptInstance(signType);
    string encryData = encryption.Encrypt(orderDate);
    
    if(String.Compare(encryData, validateKey) == 0)
    {
        //进行下一步操作
    }
}

 

四:参数合法性该如何验证?

谈到参数验证,我们都知道微软再.net framework都提供了一系列的验证方法,比如 转整形 int.TryParse(), 字符串长度验证 string.Length > X,字符串是否包含某个特殊字符,等等 string.IndexOf(“<”) >= 0 等等,但是试想一下我们如果这样验证也许就会掉入十分复杂的逻辑验证深渊,还可能出现验证漏洞,那么这里推荐大家用正则表达。

验证之前,先来细看接收参数都有什么:

1. 首先有html标签要么转化,要么直接kill掉

2. 长度是否符合我们约定的标准

3. 价格、数量等参数是否可以转整形、日期型是否为合法日期

加入我们约定在接受字符串时,仅仅允许字符、数字、下划线。示例代码如下:

 

System.Text.RegularExpressions.Regex regex = new System.Text.RegularExpressions.Regex(@"^\w+$");
if (regex.IsMatch(currencyType))
{
    //do next...
}

 

本节先到这里~~

posted @ 2009-01-10 01:53 Kevin Zhou 阅读(281) 评论(1) 编辑

     假如在线支付平台让我们来设计,就是说我们作为bank方,我们该怎样设计系统。首先,我想很简单的是,设计的支付平台至少包含两个:

Order.do(支付功能)

Query.do(历史交易查询功能)

     这节我们只谈Order.do,下面我们开始正文;

一:Order.do工作流程

    谈到支付接口,就要先看一下,支付接口Order.do的整体工作流程

    这里我们假设bank位最终的接口(不是支付网关),可以直接进行划款。为了说明bank和支付网关的不同,这里我也将支付网关的工作流程简要的用图形描述一下:

二:参数约定

    谈到参数设计,我们一定要考虑可从重用、多用性,使得我们设计的Order.do不会因为增加商户而要去重构接口,所以在参数设计上一定要周密。

这里谈一下设计思想:

(1) 为了能够供多个商家使用接口,参数应含有partner_no

(2) 为了能够区分每一笔交易,那么应该对每笔交易有order_no

(3) 当然支付接口不可以少money

(4) 还有交易日期order_date

(5) 为了交易时数据不被篡改,应该有一个加密之后的validate_key

(6) 附加说明:partner_no + order_no + order_date 必须唯一(或者前两项唯一)

当然还有一些其他的附加参数,这里我们\设计如下:

参数 长度 参数名称 是否为空 说明
partner_no 6 商户代码 not 例如:000010
order_no 50 订单号 not 例如:0001020020090101
money 16 金额 not 例如:50
date 14 订单日期 not 例如:20090105002300
currency_type 3 币种 not 例如:RMB
lang 6 语言 not 例如:GB
return_url 255 交易成功跳转的url not 例如:http://...
signtype 6 加密类型 not 例如:MD5
signkey 50 加密串 not 例如:加密后的key

三:附加功能(Notify)

     这里我主要谈谈Notify(通知),做过接口或者支付,都应该或多或少接触过支付接口的Notify。那么什么是Notify呢?这里用图展示一下:

    从图中可以看出,商家得到客户是否支付成功,就是通过客户在bank支付成功之后,然后通过bank把支付成功后的参数加密后传递给商家,商家再进行下一步处理。那么试想一下,客户在bank端支付成功后,客户的电脑突然断电了,那么bank跳转到商家的Return路子就断了。这个时候,当然也可以处理,因为支付接口还有Query.do,商家可以根据order_no + order_date 去查询客户是否已经支付,但是这个过程还需要手工去操作,十分麻烦。

    现在我们引入Notify,简单来讲,商家先给bank一个页面A,其功能就是得到客户支付后的信息,并在成功处理后Response.write(“Y”),否则Response.write(“N”)。就是客户在bank支付成功后,

    然后,bank在web前端就response.redirect到商家的return_url,然后后台也通过httpwebrequest去Notify商家的页面A,然后得到商家的页面A的“Y”之后,整个支付过程就结束;反之则间隔某个时间(比如1Min)继续Notify,直到Notify得到“Y”或者在进行某(比如50)次都得到“N”后,也结束,因为这个过程不可能死循环下去~~。

四:安全附加

    因为我们在设计支付接口,直接和RMB打交道,又是WEB的,能上网的地方都可以看到。所以安全性必须得很高。那么我们大概看一下,至少应该有以下几个限制:

(1) SQL注入攻击防范

(2) 参数合法性(是否含有html标签)

(3) Partner_no是否存在

(4) Validate_key是否正确

(5) 其他约定的限制(比如单次充值金额最大值限制)

五:代码范例

    (1)接受参数内容

        string partnerNo = SafeRequset(Request["partner_no"]);
        //...
        //public string SafeRequset(object obj) {}  
        //SafeRequset: when obj is null return String.Empty

 

   (2)判断商户是否存在

if(true == IsLeagalPartner(partnerNo))
{
    //IsLeagalPartner : judge the partnerNo is leagal...
    //
    //进行下一步的操作
}

   (3)判断加密串是否合法

string bankPrivate = bankEncrypt(partnerNo, /*...*/);  //加密Request内容
if(String.Compare(validateKey, bankPrivate, true) == 0)
{
    //进行下一步的操作
}

   这次先谈到这里,一次看的太多,太累,也不好理解。这也是我的学习习惯!

   欢迎大家pk……

posted @ 2009-01-07 21:13 Kevin Zhou 阅读(1985) 评论(5) 编辑

    因为发布了上篇“在线支付平台间交易对账之我见”,看到大家的评论,我这才发现文章没有完成,具体的就aspx部分还尚未实现。下面就对账部分的aspx部分的实现做说明,毕竟因为财务的同事在去对账的时候,不会去执行sp的,执行sp这个好像只有技术才会做的事情。

    首先我们的页面会这样设计:

开始日期:    
结束日期:  
       
shop交易数:   bank交易数:  
shop交易额:   bank交易额:  
掉单明细:      
交易号 交易日期 金额 操作
       

    然后再选择开始日期,结束日期,点击查询,实现执行sp: dep_order_check,然后把执行结果反馈到页面上:

button的执行(主要)代码如下:

protected void BtnCheck_Click(object sender, EventArgs e)
    {
        
        using(SqlConnection conn = new SqlConnection(ConfigurationManager.AppSettings["connstring"]))
        {
            SqlCommand cmd = new SqlCommand("dep_order_check", conn);
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Parameters.Add("@startdate",SqlDbType.VarChar,14);
            cmd.Parameters["@startdate"].Value = TxtStartDate.Text.ToString(); //TextBox_Start_Date
            //......
            cmd.Parameters.Add("@shopcount ",SqlDbType.Int);
            cmd.Parameters["@shopcount"].Direction = ParameterDirection.Output;
            //......

            DataSet ds = new DataSet();
            SqlDataAdapter da = new SqlDataAdapter(cmd);
            RptList.DataSource = ds;  //The ""
            RptList.DataBind();
        }
    }
 

然后执行完毕,结果体现出来为:

开始日期:    
结束日期:  
       
shop交易数: 5笔 bank交易数: 5笔
shop交易额: 240元 bank交易额: 340元
掉单明细:      
交易号 交易日期 金额 操作
10000024 20081225 100 处理

 

然后,对账的同事就会发现,shop5笔,bank6笔,但是,shop掉单1笔,总体上

shop与bank交易数:  5 + 1 = 6

shop与bank交易额: 240+100=340

这里shop里的1笔100元的掉单还需要进一步的处理。这部分我会在支付平台后续的文章中介绍。

posted @ 2009-01-03 00:06 Kevin Zhou 阅读(299) 评论(4) 编辑
摘要: 上节“在线支付平台(大多数)采用的加密方法之MD5”中大家的评论给了我很大动力,看来大家还是比较关注在线支付平台的实现。因此我决定继续写下去,可能后来的文章会包括: · 支付平台数据库设计之我见 · 支付平台间历史交易记录对账实现 · 支付平台间“掉单”的产生及处理方法 · 支付平台管理后台所需实现功能之我见 暂定以上这些内容,路过的朋友请尽情pk,大家共同提高。~~ 下面开始正文: 这里我们还...阅读全文
posted @ 2008-12-31 23:19 Kevin Zhou 阅读(1743) 评论(8) 编辑
摘要: 现在的网络安全确实不是令人很放心,那么作为“在线支付”的一些直接和RMB打交道的系统,安全性的要求就更高了,那么一般我们会采用什么样的方式来保证各个系统间(比如A方系统和支付宝等一些在线支付系统)参数传递的正确性、严密性? 闲话不多说,根据我在支付部门长期的工作经验,以及接触到的各种支付接口,总结来看,加密参数无非采用证书、md5等方法,下面谈一下md5加密方法: 假设以下是双方参数约定,由网上商...阅读全文
posted @ 2008-12-26 16:35 Kevin Zhou 阅读(3319) 评论(39) 编辑
摘要: .Net资源文件在需要本地化的项目中可以很方便的应用:1,在项目中添加资源文件Resource.resx, 双击 Resource.resx打开添加名称为“Range”,值为“值必须在"{0}"与"{1}"之间”。保存,双击 Resource.Designer.cs, 会看到以下代码:[代码]2,应用方法:在需要读取值的地方,编写以下代码:[代码]以...阅读全文
posted @ 2008-11-16 01:19 Kevin Zhou 阅读(2319) 评论(3) 编辑
摘要: 遇到此问题先需确认几个问题: 1)MS DTC是否设置正确? 2)是否启用了防火墙?是否对DTC做了例外? 3)是否做了hosts映射?是否跨网域通信?开发分布式事务,碰到一个错误“与基础事务管理器的通信失败”,去百度了一下,发现问这个问题的人甚多,但是能解决的却很少了,而且所提供的方法无法解决问题。没有办法,我只有转移到Google去搜索E文的。最后发现了三篇“有里程碑性质的文章”: http:...阅读全文
posted @ 2008-07-31 21:18 Kevin Zhou 阅读(3713) 评论(5) 编辑
摘要: <script type = "text/javascript" >var num = new Array();InitCheckbox(frm);function InitCheckbox(frm){ var chb = document.getElementsByName("checkrightsall"); for(var i=0;i<=chb.length;i++){ f...阅读全文
posted @ 2008-04-23 14:47 Kevin Zhou 阅读(75) 评论(0) 编辑