1、微信支付
1.1、安裝依賴包
- 我這里使用 EasyWeChat 實(shí)現(xiàn)微信支付,另外我附上之前我封裝的微信類。
- 詳細(xì)操作里面寫的比較清楚,請(qǐng)先看這個(gè):http://m.itdecent.cn/p/d376d921bf16
1.2、準(zhǔn)備工作
(1)需要去微信開放平臺(tái)注冊(cè)賬號(hào)
- appid(微信開放平臺(tái)上的應(yīng)用id)
- mch_id(微信申請(qǐng)成功之后郵件中的商戶id)
- notify_url(支付成功后的回調(diào)地址)
- api_key(在微信商戶平臺(tái)上自己設(shè)定的api密鑰 32位)
- apiclient_cert.pem 和 apiclient_key.pem 證書
相關(guān)的申請(qǐng)流程可以參考網(wǎng)站: https://developers.weixin.qq.com/doc/oplatform/Mobile_App/WeChat_Pay/Vendor_Service_Center.html
(2)將對(duì)應(yīng)的配置寫入配置文件中(配置文件可以參考我下面封裝的微信類)
(3)創(chuàng)建訂單表
-
關(guān)于訂單表,這里給你們參考下我的
1.3、封裝 WechatServer.php 微信服務(wù)類
<?php
namespace app\common\service;
use EasyWeChat\Factory;
use EasyWeChat\MiniProgram\Application;
use think\Hook;
/**
* 微信服務(wù)
* @package app\common\service
*/
class WeChatService
{
//微信公眾號(hào)配置
private $officeConfig = [
'app_id' => 'asdasdasf23413', //測(cè)試號(hào)
'secret' => 'asdasdasr3421412412312312', //測(cè)試號(hào)
// 'app_id' => '515125141',
// 'secret' => '123131212asdasdsadasd',
// 指定 API 調(diào)用返回結(jié)果的類型:array(default)/collection/object/raw/自定義類名
'response_type' => 'array',
//...
];
//默認(rèn)APP微信支付,修改appId和secret就可以換其他方式支付
private $appPayConfig= [
// 必要配置
'app_id' => 'asdasdasf23413',
'secret' => 'asdasdasr3421412412312312', //
'mch_id' => '515125141',
'key' => 'asdasdasdas', // API 密鑰
// 如需使用敏感接口(如退款、發(fā)送紅包等)需要配置 API 證書路徑(登錄商戶平臺(tái)下載 API 證書)
'cert_path' => PUBLIC_PATH . '/wechatCert/apiclient_cert.pem', // XXX: 絕對(duì)路徑!?。?!
'key_path' => PUBLIC_PATH . '/wechatCert/apiclient_key.pem', // XXX: 絕對(duì)路徑!?。?!
'notify_url' => '', // 你也可以在下單時(shí)單獨(dú)設(shè)置來(lái)想覆蓋它
'log' => [
'level' => 'debug',
'file' => PUBLIC_PATH . '/logs/pay_wechat.log',
],
];
//微信小程序配置
private $miniConfig = [
'app_id' => 'qwad312321312312',
'secret' => 'asdasdasdasdasdasdweqe',
// 下面為可選項(xiàng)
// 指定 API 調(diào)用返回結(jié)果的類型:array(default)/collection/object/raw/自定義類名
'response_type' => 'array',
'log' => [
'level' => 'debug',
'file' => PUBLIC_PATH . '/logs/mini_wechat.log',
],
];
//開放平臺(tái)配置
private $openConfig = [
'app_id' => '開放平臺(tái)第三方平臺(tái) APPID',
'secret' => '開放平臺(tái)第三方平臺(tái) Secret',
'token' => '開放平臺(tái)第三方平臺(tái) Token',
'aes_key' => '開放平臺(tái)第三方平臺(tái) AES Key'
];
private $token = ''; //獲取小程序的ACCESS_TOKEN
private $isContract = false; //是否開啟支付中簽約
/**
* @ApiTitle (實(shí)例化)
*/
public function connect($type = 0)
{
//實(shí)例化對(duì)象
if ($type == 0) $app = Factory::miniProgram($this->miniConfig); //微信小程序
if ($type == 1) $app = Factory::officialAccount($this->officeConfig); //微信公眾號(hào)
if ($type == 3) $app = Factory::openPlatform($this->openConfig); //微信開放平臺(tái)
if ($type == 10) $app = Factory::payment($this->payConfig); //微信支付
if ($type == 11) {
$this->appPayConfig['app_id'] = 'wx652625123238453'; //小程序appId
$this->appPayConfig['secret'] = 'a51dsa5d1w22222wq5e3qw151q'; //小程序秘鑰
$app = Factory::payment($this->appPayConfig); //微信小程序支付
} else if ($type == 12 || $type == 13 || $type == 14) {
$this->appPayConfig['app_id'] = 'wx5a13sd5a1sd3as5d1'; //公眾號(hào)Id
$this->appPayConfig['secret'] = '5s1ad51as3d5w413d21a5w1w523'; //公眾號(hào)秘鑰
$app = Factory::payment($this->appPayConfig); //H5支付、生成支付二維碼
}
//獲取token
$accessToken = $app->access_token;
$this->token = $accessToken->getToken()['access_token']; // token 數(shù)組 token['access_token'] 字符串
return $app ?? false;
}
/**
* 統(tǒng)一下單
* @param int $payType 支付類型(10-APP微信支付 11-微信小程序支付 12-微信外部H5調(diào)起支付 13-生成微信支付二維碼 14-微信內(nèi)部H5調(diào)起支付)
* @param string $body 描述
* @param string $oderNumber 訂單號(hào)
* @param float $amount 金額
* @param string $openid 公眾openid
* @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
* @throws \EasyWeChat\Kernel\Exceptions\HttpException
* @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
* @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
* @throws \EasyWeChat\Kernel\Exceptions\RuntimeException
* @throws \GuzzleHttp\Exception\GuzzleException
* @throws \Psr\SimpleCache\InvalidArgumentException
* @throws Exception
*/
public function unify($payType, $body, $oderNumber, $amount, $openid = '')
{
$app = (new WeChatService())->connect($payType);
if ($payType == 10) $tradeType = 'APP';
if ($payType == 11) $tradeType = 'JSAPI';
if ($payType == 12) $tradeType = 'MWEB';
if ($payType == 13) $tradeType = 'NATIVE';
if ($payType == 14) $tradeType = 'JSAPI';
$data = [
'body' => $body,
'out_trade_no' => $oderNumber,
'total_fee' => $amount * 100, // **單位:分**
'notify_url' => 'http://test.sulinks.com/api/Payment/wechatNotify', // 支付結(jié)果通知網(wǎng)址,如果不設(shè)置則會(huì)使用配置里的默認(rèn)地址
'trade_type' => $tradeType, // 請(qǐng)對(duì)應(yīng)換成你的支付方式對(duì)應(yīng)的值類型
// 'spbill_create_ip' => '', // 可選,如不傳該參數(shù),SDK 將會(huì)自動(dòng)獲取相應(yīng) IP 地址
// 'openid' => $openId, //從用戶額外表中取到openId
];
if ($payType == 11) {
//小程序
$uid = db('sulink_user_account')->where('order_number', $oderNumber)->value('from_id');
$openid = db('weixin_user')->where('uid', $uid)->value('routine_openid');
if (!$openid) throw new Exception('該用戶不存在openId');
$data['openid'] = $openid;
} else if ($payType == 12) {
//微信外部的H5頁(yè)面
$data['spbill_create_ip'] = '28.19.113.73';
} else if ($payType == 13) {
//生成微信支付二維碼
$data['product_id'] = $oderNumber;
} else if ($payType == 14) {
//微信內(nèi)部的H5頁(yè)面
$data['openid'] = $openid;
if ($openid == '') throw new Exception('openid不得為空!');
}
$result = $app->order->unify($data, $this->isContract);
//第二次驗(yàn)簽
if ($result['return_code'] === 'SUCCESS') {
if ($result['result_code'] === 'SUCCESS') {
if ($payType == 10) {
$result = $app->jssdk->appConfig($result['prepay_id']); //第二次簽名
} else if ($payType == 11) {
//微信小程序
$result = $app->jssdk->bridgeConfig($result["prepay_id"], false);
unset($result['appId']);
$result['timeStamp'] = strval($result['timeStamp']);
} else if ($payType == 13) {
//微信二維碼支付
$result['code_url'] = (二維碼服務(wù)類)->create($result['code_url'], $oderNumber);
return $result;
} else if ($payType == 14) {
//微信內(nèi)部H5
$result = $app->jssdk->sdkConfig($result["prepay_id"]);
return $result;
}
return $result;
} else {
throw new Exception($result['err_code_des']);
}
} else {
throw new Exception($result['return_msg']);
}
}
}
特別注意:
1、如果是 JSAPI類型支付時(shí),unify驗(yàn)簽的這個(gè)方法必須要傳入用戶的openId。
2、openId可以在微信小程序授權(quán)的時(shí)候存入數(shù)據(jù)庫(kù),然后取出來(lái)就可以傳入了。
3、微信內(nèi)部H5頁(yè)面 支付用的 JSSDK 二次驗(yàn)簽調(diào)用sdkConfig方法。
4、微信小程序 支付用的 JSSDK 二次驗(yàn)簽調(diào)用bridgeConfig方法。
5、APP支付用的 JSSDK 二次驗(yàn)簽調(diào)用appConfig方法。
6、如果是生成 微信二維碼支付 時(shí),unify驗(yàn)簽的這個(gè)方法必須要傳入商戶內(nèi)部自定義的商品IDproduct_id。
7、支付時(shí)候 需要確保描述body、商戶訂單號(hào)out_trate_no和 金額amount和上一次提交微信的一致,否則會(huì)報(bào)錯(cuò)201--商戶訂單號(hào)重復(fù)。
8、微信內(nèi)部H5頁(yè)面 支付所需要的openId可以參考‘
9、二維碼服務(wù)類 自己可以進(jìn)行封裝,主要將信息內(nèi)容生成二維碼保存起來(lái)。
1.4、第一步:創(chuàng)建訂單
/**
* @ApiTitle (用戶開通VIP創(chuàng)建不同的訂單)
* @ApiMethod (POST)
*/
public function createOrder()
{
//根據(jù)傳入內(nèi)容或者查庫(kù)獲取相關(guān)的數(shù)據(jù)
//$amount 需要內(nèi)部計(jì)算,不能傳入
//$userId 從Token中獲取用戶ID
//$orderNumber 需要生成隨機(jī)不重復(fù)的字符串,用于商戶內(nèi)部訂單號(hào)
//生成資金流水記錄
Db::startTrans();
try {
// 具體業(yè)務(wù)數(shù)據(jù)表插入以及操作
//將數(shù)據(jù)插入資金表
(用戶資金表)->insert([
'from_id' => $userId, //支付方ID(系統(tǒng)默認(rèn)為1)
'to_id' => 1, //收款方ID(系統(tǒng)默認(rèn)為1)
'type' => 1, //資金類型:1=VIP開通/升級(jí),2=推薦提成,3=退款
'money' => $amount, //資金金額
'desc' => $subject, //相關(guān)描述
'pay_status' => 0, //支付狀態(tài):0=未到賬,1=已到賬
'order_number' => $orderNumber, //訂單流水號(hào)
'create_time' => date('Y-m-d H:i:s', time()), //創(chuàng)建時(shí)間
]);
Db::commit();
} catch (\Exception $e) {
Db::rollback();
$this->error($e->getMessage());
}
$this->success('創(chuàng)建訂單成功!', ['order_number' => $orderNumber,]);
}
-
$amount表示支付金額,需要根據(jù)具體業(yè)務(wù)計(jì)算,不能取 input 傳入的值。 -
pay_status用于判斷訂單是否支付完成,這一步主要通過(guò)訂單查詢/異步調(diào)用時(shí)候成功的情況下才會(huì)變?yōu)? - 另外訂單表中需要有一個(gè)
is_deal字段,用于判斷 是否處理(0=否,1=是)支付成功的操作 ,因?yàn)?異步調(diào)用 有時(shí)候會(huì)出現(xiàn)問(wèn)題,我們也需要在 調(diào)用支付寶查詢訂單 的時(shí)候通過(guò)這個(gè)字段去判斷是否處理從而去 更新訂單表。 - 其中需要去判斷是否有相同類型 未失效 的訂單,如果存在則直接使用原來(lái)的訂單號(hào)
1.5、第二步:獲取調(diào)起微信支付的參數(shù)
/**
* @ApiTitle (用戶支付訂單)
* @ApiMethod (POST)
*/
public function payAmount($orderNumber = '')
{
//支付類型 10-APP微信支付 11-微信小程序支付 12-微信外部H5調(diào)起支付 13-生成微信支付二維碼 14-微信內(nèi)部H5調(diào)起支付 20-APP支付寶支付 21-PC支付寶支付 22-H5支付寶支付
$payType = intval(input('pay_type')) ?? 0;
$openid = input('openid') ?? '';
if ($payType == 14 && $openid == '') $this->error('openid必須傳入');
if ($orderNumber == '') $orderNumber = input('order_number') ?? 0; //內(nèi)部訂單號(hào)
if (!$orderNumber) $this->error('訂單號(hào)不得為空!');
//查看記錄表和資金表 分別獲取金額/充值類型/用戶ID/備注
$userVipLog = (會(huì)員日志表)->where('order_number', $orderNumber)->find();
$user = $this->auth->getUser();
$amount = $userVipLog['amount'];
$userId = $userVipLog['user_id'];
$vipType = $userVipLog['vip_type'];
//判斷用戶是否為該用戶
if ($userId != $this->auth->uid) $this->error('訂單不匹配!');
//獲取VIP標(biāo)題
$newVip = (new VipLevelModel)->where('id', $userVipLog['vip_id'])->find();
//判斷是否可以開通會(huì)員
//操作備注
if ($payType == 10 || $payType == 11 || $payType == 12 || $payType == 13 || $payType == 14) {
$payTypeText = '微信支付';
$accountType = 1;
} else if ($payType == 20 || $payType == 21 || $payType == 22) {
$payTypeText = '支付寶';
$accountType = 2;
} else {
throw new Exception('支付類型參數(shù)錯(cuò)誤!');
}
if ($vipType == 1) $subject = $payTypeText . '方式開通' . $newVip['title'] . ',充值金額:' . $amount . '元';
if ($vipType == 2) $subject = $payTypeText . '方式續(xù)費(fèi)' . $newVip['title'] . ',充值金額:' . $amount . '元';
if ($vipType == 3) $subject = $payTypeText . '方式升級(jí)' . $newVip['title'] . ',充值金額:' . $amount . '元';
//更新資金表
(new UserAccountModel)->where('order_number', $orderNumber)->update([
'desc' => $subject, //相關(guān)描述
'pay_type' => $accountType, //支付方式:1=微信支付,2=支付寶,3=銀行卡,11=其他
]);
if ($accountType == 1) { //10-APP微信支付 11-微信小程序支付 12-微信外部H5調(diào)起支付 13-生成微信支付二維碼 14-微信內(nèi)部H5調(diào)起支付
$result = (new WeChatService())->unify($payType, $subject, $orderNumber, $amount, $openid);
$result['order_number'] = $orderNumber;
$result['amount'] = $amount;
$this->success('調(diào)起微信支付成功', $result); //支付成功
} elseif ($accountType == 2) {
//20-APP支付寶支付 21-PC支付寶支付 22-H5支付寶支付
//訂單內(nèi)容
$order = [
'out_trade_no' => $orderNumber,
'total_amount' => $amount,
'subject' => $subject,
];
$ailpayConfig = config('alipay');
if ($payType == 20) $alipay = Pay::alipay($ailpayConfig)->app($order); //app支付
if ($payType == 21) {
//PC支付
$ailpayConfig['return_url'] = 'PC回調(diào)地址url';
$alipay = Pay::alipay($ailpayConfig)->web($order);
}
if ($payType == 22) {
//手機(jī)網(wǎng)站支付
$ailpayConfig['return_url'] = '手機(jī)回調(diào)地址url';
$alipay = Pay::alipay($ailpayConfig)->wap($order);
}
$res = $alipay->getContent();
$this->success('調(diào)起支付寶支付成功', $res);
}
}
- 后端 只需要在調(diào)用微信支付地方調(diào)用這段方法即可。
- H5 支付、公眾號(hào)支付、掃碼支付、APP支付,全部都是用這個(gè)接口下單。
- 前端 微信支付參考文檔 https://pay.weixin.qq.com/wiki/doc/api/index.html。
- APP的
$res是返回 給前端調(diào)起微信 的參數(shù),如下:
{
"code": 1,
"msg": "成功",
"time": "1593600229",
"data": {
"appid": "wx23123124124",
"partnerid": "123123123123",
"prepayid": "wx531351531531515",
"noncestr": "5efc68e65d469",
"timestamp": 123123123,
"package": "Sign=WXPay",
"sign": "05FC29CD1DSDd341251B1C77"
}
}
1.6、查詢訂單
/**
* @ApiTitle (獲取訂單支付狀態(tài))
* @ApiMethod (GET)
*/
public function getPayStatus()
{
$orderNumber = input('order_number'); //內(nèi)部訂單流水號(hào)
$userAccount = (資金表)->where('order_number', $orderNumber)->find();
if (!$userAccount) $this->error('不存在該訂單!');
//未處理:0=否,1=是(用于處理業(yè)務(wù)邏輯)
if ($userAccount->is_deal == 0) {
//微信異步調(diào)用異常情況下:
//支付成功根據(jù)支付方式:1=微信支付,2=支付寶,3=銀行卡,11=其他
if ($userAccount->pay_type == 1) {
//微信支付查看訂單
$app = (new WeChatService)->connect(10);
$res = $app->order->queryByOutTradeNumber($orderNumber);
if ($res['return_code'] === 'SUCCESS') { // return_code 表示通信狀態(tài),不代表支付狀態(tài)
if ($res['result_code'] === 'SUCCESS') { //以下字段在return_code為SUCCESS的時(shí)候有返回
if ($res['trade_state'] === 'SUCCESS') { //支付成功
$tradeNo = $res['transaction_id']; //微信支付訂單號(hào)
$totalFee = $res['total_fee']; //充值總金額
$timeEnd = $res['time_end']; //支付完成時(shí)間
//如果金額不匹配直接退出
if (($userAccount->money) != $totalFee / 100) goto S;
//支付成功
$this->paySuccess($orderNumber, $tradeNo, $timeEnd);
} else {
goto S;
}
}
}
} elseif ($userAccount->pay_type == 2) {
//支付寶查看訂單
$res = Pay::alipay(config('alipay'))->find($orderNumber);
$state = $res->trade_status; //訂單狀態(tài)
$outTradeNo = $res->out_trade_no; //自定義訂單號(hào)
$tradeNo = $res->trade_no; //支付寶訂單號(hào)
$totalAmount = $res->total_amount; //充值總金額
$appId = $res->app_id; //收款方的APPID
$payTime = $res->gmt_payment; //交易付款時(shí)間
if (!in_array($state, ['TRADE_SUCCESS', 'TRADE_FINISHED'])) goto S;
if (!$userAccount) goto S;
if ($userAccount['money'] != $totalAmount) goto S;
if ($appId != config('alipay.app_id')) goto S;
//支付成功
$this->paySuccess($outTradeNo, $tradeNo, $payTime);
}
}
S:
//需要再查一次訂單狀態(tài)
$userAccount = (new UserAccountModel)->where('order_number', $orderNumber)->find();
//返回?cái)?shù)據(jù)前端
$data = [
'order_number' => $orderNumber,
'vip_title' => $vip['title'],
'pay_status' => $userAccount['pay_status'], //支付狀態(tài):0=待支付,1=支付成功
'pay_type' => $userAccount['pay_type'], //支付方式:1=微信支付,2=支付寶,3=銀行卡,11=其他
];
$this->success('獲取訂單信息成功!', $data);
}
- 查詢訂單時(shí)候用到
is_deal用于判斷異步接口是否調(diào)用處理,沒(méi)有則調(diào)用一次
1.7、微信異步操作
/**
* @ApiTitle (微信異步支付會(huì)員VIP)
* @ApiMethod (POST)
*/
public function wechatNotify()
{
$app = (new WeChatService())->connect(10);
$response = $app->handlePaidNotify(function ($message, $fail) {
$outTradeNo = $message['out_trade_no']; //自定義訂單號(hào)
//查詢是否存在訂單
$res = (new UserAccountModel)->where('order_number', $outTradeNo)->find();
// 如果訂單不存在 或者 訂單已經(jīng)支付過(guò)了 或者 已經(jīng)處理過(guò)
if (!$res || $res->pay_time || $res->pay_status == 1 || $res->is_deal == 1) return true;
if ($message['return_code'] === 'SUCCESS') { // return_code 表示通信狀態(tài),不代表支付狀態(tài)
if ($message['result_code'] === 'SUCCESS') { //以下字段在return_code為SUCCESS的時(shí)候有返回
if ($message['trade_state'] === 'SUCCESS') { //以下字段在return_code 和result_code都為SUCCESS的時(shí)候有返回
$tradeNo = $message['transaction_id']; //微信支付訂單號(hào)
$totalFee = $message['total_fee']; //充值總金額
$timeEnd = $message['time_end']; //支付完成時(shí)間
//如果金額不匹配直接退出
if (($res->money) != $totalFee / 100) return true;
//支付成功
$this->paySuccess($outTradeNo, $tradeNo, $timeEnd);
}
}
} else {
return $fail('通信失敗,請(qǐng)稍后再通知我');
}
return true;
});
$response->send(); // Laravel 里請(qǐng)使用:return $response;
}
- 其中必須
trade_state是SUCCESS的時(shí)候才算支付成功 - 其中
$this->paySuccess($outTradeNo, $tradeNo, $payTime);用于 支付成功調(diào)用的接口 - 該接口主要根據(jù)(訂單號(hào)查詢到的)訂單業(yè)務(wù)類型 去調(diào)不同的方法,同時(shí)需要加入 并發(fā)鎖
1.8、支付成功的方法
/**
* @ApiTitle (支付成功的操作,需要鎖)
* @ApiInternal
* @param string $outTradeNo 商戶內(nèi)部訂單號(hào)
* @param string $tradeNo 微信/支付寶訂單號(hào)
* @param string $payTime 支付時(shí)間
* @return bool|string
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
private function paySuccess($outTradeNo, $tradeNo, $payTime)
{
//加鎖失??!
if (!RedisService::lock('paySuccess_' . $outTradeNo)) return false;
//查詢訂單
$res = (用戶資金表)->where('order_number', $outTradeNo)->find();
if (!$res) return false;
Db::startTrans();
try {
//更新資金表狀態(tài)
(new UserAccountModel)->where('order_number', $outTradeNo)->update([
'trade_no' => $tradeNo, //微信訂單號(hào)
'pay_time' => $payTime, //支付時(shí)間
'pay_status' => 1, //支付狀態(tài):0=未到賬,1=已到賬
]);
//查看訂單類型 1=VIP開通/升級(jí),2=推薦提成,3=退款
if ($res->type == 1 && $res->is_deal == 0) {
$res = $this->vipSuccess($res['from_id'], $outTradeNo);
if (!$res) throw new Exception('訂單狀態(tài)處理異常');
}
Db::commit();
} catch (\Exception $e) {
Db::rollback();
//記錄資金日志
Log::warning($e->error());
return false;
}
return true;
}
-
$this->vipSuccess($res['from_id'], $outTradeNo);是充值會(huì)員成功的方法
1.9、Redis鎖方法
- composer安裝
predis,命令行:composer require predis/predis,點(diǎn)擊查看鏈接。 - 新建一個(gè)
RedisServer.php服務(wù)類
<?php
namespace app\common\service;
use app\common\controller\Api;
use Predis\Client;
class RedisService extends Api
{
//Redis并發(fā)鎖
const SU_REDIS_LOCK = 'redis::lock::'; //Redis并發(fā)鎖(后面跟對(duì)應(yīng)業(yè)務(wù)的鎖名)
private static $prefix = '';
private static $client;
/**
* 單例模式獲取redis連接實(shí)例
* @return Client
*/
public static function connect()
{
if (!self::$client) {
self::$prefix = config('redis_prefix');
$config = [
'scheme' => 'tcp',
'host' => config('redis_host'),
'port' => config('redis_port'),
'timeout' => 60,
'read_write_timeout ' => 60,
];
//沒(méi)有配置密碼時(shí),不傳入密碼項(xiàng)參數(shù)
if (config('redis_password')) $config['password'] = config('redis_password');
self::$client = new Client($config, ['prefix' => self::$prefix]);
}
return self::$client;
}
/**
* 添加自定義并發(fā)鎖
* 原理是redis的單線程操作
* @param string $lockName 鎖名
* @param int $expireTTL 過(guò)期時(shí)間
* @return bool 是否由當(dāng)前調(diào)用加鎖成功
*/
public static function lock(string $lockName, int $expireTTL = 10)
{
$redis = self::connect();
$countKey = self::SU_REDIS_LOCK . $lockName;
$flag = false; //默認(rèn)是加鎖失敗
$redisIncr = $redis->incr($countKey); //只有第一個(gè)操作的返回是1
if ($redisIncr === 1) {
$redis->expire($countKey, $expireTTL);
$flag = true; //只有第一次操作的才算加鎖成功
}
return $flag;
}
/**
* 解除自定義并發(fā)鎖
* @param string $lockName 鎖名
* @return bool 是否成功
*/
public static function unlock(string $lockName)
{
$countKey = self::SU_REDIS_LOCK . $lockName;
return (bool)self::connect()->del([$countKey]);
}
}
微信調(diào)用的時(shí)候需要配置白名單,這樣才可以調(diào)用微信內(nèi)部的方法,例如查詢訂單的接口。
大功告成,其中調(diào)試也會(huì)遇到問(wèn)題,我們可以在日志中進(jìn)行查看,日志在配置中可以進(jìn)行修改。
歡迎來(lái)指導(dǎo)和學(xué)習(xí),如果有什么問(wèn)題可以在留言區(qū)留言并一起探討。
另外還有詳細(xì)的 TP5 實(shí)現(xiàn)支付寶APP/PC端統(tǒng)一下單支付(詳細(xì)步驟)
