Files
2026-03-15 01:27:05 +08:00

1359 lines
44 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, PATCH, DELETE");
header("Access-Control-Allow-Headers: Content-Type, Authorization, Content-Length, X-Requested-With");
header("Access-Control-Allow-Credentials: true");
header("Content-Type: text/html; charset=utf-8");
use phprs\util\Verify;
use phprs\util\exceptions\Forbidden;
use phprs\util\Logger;
use phprs\util\exceptions\NotFound;
use phprs\ezsql\Sql;
use phprs\util\exceptions\BadRequest;
require_once 'apiBase.php';
require_once "../../payment/wechat/lib/WxPay.Api.php";
require_once "../../payment/wechat/WxPay.JsApiPay.php";
require_once '../../payment/wechat/log.php';
require_once '../../payment/wechat/notify.php';
//初始化日志
$logHandler = new CLogFileHandler("../../logs/" . date('Y-m-d') . '.log');
$log = Log::Init($logHandler, 15);
/**
* 支付管理
* @path("/pay")
*/
class Pay extends apiBase
{
/**
* 检测支付是否成功(错误代码12000-12050)
* @route({"POST","/paystatus"})
* @param({"appid","$._POST.appid"}) 应用appid
* @param({"devkey","$._POST.devkey"}) 开发者key
* @param({"sid","$._POST.sid"}) sid
* @param({"scode","$._POST.scode"}) scode
* @param({"orderid","$._POST.orderid"}) 订单编号
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
*/
public function checkPayStatus($appid = '', $devkey = '', $sid = '', $scode = '', $orderid = '')
{
// 验证公共参数是否合法
parent::init($appid, $devkey, $sid, $scode);
$verify_result = parent::verify();
if (!is_error_api($verify_result))
{
$result = array();
if (empty($orderid))
{
$result["error"] = "1";
$result["error_code"] = 12001;
$result["msg"] = "请指定订单编号";
return json_encode($result, JSON_UNESCAPED_UNICODE);
}
// 根据tid查询指定支付纪录的状态
$payLog = Sql::select('syweb_core_paylog.*')
->from('syweb_core_paylog')
->where('syweb_core_paylog.tid=? and syweb_core_paylog.app_key=? and syweb_core_paylog.business_id=?', $orderid, $this->appInfo['id'], $this->userInfo["business_id"])
->get($this->db, null);
if (!empty($payLog) && count($payLog) > 0)
{
$payLog = $payLog[0];
}
if (!empty($payLog) && count($payLog) > 0)
{
$result["error"] = "0";
$payLog['tag'] = iunserializer($payLog['tag']);
$result["data"] = $payLog;
return json_encode($result, JSON_UNESCAPED_UNICODE);
}
}
else
{
return json_encode($verify_result, JSON_UNESCAPED_UNICODE);
}
}
/**
* 检测支付是否成功(错误代码12000-12050)
* @route({"GET","/paystatus"})
* @param({"appid","$._GET.appid"}) 应用appid
* @param({"devkey","$._GET.devkey"}) 开发者key
* @param({"sid","$._GET.sid"}) sid
* @param({"scode","$._GET.scode"}) scode
* @param({"orderid","$._GET.orderid"}) 订单编号
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
*/
public function checkPayStatus_get($appid = '', $devkey = '', $sid = '', $scode = '', $orderid = '')
{
// 验证公共参数是否合法
parent::init($appid, $devkey, $sid, $scode);
$verify_result = parent::verify();
if (!is_error_api($verify_result))
{
$result = array();
if (empty($orderid))
{
$result["error"] = "1";
$result["error_code"] = 12001;
$result["msg"] = "请指定订单编号";
return json_encode($result, JSON_UNESCAPED_UNICODE);
}
// 根据tid查询指定支付纪录的状态
$payLog = Sql::select('syweb_core_paylog.*')
->from('syweb_core_paylog')
->where('syweb_core_paylog.tid=? and syweb_core_paylog.app_key=? and syweb_core_paylog.business_id=?', $orderid, $this->appInfo['id'], $this->userInfo["business_id"])
->get($this->db, null);
if (!empty($payLog) && count($payLog) > 0)
{
$result["error"] = "0";
$result["data"] = $payLog;
return json_encode($result, JSON_UNESCAPED_UNICODE);
}
}
else
{
return json_encode($verify_result, JSON_UNESCAPED_UNICODE);
}
}
/**
* 微信支付
* @route({"POST","/back_wechat"})
* @param({"appid","$._POST.appid"}) 应用appid
* @param({"devkey","$._POST.devkey"}) 开发者key
* @param({"businessid","$._POST.businessid"}) businessid
* @param({"openid","$._POST.openid"}) openid
* @param({"orderid","$._POST.orderid"}) 订单编号
* @param({"fee","$._POST.fee"}) 支付总价
* @param({"return_url","$._POST.return_url"}) 回调地址
* @param({"title","$._POST.title"}) 支付主题
* @param({"state","$._POST.state"}) 随机参数
* @param({"notice_url","$._POST.notice_url"}) 回调地址
* @param({"return_paramer_format","$._POST.return_paramer_format"}) 回复的参数格式
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
*/
public function backWechatPay($appid = '', $devkey = '', $businessid = '', $openid = '', $orderid = '', $fee = 0, $return_url = '', $title = '', $state = '', $notice_url = '', $return_paramer_format = '')
{
// 验证公共参数是否合法
parent::init($appid, $devkey, '', '');
$verify_result = parent::verify_admin($businessid);
if (!is_error_api($verify_result))
{
if (empty($orderid))
{
exit("请指定订单编号!");
}
if (!is_numeric($fee))
{
exit("请正确指定订单价格!");
}
if (empty($return_url))
{
exit("请指定notify");
}
if (empty($title))
{
exit("请指定title");
}
if ($this->userInfo["auth_type"] == AUTHTYPE_WECHAT)
{
$this->startPay($this->appInfo["id"], $this->businessInfo["id"], 'wechat', $orderid, $fee, $return_url, $openid, $title, $state, $notice_url, $return_paramer_format);
}
else
{
exit("请使用微信登录再进行支付!");
}
}
else
{
exit("支付失败,错误消息为:" . $verify_result['msg']);
}
}
/**
* 微信支付
* @route({"POST","/wechat"})
* @param({"appid","$._POST.appid"}) 应用appid
* @param({"devkey","$._POST.devkey"}) 开发者key
* @param({"sid","$._POST.sid"}) sid
* @param({"scode","$._POST.scode"}) scode
* @param({"orderid","$._POST.orderid"}) 订单编号
* @param({"fee","$._POST.fee"}) 支付总价
* @param({"return_url","$._POST.return_url"}) 回调地址
* @param({"title","$._POST.title"}) 支付主题
* @param({"state","$._POST.state"}) 随机参数
* @param({"notice_url","$._POST.notice_url"}) 回调地址
* @param({"return_paramer_format","$._POST.return_paramer_format"}) 回复的参数格式
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
*/
public function wechatPay($appid = '', $devkey = '', $sid = '', $scode = '', $orderid = '', $fee = 0, $return_url = '', $title = '', $state = '', $notice_url = '', $return_paramer_format = '')
{
// 验证公共参数是否合法
parent::init($appid, $devkey, $sid, $scode);
$verify_result = parent::verify();
if (!is_error_api($verify_result))
{
if (empty($orderid))
{
exit("请指定订单编号!");
}
if (!is_numeric($fee))
{
exit("请正确指定订单价格!");
}
if (empty($return_url))
{
exit("请指定notify");
}
if (empty($title))
{
exit("请指定title");
}
if ($this->userInfo["auth_type"] == AUTHTYPE_WECHAT)
{
$fromUser = $this->userInfo["openid"];
$this->startPay($appid,
$this->market_key,
'wechat',
$orderid,
$fee,
$return_url,
$fromUser,
$title,
$state,
$notice_url,
$return_paramer_format);
}
else
{
exit("请使用微信登录再进行支付!");
}
}
else
{
exit("支付失败,错误消息为:" . $verify_result['msg']);
}
}
/**
*
* $app_id支付应用(int)
* $business_id支付商家(int)
* $type支付方式
* $orderid订单ID
* $fee支付价格
* $return_url支付回调地址
* $fromUser支付用户
* $title支付主题
* $state支付携带参数
* $notice_url支付成功回调地址
**/
private function startPay($app_id, $business_id, $type, $orderid, $fee, $return_url, $fromUser, $title, $state, $notice_url = '', $return_paramer_format = '')
{
$log = Sql::select('syweb_core_paylog.*')
->from('syweb_core_paylog')
->where('app_key=? and market_key=? and `tid`=?', $app_id, $business_id, $orderid)
->get($this->db, null);
if (!empty($log) && count($log) > 0)
{
$log = $log[0];
}
if (!empty($log) && !empty($log['plid']) && is_numeric($log['status']) && $log['status'] != '0')
{
exit('订单已经付款');
}
// 重置支付记录
if (!empty($log) && $log['status'] == '0')
{
$log = null;
}
if (empty($log))
{
$tag = array();
$tag['returnURL'] = $return_url; // 支付完成页面跳转地址
$tag['notice_url'] = $notice_url; // 支付回调页面请求地址
$tag["return_paramer_format"] = $return_paramer_format; // 支付回复参数格式
$tag['state'] = $state;
$tag = iserializer($tag);
$record = array();
$record['type'] = $type; // 支付方式
$record['app_key'] = $app_id; // 支付应用(int)
$record['market_key'] = $business_id; // 支付商家(int)
$record['openid'] = $fromUser; // 支付来源用户
$record['tid'] = $orderid; // 订单编号
$record['fee'] = $fee; // 支付价格
$record['tag'] = $tag; // 其他附加内容
$record['title'] = $title; // 支付主题
$record['status'] = '0'; // 支付状态
$record['encrypt_code'] = ''; // 编码
$record['createtime'] = TIMESTAMP; // 支付创建时间戳
$record['uniontid'] = md5(date('YmdHis') . '_' . $app_id . '_' . $business_id . '_' . random(8, 1)); // 支付唯一ID
$pdo = $this->db;
$pdo->beginTransaction();
// 插入一条支付记录
$plid = Sql::insertInto('syweb_core_paylog')->values($record)->exec($pdo)->lastInsertId();
$pdo->commit();
if ($plid)
{
$record['plid'] = $plid; // 支付记录编号
$log = $record;
if ($type == 'wechat')
{ // 微信支付
$ps = array();
$ps["app_id"] = $app_id; // 支付应用(int)
$ps["business_id"] = $business_id;// 支付商家(int)
$ps["orderid"] = $orderid;
$ps["title"] = $title;
$this->goWeChatPay($ps);
}
else
{
exit("暂不支持的支付方式");
}
}
else
{
exit('记录支付记录失败, 请稍后重试.');
}
}
}
private function goWeChatPay($ps = array())
{
global $_W;
// 根据支付记录编号查询支付记录
$log = Sql::select('syweb_core_paylog.*')
->from('syweb_core_paylog')
->where('app_key=? and market_key=? and `tid`=?', $ps["app_id"], $ps["business_id"], $ps["orderid"])
->get($this->db, null);
if (empty($log))
{
exit('不存在的支付订单!');
}
$log = $log[0];
if ($log['status'] != '0')
{
exit('这个订单已经支付成功, 不需要重复支付.');
}
load()->model('payment');
$wechat = array();
$wechat['appid'] = $this->marketInfo["weixin_appid"];// 微信公众号APPID
$wechat['secret'] = $this->marketInfo["weixin_secret_appid"];
$wechat['mchid'] = $this->marketInfo["weixin_mchid"];// 微信公众号商户号
$wechat['signkey'] = $this->marketInfo["weixin_paykey"];// 支付秘钥
$tools = new JsApiPay();
// ②、实例化统一下单对象
$input = new WxPayUnifiedOrder();
$input->SetAppid($wechat['appid']); // 公众号APPID
$input->SetMch_id($wechat['mchid']); // 公众号商户ID
//$input->SetPayKey($wechat['signkey']); // 公众号APPID
//$input->SetSecretId($wechat['secret']); // 公众号商户ID
$input->SetBody($ps['title']); // 本次支付主题
$input->SetAttach($log['app_id'] . '======' . $log['business_id']);// 支付回传的值
$input->SetOut_trade_no($log['uniontid']);
$input->SetTotal_fee($log['fee'] * 100);// 微信支付单位为分
$input->SetTime_start(date("YmdHis"));// 支付发起时间戳
$input->SetTime_expire(date("YmdHis", time() + 600));// 支付有效期
$input->SetGoods_tag("");
$input->SetNotify_url($_W['siteroot'] . 'callback/');
$input->SetTrade_type("JSAPI");
$input->SetOpenid($log['openid']);
try
{
$order = WxPayApi::unifiedOrder($input, 6, $wechat); // 提交统一订单
}
catch (Exception $e)
{
if (isset($order['return_msg']))
echo $order['return_msg'], '<br>';
exit($e->getMessage());
}
// $wOpt = wechat_build($params, $wechat);
$jsApiParameters = $tools->GetJsApiParameters($order, $wechat);
if (is_error($jsApiParameters))
{
if ($jsApiParameters['message'] == 'invalid out_trade_no' || $jsApiParameters['message'] == 'OUT_TRADE_NO_USED')
{
$id = date('YmdH');
pdo_update('syweb_core_paylog', array('plid' => $id), array('plid' => $log['plid']));
pdo_query("ALTER TABLE " . tablename('syweb_core_paylog') . " auto_increment = " . ($id + 1) . ";");
exit('抱歉,发起支付失败,系统已经修复此问题,请重新尝试支付。');
}
exit("抱歉,发起支付失败,具体原因为:“{$jsApiParameters['errno']}:{$jsApiParameters['message']}”。请及时联系站点管理员。");
}
$htmlContent = <<<EOF
<script type="text/javascript">
function jsApiCall() {
WeixinJSBridge.invoke(
'getBrandWCPayRequest',
{$jsApiParameters},
function(res){
if(res.err_msg == 'get_brand_wcpay_request:ok') {
window.location.href="http://api.daoqijuyou77.cn/api/pay/notify?plid={$log['plid']}";
} else {
//alert('启动微信支付失败, 请检查你的支付参数. 详细错误为: ' + res.err_msg);
history.go(-1);
}
}
);
}
if (typeof WeixinJSBridge == "undefined") {
if( document.addEventListener ){
document.addEventListener('WeixinJSBridgeReady', jsApiCall, false);
}else if (document.attachEvent){
document.attachEvent('WeixinJSBridgeReady', jsApiCall);
document.attachEvent('onWeixinJSBridgeReady', jsApiCall);
}
}else{
jsApiCall();
}
</script>
EOF;
echo $htmlContent;
}
/**
* 微信支付
* @route({"POST","/callback"})
* @route({"GET","/callback"})
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
*/
public function payCallBack()
{
Log::DEBUG("begin notify");
$return_url = new PayNotifyCallBack();
$return_url->Handle(false, $this->db);
}
/**
* 支付完成回调到客户端
* @route({"GET","/notify"})
* @param({"plid","$._GET.plid"}) 订单编号
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
*/
public function goNotify($plid)
{
$log = Sql::select('syweb_core_paylog.*')
->from('syweb_core_paylog')
->where('`plid`=?', $plid)
->get($this->db, null);
if (!empty($log))
{
$log = $log[0];
// 判断支付方式(1: 微信支付; 2: 支付宝支付; 3: 威富通聚合支付(微信); 4: 威富通聚合支付(支付宝))
if (strcasecmp($log['type'], PAYTYPE_WECHAT) == 0)
$paytype = PAYCODE_WECHAT;
elseif (strcasecmp($log['type'], PAYTYPE_ALIPAY) == 0)
$paytype = PAYCODE_ALIPAY;
elseif (strcasecmp($log['type'], PAYTYPE_SWIFTPASS_WECHAT) == 0)
$paytype = PAYCODE_SWIFTPASS_WECHAT;
elseif (strcasecmp($log['type'], PAYTYPE_SWIFTPASS_ALIPAY) == 0)
$paytype = PAYCODE_SWIFTPASS_ALIPAY;
else
$paytype = PAYCODE_UNKNOWN;
// 判断支付订单号(内部)
$log['tag'] = iunserializer($log['tag']);
$returnUrl = $log['tag']['return_url']; // 客户端回调地址
$attach = json_decode($log['tag']['attach']); // 客户端传回的参数
$transaction_id = $log['tag']['transaction_id']; // 支付订单号(内部)
$tid = $log['tid']; // 订单编号
$record = array();
$record['status'] = '1';
$record['paytype'] = $paytype;
$record['transid'] = $transaction_id;
//$pdo = $this->db;
//$pdo->beginTransaction();
//Sql::update('syweb_order')->setArgs($record)->where('ordersn = ?',$tid)->exec($pdo);
//$pdo->commit();
$param = '';
foreach ($attach as $k => $v)
{
$param .= "&{$k}={$v}";
}
if (strstr($returnUrl, '?'))
{
$returnUrl .= "&orderSN={$tid}{$param}";
}
else
{
$returnUrl .= "?orderSN={$tid}{$param}";
}
header("location: " . $returnUrl);
}
}
/**
* 退款(错误码13000-13050)
* @route({"POST","/refund"})
* @param({"appid","$._POST.appid"}) 应用appid
* @param({"devkey","$._POST.devkey"}) 开发者key
* @param({"sid","$._POST.sid"}) sid
* @param({"scode","$._POST.scode"}) scode
* @param({"transaction_id","$._POST.transaction_id"}) 微信订单号
* @param({"out_trade_no","$._POST.out_trade_no"}) 商户单号
* @param({"total_fee","$._POST.total_fee"}) 订单总价
* @param({"refund_fee","$._POST.refund_fee"}) 退款价格
* @param({"state","$._POST.state"}) 原样退回参数
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
*/
public function refund($appid = '', $devkey = '', $sid = '', $scode = '', $transaction_id = '', $out_trade_no = '', $total_fee = 0, $refund_fee = 0, $state = "")
{
// 验证公共参数是否合法
parent::init($appid, $devkey, $sid, $scode);
$verify_result = parent::verify();
if (!is_error_api($verify_result))
{
if (!isset($transaction_id) && !isset($out_trade_no))
{
$result["error"] = '1';
$result["error_code"] = 13001;
$result["msg"] = "transaction_id和out_trade_no参数必须至少传入一个。";
return $result;
}
if (empty($transaction_id) && empty($out_trade_no))
{
$result["error"] = '1';
$result["error_code"] = 13002;
$result["msg"] = "transaction_id和out_trade_no参数必须有一个不为空。";
return $result;
}
if (empty($total_fee) || (!is_numeric($total_fee) && !is_float($total_fee)))
{
$result["error"] = '1';
$result["error_code"] = 13003;
$result["msg"] = "total_fee不能为空并且需要为数字。";
return $result;
}
if (empty($refund_fee) || (!is_numeric($refund_fee) && !is_float($refund_fee)))
{
$result["error"] = '1';
$result["error_code"] = 13004;
$result["msg"] = "refund_fee不能为空并且需要为数字。";
return $result;
}
$refererUrl = $_SERVER['HTTP_REFERER'];// 当前调用退款的域名
/*if( empty($refererUrl) ){
$result["error"] = '1';
$result["error_code"] = 13005;
$result["msg"] = "不是安全的域名。";
return $result;
}*/
// 退款安全域名
$refund_safe_domain = iunserializer($this->businessInfo['refund_safe_domain']);
$refund_safe_domain1 = $refund_safe_domain["refund_safe_domain1"];
$refund_safe_domain2 = $refund_safe_domain["refund_safe_domain2"];
$refund_safe_domain3 = $refund_safe_domain["refund_safe_domain3"];
$referer_paths = parse_url($refererUrl);
if (!empty($referer_paths) && count($referer_paths) > 0)
{
$referer_domain = $referer_paths["host"];
if ($refund_safe_domain1 != $referer_domain && $refund_safe_domain2 != $referer_domain && $refund_safe_domain3 != $referer_domain)
{
$result["error"] = '1';
$result["error_code"] = 13006;
$result["msg"] = "不是安全的域名。";
return $result;
}
}
$wechat['appid'] = $this->businessInfo["weixin_appid"];// 微信公众号APPID
$wechat['secret'] = $this->businessInfo["weixin_secret_appid"];
$wechat['mchid'] = $this->businessInfo["mchid"];// 微信公众号商户号
$wechat['signkey'] = $this->businessInfo["signkey"];// 支付秘钥
if (isset($transaction_id) && $transaction_id != "")
{
$input = new WxPayRefund();
$input->SetTransaction_id($transaction_id);
$input->SetTotal_fee($total_fee * 100);
$input->SetRefund_fee($refund_fee * 100);
$input->SetOut_refund_no($this->businessInfo["mchid"] . date("YmdHis") . random(8, 1));
$input->SetOp_user_id($this->businessInfo["mchid"]);
$refund_result = WxPayApi::refund($input, 6, $wechat, $this->db);
if (!empty($refund_result) && count($refund_result) > 0)
{
if ($refund_result["return_code"] == "SUCCESS")
{
$result["error"] = "0";
$result["state"] = $state;
$result["msg"] = "申请退款成功。";
return $result;
}
else
{
$result["error"] = '1';
$result["error_code"] = 13001;
$result["msg"] = $refund_result["err_code_des"];
return $result;
}
}
else
{
$result["error"] = '1';
$result["error_code"] = 13000;
$result["msg"] = "申请退款返回消息为空。";
return $result;
}
}
if (isset($out_trade_no) && $out_trade_no != "")
{
$input = new WxPayRefund();
$input->SetOut_trade_no($out_trade_no);
$input->SetTotal_fee($total_fee * 100);
$input->SetRefund_fee($refund_fee * 100);
$input->SetOut_refund_no($this->businessInfo["mchid"] . date("YmdHis") . random(8, 1));
$input->SetOp_user_id($this->businessInfo["mchid"]);
$refund_result = WxPayApi::refund($input, 6, $wechat, $this->db);
if (!empty($refund_result) && count($refund_result) > 0)
{
if ($refund_result["return_code"] == "SUCCESS")
{
$result["error"] = "0";
$result["state"] = $state;
$result["msg"] = "申请退款成功。";
return $result;
}
else
{
$result["error"] = '1';
$result["error_code"] = 13001;
$result["msg"] = $refund_result["err_code_des"];
return $result;
}
}
else
{
$result["error"] = '1';
$result["error_code"] = 13000;
$result["msg"] = "申请退款返回消息为空。";
return $result;
}
}
}
else
{
return $verify_result;
}
}
/**
* 退款(错误码13000-13050)
* @route({"POST","/back_refund"})
* @param({"appid","$._POST.appid"}) 应用appid
* @param({"devkey","$._POST.devkey"}) 开发者key
* @param({"businessid","$._POST.businessid"}) businessid
* @param({"transaction_id","$._POST.transaction_id"}) 微信订单号
* @param({"out_trade_no","$._POST.out_trade_no"}) 商户单号
* @param({"total_fee","$._POST.total_fee"}) 订单总价
* @param({"refund_fee","$._POST.refund_fee"}) 退款价格
* @param({"state","$._POST.state"}) 原样退回参数
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
*/
public function refund_backGroupd($appid = '', $devkey = '', $businessid = '', $transaction_id = '', $out_trade_no = '', $total_fee = 0, $refund_fee = 0, $state = "")
{
// 验证公共参数是否合法
parent::init($appid, $devkey, '', '');
$verify_result = parent::verify_admin($businessid);
if (!is_error_api($verify_result))
{
if (!isset($transaction_id) && !isset($out_trade_no))
{
$result["error"] = '1';
$result["error_code"] = 13001;
$result["msg"] = "transaction_id和out_trade_no参数必须至少传入一个。";
return $result;
}
if (empty($transaction_id) && empty($out_trade_no))
{
$result["error"] = '1';
$result["error_code"] = 13002;
$result["msg"] = "transaction_id和out_trade_no参数必须有一个不为空。";
return $result;
}
if (empty($total_fee) || (!is_numeric($total_fee) && !is_float($total_fee)))
{
$result["error"] = '1';
$result["error_code"] = 13003;
$result["msg"] = "total_fee不能为空并且需要为数字。";
return $result;
}
if (empty($refund_fee) || (!is_numeric($refund_fee) && !is_float($refund_fee)))
{
$result["error"] = '1';
$result["error_code"] = 13004;
$result["msg"] = "refund_fee不能为空并且需要为数字。";
return $result;
}
$wechat['appid'] = $this->businessInfo["weixin_appid"];// 微信公众号APPID
$wechat['secret'] = $this->businessInfo["weixin_secret_appid"];
$wechat['mchid'] = $this->businessInfo["mchid"];// 微信公众号商户号
$wechat['signkey'] = $this->businessInfo["signkey"];// 支付秘钥
if (isset($transaction_id) && $transaction_id != "")
{
$input = new WxPayRefund();
$input->SetTransaction_id($transaction_id);
$input->SetTotal_fee($total_fee * 100);
$input->SetRefund_fee($refund_fee * 100);
$input->SetOut_refund_no($this->businessInfo["mchid"] . date("YmdHis") . random(8, 1));
$input->SetOp_user_id($this->businessInfo["mchid"]);
$refund_result = WxPayApi::refund($input, 6, $wechat, $this->db);
if (!empty($refund_result) && count($refund_result) > 0)
{
if ($refund_result["return_code"] == "SUCCESS" && $refund_result["result_code"] == "SUCCESS")
{
$result["error"] = "0";
$result["state"] = $state;
$result["msg"] = "申请退款成功。";
return $result;
}
else
{
$result["error"] = '1';
$result["error_code"] = 13001;
$result["msg"] = $refund_result["err_code_des"];
return $result;
}
}
else
{
$result["error"] = '1';
$result["error_code"] = 13000;
$result["msg"] = "申请退款返回消息为空。";
return $result;
}
}
if (isset($out_trade_no) && $out_trade_no != "")
{
$input = new WxPayRefund();
$input->SetOut_trade_no($out_trade_no);
$input->SetTotal_fee($total_fee * 100);
$input->SetRefund_fee($refund_fee * 100);
$input->SetOut_refund_no($this->businessInfo["mchid"] . date("YmdHis") . random(8, 1));
$input->SetOp_user_id($this->businessInfo["mchid"]);
$refund_result = WxPayApi::refund($input, 6, $wechat, $this->db);
if (!empty($refund_result) && count($refund_result) > 0)
{
if ($refund_result["return_code"] == "SUCCESS" && $refund_result["result_code"] == "SUCCESS")
{
$result["error"] = "0";
$result["state"] = $state;
$result["msg"] = "申请退款成功。";
return $result;
}
else
{
$result["error"] = '1';
$result["error_code"] = 13001;
$result["msg"] = $refund_result["err_code_des"];
return $result;
}
}
else
{
$result["error"] = '1';
$result["error_code"] = 13000;
$result["msg"] = "申请退款返回消息为空。";
return $result;
}
}
}
else
{
return $verify_result;
}
}
/**
* 发送普通红包(错误码14000-14050)
* @route({"POST","/sendredpack"})
* @param({"appid","$._POST.appid"}) 应用appid
* @param({"devkey","$._POST.devkey"}) 开发者key
* @param({"sid","$._POST.sid"}) sid
* @param({"scode","$._POST.scode"}) scode
* @param({"out_mch_billno","$._POST.out_mch_billno"}) 商户订单号
* @param({"send_name","$._POST.send_name"}) 红包发送者名称
* @param({"total_amount","$._POST.total_amount"}) 付款金额,单位分
* @param({"total_num","$._POST.total_num"}) 红包发放总人数
* @param({"wishing","$._POST.wishing"}) 红包祝福语
* @param({"act_name","$._POST.act_name"}) 活动名称
* @param({"remark","$._POST.remark"}) 备注信息
* @param({"state","$._POST.state"}) 原样返回参数
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
*/
public function sendredpack($appid = '', $devkey = '', $sid = '', $scode = '', $out_mch_billno = '', $send_name = '', $total_amount = 0, $total_num = 0, $wishing = '', $act_name = '', $remark = '', $state = "")
{
// 验证公共参数是否合法
parent::init($appid, $devkey, $sid, $scode);
$verify_result = parent::verify();
if (!is_error_api($verify_result))
{
if (!isset($out_mch_billno))
{
$result["error"] = '1';
$result["error_code"] = 14001;
$result["msg"] = "out_mch_billno参数必须传入。";
return $result;
}
if (empty($out_mch_billno))
{
$result["error"] = '1';
$result["error_code"] = 14002;
$result["msg"] = "out_mch_billno参数不能为空。";
return $result;
}
if (!isset($send_name))
{
$result["error"] = '1';
$result["error_code"] = 14003;
$result["msg"] = "send_name参数必须传入。";
return $result;
}
if (empty($send_name))
{
$result["error"] = '1';
$result["error_code"] = 14004;
$result["msg"] = "send_name参数不能为空。";
return $result;
}
if (!isset($total_amount))
{
$result["error"] = '1';
$result["error_code"] = 14005;
$result["msg"] = "total_amount参数必须传入。";
return $result;
}
if (empty($total_amount))
{
$result["error"] = '1';
$result["error_code"] = 14006;
$result["msg"] = "total_amount参数不能为空。";
return $result;
}
if (!is_numeric($total_amount) && !is_float($total_amount))
{
$result["error"] = '1';
$result["error_code"] = 14007;
$result["msg"] = "total_amount参数必须为数字。";
return $result;
}
if (!isset($total_num))
{
$result["error"] = '1';
$result["error_code"] = 14008;
$result["msg"] = "total_num参数必须传入。";
return $result;
}
if (empty($total_num))
{
$result["error"] = '1';
$result["error_code"] = 14009;
$result["msg"] = "total_num参数不能为空。";
return $result;
}
if (!is_numeric($total_num) && !is_float($total_num))
{
$result["error"] = '1';
$result["error_code"] = 14010;
$result["msg"] = "total_num参数必须为数字。";
return $result;
}
if (!isset($wishing))
{
$result["error"] = '1';
$result["error_code"] = 14011;
$result["msg"] = "wishing参数必须传入。";
return $result;
}
if (empty($wishing))
{
$result["error"] = '1';
$result["error_code"] = 14012;
$result["msg"] = "wishing参数不能为空。";
return $result;
}
if (!isset($act_name))
{
$result["error"] = '1';
$result["error_code"] = 14013;
$result["msg"] = "act_name参数必须传入。";
return $result;
}
if (empty($act_name))
{
$result["error"] = '1';
$result["error_code"] = 14014;
$result["msg"] = "act_name参数不能为空。";
return $result;
}
if (!isset($remark))
{
$result["error"] = '1';
$result["error_code"] = 14015;
$result["msg"] = "remark参数必须传入。";
return $result;
}
if (empty($remark))
{
$result["error"] = '1';
$result["error_code"] = 14016;
$result["msg"] = "remark参数不能为空。";
return $result;
}
if ($this->userInfo["auth_type"] == AUTHTYPE_WECHAT)
{
/*$refererUrl = $_SERVER['HTTP_REFERER'];// 当前调用发红包的域名
if( !isset($refererUrl) || empty($refererUrl) ){
$result["error"] = '1';
$result["error_code"] = 14017;
$result["msg"] = "不是安全的域名。";
return $result;
}
// 发红包的安全域名
$sendredpack_safe_domain = iunserializer($this->businessInfo['sendredpack_safe_domain']);
$sendredpack_safe_domain1 = $sendredpack_safe_domain["sendredpack_safe_domain1"];
$sendredpack_safe_domain2 = $sendredpack_safe_domain["sendredpack_safe_domain2"];
$sendredpack_safe_domain3 = $sendredpack_safe_domain["sendredpack_safe_domain3"];
$referer_paths = parse_url($refererUrl);
if( !empty($referer_paths) && count($referer_paths)>0 ){
$referer_domain = $referer_paths["host"];
if( $sendredpack_safe_domain1!=$referer_domain && $sendredpack_safe_domain2!=$referer_domain && $sendredpack_safe_domain3!=$referer_domain ) {
$result["error"] = '1';
$result["error_code"] = 14018;
$result["msg"] = "不是安全的域名。";
return $result;
}
}*/
$wechat['appid'] = $this->businessInfo["weixin_appid"];// 微信公众号APPID
$wechat['secret'] = $this->businessInfo["weixin_secret_appid"];
$wechat['mchid'] = $this->businessInfo["mchid"];// 微信公众号商户号
$wechat['signkey'] = $this->businessInfo["signkey"];// 支付秘钥
$mch_billno = $this->businessInfo["mchid"] . date("YmdHis") . random(4, 1);
$record = array();
$record['app_id'] = $this->appInfo["id"];// app_id
$record['business_id'] = $this->businessInfo["id"];// business_id
$record['status'] = '0';// 发送状态(待发放)
$record['re_openid'] = $this->userInfo["openid"];// 发放红包的目标用户
$record['out_mch_billno'] = $out_mch_billno;// 订单编号
$record['mch_billno'] = $mch_billno;// 本平台订单编号
$record['send_name'] = $send_name;// 红包发送者名称
$record['total_amount'] = $total_amount;// 付款金额,单位分
$record['total_num'] = $total_num;// 红包发放总人数
$record['wishing'] = $wishing;// 红包祝福语
$record['client_ip'] = CLIENT_IP;// 调用接口的机器Ip地址
$record['act_name'] = $act_name;// 活动名称
$record['remark'] = $remark;// 备注信息
$record['send_listid'] = "";// 微信订单号
$record['createtime'] = TIMESTAMP;// 订单创建时间戳
$pdo = $this->db;
$pdo->beginTransaction();
// 插入一条支付记录
$send_redpack_id = Sql::insertInto('syweb_sendredpack_order')->values($record)->exec($pdo)->lastInsertId();
$pdo->commit();
if ($send_redpack_id)
{
$input = new WxPaySendredpack();
$input->SetMch_billno($mch_billno); // 商户订单号
$input->SetSend_name($send_name); // 商户名称
$input->SetRe_openid($this->userInfo["openid"]);// 接受红包的用户的openid
$input->SetTotal_amount($total_amount * 100);// 付款金额,单位分
$input->SetTotal_num($total_num);// 红包发放总人数
$input->SetWishing($wishing);// 红包祝福语
$input->SetClient_ip(CLIENT_IP);// 调用接口的机器Ip地址
$input->SetAct_name($act_name);// 活动名称
$input->SetRemark($remark);// 备注信息
$sendredpack_result = WxPayApi::sendredpack($input, 6, $wechat, $this->db);
if (!empty($sendredpack_result) && count($sendredpack_result) > 0)
{
if ($sendredpack_result["return_code"] == "SUCCESS")
{
if ($sendredpack_result["result_code"] == "SUCCESS")
{
$pdo->beginTransaction();
Sql::update('syweb_sendredpack_order')->setArgs(array(
'status' => 1,
'send_listid' => $sendredpack_result["send_listid"],
))->where('id = ?', $send_redpack_id)->exec($pdo);
$pdo->commit();
$result["error"] = "0";
$result["state"] = $state;
$result["msg"] = "申请发送红包成功。";
return $result;
}
else
{
$result["error"] = '1';
$result["error_code"] = 14021;
$result["msg"] = $sendredpack_result["return_msg"];
return $result;
}
}
else
{
$result["error"] = '1';
$result["error_code"] = 14020;
$result["msg"] = $sendredpack_result["return_msg"];
return $result;
}
}
else
{
$result["error"] = '1';
$result["error_code"] = 14019;
$result["msg"] = "申请发送红包返回消息为空。";
return $result;
}
}
}
else
{
exit("请使用微信登录再申请红包!");
}
}
else
{
return $verify_result;
}
}
/**
* 发送普通红包(错误码14000-14050)
* @route({"POST","/back_sendredpack"})
* @param({"appid","$._POST.appid"}) 应用appid
* @param({"devkey","$._POST.devkey"}) 开发者key
* @param({"businessid","$._POST.businessid"}) businessid
* @param({"re_openid","$._POST.re_openid"}) re_openid 发送红包的目标用户
* @param({"out_mch_billno","$._POST.out_mch_billno"}) 商户订单号
* @param({"send_name","$._POST.send_name"}) 红包发送者名称
* @param({"total_amount","$._POST.total_amount"}) 付款金额,单位分
* @param({"total_num","$._POST.total_num"}) 红包发放总人数
* @param({"wishing","$._POST.wishing"}) 红包祝福语
* @param({"act_name","$._POST.act_name"}) 活动名称
* @param({"remark","$._POST.remark"}) 备注信息
* @param({"state","$._POST.state"}) 原样返回参数
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
*/
public function backsendredpack($appid = '', $devkey = '', $businessid = '', $re_openid = "", $out_mch_billno = '', $send_name = '', $total_amount = 0, $total_num = 0, $wishing = '', $act_name = '', $remark = '', $state = "")
{
// 验证公共参数是否合法
parent::init($appid, $devkey, '', '');
$verify_result = parent::verify_admin($businessid);
if (!is_error_api($verify_result))
{
if (!isset($out_mch_billno))
{
$result["error"] = '1';
$result["error_code"] = 14001;
$result["msg"] = "out_mch_billno参数必须传入。";
return $result;
}
if (empty($out_mch_billno))
{
$result["error"] = '1';
$result["error_code"] = 14002;
$result["msg"] = "out_mch_billno参数不能为空。";
return $result;
}
if (!isset($send_name))
{
$result["error"] = '1';
$result["error_code"] = 14003;
$result["msg"] = "send_name参数必须传入。";
return $result;
}
if (empty($send_name))
{
$result["error"] = '1';
$result["error_code"] = 14004;
$result["msg"] = "send_name参数不能为空。";
return $result;
}
if (!isset($total_amount))
{
$result["error"] = '1';
$result["error_code"] = 14005;
$result["msg"] = "total_amount参数必须传入。";
return $result;
}
if (empty($total_amount))
{
$result["error"] = '1';
$result["error_code"] = 14006;
$result["msg"] = "total_amount参数不能为空。";
return $result;
}
if (!is_numeric($total_amount) && !is_float($total_amount))
{
$result["error"] = '1';
$result["error_code"] = 14007;
$result["msg"] = "total_amount参数必须为数字。";
return $result;
}
if (!isset($total_num))
{
$result["error"] = '1';
$result["error_code"] = 14008;
$result["msg"] = "total_num参数必须传入。";
return $result;
}
if (empty($total_num))
{
$result["error"] = '1';
$result["error_code"] = 14009;
$result["msg"] = "total_num参数不能为空。";
return $result;
}
if (!is_numeric($total_num) && !is_float($total_num))
{
$result["error"] = '1';
$result["error_code"] = 14010;
$result["msg"] = "total_num参数必须为数字。";
return $result;
}
if (!isset($wishing))
{
$result["error"] = '1';
$result["error_code"] = 14011;
$result["msg"] = "wishing参数必须传入。";
return $result;
}
if (empty($wishing))
{
$result["error"] = '1';
$result["error_code"] = 14012;
$result["msg"] = "wishing参数不能为空。";
return $result;
}
if (!isset($act_name))
{
$result["error"] = '1';
$result["error_code"] = 14013;
$result["msg"] = "act_name参数必须传入。";
return $result;
}
if (empty($act_name))
{
$result["error"] = '1';
$result["error_code"] = 14014;
$result["msg"] = "act_name参数不能为空。";
return $result;
}
if (!isset($remark))
{
$result["error"] = '1';
$result["error_code"] = 14015;
$result["msg"] = "remark参数必须传入。";
return $result;
}
if (empty($remark))
{
$result["error"] = '1';
$result["error_code"] = 14016;
$result["msg"] = "remark参数不能为空。";
return $result;
}
if (!isset($re_openid))
{
$result["error"] = '1';
$result["error_code"] = 14022;
$result["msg"] = "re_openid参数必须传入。";
return $result;
}
if (empty($re_openid))
{
$result["error"] = '1';
$result["error_code"] = 14023;
$result["msg"] = "re_openid参数不能为空。";
return $result;
}
if ($this->userInfo["auth_type"] == AUTHTYPE_WECHAT)
{
/*$refererUrl = $_SERVER['HTTP_REFERER'];// 当前调用发红包的域名
if( !isset($refererUrl) || empty($refererUrl) ){
$result["error"] = '1';
$result["error_code"] = 14017;
$result["msg"] = "不是安全的域名。";
return $result;
}
// 发红包的安全域名
$sendredpack_safe_domain = iunserializer($this->businessInfo['sendredpack_safe_domain']);
$sendredpack_safe_domain1 = $sendredpack_safe_domain["sendredpack_safe_domain1"];
$sendredpack_safe_domain2 = $sendredpack_safe_domain["sendredpack_safe_domain2"];
$sendredpack_safe_domain3 = $sendredpack_safe_domain["sendredpack_safe_domain3"];
$referer_paths = parse_url($refererUrl);
if( !empty($referer_paths) && count($referer_paths)>0 ){
$referer_domain = $referer_paths["host"];
if( $sendredpack_safe_domain1!=$referer_domain && $sendredpack_safe_domain2!=$referer_domain && $sendredpack_safe_domain3!=$referer_domain ) {
$result["error"] = '1';
$result["error_code"] = 14018;
$result["msg"] = "不是安全的域名。";
return $result;
}
}*/
$wechat['appid'] = $this->businessInfo["weixin_appid"];// 微信公众号APPID
$wechat['secret'] = $this->businessInfo["weixin_secret_appid"];
$wechat['mchid'] = $this->businessInfo["mchid"];// 微信公众号商户号
$wechat['signkey'] = $this->businessInfo["signkey"];// 支付秘钥
$mch_billno = $this->businessInfo["mchid"] . date("YmdHis") . random(4, 1);
$record = array();
$record['app_id'] = $this->appInfo["id"];// app_id
$record['business_id'] = $this->businessInfo["id"];// business_id
$record['status'] = '0';// 发送状态(待发放)
$record['re_openid'] = $re_openid;// 发放红包的目标用户
$record['out_mch_billno'] = $out_mch_billno;// 订单编号
$record['mch_billno'] = $mch_billno;// 本平台订单编号
$record['send_name'] = $send_name;// 红包发送者名称
$record['total_amount'] = $total_amount;// 付款金额,单位分
$record['total_num'] = $total_num;// 红包发放总人数
$record['wishing'] = $wishing;// 红包祝福语
$record['client_ip'] = CLIENT_IP;// 调用接口的机器Ip地址
$record['act_name'] = $act_name;// 活动名称
$record['remark'] = $remark;// 备注信息
$record['send_listid'] = "";// 微信订单号
$record['createtime'] = TIMESTAMP;// 订单创建时间戳
$pdo = $this->db;
$pdo->beginTransaction();
// 插入一条支付记录
$send_redpack_id = Sql::insertInto('syweb_sendredpack_order')->values($record)->exec($pdo)->lastInsertId();
$pdo->commit();
if ($send_redpack_id)
{
$input = new WxPaySendredpack();
$input->SetMch_billno($mch_billno); // 商户订单号
$input->SetSend_name($send_name); // 商户名称
$input->SetRe_openid($re_openid);// 接受红包的用户的openid
$input->SetTotal_amount($total_amount * 100);// 付款金额,单位分
$input->SetTotal_num($total_num);// 红包发放总人数
$input->SetWishing($wishing);// 红包祝福语
$input->SetClient_ip(CLIENT_IP);// 调用接口的机器Ip地址
$input->SetAct_name($act_name);// 活动名称
$input->SetRemark($remark);// 备注信息
$sendredpack_result = WxPayApi::sendredpack($input, 6, $wechat, $this->db);
if (!empty($sendredpack_result) && count($sendredpack_result) > 0)
{
if ($sendredpack_result["return_code"] == "SUCCESS")
{
if ($sendredpack_result["result_code"] == "SUCCESS")
{
$pdo->beginTransaction();
Sql::update('syweb_sendredpack_order')->setArgs(array(
'status' => 1,
'send_listid' => $sendredpack_result["send_listid"],
))->where('id = ?', $send_redpack_id)->exec($pdo);
$pdo->commit();
$result["error"] = "0";
$result["state"] = $state;
$result["msg"] = "申请发送红包成功。";
return $result;
}
else
{
$result["error"] = '1';
$result["error_code"] = 14021;
$result["msg"] = $sendredpack_result["return_msg"];
return $result;
}
}
else
{
$result["error"] = '1';
$result["error_code"] = 14020;
$result["msg"] = $sendredpack_result["return_msg"];
return $result;
}
}
else
{
$result["error"] = '1';
$result["error_code"] = 14019;
$result["msg"] = "申请发送红包返回消息为空。";
return $result;
}
}
}
else
{
exit("请使用微信登录再申请红包!");
}
}
else
{
return $verify_result;
}
}
/** @inject("ioc_factory") */
private $factory;
/**
* @property({"default":"@db"})
* @var PDO
*/
public $db;
}