完整教程鏈接:ASP.Net: EshineASPNet-基於ASP.Net敏捷開發開源框架
支付也是最常見功能之一了,不管是商城還是服務,從商業模式上講,一般會看一個項目離錢有多近,支付功能是2C的最直接盈利方式了。
支付機構
支付機構很多,哪些公司拿到了國家給的支付牌照不是討論範疇,主流的大家肯定都會使用到支付寶和微信支付,下面會着重講。另外還有大家可能不太熟悉的比如聯動U付、快錢、通聯、易寶等。每家支付提供的服務大同小異,一般要用到的網頁支付、移動支付、批量付款等都是有的。差別也總是有的,手續費率,服務等還是有差別。你總可能會遇到一些支付寶並不滿足的需求時,你就可能回去尋求別的第三方支付了。比如筆者此前的業務需要效仿歐美的消費方式,輸入信用卡卡面信息來支付。又或者你想在手續費上能討價還價,因爲支付寶太大了除非你的流水很大否則人家根本不會鳥你。又或者你想作爲中間平臺把收入扣除你的手續費後轉到其他賬戶,等各種金融相關的奇怪需求,都是可談的,國人就是這樣好,靈活,也是這樣不好,章法不嚴格壞事的比較多。當然這些一般程序員不需要考慮,CTO是需要掌控的,只是想說一句永遠不要只侷限在技術範疇,不閒扯了。
手續費
費率方面支付寶此前是交易的1.2%,按流水大小最低可以降到0.6%,現在中小企業能降到固定0.55%了,微信也是0.6%,其他第三方也差不多,快錢通聯0.5%,量大可談。這筆手續費會在交易成功後立刻扣除,到賬的就是扣除後的金額。別小看0.1%,每100萬流水支付機構就要收1000塊,那0.6%就是6000塊,這也不能忽視了,因爲銷售的數額裏面很大一部分是成本,這個手續費要從利潤裏面扣,考慮到稅就更復雜了。當然現在國家稅務在互聯網支付平臺的錢還不怎麼監管,主要看的是銀行流水,所以用支付寶等也提供了一個避稅的可行方式很多公司也這麼在做。未來肯定沒這空子了,連比特幣央行也會研究,怎麼讓稅務監管到支付寶只是時間的事,只是法規的出臺週期比較長。
無手續費轉賬
上面說的費率是網上商店購買產生訂單的情況,還有一種情況是沒有手續費的,那就是用戶轉賬,每個商戶都有個二維碼,在支付寶叫商戶收款碼,掃這個二維碼不會出現金額,因爲這個沒有對應某個訂單,金額自己輸入,錢到了商戶賬戶不會扣除手續費。這種方式的弊端也很明顯,需要人工去查賬,需要人工去匹配訂單。所以可以權衡0.6%的手續費高還是僱一個員工來做查賬的成本高,這個根據訂單數量實際情況考慮就行了。現在街邊小商店放的二維碼多數都是個人二維碼,也是這種轉賬形式的,小商店連發票都不開怎麼會交這0.6%的手續費對不對。
網銀支付
除了支付寶等第三方支付公司,還有當初牛逼哄哄現在也還牛逼哄哄的銀行了。網銀支付一直有,需要知道的是現在選了網銀支付其實多數最後走的還是第三方支付通道,不一定是支付寶,而且多數都不是支付寶,爲什麼呢,因爲其他小支付公司可以給到更優惠的費率。不過我們還是可以在給消費者的展示頁面顯示銀行列表,最後跳轉到的頁面也確實是銀行的支付頁面,只是收款方變成了第三方支付機構而不是你消費的商戶了。
支付限制
再說說支付限制,首先是消費者付款的限制,大多數自己不做限制,而是根據銀行的限制來。有些比如快錢單筆不超過1萬,1天不超過2萬,量大可調。支付寶單筆不超過10萬,1天不超過200萬。這個可能你會覺得一般怎麼會達到這個限制,筆者舉個例子,如果你做的是租房業務,你可能會提供年付的選項(獲得額外折扣),1個好房源可能月租金就過萬了,那麼單筆就可能超額了。至於玉石字畫奢侈品這些那就更可能超了。
然後是商戶賬號轉出的限制,多數無金額限制,支付寶限制每天限額500萬,快錢限制只能提現到對公賬戶。多數也沒有提現手續費,支付寶當日到賬會有0.2%手續費,最低2元最高25元,次日到賬不收。還沒完,這些不能都是人工操作吧,如果要自動操作那就需要對接API接口了,API付款,快錢2元每筆,通聯2.5元每筆,易寶5000以下本地1元異地5.5元,支付寶單筆超過2萬收0.15%,最低2元最高25元。都不大一樣,自行比較。
支付寶與微信支付
一家阿里一家騰訊,淵源也挺深的,馬雲創阿里的時候找馬化騰投資沒投,看不看好的原因還是估值原因還是佔股份額原因就不究了可能都有。騰訊很牛的,騰訊最牛的就是抄(筆者說的是過去,現在也創新也投資),抄的都青出於藍而勝於藍,不過也有不成功的,微博輸給新浪,財付通輸給支付寶,現在微信支付纔算不錯。當然也有阿里想去社交分一杯羹的沒成功。微信支付背後也綁的是財付通,個人感覺支付還是支付寶做的比較好,純個人意見勿噴。
接口對接
每家做支付的都提供完善的接口文檔和使用範例等,對接是挺容易的一件事情,無非就是修改一下商戶號,密鑰等的參數,而這些其實都是簽約的產出,屬於商務部分,但是過程中也可能涉及到填寫域名,ip等小部分技術參數的,屬於業務和技術共同參與的部分。這裏不會把接口文檔的代碼貼出來,每家也不一樣,不過需要提一樣跟支付關聯的數據庫設計。我們的訂單數據庫必須預留字段來存儲從支付機構返回回來的支付號碼,支付日期等數據,這樣後期不管人工還是自動查賬纔好有個依據。如果計劃對接多個第三方支付,那麼每個支付機構都有對應的字段,當然也可以只用1個公用的字段用JSON方式存儲,可以自行在篩選便利性和數據結構複雜性上權衡。必定要修改的就是訂單狀態字段了,支付端口會在支付完成後多次推送支付成功消息,接口在收到後要首先檢查訂單狀態是否已經處理了這個支付消息,如果是就忽略,否則執行相應的操作,比如修改訂單狀態爲付款成功,發送通知短信,啓動配貨流程等。
這裏拿支付寶即時到賬產品做個例子。通常我們會把notify_url和return_url等寫在Web.Config來讀取,首先引用支付寶Com.Alipay,然後把訂單信息存入Dictionary,包括上面的notify_url、return_url、主題(通常訂單不會有名稱,可以設一個通用名稱比如Eshine精選,或者多個商品就挑選第一個商品名作爲主題)、訂單號(自己的訂單號,不是後面在支付寶的支付訂單號)、總價(注意不同第三方支付的標準不一樣,有些以分爲單位,即整形,有些以元爲單位,即浮點型)、內容(空着就好了)、防釣魚時間戳等,如果是選擇了網銀支付還要把銀行的代碼填進去,這個比較通用,最後其實是生成了一個用來Post的Form和一條JS用來自動執行Post。
public void goalipay(string out_trade_no, string total_fee, string paytype)
{
//支付類型
string payment_type = "1";
string notify_url = System.Configuration.ConfigurationManager.AppSettings["notify_url"];
string return_url = System.Configuration.ConfigurationManager.AppSettings["return_url"];
string seller_email = "[email protected]";
//訂單名稱
string subject = (string)GetGlobalResourceObject("GResource", "mpselection");
//訂單描述
string body = "";
//商品展示地址
string show_url = "";
//防釣魚時間戳
string anti_phishing_key = Submit.Query_timestamp();
//若要使用請調用類文件submit中的query_timestamp函數
//客戶端的IP地址
string exter_invoke_ip = "";
//非局域網的外網IP地址,如:221.0.0.1
//把請求參數打包成數組
SortedDictionary<string, string> sParaTemp = new SortedDictionary<string, string>();
sParaTemp.Add("partner", Config.Partner);
sParaTemp.Add("_input_charset", Config.Input_charset.ToLower());
sParaTemp.Add("service", "create_direct_pay_by_user");
sParaTemp.Add("payment_type", payment_type);
sParaTemp.Add("notify_url", notify_url);
sParaTemp.Add("return_url", return_url);
sParaTemp.Add("seller_email", seller_email);
sParaTemp.Add("out_trade_no", out_trade_no);
sParaTemp.Add("subject", subject);
sParaTemp.Add("total_fee", total_fee);
sParaTemp.Add("body", body);
if (paytype != "alipay")
{
sParaTemp.Add("paymethod", "bankPay");
sParaTemp.Add("defaultbank", paytype.Substring(7, paytype.Length - 7));
}
sParaTemp.Add("show_url", show_url);
sParaTemp.Add("anti_phishing_key", anti_phishing_key);
sParaTemp.Add("exter_invoke_ip", exter_invoke_ip);
//建立請求
string sHtmlText = Submit.BuildRequest(sParaTemp, "get", "確認");
Response.Write(sHtmlText);
}
上面的Submit是支付寶的類裏面的。這段代碼展示了訂單提交到支付寶的過程,從這一刻起頁面就跳轉到支付寶網站了,也就是不在你自己的網站頁面了,爲避免用戶沒有完成付款卻無法跳轉回到你的網站,這個付款頁面應該是一個新窗口,但不是JS打開的新窗口,因爲會被瀏覽器攔截,這樣不管付款成功不成功,用戶還能瀏覽你的網站,可以去我的訂單頁面重新支付。
支付成功後的處理這裏展示一個樣例,最終按照實際情況處理。
if (verifyResult)//驗證成功
{
orders.orderID = int.Parse(Request.QueryString["out_trade_no"]);
orders = ob.getorders(orders);
if (orders != null)
{
orders.payRefNum = Request.QueryString["trade_no"];
orders.payNote = Request.QueryString["trade_status"];
if (Request.Form["trade_status"] == "TRADE_FINISHED")
{
//判斷該筆訂單是否在商戶網站中已經做過處理
//如果沒有做過處理,根據訂單號(out_trade_no)在商戶網站的訂單系統中查到該筆訂單的詳細,並執行商戶的業務程序
//如果有做過處理,不執行商戶的業務程序
if (orders.orderStatus != "付款完成")
{
orders.orderStatus = "付款完成";
PublicClass pc = new PublicClass();
orders = pc.doshop_eticket(orders);
}
}
else if (Request.Form["trade_status"] == "TRADE_SUCCESS")
{
}
ob.Update(orders);
}
Response.Write("success"); //請不要修改或刪除
}
上面這段代碼是放在notify_url裏面的在驗證成功後首先根據返回回來的訂單號在自己的數據庫把訂單找出來,如果找到了,如果沒有處理過,那麼把支付寶訂單號、支付狀態等存進去,修改付款訂單爲付款完成,並做後續處理。
結語
最開始大篇幅的內容是想共勉不要把眼光僅侷限在技術,技術是爲業務服務的。
本教程代碼參考
EshineASPNet\Web\payment.aspx
EshineASPNet\Web\notify_url.aspx