說說第三方支付接口開發及開發中遇到的坑爹問題


前言

  最近在做公司的支付接口,從微信支付到各種第三方的支付接口,還有點卡等支付,微信支付文檔相對比較詳細,雖然也不少坑,被各路開發人員吐槽,但是填的人多啊,所以是最好開發的,但是公司還有用到一些第三方的網頁支付接口,然后遇到很多坑,忍不住想吐槽一下。

一、第三方支付流程

  各種支付的文檔,業務流程圖有的過於簡單,有的真的是復雜的不要不要的,開發者看了也是醉,寫這些文檔的人好像從來不會考慮看的人的感受,所以我覺得有必要在這里簡單介紹,我覺得給開發者的流程圖大致應該是這樣的,而不是一堆用不上的東西在開發文檔里面。

再簡單化就是:獲取接口信息(銀行列表等)-》提交參數及簽名-》獲取結果(需要驗證簽名)

我們做接口開發  能力多么強的程序員,不看文檔也是沒有辦法做的,簽名算法是人家做接口的人提供的,參數也是人家命名的,所以學會看文檔是很重要的,看過大量別人寫的文檔,我們才可以寫出簡單明了的文檔了,這是經驗之談。

二、開發中遇到的那些坑

有寫坑是文檔的坑,有些坑是人為的坑,反正坑你沒商量。

1.微信支付

  之前做微信支付,從官方文檔下載了asp.net的開發demo,替換好了參數,按照官方的步驟一步一步來,想先測試支付成功后,再對接系統,坑的是我恰好用的是蘋果手機,恰好官方asp.net的demo里面支付按鈕拖的是一個控件,在安卓上支付沒有問題,在蘋果手機上卻不可以,然后我再不知情的情況下我硬是搞了半天,看看代碼注釋明顯不是C#的注釋方式,多半是做java的抓過來把java版本修改的。然后網上搜了一下,發現好多人被這個問題坑到!

2.環訊支付

  ①環訊支付提供了測試的商戶id和密鑰,並且提供了webservice接口獲取對應銀行的名稱和代號,方便開發直連支付模式,但是根據接口,獲取到的銀行列表的銀行代號竟然有重復的,我一直以為是我接口調用有問題,再三確認,真的是提供接口的太隨意了;②支付接口的商戶號下來了,我嘗試着去支付,改了正式的接口和商戶信息,然后支付,結果鏈接失敗,錯誤碼#E008,我查文檔,沒有,百度,沒有,找人問,不知道···然后我咨詢他們官方客服,官方客服轉接到技術客服,反正各種麻煩,對方說是域名沒綁定,我也是醉。公司讓我開發,就給了文檔和商戶信息,其他的都沒有,我以為只要微信才需要綁定域名呢。然后讓客服給個錯誤碼的文檔,對方非要我提供商戶號才肯給····不知道這錯誤碼還是什么機密么?

3.新生支付

  ①這個官方提供的文檔就更離譜了,我看了文檔是2011年寫的,pdf是2013年生成的,然后上面也是提供了測試的地址,地址不是真的可訪問的地址,需要修改hosts文件,重定向到指定的域名。我做好了准備測試的時候,發現一直提示網頁鏈接錯誤。納悶,當然我肯定是從自己身上找問題,是不是host文件修改的不對,或者是其他什么問題。經過我再三確認 各種ping 發現測試地址是不可用的,於是找度年,沒結果,問小伙伴,沒結果,好了,該去找官方客服,然后對接技術客服,問他們要最新的文檔,及測試地址是換了么?然后對方給我的答復是測試地址是不可用的,我現在在用的文檔(2011年寫的13年最后修改)是最新的,測試不可以用 你給各種測試的一堆東西干嘛?

  ②直連的時候有個參數是必填的,用戶付款賬號,我覺得邏輯很奇怪,就問技術客服,結果對方給的答復是只要是郵箱和手機格式的,隨便填就可以···

  ③這個平台沒有提供接口獲取銀行列表,所有的銀行參數都要手動寫,而且有變動的話也只能手動改!

4.關於文檔

  不明白的點是官方網站上怎么沒有網頁版的開發文檔,word或者pdf方便,但是如果接口更新了什么東西開發者第一時間怎么修改呢?

三、案列代碼

環訊支付的接口代碼

