위챗 소프로그램 개발 기교 모음(5): 지급 개시
7928 단어 위챗 소프로그램 개발 기교 모음집
클라이언트 발기 요청 서버 검사 주문 유효성, 재고 생성 서명 위챗 클라이언트에 반환 지불 리셋 처리 리셋
'지급 상태 업데이트
1. 주문 유효성 검사
private function checkOrderValid()
{
//
$order = OrderModel::where('id','=',$this->orderID)->find();
if (!$order){
throw new OrderException();
}
//
if (!TokenService::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;
}
public static function isValidOperate($checkedUID)
{
if (!$checkedUID){
throw new Exception(' uid ');
}
$currentOperateUID = self::getCurrentUid();
if($currentOperateUID == $checkedUID){
return true;
}
return false;
}
2. 재고 검사
$orderService = new OrderService();
//
$status = $orderService->checkOrderStock($this->orderID);
if (!$status['pass']){
return $status;//
}
public function checkOrderStock($orderID)
{
$oProducts = OrderProduct::where('order_id','=',$orderID)->select();
$this->oProducts = $oProducts;
$this->products = $this->getProductsByOrder($oProducts);
$status = $this->getOrderStatus();
return $status;
}
private function getProductsByOrder($oProducts)
{
$oPIDs = [];
foreach ($oProducts as $oProduct) {
array_push($oPIDs,$oProduct['product_id']);
}
$products = Product::all($oPIDs)
->visible(['id','price','stock','name','main_img_url'])
->toArray();
return $products;
}
private function getOrderStatus()
{
$status = [
'pass' => true,
'orderPrice' => 0,//
'totalCount' => 0,//
'pStatusArray' => [],//
];
foreach ($this->oProducts as $oProduct) {
$pStatus = $this->getProductStatus($oProduct['product_id'],$oProduct['count'],$this->products);
if (!$pStatus['haveStock']){
$status['pass'] = false;
}
$status['orderPrice'] += $pStatus['totalPrice'];
$status['totalCount'] += $pStatus['count'];
array_push($status['pStatusArray'],$pStatus);
}
return $status;
}
private function getProductStatus($oPID,$oCount,$products)
{
$pIndex = -1;
//
$pStatus = [
'id' => null,
'haveStock' => false,
'count' => 0,
'name' => '',
'totalPrice' => 0, //
];
for ($i = 0; $i'id '.$oPID.' , ']);
}else{
$product = $products[$pIndex];
$pStatus['id'] = $product['id'];
$pStatus['name'] = $product['name'];
$pStatus['count'] = $oCount;
$pStatus['totalPrice'] = $product['price'] * $oCount;
if ($product['stock'] - $oCount >= 0){
$pStatus['haveStock'] = true;
}
}
return $pStatus;
}
3. 결제 시작
private function makeWxPreOrder($totalPrice)
{
$openid = TokenService::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);
$wxOrderData->SetNotify_url(config('secure.pay_back_url'));
return $this->getPaySignature($wxOrderData);
}
private function getPaySignature($wxOrderData)
{
$config = new \WxPayConfig();
$wxOrder = \WxPayApi::unifiedOrder($config,$wxOrderData);
if ($wxOrder['return_code']!='SUCCESS'||$wxOrder['result_code']!='SUCCESS'){
Log::record($wxOrder,'error');
Log::record(' ','error');
}
$this->recordPreOrder($wxOrder);
$signature = $this->sing($wxOrder);
return $signature;
}
private function sing($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($wxOrder['prepay_id='.'prepay_id']);
$jsApiPayData->SetSignType('md5');
$sign = $jsApiPayData->MakeSign();
$rawValues = $jsApiPayData->GetValues();
$rawValues['paySign'] = $sign;
unset($rawValues['appId']);
return $rawValues;
}
private function recordPreOrder($wxOrder)
{
OrderModel::where('id','=',$this->orderID)
->update(['prepay_id'=>$wxOrder['prepay_id']]);
}
4. 클라이언트가 지불하면 위챗 서버는 지불 결과를 우리 서버의 통지 주소로 비동기적으로 되돌려줍니다.상응하는 처리를 하다
public function NotifyProcess($data,&$msg)
{
if($data['result_code'] == 'SUCCESS'){
$orderNo = $data['out_trade_no'];
Db::startTrans();
try{
$order = OrderModel::where('order_no','=',$orderNo)
->lock(true)
->find();
if ($order->status == OrderStatusEnum::UNPAID){
// , ,
$service = new OrderService();
$stockStatus = $service->checkOrderStock($order->id);
if ($stockStatus['pass']){
$this->updateOrderStatus($order->id,true);
$this->reduceStock($stockStatus);
}else{
$this->updateOrderStatus($order->id,false);
}
}
Db::commit();
return true;
}catch (Exception $ex){
Db::rollback();
Log::error($ex);
return false;
}
}else{
return true;
}
}
//
private function updateOrderStatus($orderID,$success)
{
// $success 1 : ;
$status = $success ? OrderStatusEnum::PAID : OrderStatusEnum::PAID_BUT_OUT_OF;
OrderModel::where('id','=',$orderID)->update(['status',$status]);
return true;
}
//
private function reduceStock($stockStatus)
{
foreach ($stockStatus['pStatusArray'] as $singlePStatus) {
Product::where('id','=',$singlePStatus['id'])->setDec('stock',$singlePStatus['count']);
}
return true;
}