test_lgq/niucloud/core/pay/Wechatpay.php

453 lines
14 KiB
PHP
Raw Normal View History

2024-01-24 17:36:08 +08:00
<?php
namespace core\pay;
use app\dict\pay\OnlinePayDict;
use app\dict\pay\RefundDict;
use app\dict\pay\TransferDict;
use core\exception\PayException;
use EasyWeChat\Factory;
use Psr\Http\Message\MessageInterface;
use Psr\Http\Message\ResponseInterface;
use think\Response;
use Throwable;
use Yansongda\Pay\Exception\ContainerException;
use Yansongda\Pay\Exception\InvalidParamsException;
use Yansongda\Pay\Exception\ServiceNotFoundException;
use Yansongda\Pay\Pay;
use Yansongda\Pay\Plugin\Wechat\Fund\Transfer\QueryOutBatchNoPlugin;
use Yansongda\Supports\Collection;
/**
* 微信支付管理驱动类 todo 注意:暂时不考虑合单类业务
* Class FileDriver
* @package core\file
*/
class Wechatpay extends BasePay
{
/**
* @param array $config
* @return void
* @throws ContainerException
*/
protected function initialize(array $config = [])
{
$this->config = $config;
$config['mch_secret_cert'] = url_to_path($config['mch_secret_cert'] ?? '');
$config['mch_public_cert_path'] = url_to_path($config['mch_public_cert_path'] ?? '');
Pay::config($this->payConfig($config, 'wechat'));
}
/**
* 公众号支付
* @param array $params
* @return mixed|Collection
*/
public function mp(array $params)
{
$result = $this->returnFormat(Pay::wechat()->mp([
'out_trade_no' => $params['out_trade_no'],
'description' => $params['boby'],
'amount' => [
'total' => $params['money'],
],
'payer' => [
'openid' => $params['openid'],
],
]));
$code = $result['code'] ?? 0;
if ($code == 0) return $result;
//支付错误抛出
throw new PayException($result['message']);
}
/**
* 手机网页支付
* @param array $params
* @return mixed
*/
public function wap(array $params)
{
$order = [
'out_trade_no' => $params['out_trade_no'],
'description' => $params['boby'],
'amount' => [
'total' => $params['money'],
],
'scene_info' => [
'payer_client_ip' => request()->ip(),
'h5_info' => [
'type' => 'Wap',
]
],
];
//这儿有些特殊, 默认情况下H5 支付所使用的 appid 是微信公众号的 appid即配置文件中的 mp_app_id 参数,如果想使用关联的小程序的 appid则只需要在调用参数中增加 ['_type' => 'mini'] 即可
if (!empty($order['type'])) {
$order['_type'] = 'mini'; // 注意这一行
}
return $this->returnFormat(Pay::wechat()->wap($order));
}
public function web(array $params)
{
}
/**
* app支付
* @param array $params
* @return mixed|ResponseInterface
*/
public function app(array $params)
{
return $this->returnFormat(Pay::wechat()->app([
'out_trade_no' => $params['out_trade_no'],
'description' => $params['boby'],
'amount' => [
'total' => $params['money'],
],
]));
}
/**
* 小程序支付
* @param array $params
* @return mixed|ResponseInterface
*/
public function mini(array $params)
{
return $this->returnFormat(Pay::wechat()->mini([
'out_trade_no' => $params['out_trade_no'],
'description' => $params['boby'],
'amount' => [
'total' => $params['money'],
'currency' => 'CNY',//一般是人民币
],
'payer' => [
'openid' => $params['openid'],
]
]));
}
/**
* 付款码支付
* @param array $params
* @return mixed|Collection
*/
public function pos(array $params)
{
//todo 需要自定义通过plugin来侧载开发
$app = Factory::payment([
'app_id' => $this->config['appid'], //应用id
'mch_id' => $this->config["mch_id"] ?? '', //商户号
'key' => $this->config["pay_v2_signkey"] ?? '', // API 密钥 todo 注意: 是v2密钥 是v2密钥 是v2密钥
'response_type' => 'array',
'log' => [
'level' => 'debug',
'permission' => 0777,
'file' => 'runtime/log/wechat/easywechat.logs',
],
'sandbox' => false, // 设置为 false 或注释则关闭沙箱模式
]);
$data = [
'body' => $params['boby'],
'out_trade_no' => $params['out_trade_no'],
'total_fee' => $params['money'],
'auth_code' => $params["auth_code"],//传入的付款码
];
$result = $app->base->pay($data);//没有注释路由,调用没有问题
return $this->returnFormat($result);
}
/**
* 扫码支付
* @param array $params
* @return mixed|Collection
*/
public function scan(array $params)
{
return $this->returnFormat(Pay::wechat()->scan([
'out_trade_no' => $params['out_trade_no'],
'description' => $params['boby'],
'amount' => [
'total' => $params['money'],
],
]));
}
/**
* 转账(微信的转账是很多笔的)
* @param array $params
* @return array
*/
public function transfer(array $params)
{
//这儿的批次信息可能是这儿生成的,但依然需要记录
$order = [
'out_batch_no' => time() . '',//
'batch_name' => $params['remark'],
'batch_remark' => $params['remark'],
];
$transfer_list = $params['transfer_list'];
//单笔转账
if (empty($transfer_list)) {
$transfer_list = array(
[
'transfer_no' => $params['transfer_no'] . '1',
'money' => (int)$params['money'],
'remark' => $params['remark'],
'openid' => $params['to_no']
]
);
}
$total_amount = 0;
$total_num = 0;
foreach ($transfer_list as $v) {
$item_transfer = [
'out_detail_no' => time() . '1',
'transfer_amount' => (int)$v['money'],
'transfer_remark' => $v['remark'],
'openid' => $v['openid'],
];
$total_amount += (int)$v['money'];
$total_num++;
if (!empty($v['user_name'])) {
$item_transfer['user_name'] = $v['user_name'];// 明文传参即可sdk 会自动加密
}
$order['transfer_detail_list'][] = $item_transfer;
}
$order['total_amount'] = $total_amount;
$order['total_num'] = $total_num;
$result = $this->returnFormat(Pay::wechat()->transfer($order));
if (!empty($result['code'])) {
// if($result['code'] == 'PARAM_ERROR'){
// throw new PayException();
// }else if($result['code'] == 'INVALID_REQUEST'){
// throw new PayException();
// }
if ($result['code'] == 'INVALID_REQUEST') {
throw new PayException(700010);
}
throw new PayException($result['message']);
}
return ['batch_id' => $result['batch_id'], 'out_batch_no' => $result['out_batch_no']];
}
/**
* 支付关闭
* @param string $out_trade_no
* @return void
* @throws ContainerException
* @throws InvalidParamsException
* @throws ServiceNotFoundException
*/
public function close(string $out_trade_no)
{
$result = Pay::wechat()->close([
'out_trade_no' => $out_trade_no,
]);
return $this->returnFormat($result);
}
/**
* 退款
* @param array $params
* @return array
* @throws ContainerException
* @throws InvalidParamsException
* @throws ServiceNotFoundException
*/
public function refund(array $params)
{
$out_trade_no = $params['out_trade_no'];
$money = $params['money'];
$total = $params['total'];
$refund_no = $params['refund_no'];
$result = Pay::wechat()->refund([
'out_trade_no' => $out_trade_no,
'out_refund_no' => $refund_no,
'amount' => [
'refund' => $money,
'total' => $total,
'currency' => 'CNY',
],
]);
$result = $this->returnFormat($result);
$refund_status_array = [
'SUCCESS' => RefundDict::SUCCESS,
'CLOSED' => RefundDict::FAIL,
'PROCESSING' => RefundDict::DEALING,
'ABNORMAL' => RefundDict::FAIL,
];
return [
'status' => $refund_status_array[$result['status']],
'refund_no' => $refund_no,
'out_trade_no' => $out_trade_no
];
}
/**
* 异步回调
* @param string $action
* @param callable $callback
* @return ResponseInterface|Response
*/
public function notify(string $action, callable $callback)
{
try {
$result = $this->returnFormat(Pay::wechat()->callback());
if ($action == 'pay') {//支付
if ($result['event_type'] == 'TRANSACTION.SUCCESS') {
$pay_trade_data = $result['resource']['ciphertext'];
$temp_params = [
'trade_no' => $pay_trade_data['transaction_id'],
'mch_id' => $pay_trade_data['mchid'],
'status' => OnlinePayDict::getWechatPayStatus($pay_trade_data['trade_state'])
];
$callback_result = $callback($pay_trade_data['out_trade_no'], $temp_params);
if (is_bool($callback_result) && $callback_result) {
return Pay::wechat()->success();
}
}
} else if ($action == 'refund') {//退款
if ($result['event_type'] == 'REFUND.SUCCESS') {
$refund_trade_data = $result['resource']['ciphertext'];
$refund_status_array = [
'SUCCESS' => RefundDict::SUCCESS,
'CLOSED' => RefundDict::FAIL,
'PROCESSING' => RefundDict::DEALING,
'ABNORMAL' => RefundDict::FAIL,
];
$temp_params = [
'trade_no' => $refund_trade_data['transaction_id'],
'mch_id' => $refund_trade_data['mchid'],
'refund_no' => $refund_trade_data['out_refund_no'],
'status' => $refund_status_array[$refund_trade_data['refund_status']],
];
$callback_result = $callback($refund_trade_data['out_trade_no'], $temp_params);
if (is_bool($callback_result) && $callback_result) {
return Pay::wechat()->success();
}
}
}
return $this->fail();
} catch ( Throwable $e ) {
// throw new PayException($e->getMessage());
return $this->fail($e->getMessage());
}
}
/**
* 查询普通支付订单
* @param array $params
* @return array|MessageInterface|Collection|null
* @throws ContainerException
* @throws InvalidParamsException
* @throws ServiceNotFoundException
*/
public function getOrder(array $params = [])
{
$out_trade_no = $params['out_trade_no'];
$transaction_id = $params['transaction_id'] ?? '';
$order = [
];
if (!empty($out_trade_no)) {
$order['out_trade_no'] = $out_trade_no;
}
if (!empty($transaction_id)) {
$order['transaction_id'] = $transaction_id;
}
$result = Pay::wechat()->find($order);
if (empty($result))
return $result;
$result = $this->returnFormat($result);
return [
'status' => OnlinePayDict::getWechatPayStatus($result['trade_state']),
];
}
/**
* 查询退款单据
* @param string|null $out_trade_no
* @param string|null $refund_no
* @return array|Collection|MessageInterface|null
* @throws ContainerException
* @throws InvalidParamsException
* @throws ServiceNotFoundException
*/
public function getRefund(?string $out_trade_no, ?string $refund_no = '')
{
$order = [
'_type' => 'refund',
'out_refund_no' => $refund_no
];
$result = Pay::wechat()->find($order);
if (empty($result))
return $result;
$result = $this->returnFormat($result);
$refund_status_array = [
'SUCCESS' => RefundDict::SUCCESS,
'CLOSED' => RefundDict::FAIL,
'PROCESSING' => RefundDict::DEALING,
'ABNORMAL' => RefundDict::FAIL,
];
return [
'status' => $refund_status_array[$result['status']],
'refund_no' => $refund_no,
'out_trade_no' => $out_trade_no
];
}
/**
* 获取转账订单(todo 切勿调用)
* @param string $transfer_no
* @return array
* @throws ContainerException
* @throws InvalidParamsException
*/
public function getTransfer(string $transfer_no)
{
$params = [
'out_batch_no' => $transfer_no,
];
$allPlugins = Pay::wechat()->mergeCommonPlugins([QueryOutBatchNoPlugin::class]);
$result = Pay::wechat()->pay($allPlugins, $params);
$result = $this->returnFormat($result);
//微信转账状态
$transfer_status_array = [
'INIT' => TransferDict::DEALING,//初始态。 系统转账校验中
'WAIT_PAY' => TransferDict::DEALING,
'PROCESSING' => TransferDict::DEALING,
'FAIL' => TransferDict::FAIL,
'SUCCESS' => TransferDict::SUCCESS,
];
return [
'status' => $transfer_status_array[$result['status']],
'transfer_no' => $transfer_no
];
}
public function fail($message = '')
{
$response = [
'code' => 'FAIL',
'message' => $message ?: '失败',
];
return response($response, 400, [], 'json');
}
}