.NET银联支付开发(一):支付

来源:互联网 发布:linux编译android源码 编辑:程序博客网 时间:2024/06/05 19:36

目录(?)[+]

第一次做银联支付的开发,无论是支付还是退款都走了不少弯路,银联支付的sdk和demo并不容易让人明白如何调用sdk。所以,想写两篇文章把开发的过程分享出来供大家参考。这篇文章讲一下银联支付的网关支付产品前台交易类型的付款开发流程。闲话少叙,进入正题。

一、付款需要发送的报文(发送给银联的数据)

报文中包含以下信息:

1、基本信息,必须发送,可固定不变

1版本号versionNS5M按规范填写。固定填写2编码方式encodingANS1..20M填写报文使用的字符编码,UTF-8|GBK|GB2312|GB18030
若不填写,默认取值:UTF-8可取值UTF-8或GBK3证书IDcertIdN1..128M填写签名私钥证书的 Serial Number,
该值可通过银联提 供的 SDK 获取 4签名方法signMethodN2M非对称签名:01(表示采用 RSA 签名)固定填写:01(表示采用 RSA 签名)5签名signatureANS1..1024M填写对报文摘要的签名,可通过SDK生成签名填写对报文摘要的签名,可通过SDK生成签名6交易类型txnTypeN2M取值: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:查询更新加密公钥证书固定填写:017交易子类txnSubTypeN2M依据实际交易类型填写。默认取值:00固定填写:01:自助消费,
通过地址的方式区 分前台消费
和后台消费(含无跳转 支付)8产品类型bizTypeN6M依据实际业务场景填写
(目前仅使用后 4 位,签名 2 位 默认为 00)
 默认取值:000000 具体取值范围: 000201:B2C 网关支付 
000301:认证支付 2.0 000302:评级支付 000401:代付
 000501:代收 000601:账单支付 000801:
跨行收单 000901:绑定支付 001001:订购 000202:B2B0002019渠道类型channelTypeN2M05:语音07:互联网08:移动 16:数字机顶盒固定填写:07

2、商户信息


接入类型accessTypeN1M0:商户直连接入
1:收单机构接入
 2:平台商户接入0:普通商户直连接入
 1:收单机构接入2商户代码merIdAN15M已被批准加入银联互联网系统
的商户代码 3前台通知地址frontUrlANS1..256C前台返回商户结果时使用,
前台类交易需上送 
不支持换行符等不可见字符前台返回商户结果时使用,
例:https://xxx.xxx.com/xxx4后台通知地址backUrlANS1..256M后台返回商户结果时使用,
如上送,则发送商户后台交 易结果通知,
不支持换行符等不可见字符,
如需通过专 线通知,
需要在通知地址前面加上前缀:
专线的首字母 加竖线 ZX|后台返回商户结果时使用,
例:https://xxx.xxx.com/xxx5失败交易
前台跳转地址frontFailUrlANS1..256O前台消费交易若商户上送此字段,
则在支付失败时,
页面跳转至商户该URL
(不带交易信息,仅跳转),
支持HTTP与HTTPS协议,
互联网可访问前台消费交易若商户上送此字段,
则在支付失败时,
页面跳转至商户该URL
(不带交易信息,仅跳转),
支持HTTP与HTTPS协议,互联网可访问

3、订单信息


商户订单号orderIdAN8..40M商户订单号,不应含“-”或“_”商户端生成,例:12345asdf2交易币种currencyCodeAN3M币种格式必须为3位代码,
境内客户取值:156(人民币)固定填写:1563交易金额txnAmtN1..12M单位为分,不能带小数点,样例:1元送100单位为分,例:1元填写1004订单发送时间txnTimeYYYYMMDDHHmmssM必须使用当前北京时间
(年年年年月月日日时时分分秒秒)24小时制,
样例:20151123152540,北京时间 商户发送交易时间商户发送交易时间,例:201511181005055订单接收超时时间orderTimeoutN1..10O单位为毫秒,交易发生时,该笔交易在银联全渠道系统中有效的最长时间。
当距离交易发送时间超过该时间时,银联全渠道系统不再为该笔交易提供支付服务1、前台类消费交易时上送 
2、认证支付 2.0,后台交易时可选6支付超时时间payTimeoutYYYYMMDDHHmmssO订单支付超时时间,超过此时间用户支付成功的交易, 不通知商户,系统自动退款,
大约 5 个工作日金额返还 到用户账户非网银的交易:超过此时间未完成支付时银联页面会提示超时,不允许后续支付。
 跳转网银的交易银联无法控制,超过此时间用户支付成功的交易,不通知商户,系统自动退款,
