銀聯支付 Chinapay 在.net下的使用總結


一、 准備文件

文檔資料

 

根據  客戶提供文檔《CHINAPAY商戶控制台使用手冊 》登陸 http://console.chinapay.com/newgms 需要客戶提供 商戶號,操作員號及密碼)

下載

 

解壓文件后得到如下文件

 

還需要2keyMerPrK.keyPgPubk.key)文件,分別是商戶私匙和公匙,需要客戶簽訂合同后銀聯才提供。

二、安裝部署

1.    ChinaPay.dllCPNPC.dllnetpay.dll復制bin

2.    注冊Chinapay.dllCPNPC.dll(指令regsvr32

例如  regsvr32  F:\工作\MySolution\Web\bin\Chinapay.dll

    regsvr32  F:\工作\MySolution\Web\bin\CPNPC.dll    

3.    Com類型信息轉換為.NET元數據, 需要vs命令提示 工具下運行

tlbimp F:\工作\MySolution\Web\bin\Chinapay.dll /out: F:\工作\MySolution\Web\bin\ ChinaPay_loaf.dll

站點增加引用ChinaPay_loaf.dll   使用的時候引用using ChinaPay_loaf 即可

 

4.    寫一個Chinapay.cs放在App_Code 用於 用戶簽名 和驗證,不理解簽名和驗證的看《附3商戶技術開發手冊.doc》數字簽名,

 

Chinapay.cs
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using ChinaPay_loaf        ;
using System.Web.UI;

     ///   <summary>
    
/// Chinapay 的摘要說明
    
///   </summary>
     public  class Chinapay
    {
         string strUrl =HttpContext.Current.Request.PhysicalApplicationPath;  // 獲取網站根目錄物理路徑
         public Chinapay()
        {
        }      
       
         ///   <summary>
        
///  訂單簽名函數sign
        
///   </summary>
        
///   <param name="MerId"> 商戶號,長度為15個字節的數字串,由ChinaPay或清算銀行分配 </param>
        
///   <param name="OrdId"> 訂單號,長度為16個字節的數字串,由用戶系統/網站生成,失敗的訂單號允許重復支付 </param>
        
///   <param name="TransAmt"> 交易金額,長度為12個字節的數字串,例如:數字串"000000001234"表示12.34元 </param>
        
///   <param name="CuryId"> 貨幣代碼, 長度為3個字節的數字串,目前只支持人民幣,取值為"156" </param>
        
///   <param name="TransDate"> 交易日期,長度為8個字節的數字串,表示格式為:YYYYMMDD </param>
        
///   <param name="TransType"> 交易類型,長度為4個字節的數字串,取值范圍為:"0001"和"0002", 其中"0001"表示消費交易,"0002"表示退貨交易 </param>
        
///   <returns> string CheckValue[256]  即NetPayClient根據上述輸入參數生成的商戶數字簽名,長度為256字節的字符串 </returns>
         public  string getSign( string MerId,  string OrdId,  string TransAmt,  string CuryId,  string TransDate,  string TransType)
        {
            NetPayClientClass npc =  new NetPayClientClass();  // 實例NetPay簽名        
             string temp = strUrl +  " key\\MerPrK.key ";
            npc.setMerKeyFile(strUrl +  " \\App_Data\\MerPrK.key ");
             string strChkValue =  "";                          // chinapay返回的商戶數字簽名
            strChkValue = npc.sign(MerId, OrdId, TransAmt, CuryId, TransDate, TransType);
             return strChkValue.Trim();
        }
         ///   <summary>
        
///  對一段字符進行簽名 signData
        
///   </summary>
        
///   <param name="MerId"> 商戶號,長度為15個字節的數字串,由ChinaPay分配 </param>
        
///   <param name="SignMsg"> 用於要簽名的字符串 </param>
        
///   <returns> String CheckValue[256]即NetPayClient根據上述輸入參數生成的商戶數字簽名,長度為256字節的字符串 </returns>
         public  string signData( string MerId,  string SignMsg)
        {
            NetPayClientClass npc =  new NetPayClientClass();  // 實例NetPay簽名           
            npc.setMerKeyFile(strUrl +  " App_Data\\MerPrK.key ");
             string strChkValueData =  "";
            strChkValueData = npc.signData(MerId, SignMsg);
             return strChkValueData.Trim();
        }

         ///   <summary>
        
///  驗證交易應答函數check
        
///   </summary>
        
///   <param name="MerId"> 商戶號,長度為15個字節的數字串,由ChinaPay分配 </param>
        
///   <param name="OrdId"> 訂單號,長度為16個字節的數字串,由商戶系統生成,失敗的訂單號允許重復支付 </param>
        
///   <param name="TransAmt"> 交易金額,長度為12個字節的數字串,例如:數字串"000000001234"表示12.34元 </param>
        
///   <param name="CuryId"> 貨幣代碼, 長度為3個字節的數字串,目前只支持人民幣,取值為"156" </param>
        
///   <param name="TransDate"> 交易日期,長度為8個字節的數字串,表示格式為: YYYYMMDD </param>
        
///   <param name="TransType"> 交易類型,長度為4個字節的數字串,取值范圍為:"0001"和"0002", 其中"0001"表示消費交易,"0002"表示退貨交易 </param>
        
///   <param name="OrderStatus"> 交易狀態,長度為4個字節的數字串。詳見交易狀態碼說明 </param>
        
///   <param name="CheckValue"> 校驗值,即ChinaPay對交易應答的數字簽名,長度為256字節的字符串 </param>
        
///   <returns> true 表示成功,即該交易應答為ChinaPay所發送,商戶根據“交易狀態”進行后續處理;否則表示失敗,即無效應答,商戶可忽略該應答 </returns>
         public  bool getCheck( string MerId,  string OrdId,  string TransAmt,  string CuryId,  string TransDate,  string TransType,  string OrderStatus,  string CheckValue)
        {
            NetPayClientClass npc =  new NetPayClientClass();  // 實例NetPay簽名           
            npc.setPubKeyFile(strUrl +  " App_Data\\PgPubk.key ");
             string strFlag =  "";
             bool bolFlag =  false;
            strFlag = npc.check(MerId, OrdId, TransAmt, CuryId, TransDate, TransType, OrderStatus, CheckValue);  //  ChkValue 為ChinaPay返回給商戶的域段內容
             if (strFlag ==  " 0 "// “0”表示驗簽成功
                bolFlag =  true;
             return bolFlag;
        }
         ///   <summary>
        
///  對一段字符串進行簽名驗證 checkData
        
///   </summary>
        
///   <param name="PlainData"> 用於數字簽名的字符串 </param>
        
///   <param name="CheckValue"> 校驗值,要驗證的字符串的數字簽名,長度為256字節的字符串 </param>
        
///   <returns> true 表示驗證通過成功;否則表示失敗 </returns>
         public  bool checkData( string PlainData,  string CheckValue)
        {
            NetPayClientClass npc =  new NetPayClientClass();  // 實例NetPay簽名           
            npc.setPubKeyFile(strUrl +  " App_Data\\PgPubk.key ");
             string strFlagData =  "";
             bool bolFlagData =  false;
            strFlagData = npc.checkData(PlainData, CheckValue);
             if (strFlagData ==  " true ")
                bolFlagData =  true;
             return bolFlagData;
        }


         //

        
// 支付函數
         ///   <summary>
        
///  支付函數
        
///   </summary>
        
///   <param name="OrderID"> 程序 訂單編號 </param>
        
///   <param name="TransAmt"> 交易錢數 </param>
        
///   <param name="proName"> 產品名稱 可選 </param>
         public  void GoToPay( string OrderID,  string TransAmt,  string proName, string gateid)
        {
            Chinapay cpy =  new Chinapay();
             // 獲取傳遞給銀聯chinapay的各個參數-----------------------------------------------
           
//  string cpyUrl = " http://payment-test.chinapay.com/pay/TransGet ";  // 測試地址,測試的時候用這個地址,應用到網站時用下面那個地址
             string cpyUrl =  " http://payment.chinapay.com/pay/TransGet ";
             string cpyMerId =  " 808080580112345 ";             // ChinaPay統一分配給商戶的商戶號,15位長度,必填
             string cpyOrdId = getOrderID(OrderID);            // 商戶提交給ChinaPay的交易訂單號,訂單號的第五至第九位必須是商戶號的最后五位,即“12345”;16位長度,必填
             string cpyTransAmt = getTransAmt(TransAmt);  // 訂單交易金額,12位長度,左補0,必填,單位為分,000000000001 表示 12.34 元
             string cpyCuryId =  " 156 ";             // 訂單交易幣種,3位長度,固定為人民幣156,必填
             string cpyTransDate = DateTime.Now.ToString( " yyyyMMdd ");             // 訂單交易日期,8位長度,必填,格式yyyyMMdd
             string cpyTransType =  " 0001 ";         // 交易類型,4位長度,必填,0001表示消費交易,0002表示退貨交易
             string cpyVersion =  " 20040916 ";       // 支付接入版本號,808080開頭的商戶用此版本,必填,另一版本為"20070129"
             string cpyBgRetUrl =  " http://test003.abc.cc/Chinapay_Bgreturn.aspx ";    // 后台交易接收URL,為后台接受應答地址,用於商戶記錄交易信息和處理,對於使用者是不可見的,長度不要超過80個字節,必填
             string cpyPageRetUrl =  " http://test003.abc.cc/Chinapay_Pgreturn.aspx "// 頁面交易接收URL,為頁面接受應答地址,用於引導使用者返回支付后的商戶網站頁面,長度不要超過80個字節,必填
             string cpyGateId = gateid;   // 支付網關號,可選,參看銀聯網關類型,如填寫GateId(支付網關號),則消費者將直接進入支付頁面,否則進入網關選擇頁面,可登陸商戶管理平台 查看各個銀行的網管號
             string cpyPriv1 = proName;   // 商戶私有域,長度不要超過60個字節,商戶通過此字段向Chinapay發送的信息,Chinapay依原樣填充返回給商戶

             string strChkValue =  ""// 256字節長的ASCII碼,此次交易所提交的關鍵數據的數字簽名,必填
            strChkValue = cpy.getSign(cpyMerId, cpyOrdId, cpyTransAmt, cpyCuryId, cpyTransDate, cpyTransType);

             if (strChkValue !=  "")
            {
             HttpContext.Current.Response.Write( " <form name='chinapayForm' method='post' action=' " + cpyUrl +  " '> ");          // 支付地址
             HttpContext.Current.Response.Write( " <input type='hidden' name='MerId' value=' " + cpyMerId +  " ' /> ");             // 商戶號
             HttpContext.Current.Response.Write( " <input type='hidden' name='OrdId' value=' " + cpyOrdId +  " ' /> ");             // 訂單號
             HttpContext.Current.Response.Write( " <input type='hidden' name='TransAmt' value=' " + cpyTransAmt +  " ' /> ");       // 支付金額
             HttpContext.Current.Response.Write( " <input type='hidden' name='CuryId' value=' " + cpyCuryId +  " ' /> ");           // 交易幣種
             HttpContext.Current.Response.Write( " <input type='hidden' name='TransDate' value=' " + cpyTransDate +  " ' /> ");     // 交易日期
             HttpContext.Current.Response.Write( " <input type='hidden' name='TransType' value=' " + cpyTransType +  " ' /> ");     // 交易類型
             HttpContext.Current.Response.Write( " <input type='hidden' name='Version' value=' " + cpyVersion +  " ' /> ");         // 支付接入版本號
             HttpContext.Current.Response.Write( " <input type='hidden' name='BgRetUrl' value=' " + cpyBgRetUrl +  " ' /> ");       // 后台接受應答地址
             HttpContext.Current.Response.Write( " <input type='hidden' name='PageRetUrl' value=' " + cpyPageRetUrl +  " ' /> ");   // 為頁面接受應答地址
             HttpContext.Current.Response.Write( " <input type='hidden' name='GateId' value=' " + cpyGateId +  " ' /> ");           // 支付網關號
             HttpContext.Current.Response.Write( " <input type='hidden' name='Priv1' value=' " + cpyPriv1 +  " ' /> ");             // 商戶私有域,這里將訂單自增編號放進去了
             HttpContext.Current.Response.Write( " <input type='hidden' name='ChkValue' value=' " + strChkValue +  " ' /> ");       // 此次交易所提交的關鍵數據的數字簽名
             HttpContext.Current.Response.Write( " <script> ");
             HttpContext.Current.Response.Write( " document.chinapayForm.submit(); ");
             HttpContext.Current.Response.Write( " </script></form> ");
            }       
        }

         // 訂單號
          private  string getOrderID( string orderID)
        {
             // 程序中的訂單號 案例12022800001
             string orderid =  string.Format( " {0}{1}{2} ", orderID.Substring( 04),  " 12345 ", orderID.Substring( 4));  // 訂單前四位+商家最后五位+訂單后七位
             return orderid;
        }

         // 返回交易金額
          private  string getTransAmt( string count)
        {
             string moneyCount = count.ToString().Replace( " . """);
             return moneyCount.PadLeft( 12' 0 ');
        }
    }

 

5.    下面的需要解決的就是寫四個頁面(支付頁,銀行選擇頁面,后台接受處理頁和用戶支付成功后跳轉頁),銀行選擇頁面,主要是自己定義圖標,這里目的就是為了選擇不同的網關來對應不同的銀行.羅列出常用的銀行。

   

后台接受頁面
protected  void Page_Load( object sender, EventArgs e)
    {
        Chinapay cpy =  new Chinapay(); 
         string TransDate =  "",MerId =  "",OrdId =  "",TransType =  "",TransAmt =  "",CuryId =  "",ChkValue =  "",OrderStatus =  "",GateId =  "",Priv1 =  "";
         bool bolCheck= false;

        TransDate = Request[ " transdate "].Trim();  // 交易日期
        MerId = Request[ " merid "].Trim();         // 商家號
        OrdId = Request[ " orderno "].Trim();       // 訂單號
        TransType = Request[ " transtype "].Trim(); // 交易類型
        TransAmt = Request[ " amount "].Trim();     // 交易貨幣值
        CuryId = Request[ " currencycode "].Trim();    // 交易幣種
        ChkValue = Request[ " checkvalue "].Trim();
        OrderStatus = Request[ " status "].Trim();   // 訂單狀態
        GateId = Request[ " GateId "].Trim();        // 支付網關號
        Priv1 = Request[ " Priv1 "].Trim();          // 商戶私有域

         /// 檢驗是否是銀聯chinapay返回的交易數據
        bolCheck = cpy.getCheck(MerId,OrdId,TransAmt,CuryId,TransDate,TransType,OrderStatus,ChkValue);
         if (bolCheck){
             if (OrderStatus ==  " 1001 ") // 交易成功
            {
              
                 string myOrderID = OrdId.Replace( " 12345 "string.Empty); // 移除商戶號后正好是我系統的訂單號
                
// 更新訂單表              
                OrderDetailBLL bll =  new OrderDetailBLL();
                bll.UpdateStateAll(myOrderID); // 訂單號                 
            }         
        }
    }

 

三、需要注意的地方

1. 后台接受頁面驗證簽名后還要判斷下訂單狀態 只有1001狀態才是成功交易,退款其他 要看文檔

2. 商戶提交給ChinaPay的交易訂單號,訂單號的第五至第九位必須是商戶號的最后五位(04版的,現在07版不用這樣做了),即“12345”;16位長度

     例如商家號是: 8080805801123456   則提交的訂單號必須如下形式

      例如    2012123450000000 ;

    這里你要看着 怎么處理比較好,根據這個訂單號 能對應上,你網站里面的訂單號

    我的訂單號生成規則是

     訂單號=年數后2+月數2+2+五位自增數(不夠補0);

     例如 :12030100001; //1231 00001個單子,能看出當天的銷售量 也就是說 每天售量最大值是99999,一般小商場足夠用了。

 

 

 


免責聲明!

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



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