/** * 重新支付 * @return string * @author zhengqian@dajiayao.cc */ public function rePay() { $buyerId = $this->buyerId; $wxUser = Buyer::find($buyerId)->wxUser; if (!$wxUser) { return RestHelp::encodeResult(24000, "user illegality"); } $inputData = $this->inputData->all(); $validator = Validator::make($inputData, ['orderNumber' => 'required']); if ($validator->fails()) { return RestHelp::parametersIllegal($validator->messages()->first()); } $objOrder = Order::where('order_number', $inputData['orderNumber'])->first(); $objShop = Shop::find($objOrder->shop_id); if (!$objShop) { return RestHelp::encodeResult(21000, sprintf("shop short id %s not found in db", $objOrder->shop_id)); } //查找价格 $itemTotal = $objOrder->item_total; $grandTotal = $objOrder->grand_total; $payment = new Payment(); $payment->serial_number = OrderHelper::getPaymentSerialNumber(1); $payment->payment_number = ''; $payment->order_id = $objOrder->id; $payment->order_number = $inputData['orderNumber']; $payment->buyer_id = $buyerId; $payment->amount = $itemTotal; $payment->channel = Payment::PAYMENT_CHANNEL_PXX; $payment->type = Payment::PAYMENT_TYPE_WX; $payment->status = Order::PAY_STATUS_NO; $payment->save(); $subject = ''; //32 $body = ''; //128 foreach ($objOrder->orderItems as $orderItem) { $subject .= $orderItem->items->title . "*" . $orderItem->items->spec . "*" . $orderItem->quantity . ","; $body .= $orderItem->items->title . $orderItem->items->spec . $orderItem->quantity; } try { \Pingpp\Pingpp::setApiKey('sk_live_3dKEivmziedjzitFhaHL7gYF'); $ch = \Pingpp\Charge::create(array('order_no' => $payment->serial_number, 'app' => array('id' => 'app_XTOW5SXTWLGCGKef'), 'channel' => 'wx_pub', 'amount' => $grandTotal * 100, 'client_ip' => $this->inputData->ip(), 'currency' => 'cny', 'subject' => mb_substr($subject, 0, 32), 'body' => mb_substr($body, 0, 128), 'extra' => array('open_id' => $wxUser->openid))); } catch (\Exception $e) { return RestHelp::encodeResult(22003, $e->getMessage(), ['orderNum' => $inputData['orderNumber']]); } //写入paytmentLOg $paymentLog = new PaymentLog(); $paymentLog->payment_id = $payment->id; $paymentLog->channel = Payment::PAYMENT_CHANNEL_PXX; $paymentLog->request_data = $ch; $paymentLog->respond_data = ''; $paymentLog->save(); //保存支付流水号 $payment->payment_number = json_decode($ch)->id; $payment->save(); return RestHelp::success(['orderNumber' => $inputData['orderNumber'], 'paymentNumber' => $payment->serial_number, 'charge' => json_decode($ch, true)]); }
/** * * 生成流水号算法:第1位为支付渠道,2-7位为日期,8-17位是当日流水经过Skip32加密过的流水号,可解密出真实流水。最后3位为随机数。 * @param $prefix 1位数字,标记支付类型.1:微信支付,2:支付宝支付,3:银联支付 * @return string */ public static function getPaymentSerialNumber($prefix) { $timestamp = time(); $datePrefix = date('ymd', $timestamp); $key = self::CACHE_KEY_PAYMENT_COUNT . $datePrefix; if (!Cache::has($key)) { $counter = Payment::getTodayCount(); $expiresAt = Carbon::now()->addMinutes(1440); Cache::put($key, $counter, $expiresAt); } $value = Cache::increment($key); $value = str_pad(Skip32::encrypt(self::ENCRYPTED_KEY, $value), 10, '0', STR_PAD_LEFT); return $prefix . $datePrefix . $value . str_pad(rand(0, 999), 3, '0', STR_PAD_LEFT); }
/** * 生成订单 * @return string * @author zhengqian@dajiayao.cc */ public function create() { // $inputData = $this->inputData->all(); $buyerId = $this->buyerId; $wxUser = Buyer::find($buyerId)->wxUser; if (!$wxUser) { return RestHelp::encodeResult(24000, "user illegality"); } $inputData = json_decode(file_get_contents("php://input"), true); $validator = Validator::make($inputData, ['shopShortId' => 'required', 'items' => 'required', 'deliverAddressId' => 'required', 'paymentType' => 'required', "shopType" => '', 'orderNumber' => '', "isAnonymous" => 'required|Boolean']); if ($validator->fails()) { return RestHelp::parametersIllegal($validator->messages()->first()); } if (!isset($inputData['items']) or !is_array($inputData['items'])) { return RestHelp::encodeResult(23003, 'item must be array'); } $objShop = Shop::getShopByShort($inputData['shopShortId']); if (!$objShop) { return RestHelp::encodeResult(21000, sprintf("shop short id %s not found in db", $inputData['shopShortId'])); } $deliver = BuyerAddress::find($inputData['deliverAddressId']); if (!$deliver) { return RestHelp::encodeResult(23001, sprintf("deliver address id: %s not found in db", $inputData['deliverAddressId'])); } if (!isset($inputData['orderNumber'])) { $orderNumber = OrderHelper::getOrderSerialNumber(); } else { $orderNumber = $inputData['orderNumber']; } $deliverAddressId = $inputData['deliverAddressId']; $shopId = $objShop->id; $itemTotal = 0; $postageFlag = 0; $shelfItems = $objShop->getItemsOnShelf(); //检查商品合法性、库存等等 foreach ($inputData['items'] as $item) { if (!array_key_exists('id', $item) or !array_key_exists('count', $item)) { return RestHelp::encodeResult(23005, "items not correct"); } $objItem = Item::find($item['id']); $itemTotal += $objItem->price * $item['count']; if ($objItem->postage_type == Item::POSTAGE_TYPE_BUYER) { $postageFlag++; } if ($objItem->sale_status == Item::SALE_STATUS_NO) { return RestHelp::encodeResult(23006, sprintf("%s已停售", $objItem->title)); } if ($objItem->shelf_status == Item::SHELF_STATUS_NO or !array_key_exists($objItem->id, $shelfItems)) { return RestHelp::encodeResult(23006, sprintf("%s已下架", $objItem->title)); } //库存 if ($objItem->stock < $item['count']) { return RestHelp::encodeResult(23006, sprintf("%s库存不足", $objItem->title)); } } $postage = $postageFlag ? $this->settingService->getSettingByKey(Setting::KEY_ORDER_POSTAGE)->value : 0; $grandTotal = $itemTotal + $postage; $sessionTotal = WxUserKv::getValue(Buyer::find($this->buyerId)->wxUser->id, WxUserKv::BUYER_CHECK_PRICE); if ((string) $sessionTotal != (string) $grandTotal) { return RestHelp::encodeResult(22002, "illegal operation"); } $discount = 0; $orderType = Order::PAYMENT_TYPE_WX; //如果传入了订单号 if (isset($inputData['orderNumber'])) { //update $objOrder = Order::where('order_number', $inputData['orderNumber'])->first(); if (!$objOrder) { return RestHelp::encodeResult(22001, "the order not found"); } //new try { $orderId = $this->orderService->update($objOrder, $itemTotal, $grandTotal, $discount, $grandTotal - $discount, $inputData['isAnonymous'] ? 1 : 0, $postage, $orderType, $deliverAddressId); } catch (\Exception $e) { return RestHelp::encodeResult(23004, $e->getMessage()); } } else { //new try { $orderId = $this->orderService->create($orderNumber, $shopId, $this->buyerId, $itemTotal, $grandTotal, $discount, $grandTotal - $discount, $postage, $orderType, $deliverAddressId, $inputData['isAnonymous'] ? 1 : 0, null, null); } catch (\Exception $e) { return RestHelp::encodeResult(23004, $e->getMessage()); } //减少库存 $commissonTotal = 0; foreach ($inputData['items'] as $item) { $objItem = Item::find($item['id']); $objItem->stock -= $item['count']; $objItem->save(); //计算挨个佣金 $commissonTotal += $objItem->commission * $item['count']; } //生成佣金表数据 $commisson = OrderCommission::firstOrNew(['order_id' => $orderId]); $commisson->amount = $objShop->is_direct_sale == 'Y' ? 0 : $commissonTotal; $commisson->status = OrderCommission::STATUS_UNCONFIRMED; $commisson->save(); //生成seller commisson $sellerCommission = SellerCommission::firstOrNew(['order_id' => $orderId, 'seller_id' => $objShop->seller_id]); $sellerCommission->amount = $objShop->is_direct_sale == 'Y' ? 0 : $commissonTotal; $sellerCommission->status = SellerCommission::STATUS_UNCONFIRMED; $sellerCommission->save(); } $subject = ''; //32 $body = ''; //128 $itemIdList = \DB::table('order_items')->where('order_id', $orderId)->lists('item_id'); foreach ($inputData['items'] as $item) { if (isset($inputData['orderNumber'])) { $orderItem = OrderItem::where('order_id', $orderId)->where('item_id', $item['id'])->first(); $quantity = $orderItem ? $orderItem->quantity : 0; $count = $item['count']; $balance = $count - $quantity; $objItem = Item::find($item['id']); $objItem->stock -= $balance; $objItem->save(); OrderItem::where('order_id', $orderId)->where('item_id', $item['id'])->forceDelete(); //如果支付失败,返回修改删除了某个商品,则恢复库存 Step 1 @author zhengqian foreach ($itemIdList as $k => $itid) { if ($item['id'] == $itid) { unset($itemIdList[$k]); } } } $orderItem = new OrderItem(); $orderItem->order_id = $orderId; $orderItem->item_id = $item['id']; $objItem = Item::find($item['id']); $orderItem->name = $objItem->name; $subject .= $objItem->title . "*" . $objItem->spec . "*" . $objItem->{$item}['count'] . ","; $body .= $objItem->title . $objItem->spec . $objItem->{$item}['count']; $orderItem->title = $objItem->title; $orderItem->code = $objItem->code; $orderItem->barcode = $objItem->barcode; $orderItem->type = ItemType::find($objItem->type_id)->name; $orderItem->quantity = $item['count']; $orderItem->price = $objItem->price; $orderItem->item_total = $objItem->price * $item['count']; $commissionsRate = $this->settingService->getSettingByKey(Setting::KEY_COMMISSIONS_RATE); if (!$commissionsRate) { $commissionsRate = Setting::DEFAULT_KEY_COMMISSIONS_RATE; } else { $commissionsRate = $commissionsRate->value; } $orderItem->commission = $orderItem->item_total * $commissionsRate; $orderItem->save(); } //如果支付失败,返回修改删除了某个商品,则恢复库存 Step 2 @author zhengqian if (isset($inputData['orderNumber'])) { foreach ($itemIdList as $itid) { $orderItem = OrderItem::where('order_id', $orderId)->where('item_id', $itid)->first(); $quantity = $orderItem->quantity; $objItem = Item::find($itid); $objItem->stock += $quantity; $objItem->save(); OrderItem::where('order_id', $orderId)->where('item_id', $itid)->forceDelete(); } } $payment = new Payment(); $payment->serial_number = OrderHelper::getPaymentSerialNumber(1); $payment->payment_number = ''; $payment->order_id = $orderId; $payment->order_number = Order::find($orderId)->order_number; $payment->buyer_id = $this->buyerId; $payment->amount = $itemTotal; $payment->channel = Payment::PAYMENT_CHANNEL_PXX; $payment->type = Payment::PAYMENT_TYPE_WX; $payment->status = Order::PAY_STATUS_NO; $payment->save(); try { \Pingpp\Pingpp::setApiKey('sk_live_3dKEivmziedjzitFhaHL7gYF'); $ch = \Pingpp\Charge::create(array('order_no' => $payment->serial_number, 'app' => array('id' => 'app_XTOW5SXTWLGCGKef'), 'channel' => 'wx_pub', 'amount' => $sessionTotal * 100, 'client_ip' => $this->inputData->ip(), 'currency' => 'cny', 'subject' => mb_substr($subject, 0, 32), 'body' => mb_substr($body, 0, 128), 'extra' => array('open_id' => $wxUser->openid))); } catch (\Exception $e) { return RestHelp::encodeResult(22003, $e->getMessage(), ['orderNum' => $orderNumber]); } //写入paytmentLOg $paymentLog = new PaymentLog(); $paymentLog->payment_id = $payment->id; $paymentLog->channel = Payment::PAYMENT_CHANNEL_PXX; $paymentLog->request_data = $ch; $paymentLog->respond_data = ''; $paymentLog->save(); //保存支付流水号 $payment->payment_number = json_decode($ch)->id; $payment->save(); return RestHelp::success(['orderNumber' => $orderNumber, 'paymentNumber' => $payment->serial_number, 'charge' => json_decode($ch, true)]); }
/** * 用于接收 p++ 支付结果的回调地址 * @author zhengqian@dajiayao.cc */ public function payCallBack() { $input = file_get_contents("php://input"); \Log::info(sprintf("input: %s", $input)); $objPayResult = json_decode($input); $payment = Payment::where('payment_number', $objPayResult->id)->first(); if (!$payment) { \Log::info(sprintf("the payment_number : %s not found in db", $objPayResult->id)); return; } //写入支付日志 $paymentLog = PaymentLog::where('payment_id', $payment->id)->first(); if (!$paymentLog) { return; } $order = $payment->order; $paymentLog->respond_data = $input; $paymentLog->save(); if ($objPayResult->paid == true) { //修改订单状态 $order->payment_serial_number = $payment->serial_number; $order->payment_id = $payment->id; $order->payment_status = Order::PAY_STATUS_YES; $order->status = Order::STATUS_TO_DELIVER; $order->save(); //支付状态 $payment->status = Payment::PAYMENT_STATUS_SUCCESS; $payment->save(); //佣金状态 $commission = OrderCommission::where('order_id', $order->id)->first(); if (!$commission) { return; } $commission->status = OrderCommission::STATUS_CONFIRMED; $commission->save(); //seller commission $sellerCommission = SellerCommission::firstOrNew(['order_id' => $order->id, 'seller_id' => $order->shop->seller_id, 'amount' => $commission->amount]); $sellerCommission->status = SellerCommission::STATUS_CONFIRMED; $sellerCommission->save(); //将销售额存入redis $orderItems = $order->orderItems; foreach ($orderItems as $orderItem) { $quantity = $orderItem->quantity; $this->redis->incrby("dajiayao:mall:item:sellcount:" . $orderItem->item_id, $quantity); $wxUser = $orderItem->order->buyer->wxUser; $header = $wxUser->headimgurl; if ($order->is_anonymous == 1 or !$header) { continue; } $this->redis->sadd("dajiayao:mall:item:buyers:" . $orderItem->item_id, json_encode(['name' => $wxUser->nickname, 'avatar' => $header])); } //微信消息推送 $this->buyerService->sendNewOrderMsg($order); $this->sellerService->sendPaidMsg($order); } elseif ($objPayResult->paid == false) { //支付状态 $payment->status = Payment::PAYMENT_STATUS_FAIL; $payment->save(); } else { return; } return "success"; }