272 lines
9.6 KiB
PHP
272 lines
9.6 KiB
PHP
<?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;
|
||
}
|
||
|
||
}
|