支付寶微信提現

一.支付寶

支付寶提現官方名稱爲  單筆轉帳到支付寶帳戶  主要分爲2個接口 :php

1.alipay.fund.trans.toaccount.transfer(單筆轉帳到支付寶帳戶接口)  官方文檔:https://docs.open.alipay.com/api_28/alipay.fund.trans.toaccount.transfernode

2.alipay.fund.trans.order.query(查詢轉帳訂單接口)  官方文檔https://docs.open.alipay.com/api_28/alipay.fund.trans.order.query/web

ps:其中查詢轉帳接口主要是爲了防止漏單 在錯誤碼爲20000,40004,或者編碼爲SYSTEM_ERROR 時須要使用該接口查詢是否已經轉帳過 根據接口返回值判斷是否已經打款 若是未打款須要從新發起打款 若是重試後失敗須要加入出錯列表或其餘處理 隨業務須要而定json

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

調用時準備步驟:服務器

1. 建立應用並獲取APPID微信

2.添加功能網絡

測試時可以使用沙盒內數據app

3.配置應用環境ide

生成祕鑰

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:\certificate\wechart\apiclient_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文檔

還有個簡潔的作法就是 服務的狀況下 在屬性--->登陸--->選擇此帳戶 選擇管理員帳戶

相關文章
相關標籤/搜索