PHP實現微信提現(企業付款到零錢)

来源:https://www.cnblogs.com/a609251438/archive/2019/11/20/11901040.html
-Advertisement-
Play Games

怎麼開通企業付款到零錢? 有的商戶號的產品中心是沒有這個功能的,不過,該功能的pid(product id)是5,只要隨便進去某一個產品,在地址欄把pid改為5。 即可進入該功能頁面,進行開通,不過要滿足條件。 用戶提現代碼: 1 //用戶微信提現 2 private function withdr ...


怎麼開通企業付款到零錢?

有的商戶號的產品中心是沒有這個功能的,不過,該功能的pid(product id)是5,只要隨便進去某一個產品,在地址欄把pid改為5。

即可進入該功能頁面,進行開通,不過要滿足條件。

用戶提現代碼:

 1 //用戶微信提現
 2 private function withdrawals_weixin($id){
 3 $falg = M('withdrawals')->where(['id'=>$id])->find();
 4 $openid = M('users')->where('user_id', $falg['user_id'])->value('openid');
 5 $data['openid'] = $openid;
 6 $data['pay_code'] = $falg['id'].$falg['user_id'];
 7 $data['desc'] = '提現ID'.$falg['id'];
 8 if($falg['taxfee'] >= $falg['money']){
 9 return array('status'=>1, 'msg'=>"提現額度必須大於手續費!" );
10 }else{
11 $data['money'] = bcsub($falg['money'], $falg['taxfee'], 2);
12 }
13 include_once PLUGIN_PATH . "payment/weixin/weixin.class.php";
14 $weixin_obj = new \weixin();
15 $result = $weixin_obj->transfer($data);
16 
17 return $result;
18 }

 


其中pay_code在商戶號的提現功能是唯一的,所以為了防重放攻擊,這個值千萬不能用隨機數,最好用ID,具有提現記錄唯一。

提現邏輯代碼:

 1 // 微信提現轉賬
 2 function transfer($data){
 3 
 4 header("Content-type: text/html; charset=utf-8");
 5 //CA證書及支付信息
 6 $wxchat['appid'] = WxPayConfig::$appid;
 7 $wxchat['mchid'] = WxPayConfig::$mchid;
 8 
 9 $wxchat['api_cert'] = PLUGIN_PATH.'/payment/weixin/cert/apiclient_cert.pem';
10 $wxchat['api_key'] = PLUGIN_PATH.'/payment/weixin/cert/apiclient_key.pem';
11 
12 // $wxchat['api_ca'] = '/plugins/payment/weixin/cert/rootca.pem';
13 $webdata = array(
14 'mch_appid' => $wxchat['appid'],
15 'mchid' => $wxchat['mchid'],
16 'nonce_str' => md5(time()),
17 //'device_info' => '1000',
18 'partner_trade_no'=> $data['pay_code'], //商戶訂單號,需要唯一
19 'openid' => $data['openid'],//轉賬用戶的openid
20 'check_name'=> 'NO_CHECK', //OPTION_CHECK不強制校驗真實姓名, FORCE_CHECK:強制 NO_CHECK:
21 //'re_user_name' => 'jorsh', //收款人用戶姓名
22 'amount' => $data['money'] * 100, //付款金額單位為分
23 'desc' => $data['desc'],
24 'spbill_create_ip' => request()->ip(),
25 );
26 
27 foreach ($webdata as $k => $v) {
28 $tarr[] =$k.'='.$v;
29 }
30 
31 sort($tarr);
32 $sign = implode($tarr, '&');
33 $sign .= '&key='.WxPayConfig::$key;
34 $webdata['sign']=strtoupper(md5($sign));
35 
36 $wget = $this->array2xml($webdata);
37 
38 $pay_url = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers';
39 
40 $res = $this->http_post($pay_url, $wget, $wxchat);
41 
42 if(!$res){
43 return array('status'=>1, 'msg'=>"Can't connect the server" );
44 }
45 $content = simplexml_load_string($res, 'SimpleXMLElement', LIBXML_NOCDATA);
46 
47 if(strval($content->return_code) == 'FAIL'){
48 return array('status'=>1, 'msg'=>strval($content->return_msg));
49 }
50 if(strval($content->result_code) == 'FAIL'){
51 return array('status'=>1, 'msg'=>strval($content->err_code),':'.strval($content->err_code_des));
52 }
53 
54 $rdata = array(
55 'mch_appid' => strval($content->mch_appid),
56 'mchid' => strval($content->mchid),
57 'device_info' => strval($content->device_info),
58 'nonce_str' => strval($content->nonce_str),
59 'result_code' => strval($content->result_code),
60 'partner_trade_no' => strval($content->partner_trade_no),
61 'payment_no' => strval($content->payment_no),
62 'payment_time' => strval($content->payment_time),
63 );
64 return $rdata;
65 
66 }

 


