zoukankan      html  css  js  c++  java
  • 银联支付 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,一般小商场足够用了。

     

     

     

  • 相关阅读:
    element ui 表单清空
    element ui 覆盖样式 方法
    element ui 修改表单值 提交无效
    element ui 抽屉里的表单输入框无法修改值
    element ui 抽屉首次显示 闪烁
    css 左侧高度 跟随右侧内容高度 自适应
    PICNUF框架
    elementui 抽屉组件标题 出现黑色边框
    vue 子组件跨多层调用父组件中方法
    vue 编辑table 数据 未点击提交,table里的数据就发生了改变(深拷贝处理)
  • 原文地址:https://www.cnblogs.com/clc2008/p/2375294.html
Copyright © 2011-2022 走看看