銀聯在線支付B2C UnionPay.NET


 

新春即將來臨,首先給大家拜個早年,祝攻城獅們新年快樂、萬事如意、合家歡樂、團團圓圓、幸福健康、來年更能大展宏圖 實現各自的夢想! 同時預祝各大科技公司大佬們事業蒸蒸日上、公司轉型突破創新、沖出突圍帶領員工們早日實現上市夢想!

 今天研究了下銀聯在線支付功能,特地記錄下以表碼農們還在堅守崗位。此功能主要是一般的.NET實現的,有機會轉為標准的MVC模式實現以及應用到asp.net core 中。

首先第一是支付首頁代碼:

PayIndex.aspx:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="PayIndex.aspx.cs" Inherits="UnionPayNET.PayIndex" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
</head>
<body>
    
    <form id="form1" runat="server" method="post" action="UnionPay.aspx">
        <div>
                <p>
<label>商戶號:</label>
<input id="merId" type="text" pattern="\d{15}" name="merId" placeholder="商戶號" value="777290058110048" title="默認商戶號僅作為聯調測試使用,正式上線還請使用正式申請的商戶號。" required="required"/>
</p>
<p>
<label>交易金額:</label>
<input id="txnAmt" type="text" pattern="\d{1,12}" name="txnAmt" placeholder="交易金額" value="1000" title="單位為分,1-12位數字。" required="required"/>
</p>
<p>
<label>訂單發送時間:</label>  
<input id="txnTime" type="text" pattern="\d{14}" name="txnTime" placeholder="訂單發送時間,YYYYMMDDhhmmss格式" value="<%= DateTime.Now.ToString("yyyyMMddHHmmss") %>" title="取北京時間,YYYYMMDDhhmmss格式。" required="required"/>
</p>
<p>
<label>商戶訂單號:</label>
<input id="orderId" type="text" pattern="[0-9a-zA-Z]{8,32}" name="orderId" placeholder="商戶訂單號" value="<%= DateTime.Now.ToString("yyyyMMddHHmmssfff") %>" title="8-32位數字字母,自行定義內容。" required="required"/>
</p>
<p>
<label>&nbsp;</label>
<input type="submit" class="button" value="跳轉銀聯頁面支付" />

</p>
        </div>
    </form>
</body>
</html>

第二是跳轉到支付:UnionPay.aspx

 protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                Dictionary<string, string> param = new Dictionary<string, string>();

                //以下信息非特殊情況不需要改動
                param["version"] = SDKConfig.Version;//版本號
                param["encoding"] = "UTF-8";//編碼方式
                param["txnType"] = "01";//交易類型
                param["txnSubType"] = "01";//交易子類
                param["bizType"] = "000201";//業務類型
                param["signMethod"] = SDKConfig.SignMethod;//簽名方法
                param["channelType"] = "08";//渠道類型
                param["accessType"] = "0";//接入類型
                param["frontUrl"] = SDKConfig.FrontUrl;  //前台通知地址      
                param["backUrl"] = SDKConfig.BackUrl;  //后台通知地址
                param["currencyCode"] = "156";//交易幣種

                // 訂單超時時間。
                // 超過此時間后,除網銀交易外,其他交易銀聯系統會拒絕受理,提示超時。 跳轉銀行網銀交易如果超時后交易成功,會自動退款,大約5個工作日金額返還到持卡人賬戶。
                // 此時間建議取支付時的北京時間加15分鍾。
                // 超過超時時間調查詢接口應答origRespCode不是A6或者00的就可以判斷為失敗。
                param["payTimeout"] = DateTime.Now.AddMinutes(15).ToString("yyyyMMddHHmmss");


                //TODO 以下信息需要填寫
                param["merId"] = Request.Form["merId"].ToString();//商戶號,請改自己的測試商戶號,此處默認取demo演示頁面傳遞的參數
                param["orderId"] = Request.Form["orderId"].ToString();//商戶訂單號,8-32位數字字母,不能含“-”或“_”,此處默認取demo演示頁面傳遞的參數,可以自行定制規則
                param["txnTime"] = Request.Form["txnTime"].ToString();//訂單發送時間,格式為YYYYMMDDhhmmss,取北京時間,此處默認取demo演示頁面傳遞的參數,參考取法: DateTime.Now.ToString("yyyyMMddHHmmss")
                param["txnAmt"] = Request.Form["txnAmt"].ToString();//交易金額,單位分,此處默認取demo演示頁面傳遞的參數

               
                AcpService.Sign(param, System.Text.Encoding.UTF8);
                string html = AcpService.CreateAutoFormHtml(SDKConfig.FrontTransUrl, param, System.Text.Encoding.UTF8);// 將SDKUtil產生的Html文檔寫入頁面,從而引導用戶瀏覽器重定向   
                Response.ContentEncoding = Encoding.UTF8; // 指定輸出編碼
                Response.Write(html);
            }
        }