大约5个工作日金额返还到用户账户。7发卡机构代码issInsCodeAN1..20C当账号类型为 02-存折时需填写 在前台类交易时填写默认银行代码,
支持直接跳转到网 银1、当帐号类型为02-存折时需填写 
2、在前台类交易时填写默认银行代码,支持直接跳转到网银。
银行简码列表参考附录C.1、C.2,其中C.2银行列表仅支持借记卡,例:工行填写ICBC8请求方自定义域reqReservedANS1..1024O商户自定义保留域,
交易应答时会原样返回商户自定义保留域,交易应答时会原样返回

4、机构信息


收单机构代码acqInsCodeAN8..11C已被批准加入银联互联网系统的收单机构代码,
适用于收单机构接入测试场景。
在商户接入时不返回此域,
且上送报文中不应出现此域。 2商户类别merCatCodeN4C填写MCC码,接入类型为收单机构接入时需上送 3商户名称merNameANS1..40C接入类型为收单机构接入时需上送,
不支持换行符等不可见字符 4商户简称merAbbrANS1..8C接入类型为收单机构接入时需上送最长 8 位,
不支持换行符等不可见字符

二、付款的应答报文(银联返回的数据)

1、应答报文的基本信息

1版本号versionNS5R按规范填写。 2编码方式encodingANS1..20R填写报文使用的字符编码,
UTF-8|GBK|GB2312|GB18030
若不填写,默认取值:UTF-8 3签名方法signMethodN2M非对称签名:01(表示采用 RSA 签名) 4签名signatureANS1..1024M填写对报文摘要的签名,可通过SDK生成签名 5交易类型txnTypeN2R取值:
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交易子类txnSubTypeN2R依据实际交易类型填写。默认取值:00 7产品类型bizTypeN6R依据实际业务场景填写(目前仅使用后 4 位,签名 2 位 默认为 00)
 默认取值:000000 具体取值范围: 000201:B2C 网关支付
 000301:认证支付 2.0 000302:评级支付 000401:代付 
000501:代收 000601:账单支付 
000801:跨行收单 
000901:绑定支付 001001:订购 
000202:B2B 8签名公钥 证书signPubKeyCertAN2048C使用 RSA 签名方式时必选,
此域填写银联签名公钥证书使用 RSA 签名方式时必选,
此域填写银联签名公钥证书。

2、应答报文的商户信息

1接入类型accessTypeN1R0:商户直连接入1:收单机构接入 2:平台商户接入 2商户代码merIdAN15R已被批准加入银联互联网系统的商户代码

3、应答报文的订单信息

1商户订单号orderIdAN8..40R商户订单号,不应含“-”或“_” 2交易币种currencyCodeAN3R币种格式必须为3位代码,境内客户取值:156(人民币)默认为 1563交易金额txnAmtN1..12R单位为分,不能带小数点,样例:1元送100 4订单发送时间txnTimeYYYYMMDDHHmmssR必须使用当前北京时间(年年年年月月日日时时分分秒秒)
24小时制,样例:20151123152540,北京时间 商户发送交易时间 5支付方式payTypeN4C默认不返回此域,如需要返此域,需要提交申请,
视商户配置返回,可在消费类交易中返回以下中的一种:
0001:认证支付 0002:快捷支付 0004:储值卡支付 
0005:IC卡支付 0201:网银支付 1001:牡丹畅通卡支付 
1002:中铁银通卡支付 0401:信用卡支付——暂定 
0402:小额临时支付 0403:认证支付 2.0
 0404:互联网订单手机支付 9000:其他无卡支付(如手机客户端支付)根据商户配置返回6账号accNoAN1..1024C交易账号。请求时使用加密公钥对交易账号加密,
并做 Base64 编码后上送;
应答时如需返回,则使用签名私钥 进行解密。
 前台交易可由银联页面采集,也可由商户上送并返显。 
如需锁定返显卡号,应通过保留域(reserved)上送卡 号锁定标识。根据商户配置返回7支付卡类型payCardTypeN2C消费交易,视商户配置返回。该域取值为:
 00:未知 01:借记账户 02:贷记账户 
03:准贷记账户 04:借贷合一账户 05:预付费账户 
06:半开放预付费账户根据商户配置返回8请求方自定义域reqReservedANS1..1024R商户自定义保留域,交易应答时会原样返回 9保留域reservedANS1..2048O保留域包含多个子域,所有子域需用“{}”包含,子域间以“&”符号链接。
格式如下:{子域名1=值&子域名2=值&子域名3=值}。
相关子域说明见注 5  

4、应答报文的通知信息

