247 lines
8.1 KiB
PHP
247 lines
8.1 KiB
PHP
<?php
|
||
|
||
namespace app\api\controller\school;
|
||
|
||
use addons\epay\library\Service;
|
||
use addons\third\model\Third;
|
||
use app\common\model\school\classes\order\Order as OrderModel;
|
||
use Exception;
|
||
|
||
use think\Log;
|
||
|
||
/**
|
||
* 课程支付接口
|
||
*/
|
||
class Pay extends Base
|
||
{
|
||
|
||
protected $noNeedLogin = '*';
|
||
protected $noNeedRight = '*';
|
||
protected $model = null;
|
||
|
||
/**
|
||
* 初始化操作
|
||
* @access protected
|
||
*/
|
||
protected function _initialize()
|
||
{
|
||
|
||
$this->model = new OrderModel;
|
||
parent::_initialize();
|
||
|
||
//判断登录用户是否是员工
|
||
}
|
||
|
||
|
||
/**
|
||
* @ApiTitle( 课程第三方支付)
|
||
* @ApiSummary(课程第三方支付(微信等支付))
|
||
* @ApiRoute(/api/school/pay/payment)
|
||
* @ApiMethod(POST)
|
||
* @ApiParams(name = "order_no", type = "string",required=true,description = "订单id或订单号")
|
||
* @ApiParams(name = "type", type = "string",required=true,description = "服务商:alipay=支付宝,wechat=微信")
|
||
* @ApiParams(name = "platform", type = "string",required=true,description = "平台:web=PC网页支付,wap=H5手机网页支付,app=APP支付,scan=扫码支付,mp=微信公众号支付,miniapp=微信小程序支付")
|
||
* @ApiParams(name = "openid", type = "string",required=false,description = "用户openid(非必填)")
|
||
* @ApiReturn({
|
||
*
|
||
*})
|
||
*/
|
||
public function payment()
|
||
{
|
||
$order_no = $this->request->post('order_no/s');
|
||
$type = $this->request->post('type/s');
|
||
$method = $this->request->post('platform/s');
|
||
$openid = $this->request->post('openid/s', "");
|
||
$platform = $method;
|
||
try {
|
||
//订单支付前校验
|
||
$this->model->checkPay($order_no,$type);
|
||
$order = OrderModel::where('order_no', $order_no)->find();
|
||
$amount = $order["totalprice"];
|
||
} catch (\Exception $e) {
|
||
$this->error($e->getMessage());
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
if (!$amount || $amount < 0) {
|
||
$this->error("支付金额必须大于0");
|
||
}
|
||
|
||
if (!$type || !in_array($type, ['alipay', 'wechat'])) {
|
||
$this->error("支付类型不能为空");
|
||
}
|
||
|
||
if (in_array($method, ['miniapp', 'mp']) && !$openid) {
|
||
|
||
// 微信公众号,小程序支付,必须有 openid
|
||
if (isset($openid) && $openid) {
|
||
// 如果传的有 openid
|
||
} else {
|
||
// 没有 openid 默认拿下单人的 openid
|
||
$oauth = Third::where([
|
||
'user_id' => $order->user_id,
|
||
'platform' => $type,
|
||
'apptype' => $platform
|
||
])->find();
|
||
|
||
$openid = $oauth ? $oauth->openid : '';
|
||
}
|
||
|
||
if (!$openid) {
|
||
// 缺少 openid
|
||
$this->error("授权过期,请您重新授权登录");
|
||
}
|
||
}
|
||
|
||
//订单号
|
||
$out_trade_no = $order_no;
|
||
|
||
//订单标题
|
||
$title = '课程订单['.$out_trade_no."]支付";
|
||
|
||
//回调链接
|
||
$notifyurl = $this->request->root(true) . '/api/school/pay/notifyx/paytype/' . $type. '/platform/' . $method;
|
||
$returnurl = $this->request->root(true) . '/api/school/pay/returnx/paytype/' . $type . '/out_trade_no/' . $out_trade_no;
|
||
|
||
$response = Service::submitOrder($amount, $out_trade_no, $type, $title, $notifyurl, $returnurl, $method, $openid);
|
||
|
||
$this->success('查询成功', ["paydata"=>$response]);
|
||
|
||
// return $response;
|
||
}
|
||
|
||
/**
|
||
* @ApiTitle( 第三方支付支付成功回调)
|
||
* @ApiSummary(第三方支付成功回调)
|
||
* @ApiRoute(/api/school/pay/notifyx)
|
||
* @ApiMethod(GET)
|
||
* @ApiReturn({
|
||
*
|
||
*})
|
||
*/
|
||
public function notifyx()
|
||
{
|
||
$paytype = $this->request->param('paytype');
|
||
$platform = $this->request->param('platform');
|
||
$pay = Service::checkNotify($paytype);
|
||
if (!$pay) {
|
||
return json(['code' => 'FAIL', 'message' => '失败'], 500, ['Content-Type' => 'application/json']);
|
||
}
|
||
$payment = $paytype;
|
||
// 获取回调数据,V3和V2的回调接收不同
|
||
$data = Service::isVersionV3() ? $pay->callback() : $pay->verify();
|
||
|
||
|
||
|
||
Log::write('notifyx-result:'. json_encode($data));
|
||
|
||
$out_trade_no = $data['out_trade_no'];
|
||
$out_refund_no = $data['out_biz_no'] ?? '';
|
||
|
||
|
||
|
||
// 判断是否是支付宝退款(支付宝退款成功会通知该接口)
|
||
if ($paytype == 'alipay' // 支付宝支付
|
||
&& $data['notify_type'] == 'trade_status_sync' // 同步交易状态
|
||
&& $data['trade_status'] == 'TRADE_CLOSED' // 交易关闭
|
||
&& $out_refund_no // 退款单号
|
||
) {
|
||
// 退款回调
|
||
|
||
// $this->refundFinish($out_trade_no, $out_refund_no,$platform);
|
||
|
||
return $pay->success()->send();
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
// 判断支付宝微信是否是支付成功状态,如果不是,直接返回响应
|
||
if ($payment == 'alipay' && $data['trade_status'] != 'TRADE_SUCCESS') {
|
||
// 不是交易成功的通知,直接返回成功
|
||
return $pay->success()->send();
|
||
}
|
||
if ($payment == 'wechat' && ($data['result_code'] != 'SUCCESS' || $data['return_code'] != 'SUCCESS')) {
|
||
// 微信交易未成功,返回 false,让微信再次通知
|
||
return false;
|
||
}
|
||
|
||
|
||
try {
|
||
//微信支付V3返回和V2不同
|
||
if (Service::isVersionV3() && $paytype === 'wechat') {
|
||
$data = $data['resource']['ciphertext'];
|
||
$data['total_fee'] = $data['amount']['total'];
|
||
}
|
||
|
||
\think\Log::record($data);
|
||
|
||
$payamount = $paytype == 'alipay' ? $data['total_amount'] : $data['total_fee'] / 100;
|
||
$out_trade_no = $data['out_trade_no'];
|
||
|
||
\think\Log::record("回调成功,订单号:{$out_trade_no},金额:{$payamount}");
|
||
|
||
//你可以在此编写订单逻辑
|
||
|
||
// 支付成功流程
|
||
//获取支付金额、订单号
|
||
$pay_fee = $payment == 'alipay' ? $data['total_amount'] : $data['total_fee'] / 100;
|
||
|
||
//你可以在此编写订单逻辑
|
||
$order = OrderModel::getNopayOrder($out_trade_no);
|
||
|
||
if (!$order || $order["status"] != '0') {
|
||
// 订单不存在,或者订单已支付
|
||
return $pay->success()->send();
|
||
}
|
||
$notify = [
|
||
'order_no' => $data['out_trade_no'],
|
||
'transaction_id' => $payment == 'alipay' ? $data['trade_no'] : $data['transaction_id'],
|
||
'notify_time' => date('Y-m-d H:i:s', strtotime($data['time_end'])),
|
||
'buyer_email' => $payment == 'alipay' ? $data['buyer_logon_id'] : $data['openid'],
|
||
'payment_json' => json_encode($data->all()),
|
||
'pay_fee' => $pay_fee,
|
||
'pay_type' => $payment, // 支付方式
|
||
'platform' => $platform,
|
||
];
|
||
|
||
$this->model->paySuccess($order['order_no'],$notify,$pay_fee,true,true);
|
||
|
||
|
||
|
||
} catch (Exception $e) {
|
||
\think\Log::record("回调逻辑处理错误:" . $e->getMessage(), "error");
|
||
}
|
||
|
||
//下面这句必须要执行,且在此之前不能有任何输出
|
||
if (Service::isVersionV3()) {
|
||
return $pay->success()->getBody()->getContents();
|
||
} else {
|
||
return $pay->success()->send();
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 支付返回,网页支付版本(小程序忽略)
|
||
*/
|
||
public function returnx()
|
||
{
|
||
$paytype = $this->request->param('paytype');
|
||
$out_trade_no = $this->request->param('out_trade_no');
|
||
$pay = Service::checkReturn($paytype);
|
||
if (!$pay) {
|
||
$this->error('签名错误', '');
|
||
}
|
||
|
||
//你可以在这里定义你的提示信息,但切记不可在此编写逻辑
|
||
$this->success("请返回网站查看支付结果", addon_url("epay/index/index"));
|
||
}
|
||
|
||
|
||
|
||
} |