Files
duolamaojiazhen/application/common/logic/PaymentLogic.php
2025-12-22 13:59:40 +08:00

420 lines
13 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
// +----------------------------------------------------------------------
// | likeshop100%开源免费商用商城系统
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用可去除界面版权logo
// | 商业版本务必购买商业授权,以免引起法律纠纷
// | 禁止对系统程序代码以任何目的,任何形式的再发布
// | gitee下载https://gitee.com/likeshop_gitee
// | github下载https://github.com/likeshop-github
// | 访问官网https://www.likeshop.cn
// | 访问社区https://home.likeshop.cn
// | 访问手册http://doc.likeshop.cn
// | 微信公众号likeshop技术社区
// | likeshop团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeshopTeam
// +----------------------------------------------------------------------
namespace app\common\logic;
use app\common\server\AliPayServer;
use app\common\server\WeChatPayServer;
use app\common\model\{Client_, Order, Pay, User};
use think\facade\Env;
class PaymentLogic extends LogicBase
{
protected static $error = '';
protected static $return_code = 0;
/**
* Notes: 错误信息
* @return string
* @author 段誉(2021/2/1 11:19)
*/
public static function getError()
{
return self::$error;
}
/**
* Notes: 返回状态码
* @return int
* @author 段誉(2021/2/1 11:19)
*/
public static function getReturnCode()
{
return self::$return_code;
}
/**
* Notes: 支付
* @param $from
* @param $order
* @param $order_source
* @return array|bool|string
* @author 段誉(2021/2/1 11:19)
*/
public static function pay($from, $order, $order_source)
{
switch ($order['pay_way']) {
case Pay::WECHAT_PAY:
$res = WeChatPayServer::unifiedOrder($from, $order, $order_source);
if (false === $res) {
self::$error = WeChatPayServer::getError();
}
break;
case Pay::ALI_PAY:
$aliPay = new AliPayServer();
$res = $aliPay->pay($from, $order, $order_source);
if(false === $res) {
self::$error = $aliPay->getError();
} else {
self::$return_code = 20001;//特殊状态码,用于前端判断
}
break;
case 8:
$ttPay = new ttPay();
$res = $ttPay->run('order',$order);
// $res = self::ttpay($order);
if(!empty($res['data'])) {
self::$return_code = 8888;//特殊状态码,用于前端判断
$res = $res['data'];
}else{
self::$error = $res['err_tips'];
$res = false;
}
break;
default:
self::$error = '订单异常';
$res = false;
}
return $res;
}
//抖音支付
public static function ttpay($data)
{
$url = 'https://developer.toutiao.com/api/apps/ecpay/v1/create_order';
$params['app_id'] = 'tt0523739e9a12236501';
$params['out_order_no'] = (string)$data['order_sn'];
$params['total_amount'] = (int)$data['order_amount'] * 100;
$params['subject'] = 'subject';
$params['body'] = 'body';
$params['valid_time'] = 3600;
$params['sign'] = self::ttsign($params,'ejAuHvbI472euyhb34aVyLD92ll9tgZCqWnMi0tX');
$http = self::httpPost($url, $params);
return json_decode($http,true);
}
//curl
public static function httpPost($url, $data = null)
{
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
if (!$data) return false;
if (is_array($data)) {
$data = json_encode($data);
}
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
curl_setopt($curl, CURLOPT_HEADER, 0);
curl_setopt($curl, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json; charset=utf-8',
'Content-Length:' . strlen($data),
'Cache-Control: no-cache',
'Pragma: no-cache'
));
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$res = curl_exec($curl);
curl_close($curl);
return $res;
}
// 签名
public static function ttsign($map,$secret)
{
$rList = [];
foreach($map as $k =>$v) {
if ($k == "other_settle_params" || $k == "app_id" || $k == "sign" || $k == "thirdparty_id")
continue;
$value = trim(strval($v));
$len = strlen($value);
if ($len > 1 && substr($value, 0,1)=="\"" && substr($value, $len-1)=="\"")
$value = substr($value,1, $len-1);
$value = trim($value);
if ($value == "" || $value == "null")
continue;
$rList[] = $value;
}
$rList[] = $secret;
sort($rList, SORT_STRING);
return md5(implode('&', $rList));
}
/**
* Notes: 是否在白名单内支付
* @param $user_id
* @author 段誉(2021/2/24 10:01)
* @return bool
*/
public static function isPayWhiteList($user_id)
{
$white_list = Env::get('wechat.white_list', '');
$white_list = explode(',', $white_list);
if (in_array($user_id, $white_list)) {
return true;
}
return false;
}
}
Class ttPay{
private $api_url='https://developer.toutiao.com/api/apps/ecpay/v1/';
private $app_id;
private $token;
private $salt;
public function __construct() {
$this->app_id = 'tt0523739e9a12236501';
$this->token='123qazqweeesdflomswwe';
$this->salt='ejAuHvbI472euyhb34aVyLD92ll9tgZCqWnMi0tX';
// $this->salt='58280e4f36d88e93d7a4be9f0e590b2302a462c5';
}
public function run($action,$order){
$action=$action?$action:'order';
if(!in_array($action,['order','query','refund','settle','notify','set'])){
echo '非法请求';die;
}
return $this->$action($order);
}
//下单
private function order($order){
$data=[
'out_order_no'=>$order['order_sn'],
'total_amount'=>(int)$order['order_amount'] * 100,
'subject'=>'购买服务',
'body'=>'购买商品',
'valid_time'=>3600,
];
return $this->post('create_order',$data);
}
//查询订单
private function query(){
$data=[
'out_order_no'=>'2021110117254573565'
];
$res=$this->post('query_order',$data,false);
echo json_encode($res);die;
}
//订单退款
private function refund(){
$data=[
'out_order_no'=>'2021110118351347832',
'out_refund_no'=>$this->order_number(),
'reason'=>'退款原因',
'refund_amount'=>1,
];
$res=$this->post('create_refund',$data);
echo json_encode($res);die;
}
//订单分账
private function settle(){
$data=[
'out_order_no'=>'2021110118301265990',
'out_settle_no'=>$this->order_number(),
'settle_desc'=>'分账描述',
'settle_params'=>json_encode([]),//分润方参数 如[['merchant_uid'=>'商户号','amount'=>'10']] 可以有多个分账商户
];
$res=$this->post('settle',$data);
echo json_encode($res);die;
}
//支付设置回调测试
private function set(){
$content=file_get_contents('php://input');
$this->log('log.txt',$content);
}
//回调
private function notify(){
$content=file_get_contents('php://input');
if(empty($content)) return false;
$this->log('notify.txt',$content);
$content=json_decode($content,true);
$sign=$this->handler($content);
if($sign==$content['msg_signature']){
$msg=json_decode($content['msg'],true);
echo '回调----'.$content['type']."\n";
//这里更新应用业务逻辑代码,使用$msg跟应用订单比对更新订单,可以用 $content['type']判断是支付回调还是退款回调payment支付回调 refund退款回调。
$res=['err_no'=>0,'err_tips'=>'success'];
echo json_encode($res);
}
}
/**
* 测试订单号,实际应用根据自己应用实际生成
* @return string
*/
private function order_number(){
return date('YmdHis').rand(10000,99999);
}
/**
* 请求小程序平台服务端
* @param string $url 接口地址
* @param array $data 参数内容
* @param boolean $notify 是否有回调
* @return array
*/
private function post($method,$data,$notify=true){
$data['app_id']=$this->app_id;
$data['sign']=$this->sign($data);
$url=$this->api_url.$method;
$res=$this->http('POST',$url,json_encode($data),['Content-Type: application/json'],true);
return json_decode($res,true);
}
/**
* 回调验签
* @param array $map 验签参数
* @return stirng
*/
private function handler($map){
$rList = array();
array_push($rList, $this->token);
foreach($map as $k =>$v) {
if ( $k == "type" || $k=='msg_signature')
continue;
$value = trim(strval($v));
if ($value == "" || $value == "null")
continue;
array_push($rList, $value);
}
sort($rList,2);
return sha1(implode($rList));
}
/**
* 请求签名
* @param array $map 请求参数
* @return stirng
*/
private function sign($map) {
$rList = array();
foreach($map as $k =>$v) {
if ($k == "other_settle_params" || $k == "app_id" || $k == "sign" || $k == "thirdparty_id")
continue;
$value = trim(strval($v));
$len = strlen($value);
if ($len > 1 && substr($value, 0,1)=="\"" && substr($value,$len, $len-1)=="\"")
$value = substr($value,1, $len-1);
$value = trim($value);
if ($value == "" || $value == "null")
continue;
array_push($rList, $value);
}
array_push($rList, $this->salt);
sort($rList, 2);
return md5(implode('&', $rList));
}
/**
* 写日志
* @param string $path 日志路径
* @param string $content 内容
*/
private function log($path, $content){
$file=fopen($path, "a");
fwrite($file, date('Y-m-d H:i:s').'-----'.$content."\n");
fclose($file);
}
/**
* 网络请求
* @param stirng $method 请求模式
* @param stirng $url请求网关
* @param array $params 请求参数
* @param stirng $header 自定义头
* @param boolean $multi 文件上传
* @return array
*/
private function http( $method = 'GET', $url,$params,$header = array(), $multi = false){
$opts = array(
CURLOPT_TIMEOUT => 30,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
CURLOPT_HTTPHEADER => $header
);
/* 根据请求类型设置特定参数 */
switch(strtoupper($method)){
case 'GET':
$opts[CURLOPT_URL] = $url . '?' . http_build_query($params);
break;
case 'POST':
//判断是否传输文件
$params = $multi ? $params : http_build_query($params);
$opts[CURLOPT_URL] = $url;
$opts[CURLOPT_POST] = 1;
$opts[CURLOPT_POSTFIELDS] = $params;
break;
default:
throw new Exception('不支持的请求方式!');
}
/* 初始化并执行curl请求 */
$ch = curl_init();
curl_setopt_array($ch, $opts);
$data = curl_exec($ch);
$error = curl_error($ch);
curl_close($ch);
if($error) throw new Exception('请求发生错误:' . $error);
return $data;
}
}