1.獲取銀行列表

 1 #region 環訊網銀支付接口 WebService獲取銀行列表信息BankList()(暫時是測試的接口)
 2 PayServiceIps.ServiceSoapClient IpsPay = new PayServiceIps.ServiceSoapClient();//調用webservice 此處是測試地址
 3 protected List<string> Array;
 4 //獲取銀行列表
 5 //格式為  銀行|銀行別名|銀行代號的數組
 6 protected List<string> BankList()
 7 {
 8     string Mer_code = System.Configuration.ConfigurationManager.AppSettings["Mer_code"];//商戶號
 9     string Mer_key = System.Configuration.ConfigurationManager.AppSettings["Mer_key"];//商戶證書:登陸http://merchant.ips.com.cn/商戶后台下載的商戶證書內容
10     string Re = IpsPay.GetBankList(Mer_code, Game.Utils.Utility.MD5(Mer_code + Mer_key).ToLower());
11     Re = HttpUtility.UrlDecode(Re);//Re的格式為銀行|銀行別名|銀行代號#
12     List<string> ArrayList = new List<string>();
13     for (int i = 0; i < (Re.Split('#').Length - 1); i++)//數組是以#結束的 所以最后一個字符串是空的
14     {
15         ArrayList.Add(Re.Split('#')[i]);
16     }
17     return ArrayList;
18 }
19 #endregion

2.支付跳轉到第三方頁面

 1 #region 配置支付參數並且跳轉到支付
 2 //提交地址
 3 //string form_url = "http://pay.ips.net.cn/ipayment.aspx"; //測試
 4 string form_url = "https://pay.ips.com.cn/ipayment.aspx"; //正式
 5 //商戶號
 6 string Mer_code = System.Configuration.ConfigurationManager.AppSettings["Mer_code"];
 7 //商戶證書:登陸http://merchant.ips.com.cn/商戶后台下載的商戶證書內容
 8 string Mer_key = System.Configuration.ConfigurationManager.AppSettings["Mer_key"];
 9 //商戶訂單編號
10 string Billno = orderInfo.OrderID;// 
11 //訂單金額(保留2位小數)
12 string Amount = this.txtSalePrice.Text.Trim() + ".00";
13 //訂單日期
14 string BillDate = DateTime.Now.ToString("yyyyMMdd");
15 //幣種
16 string Currency_Type = "RMB";
17 //支付卡種
18 string Gateway_Type = "01";
19 //銀行代號
20 string Bankco = Bankco;
21 //語言
22 string Lang = "GB";
23 string nurl = "http://" + Request.Url.Authority + "/Return.aspx";
24 //支付結果成功返回的商戶URL
25 string Merchanturl = nurl;
26 //支付結果失敗返回的商戶URL
27 string FailUrl = "http://" + Request.Url.Authority + "/FailUrl.aspx";
28 //商戶數據包
29 string Attach = Amount;
30 //顯示金額
31 string DispAmount = Amount;
32 //訂單支付接口加密方式
33 string OrderEncodeType = "5";
34 //交易返回接口加密方式 
35 string RetEncodeType = "17";
36 //返回方式
37 string Rettype = "1";
38 //Server to Server 返回頁面URL
39 string ServerUrl = nurl;
40 //訂單支付接口的Md5摘要, 原文=billno+訂單編號+ currencytype +幣種+ amount +訂單金額+ date +訂單日期+ orderencodetype +訂單支付接口加密方式+商戶內部證書字符串
41 string SignMD5 = System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile("billno" + Billno + "currencytype" + Currency_Type + "amount" + Amount + "date" + BillDate + "orderencodetype" + OrderEncodeType + Mer_key, "MD5").ToLower();
42 string postForm = "<form name=\"frm1\" id=\"frm1\" method=\"post\" action=\"" + form_url + "\">";
43 postForm += "<input type=\"hidden\" name=\"Mer_code\" value=\"" + Mer_code + "\" />";
44 postForm += "<input type=\"hidden\" name=\"Billno\" value=\"" + Billno + "\" />";
45 postForm += "<input type=\"hidden\" name=\"Amount\" value=\"" + Amount + "\" />";
46 postForm += "<input type=\"hidden\" name=\"Date\" value=\"" + BillDate + "\" />";
47 postForm += "<input type=\"hidden\" name=\"Currency_Type\" value=\"" + Currency_Type + "\" />";
48 postForm += "<input type=\"hidden\" name=\"Gateway_Type\" value=\"" + Gateway_Type + "\" />";
49 postForm += "<input type=\"hidden\" name=\"Lang\" value=\"" + Lang + "\" />";
50 postForm += "<input type=\"hidden\" name=\"Merchanturl\" value=\"" + Merchanturl + "\" />";
51 postForm += "<input type=\"hidden\" name=\"FailUrl\" value=\"" + FailUrl + "\" />";
52 postForm += "<input type=\"hidden\" name=\"Attach\" value=\"" + Attach + "\" />";
53 postForm += "<input type=\"hidden\" name=\"Bankco\" value=\"" + Bankco + "\" />";
54 postForm += "<input type=\"hidden\" name=\"DispAmount\" value=\"" + DispAmount + "\" />";
55 postForm += "<input type=\"hidden\" name=\"OrderEncodeType\" value=\"" + OrderEncodeType + "\" />";
56 postForm += "<input type=\"hidden\" name=\"RetEncodeType\" value=\"" + RetEncodeType + "\" />";
57 postForm += "<input type=\"hidden\" name=\"Rettype\" value=\"" + Rettype + "\" />";
58 postForm += "<input type=\"hidden\" name=\"ServerUrl\" value=\"" + ServerUrl + "\" />";
59 postForm += "<input type=\"hidden\" name=\"SignMD5\" value=\"" + SignMD5 + "\" />";
60 if (Bankco != "")
61     postForm += "<input type=\"hidden\" name=\"DoCredit\" value=\"1\">";
62 postForm += "</form>";
63 //自動提交該表單到測試網關
64 postForm += "<script type=\"text/javascript\" language=\"javascript\">setTimeout(\"document.getElementById('frm1').submit();\",10);</script>";
65 #endregion

