You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
327 lines
14 KiB
327 lines
14 KiB
<?php
|
|
/**
|
|
* 订单退款模型/商户提现打款模型/代理商提现打款模型
|
|
*/
|
|
defined('IN_IA') or exit('Access Denied');
|
|
use Yansongda\Pay\Pay as YanSongDa;
|
|
class Refund{
|
|
protected static $orderNo ,//订单号
|
|
$orderInfo ,//订单信息
|
|
$source ,//渠道信息:1=公众号(默认);2=h5;3=小程序
|
|
$type ,//支付方式:1=余额;2=微信;3=支付宝;4=货到付款
|
|
$key ,//由渠道信息和支付方式拼接获得
|
|
$settingInfo ,//支付设置信息
|
|
$configInfo ,//支付配置信息
|
|
$payNotify ,//异步通知地址
|
|
$payReturn ,//跳转地址
|
|
$refundPrice ,//退款的金额
|
|
$blendcredit ,//退款的余额
|
|
$payLogPath = PATH_MODULE."payment/",//支付异步通知日志地址
|
|
$dd;
|
|
|
|
/**
|
|
* Comment: 申请退款并且进行信息的初始化
|
|
* Author: zzw
|
|
* Date: 2019/9/28 17:36
|
|
* @param $order_no
|
|
* @param int $price
|
|
* @return array|bool|string
|
|
*/
|
|
public static function refundInit($order_no,$price = -1,$blendcredit = 0){
|
|
self::$orderNo = $order_no;
|
|
self::$refundPrice = $price;
|
|
self::$blendcredit = $blendcredit;
|
|
#1、订单信息获取
|
|
$res = self::getOrderInfo();
|
|
if ($res) return $res;
|
|
#1、拼接渠道信息和支付方式 获得key信息 1_credit
|
|
//渠道信息:1=公众号(默认);2=h5;3=小程序
|
|
//支付方式:1=余额;2=微信;3=支付宝;4=货到付款 5=云收单
|
|
if($price < 0.01 && $blendcredit > 0){
|
|
self::$refundPrice = $blendcredit;
|
|
self::$orderInfo['type'] = 1;
|
|
}
|
|
self::$key = self::$orderInfo['source'].'_'.self::$orderInfo['type'];
|
|
#1、支付设置信息获取
|
|
self::getSettingInfo();
|
|
#1、调用对应的退款接口
|
|
switch (self::$key){
|
|
case '1_1': case '2_1': case '3_1':
|
|
$res = self::balance();
|
|
break;//余额退款(所有渠道)
|
|
case '1_2': case '2_2':case '3_2':
|
|
//self::$payNotify = PAY_PATH."WeChatRefund.php";
|
|
//self::$payReturn = '';
|
|
self::weChatConfig();
|
|
$res = self::weChat_weChat();
|
|
if(self::$blendcredit > 0 && $res['error'] > 0){
|
|
Member::credit_update_credit2(self::$orderInfo['mid'],self::$blendcredit,'订单['.self::$orderNo.']退款');
|
|
}
|
|
break;//公众号 - 微信退款 || H5 - 微信退款
|
|
case '1_3': case '2_3':
|
|
self::$payNotify = PAY_PATH."AlipayRefund.php";
|
|
self::$payReturn = '';
|
|
self::aliPayConfig();
|
|
$res = self::weChat_aliPay();
|
|
break;//公众号 - 支付宝退款 || H5 - 支付宝退款
|
|
case '1_5':
|
|
self::yunWeChatConfig();
|
|
$res = self::Yun_WeChat_WeChat();
|
|
break;//公众号 - 云收单
|
|
}
|
|
|
|
return $res;
|
|
}
|
|
|
|
/****** 退款接口 ******************************************************************************************************/
|
|
/**
|
|
* Comment: 余额退款
|
|
* Author: zzw
|
|
* Date: 2019/9/28 16:07
|
|
* @return array|bool
|
|
*/
|
|
protected static function balance(){
|
|
#2、余额退款,直接为用户添加余额即可
|
|
Member::credit_update_credit2(self::$orderInfo['mid'],self::$refundPrice,'订单['.self::$orderNo.']退款');
|
|
return ['error'=>1];
|
|
}
|
|
/**
|
|
* Comment: 微信公众号|H5 - 微信退款
|
|
* Author: zzw
|
|
* Date: 2019/9/28 17:25
|
|
* @return array
|
|
*/
|
|
protected static function weChat_weChat(){
|
|
#1、配置订单信息
|
|
$order = [
|
|
'out_trade_no' => self::$orderInfo['pay_order_no'] ,
|
|
'out_refund_no' => 'R'.rand(0,9).self::$orderNo ,
|
|
'total_fee' => sprintf("%.0f",self::$orderInfo['fee'] * 100),
|
|
'refund_fee' => sprintf("%.0f",self::$refundPrice * 100),
|
|
'refund_desc' => '订单['.self::$orderNo.']退款' ,
|
|
];
|
|
#2、调用接口进行退款操作
|
|
try {
|
|
yanSongDa::wechat(self::$configInfo)->refund($order);
|
|
return ['error'=>1];
|
|
} catch (Exception $e) {
|
|
$emg = $e->getMessage();
|
|
return ['error'=>0,'msg'=>$emg];
|
|
}
|
|
}
|
|
/**
|
|
* Comment: 微信公众号|H5 - 支付宝退款
|
|
* Author: zzw
|
|
* Date: 2019/9/28 17:35
|
|
* @return array
|
|
*/
|
|
protected static function weChat_aliPay(){
|
|
#1、获取支付宝订单信息
|
|
$order = [
|
|
'out_trade_no' => self::$orderInfo['pay_order_no'],
|
|
'refund_amount' => self::$refundPrice,
|
|
'out_request_no' => rand(100,999).time(),
|
|
];
|
|
#2、调用接口进行退款操作
|
|
try {
|
|
yanSongDa::alipay(self::$configInfo)->refund($order);
|
|
return ['error'=>1];
|
|
} catch (Exception $e) {
|
|
$emg = $e->getMessage();
|
|
//忽略签名错误
|
|
if($emg == 'INVALID_SIGN: Alipay Sign Verify FAILED'){
|
|
return ['error'=>1];
|
|
}else{
|
|
return ['error'=>0,'msg'=>$emg];
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/****** 配置信息获取 **************************************************************************************************/
|
|
/**
|
|
* Comment: 支付宝配置信息获取
|
|
* Author: zzw
|
|
* Date: 2019/8/29 10:30
|
|
* @return array
|
|
*/
|
|
protected static function aliPayConfig(){
|
|
self::$configInfo = [
|
|
'app_id' => trim(self::$settingInfo['ali_app_id']),
|
|
'notify_url' => trim(self::$payNotify),
|
|
'return_url' => trim(self::$payReturn),
|
|
'ali_public_key' => trim(self::$settingInfo['ali_public_key']),
|
|
'private_key' => trim(self::$settingInfo['app_private_key']),
|
|
];
|
|
}
|
|
/**
|
|
* Comment: 微信配置信息获取
|
|
* Author: zzw
|
|
* Date: 2019/9/2 15:00
|
|
*/
|
|
protected static function weChatConfig(){
|
|
$filePath = PATH_ATTACHMENT . "public_file/" . MODULE_NAME . "/";
|
|
if(self::$settingInfo['shop_type'] == 2){
|
|
//子商户支付
|
|
self::$configInfo = [
|
|
'appid' => trim(self::$settingInfo['sub_up_app_id']) , // APP APPID
|
|
'app_id' => trim(self::$settingInfo['sub_up_app_id']) , // 公众号 APPID
|
|
'miniapp_id' => trim(self::$settingInfo['sub_up_app_id']) , // 小程序 APPID
|
|
'sub_appid' => trim(self::$settingInfo['app_id']) , // 子商户 APP APPID
|
|
'sub_app_id' => trim(self::$settingInfo['app_id']) , // 子商户 公众号 APPID
|
|
'sub_miniapp_id' => trim(self::$settingInfo['app_id']) , // 子商户 小程序 APPID
|
|
'mch_id' => trim(self::$settingInfo['shop_number']) ,
|
|
'sub_mch_id' => trim(self::$settingInfo['sub_shop_number']) , // 子商户商户号
|
|
'key' => trim(self::$settingInfo['secret_key']) ,//secret_key sub_secret_key
|
|
'notify_url' => trim(self::$payNotify) ,
|
|
'cert_client' => trim($filePath . self::$settingInfo['cert_certificate']) , // optional, 退款,红包等情况时需要用到
|
|
'cert_key' => trim($filePath . self::$settingInfo['key_certificate']) ,// optional, 退款,红包等情况时需要用到
|
|
'mode' => 'service' ,
|
|
];
|
|
//是否开启子商户企业付款
|
|
/*if (self::$setting['sub_enterprise_payment'] == 2) {
|
|
self::$payConfig['key'] = trim(self::$setting['sub_secret_key']);
|
|
self::$payConfig['cert_client'] = trim(self::$setting['sub_cert_certificate']);
|
|
self::$payConfig['cert_key'] = trim(self::$setting['sub_key_certificate']);
|
|
}*/
|
|
}else{
|
|
//一般支付
|
|
self::$configInfo = [
|
|
'appid' => trim(self::$settingInfo['app_id']) , // APP APPID
|
|
'app_id' => trim(self::$settingInfo['app_id']) , // 公众号 APPID
|
|
'miniapp_id' => trim(self::$settingInfo['app_id']) , // 小程序 APPID
|
|
'mch_id' => trim(self::$settingInfo['shop_number']) ,
|
|
'key' => trim(self::$settingInfo['secret_key']) ,
|
|
'notify_url' => trim(self::$payNotify) ,
|
|
'cert_client' => trim($filePath . self::$settingInfo['cert_certificate']) , // optional, 退款,红包等情况时需要用到
|
|
'cert_key' => trim($filePath . self::$settingInfo['key_certificate']) ,// optional, 退款,红包等情况时需要用到
|
|
];
|
|
}
|
|
}
|
|
|
|
protected static function yunWeChatConfig(){
|
|
//云收单
|
|
$yun_signIn = Payment::yunSignIn(self::$settingInfo['yun_merchantNo'],self::$settingInfo['yun_terminalNo']);
|
|
self::$configInfo = [
|
|
'itpOrderId' => self::$orderInfo['transaction_id'],
|
|
'merchantNo' => self::$settingInfo['yun_merchantNo'],
|
|
'terminalNo' => self::$settingInfo['yun_terminalNo'],
|
|
'batchNo' => $yun_signIn['batchNo'],
|
|
'traceNo' => $yun_signIn['traceNo'],
|
|
'mchtRefundNo' => 'R'.rand(0,9).self::$orderNo,
|
|
'refundAmount' => sprintf("%.0f",self::$refundPrice * 100),
|
|
'nonceStr' => random(16)
|
|
];
|
|
}
|
|
|
|
|
|
/****** 公共方法 ******************************************************************************************************/
|
|
/**
|
|
* Comment: 获取订单信息
|
|
* Author: zzw
|
|
* Date: 2019/9/28 15:06
|
|
*/
|
|
protected static function getOrderInfo(){
|
|
#1、获取订单信息
|
|
self::$orderInfo = pdo_get(PDO_NAME."paylogvfour",['tid'=>self::$orderNo]
|
|
,['transaction_id','source','mid','tid','fee','status','plugin','type','pay_order_no','blendcredit','batchNo','traceNo']);
|
|
#2、判断当前订单是否符合退款操作
|
|
if(!self::$orderInfo){
|
|
self::$orderInfo = pdo_get(PDO_NAME."paylog",['tid'=>self::$orderNo],['transaction_id','source','mid','tid','fee','status','plugin','type','pay_order_no']);
|
|
}
|
|
if(!self::$orderInfo) return array('error'=>0,'msg'=>'订单不存在');
|
|
if(self::$orderInfo['status'] == 0) return array('error'=>0,'msg'=>'订单未支付,不可退款');
|
|
if(self::$orderInfo['plugin'] == 'Rush'){
|
|
self::$orderInfo['sid'] = pdo_getcolumn(PDO_NAME.'rush_order',array('orderno' => self::$orderNo ),'sid');
|
|
}else {
|
|
self::$orderInfo['sid'] = pdo_getcolumn(PDO_NAME.'order',array('orderno' => self::$orderNo ),'sid');
|
|
}
|
|
#3、同订单信息获取其他基本信息
|
|
self::$source = self::$orderInfo['source'];
|
|
self::$type = self::$orderInfo['type'];
|
|
if(self::$orderInfo['blendcredit'] > 0){
|
|
self::$orderInfo['fee'] = sprintf("%.2f",self::$orderInfo['fee'] - self::$orderInfo['blendcredit']);
|
|
}
|
|
if(self::$refundPrice <= 0) self::$refundPrice = self::$orderInfo['fee'];
|
|
//判断云收单
|
|
if(!empty(self::$orderInfo['batchNo'])){
|
|
self::$orderInfo['type'] = 5;
|
|
}
|
|
}
|
|
/**
|
|
* Comment: 获取当前订单支付方式对应的支付设置信息
|
|
* Author: zzw
|
|
* Date: 2019/9/28 15:40
|
|
*/
|
|
protected static function getSettingInfo(){
|
|
global $_W;
|
|
#1、通过key值获取
|
|
$set = Setting::wlsetting_read("payment_set");
|
|
$cashset = Setting::wlsetting_read("cashset");
|
|
switch (self::$key){
|
|
case '1_2':
|
|
if($cashset['allocationtype'] == 1){
|
|
$id = pdo_getcolumn(PDO_NAME.'merchantdata',array('id'=>self::$orderInfo['sid']),'wxallid');
|
|
}
|
|
if(empty($id)){
|
|
$id = $set['wechat']['wechat'];
|
|
}
|
|
break;//公众号 - 微信支付配置信息
|
|
case '1_3':
|
|
$id = $set['wechat']['alipay'];
|
|
break;//公众号 - 支付宝配置信息
|
|
case '2_2':
|
|
$id = $set['h5']['wechat'];
|
|
break;//H5 - 微信支付配置信息
|
|
case '2_3':
|
|
$id = $set['h5']['alipay'];
|
|
break;//H5 - 支付宝配置信息
|
|
case '3_2':
|
|
if($cashset['allocationtype'] == 1){
|
|
$id = pdo_getcolumn(PDO_NAME.'merchantdata',array('id'=>self::$orderInfo['sid']),'appallid');
|
|
}
|
|
if(empty($id)){
|
|
$id = $set['wxapp']['wechat'];
|
|
}
|
|
break;//小程序 - 微信支付
|
|
case '1_5':
|
|
$id = $set['wechat']['yunpay'];
|
|
break;//公众号 - 云收单
|
|
}
|
|
#2、获取设置信息数据
|
|
self::$settingInfo = json_decode(pdo_getcolumn(PDO_NAME."payment",['id'=>$id],'param'),true);
|
|
#3、获取对应渠道的appid
|
|
switch (self::$type){
|
|
case 2:
|
|
if(self::$source == 1){
|
|
$account = $_W['account'] ? : uni_fetch($_W['uniacid']);
|
|
self::$settingInfo['app_id'] = Util::object_array($account)['key'];//公众号、H5
|
|
}else{
|
|
self::$settingInfo['app_id'] = Setting::wlsetting_read('wxapp_config')['appid'];//小程序
|
|
}
|
|
break;//微信
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Comment: 微信公众号 —— 云收单微信支付
|
|
* Author: wlf
|
|
* Date: 2021/07/22 16:09
|
|
* @return array
|
|
*/
|
|
protected static function Yun_WeChat_WeChat(){
|
|
$wechatUrl = 'https://epos.ahrcu.com:3443/cposp/pay/refund';
|
|
$wechatData = self::$configInfo;
|
|
$wechatData['sign'] = Payment::getYunSign($wechatData,self::$settingInfo['yun_KEY']);
|
|
$wechatData = json_encode($wechatData);
|
|
$refundInfo = curlPostRequest($wechatUrl,$wechatData,["Content-type: application/json;charset='utf-8'"]);
|
|
if($refundInfo['refundStatus'] != '01'){
|
|
Util::wl_log('160PayApi.log',PATH_DATA,$refundInfo); //写入异步日志记录
|
|
return ['error'=>0,'msg'=>$refundInfo['errorDesc']];
|
|
}else{
|
|
return ['error'=>1];
|
|
}
|
|
}
|
|
|
|
}
|
|
|