|
|
<?php
|
|
|
|
|
|
namespace App\Models;
|
|
|
|
|
|
use App\Customer;
|
|
|
use App\Libs\AlipayF2F;
|
|
|
use App\Manager;
|
|
|
use Illuminate\Support\Facades\Log;
|
|
|
|
|
|
class Refund extends SoftDeletesModel
|
|
|
{
|
|
|
protected $table = "refund";
|
|
|
protected $tryTimes = 3;
|
|
|
|
|
|
public function getPaymentLabelAttribute()
|
|
|
{
|
|
|
$payment_label = $this->payment;
|
|
|
switch ($this->payment) {
|
|
|
case "weixin":
|
|
|
$payment_label = "微信";
|
|
|
break;
|
|
|
case "alipay":
|
|
|
$payment_label = "支付宝";
|
|
|
break;
|
|
|
case "cash":
|
|
|
$payment_label = "现金";
|
|
|
break;
|
|
|
}
|
|
|
return $payment_label;
|
|
|
}
|
|
|
|
|
|
public function customer()
|
|
|
{
|
|
|
return $this->belongsTo(Customer::class);
|
|
|
}
|
|
|
|
|
|
public function manager()
|
|
|
{
|
|
|
return $this->belongsTo(Manager::class);
|
|
|
}
|
|
|
|
|
|
public function order()
|
|
|
{
|
|
|
return $this->belongsTo(Orders::class)->withTrashed();
|
|
|
}
|
|
|
|
|
|
public function patient()
|
|
|
{
|
|
|
return $this->hasOneThrough(Patient::class, Orders::class, "id", "id", "order_id", "patient_id");
|
|
|
}
|
|
|
|
|
|
public function relatedRecharge()
|
|
|
{
|
|
|
return $this->belongsTo(Recharge::class, "recharge_id");
|
|
|
}
|
|
|
|
|
|
public function getSerial()
|
|
|
{
|
|
|
if ($this->serial) {
|
|
|
return $this;
|
|
|
}
|
|
|
$serial = date("YmdHis", strtotime($this->created_at)) . sprintf("%06d", $this->id);
|
|
|
$this->update(["serial" => $serial]);
|
|
|
return $this;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 计划任务自动退款
|
|
|
*/
|
|
|
public function autoRefund()
|
|
|
{
|
|
|
$threshold = 5;
|
|
|
$refunds = $this->with("relatedRecharge")->whereNull("paid_at")->where("payment", "<>", "cash")->where("try_times", "<", $this->tryTimes)->limit($threshold)->get();
|
|
|
|
|
|
foreach ($refunds as $refund) {
|
|
|
switch ($refund->relatedRecharge->payment) {
|
|
|
case "weixin":
|
|
|
$refund->weixinRefund();
|
|
|
break;
|
|
|
case "alipay":
|
|
|
$refund->alipayRefund();
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public function alipayRefund()
|
|
|
{
|
|
|
return (new AlipayF2F())->refund($this);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
*
|
|
|
* 申请微信退款,WxPayRefund中out_trade_no、transaction_id至少填一个且
|
|
|
*/
|
|
|
public function weixinRefund()
|
|
|
{
|
|
|
$order = $this->order;
|
|
|
$url = "https://api.mch.weixin.qq.com/secapi/pay/refund";
|
|
|
$CommonUtilPub = new \CommonUtilPub($order->project_id, $this->merchant_id);
|
|
|
$WxPayConfPub = new \WxPayConfPub($order->project_id, $this->merchant_id);
|
|
|
$inputObj = [];
|
|
|
$inputObj["transaction_id"] = $this->relatedRecharge->payment_serial;
|
|
|
$inputObj["out_refund_no"] = $this->serial;
|
|
|
$inputObj["total_fee"] = $this->relatedRecharge->money * 100;
|
|
|
$inputObj["refund_fee"] = $this->money * 100;
|
|
|
$inputObj["nonce_str"] = $CommonUtilPub->createNoncestr();
|
|
|
$inputObj["appid"] = $WxPayConfPub::$APPID;
|
|
|
$inputObj["mch_id"] = $WxPayConfPub::$MCHID;
|
|
|
$inputObj["sign"] = $CommonUtilPub->getSign($inputObj);
|
|
|
|
|
|
$xml = $CommonUtilPub->arrayToXml($inputObj);
|
|
|
$result = $CommonUtilPub->postXmlSSLCurl($xml, $url);
|
|
|
|
|
|
$this->increment("try_times");
|
|
|
try {
|
|
|
$result = $CommonUtilPub->xmlToArray($result);
|
|
|
|
|
|
if ($result["result_code"] == "SUCCESS") {
|
|
|
dump("退款成功");
|
|
|
$this->update([
|
|
|
"payment_serial" => $result["refund_id"],
|
|
|
"paid_at" => date("Y-m-d H:i:s")
|
|
|
]);
|
|
|
} else {
|
|
|
dump("退款失败");
|
|
|
if ($result["err_code"] == "NOTENOUGH") {
|
|
|
$this->decrement("try_times");
|
|
|
}
|
|
|
}
|
|
|
dump($result);
|
|
|
} catch (\Exception $exception) {
|
|
|
$msg = "在线退款失败,原因:" . $exception->getMessage();
|
|
|
Log::info($msg);
|
|
|
dd($msg);
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
}
|