以下是代码
namespace app\api\service;
use app\api\model\Order as OrderModel;
use app\lib\enum\OrderStatusEnum;
use app\lib\exception\OrderException;
use app\lib\exception\TokenException;
use think\Exception;
use think\Loader;
use think\Log;
Loader::import(‘WxPay.WxPay’, EXTEND_PATH, ‘.Api.php’);
class Pay
{
private $orderNo;
private $orderID;
function __construct($orderID)
{
if (!$orderID)
{
throw new Exception(‘订单号不允许为NULL’);
}
$this->orderID = $orderID;
}
public function pay()
{
$this->checkOrderValid();
$order = new Order(); //这里是service的 Order
$status = $order->checkOrderStock($this->orderID);
if (!$status[‘pass’])
{
return $status;
}
return $this->makeWxPreOrder($status[‘orderPrice’]);
}
// 构建微信支付订单信息
private function makeWxPreOrder($totalPrice)
{
$openid = Token::getCurrentTokenVar(‘openid’);
if (!$openid)
{
throw new TokenException();
}
$wxOrderData = new \WxPayUnifiedOrder();
$wxOrderData->SetOut_trade_no($this->orderNo); //订单号
$wxOrderData->SetTrade_type(‘JSAPI’); //交易类型
$wxOrderData->SetTotal_fee($totalPrice * 100); //金额
$wxOrderData->SetBody(‘测试’); //设置商品或支付单简要描述
$wxOrderData->SetOpenid($openid); //用户的openid
$wxOrderData->SetNotify_url(config(‘secure.pay_back_url’)); //设置接收微信支付异步通知回调地址
return $this->getPaySignature($wxOrderData);
}
//向微信请求订单号并生成签名
/**
* @param $wxOrderData
* @return array
*/
private function getPaySignature($wxOrderData)
{
$wxOrder = \WxPayApi::unifiedOrder($wxOrderData);
// 失败时不会返回result_code
if($wxOrder[‘return_code’] != ‘SUCCESS’ || $wxOrder[‘result_code’] !=‘SUCCESS’){
//dump($wxOrder);
Log::record($wxOrder,‘error’);
Log::record(‘获取预支付订单失败’,‘error’);
//throw new Exception(‘获取预支付订单失败’);
}
$this->recordPreOrder($wxOrder);
$signature = $this->sign($wxOrder);
return $signature;
}
private function recordPreOrder($wxOrder){
// 必须是update,每次用户取消支付后再次对同一订单支付,prepay_id是不同的
OrderModel::where(‘id’, ‘=’, $this->orderID)
->update([‘prepay_id’ => $wxOrder[‘prepay_id’]]);
}
// 签名
private function sign($wxOrder)
{
$jsApiPayData = new \WxPayJsApiPay();
$jsApiPayData->SetAppid(config(‘wx.app_id’));
$jsApiPayData->SetTimeStamp((string)time());
$rand = md5(time() . mt_rand(0, 1000));
$jsApiPayData->SetNonceStr($rand);
$jsApiPayData->SetPackage(‘prepay_id=’ . $wxOrder[‘prepay_id’]);
$jsApiPayData->SetSignType(‘md5’);
$sign = $jsApiPayData->MakeSign();
$rawValues = $jsApiPayData->GetValues(); //数组
$rawValues[‘paySign’] = $sign;
unset($rawValues[‘appId’]);
return $rawValues;
}
/**
* @return bool
* @throws OrderException
* @throws TokenException
*/
private function checkOrderValid()
{
$order = OrderModel::where(‘id’, ‘=’, $this->orderID)
->find();
if (!$order)
{
throw new OrderException();
}
// $currentUid = Token::getCurrentUid();
if(!Token::isValidOperate($order->user_id))
{
throw new TokenException(
[
‘msg’ => ‘订单与用户不匹配’,
‘errorCode’ => 10003
]);
}
if($order->status != OrderStatusEnum::UNPAID){
throw new OrderException([
‘msg’ => ‘订单已支付过啦’,
‘errorCode’ => 80003,
‘code’ => 400
]);
}
$this->orderNo = $order->order_no;
return true;
}
}