其中 PLUGIN_PATH 是一個常量

 1 define('PLUGIN_PATH', __DIR__ . '/plugins/');
 2  定義插件目錄
 3 
 4 
 5 /**
 6 * 將一個數組轉換為 XML 結構的字元串
 7 * @param array $arr 要轉換的數組
 8 * @param int $level 節點層級, 1 為 Root.
 9 * @return string XML 結構的字元串
10 */
11 function array2xml($arr, $level = 1) {
12 $s = $level == 1 ? "<xml>" : '';
13 foreach($arr as $tagname => $value) {
14 if (is_numeric($tagname)) {
15 $tagname = $value['TagName'];
16 unset($value['TagName']);
17 }
18 if(!is_array($value)) {
19 $s .= "<{$tagname}>".(!is_numeric($value) ? '<![CDATA[' : '').$value.(!is_numeric($value) ? ']]>' : '')."</{$tagname}>";
20 } else {
21 $s .= "<{$tagname}>" . $this->array2xml($value, $level + 1)."</{$tagname}>";
22 }
23 }
24 $s = preg_replace("/([\x01-\x08\x0b-\x0c\x0e-\x1f])+/", ' ', $s);
25 return $level == 1 ? $s."</xml>" : $s;
26 }
27 
28 function http_post($url, $param, $wxchat) {
29 $oCurl = curl_init();
30 if (stripos($url, "https://") !== FALSE) {
31 curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, FALSE);
32 curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, FALSE);
33 }
34 if (is_string($param)) {
35 $strPOST = $param;
36 } else {
37 $aPOST = array();
38 foreach ($param as $key => $val) {
39 $aPOST[] = $key . "=" . urlencode($val);
40 }
41 $strPOST = join("&", $aPOST);
42 }
43 curl_setopt($oCurl, CURLOPT_URL, $url);
44 curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1);
45 curl_setopt($oCurl, CURLOPT_POST, true);
46 curl_setopt($oCurl, CURLOPT_POSTFIELDS, $strPOST);
47 if($wxchat){
48 curl_setopt($oCurl,CURLOPT_SSLCERT,$wxchat['api_cert']);
49 curl_setopt($oCurl,CURLOPT_SSLKEY,$wxchat['api_key']);
50 curl_setopt($oCurl,CURLOPT_CAINFO,$wxchat['api_ca']);
51 }
52 $sContent = curl_exec($oCurl);
53 $aStatus = curl_getinfo($oCurl);
54 curl_close($oCurl);
55 
56 if (intval($aStatus["http_code"]) == 200) {
57 return $sContent;
58 } else {
59 return false;
60 }
61 }

 

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 本位是複習筆記,不適合零基礎 賦值運算符 變數 名稱 = 值/表達式 ; 需要註意的是,賦值運算符的計算是按照從右往左的; 註意: 1.在使用賦值符號時,必須保證左側的類型範圍大於等於右側產生的類型 2.兩個類型不同的數據相加時,得到的結果類型為範圍更大的一方 算術運算符 "+"號不僅可以作為加法運 ...
  • 本文是複習筆記,不適合零基礎 標識符命名規範 可以有字母數字下劃線和美元符組成, hello abc 不能以數字開頭 123abc 嚴格區分大小寫 void Void 不能是java的關鍵字和保留字 class 標識符必須是見名知意的 ps:在Eclipse中紫色的都是關鍵字 關鍵字 具有某個特殊含 ...
  • 本文是複習筆記,不適合零基礎 簡介: JAVA是一門面向對象的編程語言 1995有sun公司發佈 java程式執行流程: 1. xxxjava源文件, 2. 經過編譯器編譯 3. 產生位元組碼文件 4. 位元組碼交給解釋器 5. 解釋成當前平臺的本地機器指令 名詞概念 JVM,:是java虛擬機 jvm ...
  • 學習:1.先大綱,然後思路優先(適當的提出問題) 2.合理推測 為了熟悉線程池,提出一些問題 1.線程什麼時候創建? 2.線程池主要做什麼? 3.無任務執行處於什麼狀態? 4.提交一個任務,執行邏輯? 5.線程池怎樣被銷毀? ...
  • 判斷是linux系統,並且uid為0,allowRoot是通過命令行傳參傳進來的,通過flag包解析出來的,可以使用go run node.go -h看到這些參數 log.Fatal傳入的是一個可變參數v ...interface{},並且可以傳入任意類型,可變參數的使用和切片很像 如果要真的傳入一 ...
  • goroutine 和 channel goroutine 看一個需求 需求:要求統計 1 9000000000 的數字中,哪些是素數? 分析思路: 1) 傳統的方法,就是使用一個迴圈,迴圈的判斷各個數是不是素數。[很慢] 2) 使用併發或者並行的方式,將統計素數的任務分配給多個 goroutine ...
  • Zuul在Web項目中的使用見上文《SpringBoot中使用Zuul》,下麵例子為Zuul在Spring Cloud的使用。 ...
  • Mybatis配置詳解 XML配置文件層次結構 下圖展示了mybatis config.xml的全部配置元素 properties元素 properties是一個配置屬性的元素,讓我們能在配置文件的上下文中使用它,MyBatis提供3種配置方式。 property子元素。 properties配置文 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...