1查询流水号queryIdAN21M由银联返回,用于在后续类交易中唯一标识一笔交易消费交易的流水号,供后续查询用2应答码respCodeAN2M具体参见应答码定义章节 3应答信息respMsgANS1..256M填写具体的应答信息 4银联受理订单号tnN21C商户推送订单后银联系统返回该流水号,
商户调用支付控件时使用商户推送订单后银联移动支付 系统返回该流水号,
商户调用支付控件时使用

三、交易流程

相关交易流程如下:

1416391251671030464.png

交易步骤:

1、持卡人/企业浏览商户网页,选择消费交易;

2、商户组织交易报文,通过浏览器跳转至银联全渠道系统的支付页面;

3、持卡人/企业在银联全渠道系统支付页面输入相关交易信息;

4、全渠道系统完成用户的交易处理;

5、银联全渠道系统,将交易受理结果返回给商户;

6、因消费交易涉及资金清算,银联系统发送后台通知(交易结果)给商户。

四、真实开发实例

下面展示的代码为开发实例,代码展示顺序按照交易流程进行排列。

1、用户浏览页面,进行消费交易,对订单进行付款。页面提交订单信息表单的js代码

[javascript] view plain copy
 print?
  1. $(function () {  
  2.         //支付提交表单  
  3.         $("#paySubmit").click(function () {  
  4.             $("#mainForm").submit();  
  5.         });  
  6.     });  
2、接收订单数据的控制器代码

[csharp] view plain copy
 print?
  1.      public void GotoPay()  
  2.      {  
  3. Dictionary<string,string> param = new Dictionary<string,string>();  
  4. param["orderId"] = Request.Form["orderId"].ToString();//订单号  
  5. param["merId"] = merId; //商户号  
  6.   
  7. decimal orderSum = IOrderService.GetMoney(param["orderId"]);  
  8. param["txnAmt"] = ((int)orderSum*100).ToString(); //订单金额,单位为分  
  9.   
  10.   
  11. string payType = Request.Form["payType"].ToString();//支付类型  
  12.   
  13. if (payType==PayType.unionpay.ToString())   //银联支付  
  14. {  
  15.     UnionpayB2C.Unionpay(param);  
  16. }  
  17.      }  

3、支付层的银联支付处理

[csharp] view plain copy
 print?
  1. public static void Unionpay(Dictionary<stringstring> data)  
  2.         {  
  3.   
  4.             Dictionary<stringstring> param = new Dictionary<stringstring>();  
  5.   
  6.             //以下信息非特殊情况不需要改动  
  7.             param["version"] = "5.0.0";//版本号  
  8.             param["encoding"] = "UTF-8";//编码方式  
  9.             param["txnType"] = "01";//交易类型  
  10.             param["txnSubType"] = "01";//交易子类  
  11.             param["bizType"] = "000201";//业务类型  
  12.             param["signMethod"] = "01";//签名方法  
  13.             param["channelType"] = "08";//渠道类型  
  14.             param["accessType"] = "0";//接入类型  
  15.             param["frontUrl"] = SDKConfig.FrontUrl;  //前台通知地址        
  16.             param["backUrl"] = SDKConfig.BackUrl;  //后台通知地址  
  17.             param["currencyCode"] = "156";//交易币种  
  18.   
  19.             //TODO 以下信息需要填写  
  20.             param["merId"] = data["merId"];//商户号,请改自己的测试商户号,此处默认取demo演示页面传递的参数  
  21.             param["orderId"] = data["orderId"];//商户订单号,8-32位数字字母,不能含“-”或“_”,此处默认取demo演示页面传递的参数,可以自行定制规则  
  22.             param["txnTime"] = DateTime.Now.ToString("yyyyMMddHHmmss");//订单发送时间,格式为YYYYMMDDhhmmss,取北京时间,此处默认取demo演示页面传递的参数,参考取法: DateTime.Now.ToString("yyyyMMddHHmmss")  
  23.             param["txnAmt"] = data["txnAmt"];//交易金额,单位分,此处默认取demo演示页面传递的参数  
  24.             //param["reqReserved"] = "透传信息";//请求方保留域,透传字段,查询、通知、对账文件中均会原样出现,如有需要请启用并修改自己希望透传的数据  
  25.   
  26.             //TODO 其他特殊用法请查看 pages/api_01_gateway/special_use_purchase.htm  
  27.   
  28.               
  29.             AcpService.Sign(param, System.Text.Encoding.UTF8);  
  30.             string html = AcpService.CreateAutoFormHtml(SDKConfig.FrontTransUrl, param, System.Text.Encoding.UTF8);// 将SDKUtil产生的Html文档写入页面,从而引导用户浏览器重定向     
  31.             HttpContext.Current.Response.ContentEncoding = Encoding.UTF8; // 指定输出编码  
  32.             HttpContext.Current.Response.Write(html);  
  33.               
  34.         }  

