-
Notifications
You must be signed in to change notification settings - Fork 64
Implement a new gateway
GatewayBase
所有的支付网关的基类,新增加支持的支付网关必须继承自GatewayBase
。
IPaymentForm
当支付网关是通过创建一个包含订单数据的form表单来提交订单时通过实现IPaymentForm
接口来创建支付订单的html页面代码。
IPaymentUrl
当支付网关是通过创建一个包含订单数据的url来提交订单时通过实现IPaymentUrl
接口来创建订单的url。
IPaymentQRCode
当支付网关是使用二维码支付时通过实现IPaymentQRCode
接口来创建订单并获得支付二维码。
IQueryNow
通过向支付网关查询url发送需要查询的订单数据,支付网关在查询url页面输出查询结果时实现此接口。
IQueryForm
当支付网关是通过创建一个包含订单数据的form表单来查询订单时通过实现IQueryForm
接口来创建查询订单的html页面代码。查询结果跟订单支付成功时的通知返回方式一致。
IQueryUrl
当支付网关是通过创建一个包含订单数据的url来查询订单时通过实现IPaymentUrl
接口来创建订单的url。查询结果跟订单支付成功时的通知返回方式一致。
下面演示如何增加新的支付网关,我们新建一个名为DemoGateway
的新支付网关它继承自GatewayBase
基类。
public sealed class DemoGateway : GatewayBase
{
}
接着我们需要修改ICanPay.GatewayType
枚举,在ICanPay.GatewayType
枚举中增加Demo
值来表示当前网关为DemoGateway
。
public enum GatewayType
{
// 省略已存在枚举值
Demo
}
再修改DemoGateway.GatewayType
属性,让它返回新增的GatewayType.Demo
值。
public sealed class DemoGateway : GatewayBase
{
public override GatewayType GatewayType
{
get { return GatewayType.Demo }
}
}
我们还需要实现PaymentNotifyMethod
属性。订单的支付结果目前会通过2种形式返回,1
、支付网关服务器发送支付结果通知到指定url,2、将用户跳转到设置的通知url,并在查询字符串里包含支付结果。
有的支付网关可能通过服务器发送支付结果通知给你时会要求你输出一个特定的字符串用户表示已接收到支付通知,而将用户跳转到通知url时则不需要。如果没有对这2种方式做判断,在用户跳转到通知url时输出表示接收到支付网站通知的字符串时会让用户觉得很奇怪,这时应该给用户一个支付成功的提示页面,而不是奇怪的字符串。
支付通知是否由网关服务器发送,我们可以通过HttpContext.Current.Request
的RequestType
、UserAgent
2个属性来判断,因为支付网关的服务器通知的这2个属性都是固定值,而用户通过浏览器返回支付通知页面时的这2个属性会明显不同。这2个属性你可以先运行几次你需要新增的支付网关提供的Demo
,完成支付并获得相关值。
public sealed class DemoGateway : GatewayBase
{
public override PaymentNotifyMethod PaymentNotifyMethod
{
get
{
if (string.Compare(HttpContext.Current.Request.RequestType, "POST") == 0 &&
string.Compare(HttpContext.Current.Request.UserAgent, "Mozilla/4.0") == 0)
{
return PaymentNotifyMethod.ServerNotify;
}
return PaymentNotifyMethod.AutoReturn;
}
}
}
WriteSucceedFlag
方法在收到支付网关通知并验证无误时输出表示接收到支付通知的字符串,请参考相关支付网关的文档,如果支付网关没有要求则保持方法为空即可。
public sealed class DemoGateway : GatewayBase
{
public override void WriteSucceedFlag()
{
}
}
ValidateNotify
方法用于验证当前支付网关返回的支付结果。支付网关返回的支付通知数据(查询字符串、from表单)都保存在GatewayParameterData
属性中,你可以使用GetGatewayParameterValue
帮助方法来获得相应参数的值。支付结果的验证请参考相关支付网关的文档。
DemoGateway同时需要如下2个公共的构造函数,它们将用于创建生成支付订单与处理网关的支付通知。
public DemoGateway()
{
}
public DemoGateway(List<GatewayParameter> gatewayParameterData)
: base(gatewayParameterData)
{
}
为了能让新增加的DemoGateway
支付网关可以创建订单需要修改PaymentSetting
类的CreateGateway
方法,当需要创建的支付网关为Demo时返回DemoGateway
类的实例。
public class PaymentSetting
{
private GatewayBase CreateGateway(GatewayType gatewayType)
{
switch (gatewayType)
{
// 省略已存在代码
case GatewayType.Demo:
{
return new DemoGateway();
}
default:
{
return new NullGateway();
}
}
}
}
这样就能正确返回Demo支付网关的创建订单的实现了。
我们还需要让ICanPay
能够识别支付通知是否是DemoGateway
发送的。先在NotifyProcess
类中增加IsDemoGateway
方法,在IsDemoGateway
方法中我们通过判断当前支付通知中是否存在DemoGateway
的支付通知中必须包含的参数来判断当前支付通知是否是DemoGateway
支付网关发送的,相关参数请阅读相关支付网关的文档。
internal static class NotifyProcess
{
static string[] demoGatewayVerifyParmaNames= { "c_mid", "c_order", "c_orderamount", "c_ymd", "c_succmark" };
private static bool IsDemoGateway(List<GatewayParameter> gatewayParameterData)
{
return ExistParameter(demoGatewayVerifyParmaNames, gatewayParameterData);
}
}
接着修改NotifyProcess
类的GetGateway
方法,让它在当前支付通知是由DemoGateway
发送时返回DemoGateway
的实例。
internal static class NotifyProcess
{
public static GatewayBase GetGateway()
{
// 省略已存在代码
if (IsDemoGateway(gatewayParameterData))
{
return new DemoGateway(gatewayParameterData);
}
return new NullGateway(gatewayParameterData);
}
}
完成上面的这些步骤之后我们的DemoGateway
已经可以处理支付网关的支付通知了。
阅读你需要支持的支付网关的文档,当它们是通过from表单提交订单时你需要继承IPaymentForm
接口,当它们是通过url表单提交订单时你需要继承IPaymentUrl
接口。
GatewayBase
基类中提供了一些帮助方法可以让你更方便的创建支付订单,详情请阅读已实现的支付网关的代码。
阅读你需要支持的支付网关的文档,它们是否提供查询接口。如果是需要向支付网关查询url发送需要查询的订单数据,支付网关在查询url页面输出查询结果时你需要继承IQueryNow
接口。
当它们是通过from表单提交订单并且是通过与支付通知结果一样的方法返回查询时你需要继承IQueryForm
接口,当它们是通过url表单提交订单并且是通过与支付通知结果一样的方法返回查询时你需要继承IQueryUrl
接口。目前没有实现支持IQueryForm
接口跟IQueryUrl
接口这种查询方式的支付网关,之前使用这种查询方式的网银在线已经删除掉了。