@@ -2,10 +2,12 @@ | |||
namespace addons\epay\library; | |||
use addons\unishop\model\Config; | |||
use Exception; | |||
use think\Log; | |||
use think\Response; | |||
use think\Session; | |||
use Yansongda\Pay\Gateways\Alipay\Alipay; | |||
use Yansongda\Pay\Pay; | |||
/** | |||
@@ -156,6 +158,32 @@ class Service | |||
} | |||
/** | |||
* @param string $orderNo 订单号 | |||
* @param string $type 支付类型 wechat alipay | |||
* @param int $amount 退款金额 | |||
*/ | |||
public static function refund($orderNo,$type,$amount){ | |||
$config = Service::getConfig($type); | |||
$pay = new Pay($config); | |||
if ($type == "alipay") { | |||
$config_biz = [ | |||
'out_trade_no' => $orderNo, | |||
'refund_amount' => $amount, | |||
]; | |||
$pay->driver($type)->gateway()->refund($config_biz); | |||
} else { | |||
$config_biz = [ | |||
'out_trade_no' => $orderNo, | |||
'out_refund_no' => $orderNo, | |||
'total_fee' => bcmul($amount, 100), | |||
'refund_fee' => bcmul($amount, 100), | |||
]; | |||
$pay->driver($type)->gateway()->refund($config_biz); | |||
} | |||
} | |||
/** | |||
* 创建支付对象 | |||
* @param string $type 支付类型 | |||
* @param array $config 配置信息 | |||
@@ -53,8 +53,8 @@ abstract class Alipay implements GatewayInterface | |||
'charset' => 'UTF-8', | |||
'sign_type' => 'RSA2', | |||
'version' => '1.0', | |||
'return_url' => $this->user_config->get('return_url', ''), | |||
'notify_url' => $this->user_config->get('notify_url', ''), | |||
'notifyurl' => \addons\unishop\model\Config::getByName('ali_notify_url')['value'], | |||
'returnurl' => \addons\unishop\model\Config::getByName('ali_return_url')['value'], | |||
'timestamp' => date('Y-m-d H:i:s'), | |||
'sign' => '', | |||
'biz_content' => '', | |||
@@ -0,0 +1,307 @@ | |||
<?php | |||
/** | |||
* | |||
* ============================================================================ | |||
* * 版权�?�? 运游�? * * | |||
* 网站地址: http://www.zhizhuchuxing.com | |||
* ---------------------------------------------------------------------------- | |||
* 这不是一个自由软件!您只能在不用于商业目的的前提下对程序代码进行修改�? | |||
* 使用;不允许对程序代码以任何形式任何目的的再发布�? | |||
* ============================================================================ | |||
* Author By: 倪宗�? | |||
* PhpStorm AliPayService.php | |||
* Create By 2016/12/12 14:32 $ | |||
*/ | |||
namespace addons\nzf; | |||
use addons\unishop\model\Config; | |||
class AliPay | |||
{ | |||
private static $gatewayUrl = "https://openapi.alipaydev.com/gateway.do"; | |||
/** | |||
* Des:扫描支付 | |||
* Name: unifiedOrderByOrderIdForSao | |||
* @param $par | |||
* @return array | |||
* @author 倪宗锋 | |||
*/ | |||
public function unifiedOrderByOrderIdForSao($par) | |||
{ | |||
$aliPay = new AliPay(); | |||
//交易参数 | |||
$params['body'] = $par['name']; | |||
$params['subject'] = $par['name']; | |||
$params['order_id'] = $par['order_id']; | |||
$params['price'] = $par['total_fee']; | |||
$params['timeout_express'] = '1m'; | |||
$params['goType'] = 3; | |||
$params['method'] = 'alipay.trade.precreate'; | |||
$getUrl = $aliPay->getAliPayUrl($params); | |||
$url = '/fx/?r=weChat/we-chat/q-code&qCode=' . urlencode($getUrl['data']['codUrl']) . '&_math=' . rand(100, 999); | |||
return Util::returnArrSu('', array('codUrl' => $url, 'price' => $par['total_fee'])); | |||
} | |||
/** | |||
* Function Description:支付宝web支付 | |||
* Function Name: webPay | |||
* @param $param array | |||
* @return array | |||
* | |||
* @author nzf | |||
*/ | |||
public function webPay($param) | |||
{ | |||
//交易参数 | |||
$params['body'] = $param['name']; | |||
$params['subject'] = $param['name']; | |||
$params['order_id'] = $param['order_id']; | |||
$params['price'] = $param['total_fee']; | |||
$params['timeout_express'] = '1m'; | |||
$params['goType'] = 2; | |||
$params['method'] = 'alipay.trade.wap.pay'; | |||
$return = static::getAliPayUrl($params); | |||
return $return; | |||
} | |||
/********************通用方法**************************/ | |||
/** | |||
* Function Description:获取阿里支付pay | |||
* Function Name: getAliPayUrl | |||
* @param $params array | |||
* | |||
* @return array | |||
* | |||
* @author 倪宗�? | |||
*/ | |||
private static function getAliPayUrl($params) | |||
{ | |||
$sysParams = self::getSysParams(); | |||
$sysParams["method"] = $params['method']; | |||
//交易参数 | |||
$body['productCode'] = 'QUICK_WAP_PAY'; | |||
$body['body'] = $params['body']; | |||
$body['subject'] = $params['subject']; | |||
$body['out_trade_no'] = $params['order_id']; | |||
$body['total_amount'] = $params['price']; | |||
$body['timeout_express'] = "1m"; | |||
$sysParams['biz_content'] = json_encode($body); | |||
if ($params['goType'] == 1) {//如果是页面跳�? | |||
$sysParams['sign'] = urlencode(static::getSign($sysParams)); | |||
$paramString = static::getSignContent($sysParams); | |||
$requestUrl = static::$gatewayUrl . "?" . $paramString; | |||
return Util::returnArrSu('', ['payData' => $requestUrl]); | |||
} elseif ($params['goType'] == 2) {//如果是参数返�? | |||
$sysParams['sign'] = static::getSign($sysParams); | |||
$result = self::buildRequestForm($sysParams); | |||
return Util::returnArrSu('', ['payData' => $result]); | |||
} else { | |||
$sysParams['sign'] = urlencode(static::getSign($sysParams)); | |||
$paramString = static::getSignContent($sysParams); | |||
$requestUrl = static::$gatewayUrl . "?" . $paramString; | |||
$curl = new CurlInterface('', 5); | |||
$result = $curl->execute($requestUrl, 'GET'); | |||
$result = json_decode($result, true); | |||
$return['codUrl'] = ''; | |||
if ($result['alipay_trade_precreate_response']['code'] == '10000') { | |||
$return['codUrl'] = $result['alipay_trade_precreate_response']['qr_code']; | |||
} | |||
return Util::returnArrSu('', $return); | |||
} | |||
} | |||
/** | |||
* Function Description:取消订单 | |||
* Function Name: cancelOrder | |||
* @param $params | |||
* | |||
* @return array | |||
* | |||
* @author 倪宗�? | |||
*/ | |||
public static function cancelOrder($params) | |||
{ | |||
$sysParams = self::getSysParams(); | |||
$sysParams["method"] = 'alipay.trade.refund'; | |||
$body = array( | |||
'out_trade_no' => $params['order_id'],//订单�? | |||
'refund_amount' => $params['refund_fee'],//退款金额 | |||
'refund_reason' => $params['memo'], | |||
'out_request_no' => $params['order_id'] . '-' . date('YmdHis') . rand(100, 999)//�?款原�? | |||
); | |||
unset($sysParams["notify_url"]); | |||
unset($sysParams["return_url"]); | |||
$sysParams['biz_content'] = json_encode($body); | |||
$sysParams['sign'] = static::getSign($sysParams); | |||
$sysParams['sign'] = urlencode(static::getSign($sysParams)); | |||
$paramString = static::getSignContent($sysParams); | |||
$requestUrl = static::$gatewayUrl."?".$paramString; | |||
//调用款接 | |||
$curlInterface = new CurlInterface($sysParams, 5); | |||
$result = $curlInterface->execute($requestUrl, 'GET'); | |||
$result = json_decode(mb_convert_encoding($result, 'utf-8'), true); | |||
if (isset($result['alipay_trade_refund_response']) && $result['alipay_trade_refund_response']['code'] == '10000') { | |||
return Util::returnArrSu(); | |||
} | |||
return Util::returnArrEr('退款失败!'); | |||
} | |||
/** | |||
* Function Description:获取系统通用参数 | |||
* Function Name: getSysParams | |||
* @param $app_id string | |||
* @param $order_id string | |||
* @return mixed | |||
* | |||
* @author 倪宗�? | |||
*/ | |||
private static function getSysParams() | |||
{ | |||
//组装系统参数 | |||
$sysParams["app_id"] = Config::getByName('ali_app_id')['value']; | |||
$sysParams["version"] = '1.0'; | |||
$sysParams["format"] = 'json'; | |||
$sysParams["sign_type"] = 'RSA2'; | |||
$sysParams["timestamp"] = date("Y-m-d H:i:s"); | |||
$sysParams["alipay_sdk"] = 'alipay-sdk-php-20160411'; | |||
$sysParams["prod_code"] = ''; | |||
$sysParams["notify_url"] = Config::getByName('ali_notify_url')['value']; | |||
$sysParams["return_url"] = Config::getByName('ali_return_url')['value']; | |||
$sysParams["charset"] = "utf-8"; | |||
return $sysParams; | |||
} | |||
/** | |||
* Function Description:建立请求,以表单HTML形式构�?�(默认�? | |||
* Function Name: buildRequestForm | |||
* @param $para_temp | |||
* | |||
* @return string 提交表单HTML文本 | |||
* | |||
* @author 倪宗�? | |||
*/ | |||
protected static function buildRequestForm($para_temp) | |||
{ | |||
$sHtml = "<form id='alipaysubmit' name='alipaysubmit' action='" . static::$gatewayUrl . "?charset=utf-8' method='get'>"; | |||
while (list ($key, $val) = each($para_temp)) { | |||
if (false === static::checkEmpty($val)) { | |||
$val = str_replace("'", "'", $val); | |||
$sHtml .= "<input type='hidden' name='" . $key . "' value='" . $val . "'/>"; | |||
} | |||
} | |||
return $sHtml; | |||
} | |||
/** | |||
* Function Description:获取签名 | |||
* Function Name: getSign | |||
* @param $params | |||
* @param $app_id | |||
* @return string | |||
* | |||
* @author 倪宗�? | |||
*/ | |||
public static function getSign($params) | |||
{ | |||
if (isset($params['sign'])) { | |||
unset($params['sign']); | |||
} | |||
$content = self::getSignContent($params); | |||
$priKey = Config::getByName('ali_private_key')['value']; | |||
// $res = "-----BEGIN RSA PRIVATE KEY-----\n" . | |||
// wordwrap($priKey, 64, "\n", true) . | |||
// "\n-----END RSA PRIVATE KEY-----"; | |||
// openssl_sign($content, $sign, $res); | |||
// $sign = base64_encode($sign); | |||
// return $sign; | |||
$res = "-----BEGIN RSA PRIVATE KEY-----\n". | |||
wordwrap($priKey, 64, "\n", true). | |||
"\n-----END RSA PRIVATE KEY-----"; | |||
openssl_sign($content, $sign, $res, OPENSSL_ALGO_SHA256); | |||
return base64_encode($sign); | |||
} | |||
/** | |||
* Function Description:将数组转换为符合阿里支付的路由参�? | |||
* Function Name: getSignContent | |||
* @param $params | |||
* | |||
* @return string | |||
* | |||
* @author 倪宗�? | |||
*/ | |||
public static function getSignContent($params) | |||
{ | |||
ksort($params); | |||
$stringToBeSigned = ""; | |||
$i = 0; | |||
foreach ($params as $k => $v) { | |||
if (false === self::checkEmpty($v) && "@" != substr($v, 0, 1)) { | |||
// 转换成目标字符集 | |||
$v = self::characet($v, 'utf-8'); | |||
if ($i == 0) { | |||
$stringToBeSigned.="$k"."="."$v"; | |||
} else { | |||
$stringToBeSigned.="&"."$k"."=".$v; | |||
} | |||
$i++; | |||
} | |||
} | |||
unset ($k, $v); | |||
return $stringToBeSigned; | |||
} | |||
/** | |||
* Function Description:校验$value是否非空 | |||
* Function Name: checkEmpty | |||
* @param $value | |||
* | |||
* @return bool | |||
* | |||
* @author 倪宗�? | |||
*/ | |||
private static function checkEmpty($value) | |||
{ | |||
if (!isset($value)) { | |||
return true; | |||
} | |||
if ($value === null) { | |||
return true; | |||
} | |||
if (trim($value) === "") { | |||
return true; | |||
} | |||
return false; | |||
} | |||
/** | |||
* Function Description:转换字符集编�? | |||
* Function Name: characet | |||
* @param $data | |||
* @param $targetCharset | |||
* | |||
* @return string | |||
* | |||
* @author 倪宗�? | |||
*/ | |||
private static function characet($data, $targetCharset) | |||
{ | |||
if (!empty($data)) { | |||
$fileType = 'utf-8'; | |||
if (strcasecmp($fileType, $targetCharset) != 0) { | |||
$data = mb_convert_encoding($data, $targetCharset); | |||
} | |||
} | |||
return $data; | |||
} | |||
} |
@@ -0,0 +1,466 @@ | |||
<?php | |||
/** | |||
* 接口调用 | |||
* ============================================================================ | |||
* * 版权所有 蜘蛛行 * * | |||
* 网站地址: http://www.zhizhuchuxing.com | |||
* ---------------------------------------------------------------------------- | |||
* 这不是一个自由软件!您只能在不用于商业目的的前提下对程序代码进行修改和 | |||
* 使用;不允许对程序代码以任何形式任何目的的再发布。 | |||
* ============================================================================ | |||
* Author By: 倪宗锋 | |||
* PhpStorm CurlInterface.php | |||
* Create By 2016/11/10 13:20 $ | |||
*/ | |||
namespace addons\nzf; | |||
class CurlInterface | |||
{ | |||
protected $url = null; | |||
protected $verb = 'GET'; | |||
protected $body = ''; | |||
protected $requestLength = 0; | |||
protected $baseUrl = null; | |||
protected $timeOut = 200; | |||
protected $clientId = 1;//站点类型 1 微信 | |||
protected $responseBody = null;//接收到的返回值 | |||
protected $notReturn = false; //是否有返回值 | |||
protected $siteConfig = null; //配置参数 | |||
protected $curlGetInfo = null;//交易概要 | |||
private $logMessage = ''; //日志内容 | |||
private $curlOptHeader = 0; //是否返回头部信息 | |||
private $bodyType = 1; | |||
private $cert = false;//是否使用证书 | |||
private $certPem; | |||
private $keyPem; | |||
/****************============类的初始化=============*******************/ | |||
/** | |||
* @param null $body 2:xml | |||
* @param int $type 1:json 2:xml 3 发送原数据接收xml 4 发送原数据 接收json 5:都是原数据 | |||
*/ | |||
public function __construct($body = null, $type = 1) | |||
{ | |||
$this->setBody($body, $type); | |||
$this->setBaseUrl(); | |||
} | |||
/*****************==========参数设置函数开始=========******************/ | |||
/** | |||
* Function Description:设置是否返回头部信息 | |||
* Function Name: setCurlOptHeader | |||
* @param $curlOptHeader | |||
* | |||
* | |||
* @author 倪宗锋 | |||
*/ | |||
public function setCurlOptHeader($curlOptHeader) | |||
{ | |||
$this->curlOptHeader = $curlOptHeader; | |||
} | |||
/** | |||
* Function Description:获取交易概要 | |||
* Function Name: getCurlGetInfo | |||
* | |||
* @return null | |||
* | |||
* @author 倪宗锋 | |||
*/ | |||
public function getCurlGetInfo() | |||
{ | |||
return $this->curlGetInfo; | |||
} | |||
/** | |||
* Function Description:获取返回值报文 | |||
* Function Name: getResponseBody | |||
* | |||
* @return null | |||
* | |||
* @author 倪宗锋 | |||
*/ | |||
public function getResponseBody() | |||
{ | |||
return $this->responseBody; | |||
} | |||
/** | |||
* Function Description:获取全路径地址 | |||
* Function Name: getUrl | |||
* | |||
* @return null | |||
* | |||
* @author 倪宗锋 | |||
*/ | |||
public function getUrl() | |||
{ | |||
return $this->url; | |||
} | |||
/** | |||
* Function Description:设置路径 在baseUrl基础上 | |||
* Function Name: setUrl | |||
* @param $url | |||
* | |||
* | |||
* @author 倪宗锋 | |||
*/ | |||
public function setUrl($url) | |||
{ | |||
$this->url = $this->baseUrl . $url; | |||
} | |||
/** | |||
* Function Description:设置过期时间 | |||
* Function Name: setTimeOut | |||
* @param $timeOut | |||
* | |||
* | |||
* @author 倪宗锋 | |||
*/ | |||
public function setTimeOut($timeOut) | |||
{ | |||
$this->timeOut = $timeOut; | |||
} | |||
/** | |||
* Function Description:设置传值方式 | |||
* Function Name: setVerb | |||
* @param $verb | |||
* | |||
* | |||
* @author 倪宗锋 | |||
*/ | |||
public function setVerb($verb) | |||
{ | |||
$this->verb = $verb; | |||
} | |||
/** | |||
* Function Description:设置baseUrl | |||
* Function Name: setBaseUrl | |||
* @param $baseUrl string | |||
* | |||
* @author 倪宗锋 | |||
*/ | |||
public function setBaseUrl($baseUrl = '') | |||
{ | |||
$this->baseUrl = $baseUrl; | |||
} | |||
/** | |||
* Function Description:获取BaseUrl | |||
* Function Name: getBaseUrl | |||
* | |||
* @return null | |||
* | |||
* @author 倪宗锋 | |||
*/ | |||
public function getBaseUrl() | |||
{ | |||
return $this->baseUrl; | |||
} | |||
/** | |||
* Function Description:设置是否有返回值 | |||
* Function Name: setNotReturn | |||
* @param $str | |||
* | |||
* | |||
* @author 倪宗锋 | |||
*/ | |||
public function setNotReturn($str) | |||
{ | |||
$this->notReturn = $str; | |||
} | |||
/** | |||
* Function Description:设置请求报文 $body 必须是个数组 | |||
* Function Name: setBody | |||
* @param $body | |||
* @param $type int 1:json 2:xml 3 发送原数据接收xml 4 发送原数据 接收json 5:都是原数据 | |||
* | |||
* @author 倪宗锋 | |||
*/ | |||
public function setBody($body, $type = 1) | |||
{ | |||
$this->body = ''; | |||
if (is_array($body)) { | |||
if ($type == 1) { | |||
$this->body = json_encode($body); | |||
$this->requestLength = strlen($this->body); | |||
} elseif ($type == 2) { | |||
$this->body = '<?xml version="1.0" encoding="UTF-8"?>' . Util::arraysToXml(['response' => $body]); | |||
$this->requestLength = strlen($this->body); | |||
} elseif (in_array($type, array(3, 4, 5))) { | |||
$this->body = $body; | |||
} | |||
} else { | |||
$this->body = $body; | |||
} | |||
$this->bodyType = $type; | |||
} | |||
/** | |||
* Function Description:设置ssl类型 | |||
* Function Name: setCert | |||
* @param $certArr array | |||
* | |||
* | |||
* @author 倪宗锋 | |||
*/ | |||
public function setCert($certArr) | |||
{ | |||
$this->cert = true; | |||
$this->certPem = $certArr['SSLCERT_PATH']; | |||
$this->keyPem = $certArr['SSLKEY_PATH']; | |||
} | |||
/*****************==========参数设置函数结束=========******************/ | |||
/*****************==========调用接口并返回结果===开始======******************/ | |||
/** | |||
* Function Description:执行交易 | |||
* Function Name: execute | |||
* @param $url string sap地址 | |||
* @param $verb string 请求方式 post|get | |||
* @return array | |||
* @author nizongfeng | |||
* Modify Date:2016.11.10 | |||
*/ | |||
public function execute($url, $verb = 'GET') | |||
{ | |||
$url = preg_replace('# #','%20',$url); | |||
$this->verb = $verb; | |||
$this->url = $this->baseUrl . $url; | |||
$this->logMessage .= date('Y-m-d H:i:s') . " Url : {$this->url}"; | |||
$this->logMessage .= ' Method:' . $this->verb . PHP_EOL; | |||
if (is_array($this->body)) { | |||
$this->logMessage .= "sendContent: " . json_encode($this->body) . PHP_EOL; | |||
} else { | |||
$this->logMessage .= "sendContent: {$this->body}" . PHP_EOL; | |||
} | |||
$ch = curl_init($this->url); | |||
try { | |||
switch (strtoupper($this->verb)) { | |||
case 'GET': | |||
$this->executeGet($ch); | |||
break; | |||
case 'POST': | |||
$this->executePost($ch); | |||
break; | |||
case 'PUT': | |||
$this->executePut($ch); | |||
break; | |||
case 'DELETE': | |||
$this->executeDelete($ch); | |||
break; | |||
default: | |||
$this->logMessage .= "current verb: {$this->verb}, is an invalid REST verb." . PHP_EOL; | |||
break; | |||
} | |||
} catch (\Exception $e) { | |||
$this->logMessage .= $e->getMessage() . PHP_EOL; | |||
} | |||
curl_close($ch); | |||
$ch = null; | |||
return $this->getResult(); | |||
} | |||
/** | |||
* Function Description:获取返回数据 | |||
* Function Name: getResult | |||
* | |||
* @return array|mixed | |||
* | |||
* @author nizongfeng | |||
* Modify Date:2016.11.10 | |||
*/ | |||
public function getResult() | |||
{ | |||
if (in_array($this->bodyType, array(1, 4))) { | |||
$return = json_decode($this->responseBody, true); | |||
} elseif (in_array($this->bodyType, array(2, 3))) { | |||
$return = Util::xmlToArray($this->responseBody); | |||
} elseif ($this->bodyType == 5) { | |||
$return = $this->responseBody; | |||
} else { | |||
$return = ''; | |||
} | |||
// file_put_contents(APP_PATH . '/log/curl/' . date('Y-m-d') . '.log', $this->logMessage . PHP_EOL, FILE_APPEND); | |||
return $return; | |||
} | |||
/*******************=====GET传值=====********************/ | |||
/** | |||
* Function Description:GET传值 | |||
* Function Name: executeGet | |||
* @param $ch | |||
* | |||
* @return void | |||
* | |||
* @author nizongfeng 2016.11.10 | |||
*/ | |||
protected function executeGet($ch) | |||
{ | |||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); | |||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); | |||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); | |||
$this->doExecute($ch); | |||
} | |||
/*******************=====POST传值=====********************/ | |||
/** | |||
* Function Description:POST传值 | |||
* Function Name: executePost | |||
* @param $ch | |||
* | |||
* @return void | |||
* | |||
* @author nizongfeng 2016.11.10 | |||
*/ | |||
protected function executePost($ch) | |||
{ | |||
// curl_setopt($ch, CURLOPT_VERBOSE, true); | |||
curl_setopt($ch, CURLOPT_POST, true); | |||
if (is_array($this->body)) { | |||
$cnt = $this->getmaxdim($this->body); | |||
if ($cnt > 1) { | |||
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($this->body)); | |||
} else { | |||
curl_setopt($ch, CURLOPT_POSTFIELDS, $this->body); | |||
} | |||
} else { | |||
curl_setopt($ch, CURLOPT_POSTFIELDS, $this->body); | |||
} | |||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); | |||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); | |||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); | |||
$this->doExecute($ch); | |||
} | |||
/*******************=====PUT传值=====********************/ | |||
/** | |||
* Function Description:PUT传值 | |||
* Function Name: executePut | |||
* @param $ch | |||
* | |||
* | |||
* @author 倪宗锋 | |||
*/ | |||
protected function executePut($ch) | |||
{ | |||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT'); | |||
curl_setopt($ch, CURLOPT_POSTFIELDS, $this->body); | |||
$this->doExecute($ch); | |||
} | |||
/*******************=====DELETE传值=====********************/ | |||
/** | |||
* Function Description:DELETE传值 | |||
* Function Name: executeDelete | |||
* @param $ch | |||
* | |||
* | |||
* @author 倪宗锋 | |||
*/ | |||
protected function executeDelete($ch) | |||
{ | |||
curl_setopt($ch, CURLOPT_POSTFIELDS, $this->body); | |||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE'); | |||
$this->doExecute($ch); | |||
} | |||
/*******************=====传值及接收=====********************/ | |||
/** | |||
* Function Description: 传值及接受数据 | |||
* Function Name: doExecute | |||
* @param $curlHandle | |||
* | |||
* @return void | |||
* | |||
* @author nizongfeng 2015.12.08 | |||
*/ | |||
protected function doExecute(&$curlHandle) | |||
{ | |||
if ($this->verb != 'get') { | |||
$this->setCurlOpts($curlHandle); | |||
} | |||
curl_setopt($curlHandle, CURLOPT_HEADER, $this->curlOptHeader); | |||
curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, true); | |||
curl_setopt($curlHandle, CURLOPT_TIMEOUT, $this->timeOut); | |||
//记录报文发送时间 | |||
$sendTime = microtime(true); | |||
$this->responseBody = curl_exec($curlHandle); | |||
//记录报文返回时间 | |||
$responseTime = microtime(true); | |||
$timeIncrement = round(floatval($responseTime - $sendTime), 3); | |||
//记录返回的报文信息 | |||
$this->logMessage .= "response: {$this->responseBody}" . PHP_EOL; | |||
$curlInfo = curl_getinfo($curlHandle); | |||
$this->curlGetInfo = $curlInfo; | |||
if (empty($curlInfo['primary_port'])) { | |||
$curlInfo['primary_port'] = ''; | |||
} | |||
$curlInfoStr = ''; | |||
if (isset($_SERVER['SERVER_ADDR']) && $_SERVER['SERVER_PORT']) { | |||
$curlInfoStr = " toIP {$curlInfo['primary_ip']}:{$curlInfo['primary_port']}"; | |||
$curlInfoStr .= " selfIP {$_SERVER['SERVER_ADDR']} {$_SERVER['SERVER_PORT']}"; | |||
} | |||
//记录通信信息及性能指标 | |||
$this->logMessage .= "Info: " . json_encode($curlInfoStr) . PHP_EOL; | |||
$this->logMessage .= "sendTime: " . date('H:i:s', $sendTime) . " , responseTime: "; | |||
$this->logMessage .= date('H:i:s', $responseTime) . " , timeIncrement:" . $timeIncrement . 's' | |||
. PHP_EOL; | |||
$curlError = curl_error($curlHandle); | |||
if ($curlError) { | |||
$this->logMessage .= "Error: " . $curlError . PHP_EOL; | |||
} | |||
} | |||
/*******************=====头部设置=====********************/ | |||
/** | |||
* Function Description:头部设置 | |||
* Function Name: setCurlOpts | |||
* @param $curlHandle | |||
* | |||
* | |||
* @author 倪宗锋 | |||
*/ | |||
protected function setCurlOpts(&$curlHandle) | |||
{ | |||
if ($this->cert == 1) { | |||
//设置证书 | |||
//使用证书:cert 与 key 分别属于两个.pem文件 | |||
curl_setopt($curlHandle, CURLOPT_SSLCERTTYPE, 'PEM'); | |||
curl_setopt($curlHandle, CURLOPT_SSLCERT, $this->certPem); | |||
curl_setopt($curlHandle, CURLOPT_SSLKEYTYPE, 'PEM'); | |||
curl_setopt($curlHandle, CURLOPT_SSLKEY, $this->keyPem); | |||
} | |||
} | |||
/*****************==========调用接口并返回结果===结束======******************/ | |||
//获取数组是几维数组 | |||
private function getmaxdim($vDim) | |||
{ | |||
if (!is_array($vDim)) return 0; | |||
else { | |||
$max1 = 0; | |||
foreach ($vDim as $item1) { | |||
$t1 = $this->getmaxdim($item1); | |||
if ($t1 > $max1) $max1 = $t1; | |||
} | |||
return $max1 + 1; | |||
} | |||
} | |||
} | |||
?> |
@@ -0,0 +1,98 @@ | |||
<?php | |||
/** | |||
* | |||
* ============================================================================ | |||
* * 版权所有 蜘蛛出行 * * | |||
* 网站地址: http://www.zhizhuchuxing.com | |||
* ---------------------------------------------------------------------------- | |||
* 这不是一个自由软件!您只能在不用于商业目的的前提下对程序代码进行修改和 | |||
* 使用;不允许对程序代码以任何形式任何目的的再发布。 | |||
* ============================================================================ | |||
* Author By: 倪宗锋 | |||
* PhpStorm PayService.php | |||
* Create By 2017/3/3 19:53 $ | |||
*/ | |||
namespace addons\nzf; | |||
class PayService | |||
{ | |||
/** | |||
* Des:扫码支付 | |||
* Name: sao | |||
* @param $params array order_id:订单ID name:订单名称 total_fee:总金额-元 | |||
* @param int $type 3、微信4、支付宝 | |||
* @return array | |||
* @author 倪宗锋 | |||
*/ | |||
public static function sao($params, $type = 1) | |||
{ | |||
if ($type == 3) { | |||
$pay = new WeChatPay();//微信支付类 | |||
} else { | |||
$pay = new AliPay();//支付宝支付类 | |||
} | |||
$return = $pay->unifiedOrderByOrderIdForSao($params); | |||
return $return; | |||
} | |||
/** | |||
* Des:取消订单 | |||
* Name: cancel | |||
* @param $params array order_id:订单ID name:订单名称 total_fee:总金额-元 refund_fee退款金额 | |||
* @param int $type 3、微信 4、支付宝 | |||
* @return array | |||
* @author 倪宗锋 | |||
*/ | |||
public static function cancel($params, $type) | |||
{ | |||
if ($type == 3) {//微信支付 | |||
$pay = new WeChatPay(); | |||
$return = $pay->cancelOrder($params); | |||
} else {//阿里支付 | |||
$pay = new AliPay(); | |||
$return = $pay->cancelOrder($params); | |||
} | |||
return $return; | |||
} | |||
/** | |||
* Des: 直接付款 | |||
* Name: pay | |||
* @param $params array | |||
* $order_id string 订单表 订单ID | |||
* $name string 产品名称 | |||
* $total_fee int 总金额 单位元 | |||
* $openid string 用户opendid | |||
* @param $type 1微信 2支付宝 | |||
* | |||
* @return array | |||
* @author 倪宗锋 | |||
*/ | |||
public static function pay($params,$type = 1) | |||
{ | |||
if($type == 1) { | |||
$pay = new WeChatPay();//微信支付类 | |||
}else { | |||
$pay = new AliPay();//支付宝支付类 | |||
} | |||
$return = $pay->webPay($params); | |||
return $return['data']['payData']; | |||
} | |||
/** | |||
* Des: 支付 目前只支持微信直接支付 | |||
* Name: pay | |||
* @param $orderId string 订单ID | |||
* | |||
* @return array | |||
* @author 倪宗锋 | |||
*/ | |||
public static function checkIsPay($orderId) | |||
{ | |||
$pay = new WeChatPay(); | |||
$return = $pay->checkIsPay($orderId); | |||
return $return; | |||
} | |||
} |
@@ -0,0 +1,343 @@ | |||
<?php | |||
/** | |||
* 全局通用方法集合 | |||
* ============================================================================ | |||
* * 版权所有 蜘蛛出行 * * | |||
* 网站地址: http://www.zhizhuchuxing.com | |||
* ---------------------------------------------------------------------------- | |||
* 这不是一个自由软件!您只能在不用于商业目的的前提下对程序代码进行修改和 | |||
* 使用;不允许对程序代码以任何形式任何目的的再发布。 | |||
* ============================================================================ | |||
* Author By: 倪宗锋 | |||
* PhpStorm Util.php | |||
* Create By 2017/2/22 19:44 $ | |||
*/ | |||
namespace addons\nzf; | |||
class Util | |||
{ | |||
/** | |||
* Function Description:返回成功Json数据到 | |||
* Function Name: returnSu | |||
* @param string $msg 提示信息 | |||
* @param string $url 跳转地址 | |||
* @param string|array $data 需要传递的数据 | |||
* @param string $code 错误码 | |||
* | |||
* @return string | |||
* | |||
* @author 倪宗锋 | |||
*/ | |||
public static function returnJsSu($msg = '', $data = '', $url = '', $code = '') | |||
{ | |||
$return = array(); | |||
$return['flag'] = true; | |||
$return['msg'] = $msg; | |||
$return['url'] = $url; | |||
$return['code'] = $code; | |||
$return['data'] = $data; | |||
return json_encode($return); | |||
} | |||
/** | |||
* Function Description:返回成功Json数据 | |||
* Function Name: returnEr | |||
* @param string $msg 提示信息 | |||
* @param string $url 跳转地址 | |||
* @param string|array $data 需要传递的数据 | |||
* @param string $code 错误码 | |||
* | |||
* @return string | |||
* | |||
* @author 倪宗锋 | |||
*/ | |||
public static function returnJsEr($msg = '', $data = '', $url = '', $code = '') | |||
{ | |||
$return = array(); | |||
$return['flag'] = false; | |||
$return['msg'] = $msg; | |||
$return['url'] = $url; | |||
$return['code'] = $code; | |||
$return['data'] = $data; | |||
return json_encode($return); | |||
} | |||
/** | |||
* Function Description:返回成功数组数据 | |||
* Function Name: returnArrSu | |||
* @param string $msg 提示信息 | |||
* @param string $url 跳转地址 | |||
* @param string|array $data 需要传递的数据 | |||
* @param string $code 错误码 | |||
* | |||
* @return array | |||
* | |||
* @author 倪宗锋 | |||
*/ | |||
public static function returnArrSu($msg = '', $data = '', $url = '', $code = '') | |||
{ | |||
$return = array(); | |||
$return['flag'] = true; | |||
$return['msg'] = $msg; | |||
$return['url'] = $url; | |||
$return['code'] = $code; | |||
$return['data'] = $data; | |||
return $return; | |||
} | |||
/** | |||
* Function Description:返回错误数组数据 | |||
* Function Name: returnArrEr | |||
* @param string $msg 提示信息 | |||
* @param string $url 跳转地址 | |||
* @param string|array $data 需要传递的数据 | |||
* @param string $code 错误码 | |||
* | |||
* @return array | |||
* | |||
* @author 倪宗锋 | |||
*/ | |||
public static function returnArrEr($msg = '', $data = '', $url = '', $code = '') | |||
{ | |||
$return = array(); | |||
$return['flag'] = false; | |||
$return['msg'] = $msg; | |||
$return['url'] = $url; | |||
$return['code'] = $code; | |||
$return['data'] = $data; | |||
return $return; | |||
} | |||
/** | |||
* Function Description:json转换为xml | |||
* Function Name: jsonToXml | |||
* @param $json | |||
* | |||
* @return bool|string | |||
* | |||
* @author 倪宗锋 | |||
*/ | |||
public static function jsonToXml($json) | |||
{ | |||
if (empty($json)) { | |||
return false; | |||
} | |||
$array = json_decode($json); | |||
$xml = ''; | |||
$xml .= '<?xml version="1.0" encoding="UTF-8"?>' . self::arraysToXml(['response' => $array]); | |||
return $xml; | |||
} | |||
/** | |||
* Function Description:数组转换成xml | |||
* Function Name: arrayToXml | |||
* @param $array | |||
* @param $key | |||
* @return string | |||
* | |||
* @author 倪宗锋 | |||
*/ | |||
public static function arraysToXml($array, $key = '') | |||
{ | |||
$string = ''; | |||
if (count($array) == 0) { | |||
return ''; | |||
} | |||
foreach ($array as $k => $v) { | |||
if (is_array($v) && isset($v['0'])) { | |||
$string .= self::arraysToXml($v, $k);//是数组或者对像就的递归调用 | |||
} else { | |||
if ($key != '') { | |||
$k = $key; | |||
} | |||
$string .= '<' . $k . '>'; | |||
if (is_array($v) || is_object($v)) {//判断是否是数组,或者,对像 | |||
$string .= self::arraysToXml($v);//是数组或者对像就的递归调用 | |||
} elseif (is_numeric($v)) { | |||
$string .= $v; | |||
} elseif ($v != '') { | |||
$string .= '<![CDATA[' . $v . ']]>'; | |||
} else { | |||
$string .= ''; | |||
} | |||
$string .= '</' . $k . '>'; | |||
} | |||
} | |||
return $string; | |||
} | |||
/** | |||
* Function Description:xml转换为json | |||
* Function Name: xml_to_json | |||
* @param $source | |||
* | |||
* @return string | |||
* | |||
* @author 倪宗锋 | |||
*/ | |||
public static function xmlToJson($source) | |||
{ | |||
if (is_file($source)) { //传的是文件,还是xml的string的判断 | |||
$xml_array = simplexml_load_file($source); | |||
} else { | |||
$xml_array = simplexml_load_string(trim($source)); | |||
} | |||
$json = json_encode($xml_array, true); | |||
return $json; | |||
} | |||
/** | |||
* Function Description:xml转换成数组 | |||
* Function Name: xmlToArray | |||
* @param $source | |||
* | |||
* @return mixed | |||
* | |||
* @author 倪宗锋 | |||
*/ | |||
public static function xmlToArray($source) | |||
{ | |||
libxml_disable_entity_loader(true); | |||
$getResult = json_decode(json_encode(simplexml_load_string(trim($source), 'SimpleXMLElement', LIBXML_NOCDATA)), true); | |||
return $getResult; | |||
} | |||
/** Function Description:加密解密函数 | |||
* Function Name: authCode | |||
* @param $string | |||
* @param string $operation | |||
* @param int $expiry | |||
* @return string|array | |||
* @author 倪宗锋 | |||
*/ | |||
static function authCode($string, $operation = 'DECODE', $expiry = 0) | |||
{ | |||
$key = 'udM5A8S50eg8veH15dd0m601de7073N8Bcn7d1I8Res7C7o7z274D6y342I4C7t7'; | |||
$ckey_length = 4; // 随机密钥长度 取值 0-32; | |||
// 加入随机密钥,可以令密文无任何规律,即便是原文和密钥完全相同,加密结果也会每次不同,增大破解难度。 | |||
// 取值越大,密文变动规律越大,密文变化 = 16 的 $ckey_length 次方 | |||
// 当此值为 0 时,则不产生随机密钥 | |||
$key = md5($key); | |||
$keya = md5(substr($key, 0, 16)); | |||
$keyb = md5(substr($key, 16, 16)); | |||
$keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length) : substr(md5(microtime()), -$ckey_length)) : ''; | |||
$cryptkey = $keya . md5($keya . $keyc); | |||
$key_length = strlen($cryptkey); | |||
$string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0) . substr(md5($string . $keyb), 0, 16) . $string; | |||
$string_length = strlen($string); | |||
$result = ''; | |||
$box = range(0, 255); | |||
$rndkey = array(); | |||
for ($i = 0; $i <= 255; $i++) { | |||
$rndkey[$i] = ord($cryptkey[$i % $key_length]); | |||
} | |||
for ($j = $i = 0; $i < 256; $i++) { | |||
$j = ($j + $box[$i] + $rndkey[$i]) % 256; | |||
$tmp = $box[$i]; | |||
$box[$i] = $box[$j]; | |||
$box[$j] = $tmp; | |||
} | |||
for ($a = $j = $i = 0; $i < $string_length; $i++) { | |||
$a = ($a + 1) % 256; | |||
$j = ($j + $box[$a]) % 256; | |||
$tmp = $box[$a]; | |||
$box[$a] = $box[$j]; | |||
$box[$j] = $tmp; | |||
$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256])); | |||
} | |||
if ($operation == 'DECODE') { | |||
if ((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26) . $keyb), 0, 16)) { | |||
return substr($result, 26); | |||
} else { | |||
return ''; | |||
} | |||
} else { | |||
return $keyc . str_replace('=', '', base64_encode($result)); | |||
} | |||
} | |||
/** | |||
* 获取客户端IP地址 | |||
* @return mixed | |||
*/ | |||
public static function getclientip() | |||
{ | |||
static $realip = NULL; | |||
if ($realip !== NULL) { | |||
return $realip; | |||
} | |||
if (isset($_SERVER)) { | |||
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { //但如果客户端是使用代理服务器来访问,那取到的就是代理服务器的 IP 地址,而不是真正的客户端 IP 地址。要想透过代理服务器取得客户端的真实 IP 地址,就要使用 $_SERVER["HTTP_X_FORWARDED_FOR"] 来读取。 | |||
$arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']); | |||
/* 取X-Forwarded-For中第一个非unknown的有效IP字符串 */ | |||
foreach ($arr AS $ip) { | |||
$ip = trim($ip); | |||
if ($ip != 'unknown') { | |||
$realip = $ip; | |||
break; | |||
} | |||
} | |||
} elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {//HTTP_CLIENT_IP 是代理服务器发送的HTTP头。如果是"超级匿名代理",则返回none值。同样,REMOTE_ADDR也会被替换为这个代理服务器的IP。 | |||
$realip = $_SERVER['HTTP_CLIENT_IP']; | |||
} else { | |||
if (isset($_SERVER['REMOTE_ADDR'])) { //正在浏览当前页面用户的 IP 地址 | |||
$realip = $_SERVER['REMOTE_ADDR']; | |||
} else { | |||
$realip = '0.0.0.0'; | |||
} | |||
} | |||
} else { | |||
//getenv环境变量的值 | |||
if (getenv('HTTP_X_FORWARDED_FOR')) {//但如果客户端是使用代理服务器来访问,那取到的就是代理服务器的 IP 地址,而不是真正的客户端 IP 地址。要想透过代理服务器取得客户端的真实 IP 地址 | |||
$realip = getenv('HTTP_X_FORWARDED_FOR'); | |||
} elseif (getenv('HTTP_CLIENT_IP')) { //获取客户端IP | |||
$realip = getenv('HTTP_CLIENT_IP'); | |||
} else { | |||
$realip = getenv('REMOTE_ADDR'); //正在浏览当前页面用户的 IP 地址 | |||
} | |||
} | |||
preg_match("/[\d\.]{7,15}/", $realip, $onlineip); | |||
$realip = !empty($onlineip[0]) ? $onlineip[0] : '0.0.0.0'; | |||
return $realip; | |||
} | |||
/** | |||
* Des:获取浏览器机器类型 | |||
* Name: get_device_type | |||
* @return string | |||
* @author 倪宗锋 | |||
*/ | |||
public static function get_device_type() | |||
{ | |||
//全部变成小写字母 | |||
$agent = strtolower($_SERVER['HTTP_USER_AGENT']); | |||
$type = 'other'; | |||
//分别进行判断 | |||
if (strpos($agent, 'iphone') || strpos($agent, 'ipad')) { | |||
$type = 'ios'; | |||
} | |||
if (strpos($agent, 'android')) { | |||
$type = 'android'; | |||
} | |||
return $type; | |||
} | |||
} |
@@ -0,0 +1,337 @@ | |||
<?php | |||
namespace addons\nzf; | |||
use addons\unishop\model\Config; | |||
/** | |||
* Class WxPayService | |||
* 微信交易接口调用核心 | |||
* @package Base\Tool | |||
*/ | |||
class WeChatPay | |||
{ | |||
public $unifiedOrderUrl = 'https://api.mch.weixin.qq.com/pay/unifiedorder';//统一下单API | |||
/************************手机浏览器内web支付**************************************/ | |||
/** | |||
* | |||
*/ | |||
public function H5Pay($params) | |||
{ | |||
if (empty($params['notify_url'])) { | |||
$params['notify_url'] = Config::getByName('notify_url')['value']; | |||
} | |||
$data = array( | |||
'name' => $params['name'],//名称 | |||
'order_id' => (string)$params['order_id'] . '_' . rand(1000, 9999),//支付ID | |||
'total_fee' => (string)$params['total_fee'] * 100,//总金 | |||
'notify_url' => $params['notify_url'],//支付回调接口 | |||
'trade_type' => 'MWEB',//用户的OPENID | |||
'scene_info' => [ | |||
'h5_info' => [ | |||
'type' => 'Wap', | |||
'wap_url' => Config::getByName('name')['value'], | |||
'wap_name' => Config::getByName('name')['value'] | |||
] | |||
] | |||
); | |||
$getpay = $this->unifiedOrderForWeChat($data);//统一下单API | |||
if ($getpay['flag'] == false) { | |||
return $getpay; | |||
} | |||
if (empty($getpay['data']['mweb_url'])) { | |||
return Util::returnArrEr('预支付会话异常!'); | |||
} | |||
return Util::returnArrSu('', ['pay_url' => $getpay['data']['mweb_url']]); | |||
} | |||
/************************微信浏览器内web支付**************************************/ | |||
/** | |||
* Function Description:去微信下单并获取返回 | |||
* Function Name: unifiedOrderByOrderId | |||
* @param $params array | |||
* $order_id string 订单表 订单ID | |||
* $name string 产品名称 | |||
* $total_fee int 总金额 单位分 | |||
* $openid string 用户opendid | |||
* @return array | |||
* | |||
* @author nzf | |||
*/ | |||
public function webPay($params) | |||
{ | |||
if (empty($params['notify_url'])) { | |||
$params['notify_url'] = Config::getByName('notify_url')['value'];; | |||
} | |||
$data = array( | |||
'name' => $params['name'],//名称 | |||
'order_id' => (string)$params['order_id'] . '_' . rand(1000, 9999),//支付ID | |||
'total_fee' => (string)$params['total_fee'] * 100,//总金 | |||
'notify_url' => $params['notify_url'],//支付回调接口 | |||
'openid' => $params['openid']//用户的OPENID | |||
); | |||
$getPrepayId = $this->unifiedOrderForWeChat($data);//统一下单API | |||
if ($getPrepayId['flag'] == false) { | |||
return $getPrepayId; | |||
} | |||
//设置成功返回的结果数 | |||
$return = array( | |||
'appId' => Config::getByName('app_id')['value'],//微信�?放平台审核�?�过的应用APPID | |||
'package' => 'prepay_id=' . $getPrepayId['data']['prepay_id'],//微信返回的支付交易会话ID | |||
'nonceStr' => self::getNonceStr(),//随机字符�? | |||
'signType' => 'MD5', | |||
'timeStamp' => strval(time()),//当前时间�? | |||
); | |||
$return['paySign'] = self::getSign($return); | |||
return Util::returnArrSu('', array('payData' => $return, 'price' => $params['total_fee'])); | |||
} | |||
/** | |||
* Function Description:统一下单API | |||
* Function Name: unifiedOrder | |||
* @param $params array | |||
* attach 附加数据,在查询API和支付知中原样返回,该字段主要用于商户携带订单的自定义数 | |||
* line_name 线路名称 | |||
* order_id 订单ID | |||
* total_fee 总金 | |||
* notify_url 回调地址 | |||
* | |||
* @return array | |||
* | |||
* @author nzf | |||
*/ | |||
public function unifiedOrderForWeChat($params) | |||
{ | |||
$data = array( | |||
'appid' => Config::getByName('app_id')['value'],//微信开放平台审核过的应用APPID | |||
'attach' => empty($params['attach']) ? '' : $params['attach'], | |||
'body' => $params['name'],//产品名称 | |||
'mch_id' => Config::getByName('mch_id')['value'],//商户微信支付分配的商户号 | |||
'nonce_str' => $this->getNonceStr(),//随机字符 | |||
'notify_url' => $params['notify_url'],//通知地址 | |||
'out_trade_no' => $params['order_id'],//商户订单ID加上当前时间 | |||
'spbill_create_ip' => $_SERVER['REMOTE_ADDR'],//用户端实际ip | |||
'total_fee' => $params['total_fee'],//订单总金额,单位为分 | |||
'trade_type' => empty($params['trade_type']) ? 'JSAPI' : $params['trade_type'],//交易类型 | |||
); | |||
if (empty($params['openid']) == false) {//存在openid | |||
$data['openid'] = $params['openid']; | |||
} | |||
if (isset($params['scene_info'])) { | |||
$data['scene_info'] = json_encode($params['scene_info']); | |||
} | |||
$data['sign'] = $this->getSign($data);//交易签名 | |||
$curl = new CurlInterface($data, 2);//函数 | |||
$curl->setBaseUrl($this->unifiedOrderUrl); | |||
$result = $curl->execute('', 'POST'); | |||
if (empty($result['prepay_id'])) { | |||
return Util::returnArrEr('预支付交易会话异常!'); | |||
} | |||
return Util::returnArrSu('', array('prepay_id' => $result['prepay_id'], 'mweb_url' => empty($result['mweb_url']) ? '' : $result['mweb_url'])); | |||
} | |||
/************************扫描支付**************************************/ | |||
/** | |||
* Function Description:去微信下单并获取返回 | |||
* Function Name: unifiedOrderByOrderId | |||
* @param $par | |||
* @return array | |||
* | |||
* @author nzf | |||
*/ | |||
public function unifiedOrderByOrderIdForSao($par) | |||
{ | |||
$notify_url = Config::getByName('notify_url')['value']; | |||
$data = array( | |||
'name' => $par['name'],//线路名称 | |||
'order_id' => (string)$par['order_id'] . '_' . rand(100, 999),//订单ID | |||
'total_fee' => $par['total_fee'] * 100,//总金 | |||
'notify_url' => $notify_url | |||
); | |||
$codUrl = $this->unifiedOrderForSao($data);//统一下单API | |||
if ($codUrl['flag'] == false) { | |||
return $codUrl; | |||
} | |||
//设置成功返回的结果数�? | |||
$url = '/fx/?r=weChat/we-chat/q-code&qCode=' . urlencode($codUrl['data']['code_url']) . '&_math=' . rand(100, 999); | |||
return Util::returnArrSu('', array('codUrl' => $url, 'price' => $par['total_fee'])); | |||
} | |||
/** | |||
* Function Description:统一下单API | |||
* Function Name: unifiedOrder | |||
* @param $params array | |||
* attach 附加数据,在查询API和支付知中原样返回,该字段主要用于商户携带订单的自定义数 | |||
* line_name 线路名称 | |||
* order_id 订单ID | |||
* total_fee 总金 | |||
* notify_url 回调地址 | |||
* | |||
* @return array | |||
* | |||
* @author 倪宗�? | |||
*/ | |||
public function unifiedOrderForSao($params) | |||
{ | |||
$data = array( | |||
'appid' => Config::getByName('app_id')['value'],//微信�?放平台审核�?�过的应用APPID | |||
'mch_id' => Config::getByName('mch_id')['value'],//商户�? 微信支付分配的商户号 | |||
'nonce_str' => $this->getNonceStr(),//随机字符�? | |||
'body' => $params['name'],//线路名称 �? 上订单ID | |||
'out_trade_no' => $params['order_id'],//商户订单ID加上当前时间 | |||
'total_fee' => $params['total_fee'],//订单总金额,单位为分 | |||
'spbill_create_ip' => $_SERVER['REMOTE_ADDR'],//用户端实际ip | |||
'notify_url' => $params['notify_url'],//通知地址 | |||
'trade_type' => 'NATIVE',//交易类型 | |||
); | |||
$data['sign'] = $this->getSign($data);//交易签名 | |||
$curl = new CurlInterface($data, 2);//函数�? | |||
$curl->setBaseUrl($this->unifiedOrderUrl); | |||
$result = $curl->execute('', 'POST'); | |||
if (empty($result['prepay_id'])) { | |||
return Util::returnArrEr('预支付交易会话异常!'); | |||
} | |||
return Util::returnArrSu('', array('prepay_id' => $result['prepay_id'], 'code_url' => $result['code_url'])); | |||
} | |||
/***************************************退款****************************************/ | |||
/** | |||
* Des:微信退款接口 | |||
* Name: cancelOrder | |||
* @param $params | |||
* @return array | |||
* @author 倪宗锋 | |||
*/ | |||
public static function cancelOrder($params) | |||
{ | |||
$arr = array( | |||
'appid' => Config::getByName('app_id')['value'], | |||
'mch_id' => Config::getByName('mch_id')['value'], | |||
'nonce_str' => static::getNonceStr(), | |||
'out_trade_no' => (string)$params['order_id'],//订单ID | |||
'out_refund_no' => (string)date('YmdHis') . rand(100, 999),//退款ID | |||
'total_fee' => (string)$params['total_fee'] * 100,//订单总金额 元 | |||
'refund_fee' => (string)$params['refund_fee'] * 100,//退款金额 元 | |||
'op_user_id' => Config::getByName('mch_id')['value'] | |||
); | |||
$arr['sign'] = static::getSign($arr); | |||
$curl = new CurlInterface($arr, 2);//函数类 | |||
$certArr = [ | |||
"SSLCERT_PATH"=>ROOT_PATH.Config::getByName('cert_path')['value'], | |||
"SSLKEY_PATH"=>ROOT_PATH.Config::getByName('key_path')['value'] | |||
]; | |||
$curl->setCert($certArr); | |||
$curl->setBaseUrl('https://api.mch.weixin.qq.com/secapi/pay/refund'); | |||
$result = $curl->execute('', 'POST'); | |||
if ($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS') { | |||
return Util::returnArrSu(); | |||
} | |||
$msg = $result['return_msg']; | |||
if ($msg == 'OK') { | |||
$msg = $result['err_code_des']; | |||
} | |||
return Util::returnArrEr('退款失败!' . $msg); | |||
} | |||
/*************************************通用方法**************************************/ | |||
/** | |||
* Des:检测是否已经支付 | |||
* Name: checkIsPay | |||
* @param $orderId | |||
* @return array | |||
* @author 倪宗锋 | |||
*/ | |||
public static function checkIsPay($orderId) | |||
{ | |||
$arr = array( | |||
'appid' => Config::getByName('app_id')['value'], | |||
'mch_id' => Config::getByName('mch_id')['value'], | |||
'out_trade_no' => (string)$orderId,//订单ID | |||
'nonce_str' => static::getNonceStr(), | |||
); | |||
$arr['sign'] = static::getSign($arr); | |||
$curl = new CurlInterface($arr, 2);//函数类 | |||
$certArr = [ | |||
"SSLCERT_PATH"=>ROOT_PATH.Config::getByName('cert_path')['value'], | |||
"SSLKEY_PATH"=>ROOT_PATH.Config::getByName('key_path')['value'] | |||
]; | |||
$curl->setCert($certArr); | |||
$curl->setBaseUrl('https://api.mch.weixin.qq.com/pay/orderquery'); | |||
$result = $curl->execute('', 'POST'); | |||
if ($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS') { | |||
return Util::returnArrSu('', $result); | |||
} | |||
$msg = $result['return_msg']; | |||
if ($msg == 'OK') { | |||
$msg = $result['err_code_des']; | |||
} | |||
return Util::returnArrEr('退款失败!' . $msg); | |||
} | |||
/** | |||
* Function Description:获取签名 | |||
* Function Name: getSign | |||
* @param $params | |||
* @return string | |||
* | |||
* @author nzf | |||
*/ | |||
public static function getSign($params) | |||
{ | |||
if (isset($params['sign'])) { | |||
unset($params['sign']); | |||
} | |||
//签名步骤按字典序排序参 | |||
ksort($params); | |||
$string = self::ToUrlParams($params); | |||
//签名步骤二:在string后加入KEY | |||
$string = $string . "&key=" . Config::getByName('key')['value']; | |||
//签名步骤三:MD5加密 | |||
$string = md5($string); | |||
//签名步骤四:有字符转为大 | |||
$result = strtoupper($string); | |||
return $result; | |||
} | |||
/** | |||
* Function Description:格式化参�? 格式化成url参数 | |||
* Function Name: ToUrlParams | |||
* @param $params | |||
* | |||
* @return string | |||
* | |||
* @author 倪宗�? | |||
*/ | |||
public static function ToUrlParams($params) | |||
{ | |||
$buff = ""; | |||
foreach ($params as $k => $v) { | |||
if ($k != "sign" && $v != "" && !is_array($v)) { | |||
$buff .= $k . "=" . $v . "&"; | |||
} | |||
} | |||
$buff = trim($buff, "&"); | |||
return $buff; | |||
} | |||
/** | |||
* Function Description:产生的随机字符串 不长 | |||
* Function Name: getNonceStr | |||
* @param int $length | |||
* | |||
* @return string | |||
* | |||
* @author 倪宗�? | |||
*/ | |||
public static function getNonceStr($length = 32) | |||
{ | |||
$chars = "abcdefghijklmnopqrstuvwxyz0123456789"; | |||
$str = ""; | |||
for ($i = 0; $i < $length; $i++) { | |||
$str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1); | |||
} | |||
return $str; | |||
} | |||
} |
@@ -2,6 +2,7 @@ | |||
namespace addons\unishop\behavior; | |||
use addons\epay\library\Service; | |||
use addons\unishop\extend\Ali; | |||
use addons\unishop\extend\Hashids; | |||
use addons\unishop\extend\Wechat; | |||
@@ -256,7 +257,7 @@ $address=[]; | |||
* 行为一:退款 | |||
* @param array $params 订单数据 | |||
*/ | |||
public function orderRefund(&$params) | |||
public function orderRefundOld(&$params) | |||
{ | |||
$order = &$params; | |||
@@ -281,4 +282,25 @@ $address=[]; | |||
// More ... | |||
} | |||
/** | |||
* 订单退款 | |||
* 行为一:退款 | |||
* @param array $params 订单数据 | |||
*/ | |||
public function orderRefund(&$params) | |||
{ | |||
$order = &$params; | |||
// 行为一 | |||
switch ($order['pay_type']) { | |||
case \addons\unishop\model\Order::PAY_WXPAY: | |||
Service::refund($params["out_trade_no"],"wechat",$params["total_price"]); | |||
break; | |||
case \addons\unishop\model\Order::PAY_ALIPAY: | |||
Service::refund($params['out_trade_no'],"alipay",$params['total_price']); | |||
break; | |||
} | |||
// More ... | |||
} | |||
} |
@@ -9,6 +9,8 @@ | |||
namespace addons\unishop\controller; | |||
use addons\nzf\AliPay; | |||
use addons\nzf\PayService; | |||
use addons\unishop\extend\Hashids; | |||
use addons\unishop\model\Area; | |||
use addons\unishop\model\Config; | |||
@@ -600,9 +602,15 @@ class Order extends Base | |||
$order->status = \addons\unishop\model\Order::STATUS_REFUND; | |||
$order->refund_status = \addons\unishop\model\Order::REFUND_STATUS_AGREE; | |||
$result = $order->save(); | |||
Hook::add('order_refund', 'addons\\unishop\\behavior\\Order'); | |||
if ($result !== false){ | |||
Hook::listen('order_refund', $row); | |||
//order_id:订单ID name:订单名称 total_fee:总金额-元 refund_fee退款金额 | |||
$param = [ | |||
"order_id"=>$order['out_trade_no'], | |||
"total_fee"=>$order['total_price'], | |||
"refund_fee"=>$order['total_price'], | |||
"name"=>$order['订单退款'], | |||
]; | |||
PayService::cancel($param,$order["pay_type"]); | |||
$this->success("success",[]); | |||
} | |||
$this->error("订单信息错误"); | |||
@@ -651,4 +659,5 @@ class Order extends Base | |||
} | |||
} |
@@ -10,6 +10,7 @@ | |||
namespace addons\unishop\controller; | |||
use addons\epay\library\Service; | |||
use addons\nzf\AliPay; | |||
use addons\unishop\extend\Ali; | |||
use addons\unishop\extend\Hashids; | |||
use addons\unishop\extend\Wechat; | |||
@@ -240,4 +241,15 @@ class Pay extends Base | |||
} | |||
// public function notify(){ | |||
// $order = [ | |||
// "order_id"=>"202009275f7076e5c6f2f23", | |||
// "total_fee"=>11, | |||
// "memo"=>'取消订单', | |||
// "refund_fee"=>11, | |||
// | |||
// ];//order_id:订单ID name:订单名称 total_fee:总金额-元 refund_fee退款金额 | |||
// AliPay::cancelOrder($order); | |||
// | |||
// } | |||
} |
@@ -24,7 +24,9 @@ | |||
"phpmailer/phpmailer": "~6.0.6", | |||
"karsonzhang/fastadmin-addons": "~1.1.9", | |||
"overtrue/pinyin": "~3.0", | |||
"phpoffice/phpspreadsheet": "^1.2" | |||
"phpoffice/phpspreadsheet": "^1.2", | |||
"ext-json": "*", | |||
"ext-curl": "*" | |||
}, | |||
"config": { | |||
"preferred-install": "dist" | |||