2025-08-13 10:43:56 +08:00
|
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
|
|
namespace app\api\controller;
|
|
|
|
|
|
|
|
|
|
|
|
use think\Controller;
|
|
|
|
|
|
use think\Db;
|
|
|
|
|
|
use think\Loader;
|
|
|
|
|
|
use think\Log;
|
|
|
|
|
|
use Yzh\YunPay;
|
|
|
|
|
|
|
|
|
|
|
|
class Payment extends Controller
|
|
|
|
|
|
{
|
|
|
|
|
|
//生成订单号
|
|
|
|
|
|
private function createOrderSn() {
|
|
|
|
|
|
$orderSn = strtoupper(date('Ymd', time())).substr(time(), -5).substr(microtime(), 2, 5).sprintf('%02d',
|
|
|
|
|
|
rand(0, 99));
|
|
|
|
|
|
return $orderSn;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* APP支付
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function app_pay() {
|
|
|
|
|
|
$type = input('type', 0); //1-微信 2-支付宝 4-通联支付宝 5-通联微信
|
|
|
|
|
|
$user_id = input('user_id', 0);
|
|
|
|
|
|
$money = input('money', 0);
|
|
|
|
|
|
$coin = input('coin', 0);
|
|
|
|
|
|
if(!$coin){
|
|
|
|
|
|
$coin = $money * get_system_config_value('rmb_coin_ratio');
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!$user_id) {
|
|
|
|
|
|
return V(0, '请选择充值用户', null);
|
|
|
|
|
|
}
|
2025-09-16 20:50:05 +08:00
|
|
|
|
//获取用户的手机号
|
|
|
|
|
|
$user_phone = db::name('user')->where(["id" => $user_id])->value('mobile');
|
|
|
|
|
|
if(!$user_phone){
|
|
|
|
|
|
return V(0, '请先绑定手机号!', null);
|
|
|
|
|
|
}
|
|
|
|
|
|
//获取用户的实名信息
|
|
|
|
|
|
$real_name = db::name('user_auth')->where(["mobile" => $user_phone,'is_real' => 1])->find();
|
|
|
|
|
|
if(!$real_name){
|
|
|
|
|
|
return V(0, '请先实名认证', null);
|
|
|
|
|
|
}
|
|
|
|
|
|
//获取用户的年龄
|
|
|
|
|
|
if(!getAgeId($real_name['card_id'])){
|
|
|
|
|
|
return V(0, '未成年不可充值!', null);
|
|
|
|
|
|
}
|
2025-08-13 10:43:56 +08:00
|
|
|
|
|
2025-09-25 14:36:26 +08:00
|
|
|
|
if (!is_numeric($money) || floor($money) != $money || $money <= 0 || $money > 2000) {
|
2025-08-13 10:43:56 +08:00
|
|
|
|
return V(0, '请选择正确的充值金额', null);
|
|
|
|
|
|
}
|
|
|
|
|
|
$user_code = db::name('user')->where(["id" => $user_id])->value('user_code');
|
2025-09-08 16:50:29 +08:00
|
|
|
|
$title = "APP充值到用户". ($user_code ?? "") ."余额!";
|
2025-08-13 10:43:56 +08:00
|
|
|
|
|
|
|
|
|
|
$order_number = $this->createOrderSn();
|
|
|
|
|
|
$data['order_sn'] = $order_number;
|
|
|
|
|
|
$data['money'] = $money;
|
|
|
|
|
|
$data['coin'] = $coin;
|
|
|
|
|
|
$data['user_id'] = $user_id;
|
|
|
|
|
|
$data['pay_type'] = $type;
|
|
|
|
|
|
$data['createtime'] = time();
|
|
|
|
|
|
$data['remarke'] = '充值到app用户'.($user_code ?? "") ."余额!";;
|
|
|
|
|
|
|
|
|
|
|
|
$re = db::name('vs_user_recharge')->insert($data);
|
|
|
|
|
|
if (!$re) {
|
|
|
|
|
|
return V(0, '充值失败', null);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if($type == 2){
|
|
|
|
|
|
//引用支付宝sdk
|
|
|
|
|
|
Loader::import('AliPayV2.AliPay', EXTEND_PATH, '.php');
|
|
|
|
|
|
$ali = new \AliPay();
|
|
|
|
|
|
$result['ali'] = $ali->aliAppPays($order_number, $money, $title);
|
|
|
|
|
|
}elseif($type == 1){
|
|
|
|
|
|
//引用微信sdk
|
|
|
|
|
|
Loader::import('WxPay.WxPay', EXTEND_PATH, '.php');
|
|
|
|
|
|
$wx = new \WxPay();
|
|
|
|
|
|
$result['wx'] = $wx->WxPayApp($data);
|
|
|
|
|
|
}elseif($type == 4 || $type == 5){
|
|
|
|
|
|
//引用通联sdk
|
|
|
|
|
|
Loader::import('TongLian.TongLian', EXTEND_PATH, '.php');
|
|
|
|
|
|
$tonglian = new \TongLian();
|
|
|
|
|
|
$result['tl'] = $tonglian->TongLianPay($data, $type);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return V(1, 'app支付', $result);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//支付宝回调
|
|
|
|
|
|
public function notify_ali() {
|
|
|
|
|
|
//引用支付宝sdk
|
|
|
|
|
|
Loader::import('AliPayV2.AliPay', EXTEND_PATH, '.php');
|
|
|
|
|
|
$ali = new \AliPay();
|
|
|
|
|
|
$verify_result = $ali->verify($_POST);
|
|
|
|
|
|
Log::record("支付宝回调信息".json_encode($_POST),"info");
|
|
|
|
|
|
|
|
|
|
|
|
if($verify_result) {//验证成功
|
|
|
|
|
|
//商户订单号
|
|
|
|
|
|
$out_trade_no = $_POST['out_trade_no'];
|
|
|
|
|
|
//支付宝交易号
|
|
|
|
|
|
$trade_no = $_POST['trade_no'];
|
|
|
|
|
|
|
|
|
|
|
|
if ($_POST['trade_status'] == 'TRADE_SUCCESS') {
|
|
|
|
|
|
$where['order_sn']=$out_trade_no;
|
|
|
|
|
|
$where['order_type']=1;
|
|
|
|
|
|
$where['pay_type']=2;
|
|
|
|
|
|
|
|
|
|
|
|
$data=[
|
|
|
|
|
|
'trade_no'=>$trade_no
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
$res = handelCharge($where,$data);
|
|
|
|
|
|
if($res==0){
|
|
|
|
|
|
echo "fail";
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
echo "success"; //请不要修改或删除
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
echo "fail";
|
|
|
|
|
|
}else {
|
|
|
|
|
|
//验证失败
|
|
|
|
|
|
echo "fail";
|
|
|
|
|
|
//写入日志文件
|
|
|
|
|
|
Log::record("支付宝回调验签失败","info");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//微信回调地址 示例
|
|
|
|
|
|
public function notify_wx() {
|
|
|
|
|
|
//引用微信sdk
|
|
|
|
|
|
Loader::import('WxPay.WxPay', EXTEND_PATH, '.php');
|
|
|
|
|
|
$wx = new \WxPay();
|
|
|
|
|
|
//验证是否是微信发送且数据完整
|
|
|
|
|
|
$flag = $wx->WxPayNotifyCheck();
|
|
|
|
|
|
|
|
|
|
|
|
if ($flag['status']) {
|
|
|
|
|
|
if ($flag['data']['return_code'] == 'SUCCESS' && $flag['data']['result_code'] == 'SUCCESS') {
|
|
|
|
|
|
$out_trade_no = $flag['data']['out_trade_no'];//订单号
|
|
|
|
|
|
// $payType = $flag['data']['attach']; //商家数据包
|
|
|
|
|
|
// $time_end = strtotime($flag['data']['time_end']); //支付完成时间
|
|
|
|
|
|
$transaction_id = $flag['data']['transaction_id']; //微信支付订单号
|
|
|
|
|
|
|
|
|
|
|
|
//成功后的业务逻辑处理
|
|
|
|
|
|
$where['order_sn']=$out_trade_no;
|
|
|
|
|
|
$where['order_type']=1;//1 充值
|
|
|
|
|
|
$where['pay_type']=1;//1微信2支付宝 3通联支付宝 4通联微信
|
|
|
|
|
|
|
|
|
|
|
|
$data=[
|
|
|
|
|
|
'trade_no'=>$transaction_id
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
$res = handelCharge($where,$data);
|
|
|
|
|
|
if($res==0){
|
|
|
|
|
|
$r_arr['return_code'] = 'FAIL';
|
|
|
|
|
|
$r_arr['return_msg'] = '回调失败';
|
|
|
|
|
|
echo $wx->arrayToXml($r_arr);
|
|
|
|
|
|
die;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$r_arr['return_code'] = 'SUCCESS';
|
|
|
|
|
|
$r_arr['return_msg'] = '回调成功';
|
|
|
|
|
|
echo $wx->arrayToXml($r_arr);
|
|
|
|
|
|
die;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
$r_arr['return_code'] = 'FAIL';
|
|
|
|
|
|
$r_arr['return_msg'] = '回调失败';
|
|
|
|
|
|
echo $wx->arrayToXml($r_arr);
|
|
|
|
|
|
die;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//通联支付回调地址 示例
|
|
|
|
|
|
public function allinpayNotify() {
|
|
|
|
|
|
$params = array();
|
|
|
|
|
|
foreach($_POST as $key=>$val) {//动态遍历获取所有收到的参数,此步非常关键,因为收银宝以后可能会加字段,动态获取可以兼容由于收银宝加字段而引起的签名异常
|
|
|
|
|
|
$params[$key] = $val;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if(count($params)<1){//如果参数为空,则不进行处理
|
|
|
|
|
|
echo "error";
|
|
|
|
|
|
exit();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//引用通联sdk
|
|
|
|
|
|
Loader::import('TongLian.TongLian', EXTEND_PATH, '.php');
|
|
|
|
|
|
$tonglian = new \TongLian();
|
|
|
|
|
|
|
|
|
|
|
|
$ree = $tonglian->ValidSign($params);
|
|
|
|
|
|
// Log::record("通联支付回调信息".json_encode($ree),"info");
|
|
|
|
|
|
if($tonglian->ValidSign($params)){//验签成功
|
|
|
|
|
|
Log::record("通联支付回调信息验签成功".json_encode($params),"info");
|
|
|
|
|
|
//此处进行业务逻辑处理
|
|
|
|
|
|
$pay_type =trim($params['trxreserved']);//备注信息remark
|
|
|
|
|
|
$out_trade_no = trim($params['cusorderid']); //商户订单号
|
|
|
|
|
|
$trade_no = trim($params['trxid']); // 交易号
|
|
|
|
|
|
// $gmt_payment = strtotime(trim($_POST['paytime'])); //交易付款时间
|
|
|
|
|
|
//成功后的业务逻辑处理
|
|
|
|
|
|
$where['order_sn']=$out_trade_no;
|
|
|
|
|
|
$where['order_type']=1;//1 充值
|
|
|
|
|
|
$where['pay_type']=$pay_type;//1微信2支付宝 3通联支付宝 4通联微信
|
|
|
|
|
|
|
|
|
|
|
|
$data=[
|
|
|
|
|
|
'trade_no'=>$trade_no
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
$res = handelCharge($where,$data);
|
|
|
|
|
|
if($res==0){
|
|
|
|
|
|
echo "erro";
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
echo "success";
|
|
|
|
|
|
}else{
|
|
|
|
|
|
Log::record("通联支付回调信息验签失败".json_encode($params),"info");
|
|
|
|
|
|
echo "erro";
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
|
|
|
* 云账户回调(提现)
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function yun_callback(){
|
|
|
|
|
|
$data = input("data", "");
|
|
|
|
|
|
$mess = input("mess", "");
|
|
|
|
|
|
$timestamp = input("timestamp", "");
|
|
|
|
|
|
$sign = input("sign", "");
|
|
|
|
|
|
Log::record("云账户回调信息".json_encode($_POST),"info");
|
|
|
|
|
|
$yun_pay = new YunPay();
|
|
|
|
|
|
$result = $yun_pay->yun_callback($data,$mess,$timestamp,$sign);
|
|
|
|
|
|
if($result['code']==1){
|
|
|
|
|
|
$data = $result['data'];
|
|
|
|
|
|
if($data){
|
|
|
|
|
|
if(!isset($data['status'])){
|
|
|
|
|
|
echo 'fail';
|
|
|
|
|
|
die;
|
|
|
|
|
|
}
|
|
|
|
|
|
$status = $data['status'];
|
|
|
|
|
|
switch ($status){
|
|
|
|
|
|
case "1":
|
|
|
|
|
|
// 支付成功(对于支付宝和微信支付是最终状态,对于银行卡大部分情况是终态,小概率会出现"退汇现象",状态由"成功"变为"退汇")
|
|
|
|
|
|
db::name('vs_user_withdrawal')
|
|
|
|
|
|
->where('order_sn',$data['order_id'])
|
|
|
|
|
|
->where('status',4)
|
|
|
|
|
|
->update([
|
|
|
|
|
|
'status' => 6,
|
|
|
|
|
|
'pay_message' => $data['status_message'],
|
|
|
|
|
|
'pay_time' => time(),
|
|
|
|
|
|
'updatetime' => time()
|
|
|
|
|
|
]);
|
|
|
|
|
|
echo "success";
|
|
|
|
|
|
break;
|
|
|
|
|
|
case "2":
|
|
|
|
|
|
// 支付失败(最终状态)
|
|
|
|
|
|
// TODO 更新业务订单状态,提示用户提现失败,若有用户钱包体系,则需将提现金额退回至用户钱包
|
|
|
|
|
|
db::name('vs_user_withdrawal')
|
|
|
|
|
|
->where('order_sn',$data['order_id'])
|
|
|
|
|
|
->where('status',4)
|
|
|
|
|
|
->update([
|
|
|
|
|
|
'status' => 5,
|
|
|
|
|
|
'pay_message' => $data['status_message'],
|
|
|
|
|
|
'pay_time' => time(),
|
|
|
|
|
|
'updatetime' => time()
|
|
|
|
|
|
]);
|
|
|
|
|
|
//支付失败资金退回
|
|
|
|
|
|
$res = model('/UserWithdrawal')->withdrawal_fail($data['order_id']);
|
|
|
|
|
|
echo "success";
|
|
|
|
|
|
break;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case "4":
|
|
|
|
|
|
// 订单挂单(中间状态,挂单原因会在订单详细状态信息返回)
|
|
|
|
|
|
// TODO 提示用户提现中,其他逻辑如:若因余额不足导致的挂单,可通知财务及时充值,72小时内补足余额后可自动继续支付
|
|
|
|
|
|
echo "success";
|
|
|
|
|
|
break;
|
|
|
|
|
|
case "9":
|
|
|
|
|
|
// 退汇,(最终状态,银行卡渠道特有现象,会先收到"成功"回调,然后再收到"退汇"的回调,一般以成功状态间隔24小时以上)
|
|
|
|
|
|
// TODO 更新业务订单状态为“退汇”(失败),通知用户提现失败,建议用户更换其他银行卡提现,若有用户钱包体系,则需将提现金额退回至用户钱包
|
|
|
|
|
|
db::name('vs_user_withdrawal')
|
|
|
|
|
|
->where('order_sn',$data['order_id'])
|
|
|
|
|
|
->where('status',4)
|
|
|
|
|
|
->update([
|
|
|
|
|
|
'status' => 5,
|
|
|
|
|
|
'pay_message' => $data['status_message'],
|
|
|
|
|
|
'pay_time' => time(),
|
|
|
|
|
|
'updatetime' => time()
|
|
|
|
|
|
]);
|
|
|
|
|
|
//支付失败资金退回
|
|
|
|
|
|
$res = model('/UserWithdrawal')->withdrawal_fail($data['order_id']);
|
|
|
|
|
|
echo "success";
|
|
|
|
|
|
break;
|
|
|
|
|
|
case "15":
|
|
|
|
|
|
// 订单取消,(最终状态,只有挂单的订单才可以取消)
|
|
|
|
|
|
// TODO 更新业务订单状态为“取消”(失败),通知用户提现失败,若有用户钱包体系,则需将提现金额退回至用户钱包
|
|
|
|
|
|
db::name('vs_user_withdrawal')
|
|
|
|
|
|
->where('order_sn',$data['order_id'])
|
|
|
|
|
|
->where('status',4)
|
|
|
|
|
|
->update([
|
|
|
|
|
|
'status' => 5,
|
|
|
|
|
|
'pay_message' => $data['status_message'],
|
|
|
|
|
|
'pay_time' => time(),
|
|
|
|
|
|
'updatetime' => time()
|
|
|
|
|
|
]);
|
|
|
|
|
|
//支付失败资金退回
|
|
|
|
|
|
$res = model('/UserWithdrawal')->withdrawal_fail($data['order_id']);
|
|
|
|
|
|
echo "success";
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}else{
|
|
|
|
|
|
echo "fail";
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|