• 支付宝微信提现


    一.支付宝

    支付宝提现官方名称为  单笔转账到支付宝账户  主要分为2个接口 :

    1.alipay.fund.trans.toaccount.transfer(单笔转账到支付宝账户接口)  官方文档:https://docs.open.alipay.com/api_28/alipay.fund.trans.toaccount.transfer

    2.alipay.fund.trans.order.query(查询转账订单接口)  官方文档https://docs.open.alipay.com/api_28/alipay.fund.trans.order.query/

    ps:其中查询转账接口主要是为了防止漏单 在错误码为20000,40004,或者编码为SYSTEM_ERROR 时需要使用该接口查询是否已经转账过 根据接口返回值判断是否已经打款 如果未打款需要重新发起打款 如果重试后失败需要加入出错列表或其他处理 随业务需要而定

    主要接口 alipay.fund.trans.toaccount.transfer

    调用时准备步骤:

    1. 创建应用并获取APPID

    2.添加功能

    测试时可使用沙盒内数据

    3.配置应用环境

    生成秘钥

    4.下载sdk

    5.调用

    其中调用时 要注意在调用中放的公钥为支付宝公钥 而不是应用公钥 如果传错会造成转账成功但是报sign check fail: check Sign and Data Fail!错误

    转账金额 小数点最多只能2位 文本类型 和微信提现有差别 微信单位为分

    附代码例子:

     1  //沙箱数据
     2 string serverUrl = "https://openapi.alipaydev.com/gateway.do"; 
     3  string appId = "test appid";
     4 //私钥
     5 string privateKeyPem ="";
     6  //支付宝公钥
     7  string alipay_public_key = "";
     8 try
     9             {
    10                 IAopClient client = new DefaultAopClient(serverUrl, appId, privateKeyPem, "json", "1.0", "RSA2", alipay_public_key, "GBK", false);
    11                 AlipayFundTransToaccountTransferRequest request = new AlipayFundTransToaccountTransferRequest();
    12                 request.BizContent = "{" +
    13     "    "out_biz_no":"" + sn + ""," +//商户转账唯一订单号
    14     "    "payee_type":"ALIPAY_LOGONID"," +//ALIPAY_LOGONID:支付宝登录号
    15     "    "payee_account":"" + payee + ""," +//收款方账户
    16     "    "amount":"" + Math.Round(amount, 2).ToString() + ""," +//转账金额
    17     "    "payee_real_name":"" + userName + ""," +//收款方真实姓名
    18     "    "remark":"用户提现打款"," +
    19     "  }";
    20                 var response = client.Execute(request);
    21                 if (response.Code == "10000")
    22                 {
    23                     return true;
    24                 }
    25                 else
    26                 {
    27                     LogInfo(string.Format("单号:{1} 支付宝支付失败 原因:{0}", response.SubMsg, sn));
    28                     if (response.Code == "20000" || response.Code == "40004" || response.SubCode == "SYSTEM_ERROR")
    29                     {
    30                         //掉单
    31                         //查询转账结果
    32                         AlipayFundTransOrderQueryRequest _request = new AlipayFundTransOrderQueryRequest();
    33                         request.BizContent = "{" +
    34                         ""out_biz_no":"" + sn + ""," +
    35                         ""order_id":"" + response.OrderId + """ +
    36                         "  }";
    37                         var _response = client.Execute(_request);
    38                         if (_response.Code == "10000" && _response.Status == "SUCCESS" && !string.IsNullOrEmpty(_response.PayDate) && string.IsNullOrEmpty(_response.ErrorCode))
    39                         {
    40                             return true;//掉单 网络问题实际转账成功
    41                         }
    42                         else
    43                         {
    44                             if (errorTimes <= 3)
    45                             {
    46                                 //增加错误数
    47                                 using (MongoDbProviderFactory factory = base.NewWashcarFactory())
    48                                 {
    49                                     WithdrawalsApplyRecordAccess access = new WithdrawalsApplyRecordAccess(factory.Context);
    50                                     var rec = access.Single(recordId);
    51                                     if (rec != null)
    52                                     {
    53                                         rec.ErrorTimes = rec.ErrorTimes + 1;
    54                                         access.Update(rec);
    55                                     }
    56                                 }
    57                                 //重新打款一次
    58                                 response = client.Execute(request);
    59                                 if (response.Code == "10000")
    60                                 {
    61                                     return true;
    62                                 }
    63                                 else
    64                                 {
    65                                     LogInfo(string.Format("单号:{1} 支付宝支付失败 原因:{0}", response.SubMsg, sn));
    66                                     return false;
    67                                 }
    68                             }
    69                         }
    70                     }
    71                     return false;
    72                 }
    73             }
    74             catch (Exception ex)
    75             {
    76                 LogInfo(string.Format("单号:{1} 支付宝支付失败 ex:{0}", ex.Message, sn));
    77                 return false;
    78             }
    提现关键代码片段

     二.微信

    微信功能官方名称 企业付款 文档地址:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2  文档很全面  

    开发步骤:

    1.注册服务号

    2.注册微信商户号

    3.在商户号后台对AppID授权 开通企业付款到零钱功能

    4.下载证书

    5.调用接口

    注意事项:

    1.打款 是预付款形式 必须先在商户平台充值

    2.签名需要根据ASCII码排序 并加密 详见文档

    3.证书需要放在服务器非虚拟路径处 防止被非法下载盗用 代码中必须调用 否则证书安装了没效果

    4.必须通过微信的openId 获取被转账人 所以需要在调用之前根据业务绑定微信和用户账号

    代码部分:

      1   /// <summary>
      2         /// 微信提现
      3         /// </summary>
      4         /// <param name="sn">单号</param>
      5         /// <param name="wxOpenId">微信用户openid</param>
      6         /// <param name="userName">用户真实姓名</param>
      7         /// <param name="amount">金额 单位分</param>
      8         private bool WechatPay(string sn, string wxOpenId, string userName, int amount)
      9         {
     10             if (string.IsNullOrEmpty(sn)) { LogAndSetMsg(string.Format("单号为空 转账失败")); return false; }
     11             if (string.IsNullOrEmpty(wxOpenId)) { LogAndSetMsg(string.Format("单号{0} 微信用户openId为空 转账失败", sn)); return false; }
     12             if (string.IsNullOrEmpty(userName)) { LogAndSetMsg(string.Format("单号{0} 用户真实姓名为空 转账失败", sn)); return false; }
     13             #region 微信支付配置区
     14             string mch_appid = "";//商户账号appid
     15             string mchid = "";//商户号
     16             string key = "";//秘钥
     17             string cert = @"E:certificatewechartapiclient_cert.p12";//证书路径
     18             #endregion
     19             string nonce_str = Guid.NewGuid().ToString().Replace("-", "");//随机字符串
     20             string sign = "";//签名
     21             string partner_trade_no = sn;//商户订单号
     22             string openid = wxOpenId;//用户openid
     23             string check_name = "FORCE_CHECK";//强校验真实姓名
     24             string re_user_name = userName;//收款用户姓名
     25             string desc = "用户提现打款";//企业付款描述信息
     26             string spbill_create_ip = GetLocalIP();//Ip地址
     27             Dictionary<string, string> parm = new Dictionary<string, string>();
     28             parm.Add("mch_appid", mch_appid);
     29             parm.Add("mchid", mchid);
     30             parm.Add("nonce_str", nonce_str);
     31             parm.Add("partner_trade_no", partner_trade_no);
     32             parm.Add("openid", openid);
     33             parm.Add("check_name", check_name);
     34             parm.Add("re_user_name", re_user_name);
     35             parm.Add("amount", amount.ToString());
     36             parm.Add("desc", desc);
     37             parm.Add("spbill_create_ip", spbill_create_ip);
     38             //设置签名
     39             var stringSignTemp = getParamSrc(parm);//签名处理中间变量
     40             stringSignTemp = stringSignTemp + "&key=" + key;
     41             sign = GetMD5(stringSignTemp).ToUpper();
     42             parm.Add("sign", sign);
     43             XDocument xml;
     44             try
     45             {//发送带证书的请求
     46                 ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
     47                 X509Certificate cer = new X509Certificate(cert, mchid);
     48                 HttpWebRequest webrequest = (HttpWebRequest)HttpWebRequest.Create("https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers");
     49                 webrequest.ClientCertificates.Add(cer);
     50                 webrequest.ContentType = "application/x-www-form-urlencoded";
     51                 webrequest.Method = "post";
     52                 //拼接post请求
     53                 string parmStr = "<xml>";
     54                 parmStr += "<amount>" + amount + "</amount>";
     55                 parmStr += "<check_name>"+check_name+"</check_name>";
     56                 parmStr += "<desc>"+desc+"</desc>";
     57                 parmStr += "<mch_appid>"+ mch_appid + "</mch_appid>";
     58                 parmStr += "<mchid>"+ mchid + "</mchid>";
     59                 parmStr += "<nonce_str>"+ nonce_str + "</nonce_str>";
     60                 parmStr += "<openid>"+ openid + "</openid>";
     61                 parmStr += "<partner_trade_no>"+ partner_trade_no + "</partner_trade_no>";
     62                 parmStr += "<re_user_name>"+ re_user_name + "</re_user_name>";
     63                 parmStr += "<spbill_create_ip>"+ spbill_create_ip + "</spbill_create_ip>";
     64                 parmStr += "<sign>"+ sign + "</sign>";
     65                 parmStr += "</xml>";
     66                 byte[] byteArray = Encoding.UTF8.GetBytes(parmStr); //转化
     67                 webrequest.ContentLength = byteArray.Length;
     68                 using (Stream newStream = webrequest.GetRequestStream())
     69                 {
     70                     newStream.Write(byteArray, 0, byteArray.Length);//写入参数
     71                 }
     72                 HttpWebResponse webreponse = (HttpWebResponse)webrequest.GetResponse();
     73                 Stream stream = webreponse.GetResponseStream();
     74                 StreamReader sr = new StreamReader(webreponse.GetResponseStream(), Encoding.UTF8);
     75                 string str = sr.ReadToEnd();
     76                 xml = XDocument.Load(stream);
     77             }
     78             catch (Exception ex)
     79             {
     80                 LogAndSetMsg(string.Format("单号:{1} 发送带证书的请求失败 ex:{0}", ex.Message, sn));
     81                 return false;
     82             }
     83             //解析返回结果
     84             if (xml == null) { LogAndSetMsg(string.Format("解析微信返回值出错 单号:{0}", sn)); return false; }
     85             //获取根节点
     86             var root = xml.Root;
     87             var node = root.Element("result_code");
     88             if (node != null && node.Value == "SUCCESS")
     89             {
     90                 return true;
     91             }
     92             else
     93             {
     94                 var err = root.Element("return_msg");
     95                 if (err != null)
     96                 {
     97                     LogAndSetMsg(string.Format("支付失败:{0} 单号:{1}", err.Value, sn));
     98                 }
     99                 else
    100                 {
    101                     LogAndSetMsg(string.Format("支付失败:原因未知 单号:{0}", sn));
    102                 }
    103                 return false;
    104             }
    105         }
    关键方法
     1   //加密
     2         public static string GetMD5(string pwd)
     3         {
     4             MD5 md5Hasher = MD5.Create();
     5 
     6             byte[] data = md5Hasher.ComputeHash(Encoding.UTF8.GetBytes(pwd));
     7 
     8             StringBuilder sBuilder = new StringBuilder();
     9             for (int i = 0; i < data.Length; i++)
    10             {
    11                 sBuilder.Append(data[i].ToString("x2"));
    12             }
    13 
    14             return sBuilder.ToString();
    15         }
    MD5
     1    /// <summary>
     2         /// 参数按照ASCII码从小到大排序
     3         /// </summary>
     4         /// <param name="paramsMap"></param>
     5         /// <returns></returns>
     6         private string getParamSrc(Dictionary<string, string> paramsMap)
     7         {
     8             var vDic = (from objDic in paramsMap orderby objDic.Key ascending select objDic);
     9             StringBuilder str = new StringBuilder();
    10             foreach (KeyValuePair<string, string> kv in vDic)
    11             {
    12                 string pkey = kv.Key;
    13                 string pvalue = kv.Value;
    14                 str.Append(pkey + "=" + pvalue + "&");
    15             }
    16 
    17             string result = str.ToString().Substring(0, str.ToString().Length - 1);
    18             return result;
    19         }
    根据AscII码排序参数为文本
     1  /// <summary>
     2         /// 获取本机ip
     3         /// </summary>
     4         /// <returns></returns>
     5         private string GetLocalIP()
     6         {
     7             try
     8             {
     9                 string HostName = Dns.GetHostName(); //得到主机名
    10                 IPHostEntry IpEntry = Dns.GetHostEntry(HostName);
    11                 for (int i = 0; i < IpEntry.AddressList.Length; i++)
    12                 {
    13                     //从IP地址列表中筛选出IPv4类型的IP地址
    14                     //AddressFamily.InterNetwork表示此IP为IPv4,
    15                     //AddressFamily.InterNetworkV6表示此地址为IPv6类型
    16                     if (IpEntry.AddressList[i].AddressFamily == AddressFamily.InterNetwork)
    17                     {
    18                         return IpEntry.AddressList[i].ToString();
    19                     }
    20                 }
    21                 LogInfo("未能获取到本机IP");
    22                 return "";
    23             }
    24             catch (Exception ex)
    25             {
    26                 LogInfo("获取本机IP出错:" + ex.Message);
    27                 return "";
    28             }
    29         }
    获取本机IP
    1  private static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
    2         {
    3             if (errors == SslPolicyErrors.None)
    4                 return true;
    5             return false;
    6         }
    证书请求回调

    注:

    1. post请求参数为xml格式 

    2.SYSTEMERROR 错误时 需要原单号重试 否则会多次支付 代码中未展示

    3.证书出错  官方解决方案:https://pay.weixin.qq.com/wiki/doc/api/download/cert.zip 里面有一个word文档

    还有个简洁的做法就是 服务的情况下 在属性--->登录--->选择此账户 选择管理员账户

  • 相关阅读:
    关于Class.getResource和ClassLoader.getResource的路径问题
    JavaScript高级程序设计(读书笔记)(一)
    CSS3常用选择器(二)
    CSS3常用选择器(一)
    JS中的for/in语句和arguments参数
    css绘制特殊图形基础
    css3 3d效果及动画学习
    圣杯布局和双飞翼布局
    css3弹性盒子模型
    css盒子模型
  • 原文地址:https://www.cnblogs.com/nontracey/p/8309492.html
Copyright © 2020-2023  润新知