Files
xk-api-yii/common/services/EplPayService.php
2025-10-24 10:01:29 +08:00

272 lines
9.6 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 common\services;
use common\helpers\FuncHelper;
use yii\base\Exception;
use yii\helpers\Json;
class EplPayService
{
private static $instance = null;
public $eplConfig;
public $wechatConfig;
private function __clone()
{
}
private function __construct($module = null)
{
$eplConfig = \Yii::$app->params['eplpay'];
if(!$eplConfig['customerCode'] || !$eplConfig['url']){
throw new Exception('缺少易票联相关配置');
}
$this->eplConfig = $eplConfig;
$this->wechatConfig = \Yii::$app->params['wechat'];
}
public static function getInstance($module = null)
{
if(empty(self::$instance)){
self::$instance = new self($module);
}
return self::$instance;
}
// 微信小程序支付
public function WxJsapiPayment($params){
$url = $this->eplConfig['url'].'/api/txs/pay/WxJSAPIPayment';
$param = [
'outTradeNo' => $params['order_no'],
'customerCode' => $this->eplConfig['customerCode'],
'appId' => $this->wechatConfig['app_id'],
'openId' => $params['openId'],
'orderInfo' => $params['orderInfo'],
'payAmount' => bcmul($params['total_pay_price'], 100, 0),
'payCurrency' => 'CNY',
'payMethod' => 35,
'notifyUrl' => $this->eplConfig['pay_notify_url'],
'transactionStartTime' => date('YmdHis'),
'areaInfo' => '330102',
'nonceStr' => FuncHelper::uuid(),
'version' => '3.0'
];
$sign = $this->sign(Json::encode($param));
$result = $this->http_post_json($url,Json::encode($param),$sign);
ds(['url' => $url, 'param' => Json::encode($param), 'sign' => $sign, 'time' => date('YmdHis'), 'result' => $result]);
if(!$result || $result[0] != 200){
throw new Exception('获取支付参数失败');
}
return Json::decode($result[1]);
}
//查询支付结果
public function queryPayment($params){
$url = $this->eplConfig['url'].'/api/txs/pay/PaymentQuery';
$param = [
'outTradeNo' => $params['pay_order_no'],
'customerCode' => $this->eplConfig['customerCode'],
'nonceStr' => FuncHelper::uuid()
];
$sign = $this->sign(Json::encode($param));
$result = $this->http_post_json($url,Json::encode($param),$sign);
if(!$result || $result[0] != 200){
throw new Exception('查询支付结果失败');
}
return Json::decode($result[1]);
}
// 退款
public function refund($params){
$url = $this->eplConfig['url'].'/api/txs/pay/Refund/V2';
$param = [
'outRefundNo' => $params['refund_no'],
'customerCode' => $this->eplConfig['customerCode'],
'transactionNo' => $params['transaction_id'],
'amount' => bcmul($params['total_pay_price'], 100, 0),
'refundAmount' => bcmul($params['refund_price'], 100, 0),
'notifyUrl' => $this->eplConfig['refund_notify_url'],
'transactionStartTime' => date('YmdHis'),
'nonceStr' => FuncHelper::uuid(),
'version' => '3.0'
];
$sign = $this->sign(Json::encode($param));
$result = $this->http_post_json($url,Json::encode($param),$sign);
if(!$result || $result[0] != 200){
throw new Exception('退款失败');
}
return Json::decode($result[1]);
}
//查询退款结果
public function queryRefund($params){
$url = $this->eplConfig['url'].'/api/txs-query/refundOrderQuery';
$param = [
'outRefundNo' => $params['refund_no'],
'customerCode' => $this->eplConfig['customerCode'],
'nonceStr' => FuncHelper::uuid()
];
$sign = $this->sign(Json::encode($param));
$result = $this->http_post_json($url,Json::encode($param),$sign);
if(!$result || $result[0] != 200){
throw new Exception('查询退款结果失败');
}
return Json::decode($result[1]);
}
//单笔提现
public function withDraw($params){
// 构建请求提现接口的URL
$url = $this->eplConfig['url'].'/api/txs/pay/withdrawalToCard';
// 构建请求参数数组
$param = [
// 设置商户订单号
'outTradeNo' => $params['order_no'],
// 设置客户代码
'customerCode' => $this->eplConfig['customerCode'],
// 设置提现金额将申请的现金金额乘以100转换为分
'amount' => bcmul($params['apply_cash'], 100, 0),
// 设置到账类型0表示当日到账
'arrivalType' => 0,
// 设置手续费扣除方式,内扣或外扣 inner内扣 outer外扣
'procedureType' => 'inner',
// 设置开户人姓名,使用公钥加密
'bankUserName' => $this->public_encrypt($params['bank_user_name']),
// 设置银行卡号,使用公钥加密
'bankCardNo' => $this->public_encrypt($params['bank_card']),
// 设置银行名称
'bankName' => $params['bank_name'],
// 设置账户类型,对公、对私或存折 1对公 2对私 5存折
'bankAccountType' => $params['bank_account_type'],
// 设置服务器回调通知URL
'notifyUrl' => $this->eplConfig['withdraw_notify_url'],
// 设置支付货币类型
'payCurrency' => 'CNY',
// 设置随机字符串
'nonceStr' => FuncHelper::uuid()
];
// 根据银行账户类型和银行卡号的前两位判断是否需要设置银行代码
if($params['bank_account_type'] != '2' || substr($params['bank_card'],0,2) != '62'){
$param['bankNo'] = $params['bank_no'];
}
// 生成请求的签名
$sign = $this->sign(Json::encode($param));
// 发起提现请求
$result = $this->http_post_json($url,Json::encode($param),$sign);
// 验证请求结果如果结果为空或HTTP状态码不是200则抛出异常
if(!$result || $result[0] != 200){
throw new Exception('提现失败');
}
// 解析并返回提现请求的结果
return Json::decode($result[1]);
}
//查询提现结果
public function queryWithdraw($params){
$url = $this->eplConfig['url'].'/api/txs/pay/withdrawalToCardQuery';
$param = [
'outTradeNo' => $params['withdraw_order_no'],
'customerCode' => $this->eplConfig['customerCode'],
'nonceStr' => FuncHelper::uuid()
];
$sign = $this->sign(Json::encode($param));
$result = $this->http_post_json($url,Json::encode($param),$sign);
if(!$result || $result[0] != 200){
throw new Exception('查询提现结果失败');
}
return Json::decode($result[1]);
}
protected function sign($data) {
$certs = [];
openssl_pkcs12_read(file_get_contents($this->eplConfig['rsaPrivateKeyFilePath']), $certs, $this->eplConfig['password']); //其中password为你的证书密码
if(!$certs){
throw new Exception('请检查RSA私钥配置'. openssl_error_string());
}
openssl_sign($data, $sign, $certs['pkey'], OPENSSL_ALGO_SHA256);
$sign = base64_encode($sign);
return $sign;
}
protected function http_post_json($url, $jsonStr, $sign)
{
$ch = curl_init();
$headers = array(
'Content-Type: application/json; charset=utf-8',
'Content-Length: ' . strlen($jsonStr),
'x-efps-sign-no:'.$this->eplConfig['signNo'],
'x-efps-sign-type:SHA256withRSA',
'x-efps-sign:'.$sign,
'x-efps-timestamp:'.date('YmdHis'),
);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonStr);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 跳过检查
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // 跳过检查
//curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
return [$httpCode, $response];
}
// 公钥加密
protected function public_encrypt($data)
{
//读取公钥文件
$pubKey = file_get_contents($this->eplConfig['publicKeyFilePath']);
$res = openssl_get_publickey($pubKey);
if(!$res){
throw new Exception('RSA公钥错误。请检查公钥文件格式是否正确');
}
$crypttext = "";
openssl_public_encrypt($data,$crypttext, $res );
if(!$this->checkEmpty($this->eplConfig['publicKeyFilePath'])) {
//释放资源
if (PHP_VERSION_ID < 80000) {
openssl_free_key($res);
}
}
return(base64_encode($crypttext));
}
/**
* 校验$value是否非空
* if not set ,return true;
* if is null , return true;
**/
protected function checkEmpty($value) {
if (!isset($value))
return true;
if ($value === null)
return true;
if (trim($value) === "")
return true;
return false;
}
}