4、接收银联应答报文的控制器代码

[csharp] view plain copy
 print?
  1. /// <summary>  
  2.         /// 前台交易返回结果  
  3.         /// </summary>  
  4.         [HttpPost]  
  5.         public ActionResult RcvResponse()  
  6.         {  
  7.             Dictionary<stringstring> result = UnionpayB2C.FrontRcvResponse();  
  8.               
  9.             JsonDTO json = new JsonDTO()  
  10.             {  
  11.                 Res = false,  
  12.                 Msg = "支付失败,请重新支付"  
  13.             };  
  14.   
  15.             if (result!=null)  
  16.             {  
  17.                 if (result[RespData.respCode.ToString()]==RespCode.success)     //交易成功  
  18.                 {  
  19.                     OrderDetailDTO dto = new OrderDetailDTO() {  
  20.                         OrderNum = result[RespData.orderId.ToString()],  
  21.                         OrderStatus = EnumOrderStatus.WatingReceive,  
  22.                         PayTime = Convert.ToDateTime(result[RespData.txnTime.ToString()])  
  23.                         //OrderNum = "20170217102907590110902120",  
  24.                         //OrderStatus = EnumOrderStatus.WatingReceive,  
  25.                         //PayTime = DateTime.Now  
  26.                     };  
  27.   
  28.                     json.Res=IOrderService.UpdateOrder(dto);  
  29.   
  30.                     if (json.Res)  
  31.                     {  
  32.                         IOrderService.AddOrderPayInfo(new OrderPayInfoDTO {  
  33.                             OrderID = result[RespData.orderId.ToString()],  
  34.                             QueryID = result[RespData.queryId.ToString()],  
  35.                             TxnTime = result[RespData.txnTime.ToString()],  
  36.                             TxnAmt =int.Parse(result[RespData.txnAmt.ToString()]),  
  37.                         });  
  38.   
  39.                         json.Msg = "支付成功";  
  40.                     }  
  41.   
  42.                     return View(json);  
  43.                 }  
  44.                 else  
  45.                 {  
  46.                     return View(json);  
  47.                 }  
  48.             }  
  49.   
  50.             return View(json);  
  51.         }  

5、支付层处理银联应答报文

[csharp] view plain copy
 print?
  1. /// <summary>  
  2.         /// 接收银联返回的前台交易结果报文  
  3.         /// </summary>  
  4.         public static Dictionary<stringstring> FrontRcvResponse()  
  5.         {  
  6.             if (HttpContext.Current.Request.HttpMethod == "POST")  
  7.             {  
  8.                 // 使用Dictionary保存参数  
  9.                 Dictionary<stringstring> resData = new Dictionary<stringstring>();  
  10.   
  11.                 NameValueCollection coll = HttpContext.Current.Request.Form;  
  12.   
  13.                 string[] requestItem = coll.AllKeys;  
  14.   
  15.                 for (int i = 0; i < requestItem.Length; i++)  
  16.                 {  
  17.                     resData.Add(requestItem[i], HttpContext.Current.Request.Form[requestItem[i]]);  
  18.                 }  
  19.   
  20.                 // 返回报文中不包含UPOG,表示Server端正确接收交易请求,则需要验证Server端返回报文的签名  
  21.                 if (AcpService.Validate(resData, System.Text.Encoding.UTF8))  
  22.                 {  
  23.                     //Response.Write("商户端验证返回报文签名成功\n");  
  24.   
  25.                     //string respcode = resData["respCode"]; //00、A6为成功,其余为失败。其他字段也可按此方式获取。  
  26.   
  27.                     //如果卡号我们业务配了会返回且配了需要加密的话,请按此方法解密  
  28.                     //if(resData.ContainsKey("accNo"))  
  29.                     //{  
  30.                     //    string accNo = SecurityUtil.DecryptData(resData["accNo"], System.Text.Encoding.UTF8);   
  31.                     //}  
  32.   
  33.                     //商户端根据返回报文内容处理自己的业务逻辑 ,DEMO此处只输出报文结果  
  34.                     return resData;  
  35.                 }  
  36.                 else  
  37.                 {  
  38.                     log.Error("商户端验证银联返回报文结果:验证签名失败");  
  39.                     return null;  
  40.                 }  
  41.   
  42.             }  
  43.             return null;  
  44.         }  

注:银联的测试环境和生产环境的配置是不同的,其中,前台交易通知地址配置为接收银联应答报文的地址。
FROM:http://blog.csdn.net/wangzl1163/article/details/56843645
原创粉丝点击