course/app/common/service/PayService.php

180 lines
6.3 KiB
PHP
Raw 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 app\common\service;
use app\common\service\Channel\wechat\WechatConstants;
use app\constant\ResponseCode;
use GuzzleHttp\Exception\RequestException;
use think\Exception;
use WeChatPay\Builder;
use WeChatPay\Crypto\Rsa;
use WeChatPay\Formatter;
use WeChatPay\Util\PemUtil;
class PayService
{
protected $config;
protected $instance;
protected $platformPublicKeyInstance;
protected $merchantPrivateKeyInstance;
public function __construct()
{
// 服务商 商户号
$merchantId = getenv('MERCHANT_ID');
// 从本地文件中加载「商户API私钥」「商户API私钥」会用来生成请求的签名
$merchantPrivateKeyFilePath = 'file://' . base_path() . '/certificate/apiclient_key.pem';
$this->merchantPrivateKeyInstance = Rsa::from($merchantPrivateKeyFilePath, Rsa::KEY_TYPE_PRIVATE);
// 「商户API证书」的「证书序列号」
$merchantCertificateSerial = '3297EB3A1132A39DAFFD70A6C4A6C3078CD346F7';
// 从本地文件中加载「微信支付平台证书」,用来验证微信支付应答的签名
$platformCertificateFilePath = 'file://' . base_path() . '/certificate/wechatpay_660FAD2D6E804E37BE9D77EF5882718CC1E3399F.pem';
$this->platformPublicKeyInstance = Rsa::from($platformCertificateFilePath, Rsa::KEY_TYPE_PUBLIC);
// 从「微信支付平台证书」中获取「证书序列号」
$platformCertificateSerial = PemUtil::parseCertificateSerialNo($platformCertificateFilePath);
// 构造一个 APIv3 客户端实例
$this->instance = Builder::factory([
'mchid' => $merchantId,
'serial' => $merchantCertificateSerial,
'privateKey' => $this->merchantPrivateKeyInstance,
'certs' => [
$platformCertificateSerial => $this->platformPublicKeyInstance,
],
]);
}
/**
* @desc jsapi支付
* @param array $pay_data
* @param $seller_channel
* @return array
*/
public function payment(array $pay_data)
{
try {
$request_data = [
'appid' => getenv('APP_ID'),// 公众号ID
'mchid' => getenv('MERCHANT_ID'),//直连商户号
'description' => $pay_data['desc'],//商品描述
'out_trade_no' => $pay_data['out_trade_no'],//商户订单号
'notify_url' => $pay_data['notify_url'],//通知地址
'amount' => [
'total' => round($pay_data['total_amount'] * 100),//总金额 单位为分
],
'payer' => [
'openid' => $pay_data['openid'],// 用户在服务商AppID下的唯一标识
]
];
$resp = $this->instance
->chain('/v3/pay/transactions/jsapi')
->post([
'json' => $request_data,
// 'debug' => true
]);
$result = json_decode($resp->getBody(), true);
raw_log('wechat_pay/transactions_jsapi', ['request_data' => $request_data, 'result' => $result]);
$pay_data = [
'appId' => getenv('APP_ID'), //微信小程序appid
'timeStamp' => strval(Formatter::timestamp()),
'nonceStr' => Formatter::nonce(),
'package' => 'prepay_id=' . $result['prepay_id'],
];
$pay_data['paySign'] = Rsa::sign(
Formatter::joinedByLineFeed(...array_values($pay_data)),
$this->merchantPrivateKeyInstance
);
$pay_data['signType'] = 'RSA';
return $pay_data;
} catch (RequestException $exception) {
$response = $exception->getResponse();
$result = json_decode($response->getBody()->getContents(), true);
raw_log('wechat_pay/transactions_jsapi_failed', ['pay_data' => $pay_data, 'result' => $result]);
return [
'code' => ResponseCode::FAIL,
'msg' => $result['message']
];
}
}
/**
* @desc 退款
* @param $refund_data
* @return array
*/
public function refundPayment($refund_data)
{
try {
//退款数据
$request_data = [
'out_trade_no' => $refund_data['out_trade_no'],//微信支付订单号
'out_refund_no' => $refund_data['out_refund_no'],//商户退款单号
'reason' => $refund_data['refund_desc'],//退款原因
'notify_url' => $refund_data['notify_url'],//通知地址
'amount' => [
'refund' => round($refund_data['refund_amount'] * 100),//退款金额
'total' => round($refund_data['total'] * 100),//原订单金额
'currency' => 'CNY',//退款币种
]
];
$resp = $this->instance
->chain('/v3/refund/domestic/refunds')
->post([
'json' => $request_data,
// 'debug' => true
]);
$result = json_decode($resp->getBody(), true);
raw_log('wechat_pay/refund', ['request_data' => $request_data, 'result' => $result]);
return [
'transaction_id' => $result['transaction_id'],
'out_transaction_id' => $result['refund_id'],
'out_trade_no' => $result['out_refund_no'],
];
} catch (RequestException $exception) {
$response = $exception->getResponse();
$result = json_decode($response->getBody()->getContents(), true);
raw_log('wechat_pay/refund_failed', ['request_data' => $request_data, 'result' => $result]);
return [
'code' => ResponseCode::FAIL,
'msg' => $result['message']
];
}
}
/**
* @desc 余额查询 微信没有余额查询接口,返回假数据
* @param $seller_channel
* @return array
*/
public function queryBalanceAmount($seller_channel)
{
return [
'code'=>ResponseCode::SUCCESS,
'data'=>[
'total_amount'=>0.00,
'settled_amount'=>0.00,
'not_settled_amount'=>0.00
]
];
}
}