做者:
Jacky
聲明:本文版權歸做者和博客園共有,歡迎轉載,但未經做者贊成必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接,不然保留追究法律責任的權利。
第三方短信接口,支付接口普遍應用於金融領域與電商領域,這是我在14年工做時的一些經驗總結,如今分享出來,但願能對一部分朋友有所幫助!設計模式
一:對接短信接口ide
對接短信接口大致分爲兩個步驟:網站
1. 根據接口文檔發送短信類容到短信網關;ui
2. 回調結果並獲取短信剩餘條數this
考慮到一個網站可能不止一個短信網關,我使用了工廠設計模式,下面附上代碼url
短信網關接口spa
/// <summary> /// 短信網關接口 /// </summary> public interface ISMS { /// <summary> /// 短信商 /// </summary> SMSProvider Provider { get; } /// <summary> /// 發送短信 /// </summary> /// <param name="destnumbers">要發送到的手機號碼</param> /// <param name="msg">要發送的內容</param> /// <param name="sendTime">發送時間 爲null表示馬上發送</param> int Send(string destnumbers, string msg, out SMSStatus status, DateTime? sendTime = null); /// <summary> /// 獲取餘額 /// </summary> int Balance(); /// <summary> /// 獲取上行短信內容 /// </summary> /// <returns>返回null表示沒有獲取到上行短信</returns> List<SMSReply> GetReply(); }
短信工廠類設計
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Web; using System.IO; using System.ComponentModel; using SP.Studio.IO; using SP.Studio.Core; namespace SP.Studio.Gateway.SMS { /// <summary> /// 短信工廠 /// </summary> public class SMSFactory { public static ISMS CreateSMS(SMSConfig config) { ISMS sms = null; sms = (ISMS)Activator.CreateInstance(Type.GetType("SP.Studio.Gateway.SMS." + config.Provider), config.UserName, config.Password); return sms; } } /// <summary> /// 短信提供商 /// </summary> public enum SMSProvider : byte { /// <summary> /// 無供應商 /// </summary> None, /// <summary> /// 單元科技 /// </summary> [Description("單元科技")] CCell, /// <summary> /// 單元科技 接口2 /// </summary> [Description("單元科技")] CCell2, /// <summary> /// 億美科技 /// </summary> [Description("億美科技")] EMay, /// <summary> /// /// <summary> /// 中國網建 /// </summary> [Description("中國網建")] WebChinese, /// <summary> /// 國都 /// </summary> [Description("國都")] Guodu, /// <summary> /// 企信通(鑫陽創投) /// </summary> [Description("企信通")] YDQXT, /// <summary> /// http://sdk.entinfo.cn:8061/ /// </summary> [Description("DXC")] DXC, /// <summary> /// 凌凱科技 http://www.zhongguowuxian.com/Item/list.asp?id=1460 /// </summary> [Description("凌凱科技")] LingKai, /// <summary> /// 玄武科技 /// </summary> [Description("玄武科技")] MT, /// <summary> /// 單元科技新接口 /// </summary> [Description("單元科技-3")] CCell3, /// <summary> /// 使用短信貓發送 /// </summary> [Description("短信貓")] Modem = 100 } /// <summary> /// 短信息配置類 /// </summary> public class SMSConfig { public SMSProvider Provider { get; set; } public string UserName { get; set; } public string Password { get; set; } } }
實例rest
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Web; using SP.Studio.Net; using SP.Studio.Text; using SP.Studio.Security; using SP.Studio.Web; namespace SP.Studio.Gateway.SMS { public class LingKai : SMSBase, ISMS { public LingKai(string userName, string password) : base(userName, password) { } public SMSProvider Provider { get { return SMSProvider.LingKai; } } public int Send(string destnumbers, string msg, out SMSStatus status, DateTime? sendTime = null) { if (!WebAgent.IsMobile(destnumbers)) { status = SMSStatus.Number; return 0; } string url = string.Format("http://sdk.zhongguowuxian.com:98/ws/BatchSend.aspx?CorpID={0}&Pwd={1}&Mobile={2}&Content={3}&Cell=&SendTime=", this.UserName, this.Password, destnumbers, HttpUtility.UrlEncode(msg, Encoding.GetEncoding("GB2312"))); string result = NetAgent.DownloadData(url, Encoding.GetEncoding("GB2312")); //大於等於0的數字,發送成功(獲得大於等於0的數字、做爲取報告的id);-一、賬號未註冊;-二、其餘錯誤;-三、密碼錯誤;-四、手機號格式不對;-五、餘額不足;-六、定時發送時間不是有效的時間格式; //-七、請在提交信息末尾添加中文企業簽名【】; -八、發送內容需在1到500個字之間;-九、 發送號碼爲空 this.SaveGateway(result); status = SMSStatus.Success; long code; if (long.TryParse(result, out code)) { switch (code) { case -1: case -3: status = SMSStatus.Account; break; case -2: case -6: status = SMSStatus.Other; break; case -4: case -9: status = SMSStatus.Number; break; case -5: status = SMSStatus.Money; break; case -7: case -8: status = SMSStatus.Message; break; } } else { status = SMSStatus.Other; } return status == SMSStatus.Success ? 1 : 0; } /// <summary> ///獲取短信的剩餘量 /// </summary> /// <returns></returns> public int Balance() { string url = string.Format("http://sdk.zhongguowuxian.com:98/WS/SelSum.aspx?CorpID={0}&Pwd={1}", this.UserName, this.Password); string result = NetAgent.DownloadData(url,Encoding.GetEncoding("GB2312")); int balance; int.TryParse(result, out balance); return balance; } public List<SMSReply> GetReply() { return new List<SMSReply>(); } } }
二:對接支付接口code
對接支付接口大致步驟也分爲兩步,部分支付廠商可能存在小差別
1. 找到合適的支持廠商,簽定協議,拿到商戶code與簽名私鑰;
2. 根據提供對接文檔Post數據跳轉到支付網關;
3. 支付回調結果並驗證商戶網頁(通常作法是把回調地址傳給網關,在回調地址中驗證支付結果)
下面附上部分代碼
/// <summary> /// Post數據,跳轉支付網關 /// </summary> public override void GoGateway() { SortedDictionary<string, string> sParaTemp = new SortedDictionary<string, string>(); if (this.PayMethod == "bankPay") // 若是是網銀直接支付 { sParaTemp.Add("defaultbank", this.defaultbank); } switch (this.Service) { case "create_partner_trade_by_buyer": // 若是是擔保支付 case "trade_create_by_buyer": // 雙功能收款 sParaTemp.Add("logistics_type", "POST"); sParaTemp.Add("logistics_fee", "0.00"); sParaTemp.Add("logistics_payment", "BUYER_PAY"); sParaTemp.Add("price", base.Money.ToString("0.00")); sParaTemp.Add("quantity", "1"); break; } sParaTemp.Add("partner", this.Partner); sParaTemp.Add("_input_charset", _input_charset.ToLower()); sParaTemp.Add("service", this.Service); sParaTemp.Add("payment_type", paymentType.ToString()); sParaTemp.Add("notify_url", this.NotifyUrl); sParaTemp.Add("return_url", this.ReturnUrl); sParaTemp.Add("seller_email", this.SellerEmail); sParaTemp.Add("out_trade_no", base.OrderID); sParaTemp.Add("subject", base.Name); sParaTemp.Add("total_fee", base.Money.ToString("0.00")); sParaTemp.Add("body", base.Description); sParaTemp.Add("paymethod", this.PayMethod); sParaTemp.Add("anti_phishing_key", this.anti_phishing_key); sParaTemp.Add("exter_invoke_ip", this.clientIP); Encoding encoding = Encoding.GetEncoding(_input_charset); Dictionary<string, string> sPara = this.FilterPara(sParaTemp); //處理字符串 string prestr = this.CreateLinkString(sPara); sPara.Add("sign", Sign(prestr)); //簽名驗證 sPara.Add("sign_type", sign_type); string url = string.Format("{0}_input_charset={1}&{2}", GATEWAY, _input_charset, CreateLinkString(sPara)); HttpContext.Current.Response.Redirect(url); } public override bool Verify(VerifyCallBack callback) { #region ========= DEBUG ========== StringBuilder sb = new StringBuilder(); sb.AppendLine(DateTime.Now + "\n"); foreach (var keyValue in this.GetRequestGet()) { sb.AppendFormat("{0}:{1}\t", keyValue.Key, keyValue.Value); } sb.AppendLine().AppendLine("------------------------"); if (HttpContext.Current != null) System.IO.File.AppendAllText(HttpContext.Current.Server.MapPath("~/App_Data/Alipay.log"), sb.ToString(), Encoding.UTF8); #endregion SortedDictionary<string, string> inputPara = this.GetRequestGet(); string notify_id = WebAgent.GetParam("notify_id"); string sign = WebAgent.GetParam("sign"); string status = WebAgent.GetParam("trade_status"); Dictionary<string, string> sPara = this.FilterPara(inputPara); string preSignStr = this.CreateLinkString(sPara); if (this.Sign(preSignStr) != sign) return false; if (!string.IsNullOrEmpty(notify_id)) { string veryfy_url = VERYFYURL + "partner=" + this.Partner + "¬ify_id=" + notify_id; if (NetAgent.DownloadData(veryfy_url, Encoding.GetEncoding(_input_charset)) != "true") return false; } bool isSuccess = false; switch (status) { case "TRADE_SUCCESS": // 高級即時到賬狀態下 case "TRADE_FINISHED": // 普通即時到賬狀態下 case "WAIT_SELLER_SEND_GOODS": // 擔保交易 等待賣家發貨 isSuccess = true; break; default: isSuccess = false; break; } if (isSuccess) callback.Invoke(); return isSuccess; }