zoukankan      html  css  js  c++  java
  • 说说第三方支付接口开发及开发中遇到的坑爹问题

    前言

      最近在做公司的支付接口,从微信支付到各种第三方的支付接口,还有点卡等支付,微信支付文档相对比较详细,虽然也不少坑,被各路开发人员吐槽,但是填的人多啊,所以是最好开发的,但是公司还有用到一些第三方的网页支付接口,然后遇到很多坑,忍不住想吐槽一下。

    一、第三方支付流程

      各种支付的文档,业务流程图有的过于简单,有的真的是复杂的不要不要的,开发者看了也是醉,写这些文档的人好像从来不会考虑看的人的感受,所以我觉得有必要在这里简单介绍,我觉得给开发者的流程图大致应该是这样的,而不是一堆用不上的东西在开发文档里面。

    再简单化就是:获取接口信息(银行列表等)-》提交参数及签名-》获取结果(需要验证签名)

    我们做接口开发  能力多么强的程序员,不看文档也是没有办法做的,签名算法是人家做接口的人提供的,参数也是人家命名的,所以学会看文档是很重要的,看过大量别人写的文档,我们才可以写出简单明了的文档了,这是经验之谈。

    二、开发中遇到的那些坑

    有写坑是文档的坑,有些坑是人为的坑,反正坑你没商量。

    1.微信支付

      之前做微信支付,从官方文档下载了asp.net的开发demo,替换好了参数,按照官方的步骤一步一步来,想先测试支付成功后,再对接系统,坑的是我恰好用的是苹果手机,恰好官方asp.net的demo里面支付按钮拖的是一个控件,在安卓上支付没有问题,在苹果手机上却不可以,然后我再不知情的情况下我硬是搞了半天,看看代码注释明显不是C#的注释方式,多半是做java的抓过来把java版本修改的。然后网上搜了一下,发现好多人被这个问题坑到!

    2.环讯支付

      ①环讯支付提供了测试的商户id和密钥,并且提供了webservice接口获取对应银行的名称和代号,方便开发直连支付模式,但是根据接口,获取到的银行列表的银行代号竟然有重复的,我一直以为是我接口调用有问题,再三确认,真的是提供接口的太随意了;②支付接口的商户号下来了,我尝试着去支付,改了正式的接口和商户信息,然后支付,结果链接失败,错误码#E008,我查文档,没有,百度,没有,找人问,不知道···然后我咨询他们官方客服,官方客服转接到技术客服,反正各种麻烦,对方说是域名没绑定,我也是醉。公司让我开发,就给了文档和商户信息,其他的都没有,我以为只要微信才需要绑定域名呢。然后让客服给个错误码的文档,对方非要我提供商户号才肯给····不知道这错误码还是什么机密么?

    3.新生支付

      ①这个官方提供的文档就更离谱了,我看了文档是2011年写的,pdf是2013年生成的,然后上面也是提供了测试的地址,地址不是真的可访问的地址,需要修改hosts文件,重定向到指定的域名。我做好了准备测试的时候,发现一直提示网页链接错误。纳闷,当然我肯定是从自己身上找问题,是不是host文件修改的不对,或者是其他什么问题。经过我再三确认 各种ping 发现测试地址是不可用的,于是找度年,没结果,问小伙伴,没结果,好了,该去找官方客服,然后对接技术客服,问他们要最新的文档,及测试地址是换了么?然后对方给我的答复是测试地址是不可用的,我现在在用的文档(2011年写的13年最后修改)是最新的,测试不可以用 你给各种测试的一堆东西干嘛?

      ②直连的时候有个参数是必填的,用户付款账号,我觉得逻辑很奇怪,就问技术客服,结果对方给的答复是只要是邮箱和手机格式的,随便填就可以···

      ③这个平台没有提供接口获取银行列表,所有的银行参数都要手动写,而且有变动的话也只能手动改!

    4.关于文档

      不明白的点是官方网站上怎么没有网页版的开发文档,word或者pdf方便,但是如果接口更新了什么东西开发者第一时间怎么修改呢?

    三、案列代码

    环讯支付的接口代码

    1.获取银行列表

     1 #region 环讯网银支付接口 WebService获取银行列表信息BankList()(暂时是测试的接口)
     2 PayServiceIps.ServiceSoapClient IpsPay = new PayServiceIps.ServiceSoapClient();//调用webservice 此处是测试地址
     3 protected List<string> Array;
     4 //获取银行列表
     5 //格式为  银行|银行别名|银行代号的数组
     6 protected List<string> BankList()
     7 {
     8     string Mer_code = System.Configuration.ConfigurationManager.AppSettings["Mer_code"];//商户号
     9     string Mer_key = System.Configuration.ConfigurationManager.AppSettings["Mer_key"];//商户证书:登陆http://merchant.ips.com.cn/商户后台下载的商户证书内容
    10     string Re = IpsPay.GetBankList(Mer_code, Game.Utils.Utility.MD5(Mer_code + Mer_key).ToLower());
    11     Re = HttpUtility.UrlDecode(Re);//Re的格式为银行|银行别名|银行代号#
    12     List<string> ArrayList = new List<string>();
    13     for (int i = 0; i < (Re.Split('#').Length - 1); i++)//数组是以#结束的 所以最后一个字符串是空的
    14     {
    15         ArrayList.Add(Re.Split('#')[i]);
    16     }
    17     return ArrayList;
    18 }
    19 #endregion

    2.支付跳转到第三方页面

     1 #region 配置支付参数并且跳转到支付
     2 //提交地址
     3 //string form_url = "http://pay.ips.net.cn/ipayment.aspx"; //测试
     4 string form_url = "https://pay.ips.com.cn/ipayment.aspx"; //正式
     5 //商户号
     6 string Mer_code = System.Configuration.ConfigurationManager.AppSettings["Mer_code"];
     7 //商户证书:登陆http://merchant.ips.com.cn/商户后台下载的商户证书内容
     8 string Mer_key = System.Configuration.ConfigurationManager.AppSettings["Mer_key"];
     9 //商户订单编号
    10 string Billno = orderInfo.OrderID;// 
    11 //订单金额(保留2位小数)
    12 string Amount = this.txtSalePrice.Text.Trim() + ".00";
    13 //订单日期
    14 string BillDate = DateTime.Now.ToString("yyyyMMdd");
    15 //币种
    16 string Currency_Type = "RMB";
    17 //支付卡种
    18 string Gateway_Type = "01";
    19 //银行代号
    20 string Bankco = Bankco;
    21 //语言
    22 string Lang = "GB";
    23 string nurl = "http://" + Request.Url.Authority + "/Return.aspx";
    24 //支付结果成功返回的商户URL
    25 string Merchanturl = nurl;
    26 //支付结果失败返回的商户URL
    27 string FailUrl = "http://" + Request.Url.Authority + "/FailUrl.aspx";
    28 //商户数据包
    29 string Attach = Amount;
    30 //显示金额
    31 string DispAmount = Amount;
    32 //订单支付接口加密方式
    33 string OrderEncodeType = "5";
    34 //交易返回接口加密方式 
    35 string RetEncodeType = "17";
    36 //返回方式
    37 string Rettype = "1";
    38 //Server to Server 返回页面URL
    39 string ServerUrl = nurl;
    40 //订单支付接口的Md5摘要, 原文=billno+订单编号+ currencytype +币种+ amount +订单金额+ date +订单日期+ orderencodetype +订单支付接口加密方式+商户内部证书字符串
    41 string SignMD5 = System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile("billno" + Billno + "currencytype" + Currency_Type + "amount" + Amount + "date" + BillDate + "orderencodetype" + OrderEncodeType + Mer_key, "MD5").ToLower();
    42 string postForm = "<form name="frm1" id="frm1" method="post" action="" + form_url + "">";
    43 postForm += "<input type="hidden" name="Mer_code" value="" + Mer_code + "" />";
    44 postForm += "<input type="hidden" name="Billno" value="" + Billno + "" />";
    45 postForm += "<input type="hidden" name="Amount" value="" + Amount + "" />";
    46 postForm += "<input type="hidden" name="Date" value="" + BillDate + "" />";
    47 postForm += "<input type="hidden" name="Currency_Type" value="" + Currency_Type + "" />";
    48 postForm += "<input type="hidden" name="Gateway_Type" value="" + Gateway_Type + "" />";
    49 postForm += "<input type="hidden" name="Lang" value="" + Lang + "" />";
    50 postForm += "<input type="hidden" name="Merchanturl" value="" + Merchanturl + "" />";
    51 postForm += "<input type="hidden" name="FailUrl" value="" + FailUrl + "" />";
    52 postForm += "<input type="hidden" name="Attach" value="" + Attach + "" />";
    53 postForm += "<input type="hidden" name="Bankco" value="" + Bankco + "" />";
    54 postForm += "<input type="hidden" name="DispAmount" value="" + DispAmount + "" />";
    55 postForm += "<input type="hidden" name="OrderEncodeType" value="" + OrderEncodeType + "" />";
    56 postForm += "<input type="hidden" name="RetEncodeType" value="" + RetEncodeType + "" />";
    57 postForm += "<input type="hidden" name="Rettype" value="" + Rettype + "" />";
    58 postForm += "<input type="hidden" name="ServerUrl" value="" + ServerUrl + "" />";
    59 postForm += "<input type="hidden" name="SignMD5" value="" + SignMD5 + "" />";
    60 if (Bankco != "")
    61     postForm += "<input type="hidden" name="DoCredit" value="1">";
    62 postForm += "</form>";
    63 //自动提交该表单到测试网关
    64 postForm += "<script type="text/javascript" language="javascript">setTimeout("document.getElementById('frm1').submit();",10);</script>";
    65 #endregion

    3.结果返回

     1 //接收数据
     2 string billno = Request["billno"];
     3 string amount = Request["amount"];//+".00";
     4 string currency_type = Request["Currency_type"];
     5 string mydate = Request["date"];
     6 string succ = Request["succ"];
     7 string msg = Request["msg"];
     8 string attach = Request["attach"];
     9 string ipsbillno = Request["ipsbillno"];
    10 string retEncodeType = Request["retencodetype"];
    11 string signature = Request["signature"];
    12 string bankbillno = Request["bankbillno"];
    13 //签名原文
    14 //billno+【订单编号】+currencytype+【币种】+amount+【订单金额】+date+【订单日期】+succ+【成功标志】+ipsbillno+【IPS订单编号】+retencodetype +【交易返回签名方式】
    15 string content = "billno" + billno + "currencytype" + currency_type + "amount" + amount + "date" + mydate + "succ" + succ + "ipsbillno" + ipsbillno + "retencodetype" + retEncodeType;
    16 //签名是否正确
    17 Boolean verify = false;
    18 
    19 //验证方式:16-md5withRSA  17-md5
    20 
    21 // if (retEncodeType == "17")
    22 //{
    23 //登陆http://merchant.ips.com.cn/商户后台下载的商户证书内容
    24 string merchant_key = System.Configuration.ConfigurationManager.AppSettings["Mer_key"];
    25 //Md5摘要
    26 string signature1 = FormsAuthentication.HashPasswordForStoringInConfigFile(content + merchant_key, "MD5").ToLower();
    27 
    28 if (signature1 == signature)
    29 {
    30     verify = true;
    31 }
    32 
    33 //判断签名验证是否通过
    34 if (verify == true)
    35 {
    36     //判断交易是否成功
    37     if (succ != "Y")
    38     {
    39         Response.Write("<script>alert("交易失败!");</script>");
    40         Response.End();
    41     }
    42     else
    43     {
    44 
    45         Response.Write("<script>alert("交易成功!");</script>");
    46         Response.End();
    47     }
    48 }
    49 else
    50 {
    51     Response.Write("签名不正确!");
    52 }

    本文版权归作者(谢俊)和博客园所有,欢迎转载,转载请标明出处。

    原文地址:http://www.cnblogs.com/net-xiejun/

    微信开发群C#.NETWEB程序开发交流

    完整源码下载:https://github.com/xiejun-net/weixin

    公众账号:

  • 相关阅读:
    【流量劫持】SSLStrip 终极版 —— location 瞒天过海
    【流量劫持】沉默中的狂怒 —— Cookie 大喷发
    【流量劫持】SSLStrip 的未来 —— HTTPS 前端劫持
    Web 前端攻防(2014版)
    流量劫持 —— 浮层登录框的隐患
    流量劫持能有多大危害?
    流量劫持是如何产生的?
    XSS 前端防火墙 —— 整装待发
    XSS 前端防火墙 —— 天衣无缝的防护
    XSS 前端防火墙 —— 无懈可击的钩子
  • 原文地址:https://www.cnblogs.com/net-xiejun/p/4729592.html
Copyright © 2011-2022 走看看