3.結果返回

 1 //接收數據
 2 string billno = Request["billno"];
 3 string amount = Request["amount"];//+".00";
 4 string currency_type = Request["Currency_type"];
 5 string mydate = Request["date"];
 6 string succ = Request["succ"];
 7 string msg = Request["msg"];
 8 string attach = Request["attach"];
 9 string ipsbillno = Request["ipsbillno"];
10 string retEncodeType = Request["retencodetype"];
11 string signature = Request["signature"];
12 string bankbillno = Request["bankbillno"];
13 //簽名原文
14 //billno+【訂單編號】+currencytype+【幣種】+amount+【訂單金額】+date+【訂單日期】+succ+【成功標志】+ipsbillno+【IPS訂單編號】+retencodetype +【交易返回簽名方式】
15 string content = "billno" + billno + "currencytype" + currency_type + "amount" + amount + "date" + mydate + "succ" + succ + "ipsbillno" + ipsbillno + "retencodetype" + retEncodeType;
16 //簽名是否正確
17 Boolean verify = false;
18 
19 //驗證方式:16-md5withRSA  17-md5
20 
21 // if (retEncodeType == "17")
22 //{
23 //登陸http://merchant.ips.com.cn/商戶后台下載的商戶證書內容
24 string merchant_key = System.Configuration.ConfigurationManager.AppSettings["Mer_key"];
25 //Md5摘要
26 string signature1 = FormsAuthentication.HashPasswordForStoringInConfigFile(content + merchant_key, "MD5").ToLower();
27 
28 if (signature1 == signature)
29 {
30     verify = true;
31 }
32 
33 //判斷簽名驗證是否通過
34 if (verify == true)
35 {
36     //判斷交易是否成功
37     if (succ != "Y")
38     {
39         Response.Write("<script>alert(\"交易失敗!\");</script>");
40         Response.End();
41     }
42     else
43     {
44 
45         Response.Write("<script>alert(\"交易成功!\");</script>");
46         Response.End();
47     }
48 }
49 else
50 {
51     Response.Write("簽名不正確!");
52 }

 

本文版權歸作者(謝俊)和博客園所有,歡迎轉載,轉載請標明出處。

原文地址:http://www.cnblogs.com/net-xiejun/

微信開發群C#.NETWEB程序開發交流

完整源碼下載:https://github.com/xiejun-net/weixin

公眾賬號:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM