新春即将来临,首先给大家拜个早年,祝攻城狮们新年快乐、万事如意、合家欢乐、团团圆圆、幸福健康、来年更能大展宏图 实现各自的梦想! 同时预祝各大科技公司大佬们事业蒸蒸日上、公司转型突破创新、冲出突围带领员工们早日实现上市梦想!

今天研究了下银联在线支付功能,特地记录下以表码农们还在坚守岗位。此功能主要是一般的.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"] = "";//交易类型
param["txnSubType"] = "";//交易子类
param["bizType"] = "";//业务类型
param["signMethod"] = SDKConfig.SignMethod;//签名方法
param["channelType"] = "";//渠道类型
param["accessType"] = "";//接入类型
param["frontUrl"] = SDKConfig.FrontUrl; //前台通知地址
param["backUrl"] = SDKConfig.BackUrl; //后台通知地址
param["currencyCode"] = "";//交易币种 // 订单超时时间。
// 超过此时间后,除网银交易外,其他交易银联系统会拒绝受理,提示超时。 跳转银行网银交易如果超时后交易成功,会自动退款,大约5个工作日金额返还到持卡人账户。
// 此时间建议取支付时的北京时间加15分钟。
// 超过超时时间调查询接口应答origRespCode不是A6或者00的就可以判断为失败。
param["payTimeout"] = DateTime.Now.AddMinutes().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 = ; 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 = ; 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 = ; 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 = ; 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的相关类即可

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

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

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

    Phonegap项目,做支付的时候,当把网站打包到ios或android端成app后,在app上通过wap调用银联在线存在一个问题: 就是当从银联支付成功后,再从服务器返回到app客户端就很难实现. ...

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

    申请了 github student pack却因为一直没有visita信用卡,而无法使用digital ocean的 $50,一直到今天,用中国银行借记卡成功支付. 方法是: (1)注册paypal ...

  3. 银联在线 网关支付 (JAVA版)

    这一版本的编写是在我上一次博客的基础上写的,有不懂得童鞋可以先看下我的原先在线支付的博客,熟悉下:http://blog.csdn.net/yulei_qq/article/details/45197 ...

  4. Atitit 在线支付系统功能设计原理与解决方案 与目录

    Atitit 在线支付系统功能设计原理与解决方案 与目录 1.1. 支付系统1 1.2. 独立的支付子体系..微服务架构..1 1.3. 参考书籍1 支付战争 [The PayPal Wars:Bat ...

  5. php银联网页支付实现方法

         本文实例讲述了php银联网页支付实现方法.分享给大家供大家参考.具体分析如下: 这里介绍的银联WAP支付功能,仅限消费功能. 1. PHP代码如下: 复制代码代码如下: <?phpna ...

  6. php支付宝在线支付接口开发教程【转】

    php支付宝在线支付接口开发教程 这篇文章主要为大家详细介绍了php支付宝在线支付接口开发教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下   1.什么是第三方支付 所谓第三方支付,就是一些和各 ...

  7. 【drp 1】使用易宝实现在线支付

    导读:在很多网站上,都会涉及到在线支付的功能,总所周知的有:淘宝.天猫.京东等等.我们常见的支付方式有支付宝.微信钱包.银行卡支付等.本篇博客,将介绍一种使用易宝第三方软件进行在线支付的功能. 一.基 ...

  8. Android集成支付宝接口 实现在线支付

    手机的在线支付,被认为是2012年最看好的功能,我个人认为这也是移动互联网较传统互联网将会大放光彩的一个功能. 人人有手机,人人携带手机,花钱买东西,不再需要取钱付现,不再需要回家上网银,想买什么,扫 ...

  9. 在线支付接口之PHP支付宝接口开发简单介绍

    php100:92:在线支付接口之PHP支付宝接口开发 支付接口一般是第三方提供的代收款.付款的平台,可以通过支付接口帮助企业或个人利用一切可以使用的支付方式.常见支付平台:支付宝.快钱.云网支付.财 ...

随机推荐

  1. codevs 2010 求后序遍历

    时间限制: 1 s空间限制: 64000 KB题目描述 Description输入一棵二叉树的先序和中序遍历序列,输出其后序遍历序列.输入描述 Input Description共两行,第一行一个字符 ...

  2. Android从无知到有知——NO.3

    昨天看了下几种常见的布局,类似于曾经学的html.关于css+div没有接触太多,但这几种布局都比較简单.仅仅要逻辑没有太大问题就能整出来. 相对布局是我们平时默认的布局,也是最经常使用的.前边做的& ...

  3. linux下淘宝安全控件问题

    2009-09-21  我的环境:ubuntu9.04 firefox3.0.14   下载压缩包http://blog.alipay.com/wp-content/2008/10/aliedit.t ...

  4. sqlserver查询数据表中每个类别最新的一条记录

    表tariff_info, 原始数据: 想要的结果:以start_time时间倒序排序, 以code分类, 查询每一类最新的一条记录 sql: SELECT a.* FROM TARIFF_INFO ...

  5. 使用Idea添加PYTHONPATH的一种方案

    工作中我们常常需要更改PYTHONPATH,为项目添加一些依赖. 而不同的项目依赖的PYTHONPATH是不一样的,这就导致项目之间的PYTHONPATH发生混乱. 另一方面,有的电脑上PYTHON2 ...

  6. Fisher准则一维聚类

    在做FAQ系统时,用户输入一个查询之后,返回若干个打好分数的文档.对于这些文档,有些是应该输出的,有些是不应该输出的.那么应该在什么地方截断呢? 这个问题其实是一个聚类问题,在一维空间中把若干个点聚成 ...

  7. 你想要的iOS 小技巧总结

    UITableView的Group样式下顶部空白处理 //分组列表头部空白处理 UIView *view = [[UIView alloc] initWithFrame:CGRectMake(, , ...

  8. postmessage and sendmessage

    从msdn上看二者的解释: postmessage : Places (posts) a message in the message queue associated with the thread ...

  9. libev loop_init分析

    尼玛 C语言学不好真是桑心呐! 看了libev的代码有一种想死的感觉,但是还是要硬着头皮看下去,一定看完! /* initialise a loop structure, must be zero-i ...

  10. 业务、架构、技术,我们应该关注什么 Java和.Net的优势劣势简单看法 市场经济决定,商业之道即是软件之道,市场的需求决定着软件技术的发展 利益决定着选择应用新技术

    业务.架构.技术,我们应该关注什么 一个企业存在的必然和前提就是获取企业生成的利润,怎么样合法合理取得利润呢,企业怎么样生存下去呢,很简单,为客户提供等值的产品与服务,客户支付你相应的报酬. 我们是从 ...