851 行
31 KiB
PHP
可执行文件
851 行
31 KiB
PHP
可执行文件
<?php
|
||
/**
|
||
* Created by PhpStorm.
|
||
* User: Administrator
|
||
* Date: 2019/9/23 0023
|
||
* Time: 11:17
|
||
*/
|
||
|
||
namespace Pay\Library\Cloud;
|
||
|
||
//[1.7.14]
|
||
class Cloud
|
||
{
|
||
// 测试环境Œ
|
||
// static private $gatewayUrl = "http://ysf.bcbip.cn:10240";
|
||
static private $errmsg = "";
|
||
static private $gatewayUrl = "https://partner.95516.com";
|
||
static private $serprovid = ''; //云闪付服务商标识
|
||
static private $acqOrgCode = ''; //收单机构代码证
|
||
static private $merid;//当前交易的商户
|
||
static private $prvkey;//私钥文件路径
|
||
static private $prodkey;//私钥文件解密密码
|
||
static private $backUrl = "";// 交易通知地址
|
||
private $debug = 0;
|
||
protected $outTradeNo = '';
|
||
|
||
public function __construct($param)
|
||
{
|
||
self::$serprovid = $param['serprovid'];
|
||
self::$acqOrgCode = $param['acqcode'];
|
||
self::$prvkey = $param["prvkey"];
|
||
self::$prodkey = $param["prodkey"];
|
||
self::$backUrl = $param["backUrl"];
|
||
if (!empty($param['merid'])) {
|
||
self::$merid = $param['merid'];
|
||
}
|
||
}
|
||
|
||
|
||
/**统一请求参数
|
||
* @param $param
|
||
* @return mixed
|
||
*/
|
||
public function Patmerchant($param)
|
||
{
|
||
|
||
$partner['serProvId'] = self::$serprovid; //云闪付服务商标识
|
||
$partner['acqOrgCode'] = self::$acqOrgCode; //收单机构代码证
|
||
$partner['paper'] = $this->merinfo($param); //进件详细信息json格式字符串
|
||
$partner['rate'] = $this->Rates($param); //手续费扣率 json格式字符串
|
||
$partner['backUrl'] = $param['backUrl']; //审核回调地址(回调服务商地址)
|
||
return $partner;
|
||
}
|
||
|
||
|
||
/**微信参数配置-支付授权目录
|
||
* @return mixed
|
||
*/
|
||
public function jsapiPath($path, $merid)
|
||
{
|
||
$url = self::$gatewayUrl . '/gateway/api/wechatConfig/jsapiPath';
|
||
$partner['merId'] = $merid;
|
||
$partner['serProvId'] = self::$merid;
|
||
$partner['jsapiPath'] = $path;
|
||
$partner['signature'] = $this->getSignInfo($partner); //RSA签名串
|
||
if (!$partner['signature']) {
|
||
return false;
|
||
}
|
||
$re = $this->http_request(json_encode($partner), $url);
|
||
return $this->buildData($re);
|
||
}
|
||
|
||
|
||
/** 直接处理返回值
|
||
* @param $array
|
||
* @return mixed
|
||
*/
|
||
protected function buildData($array)
|
||
{
|
||
$info = json_decode($array, true);
|
||
if ($info["respCode"] == "00") {
|
||
return $info;
|
||
} else {
|
||
self::$errmsg = $info["respMsg"];
|
||
return false;
|
||
}
|
||
}
|
||
|
||
|
||
/**微信参数配置-子商户 appId
|
||
* @return mixed
|
||
*/
|
||
public function subAppid($appid, $merid)
|
||
{
|
||
$url = self::$gatewayUrl . '/gateway/api/wechatConfig/subAppid';
|
||
$partner['merId'] = $merid;
|
||
$partner['serProvId'] = self::$serprovid;
|
||
$partner['subAppid'] = $appid; //子商户appid
|
||
$partner['signature'] = $this->getSignInfo($partner); //RSA签名串
|
||
if (!$partner['signature']) {
|
||
return false;
|
||
}
|
||
$re = $this->http_request(json_encode($partner), $url);
|
||
$info = json_decode($re, true);
|
||
if ($info["respCode"] == "00") {
|
||
return true;
|
||
} else {
|
||
self::$errmsg = $info["respMsg"];
|
||
return false;
|
||
}
|
||
}
|
||
|
||
|
||
/**微信参数配置-推荐关注 appid
|
||
* @return mixed
|
||
*/
|
||
public function subscribeAppid($appid, $scribeappid, $merid)
|
||
{
|
||
$url = self::$gatewayUrl . '/gateway/api/wechatConfig/subscribeAppid';
|
||
$partner['merId'] = $merid;
|
||
$partner['serProvId'] = self::$serprovid;
|
||
$partner['subAppid'] = $appid;
|
||
$partner['subscribeAppid'] = $scribeappid;//子商户推荐关注公众号appid
|
||
$partner['signature'] = $this->getSignInfo($partner); //RSA签名串
|
||
if (!$partner['signature']) {
|
||
return false;
|
||
}
|
||
$re = $this->http_request(json_encode($partner), $url);
|
||
$info = json_decode($re, true);
|
||
if ($info["respCode"] == "00") {
|
||
return true;
|
||
} else {
|
||
$this->errmsg = $info["respMsg"];
|
||
return false;
|
||
}
|
||
}
|
||
|
||
|
||
/**图片上传
|
||
* @return mixed
|
||
*/
|
||
public function imageUpload()
|
||
{
|
||
$param = input('post.');
|
||
$url = self::$gatewayUrl . '/gateway/api/imageUpload';
|
||
$partner['serProvId'] = $param['serProvId'];
|
||
$partner['uri'] = $param['uri'];
|
||
$partner['signature'] = $this->getSignInfo($partner); //RSA签名串
|
||
if (!$partner['signature']) {
|
||
return false;
|
||
}
|
||
$partner['uploadFile'] = $param['file'];
|
||
$re = $this->http_request(json_encode($partner), $url);
|
||
$info = json_decode($re, true);
|
||
return $info;
|
||
}
|
||
|
||
/** 输出错误信息
|
||
* @return string
|
||
*/
|
||
public function getMsg()
|
||
{
|
||
return self::$errmsg;
|
||
}
|
||
|
||
//云闪付统一下单
|
||
/*
|
||
* 除付款码支付、扫码支付场景以外,商户系统先调用该接口在平台生成预支付交易单,返回正
|
||
确的预支付交易会话标识后再按 JSAPI、APP 等不同场景生成交易串调起支付
|
||
订单类型 orderType
|
||
upJs:银联 JS 支付
|
||
wechatJs:微信公众号支付
|
||
wechatH5:微信 H5 支付
|
||
wechatApp:微信 APP 支付
|
||
wechatMiniProgram:微信小程序支付
|
||
alipayJs:支付宝服务窗支付
|
||
alipayH5:支付宝 H5 支付
|
||
alipayApp:支付宝 APP 支付
|
||
* */
|
||
public function unifiedorder($param)
|
||
{
|
||
$url = self::$gatewayUrl . '/gateway/api/pay/unifiedorder';
|
||
$pays = array(
|
||
'serProvId' => self::$serprovid,
|
||
'merId' => self::$merid,
|
||
'orderType' => $param['orderType'],
|
||
'orderNo' => $param['order_no'],
|
||
'txnAmt' => strval($param['pay_price']),
|
||
'orderInfo' => $param['body'] ? $param['body'] : '商品',
|
||
'backUrl' => $this->getBackUrl(),
|
||
'customerIp' => $this->get_real_ip(),
|
||
'userId' => $param['open_id'],
|
||
'subAppId' => $param['appid']
|
||
);
|
||
|
||
$pays['signature'] = $this->getSignInfo($pays); //RSA签名串
|
||
if (!$pays['signature']) {
|
||
return false;
|
||
}
|
||
$re = $this->http_request(json_encode($pays), $url);
|
||
$this->doLogs(array(json_encode($pays), $pays, json_decode($re, true)));
|
||
$info = json_decode($re, true);
|
||
if ($info['respCode'] == 00) {
|
||
$jsons = json_decode($info['payData'], true);
|
||
// $prepay_id = str_replace('prepay_id=', '', $jsons['package']);
|
||
$jsapi = array(
|
||
'timeStamp' => $jsons['timeStamp'],
|
||
'nonceStr' => $jsons['nonceStr'],
|
||
'prepay_id' => $jsons['package'],
|
||
'package' => $jsons['package'],
|
||
'signType' => $jsons['signType'],
|
||
'paySign' => $jsons['paySign'],
|
||
'status' => 1
|
||
);
|
||
$this->doLogs($jsapi);
|
||
return $jsapi;
|
||
} else {
|
||
self::$errmsg = $info['respMsg'];
|
||
return false;
|
||
}
|
||
|
||
}
|
||
|
||
/**
|
||
* 聚合码支付宝支付
|
||
* 过调用该接口获取二维码并展示出来。
|
||
* {
|
||
* "orderNo":"123456789222",
|
||
* "payerInfo":"{"buyerAccount":"18188188188","cardAttr":"01","buyerId":"18188188188"}",
|
||
* "payTime":"20191023094838",
|
||
* "signature":"VPAKg4gKIeBAflyq7XZ/CyNO7gKlY9vXT8CDIp8gh4MXzrmtth3Ki3M0fav23ehisHYbOKnnRqBk6tC140/mgkqubTveG29HWaxjIglyRZ1mpHs77Kk6/vU9XvkmHYrDE+CpBmeb2VIuiitW0AGPkBjcf643vfE2hAEAoSbEsIIhQ3FXfrsmoZ7wqQ3XVyz5E0M0u3DPHquRASDajsmZ/A1awCDeAkHQv9e+DMhCB165O1w4fE6ik1L1YpikaDp4HwzVH/IzFjvwH9+1ZD/Z3Zw9YzNprj4eekx8/mte0TCiZ0wadElf6w/mPqkpFKfRKK/Md1KDQXFDLsk9hqvR1g==",
|
||
* "settlementAmt":"100",
|
||
* "currencyCode":"100",
|
||
* "payAmt":"100",
|
||
* "txnAmt":"100",
|
||
* "transIndex":"AM00005977_20191023094838"
|
||
* }
|
||
*/
|
||
public function barCode($param)
|
||
{
|
||
$url = self::$gatewayUrl . '/gateway/api/pay/qrpay';
|
||
$pays = array(
|
||
'serProvId' => self::$serprovid,
|
||
'merId' => self::$merid,
|
||
'orderType' => $param['orderType'],
|
||
'orderNo' => $param['trandeno'],
|
||
'orderTime' => time(),
|
||
'txnAmt' => $param['total_amount'],
|
||
'orderInfo' => $param['storetag'],
|
||
'backUrl' => $this->getBackUrl(),
|
||
'termInfo' => $this->term()
|
||
);
|
||
$pays['signature'] = $this->getSignInfo($pays); //RSA签名串
|
||
if (!$pays['signature']) {
|
||
return false;
|
||
}
|
||
$re = $this->http_request(json_encode($pays), $url);
|
||
$info = json_decode($re, true);
|
||
if ($info['respCode'] == '00') {
|
||
$datas['status'] = 1;
|
||
$datas['result']['qr_code'] = $info['qrCode'];
|
||
return $datas;
|
||
} else {
|
||
self::$errmsg = $info['respMsg'];
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 生成微信和支付宝二维码链
|
||
* 过调用该接口获取二维码并展示出来。
|
||
* {
|
||
* "orderNo":"123456789222",
|
||
* "payerInfo":"{"buyerAccount":"18188188188","cardAttr":"01","buyerId":"18188188188"}",
|
||
* "payTime":"20191023094838",
|
||
* "signature":"VPAKg4gKIeBAflyq7XZ/CyNO7gKlY9vXT8CDIp8gh4MXzrmtth3Ki3M0fav23ehisHYbOKnnRqBk6tC140/mgkqubTveG29HWaxjIglyRZ1mpHs77Kk6/vU9XvkmHYrDE+CpBmeb2VIuiitW0AGPkBjcf643vfE2hAEAoSbEsIIhQ3FXfrsmoZ7wqQ3XVyz5E0M0u3DPHquRASDajsmZ/A1awCDeAkHQv9e+DMhCB165O1w4fE6ik1L1YpikaDp4HwzVH/IzFjvwH9+1ZD/Z3Zw9YzNprj4eekx8/mte0TCiZ0wadElf6w/mPqkpFKfRKK/Md1KDQXFDLsk9hqvR1g==",
|
||
* "settlementAmt":"100",
|
||
* "currencyCode":"100",
|
||
* "payAmt":"100",
|
||
* "txnAmt":"100",
|
||
* "transIndex":"AM00005977_20191023094838"
|
||
* }
|
||
*/
|
||
public function barCodeAll($param)
|
||
{
|
||
$url = self::$gatewayUrl . '/gateway/api/pay/qrpay';
|
||
$pays = array(
|
||
'serProvId' => self::$serprovid,
|
||
'merId' => self::$merid,
|
||
'orderType' => $param['orderType'],
|
||
'orderNo' => strval($param['orderNo']),
|
||
'orderTime' => date('YmdHis'),
|
||
'txnAmt' => strval($param['pay_price']),
|
||
'orderInfo' => isset($param['body']) ? $param['body'] : '商品',
|
||
'backUrl' => $this->getBackUrl(),
|
||
'termInfo' => $this->term(),
|
||
//'termId'=>'00000012'
|
||
);
|
||
$pays['signature'] = $this->getSignInfo($pays); //RSA签名串
|
||
if (!$pays['signature']) {
|
||
return false;
|
||
}
|
||
$re = $this->http_request(json_encode($pays), $url);
|
||
$info = json_decode($re, true);
|
||
if ($info['respCode'] == '00') {
|
||
return $info['qrCode'];
|
||
} else {
|
||
$pays['requestJson'] = json_encode($pays);
|
||
$pays['url'] = $url;
|
||
$pays['info'] = $info;
|
||
$this->doLogs($pays, __LINE__);
|
||
self::$errmsg = "二维码生成失败,原因:" . $info['respMsg'];
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 付款码支付
|
||
* 订单类型 alipay-支付宝 wechat-微信支付 unionpay-银联二维码
|
||
* 收银员使用扫码设备读取用户 APP 展示的二维码后,通过后台系统调用该接口发起支付。 当合作伙伴平台返回支付中或交易状态不明时,
|
||
* 服务商需要调用交易查询接口查询订单实际支 付状态。建议间隔 5 秒调一次查询,调用 6 次后还未成功作支付超时处理。
|
||
*/
|
||
public function slotCard($order_no, $code, $total_fee, $body, $type)
|
||
{
|
||
$url = self::$gatewayUrl . '/gateway/api/pay/micropay';
|
||
$pays = array(
|
||
'serProvId' => self::$serprovid,
|
||
'merId' => self::$merid,
|
||
'authCode' => $code,
|
||
'orderType' => $type,
|
||
'orderNo' => $order_no,
|
||
'orderTime' => date('YmdHis', time()),
|
||
'txnAmt' => strval($total_fee),// 均为分
|
||
'orderInfo' => $body ? $body : '消费',
|
||
'termInfo' => $this->term(),
|
||
);
|
||
$pays['signature'] = $this->getSignInfo($pays); //RSA签名串
|
||
if (!$pays['signature']) {
|
||
return false;
|
||
}
|
||
$re = $this->http_request(json_encode($pays), $url);
|
||
$info = json_decode($re, true);
|
||
$this->doLogs(array('name' => '刷卡支付', 'data' => $pays), __LINE__);
|
||
if ($info['respCode'] == '02') {
|
||
//用户使用密码中
|
||
return $this->searchAndUpdateOrder($pays['orderNo'], $pays['orderType']);
|
||
} else if ($info['respCode'] == "00") {
|
||
//用户支付成功
|
||
return true;
|
||
} else {
|
||
self::$errmsg = "支付失败,原因:" . $info["respMsg"];
|
||
return false;
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* 付款码支付2020-10-17
|
||
* 订单类型 alipay-支付宝 wechat-微信支付 unionpay-银联二维码
|
||
* 收银员使用扫码设备读取用户 APP 展示的二维码后,通过后台系统调用该接口发起支付。 当合作伙伴平台返回支付中或交易状态不明时,
|
||
* 服务商需要调用交易查询接口查询订单实际支 付状态。建议间隔 5 秒调一次查询,调用 6 次后还未成功作支付超时处理。
|
||
*/
|
||
public function slotCard_v1($order_no, $code, $total_fee, $body, $type)
|
||
{
|
||
$url = self::$gatewayUrl . '/gateway/api/pay/micropay';
|
||
$pays = array(
|
||
'serProvId' => self::$serprovid,
|
||
'merId' => self::$merid,
|
||
'authCode' => $code,
|
||
'orderType' => $type,
|
||
'orderNo' => $order_no,
|
||
'orderTime' => date('YmdHis', time()),
|
||
'txnAmt' => strval($total_fee),// 均为分
|
||
'orderInfo' => $body ? $body : '消费',
|
||
'termInfo' => $this->term(),
|
||
);
|
||
$pays['signature'] = $this->getSignInfo($pays); //RSA签名串
|
||
if (!$pays['signature']) {
|
||
return false;
|
||
}
|
||
$re = $this->http_request(json_encode($pays), $url);
|
||
$info = json_decode($re, true);
|
||
$this->doLogs(array('name' => '刷卡支付', 'data' => $pays), __LINE__);
|
||
if ($info['respCode'] == '02') {
|
||
//用户使用密码中
|
||
return true;
|
||
} else if ($info['respCode'] == "00") {
|
||
//用户支付成功
|
||
return true;
|
||
} else {
|
||
self::$errmsg = "支付失败,原因:" . $info["respMsg"];
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/** 搜索订单接口
|
||
* @param $orderid
|
||
*/
|
||
private function searchAndUpdateOrder($orderno, $orderType)
|
||
{
|
||
$res = $this->queryOrder($orderno, $orderType);
|
||
|
||
if ($res) {
|
||
if ($res['origRespCode'] == '05' || $res['origRespCode'] == '02') {
|
||
$time = get_runtime();
|
||
if ($time < 25) {
|
||
sleep(2);
|
||
return $this->searchAndUpdateOrder($orderno, $orderType);
|
||
} else {
|
||
$this->cancelOrder($orderno, $orderType);
|
||
//超时,撤销订单
|
||
self::$errmsg = "订单超时,已取消订单";
|
||
return false;
|
||
}
|
||
} else if ($res['respCode'] == '00') {
|
||
return true;
|
||
}
|
||
} else {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* 撤销订单
|
||
* 当支付交易返回失败或系统超时,调用该接口撤销交易。如果此订单用户支付失败,会将此订 单关闭;如果用户支付成功,支付系统会将此订单资金退还给用户。
|
||
* 注意:
|
||
* 1、 正常支付的订单如需实现相同功能请调用退款接口。提交支付交易后调用【查询订单】,没 有明确的支付结果再调用【撤销订单】。
|
||
* 2、 调用支付接口后请勿立即调用撤销订单接口,建议支付后至少 15s 后再调用撤销订单接口。
|
||
* 3、 该接口只适用于付款码支付场景。
|
||
*/
|
||
public function cancelOrder($orderno, $orderType)
|
||
{
|
||
$url = self::$gatewayUrl . '/gateway/api/pay/cancelOrder';
|
||
$pays = array(
|
||
'serProvId' => self::$serprovid,
|
||
'merId' => self::$merid,
|
||
'origOrderNo' => $orderno,
|
||
'orderNo' => strval(time()),
|
||
'orderType' => $orderType
|
||
);
|
||
$pays['signature'] = $this->getSignInfo($pays); //RSA签名串
|
||
if (!$pays['signature']) {
|
||
return false;
|
||
}
|
||
$re = $this->http_request(json_encode($pays), $url);
|
||
|
||
$info = json_decode($re, true);
|
||
return $info;
|
||
}
|
||
|
||
/**
|
||
* 关闭订单
|
||
*/
|
||
public function closeOrder()
|
||
{
|
||
$param = input('post.');
|
||
$url = self::$gatewayUrl . '/gateway/api/pay/closeOrder';
|
||
$pays = array(
|
||
'serProvId' => self::$serprovid,
|
||
'merId' => self::$merid,
|
||
'orderNo' => $param['orderNo'],
|
||
'orderType' => $param['orderType']
|
||
);
|
||
$pays['signature'] = $this->getSignInfo($pays); //RSA签名串
|
||
if (!$pays['signature']) {
|
||
return false;
|
||
}
|
||
$re = $this->http_request(json_encode($pays), $url);
|
||
|
||
$info = json_decode($re, true);
|
||
pre($re);
|
||
}
|
||
|
||
/**
|
||
* 查询订单
|
||
* 根据订单号或者交易索引查询具体订单信息。
|
||
* 调用订单查询接口建议:
|
||
* 查询 6 次每隔 5 秒查 询 一次(具体的查询次数和时间也可自定义,建议查询时间不低于 30 秒)。
|
||
* 6 次查询完成,接口 仍 未返回成功标识则调用撤销接口。
|
||
*
|
||
* 订单类型 alipay-支付宝 wechat-微信支付 unionpay-银联二维码
|
||
* 当应答码 respCode 为 00 时返 回,
|
||
* 代表被查询交易的状态
|
||
* 00- 支付成功
|
||
* 01- 转入退款
|
||
* 02- 未支付
|
||
* 03- 已关闭
|
||
* 04- 已撤销(付款码支付)
|
||
* 05- 用户支付中
|
||
* 06- 支付失败
|
||
*/
|
||
public function queryOrder($orderno, $ordertype)
|
||
{
|
||
$url = self::$gatewayUrl . '/gateway/api/pay/queryOrder';
|
||
$pays = array(
|
||
'serProvId' => self::$serprovid,
|
||
'merId' => self::$merid,
|
||
'orderNo' => $orderno,
|
||
'orderType' => $ordertype
|
||
);
|
||
$pays['signature'] = $this->getSignInfo($pays); //RSA签名串
|
||
if (!$pays['signature']) {
|
||
return false;
|
||
}
|
||
$re = $this->http_request(json_encode($pays), $url);
|
||
$info = json_decode($re, true);
|
||
$this->doLogs(array('name' => '交易查询', 're' => $info, 'pays' => $pays, 'arg' => array($orderno), $url), __LINE__);
|
||
if (($info['respCode'] == 00) && ($info['origRespCode'] == 00)) {
|
||
//兼容微信参数
|
||
$info["return_code"] = 'SUCCESS';
|
||
$info["result_code"] = 'SUCCESS';
|
||
$info["trade_state"] = 'SUCCESS';
|
||
$info["time_end"] = $info["payTime"];
|
||
$info["transaction_id"] = $info["transIndex"];
|
||
//兼容支付宝参数
|
||
$info["trade_status"] = "TRADE_SUCCESS";
|
||
$info["trade_no"] = $info["transIndex"];
|
||
$info['payerInfo'] = $info['payerInfo'];
|
||
return $info;
|
||
} elseif (($info['respCode'] == 00) && ($info['origRespCode'] == 05)) {
|
||
return $info;
|
||
} elseif (($info['respCode'] == 00) && ($info['origRespCode'] == 02)) {
|
||
return $info;
|
||
} elseif (($info['respCode'] == 00) && ($info['origRespCode'] == 04)) {
|
||
self::$errmsg = "已撤销";
|
||
return false;
|
||
} elseif (($info['respCode'] == 00) && ($info['origRespCode'] == 03)) {
|
||
self::$errmsg = "已关闭";
|
||
return false;
|
||
} elseif (($info['respCode'] == 00) && ($info['origRespCode'] == 06)) {
|
||
self::$errmsg = "用户取消支付";
|
||
return false;
|
||
} else {
|
||
if (isset($info["origRespMsg"])) self::$errmsg = $info["origRespMsg"];
|
||
if (isset($info["respMsg"])) self::$errmsg = $info["respMsg"];
|
||
self::$errmsg = self::$errmsg ? self::$errmsg : "未知错误信息";
|
||
return false;
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* 查询订单
|
||
* 根据订单号或者交易索引查询具体订单信息。
|
||
* 调用订单查询接口建议:
|
||
* 查询 6 次每隔 5 秒查 询 一次(具体的查询次数和时间也可自定义,建议查询时间不低于 30 秒)。
|
||
* 6 次查询完成,接口 仍 未返回成功标识则调用撤销接口。
|
||
*
|
||
* 订单类型 alipay-支付宝 wechat-微信支付 unionpay-银联二维码
|
||
* 当应答码 respCode 为 00 时返 回,
|
||
* 代表被查询交易的状态
|
||
* 00- 支付成功
|
||
* 01- 转入退款
|
||
* 02- 未支付
|
||
* 03- 已关闭
|
||
* 04- 已撤销(付款码支付)
|
||
* 05- 用户支付中
|
||
* 06- 支付失败
|
||
*/
|
||
public function queryOrder_v1($orderno, $ordertype)
|
||
{
|
||
$url = self::$gatewayUrl . '/gateway/api/pay/queryOrder';
|
||
$pays = array(
|
||
'serProvId' => self::$serprovid,
|
||
'merId' => self::$merid,
|
||
'orderNo' => $orderno,
|
||
'orderType' => $ordertype
|
||
);
|
||
$pays['signature'] = $this->getSignInfo($pays); //RSA签名串
|
||
if (!$pays['signature']) {
|
||
return false;
|
||
}
|
||
$re = $this->http_request(json_encode($pays), $url);
|
||
$info = json_decode($re, true);
|
||
$this->doLogs(array('name' => '交易查询', 're' => $info, 'pays' => $pays, 'arg' => array($orderno), $url), __LINE__);
|
||
return $info;
|
||
}
|
||
|
||
|
||
/**
|
||
* 申请退款
|
||
* 服务商针对某一个已经成功支付的订单发起退款。
|
||
* 同一笔单的部分退款需要设置相同的原始交 易订单号(origOrderNo)和不同的订单号(orderNo)。
|
||
* 一笔退款失败后重新提交,要采 用原 来的 orderNo。 LS201911081458242000537
|
||
* 总退款金额不能超过用户实际支付金额。
|
||
*/
|
||
/**
|
||
* @param $order_no 【订单号】
|
||
* @param $money 【原交易的总金额】
|
||
* @param $type 【退款类型】 alipay-支付宝 wechat-微信支付 unionpay-银联二维码
|
||
* @param int $refund_fee 【退款金额】
|
||
* @param int $isXcx 【微信类型】 1, 普通微信(阿里,银联) 2,小程序微信
|
||
* @param str $orderNo 【本次退货交易的订单号】
|
||
* @return bool
|
||
*/
|
||
public function Refund($order_no, $money, $type, $refund_fee = 0, $orderNo = '')
|
||
{
|
||
$url = self::$gatewayUrl . '/gateway/api/pay/refund';
|
||
$origOrderNo = $order_no;
|
||
$txnAmt = $refund_fee ? $refund_fee : $money; // 是否传【退款金额】如果没传使用 【原交易的总金额】
|
||
$orderNo = $orderNo ? $orderNo : ($origOrderNo . $money);// 是否传【本次退货交易的订单号】如果没传使用 原单号拼接
|
||
$pays = array(
|
||
'serProvId' => self::$serprovid,
|
||
'merId' => self::$merid,
|
||
'orderNo' => $orderNo, //本次退货交易的订单号
|
||
'origOrderNo' => $origOrderNo, //原交易的订单号
|
||
'orderType' => $type, //订单类型
|
||
'origTxnAmt' => strval($money), //原交易的总金额
|
||
'txnAmt' => strval($txnAmt) // 退款金额
|
||
);
|
||
$pays['signature'] = $this->getSignInfo($pays); //RSA签名串
|
||
if (!$pays['signature']) {
|
||
return false;
|
||
}
|
||
$re = $this->http_request(json_encode($pays), $url);
|
||
$info = json_decode($re, true);
|
||
$this->doLogs(array('name' => '交易退款', 're' => $info, 'pays' => $pays, 'arg' => array($order_no), $url), __LINE__);
|
||
if ($info['respCode'] == '00') {
|
||
return true;
|
||
} else {
|
||
self::$errmsg = $info['respMsg'];
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 退款查询
|
||
* 当应答码 respCode 为 00 时返 回,代表退货交易的状态
|
||
* 00- 退款成功
|
||
* 01- 退款失败
|
||
* 02- 退款处理中
|
||
*/
|
||
public function refundQuery($orderNo)
|
||
{
|
||
$url = self::$gatewayUrl . '/gateway/api/pay/refundQuery';
|
||
$pays = array(
|
||
'serProvId' => self::$serprovid,
|
||
'merId' => self::$merid,
|
||
'orderNo' => $orderNo, //本次退货交易的订单号 应答码为 00 时返回。同退款交 易的订单号
|
||
);
|
||
$pays['signature'] = $this->getSignInfo($pays); //RSA签名串
|
||
if (!$pays['signature']) {
|
||
return false;
|
||
}
|
||
$re = $this->http_request(json_encode($pays), $url);
|
||
$info = json_decode($re, true);
|
||
$this->doLogs(array('name' => '退款查询', 're' => $info, 'pays' => $pays), __LINE__);
|
||
if ($info['respCode'] == '00') {
|
||
return $info;
|
||
} else if ($info['respCode'] == '02') {
|
||
return $info;
|
||
// $time = get_runtime();
|
||
// if ($time < 25) {
|
||
// sleep(3);
|
||
// return $this->refundQuery($param);
|
||
// } else {
|
||
// //超时,撤销订单
|
||
// self::$errmsg = "退款已提交,多次查询仍表示退款处理中!";
|
||
// return false;
|
||
// }
|
||
} else {
|
||
self::$errmsg = $info['respMsg'];
|
||
return false;
|
||
}
|
||
}
|
||
|
||
private function term()
|
||
{
|
||
$terminfo = array(
|
||
'longitude' => '121.483527',
|
||
'latitude' => '31.221345',
|
||
'ip' => '123.12.12.123'
|
||
);
|
||
return json_encode($terminfo);
|
||
}
|
||
|
||
/** 传入数组新增参数
|
||
* @param $postdata
|
||
* @param $arr
|
||
*/
|
||
private function addMerInfos($merinfo, $arr, $postdata)
|
||
{
|
||
foreach ($arr as $key => $val) {
|
||
$index = !is_int($key) ? $key : $val;
|
||
$postdata[$index] = $merinfo[$val];
|
||
};
|
||
return $postdata;
|
||
}
|
||
|
||
/**
|
||
* 校验签名
|
||
* @param string $pubKey 公钥
|
||
* @param string $sign 签名
|
||
* @param string $toSign 待签名字符串
|
||
* @param string $signature_alg 签名方式 比如 sha1WithRSAEncryption 或者sha512
|
||
* @return bool
|
||
*/
|
||
public function checkSign($pubKey, $sign, $toSign, $signature_alg = OPENSSL_ALGO_SHA1)
|
||
{
|
||
$publicKeyId = openssl_pkey_get_public($pubKey);
|
||
$result = openssl_verify($toSign, base64_decode($sign), $publicKeyId, $signature_alg);
|
||
openssl_free_key($publicKeyId);
|
||
return $result === 1 ? true : false;
|
||
}
|
||
|
||
/** 接口数字签名方法 private
|
||
* @param $data
|
||
* @return mixed
|
||
*/
|
||
public function getSignInfo($data)
|
||
{
|
||
ksort($data);
|
||
$str = '';
|
||
foreach ($data as $k => $v) {
|
||
if ($v === '') continue;
|
||
if ($str !== '') $str .= '&';
|
||
$str .= "{$k}={$v}";
|
||
}
|
||
$pfx = file_get_contents('.' . self::$prvkey);
|
||
$cert_info = '';
|
||
$privekey = openssl_pkcs12_read($pfx, $cert_info, self::$prodkey); //返回 布尔值
|
||
$re = hash('sha256', $str);
|
||
$signs = $this->getSign($re, $cert_info['pkey']);
|
||
return $signs;
|
||
}
|
||
|
||
//RSA私钥签名
|
||
public function getSign($signString, $priKey)
|
||
{
|
||
$res = openssl_get_privatekey($priKey);
|
||
if (!$res) {
|
||
self::$errmsg = '您使用的私钥格式错误,请检查RSA私钥配置';
|
||
return false;
|
||
}
|
||
openssl_sign($signString, $signature, $res, OPENSSL_ALGO_SHA256);
|
||
openssl_free_key($res);
|
||
$bases = base64_encode($signature);
|
||
return $bases;
|
||
}
|
||
|
||
public function getNotifyCheck($orderno, $ordertype = 'wechat')
|
||
{
|
||
$info = $this->queryOrder($orderno, $ordertype);
|
||
if (($info['respCode'] == 00) && ($info['origRespCode'] == 00)) {
|
||
//支付成功
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* @param $url 接口请求方法
|
||
* @param null $postFields
|
||
* @return mixed
|
||
*/
|
||
public function http_request($data, $url)
|
||
{
|
||
$ch = curl_init(); //用curl发送数据给api
|
||
$header = array(
|
||
'content-type:application/json;'
|
||
);
|
||
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
|
||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||
curl_setopt($ch, CURLOPT_URL, $url);
|
||
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
|
||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
|
||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
|
||
$response = curl_exec($ch);
|
||
if ($response === FALSE) {
|
||
return json_encode(array('respCode' => '500', 'respMsg' => curl_error($ch)));
|
||
}
|
||
curl_close($ch);
|
||
return $response;
|
||
}
|
||
|
||
public function doLogs($values, $line = __LINE__)
|
||
{
|
||
if ($this->debug) {
|
||
$data = array(
|
||
'line' => $line,
|
||
'data' => $values
|
||
);
|
||
return $this->write_log($data, __DIR__);
|
||
}
|
||
}
|
||
|
||
public function write_log($values, $dir)
|
||
{
|
||
if (is_array($values))
|
||
$values = print_r($values, true);
|
||
// 日志内容
|
||
$content = '[' . date('Y-m-d H:i:s') . ']' . PHP_EOL . $values . PHP_EOL . PHP_EOL;
|
||
try {
|
||
// 文件路径
|
||
$filePath = $dir . '/logs/';
|
||
// 路径不存在则创建
|
||
!is_dir($filePath) && mkdir($filePath, 0755, true);
|
||
// 写入文件
|
||
return file_put_contents($filePath . date('Ymd') . '.log', $content, FILE_APPEND);
|
||
} catch (\Exception $e) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
private function tradeNoToOutTradeNo($tradeNo)
|
||
{
|
||
$this->outTradeNo = $tradeNo;
|
||
return $tradeNo;
|
||
}
|
||
|
||
private function getBackUrl()
|
||
{
|
||
$http_type = 'http://';
|
||
if ((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on')) {
|
||
$http_type = 'https://';
|
||
} else if ((isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')) {
|
||
$http_type = 'https://';
|
||
}
|
||
$http = $http_type . $_SERVER['HTTP_HOST'];
|
||
return $http . self::$backUrl;
|
||
}
|
||
|
||
public function get_real_ip($type = 0)
|
||
{
|
||
$type = $type ? 1 : 0;
|
||
static $ip = NULL;
|
||
if ($ip !== NULL) return $ip[$type];
|
||
if ($_SERVER['HTTP_X_REAL_IP']) {//nginx 代理模式下,获取客户端真实IP
|
||
$ip = $_SERVER['HTTP_X_REAL_IP'];
|
||
} elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {//客户端的ip
|
||
$ip = $_SERVER['HTTP_CLIENT_IP'];
|
||
} elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {//浏览当前页面的用户计算机的网关
|
||
$arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
|
||
$pos = array_search('unknown', $arr);
|
||
if (false !== $pos) unset($arr[$pos]);
|
||
$ip = trim($arr[0]);
|
||
} elseif (isset($_SERVER['REMOTE_ADDR'])) {
|
||
$ip = $_SERVER['REMOTE_ADDR'];//浏览当前页面的用户计算机的ip地址
|
||
} else {
|
||
$ip = $_SERVER['REMOTE_ADDR'];
|
||
}
|
||
// IP地址合法验证
|
||
$long = sprintf("%u", ip2long($ip));
|
||
$ip = $long ? array($ip, $long) : array('0.0.0.0', 0);
|
||
return $ip[$type];
|
||
}
|
||
}
|
||
|