.NET银联支付开发(一):支付
第一次做银联支付的开发,无论是支付还是退款都走了不少弯路,银联支付的sdk和demo并不容易让人明白如何调用sdk。所以,想写两篇文章把开发的过程分享出来供大家参考。这篇文章讲一下银联支付的网关支付产品的前台交易类型的付款开发流程。闲话少叙,进入正题。
一、付款需要发送的报文(发送给银联的数据)
报文中包含以下信息:
1、基本信息,必须发送,可固定不变
1 | 版本号 | version | NS5 | M | 按规范填写。 | 固定填写 |
2 | 编码方式 | encoding | ANS1..20 | M |
填写报文使用的字符编码,UTF-8|GBK|GB2312|GB18030 若不填写,默认取值:UTF-8 |
可取值UTF-8或GBK |
3 | 证书ID | certId | N1..128 | M |
填写签名私钥证书的 Serial Number, 该值可通过银联提 供的 SDK 获取 |
|
4 | 签名方法 | signMethod | N2 | M | 非对称签名:01(表示采用 RSA 签名) | 固定填写:01(表示采用 RSA 签名) |
5 | 签名 | signature | ANS1..1024 | M | 填写对报文摘要的签名,可通过SDK生成签名 | 填写对报文摘要的签名,可通过SDK生成签名 |
6 | 交易类型 | txnType | N2 | M |
取值:00:查询交易,01:消费,02:预授权, 03:预授权完成,04:退货,05:圈存, 11:代收,12:代付, 13:账单支付,14:转账(保留),21:批量交易, 22:批量查询,31:消费撤销, 32:预授权撤销,33:预授权完成撤销, 71:余额查询,72:实名认证-建立绑定关系, 73:账单查询,74:解除绑定关系, 75:查询绑定关系,77:发送短信验证码交易, 78:开通查询交易,79:开通交易, 94:IC卡脚本通知 95:查询更新加密公钥证书 |
固定填写:01 |
7 | 交易子类 | txnSubType | N2 | M | 依据实际交易类型填写。默认取值:00 |
固定填写:01:自助消费, 通过地址的方式区 分前台消费 和后台消费(含无跳转 支付) |
8 | 产品类型 | bizType | N6 | M |
依据实际业务场景填写 (目前仅使用后 4 位,签名 2 位 默认为 00) 默认取值:000000 具体取值范围: 000201:B2C 网关支付 000301:认证支付 2.0 000302:评级支付 000401:代付 000501:代收 000601:账单支付 000801: 跨行收单 000901:绑定支付 001001:订购 000202:B2B |
000201 |
9 | 渠道类型 | channelType | N2 | M | 05:语音07:互联网08:移动 16:数字机顶盒 | 固定填写:07 |
2、商户信息
接入类型 |
accessType | N1 | M |
0:商户直连接入 1:收单机构接入 2:平台商户接入 |
0:普通商户直连接入 1:收单机构接入 |
|
2 | 商户代码 | merId | AN15 | M |
已被批准加入银联互联网系统 的商户代码 |
|
3 | 前台通知地址 | frontUrl | ANS1..256 | C |
前台返回商户结果时使用, 前台类交易需上送 不支持换行符等不可见字符 |
前台返回商户结果时使用, 例:https://xxx.xxx.com/xxx |
4 | 后台通知地址 | backUrl | ANS1..256 | M |
后台返回商户结果时使用, 如上送,则发送商户后台交 易结果通知, 不支持换行符等不可见字符, 如需通过专 线通知, 需要在通知地址前面加上前缀: 专线的首字母 加竖线 ZX| |
后台返回商户结果时使用, 例:https://xxx.xxx.com/xxx |
5 |
失败交易 前台跳转地址 |
frontFailUrl | ANS1..256 | O |
前台消费交易若商户上送此字段, 则在支付失败时, 页面跳转至商户该URL (不带交易信息,仅跳转), 支持HTTP与HTTPS协议, 互联网可访问 |
前台消费交易若商户上送此字段, 则在支付失败时, 页面跳转至商户该URL (不带交易信息,仅跳转), 支持HTTP与HTTPS协议,互联网可访问 |
3、订单信息
商户订单号 |
orderId | AN8..40 | M | 商户订单号,不应含“-”或“_” | 商户端生成,例:12345asdf | |
2 | 交易币种 | currencyCode | AN3 | M |
币种格式必须为3位代码, 境内客户取值:156(人民币) |
固定填写:156 |
3 | 交易金额 | txnAmt | N1..12 | M | 单位为分,不能带小数点,样例:1元送100 | 单位为分,例:1元填写100 |
4 | 订单发送时间 | txnTime | YYYYMMDDHHmmss | M |
必须使用当前北京时间 (年年年年月月日日时时分分秒秒)24小时制, 样例:20151123152540,北京时间 商户发送交易时间 |
商户发送交易时间,例:20151118100505 |
5 | 订单接收超时时间 | orderTimeout | N1..10 | O |
单位为毫秒,交易发生时,该笔交易在银联全渠道系统中有效的最长时间。 当距离交易发送时间超过该时间时,银联全渠道系统不再为该笔交易提供支付服务 |
1、前台类消费交易时上送 2、认证支付 2.0,后台交易时可选 |
6 | 支付超时时间 | payTimeout | YYYYMMDDHHmmss | O |
订单支付超时时间,超过此时间用户支付成功的交易, 不通知商户,系统自动退款, 大约 5 个工作日金额返还 到用户账户 |
非网银的交易:超过此时间未完成支付时银联页面会提示超时,不允许后续支付。 跳转网银的交易银联无法控制,超过此时间用户支付成功的交易,不通知商户,系统自动退款, 大约5个工作日金额返还到用户账户。 |
7 | 发卡机构代码 | issInsCode | AN1..20 | C |
当账号类型为 02-存折时需填写 在前台类交易时填写默认银行代码, 支持直接跳转到网 银 |
1、当帐号类型为02-存折时需填写 2、在前台类交易时填写默认银行代码,支持直接跳转到网银。 银行简码列表参考附录C.1、C.2,其中C.2银行列表仅支持借记卡,例:工行填写ICBC |
8 | 请求方自定义域 | reqReserved | ANS1..1024 | O |
商户自定义保留域, 交易应答时会原样返回 |
商户自定义保留域,交易应答时会原样返回 |
4、机构信息
收单机构代码 |
acqInsCode | AN8..11 | C |
已被批准加入银联互联网系统的收单机构代码, 适用于收单机构接入测试场景。 在商户接入时不返回此域, 且上送报文中不应出现此域。 |
||
2 | 商户类别 | merCatCode | N4 | C | 填写MCC码,接入类型为收单机构接入时需上送 | |
3 | 商户名称 | merName | ANS1..40 | C |
接入类型为收单机构接入时需上送, 不支持换行符等不可见字符 |
|
4 | 商户简称 | merAbbr | ANS1..8 | C |
接入类型为收单机构接入时需上送最长 8 位, 不支持换行符等不可见字符 |
二、付款的应答报文(银联返回的数据)
1、应答报文的基本信息
1 | 版本号 | version | NS5 | R | 按规范填写。 | |
2 | 编码方式 | encoding | ANS1..20 | R |
填写报文使用的字符编码, UTF-8|GBK|GB2312|GB18030 若不填写,默认取值:UTF-8 |
|
3 | 签名方法 | signMethod | N2 | M | 非对称签名:01(表示采用 RSA 签名) | |
4 | 签名 | signature | ANS1..1024 | M | 填写对报文摘要的签名,可通过SDK生成签名 | |
5 | 交易类型 | txnType | N2 | R |
取值: 00:查询交易,01:消费,02:预授权, 03:预授权完成,04:退货,05:圈存, 11:代收,12:代付,13:账单支付, 14:转账(保留),21:批量交易,22:批量查询, 31:消费撤销,32:预授权撤销,33:预授权完成撤销, 71:余额查询,72:实名认证-建立绑定关系, 73:账单查询,74:解除绑定关系,75:查询绑定关系, 77:发送短信验证码交易,78:开通查询交易, 79:开通交易,94:IC卡脚本通知 95:查询更新加密公钥证书 |
|
6 | 交易子类 | txnSubType | N2 | R | 依据实际交易类型填写。默认取值:00 | |
7 | 产品类型 | bizType | N6 | R |
依据实际业务场景填写(目前仅使用后 4 位,签名 2 位 默认为 00) 默认取值:000000 具体取值范围: 000201:B2C 网关支付 000301:认证支付 2.0 000302:评级支付 000401:代付 000501:代收 000601:账单支付 000801:跨行收单 000901:绑定支付 001001:订购 000202:B2B |
|
8 | 签名公钥 证书 | signPubKeyCert | AN2048 | C |
使用 RSA 签名方式时必选, 此域填写银联签名公钥证书 |
使用 RSA 签名方式时必选, 此域填写银联签名公钥证书。 |
2、应答报文的商户信息
1 | 接入类型 | accessType | N1 | R | 0:商户直连接入1:收单机构接入 2:平台商户接入 | |
2 | 商户代码 | merId | AN15 | R | 已被批准加入银联互联网系统的商户代码 |
3、应答报文的订单信息
1 | 商户订单号 | orderId | AN8..40 | R | 商户订单号,不应含“-”或“_” | |
2 | 交易币种 | currencyCode | AN3 | R | 币种格式必须为3位代码,境内客户取值:156(人民币) | 默认为 156 |
3 | 交易金额 | txnAmt | N1..12 | R | 单位为分,不能带小数点,样例:1元送100 | |
4 | 订单发送时间 | txnTime | YYYYMMDDHHmmss | R |
必须使用当前北京时间(年年年年月月日日时时分分秒秒) 24小时制,样例:20151123152540,北京时间 商户发送交易时间 |
|
5 | 支付方式 | payType | N4 | C |
默认不返回此域,如需要返此域,需要提交申请, 视商户配置返回,可在消费类交易中返回以下中的一种: 0001:认证支付 0002:快捷支付 0004:储值卡支付 0005:IC卡支付 0201:网银支付 1001:牡丹畅通卡支付 1002:中铁银通卡支付 0401:信用卡支付——暂定 0402:小额临时支付 0403:认证支付 2.0 0404:互联网订单手机支付 9000:其他无卡支付(如手机客户端支付) |
根据商户配置返回 |
6 | 账号 | accNo | AN1..1024 | C |
交易账号。请求时使用加密公钥对交易账号加密, 并做 Base64 编码后上送; 应答时如需返回,则使用签名私钥 进行解密。 前台交易可由银联页面采集,也可由商户上送并返显。 如需锁定返显卡号,应通过保留域(reserved)上送卡 号锁定标识。 |
根据商户配置返回 |
7 | 支付卡类型 | payCardType | N2 | C |
消费交易,视商户配置返回。该域取值为: 00:未知 01:借记账户 02:贷记账户 03:准贷记账户 04:借贷合一账户 05:预付费账户 06:半开放预付费账户 |
根据商户配置返回 |
8 | 请求方自定义域 | reqReserved | ANS1..1024 | R | 商户自定义保留域,交易应答时会原样返回 | |
9 | 保留域 | reserved | ANS1..2048 | O |
保留域包含多个子域,所有子域需用“{}”包含,子域间以“&”符号链接。 格式如下:{子域名1=值&子域名2=值&子域名3=值}。 相关子域说明见注 5 |
|
4、应答报文的通知信息
1 | 查询流水号 | queryId | AN21 | M | 由银联返回,用于在后续类交易中唯一标识一笔交易 | 消费交易的流水号,供后续查询用 |
2 | 应答码 | respCode | AN2 | M | 具体参见应答码定义章节 | |
3 | 应答信息 | respMsg | ANS1..256 | M | 填写具体的应答信息 | |
4 | 银联受理订单号 | tn | N21 | C |
商户推送订单后银联系统返回该流水号, 商户调用支付控件时使用 |
商户推送订单后银联移动支付 系统返回该流水号, 商户调用支付控件时使用 |
三、交易流程
相关交易流程如下:
交易步骤:
1、持卡人/企业浏览商户网页,选择消费交易;
2、商户组织交易报文,通过浏览器跳转至银联全渠道系统的支付页面;
3、持卡人/企业在银联全渠道系统支付页面输入相关交易信息;
4、全渠道系统完成用户的交易处理;
5、银联全渠道系统,将交易受理结果返回给商户;
6、因消费交易涉及资金清算,银联系统发送后台通知(交易结果)给商户。
四、真实开发实例
下面展示的代码为开发实例,代码展示顺序按照交易流程进行排列。
1、用户浏览页面,进行消费交易,对订单进行付款。页面提交订单信息表单的js代码
$(function () {//支付提交表单$("#paySubmit").click(function () {$("#mainForm").submit();});});
2、接收订单数据的控制器代码
public void GotoPay(){Dictionary<string,string> param = new Dictionary<string,string>();param["orderId"] = Request.Form["orderId"].ToString();//订单号param["merId"] = merId; //商户号decimal orderSum = IOrderService.GetMoney(param["orderId"]);param["txnAmt"] = ((int)orderSum*100).ToString(); //订单金额,单位为分string payType = Request.Form["payType"].ToString();//支付类型if (payType==PayType.unionpay.ToString()) //银联支付{UnionpayB2C.Unionpay(param);}}
3、支付层的银联支付处理
public static void Unionpay(Dictionary<string, string> data){Dictionary<string, string> param = new Dictionary<string, string>();//以下信息非特殊情况不需要改动param["version"] = "5.0.0";//版本号param["encoding"] = "UTF-8";//编码方式param["txnType"] = "01";//交易类型param["txnSubType"] = "01";//交易子类param["bizType"] = "000201";//业务类型param["signMethod"] = "01";//签名方法param["channelType"] = "08";//渠道类型param["accessType"] = "0";//接入类型param["frontUrl"] = SDKConfig.FrontUrl; //前台通知地址 param["backUrl"] = SDKConfig.BackUrl; //后台通知地址param["currencyCode"] = "156";//交易币种//TODO 以下信息需要填写param["merId"] = data["merId"];//商户号,请改自己的测试商户号,此处默认取demo演示页面传递的参数param["orderId"] = data["orderId"];//商户订单号,8-32位数字字母,不能含“-”或“_”,此处默认取demo演示页面传递的参数,可以自行定制规则param["txnTime"] = DateTime.Now.ToString("yyyyMMddHHmmss");//订单发送时间,格式为YYYYMMDDhhmmss,取北京时间,此处默认取demo演示页面传递的参数,参考取法: DateTime.Now.ToString("yyyyMMddHHmmss")param["txnAmt"] = data["txnAmt"];//交易金额,单位分,此处默认取demo演示页面传递的参数//param["reqReserved"] = "透传信息";//请求方保留域,透传字段,查询、通知、对账文件中均会原样出现,如有需要请启用并修改自己希望透传的数据//TODO 其他特殊用法请查看 pages/api_01_gateway/special_use_purchase.htmAcpService.Sign(param, System.Text.Encoding.UTF8);string html = AcpService.CreateAutoFormHtml(SDKConfig.FrontTransUrl, param, System.Text.Encoding.UTF8);// 将SDKUtil产生的Html文档写入页面,从而引导用户浏览器重定向 HttpContext.Current.Response.ContentEncoding = Encoding.UTF8; // 指定输出编码HttpContext.Current.Response.Write(html);}
4、接收银联应答报文的控制器代码
/// <summary>/// 前台交易返回结果/// </summary>[HttpPost]public ActionResult RcvResponse(){Dictionary<string, string> result = UnionpayB2C.FrontRcvResponse();JsonDTO json = new JsonDTO(){Res = false,Msg = "支付失败,请重新支付"};if (result!=null){if (result[RespData.respCode.ToString()]==RespCode.success) //交易成功{OrderDetailDTO dto = new OrderDetailDTO() {OrderNum = result[RespData.orderId.ToString()],OrderStatus = EnumOrderStatus.WatingReceive,PayTime = Convert.ToDateTime(result[RespData.txnTime.ToString()])//OrderNum = "20170217102907590110902120",//OrderStatus = EnumOrderStatus.WatingReceive,//PayTime = DateTime.Now};json.Res=IOrderService.UpdateOrder(dto);if (json.Res){IOrderService.AddOrderPayInfo(new OrderPayInfoDTO {OrderID = result[RespData.orderId.ToString()],QueryID = result[RespData.queryId.ToString()],TxnTime = result[RespData.txnTime.ToString()],TxnAmt =int.Parse(result[RespData.txnAmt.ToString()]),});json.Msg = "支付成功";}return View(json);}else{return View(json);}}return View(json);}
5、支付层处理银联应答报文
/// <summary>/// 接收银联返回的前台交易结果报文/// </summary>public static Dictionary<string, string> FrontRcvResponse(){if (HttpContext.Current.Request.HttpMethod == "POST"){// 使用Dictionary保存参数Dictionary<string, string> resData = new Dictionary<string, string>();NameValueCollection coll = HttpContext.Current.Request.Form;string[] requestItem = coll.AllKeys;for (int i = 0; i < requestItem.Length; i++){resData.Add(requestItem[i], HttpContext.Current.Request.Form[requestItem[i]]);}// 返回报文中不包含UPOG,表示Server端正确接收交易请求,则需要验证Server端返回报文的签名if (AcpService.Validate(resData, System.Text.Encoding.UTF8)){//Response.Write("商户端验证返回报文签名成功\n");//string respcode = resData["respCode"]; //00、A6为成功,其余为失败。其他字段也可按此方式获取。//如果卡号我们业务配了会返回且配了需要加密的话,请按此方法解密//if(resData.ContainsKey("accNo"))//{// string accNo = SecurityUtil.DecryptData(resData["accNo"], System.Text.Encoding.UTF8); //}//商户端根据返回报文内容处理自己的业务逻辑 ,DEMO此处只输出报文结果return resData;}else{log.Error("商户端验证银联返回报文结果:验证签名失败");return null;}}return null;}
注:银联的测试环境和生产环境的配置是不同的,其中,前台交易通知地址配置为接收银联应答报文的地址。
.NET银联支付开发(一):支付相关推荐
- 微信分享与支付开发详解
//第一部分 微信分享 //参考:https://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html //步骤一:绑定域名//先 ...
- 银联支付开发、使用的一些总结
现在的网页支付(PC和微信H5)和app支付,用的比较多的是微信支付.银联支付和支付宝支付,其余的是这些支付的第三方支付,我目前了解的只有这么多.我目前做了银联支付和微信支付,这里说一些银联支付的开发 ...
- 微信支付及支付宝支付开发指南
从开始学习android开始到现在还没搞过三方支付,感觉挺遗憾的.看到最近有几篇关于微信支付和支付宝支付的文章,稍微进行一下整合,供大家参考. ---------------------------- ...
- 开源商城WSTMart支付开发研究[转]
WSTMart是基于thinkphp5开发的一个开源商城,他分为开源版和授权版,授权版功能比开源版强大,但是需要付费之后才能开放源代码.这里我们不讨论授权版的,仅仅以WSTMart开源版作为研究对象. ...
- Android 银联控件支付开发流程
目录 一:介绍 二:支付流程介绍 三:下载银联SDK 四:导入开发SDK 4.1 如果项目开发使用的Eclipse软件,导入步骤如下: 4.2 如果项目开发使用的Android Studio软件,导入 ...
- 微信支付之Native支付和JSAPI支付详细开发步骤!
目录标题 微信支付之扫码Native支付与JSAPI支付 进入主题 一.Native支付 1. 使用场景 2. 开发步骤 3. 开始开发 二.JSAPI支付 1. 使用场景 2. 开发步骤 3. 开始 ...
- python 支付宝支付 无效根证书_python实现银联支付和支付宝支付接入
本文实例为大家分享了python银联支付和支付宝支付接入的具体代码,供大家参考,具体内容如下 前置条件:需要安装Python的OpenSSL模块,我使用的版本是16.1.0,可以使用pip insta ...
- java 银联支付反馈,微信支付/支付宝支付/银联支付,对比加总结(Java服务端)
今天来说讲支付.前端 工做到如今,接入过好几个项目的支付,其中涉及到了微信支付.支付宝支付.银联支付.服务器 三种支付的对接感觉其实总体上大同小异.都遵循同一个流程:微信 1).商户APP向商户服务器 ...
- php实现支付宝支付接口,PHP实现个人支付宝支付开发(二)
在前面的文章<PHP实现个人支付宝支付开发(一)>中,我们为大家简单介绍了通过第三方接口平台码支付来实现个人支付宝支付功能的交易流程. 下面我们继续结合图文,给大家介绍通过码支付实现PHP ...
- 微信服务号 微信支付开发
微信支付,须要通过微信支付验证 眼下.支付仅限服务号, 做微信支付开发,主要看开发文档 统一下单. 订单查询 退款等 1.发起支付.都是通过h5发起的,首先获取prepay_id 发起支付,须要统一下 ...
最新文章
- HTML的标签描述21
- python通过opencv使用图片制作简单视频(亲测)
- 设计模式系列--Strategy
- 如何全面的把握一个系统的异常处理
- Android对接实现内网无纸化会议|智慧教室|实时同屏功能
- c++ tcp 封装_关于TCP三次握手和四次挥手问题,求你别再问了问了...
- 常见顺口溜 / 歇后语
- aiohttp/flask python后端单元测试,单元测试覆盖率测试
- sklearn中的xgboost_RF/GBDT/XGBoost/LightGBM简单总结
- java pojo类
- MXF Operational Pattern 1a (OP1a)
- word里面搜狗输入法突然不见了
- RGB Triplets(后缀和)
- UART2USB芯片PL2303驱动安装说明
- 火狐的调试利器-----Firebug
- 人类为什么不再登月了?
- 黑人是晒黑的吗_当您是互联网上的黑人时,无处可逃
- 软件开发项目管理工具哪个好?
- 2058三国佚事——巴蜀之危
- 软件测试面试常见问题(1)
热门文章
- python中文乱码问题大总结
- 沟通CTBS立白集团远程接入成功案例
- 大数据技术原理与应用——林子雨老师MOOC知识点一
- 安装基于Ubuntu的微信小程序开发工具
- java实现电子面单pdf生成_电子面单打印功能实现方法
- 浅谈C#tabcontrol应用
- itunes计算机无法启动,打开电脑中的iTunes显示Apple Mobile Device Service无法启动如何解决...
- Inkscape将位图转换为矢量图
- matlab常微分方程2次初值问题,MATLAB求解二阶常微分方程初值问题
- 计算机网络arp表作用,arp映射表是什么?有什么作用