重要通知:BrnShop企業版NOSQL設計(基於Redis)已經開源!源碼內置於最新版的BrnShop中,感興趣的園友能夠去下載來看看。官網地址:www.brnshop.com。html
好了如今進入今天的正題:自定義插件。上一講中咱們已經闡述了BrnShop插件的工做機制,如今咱們詳細介紹下如何自定義插件。首先BrnShop的插件從功能上分爲三類,分別是:數組
對應的接口文件(注:位於BrnShop.Core項目的Plugin/Base文件夾中)依次以下:安全
如今咱們依次介紹下各個接口,首先登場的是IOAuthPlugin接口。先看它的定義:服務器
/// <summary> /// BrnShop開放受權插件接口 /// </summary> public interface IOAuthPlugin : IPlugin { /// <summary> /// 登錄控制器 /// </summary> string LoginController { get; } /// <summary> /// 登錄動做方法 /// </summary> string LoginAction { get; } /// <summary> /// 登錄路由數據 /// </summary> RouteValueDictionary LoginRouteValues { get; } }
對於一個開放受權插件來講,它只須要向主應用程序提供本身的一個登錄地址就能夠,至於怎麼受權驗證等那都是插件本身的事情了。因此IOAuthPlugin接口內容僅僅是登錄地址的mvc3要素(控制器名,動做方法名,路由數據)就能夠了,以QQ受權登錄爲例:mvc
接下來是IPayPlugin接口,代碼以下:框架
/// <summary>
/// BrnShop支付插件接口
/// </summary>
public interface IPayPlugin : IPlugin
{
/// <summary>
/// 付款方式(0表明貨到付款,1表明在線付款,2表明線下付款)
/// </summary>
int PayMode { get; }異步
/// <summary>
/// 是否容許帳戶充值(只對在線付款有效)
/// </summary>
bool AllowRecharge { get; }ide
/// <summary>
/// 支付返回控制器
/// </summary>
string ReturnController { get; }函數
/// <summary>
/// 支付返回動做方法
/// </summary>
string ReturnAction { get; }工具
/// <summary>
/// 支付返回路由數據
/// </summary>
RouteValueDictionary ReturnRouteValues { get; }
/// <summary>
/// 支付通知控制器
/// </summary>
string NotifyController { get; }
/// <summary>
/// 支付通知動做方法
/// </summary>
string NotifyAction { get; }
/// <summary>
/// 支付通知路由數據
/// </summary>
RouteValueDictionary NotifyRouteValues { get; }
/// <summary>
/// 得到支付手續費
/// </summary>
/// <param name="productAmount">商品合計</param>
/// <param name="buyTime">購買時間</param>
/// <param name="partUserInfo">購買用戶</param>
/// <returns></returns>
decimal GetPayFee(decimal productAmount, DateTime buyTime, PartUserInfo partUserInfo);
/// <summary>
/// 若是付款方式爲在線付款則返回付款請求的url,不然返回空字符串
/// </summary>
/// <param name="returnUrl">返回url</param>
/// <param name="notifyUrl">通知url</param>
/// <param name="pluginInfo">插件信息</param>
/// <param name="partUserInfo">購買用戶</param>
/// <param name="orderInfo">訂單信息</param>
/// <returns></returns>
string GetRequestUrl(string returnUrl, string notifyUrl, PluginInfo pluginInfo, PartUserInfo partUserInfo, OrderInfo orderInfo);
}
/// <summary> /// BrnShop支付插件接口 /// </summary> public interface IPayPlugin : IPlugin { /// <summary> /// 付款方式(0表明貨到付款,1表明在線付款,2表明線下付款) /// </summary> int PayMode { get; } /// <summary> /// 是否容許帳戶充值(只對在線付款有效) /// </summary> bool AllowRecharge { get; } /// <summary> /// 支付返回控制器 /// </summary> string ReturnController { get; } /// <summary> /// 支付返回動做方法 /// </summary> string ReturnAction { get; } /// <summary> /// 支付返回路由數據 /// </summary> RouteValueDictionary ReturnRouteValues { get; } /// <summary> /// 支付通知控制器 /// </summary> string NotifyController { get; } /// <summary> /// 支付通知動做方法 /// </summary> string NotifyAction { get; } /// <summary> /// 支付通知路由數據 /// </summary> RouteValueDictionary NotifyRouteValues { get; } /// <summary> /// 得到支付手續費 /// </summary> /// <param name="productAmount">商品合計</param> /// <param name="buyTime">購買時間</param> /// <param name="partUserInfo">購買用戶</param> /// <returns></returns> decimal GetPayFee(decimal productAmount, DateTime buyTime, PartUserInfo partUserInfo); /// <summary> /// 若是付款方式爲在線付款則返回付款請求的url,不然返回空字符串 /// </summary> /// <param name="returnUrl">返回url</param> /// <param name="notifyUrl">通知url</param> /// <param name="pluginInfo">插件信息</param> /// <param name="partUserInfo">購買用戶</param> /// <param name="orderInfo">訂單信息</param> /// <returns></returns> string GetRequestUrl(string returnUrl, string notifyUrl, PluginInfo pluginInfo, PartUserInfo partUserInfo, OrderInfo orderInfo); }
成員比較多,咱們分類來看就清晰了:
最後咱們來看下IShipPlugin接口,代碼以下:
/// <summary> /// BrnShop配送插件接口 /// </summary> public interface IShipPlugin : IPlugin { /// <summary> /// 得到配送費用 /// </summary> /// <param name="totalWeight">訂單總重量</param> /// <param name="productAmount">商品合計</param> /// <param name="buyTime">購買時間</param> /// <param name="shipRegionId">收貨區域</param> /// <param name="partUserInfo">購買用戶</param> /// <returns></returns> decimal GetShipFee(int totalWeight, decimal productAmount, DateTime buyTime, int shipRegionId, PartUserInfo partUserInfo); }
這個接口比較簡單,只是提供一個計算配送費用的成員。
補充說明一下:以上3個接口都繼承自IPlugin,這個接口提供後臺配置地址mvc3要素,只在BrnShop.Web.Admin項目中的插件配置視圖中使用,具體以下:
@if (Model.ConfigRouteValues == null) { @Html.Action(Model.ConfigAction, Model.ConfigController) } else { @Html.Action(Model.ConfigAction, Model.ConfigController, Model.ConfigRouteValues) }
下面咱們以支付寶插件爲例來說解下如何自定義一個插件。
首先新建一個ASP.NET MVC3應用程序並引用須要的程序集,根據上一篇講解咱們知道須要修改非.net自帶程序集的複製到本地屬性和項目生成屬性。具體以下圖:
至此咱們的項目基本框架已經搭好了。如今咱們須要添加一個插件說明文件(注:此文件爲必須文件且文件名稱必須爲PluginInfo.config,還有不要忘記修改它的複製屬性)。內容以下:
<?xml version="1.0" encoding="utf-8"?> <PluginInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <SystemName>alipay</SystemName> <FriendlyName>支付寶</FriendlyName> <ClassFullName>BrnShop.PayPlugin.Alipay.PluginService,BrnShop.PayPlugin.Alipay</ClassFullName> <Folder>BrnShop.PayPlugin.Alipay</Folder> <Description>阿里巴巴旗下支付工具</Description> <Type>1</Type> <Author>brnshop</Author> <Version>1.0</Version> <SupVersion>1.0.0</SupVersion> <DisplayOrder>3</DisplayOrder> <IsDefault>0</IsDefault> </PluginInfo>
這個文件是BrnShop.Core項目中的PluginInfo序列化文件,因此節點說明請參考下面代碼:
/// <summary>
/// 插件信息類
/// </summary>
public class PluginInfo : IComparable
{
private string _systemname = "";//插件系統名稱(必須具備惟一性)
private string _friendlyname = "";//插件友好名稱
private string _classfullname = "";//插件控制器
private string _folder = "";//插件目錄
private string _description = "";//插件描述
private int _type = 0;//插件類型(0表明開放受權插件,1表明支付插件,2表明配送插件)
private string _author = "";//插件做者
private string _version = "";//插件版本
private string _supversion = "";//插件支持的BrnShop版本
private int _displayOrder = 0;//插件順序
private int _isdefault = 0;//是不是默認插件
/// <summary>
/// 插件系統名稱
/// </summary>
public string SystemName
{
get { return _systemname; }
set { _systemname = value; }
}
/// <summary>
/// 插件友好名稱
/// </summary>
public string FriendlyName
{
get { return _friendlyname; }
set { _friendlyname = value; }
}
/// <summary>
/// 插件類型名稱
/// </summary>
public string ClassFullName
{
get { return _classfullname; }
set { _classfullname = value; }
}
/// <summary>
/// 插件目錄
/// </summary>
public string Folder
{
get { return _folder; }
set { _folder = value; }
}
/// <summary>
/// 插件描述
/// </summary>
public string Description
{
get { return _description; }
set { _description = value; }
}
/// <summary>
/// 插件類型(0表明開放受權插件,1表明支付插件,2表明配送插件)
/// </summary>
public int Type
{
get { return _type; }
set { _type = value; }
}
/// <summary>
/// 插件做者
/// </summary>
public string Author
{
get { return _author; }
set { _author = value; }
}
/// <summary>
/// 插件版本
/// </summary>
public string Version
{
get { return _version; }
set { _version = value; }
}
/// <summary>
/// 插件支持的BrnShop版本
/// </summary>
public string SupVersion
{
get { return _supversion; }
set { _supversion = value; }
}
/// <summary>
/// 插件順序
/// </summary>
public int DisplayOrder
{
get { return _displayOrder; }
set { _displayOrder = value; }
}
/// <summary>
/// 是不是默認插件
/// </summary>
public int IsDefault
{
get { return _isdefault; }
set { _isdefault = value; }
}
/// <summary>
/// 插件實例
/// </summary>
private IPlugin _instance = null;
/// <summary>
/// 插件實例
/// </summary>
[XmlIgnoreAttribute]
public IPlugin Instance
{
get
{
if (_instance == null)
{
try
{
_instance = (IPlugin)Activator.CreateInstance(System.Type.GetType(ClassFullName, false, true));
}
catch (Exception ex)
{
throw new BSPException("建立插件:" + _classfullname + "的實例失敗", ex);
}
}
return _instance;
}
}
public int CompareTo(object obj)
{
PluginInfo info = (PluginInfo)obj;
if (this.DisplayOrder > info.DisplayOrder)
return 1;
else if (this.DisplayOrder < info.DisplayOrder)
return -1;
else
return 0;
}
}
/// <summary> /// 插件信息類 /// </summary> public class PluginInfo : IComparable { private string _systemname = "";//插件系統名稱(必須具備惟一性) private string _friendlyname = "";//插件友好名稱 private string _classfullname = "";//插件控制器 private string _folder = "";//插件目錄 private string _description = "";//插件描述 private int _type = 0;//插件類型(0表明開放受權插件,1表明支付插件,2表明配送插件) private string _author = "";//插件做者 private string _version = "";//插件版本 private string _supversion = "";//插件支持的BrnShop版本 private int _displayOrder = 0;//插件順序 private int _isdefault = 0;//是不是默認插件 /// <summary> /// 插件系統名稱 /// </summary> public string SystemName { get { return _systemname; } set { _systemname = value; } } /// <summary> /// 插件友好名稱 /// </summary> public string FriendlyName { get { return _friendlyname; } set { _friendlyname = value; } } /// <summary> /// 插件類型名稱 /// </summary> public string ClassFullName { get { return _classfullname; } set { _classfullname = value; } } /// <summary> /// 插件目錄 /// </summary> public string Folder { get { return _folder; } set { _folder = value; } } /// <summary> /// 插件描述 /// </summary> public string Description { get { return _description; } set { _description = value; } } /// <summary> /// 插件類型(0表明開放受權插件,1表明支付插件,2表明配送插件) /// </summary> public int Type { get { return _type; } set { _type = value; } } /// <summary> /// 插件做者 /// </summary> public string Author { get { return _author; } set { _author = value; } } /// <summary> /// 插件版本 /// </summary> public string Version { get { return _version; } set { _version = value; } } /// <summary> /// 插件支持的BrnShop版本 /// </summary> public string SupVersion { get { return _supversion; } set { _supversion = value; } } /// <summary> /// 插件順序 /// </summary> public int DisplayOrder { get { return _displayOrder; } set { _displayOrder = value; } } /// <summary> /// 是不是默認插件 /// </summary> public int IsDefault { get { return _isdefault; } set { _isdefault = value; } } /// <summary> /// 插件實例 /// </summary> private IPlugin _instance = null; /// <summary> /// 插件實例 /// </summary> [XmlIgnoreAttribute] public IPlugin Instance { get { if (_instance == null) { try { _instance = (IPlugin)Activator.CreateInstance(System.Type.GetType(ClassFullName, false, true)); } catch (Exception ex) { throw new BSPException("建立插件:" + _classfullname + "的實例失敗", ex); } } return _instance; } } public int CompareTo(object obj) { PluginInfo info = (PluginInfo)obj; if (this.DisplayOrder > info.DisplayOrder) return 1; else if (this.DisplayOrder < info.DisplayOrder) return -1; else return 0; } }
接下來咱們定義一個類PluginService,並實現接口IPayPlugin,代碼以下:
/// <summary>
/// 插件服務類
/// </summary>
public class PluginService : IPayPlugin
{
/// <summary>
/// 插件配置控制器
/// </summary>
/// <value></value>
public string ConfigController
{
get { return "AdminAlipay"; }
}
/// <summary>
/// 插件配置動做方法
/// </summary>
/// <value></value>
public string ConfigAction
{
get { return "Config"; }
}
/// <summary>
/// 插件配置路由數據
/// </summary>
/// <value></value>
public RouteValueDictionary ConfigRouteValues
{
get { return new RouteValueDictionary() { { "area", "Admin" } }; }
}
/// <summary>
/// 付款方式(0表明貨到付款,1表明在線付款,2表明線下付款)
/// </summary>
/// <value></value>
public int PayMode
{
get { return 1; }
}
/// <summary>
/// 是否容許帳戶充值(只對在線付款有效)
/// </summary>
/// <value></value>
public bool AllowRecharge
{
get { return PluginUtils.GetPluginSet().AllowRecharge == 1; }
}
/// <summary>
/// 支付返回控制器
/// </summary>
/// <value></value>
public string ReturnController
{
get { return "Alipay"; }
}
/// <summary>
/// 支付返回動做方法
/// </summary>
/// <value></value>
public string ReturnAction
{
get { return "Return"; }
}
/// <summary>
/// 支付返回路由數據
/// </summary>
/// <value></value>
public RouteValueDictionary ReturnRouteValues
{
get { return null; }
}
/// <summary>
/// 支付通知控制器
/// </summary>
/// <value></value>
public string NotifyController
{
get { return "Alipay"; }
}
/// <summary>
/// 支付通知動做方法
/// </summary>
/// <value></value>
public string NotifyAction
{
get { return "Notify"; }
}
/// <summary>
/// 支付通知路由數據
/// </summary>
/// <value></value>
public RouteValueDictionary NotifyRouteValues
{
get { return null; }
}
/// <summary>
/// 得到支付手續費
/// </summary>
/// <param name="productAmount">商品合計</param>
/// <param name="buyTime">購買時間</param>
/// <param name="partUserInfo">購買用戶</param>
/// <returns></returns>
public decimal GetPayFee(decimal productAmount, DateTime buyTime, PartUserInfo partUserInfo)
{
return 0M;
}
/// <summary>
/// 若是付款方式爲在線付款則返回付款請求的url,不然返回空字符串
/// </summary>
/// <param name="notifyUrl">通知url</param>
/// <param name="returnUrl">返回url</param>
/// <param name="pluginInfo">插件信息</param>
/// <param name="partUserInfo">購買用戶</param>
/// <param name="orderInfo">訂單信息</param>
/// <returns></returns>
public string GetRequestUrl(string notifyUrl, string returnUrl, PluginInfo pluginInfo, PartUserInfo partUserInfo, OrderInfo orderInfo)
{
//支付類型,必填,不能修改
string paymentType = "1";
//服務器異步通知頁面路徑,需http://格式的完整路徑,不能加?id=123這類自定義參數
notifyUrl = string.Format("http://{0}{1}", BSPConfig.ShopConfig.SiteUrl, notifyUrl);
//頁面跳轉同步通知頁面路徑,需http://格式的完整路徑,不能加?id=123這類自定義參數,不能寫成http://localhost/
returnUrl = string.Format("http://{0}{1}", BSPConfig.ShopConfig.SiteUrl, returnUrl);
//收款支付寶賬戶
string sellerEmail = AlipayConfig.Seller;
//合做者身份ID
string partner = AlipayConfig.Partner;
//交易安全檢驗碼
string key = AlipayConfig.Key;
//商戶訂單號
string outTradeNo = orderInfo.Oid.ToString();
//訂單名稱
string subject = "";
//付款金額
string totalFee = orderInfo.SurplusMoney.ToString();
//訂單描述
string body = "";
//防釣魚時間戳,若要使用請調用類文件submit中的query_timestamp函數
string anti_phishing_key = "";
//客戶端的IP地址,非局域網的外網IP地址,如:221.0.0.1
string exter_invoke_ip = "";
//把請求參數打包成數組
SortedDictionary<string, string> sParaTemp = new SortedDictionary<string, string>();
sParaTemp.Add("partner", partner);
sParaTemp.Add("_input_charset", key);
sParaTemp.Add("service", "create_direct_pay_by_user");
sParaTemp.Add("payment_type", paymentType);
sParaTemp.Add("notify_url", notifyUrl);
sParaTemp.Add("return_url", returnUrl);
sParaTemp.Add("seller_email", sellerEmail);
sParaTemp.Add("out_trade_no", outTradeNo);
sParaTemp.Add("subject", subject);
sParaTemp.Add("total_fee", totalFee);
sParaTemp.Add("body", body);
sParaTemp.Add("anti_phishing_key", anti_phishing_key);
sParaTemp.Add("exter_invoke_ip", exter_invoke_ip);
return AlipaySubmit.BuildRequestUrl(sParaTemp, AlipayConfig.Gateway, AlipayConfig.InputCharset, AlipayConfig.SignType, AlipayConfig.Key, AlipayConfig.Code);
}
}
/// <summary> /// 插件服務類 /// </summary> public class PluginService : IPayPlugin { /// <summary> /// 插件配置控制器 /// </summary> /// <value></value> public string ConfigController { get { return "AdminAlipay"; } } /// <summary> /// 插件配置動做方法 /// </summary> /// <value></value> public string ConfigAction { get { return "Config"; } } /// <summary> /// 插件配置路由數據 /// </summary> /// <value></value> public RouteValueDictionary ConfigRouteValues { get { return new RouteValueDictionary() { { "area", "Admin" } }; } } /// <summary> /// 付款方式(0表明貨到付款,1表明在線付款,2表明線下付款) /// </summary> /// <value></value> public int PayMode { get { return 1; } } /// <summary> /// 是否容許帳戶充值(只對在線付款有效) /// </summary> /// <value></value> public bool AllowRecharge { get { return PluginUtils.GetPluginSet().AllowRecharge == 1; } } /// <summary> /// 支付返回控制器 /// </summary> /// <value></value> public string ReturnController { get { return "Alipay"; } } /// <summary> /// 支付返回動做方法 /// </summary> /// <value></value> public string ReturnAction { get { return "Return"; } } /// <summary> /// 支付返回路由數據 /// </summary> /// <value></value> public RouteValueDictionary ReturnRouteValues { get { return null; } } /// <summary> /// 支付通知控制器 /// </summary> /// <value></value> public string NotifyController { get { return "Alipay"; } } /// <summary> /// 支付通知動做方法 /// </summary> /// <value></value> public string NotifyAction { get { return "Notify"; } } /// <summary> /// 支付通知路由數據 /// </summary> /// <value></value> public RouteValueDictionary NotifyRouteValues { get { return null; } } /// <summary> /// 得到支付手續費 /// </summary> /// <param name="productAmount">商品合計</param> /// <param name="buyTime">購買時間</param> /// <param name="partUserInfo">購買用戶</param> /// <returns></returns> public decimal GetPayFee(decimal productAmount, DateTime buyTime, PartUserInfo partUserInfo) { return 0M; } /// <summary> /// 若是付款方式爲在線付款則返回付款請求的url,不然返回空字符串 /// </summary> /// <param name="notifyUrl">通知url</param> /// <param name="returnUrl">返回url</param> /// <param name="pluginInfo">插件信息</param> /// <param name="partUserInfo">購買用戶</param> /// <param name="orderInfo">訂單信息</param> /// <returns></returns> public string GetRequestUrl(string notifyUrl, string returnUrl, PluginInfo pluginInfo, PartUserInfo partUserInfo, OrderInfo orderInfo) { //支付類型,必填,不能修改 string paymentType = "1"; //服務器異步通知頁面路徑,需http://格式的完整路徑,不能加?id=123這類自定義參數 notifyUrl = string.Format("http://{0}{1}", BSPConfig.ShopConfig.SiteUrl, notifyUrl); //頁面跳轉同步通知頁面路徑,需http://格式的完整路徑,不能加?id=123這類自定義參數,不能寫成http://localhost/ returnUrl = string.Format("http://{0}{1}", BSPConfig.ShopConfig.SiteUrl, returnUrl); //收款支付寶賬戶 string sellerEmail = AlipayConfig.Seller; //合做者身份ID string partner = AlipayConfig.Partner; //交易安全檢驗碼 string key = AlipayConfig.Key; //商戶訂單號 string outTradeNo = orderInfo.Oid.ToString(); //訂單名稱 string subject = ""; //付款金額 string totalFee = orderInfo.SurplusMoney.ToString(); //訂單描述 string body = ""; //防釣魚時間戳,若要使用請調用類文件submit中的query_timestamp函數 string anti_phishing_key = ""; //客戶端的IP地址,非局域網的外網IP地址,如:221.0.0.1 string exter_invoke_ip = ""; //把請求參數打包成數組 SortedDictionary<string, string> sParaTemp = new SortedDictionary<string, string>(); sParaTemp.Add("partner", partner); sParaTemp.Add("_input_charset", key); sParaTemp.Add("service", "create_direct_pay_by_user"); sParaTemp.Add("payment_type", paymentType); sParaTemp.Add("notify_url", notifyUrl); sParaTemp.Add("return_url", returnUrl); sParaTemp.Add("seller_email", sellerEmail); sParaTemp.Add("out_trade_no", outTradeNo); sParaTemp.Add("subject", subject); sParaTemp.Add("total_fee", totalFee); sParaTemp.Add("body", body); sParaTemp.Add("anti_phishing_key", anti_phishing_key); sParaTemp.Add("exter_invoke_ip", exter_invoke_ip); return AlipaySubmit.BuildRequestUrl(sParaTemp, AlipayConfig.Gateway, AlipayConfig.InputCharset, AlipayConfig.SignType, AlipayConfig.Key, AlipayConfig.Code); } }
由於支付寶有一些須要配置的屬性要保存,例如收款支付寶賬戶等。在此咱們採用對象序列化和文件的方式來保存這些信息。首先定義一個設置信息類,代碼以下:
/// <summary>
/// 插件設置信息類
/// </summary>
public class PluginSetInfo
{
private string _partner;//合做者身份ID
private string _key;//交易安全檢驗碼
private string _seller;//收款支付寶賬戶
private int _allowrecharge;//是否容許帳戶充值
/// <summary>
/// 合做者身份ID
/// </summary>
public string Partner
{
get { return _partner; }
set { _partner = value; }
}
/// <summary>
/// 交易安全檢驗碼
/// </summary>
public string Key
{
get { return _key; }
set { _key = value; }
}
/// <summary>
/// 收款支付寶賬戶
/// </summary>
public string Seller
{
get { return _seller; }
set { _seller = value; }
}
/// <summary>
/// 是否容許帳戶充值
/// </summary>
public int AllowRecharge
{
get { return _allowrecharge; }
set { _allowrecharge = value; }
}
}
/// <summary> /// 插件設置信息類 /// </summary> public class PluginSetInfo { private string _partner;//合做者身份ID private string _key;//交易安全檢驗碼 private string _seller;//收款支付寶賬戶 private int _allowrecharge;//是否容許帳戶充值 /// <summary> /// 合做者身份ID /// </summary> public string Partner { get { return _partner; } set { _partner = value; } } /// <summary> /// 交易安全檢驗碼 /// </summary> public string Key { get { return _key; } set { _key = value; } } /// <summary> /// 收款支付寶賬戶 /// </summary> public string Seller { get { return _seller; } set { _seller = value; } } /// <summary> /// 是否容許帳戶充值 /// </summary> public int AllowRecharge { get { return _allowrecharge; } set { _allowrecharge = value; } } }
而後添加一個工具類PluginUtils來序列化和反序列化設置信息,代碼以下:
/// <summary>
/// 插件工具類
/// </summary>
public class PluginUtils
{
private static object _locker = new object();//鎖對象
private static PluginSetInfo _pluginsetinfo = null;//插件設置信息
private static string _plugindatafilepath = "/Plugins/BrnShop.PayPlugin.Alipay/PluginData.config";//數據文件路徑
/// <summary>
///得到插件設置
/// </summary>
/// <returns></returns>
public static PluginSetInfo GetPluginSet()
{
if (_pluginsetinfo == null)
{
lock (_locker)
{
if (_pluginsetinfo == null)
{
_pluginsetinfo = (PluginSetInfo)IOHelper.DeserializeFromXML(typeof(PluginSetInfo), IOHelper.GetMapPath(_plugindatafilepath));
}
}
}
return _pluginsetinfo;
}
/// <summary>
/// 保存插件設置到數據數據文件中
/// </summary>
public static void SavePluginSet(PluginSetInfo pluginSetInfo)
{
lock (_locker)
{
IOHelper.SerializeToXml(pluginSetInfo, IOHelper.GetMapPath(_plugindatafilepath));
_pluginsetinfo = null;
AlipayConfig.ReSet();
}
}
}
/// <summary> /// 插件工具類 /// </summary> public class PluginUtils { private static object _locker = new object();//鎖對象 private static PluginSetInfo _pluginsetinfo = null;//插件設置信息 private static string _plugindatafilepath = "/Plugins/BrnShop.PayPlugin.Alipay/PluginData.config";//數據文件路徑 /// <summary> ///得到插件設置 /// </summary> /// <returns></returns> public static PluginSetInfo GetPluginSet() { if (_pluginsetinfo == null) { lock (_locker) { if (_pluginsetinfo == null) { _pluginsetinfo = (PluginSetInfo)IOHelper.DeserializeFromXML(typeof(PluginSetInfo), IOHelper.GetMapPath(_plugindatafilepath)); } } } return _pluginsetinfo; } /// <summary> /// 保存插件設置到數據數據文件中 /// </summary> public static void SavePluginSet(PluginSetInfo pluginSetInfo) { lock (_locker) { IOHelper.SerializeToXml(pluginSetInfo, IOHelper.GetMapPath(_plugindatafilepath)); _pluginsetinfo = null; AlipayConfig.ReSet(); } } }
就下來就是前臺和後臺實現了。首先是後臺實現,對於後臺咱們只須要提供一個可供修改支付寶配置的子方法就好了,此子方法在上面講解"IPlugin"接口時已經給出了它的調用方式。代碼以下:
/// <summary> /// 通知調用 /// </summary> public ActionResult Notify() { SortedDictionary<string, string> sPara = AlipayCore.GetRequestPost(); if (sPara.Count > 0)//判斷是否有帶返回參數 { bool verifyResult = AlipayNotify.Verify(sPara, Request.QueryString["notify_id"], Request.QueryString["sign"], AlipayConfig.SignType, AlipayConfig.Key, AlipayConfig.Code, AlipayConfig.VeryfyUrl, AlipayConfig.Partner); if (verifyResult && (Request.QueryString["trade_status"] == "TRADE_FINISHED" || Request.QueryString["trade_status"] == "TRADE_SUCCESS"))//驗證成功 { int oid = TypeHelper.StringToInt(Request.QueryString["out_trade_no"]);//商戶訂單號 string tradeSN = Request.QueryString["trade_no"];//支付寶交易號 decimal tradeMoney = TypeHelper.StringToDecimal(Request.QueryString["total_fee"]);//交易金額 DateTime tradeTime = TypeHelper.StringToDateTime(Request.QueryString["gmt_payment"]);//交易時間 OrderInfo orderInfo = Orders.GetOrderByOid(oid); if (orderInfo.PayMode == 1 && orderInfo.SurplusMoney > 0 && orderInfo.SurplusMoney <= tradeMoney) { Orders.PayOrder(oid, OrderState.Confirming, tradeSN); OrderActions.CreateOrderAction(new OrderActionInfo() { Oid = oid, Uid = orderInfo.Uid, RealName = "本人", AdminGid = 1, AdminGTitle = "非管理員", ActionType = (int)OrderActionType.Pay, ActionTime = tradeTime, ActionDes = "你使用支付寶支付訂單成功,支付寶交易號爲:" + tradeSN }); } return new EmptyResult(); } else//驗證失敗 { return new EmptyResult(); } } else { return new EmptyResult(); } }
/// <summary> /// 後臺支付寶插件控制器類 /// </summary> public class AdminAlipayController : BaseAdminController { /// <summary> /// 配置 /// </summary> [HttpGet] [ChildActionOnly] public ActionResult Config() { ConfigModel model = new ConfigModel(); model.Partner = PluginUtils.GetPluginSet().Partner; model.Key = PluginUtils.GetPluginSet().Key; model.Seller = PluginUtils.GetPluginSet().Seller; model.AllowRecharge = PluginUtils.GetPluginSet().AllowRecharge; return View("~/Plugins/BrnShop.PayPlugin.Alipay/Views/AdminAlipay/Config.cshtml", model); } /// <summary> /// 配置 /// </summary> [HttpPost] public ActionResult Config(ConfigModel model) { if (ModelState.IsValid) { PluginSetInfo setting = new PluginSetInfo(); setting.Partner = model.Partner.Trim(); setting.Key = model.Key.Trim(); setting.Seller = model.Seller.Trim(); setting.AllowRecharge = model.AllowRecharge; PluginUtils.SavePluginSet(setting); } return RedirectToAction("List", "Plugin", new RouteValueDictionary() { { "area", "Admin" }, { "Type", "1" } }); } }
至於前臺咱們有3個方面須要去實現,第一個方面是返回調用動做方法,代碼以下:
/// <summary> /// 通知調用 /// </summary> public ActionResult Notify() { SortedDictionary<string, string> sPara = AlipayCore.GetRequestPost(); if (sPara.Count > 0)//判斷是否有帶返回參數 { bool verifyResult = AlipayNotify.Verify(sPara, Request.QueryString["notify_id"], Request.QueryString["sign"], AlipayConfig.SignType, AlipayConfig.Key, AlipayConfig.Code, AlipayConfig.VeryfyUrl, AlipayConfig.Partner); if (verifyResult && (Request.QueryString["trade_status"] == "TRADE_FINISHED" || Request.QueryString["trade_status"] == "TRADE_SUCCESS"))//驗證成功 { int oid = TypeHelper.StringToInt(Request.QueryString["out_trade_no"]);//商戶訂單號 string tradeSN = Request.QueryString["trade_no"];//支付寶交易號 decimal tradeMoney = TypeHelper.StringToDecimal(Request.QueryString["total_fee"]);//交易金額 DateTime tradeTime = TypeHelper.StringToDateTime(Request.QueryString["gmt_payment"]);//交易時間 OrderInfo orderInfo = Orders.GetOrderByOid(oid); if (orderInfo.PayMode == 1 && orderInfo.SurplusMoney > 0 && orderInfo.SurplusMoney <= tradeMoney) { Orders.PayOrder(oid, OrderState.Confirming, tradeSN); OrderActions.CreateOrderAction(new OrderActionInfo() { Oid = oid, Uid = orderInfo.Uid, RealName = "本人", AdminGid = 1, AdminGTitle = "非管理員", ActionType = (int)OrderActionType.Pay, ActionTime = tradeTime, ActionDes = "你使用支付寶支付訂單成功,支付寶交易號爲:" + tradeSN }); } return new EmptyResult(); } else//驗證失敗 { return new EmptyResult(); } } else { return new EmptyResult(); } }
/// <summary> /// 返回調用 /// </summary> public ActionResult Return() { SortedDictionary<string, string> sPara = AlipayCore.GetRequestGet(); if (sPara.Count > 0)//判斷是否有帶返回參數 { bool verifyResult = AlipayNotify.Verify(sPara, Request.QueryString["notify_id"], Request.QueryString["sign"], AlipayConfig.SignType, AlipayConfig.Key, AlipayConfig.Code, AlipayConfig.VeryfyUrl, AlipayConfig.Partner); if (verifyResult && (Request.QueryString["trade_status"] == "TRADE_FINISHED" || Request.QueryString["trade_status"] == "TRADE_SUCCESS"))//驗證成功 { int oid = TypeHelper.StringToInt(Request.QueryString["out_trade_no"]);//商戶訂單號 string tradeSN = Request.QueryString["trade_no"];//支付寶交易號 decimal tradeMoney = TypeHelper.StringToDecimal(Request.QueryString["total_fee"]);//交易金額 DateTime tradeTime = TypeHelper.StringToDateTime(Request.QueryString["notify_time"]);//交易時間 OrderInfo orderInfo = Orders.GetOrderByOid(oid); if (orderInfo.PayMode == 1 && orderInfo.SurplusMoney > 0 && orderInfo.SurplusMoney <= tradeMoney) { Orders.PayOrder(oid, OrderState.Confirming, tradeSN); OrderActions.CreateOrderAction(new OrderActionInfo() { Oid = oid, Uid = orderInfo.Uid, RealName = "本人", AdminGid = 1, AdminGTitle = "非管理員", ActionType = (int)OrderActionType.Pay, ActionTime = tradeTime, ActionDes = "你使用支付寶支付訂單成功,支付寶交易號爲:" + tradeSN }); } return RedirectToAction("PaySuccess", "Order", new RouteValueDictionary { { "oid", orderInfo.Oid } }); } else//驗證失敗 { return new EmptyResult(); } } else { return new EmptyResult(); } }
第二個方面是通知調用動做方法,代碼以下:
/// <summary> /// 通知調用 /// </summary> public ActionResult Notify() { SortedDictionary<string, string> sPara = AlipayCore.GetRequestPost(); if (sPara.Count > 0)//判斷是否有帶返回參數 { bool verifyResult = AlipayNotify.Verify(sPara, Request.QueryString["notify_id"], Request.QueryString["sign"], AlipayConfig.SignType, AlipayConfig.Key, AlipayConfig.Code, AlipayConfig.VeryfyUrl, AlipayConfig.Partner); if (verifyResult && (Request.QueryString["trade_status"] == "TRADE_FINISHED" || Request.QueryString["trade_status"] == "TRADE_SUCCESS"))//驗證成功 { int oid = TypeHelper.StringToInt(Request.QueryString["out_trade_no"]);//商戶訂單號 string tradeSN = Request.QueryString["trade_no"];//支付寶交易號 decimal tradeMoney = TypeHelper.StringToDecimal(Request.QueryString["total_fee"]);//交易金額 DateTime tradeTime = TypeHelper.StringToDateTime(Request.QueryString["gmt_payment"]);//交易時間 OrderInfo orderInfo = Orders.GetOrderByOid(oid); if (orderInfo.PayMode == 1 && orderInfo.SurplusMoney > 0 && orderInfo.SurplusMoney <= tradeMoney) { Orders.PayOrder(oid, OrderState.Confirming, tradeSN); OrderActions.CreateOrderAction(new OrderActionInfo() { Oid = oid, Uid = orderInfo.Uid, RealName = "本人", AdminGid = 1, AdminGTitle = "非管理員", ActionType = (int)OrderActionType.Pay, ActionTime = tradeTime, ActionDes = "你使用支付寶支付訂單成功,支付寶交易號爲:" + tradeSN }); } return new EmptyResult(); } else//驗證失敗 { return new EmptyResult(); } } else { return new EmptyResult(); } }
/// <summary> /// 通知調用 /// </summary> public ActionResult Notify() { SortedDictionary<string, string> sPara = AlipayCore.GetRequestPost(); if (sPara.Count > 0)//判斷是否有帶返回參數 { bool verifyResult = AlipayNotify.Verify(sPara, Request.QueryString["notify_id"], Request.QueryString["sign"], AlipayConfig.SignType, AlipayConfig.Key, AlipayConfig.Code, AlipayConfig.VeryfyUrl, AlipayConfig.Partner); if (verifyResult && (Request.QueryString["trade_status"] == "TRADE_FINISHED" || Request.QueryString["trade_status"] == "TRADE_SUCCESS"))//驗證成功 { int oid = TypeHelper.StringToInt(Request.QueryString["out_trade_no"]);//商戶訂單號 string tradeSN = Request.QueryString["trade_no"];//支付寶交易號 decimal tradeMoney = TypeHelper.StringToDecimal(Request.QueryString["total_fee"]);//交易金額 DateTime tradeTime = TypeHelper.StringToDateTime(Request.QueryString["gmt_payment"]);//交易時間 OrderInfo orderInfo = Orders.GetOrderByOid(oid); if (orderInfo.PayMode == 1 && orderInfo.SurplusMoney > 0 && orderInfo.SurplusMoney <= tradeMoney) { Orders.PayOrder(oid, OrderState.Confirming, tradeSN); OrderActions.CreateOrderAction(new OrderActionInfo() { Oid = oid, Uid = orderInfo.Uid, RealName = "本人", AdminGid = 1, AdminGTitle = "非管理員", ActionType = (int)OrderActionType.Pay, ActionTime = tradeTime, ActionDes = "你使用支付寶支付訂單成功,支付寶交易號爲:" + tradeSN }); } return new EmptyResult(); } else//驗證失敗 { return new EmptyResult(); } } else { return new EmptyResult(); } }
第三個方面是咱們須要提供一個支付寶簡介的視圖文件,這個視圖文件在顧客支付訂單時給其展現一些支付寶的說明信息,此文件有如下幾點要求:
這個視圖文件在BrnShop.Web項目的支付展現視圖文件PayShowModel.cshtml中調用,調用方式以下:
@Html.Partial(Model.ShowView, Model.OrderInfo)
至此支付寶插件開發完成,至於其它類型的插件開發也都是大同小異。
PS:最後附上一張BrnShop開啓NOSQL先後的性能對比圖,以商品詳細頁面爲例:
開啓NOSQL前:
開啓NOSQL後:
可見性能提高仍是很明顯的。