test_lgq/niucloud/core/pay/Wechatpay.php
2024-01-24 17:36:08 +08:00

453 lines
14 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?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');
}
}