Files
huangjingfen/pro_v3.5.1/crmeb/services/wechat/client/pay/OrderClient.php
panchengyong c1e74d8e68 chore(php): 统一 ScottPan 文件头与注释域名替换
- 按 docs/renew-code-comment.md 将 PHP 文件头改为带边框的 Author 注释\n- 注释中的 crmeb.com 替换为 uj345.cn(代码字符串中的外链未改)\n- 新增 docs/renew-code-comment.md 说明

Made-with: Cursor
2026-03-29 11:22:58 +08:00

332 lines
9.5 KiB
PHP

<?php
// +----------------------------------------------------------------------
// | Author: ScottPan Team
// +----------------------------------------------------------------------
namespace crmeb\services\wechat\client\pay;
use crmeb\services\wechat\util\Helper;
use crmeb\services\wechat\util\XML;
use EasyWeChat\Kernel\HttpClient\Response;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
use Symfony\Contracts\HttpClient\ResponseInterface;
use think\helper\Arr;
use EasyWeChat\Pay\Client;
use EasyWeChat\Kernel\Contracts\Config;
/**
* 创建订单
* Class OrderClient
* @author 等风来
* @email 136327134@qq.com
* @date 2023/9/26
* @package crmeb\services\wechat\client\pay
*/
class OrderClient
{
/**
* OrderClient constructor.
* @param Client $api
* @param Config $config
*/
public function __construct(protected Client $api, protected Config $config)
{
}
/**
* 小程序创建订单
* @param array $params
* @return Response|ResponseInterface
* @throws TransportExceptionInterface
* @author 等风来
* @email 136327134@qq.com
* @date 2023/9/15
*/
public function createorder(array $params): ResponseInterface|Response
{
$data = [
'openid' => $params['openid'],//支付者的openid
'combine_trade_no' => $params['out_trade_no'],//商家合单支付总交易单号
'expire_time' => time() + 7000,
'sub_orders' => [
[
'mchid' => $this->config->get('mch_id'),
'amount' => (int)$params['total_fee'],
'trade_no' => $params['out_trade_no'],
'description' => $params['body'],
]
],
];
return $this->api->postJson('shop/pay/createorder', $data);
}
/**
* 小程序退款
* @param array $params
* @return Response|ResponseInterface
* @throws TransportExceptionInterface
* @author 等风来
* @email 136327134@qq.com
* @date 2023/9/15
*/
public function refundorder(array $params): ResponseInterface|Response
{
$data = [
'openid' => $params['openid'],
'mchid' => $this->config->get('mch_id'),
'trade_no' => $params['trade_no'],
'transaction_id' => $params['transaction_id'],
'refund_no' => $params['refund_no'],
'total_amount' => (int)$params['total_amount'],
'refund_amount' => (int)$params['refund_amount'],
];
return $this->api->postJson('shop/pay/refundorder', $data);
}
/**
* 付款码支付
* @param array $params
* @return ResponseInterface
* @throws TransportExceptionInterface
* @author 等风来
* @email 136327134@qq.com
* @date 2023/9/15
*/
public function pay(array $params): ResponseInterface
{
$params['appid'] = $this->config->get('app_id');
return $this->api->request('post', 'pay/micropay', $params);
}
/**
* 下单
* @param array $params
* @return ResponseInterface
* @throws TransportExceptionInterface
* @author 等风来
* @email 136327134@qq.com
* @date 2023/9/14
*/
public function unify(array $params): ResponseInterface
{
if (empty($params['spbill_create_ip'])) {
$params['spbill_create_ip'] = request()->ip();
}
$params['notify_url'] = $params['notify_url'] ?? $this->config->get('notify_url');
return $this->request('pay/unifiedorder', $params);
}
/**
* 发起请求
* @param string $endpoint
* @param array $params
* @param string $method
* @param array $options
* @return Response
* @throws TransportExceptionInterface
* @author 等风来
* @email 136327134@qq.com
* @date 2023/9/14
*/
protected function request(string $endpoint, array $params = [], string $method = 'post', array $options = []): ResponseInterface
{
$base = [
'appid' => $this->config->get('app_id'),
'mch_id' => $this->config->get('mch_id'),
'nonce_str' => uniqid(),
];
$params = array_filter(array_filter(array_merge($base, [], $params)), 'strlen');
$secretKey = $this->config->get('v2_secret_key');
$encryptMethod = Helper::getEncryptMethod(Arr::get($params, 'sign_type', 'MD5'), $secretKey);
$params['sign'] = Helper::generateSign($params, $secretKey, $encryptMethod);
$options = array_merge([
'body' => XML::build($params),
], $options);
return $this->api->request(strtoupper($method), $endpoint, $options);
}
/**
* 商户订单号退款
* @param string $number
* @param string $refundNumber
* @param int $totalFee
* @param int $refundFee
* @param array $optional
* @return Response
* @throws TransportExceptionInterface
* @author 等风来
* @email 136327134@qq.com
* @date 2023/9/15
*/
public function byOutTradeNumber(string $number, string $refundNumber, int $totalFee, int $refundFee, array $optional = []): Response
{
return $this->refund($refundNumber, $totalFee, $refundFee, array_merge($optional, ['out_trade_no' => $number]));
}
/**
* 支付回执单号退款
* @param string $transactionId
* @param string $refundNumber
* @param int $totalFee
* @param int $refundFee
* @param array $optional
* @return Response
* @throws TransportExceptionInterface
* @author 等风来
* @email 136327134@qq.com
* @date 2023/9/15
*/
public function byTransactionId(string $transactionId, string $refundNumber, int $totalFee, int $refundFee, array $optional = []): Response
{
return $this->refund($refundNumber, $totalFee, $refundFee, array_merge($optional, ['transaction_id' => $transactionId]));
}
/**
* 退款
* @param string $refundNumber
* @param int $totalFee
* @param int $refundFee
* @param array $optional
* @return Response
* @throws TransportExceptionInterface
* @author 等风来
* @email 136327134@qq.com
* @date 2023/9/15
*/
protected function refund(string $refundNumber, int $totalFee, int $refundFee, array $optional = []): Response
{
$params = array_merge([
'out_refund_no' => $refundNumber,
'total_fee' => $totalFee,
'refund_fee' => $refundFee,
'appid' => $this->config->get('app_id'),
], $optional);
return $this->safeRequest('secapi/pay/refund', $params);
}
/**
* 撤销订单
* @param string $outTradeNumber
* @return Response
* @throws TransportExceptionInterface
* @author 等风来
* @email 136327134@qq.com
* @date 2023/9/15
*/
public function reverseByOutTradeNumber(string $outTradeNumber): Response
{
return $this->reverse($outTradeNumber, 'out_trade_no');
}
/**
* 撤销订单
* @param string $number
* @param string $type
* @return Response
* @throws TransportExceptionInterface
* @author 等风来
* @email 136327134@qq.com
* @date 2023/9/15
*/
protected function reverse(string $number, string $type): Response
{
$params = [
'appid' => $this->config->get('app_id'),
$type => $number,
];
return $this->safeRequest('secapi/pay/reverse', $params);
}
/**
* 查询退款订单
* @param string $number
* @return Response
* @throws TransportExceptionInterface
* @author 等风来
* @email 136327134@qq.com
* @date 2023/9/15
*/
public function queryByOutTradeNumber(string $number): Response
{
return $this->query([
'out_trade_no' => $number,
]);
}
/**
* 查询订单
* @param array $params
* @return Response
* @throws TransportExceptionInterface
* @author 等风来
* @email 136327134@qq.com
* @date 2023/9/15
*/
protected function query(array $params): Response
{
$params['appid'] = $this->config->get('app_id');
return $this->request('pay/orderquery', $params);
}
/**
* 企业付款到零钱
* @param array $params
* @return Response
* @throws TransportExceptionInterface
* @author 等风来
* @email 136327134@qq.com
* @date 2023/9/15
*/
public function toBalance(array $params): Response
{
$base = [
'mch_id' => null,
'mchid' => $this->config->get('mch_id'),
'mch_appid' => $this->config->get('app_id'),
];
if (empty($params['spbill_create_ip'])) {
$params['spbill_create_ip'] = request()->ip();
}
return $this->safeRequest('mmpaymkttransfers/promotion/transfers', array_merge($base, $params));
}
/**
* 退款请求
* @param string $endpoint
* @param array $params
* @param string $method
* @param array $options
* @return Response
* @throws TransportExceptionInterface
* @author 等风来
* @email 136327134@qq.com
* @date 2023/9/15
*/
protected function safeRequest(string $endpoint, array $params, string $method = 'post', array $options = []): Response
{
$options = array_merge([
'cert' => $this->config->get('certificate'),
'ssl_key' => $this->config->get('private_key'),
], $options);
return $this->request($endpoint, $params, $method, $options);
}
}