第三是:前台通知地址,填寫接收銀聯前台通知的地址

FrontRcvResponse

protected string html;
        protected void Page_Load(object sender, EventArgs e)
        {
            log4net.ILog log = log4net.LogManager.GetLogger(this.GetType());

            if (Request.HttpMethod == "POST")
            {
                // 使用Dictionary保存參數
                Dictionary<string, string> resData = new Dictionary<string, string>();

                NameValueCollection coll = Request.Form;

                string[] requestItem = coll.AllKeys;

                for (int i = 0; i < requestItem.Length; i++)
                {
                    resData.Add(requestItem[i], Request.Form[requestItem[i]]);
                }

                //商戶端根據返回報文內容處理自己的業務邏輯 ,DEMO此處只輸出報文結果
                StringBuilder builder = new StringBuilder();
                log.Info("receive front notify: " + SDKUtil.CreateLinkString(resData, false, true, System.Text.Encoding.UTF8));

                builder.Append("<tr><td align=\"center\" colspan=\"2\"><b>商戶端接收銀聯返回報文並按照表格形式輸出結果</b></td></tr>");

                for (int i = 0; i < requestItem.Length; i++)
                {
                    builder.Append("<tr><td width=\"30%\" align=\"right\">" + requestItem[i] + "</td><td style='word-break:break-all'>" + Request.Form[requestItem[i]] + "</td></tr>");
                }

                if (AcpService.Validate(resData, System.Text.Encoding.UTF8))
                {
                    builder.Append("<tr><td width=\"30%\" align=\"right\">商戶端驗證銀聯返回報文結果</td><td>驗證簽名成功.</td></tr>");

                    string respcode = resData["respCode"]; //00、A6為成功,其余為失敗。其他字段也可按此方式獲取。

                    //如果卡號我們業務配了會返回且配了需要加密的話,請按此方法解密
                    //if(resData.ContainsKey("accNo"))
                    //{
                    //    string accNo = SecurityUtil.DecryptData(resData["accNo"], System.Text.Encoding.UTF8); 
                    //}

                    //customerInfo子域的獲取
                    if (resData.ContainsKey("customerInfo"))
                    {
                        Dictionary<string, string> customerInfo = AcpService.ParseCustomerInfo(resData["customerInfo"], System.Text.Encoding.UTF8);
                        if (customerInfo.ContainsKey("phoneNo"))
                        {
                            string phoneNo = customerInfo["phoneNo"]; //customerInfo其他子域均可參考此方式獲取  
                        }
                        foreach (KeyValuePair<string, string> pair in customerInfo)
                        {
                            builder.Append(pair.Key + "=" + pair.Value + "<br>\n");
                        }
                    }
                }
                else
                {
                    builder.Append("<tr><td width=\"30%\" align=\"right\">商戶端驗證銀聯返回報文結果</td><td>驗證簽名失敗.</td></tr>");
                }
                html = builder.ToString();
            }
        }

第四是:后台通知地址,填寫后台接收銀聯后台通知的地址,必須外網能訪問

