一文秒懂如何搭建一個最簡單的充值系統
? ???閱讀完本文大概需要5分鐘。
目錄
- 移動支付
- 微信支付
- 支付寶支付
- 充值體系
- 最基礎的架構
- 生產環境應用
- 總結
- 參考
? ???一切都是生意。“天下熙熙皆為利來,天下攘攘皆為利往”。不知從什麽時候起,人類社會誕生了公司這樣的組織,而這個組織把人們結合在一起,產生了各種行業和商業形態,最後,公司的一切活動都變成了生意。當然,大公司有大公司的生意,小公司有小公司的買賣。
? ???過去幾年saas服務軟件大行其道,這其中就有大家熟悉的阿裏雲服務,客戶註冊賬戶+線上支付就能使用軟件。
? ???線上支付,相信大家都不陌生。支付寶,微信,雲閃付,蘋果支付等,人人都離不開支付通道。我們看到很多大公司都有自己的支付體系和金融體系。大廠,財大氣粗,有足夠的投入可以自建高可用的支付體系。那麽,如何中小微企業想在做點小生意,沒有足夠的資源自建支付體系,怎麽玩?
? ???借力。這就好比大廠花了大價錢,找到水源,然後挖了一口井,小店也得活不是,給點傭金,分一股“清泉”吧。
一、移動支付
本文代碼示例是基於威富通移動支付(https://www.swiftpass.cn/products/epay/page.html)
- 微信支付
? ???場景介紹
用戶掃描商戶展示在各種場景的二維碼進行支付。:
? ???步驟1:商戶根據微信支付的規則,為不同商品生成不同的二維碼(如圖6.1),展示在各種場景,用於用戶掃描購買。
? ???步驟2:用戶使用微信“掃一掃”(如圖6.2)掃描二維碼後,獲取商品支付信息,引導用戶完成支付(如圖6.3)。
? ???步驟3:用戶確認支付,輸入支付密碼(如圖6.4)。
? ???步驟4:支付完成後會提示用戶支付成功(如圖6.5),商戶後臺得到支付成功的通知,然後進行發貨處理。
? ???查看是否安裝成功:
? ???筆者在實際項目中要使用微信掃碼付款功能,開發的時候選擇的是微信掃碼支付的模式一(https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_4)
? ???代碼片段
/// <summary> /// 威富通-微信支付 /// </summary> /// <param name="total_fee">訂單金額</param> /// <param name="orderno">訂單號</param> /// <param name="productName">產品名稱</param> private void WebChat(decimal total_fee, string orderno, string productName) { try { total_fee = total_fee * 100;//單位:分 PayReqEntity entity = new PayReqEntity(); entity.mch_id =“商戶ID” string key =“KEY";//您申請的 entity.key = key; entity.req_url = "https://pay.swiftpass.cn/pay/gateway"; entity.service = "pay.weixin.native"; entity.version = "2.0"; entity.out_trade_no = orderno; entity.body = productName; entity.attach = ""; entity.total_fee = Math.Round(total_fee).ToString(); entity.time_start = ""; entity.time_expire = ""; entity.mch_create_ip = AppUtils.GetIp(); entity.notify_url = ChargeHelper.BuildUrl() + "WebChat/Notify.aspx"; WeChatPayInterface service = new WeChatPayInterface(); PayResEntity result = service.SubmitPay(entity); if (!result.IsSuccess) { string msg = result.Message; if (msg.Contains("訂單已存在")) { msg = msg + ",請重新下單!"; } Response.Write("<script>alert('" + msg + "')</script>"); return; } Session["pavlue"] = result.arr; Response.Redirect("WebChat/Pay.aspx"); } catch (Exception ex) { throw ex; } }
? ???付款完成之後,會回調WebChat/Pay.aspx頁面,執行訂單業務功能。
public void callback()
{
try
{
WeChatPayInterface service = new WeChatPayInterface();
Stream stream = Request.InputStream;
string key = "KEY";//你申請的
NotifyResEntity result = service.PayResult(key, stream);
if (!result.IsSuccess)
{
Log.Info("[威富通-微信支付回調]:" + result.Message);
Response.Write("failure");
return;
}
Hashtable data = result.data;
/*-----------交易狀態------------
SUCCESS—支付成功
REFUND—轉入退款
NOTPAY—未支付
CLOSED—已關閉
PAYERROR—支付失敗(其他原因,如銀行返回失敗)
------------------------------------ */
string out_trade_no = data["out_trade_no"].ToString();//商戶訂單號
int status = Convert.ToInt32(data["status"]);//返回狀態碼(0表示成功,非0表示失敗此字段是通信標識,非交易標識,交易是否成功需要查看 result_code 來判斷)
int result_code = Convert.ToInt32(data["result_code"]);//業務結果(0表示成功,非0表示失敗)
if (status == 0 && result_code == 0)
{
string total_fee = data["total_fee"].ToString();//總金額,以分為單位,不允許包含任何字、符號
string transaction_id = data["transaction_id"].ToString();//平臺交易單號
//此處可以在添加相關處理業務 ,更新數據庫表中的記錄。
int proxyid = 0;
string bankbill = "";
ulong employeeid = 1;
string comment = "微信支付";
string billtype = "正常訂單";
int payment = 24;//微信支付
string bankname = "";
string payer = "";
string orderno = out_trade_no;
string taobaopayno = transaction_id;
decimal amountpaid = 0;
if (!string.IsNullOrEmpty(total_fee))
{
amountpaid = Convert.ToDecimal(total_fee) / 100;
}
//TODO:業務處理部分
Response.Write("success");
return;
}
else
{
Log.Info("[威富通-微信支付回調]:商戶訂單號out_trade_no=" + out_trade_no + "狀態碼status=" + status + ",業務結果result_code=" + result_code);
}
}
catch (Exception ex)
{
Log.Info("[威富通-微信支付回調]異常:" + ex);
}
Response.Write("failure");
}
2.支付寶支付
? ???場景介紹
????掃碼支付,指用戶打開支付寶錢包中的“掃一掃”功能,掃描商戶針對每個訂單實時生成的訂單二維碼,並在手機端確認支付。
? ???調用流程
https://docs.open.alipay.com/194/105170/
????商戶系統調用支付寶預下單接口alipay.trade.precreate,獲得該訂單二維碼圖片地址。
????發起輪詢獲得支付結果:等待5秒後調用交易查詢接口alipay.trade.query通過支付時傳入的商戶訂單號(out_trade_no)查詢支付結果(返回參數TRADE_STATUS),如果仍然返回等待用戶付款(WAIT_BUYER_PAY),則再次等待5秒後繼續查詢,直到返回確切的支付結果(成功TRADE_SUCCESS 或 已撤銷關閉TRADE_CLOSED),或是超出輪詢時間。在最後一次查詢仍然返回等待用戶付款的情況下,必須立即調用交易撤銷接口alipay.trade.cancel將這筆交易撤銷,避免用戶繼續支付。
????除了主動輪詢,也可以通過接受異步通知獲得支付結果,詳見掃碼異步通知,註意一定要對異步通知做驗簽,確保通知是支付寶發出的。
代碼片段:
private void Alipay(decimal total_fee, string orderno, string productName)
{
total_fee = total_fee * 100;//單位:分
PayReqEntity entity = new PayReqEntity();
entity.mch_id = "商戶ID";
string key = 商戶Key"";
entity.key = key;
entity.req_url = "https://pay.swiftpass.cn/pay/gateway";
entity.service = "pay.alipay.native";
entity.version = "2.0";
entity.out_trade_no = orderno;
entity.body = productName;
entity.attach = "";
entity.total_fee = Math.Round(total_fee).ToString();
entity.time_start = "";
entity.time_expire = "";
entity.mch_create_ip = AppUtils.GetIp();
entity.notify_url = ChargeHelper.BuildUrl() + "Alipay/Notify.aspx";
WeChatPayInterface service = new WeChatPayInterface();
PayResEntity result = service.SubmitPay(entity);
if (!result.IsSuccess)
{
string msg = result.Message;
if (msg.Contains("訂單已存在"))
{
msg = msg + ",請重新下單!";
}
Response.Write("<script>alert('" + msg + "')</script>");
return;
}
Session["alipay_pavlue"] = result.arr;
Response.Redirect("Alipay/Pay.aspx");
}
????支付完成,同樣回調Alipay/Pay.aspx
public void callback()
{
try
{
WeChatPayInterface service = new WeChatPayInterface();
Stream stream = Request.InputStream;
string key = "KEY";//填寫自己的
NotifyResEntity result = service.PayResult(key, stream);
if (!result.IsSuccess)
{
Log.Info("[威富通-支付寶支付回調]:" + result.Message);
Response.Write("failure");
return;
}
Hashtable data = result.data;
/*-----------交易狀態------------
SUCCESS—支付成功
REFUND—轉入退款
NOTPAY—未支付
CLOSED—已關閉
PAYERROR—支付失敗(其他原因,如銀行返回失敗)
------------------------------------ */
//string trade_state = data["trade_state"].ToString();
string out_trade_no = data["out_trade_no"].ToString();//商戶訂單號
int status = Convert.ToInt32(data["status"]);//返回狀態碼(0表示成功,非0表示失敗此字段是通信標識,非交易標識,交易是否成功需要查看 result_code 來判斷)
int result_code = Convert.ToInt32(data["result_code"]);//業務結果(0表示成功,非0表示失敗)
if (status == 0 && result_code == 0)
{
string total_fee = data["total_fee"].ToString();//總金額,以分為單位,不允許包含任何字、符號
string transaction_id = data["transaction_id"].ToString();//平臺交易單號
//此處可以在添加相關處理業務 ,更新數據庫表中的記錄。
int proxyid = 0;
string bankbill = "";
ulong employeeid = 1;
string comment = "支付寶支付";
string billtype = "正常訂單";
int payment = 23;//威富通-支付寶支付
string bankname = "";
string payer = "";
string orderno = out_trade_no;
string taobaopayno = transaction_id;
decimal amountpaid = 0;
if (!string.IsNullOrEmpty(total_fee))
{
amountpaid = Convert.ToDecimal(total_fee) / 100;
}
//TODO:業務處理部分
Response.Write("success");
return;
}
else
{
Log.Info("[威富通-支付寶支付回調]:商戶訂單號out_trade_no=" + out_trade_no + "狀態碼status=" + status + ",業務結果result_code=" + result_code);
}
}
catch (Exception ex)
{
Log.Info("[威富通-支付寶支付回調]異常:" + ex);
}
Response.Write("failure");
}
二、充值體系
任何一家公司做生意的都會使用支付業務,這裏以SAAS行業支付為例。
最基本的充值業務架構
滿足一下基本需求
- 用戶賬戶中心
- 用戶可充值,可查看訂單和購買商品
- 代理商、銷售等營銷部門可以查看業績報表
- 訂單生成流程
? ???在實際生產環境中中,訂單的流程也是較為重要的一環。
- 防止重復支付
? ???支付完成,回調的時候檢測訂單狀態。已支付的就不再執行。
- 如何保證支付一致性
? ???在實際生產環境中中,總會發生支付接口支付成功,回調執行訂單業務失敗的情況,簡單的辦法是可以增加一個單獨檢查業務,定時對不一致的訂單進行二次執行。
三、總結
? ???基本的充值體系是通用的。訂單業務量大的可以增加消息隊列處理。在保證一致性方面,我們在該架構上還有很多細節可以完善。
四、參考
- ??https://pay.weixin.qq.com/wiki/doc/api/index.html
??https://docs.open.alipay.com/194/106078/
? ???個人微信公眾號:
一文秒懂如何搭建一個最簡單的充值系統