支付寶提現官方名稱爲 單筆轉帳到支付寶帳戶 主要分爲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 }
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 }
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 }
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文檔
還有個簡潔的作法就是 服務的狀況下 在屬性--->登陸--->選擇此帳戶 選擇管理員帳戶