BackRcvResponse

  protected string html;
        protected void Page_Load(object sender, EventArgs e)
        {
            log4net.ILog log = log4net.LogManager.GetLogger(this.GetType());

            // **************后台接收銀聯返回報文交易結果展示***********************
            if (Request.HttpMethod == "POST")
            {
                // 使用Dictionary保存參數
                Dictionary<string, string> resData = new Dictionary<string, string>();

                NameValueCollection coll = Request.Form;

                string[] requestItem = coll.AllKeys;

                for (int i = 0; i < requestItem.Length; i++)
                {
                    resData.Add(requestItem[i], Request.Form[requestItem[i]]);
                }

                //商戶端根據返回報文內容處理自己的業務邏輯 , 處理訂單狀態相關業務數據處理
                //DEMO此處只輸出報文結果
                StringBuilder builder = new StringBuilder();
                log.Info("receive back notify: " + SDKUtil.CreateLinkString(resData, false, true, System.Text.Encoding.UTF8));

                builder.Append("<tr><td align=\"center\" colspan=\"2\"><b>商戶端接收銀聯返回報文並按照表格形式輸出結果</b></td></tr>");

                for (int i = 0; i < requestItem.Length; i++)
                {
                    builder.Append("<tr><td width=\"30%\" align=\"right\">" + requestItem[i] + "</td><td style='word-break:break-all'>" + Request.Form[requestItem[i]] + "</td></tr>");
                }

                if (AcpService.Validate(resData, System.Text.Encoding.UTF8))
                {
                    builder.Append("<tr><td width=\"30%\" align=\"right\">商戶端驗證銀聯返回報文結果</td><td>驗證簽名成功.</td></tr>");

                    string respcode = resData["respCode"]; //00、A6為成功,其余為失敗。其他字段也可按此方式獲取。

                    //如果卡號我們業務配了會返回且配了需要加密的話,請按此方法解密
                    //if(resData.ContainsKey("accNo"))
                    //{
                    //    string accNo = SecurityUtil.DecryptData(resData["accNo"], System.Text.Encoding.UTF8); 
                    //}

                    //customerInfo子域的獲取
                    if (resData.ContainsKey("customerInfo"))
                    {
                        Dictionary<string, string> customerInfo = AcpService.ParseCustomerInfo(resData["customerInfo"], System.Text.Encoding.UTF8);
                        if (customerInfo.ContainsKey("phoneNo"))
                        {
                            string phoneNo = customerInfo["phoneNo"]; //customerInfo其他子域均可參考此方式獲取  
                        }
                        foreach (KeyValuePair<string, string> pair in customerInfo)
                        {
                            builder.Append(pair.Key + "=" + pair.Value + "<br>\n");
                        }
                    }
                }
                else
                {
                    builder.Append("<tr><td width=\"30%\" align=\"right\">商戶端驗證銀聯返回報文結果</td><td>驗證簽名失敗.</td></tr>");
                }
                html = builder.ToString();
            }
        }

第五是:web.config

