一、 準備文件

文檔資料

銀聯的CP_PAY_DEMO_JAVA_ALL jsp項目怎麼起_Web

 

根據  客户提供文檔《CHINAPAY商户控制枱使用手冊 》登陸(需要客户提供 商户號,操作員號及密碼)

下載

銀聯的CP_PAY_DEMO_JAVA_ALL jsp項目怎麼起_Web_02

 

解壓文件後得到如下文件

銀聯的CP_PAY_DEMO_JAVA_ALL jsp項目怎麼起_System_03

 

還需要2個key(MerPrK.key和PgPubk.key)文件,分別是商户私匙和公匙,需要客户簽訂合同後銀聯才提供。

二、安裝部署

1.    將ChinaPay.dll、CPNPC.dll及netpay.dll複製bin下

2.    註冊Chinapay.dll和CPNPC.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》數字簽名,

 

銀聯的CP_PAY_DEMO_JAVA_ALL jsp項目怎麼起_System_04

銀聯的CP_PAY_DEMO_JAVA_ALL jsp項目怎麼起_Web_05

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(0, 4), "12345", orderID.Substring(4)); //訂單前四位+商家最後五位+訂單後七位
            return orderid;
        }

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

 

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

   

銀聯的CP_PAY_DEMO_JAVA_ALL jsp項目怎麼起_System_04

銀聯的CP_PAY_DEMO_JAVA_ALL jsp項目怎麼起_Web_05

後台接受頁面

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   則提交的訂單號必須如下形式

      例如 123450000000 ;

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

    我的訂單號生成規則是

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

     例如 :12030100001; //12年3月1號 第00001個單子,能看出當天的銷售量 也就是説 每天售量最大值是99999,一般小商場足夠用了。