總結一下微信支付的企業分賬功能,自己前前後後折騰了一兩天,也給後來的同學一個參考
關於分賬這個功能,可能應用的也比較少,網上相關的資料也比較少
關於分賬功能的應用場景,可以參考微信官方文檔 https://pay.weixin.qq.com/wiki/doc/api/allocation.php?chapter=26_1
使用PHP 進行開發(畢竟PHP是世界上最好的語言)
所使用到的環境或包或者工具
本地環境 Windows10
線上環境:
服務器 CentOS 7.3
寶塔Linux面板6.9
ThinkPHP5.1.38
PHP 7.3.4
MySQL 5.7
Nginx -Tengine2.2
Redis 5.0.4
think-queue 2.0.4 (注意:3.X是TP6使用的,目前TP5.1對應的是2.X版本)
關於TP的隊列,可以參考大佬的文章 https://github.com/coolseven/notes/blob/master/thinkphp-queue/README.md
php-redis 拓展
Supervisor 進程守護
本文的微信開發使用的是EasyWechat
當前版本是4.1
EasyWechat的環境要求如下
- PHP >= 7.0
- PHP cURL 擴展
- PHP OpenSSL 擴展
- PHP SimpleXML 擴展
- PHP fileinfo 拓展
安裝EasyWechat
composer require overtrue/wechat:~4.0 -vvv
EasyWechat 官網的文檔中沒有分賬功能的介紹,但是通過閱讀源碼發現其實這個功能是有的。那麼下面會進行使用介紹
首先說一下分賬的流程,官方給的圖
從圖裏得知,要實現分賬功能需要在統一下單的API參數裏多加一個參數 profit_sharing = 'Y'
等用戶支付了之後,訂單資金會進行凍結,訂單進行分賬,分賬完畢之後,解凍資金,就可以進行後續資金操作了。
大概步驟:微信支付後的回調(支付結果通知)=>在回調處理中將數據處理好(例如更新訂單表)=>將需要分賬的人或者商戶號和需要分賬金額的數據處理完畢=>插入到隊列中=>讀取隊列的數據=>開始分賬=>分賬完畢(成功或者失敗)
下列的分賬任務我們將其 命名爲 ProfitSharingJob
1、確認訂單已經支付後(微信支付回調通知),處理好需要分賬的數據
發佈任務的關鍵代碼
Queue::later(30,'app\\api\\job\\ProfitSharing',$notify_arr,'ProfitSharingJob');
參數:
30,因爲微信推薦的是訂單20秒後再分賬,這裏延後30秒執行這個任務。
'app\\api\\job\\ProfitSharing' 任務文件的完整命名空間
$notify_arr 組裝好的數組
‘ProfitSharingJob’ 任務名稱
對隊列不熟悉的同學請參考文章開頭提供的隊列教程。
隊列的配置文件位於項目配置 config/queue.conf
將Think-queue的默認驅動調整爲Redis
<?php
return [
//Redis,Database,Topthink ,Sync這四種驅動
'connector' => 'Redis',
'expire' => null, // 任務的過期時間,默認爲60秒; 若要禁用,則設置爲 null
'default' => 'think-queue', // 默認的隊列名稱
'host' => '127.0.0.1', // redis 主機ip
'port' => 6379, // redis 端口
'password' => '', // redis 密碼
'select' => 1, // 使用哪一個 db,默認爲 db0
'timeout' => 0, // redis連接的超時時間
'persistent' => false, // 是否是長連接
];
新建一個php文件用於接收任務,位於application/api/job,命名爲ProfitSharing
寫入如下代碼
<?php
/**
* Created by 九城.
* Author: 九城
* QQ : 940993208
*
* Date: 2019/10/3
* Time: 12:43
*/
namespace app\api\job;
use app\api\service\WxPay;
use think\facade\Log;
use think\queue\Job;
class ProfitSharing
{
public function fire(Job $job,$data){
//如果任務重試次數大於5次則刪除這個任務
if ($job->attempts() > 5){
$job->delete();
}else{
//調用分賬
$res = $this->profitSharing($data);
if ($res){
//執行成功則刪除這個任務
$job->delete();
return ;
}
else{
//重試
$job->release(30);
}
}
}
//失敗了之後執行
public function failed($data){
Log::error($data);
}
//分賬功能
public function profitSharing($data){
//具體分賬的業務邏輯
$wx_pay = new WxPay();
return $wx_pay->profitSharing($data);
}
}
具體的業務邏輯
先添加分賬人到微信服務器:
我是寫在service層
先引入easywechat
use EasyWeChat\Factory;
構造函數裏寫好配置或者寫在某個基類裏。
public $config;
function __construct()
{
//CLI模式下config只能通過load方法去加載位於application下的模塊配置文件
$wxPay = \think\facade\Config::load(\think\facade\Env::get('root_path').'application/api/config/wxPay.php');
$this->config = [
'app_id' => $wxPay['app_id'],
'mch_id' => $wxPay['mch_id'],
'key' => $wxPay['mch_key'],
'cert_path' => $wxPay['cert_path'],
'key_path' => $wxPay['key_path'],
'log' => [
'level' => 'debug',
'file' => Env::get('root_path').'/runtime/log/easywechat.log',
],
];
}
添加收賬方代碼如下:
如果是個人傳入openid或者微信號
商戶則傳入商戶號
type變量接收如下三個參數中的一個
MERCHANT_ID:商戶ID
PERSONAL_WECHATID:個人微信號
PERSONAL_OPENID:個人openid
//添加分賬接收方
public function addReceiver($openid,$type){
$r = Factory::payment($this->config);
$res = $r->profit_sharing->addReceiver([
//個人類型
'type' => $type,
'account' => $openid,
'relation_type' => 'DISTRIBUTOR',
]);
if ($res['return_code']=="SUCCESS" && $res["result_code"] == "SUCCESS"){
return true;
}
return false;
}
開始分賬,注意分賬方的信息對json對象,類似以下結構
$receiver = [
"type" => $type,
"account" => $user['openid'],
"amount" => (int)$amount,
"description" => "分享好友獎勵".$user['amount'].'元',
];
接收三個參數。微信的訂單號,系統內部的訂單號,以及接受分賬的json對象。
這裏用的單次分賬功能
public function share($wx_order_no,$order_no,$receiver){
$share = Factory::payment($this->config);
$res = $share->profit_sharing->share(
$wx_order_no,
$order_no,
$receiver
);
if($res['return_code']=="SUCCESS" && $res["result_code"] == "SUCCESS"){
return "SUCCESS";
}else{
Log::write($res);
}
}
到此分賬功能就完結。
接着需要將ThinkPHP的隊列進行進程常駐
參考命令,最後的ProfitSharingJob爲任務名
php think queue:work --daemon --queue ProfitSharingJob
接着用supervisor 守護這個進程,確保在崩潰的時候能重新拉起
在寶塔安裝supervisor管理器插件
分別填入項目根目錄, php所在位置,以及命令(這時候不應該以 think開頭,完整命令爲)
think queue:work --daemon --queue ProfitSharingJob
至此,在小程序中支付之後,在supervisor管理的日誌中可以看到執行情況。
到此完結。
本人的技術水平有限,寫文章水平也有限。希望各位指出不足之處,感謝!