@@ -2,10 +2,12 @@ | |||||
namespace addons\epay\library; | namespace addons\epay\library; | ||||
use addons\unishop\model\Config; | |||||
use Exception; | use Exception; | ||||
use think\Log; | use think\Log; | ||||
use think\Response; | use think\Response; | ||||
use think\Session; | use think\Session; | ||||
use Yansongda\Pay\Gateways\Alipay\Alipay; | |||||
use Yansongda\Pay\Pay; | 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 string $type 支付类型 | ||||
* @param array $config 配置信息 | * @param array $config 配置信息 | ||||
@@ -53,8 +53,8 @@ abstract class Alipay implements GatewayInterface | |||||
'charset' => 'UTF-8', | 'charset' => 'UTF-8', | ||||
'sign_type' => 'RSA2', | 'sign_type' => 'RSA2', | ||||
'version' => '1.0', | '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'), | 'timestamp' => date('Y-m-d H:i:s'), | ||||
'sign' => '', | 'sign' => '', | ||||
'biz_content' => '', | '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; | namespace addons\unishop\behavior; | ||||
use addons\epay\library\Service; | |||||
use addons\unishop\extend\Ali; | use addons\unishop\extend\Ali; | ||||
use addons\unishop\extend\Hashids; | use addons\unishop\extend\Hashids; | ||||
use addons\unishop\extend\Wechat; | use addons\unishop\extend\Wechat; | ||||
@@ -256,7 +257,7 @@ $address=[]; | |||||
* 行为一:退款 | * 行为一:退款 | ||||
* @param array $params 订单数据 | * @param array $params 订单数据 | ||||
*/ | */ | ||||
public function orderRefund(&$params) | |||||
public function orderRefundOld(&$params) | |||||
{ | { | ||||
$order = &$params; | $order = &$params; | ||||
@@ -281,4 +282,25 @@ $address=[]; | |||||
// More ... | // 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; | namespace addons\unishop\controller; | ||||
use addons\nzf\AliPay; | |||||
use addons\nzf\PayService; | |||||
use addons\unishop\extend\Hashids; | use addons\unishop\extend\Hashids; | ||||
use addons\unishop\model\Area; | use addons\unishop\model\Area; | ||||
use addons\unishop\model\Config; | use addons\unishop\model\Config; | ||||
@@ -600,9 +602,15 @@ class Order extends Base | |||||
$order->status = \addons\unishop\model\Order::STATUS_REFUND; | $order->status = \addons\unishop\model\Order::STATUS_REFUND; | ||||
$order->refund_status = \addons\unishop\model\Order::REFUND_STATUS_AGREE; | $order->refund_status = \addons\unishop\model\Order::REFUND_STATUS_AGREE; | ||||
$result = $order->save(); | $result = $order->save(); | ||||
Hook::add('order_refund', 'addons\\unishop\\behavior\\Order'); | |||||
if ($result !== false){ | 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->success("success",[]); | ||||
} | } | ||||
$this->error("订单信息错误"); | $this->error("订单信息错误"); | ||||
@@ -651,4 +659,5 @@ class Order extends Base | |||||
} | } | ||||
} | } |
@@ -10,6 +10,7 @@ | |||||
namespace addons\unishop\controller; | namespace addons\unishop\controller; | ||||
use addons\epay\library\Service; | use addons\epay\library\Service; | ||||
use addons\nzf\AliPay; | |||||
use addons\unishop\extend\Ali; | use addons\unishop\extend\Ali; | ||||
use addons\unishop\extend\Hashids; | use addons\unishop\extend\Hashids; | ||||
use addons\unishop\extend\Wechat; | 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", | "phpmailer/phpmailer": "~6.0.6", | ||||
"karsonzhang/fastadmin-addons": "~1.1.9", | "karsonzhang/fastadmin-addons": "~1.1.9", | ||||
"overtrue/pinyin": "~3.0", | "overtrue/pinyin": "~3.0", | ||||
"phpoffice/phpspreadsheet": "^1.2" | |||||
"phpoffice/phpspreadsheet": "^1.2", | |||||
"ext-json": "*", | |||||
"ext-curl": "*" | |||||
}, | }, | ||||
"config": { | "config": { | ||||
"preferred-install": "dist" | "preferred-install": "dist" | ||||