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

今天研究了下银联在线支付功能,特地记录下以表码农们还在坚守岗位。此功能主要是一般的.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. cmd 运行(打包后的)java程序

    package cn.imeixi.chapter1.exer; public class Exer10PrintArgs { public static void main(String[] arg ...

  2. 【note】EtherCAT Configurator 使用之主菜单介绍

    EtherCAT配置器是一个工具,用于配置EtherCAT总线. 工具管理一个或多个EtherCAT主设备和连接到该主站的EtherCAT从站.配置的设备能够脱机或能够通过扫描EtherCAT现场总线 ...

  3. docker build 指定dockerfile

    1. Dockerfile文件使用 docker build命令会根据Dockerfile文件及上下文构建新Docker镜像.构建上下文是指Dockerfile所在的本地路径或一个URL(Git仓库地 ...

  4. uitableview 和UISearchBar 下拉提示结合使用

    自定cell的代码 餐厅的实体和餐厅对应控件的frame #import <Foundation/Foundation.h> @class RestaurantFrame; @interf ...

  5. 预加载与智能预加载(iOS)

    来源:Draveness(@Draveness) 链接:http://www.jianshu.com/p/1519a5302141 前两次的分享分别介绍了 ASDK 对于渲染的优化以及 ASDK 中使 ...

  6. 【LeetCode】217. Contains Duplicate (2 solutions)

    Contains Duplicate Given an array of integers, find if the array contains any duplicates. Your funct ...

  7. xfsdump命令使用

    一:使用xfsdump备份和恢复xfs文件系统 首先了解一下xfsdump的备份级别有以下两种,默认为0(即完全备份) 0                                    完全备 ...

  8. Git的图形化工具使用教程

    虽然感觉并没有什么暖用,但姑且还是写出来留作纪念好了 Git这种分布式版本控制系统最适合的就是单枪匹马搞开发的选手,不需要服务器,下载个git和图形工具,网速快十分钟就能搞定开始愉快的开发工作.我在搭 ...

  9. 【struts2】拦截器基础

    1)拦截器是什么? 拦截器(Interceptor)是Struts2最强大的特性之一,它是一种可以让你在Action执行之前和Result执行之后进行一些功能处理的机制.来回顾一下官方给出的Strut ...

  10. golang ---image

    package main import ( "image" "image/color" "image/gif" "os" ...