<?xml version="1.0" encoding="utf-8"?>
<!--
  有關如何配置 ASP.NET 應用程序的詳細信息,請訪問
  https://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
  <appSettings>
    <!--
      ##############SDK配置文件(密鑰方式簽名)################
      # 說明:
      # 1. 使用時請刪除后綴的“.密鑰”,並將此文件替換原來的Web.config。
      # 2. 具體配置項請根據注釋修改。
      # 3. 請注意無跳轉、代收付等涉及敏感信息加密的產品一定要用證書方式簽名的,請勿使用此文件。
      #########################################################
      -->

    <!-- 簽名密鑰(配置業務郵件發送的密鑰 ,測試環境固定88888888) -->
    <add key="acpsdk.secureKey" value="88888888" />


    <!--
      ##############SDK配置文件(證書方式簽名)################
      # 說明:
      # 1. 使用時請刪除后綴的“.證書”,並將此文件替換原來的Web.config。
      # 2. 具體配置項請根據注釋修改。
      #########################################################
      -->

    <!-- 簽名證書路徑,證書位於assets/測試環境證書/文件夾下,請復制到d:/certs文件夾 -->
    <add key="acpsdk.signCert.path" value="d:/UnionPayCert/acp_test_sign.pfx" />
    <!-- 簽名證書密碼,測試證書默認000000 -->
    <add key="acpsdk.signCert.pwd" value="000000" />
    <!-- 加密證書路徑 -->
    <add key="acpsdk.encryptCert.path" value="d:/UnionPayCert/acp_test_enc.cer" />
    <!-- 驗簽中級證書路徑 -->
    <add key="acpsdk.middleCert.path" value="d:/UnionPayCert/acp_test_middle.cer" />
    <!-- 驗簽根證書路徑 -->
    <add key="acpsdk.rootCert.path" value="d:/UnionPayCert/acp_test_root.cer" />

    <!-- 簽名方式,證書方式固定01,請勿改動。 -->
    <add key="acpsdk.signMethod" value="01" />
    <!-- 報文版本號,固定5.1.0,請勿改動。。 -->
    <add key="acpsdk.version" value="5.1.0" />

    <!-- 是否驗證https證書,測試環境請設置false,生產環境建議優先嘗試true,不行再false。非true的值默認都當false處理 -->
    <add key="acpsdk.ifValidateRemoteCert" value="false" />
    <!-- 是否驗證驗簽證書的CN,測試環境請設置false,生產環境請設置true。非false的值默認都當true處理 -->
    <add key="acpsdk.ifValidateCNName" value="false" />

    <!-- 前台通知地址,填寫接收銀聯前台通知的地址 -->
    <add key="acpsdk.frontUrl" value="http://localhost:3000/UnionPayNotiy/FrontRcvResponse.aspx" />
    <!-- 后台通知地址,填寫后台接收銀聯后台通知的地址,必須外網能訪問 -->
    <add key="acpsdk.backUrl" value="http://8.20.7.8:3000/UnionPayNotiy/BackRcvResponse.aspx" />

    <!--########################## 測試環境地址(生產環境地址見assets文件夾下面的生產環境配置文件) #############################-->
    <!-- 前台交易地址 -->
    <add key="acpsdk.frontTransUrl" value="https://gateway.test.95516.com/gateway/api/frontTransReq.do" />
    <!-- 后台交易地址 -->
    <add key="acpsdk.backTransUrl" value="https://gateway.test.95516.com/gateway/api/backTransReq.do" />
    <!-- 交易狀態查詢地址 -->
    <add key="acpsdk.singleQueryUrl" value="https://gateway.test.95516.com/gateway/api/queryTrans.do" />
    <!-- 文件傳輸類交易地址 -->
    <add key="acpsdk.fileTransUrl" value="https://filedownload.test.95516.com/" />
    <!-- 批量交易地址 -->
    <add key="acpsdk.batTransUrl" value="https://gateway.test.95516.com/gateway/api/batchTrans.do" />
    <!-- 有卡交易地址 -->
    <add key="acpsdk.cardRequestUrl" value="https://gateway.test.95516.com/gateway/api/cardTransReq.do" />
    <!-- app交易地址 手機控件支付使用該地址-->
    <add key="acpsdk.appRequestUrl" value="https://gateway.test.95516.com/gateway/api/appTransReq.do" />

    <!-- 前台交易地址 -->
    <add key="acpsdk.jf.frontTransUrl" value="https://gateway.test.95516.com/jiaofei/api/frontTransReq.do" />
    <!-- 后台交易地址 -->
    <add key="acpsdk.jf.backTransUrl" value="https://gateway.test.95516.com/jiaofei/api/backTransReq.do" />
    <!-- 交易狀態查詢地址 -->
    <add key="acpsdk.jf.singleQueryUrl" value="https://gateway.test.95516.com/jiaofei/api/queryTrans.do" />
    <!-- 有卡交易地址 -->
    <add key="acpsdk.jf.cardRequestUrl" value="https://gateway.test.95516.com/jiaofei/api/cardTransReq.do" />
    <!-- app交易地址 手機控件支付使用該地址-->
    <add key="acpsdk.jf.appRequestUrl" value="https://gateway.test.95516.com/jiaofei/api/appTransReq.do" />
    <!--########################## 測試環境地址(生產環境地址見assets文件夾下面的生產環境配置文件) #############################-->


    <!--########################## 生產環境地址配置文件) #############################-->
    <!--
      -->
    <!-- 前台交易地址 -->
    <!--
      <add key="acpsdk.frontTransUrl" value="https://gateway.95516.com/gateway/api/frontTransReq.do" />
      -->
    <!-- 后台交易地址 -->
    <!--
      <add key="acpsdk.backTransUrl" value="https://gateway.95516.com/gateway/api/backTransReq.do" />
      -->
    <!-- 交易狀態查詢地址 -->
    <!--
      <add key="acpsdk.singleQueryUrl" value="https://gateway.95516.com/gateway/api/queryTrans.do" />
      -->
    <!-- 文件傳輸類交易地址 -->
    <!--
      <add key="acpsdk.fileTransUrl" value="https://filedownload.95516.com/" />
      -->
    <!-- 批量交易地址 -->
    <!--
      <add key="acpsdk.batTransUrl" value="https://gateway.95516.com/gateway/api/batchTrans.do" />
      -->
    <!-- 有卡交易地址 -->
    <!--
      <add key="acpsdk.cardRequestUrl" value="https://gateway.95516.com/gateway/api/cardTransReq.do" />
      -->
    <!-- app交易地址 手機控件支付使用該地址-->
    <!--
      <add key="acpsdk.appRequestUrl" value="https://gateway.95516.com/gateway/api/appTransReq.do" />
      
      -->
    <!-- 前台交易地址 -->
    <!--
      <add key="acpsdk.jf.frontTransUrl" value="https://gateway.95516.com/jiaofei/api/frontTransReq.do" />
      -->
    <!-- 后台交易地址 -->
    <!--
      <add key="acpsdk.jf.backTransUrl" value="https://gateway.95516.com/jiaofei/api/backTransReq.do" />
      -->
    <!-- 交易狀態查詢地址 -->
    <!--
      <add key="acpsdk.jf.singleQueryUrl" value="https://gateway.95516.com/jiaofei/api/queryTrans.do" />
      -->
    <!-- 有卡交易地址 -->
    <!--
      <add key="acpsdk.jf.cardRequestUrl" value="https://gateway.95516.com/jiaofei/api/cardTransReq.do" />
      -->
    <!-- app交易地址 手機控件支付使用該地址-->
    <!--
      <add key="acpsdk.jf.appRequestUrl" value="https://gateway.95516.com/jiaofei/api/appTransReq.do" />-->



    <!--##########################log4net配置#############################-->
    <add key="log4net.Config" value="log4net.config"/>
    <add key="log4net.Config.Watch" value="True"/>
  </appSettings>
  
  <system.web>
    <compilation debug="true" targetFramework="4.6.1"/>
    <httpRuntime targetFramework="4.6.1"/>
  </system.web>
  <system.codedom>
    <compilers>
      <compiler language="c#;cs;csharp" extension=".cs"
        type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.7.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
        warningLevel="4" compilerOptions="/langversion:default /nowarn:1659;1699;1701"/>
      <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb"
        type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.7.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
        warningLevel="4" compilerOptions="/langversion:default /nowarn:41008 /define:_MYTYPE=\&quot;Web\&quot; /optionInfer+"/>
    </compilers>
  </system.codedom>
</configuration>

第六是:引用兩個重要的DLL

CSharpCode.SharpZipLib.dll

 BouncyCastle.Crypto.dll

第七就是:照搬官網SDK的相關類即可

最終顯示的支付效果頁面是:

 

 

 


免責聲明!

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



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