银联在线支付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的相关类即可

最终显示的支付效果页面是:

原文地址:https://www.cnblogs.com/Warmsunshine/p/8444746.html

时间: 2024-10-11 09:12:01

银联在线支付B2C UnionPay.NET的相关文章

PHP商城网站绑定中国银联在线支付接口

PHP商城网站绑定中国银联在线支付接口用的越来越广泛,我们公司这几年给客户建立过很多的商城网站,今天就分析下怎么为自己的PHP商城网站接入中国银联在线支付端的接口.在使用前我们必须先申请成为中国银联在线支付的商户. 第一步:下载中国银联官方PHP支付接口文件 进入中国银联在线官方网站的商户服务网站,下载PHP的技术资料端口文件(https://online.unionpay.com/mer/pages/merser/index.jsp这是中国银联在线支付商户服务网站),点击右上角的“文档下载”

Phonegap 之 iOS银联在线支付(js调用ios端银联支付控件)

Phonegap项目,做支付的时候,当把网站打包到ios或android端成app后,在app上通过wap调用银联在线存在一个问题: 就是当从银联支付成功后,再从服务器返回到app客户端就很难实现. wap银联支付流程是这样:客户端---> 服务器(构建支付请求)--> 银联支付 ---> 返回到服务端(处理支付结果).所以对于手机网站银联支付没有问题,但是对于ios端app和android端app, 再通过wap支付,发现支付成功后,很难在回到app客户端了. 所以这里就必须借助Pho

银联在线支付----测试商户账号注册

一. 测试账号注册 在中国银联商户服务系统的首页,注册一个账号,供我们测试账号使用. 注册地址:https://merchant.unionpay.com/cas/login  .              注册号后,里面有详细的API和测试介绍. 下面是我注册成功后的测试参数信息.  测试商户号:     777290058112538      测试证书  : 商户私钥证书(签名使用,密码:000000)银联公钥证书(签名使用)  测试入口地址:  前台交易请求地址: https://101

中国银联在线支付接口开发——前台支付

银联技术服务官网:https://open.unionpay.com/ajweb/index 在官网"帮助中心"->"下载"中下载:跳转网关支付产品技术开发包1.11.rar.网关支付产品示例代码_java_1.1.rar 如想使用银联测试接口需要在技术服务官网注册 登录后选择页面右上角"我的测试"-> "测试参数",下载并导入证书 根据"测试参数"提供的商户号和证书存放位置等配置示例代码 选择

【收藏】银联在线支付商户UPMP接口的使用和说明

[转载]http://www.dodobook.net/php/1110 相关的文档可以参阅.http://202.101.25.178:8080/sim/docs/ 这个接口文档还是比较完备的,相信很多技术人员稍加摸索,就能实现了. 目录结构为 Upmp ----upmp_config.php ----upmp_core.php ----UpmpService.php ----notify_url.php 直接上代码:upmp_config.php <?php /** * 类名:配置类 * 功

银联在线支付---利用测试案例代码模拟测试应用

一.工程搭建 新建一个Web工程,命名为PayOnLine,把你下载好的案例代码拷贝到你的工程下,我的代码目录如下: acp_sdk.properties配置文件需要放在类根路劲下,里面的参数配置信息,下面是案例提供的配置提示: 0. 注意: 1)依赖包和upacp_sdk-1.0.0.jar都需加到buildpath. 2)acp_sdk.properties放到src根目录下.另外如果用的不是eclipse/MyEclipse可能这个文件默认不会被拷贝到classes目录下,导致加载不到这个

简单记录:银联在线支付

1.下载ChinaPay的dll文件,解压放到BIN目录下,共4个文件. 2.引用ChinaPay_Net.dll到项目. 3.申请到的key放到网站,本例是放到根目录key文件夹下: 4.添加类: using System; using System.Text; using System.Web; using ChinaPay_Net; /// <summary> ///Chinapay 的摘要说明 /// </summary> public class Chinapay { p

PHP在线支付

php网站如何做个页面接入网银在线支付接口? =>有两个是用来接收网银在线的反馈传递页面(这两个页面一般是进行下面的第四步)一个是配置文件一个是网银在线的一些函数(一般不需要修改)1 先做商品支付页面2 用户确定提交订单(同时本地写入数据库一个唯一的订单号,并设定成未支付状态)3.提交订单到网银在线支付页面4用户支付成功后返回网站操作页面(对用户进行操作,数据中的当前订单更改成已支付) 支付宝: 网址:https://b.alipay.com/order/productDetail.htm?pr

github student pack中的digital ocean可以使用银联卡支付

申请了 github student pack却因为一直没有visita信用卡,而无法使用digital ocean的 $50,一直到今天,用中国银行借记卡成功支付. 方法是: (1)注册paypal账号,不需要绑定银行卡或信用卡. (2)打开digital ocean的welcome页面,那里会提示需要打入$5,支付方式可选“信用卡/借记卡”或者 “paypal”,选择paypal (3)进入支付页面,登陆paypal账户,输入银联卡(我的是中国银行)的卡号,然后填入后边的一些相关信息.点击“