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

    公众账号:

  • 相关阅读:
    WPF 快捷键读写txt
    win10 UWP GET Post
    win10 UWP GET Post
    win10 UWP Hmac
    win10 UWP Hmac
    win10 UWP MessageDialog 和 ContentDialog
    MySQL 触发器-更新字段时,status列会加一
    [SDOI2018]旧试题
    win10 UWP MessageDialog 和 ContentDialog
    win10 UWP RSS阅读器
  • 原文地址:https://www.cnblogs.com/net-xiejun/p/4729592.html
Copyright © 2011-2022 走看看