简单概括:
1、小程序发起购买,这时把商品id传给后台,检查商品状态是否存在或者库存是否充足,
2、生成订单(这里顺便生成小程序支付核心参数返回给小程序,包括prepay_id),
3、小程序用这些参数进行调用微信支付,支付成功,可以再把prepay_id重新掉接口进行(也可以存数据库等其他办法) 模板推送
确认订单
↓
请求后台 buyNow
public function buyNow($goods_id, $goods_num, $goods_sku_id) { // 商品结算信息 $model = new OrderModel; $order = $model->getBuyNow($this->user, $goods_id, $goods_num, $goods_sku_id); if (!$this->request->isPost()) { return $this->renderSuccess($order); } if ($model->hasError()) { return $this->renderError($model->getError()); } // 创建订单 if ($model->add($this->user['user_id'], $order)) { // 发起微信支付 return $this->renderSuccess([ 'payment' => $this->wxPay($model['order_no'], $this->user['open_id'] , $order['order_pay_price']), 'order_id' => $model['order_id'] ]); } $error = $model->getError() ?: '订单创建失败'; return $this->renderError($error); }
↓
后台创建订单
↓
public function add($user_id, $order) { if (empty($order['address'])) { $this->error = '请先选择收货地址'; return false; } Db::startTrans(); // 记录订单信息 $this->save([ 'user_id' => $user_id, 'wxapp_id' => self::$wxapp_id, 'order_no' => $this->orderNo(), 'total_price' => $order['order_total_price'], 'pay_price' => $order['order_pay_price'], 'express_price' => $order['express_price'], ]); // 订单商品列表 $goodsList = []; // 更新商品库存 (下单减库存) $deductStockData = []; foreach ($order['goods_list'] as $goods) { /* @var Goods $goods */ $goodsList[] = [ 'user_id' => $user_id, 'wxapp_id' => self::$wxapp_id, 'goods_id' => $goods['goods_id'], 'goods_name' => $goods['goods_name'], 'image_id' => $goods['image'][0]['image_id'], 'deduct_stock_type' => $goods['deduct_stock_type'], 'spec_type' => $goods['spec_type'], 'spec_sku_id' => $goods['goods_sku']['spec_sku_id'], 'goods_spec_id' => $goods['goods_sku']['goods_spec_id'], 'goods_attr' => $goods['goods_sku']['goods_attr'], 'content' => $goods['content'], 'goods_no' => $goods['goods_sku']['goods_no'], 'goods_price' => $goods['goods_sku']['goods_price'], 'line_price' => $goods['goods_sku']['line_price'], 'goods_weight' => $goods['goods_sku']['goods_weight'], 'total_num' => $goods['total_num'], 'total_price' => $goods['total_price'], ]; // 下单减库存 $goods['deduct_stock_type'] == 10 && $deductStockData[] = [ 'goods_spec_id' => $goods['goods_sku']['goods_spec_id'], 'stock_num' => ['dec', $goods['total_num']] ]; } // 保存订单商品信息 $this->goods()->saveAll($goodsList); // 更新商品库存 !empty($deductStockData) && (new GoodsSpec)->isUpdate()->saveAll($deductStockData); // 记录收货地址 $this->address()->save([ 'user_id' => $user_id, 'wxapp_id' => self::$wxapp_id, 'name' => $order['address']['name'], 'phone' => $order['address']['phone'], 'province_id' => $order['address']['province_id'], 'city_id' => $order['address']['city_id'], 'region_id' => $order['address']['region_id'], 'detail' => $order['address']['detail'], ]); Db::commit(); return true; }
↓
创建后再生成prepay_id 返回小程序
↓
/** * 构建微信支付 * @param $order_no * @param $open_id * @param $pay_price * @return array * @throws \app\common\exception\BaseException * @throws \think\exception\DbException */ private function wxPay($order_no, $open_id, $pay_price) { $wxConfig = WxappModel::getWxappCache(); $WxPay = new WxPay($wxConfig); return $WxPay->unifiedorder($order_no, $open_id, $pay_price); }
/** * 统一下单API * @param $order_no * @param $openid * @param $total_fee * @return array * @throws BaseException */ public function unifiedorder($order_no, $openid, $total_fee) { // 当前时间 $time = time(); // 生成随机字符串 $nonceStr = md5($time . $openid); // API参数 $params = [ 'appid' => $this->config['app_id'], 'attach' => 'test', 'body' => $order_no, 'mch_id' => $this->config['mchid'], 'nonce_str' => $nonceStr, 'notify_url' => base_url() . 'notice.php', // 异步通知地址 'openid' => $openid, 'out_trade_no' => $order_no, 'spbill_create_ip' => \request()->ip(), 'total_fee' => $total_fee * 100, // 价格:单位分 'trade_type' => 'JSAPI', ]; // 生成签名 $params['sign'] = $this->makeSign($params); // 请求API $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder'; $result = $this->postXmlCurl($this->toXml($params), $url); $prepay = $this->fromXml($result); // 请求失败 if ($prepay['return_code'] === 'FAIL') { throw new BaseException(['msg' => $prepay['return_msg'], 'code' => -10]); } if ($prepay['result_code'] === 'FAIL') { throw new BaseException(['msg' => $prepay['return_msg'], 'code' => -10]); } // 生成 nonce_str 供前端使用 $paySign = $this->makePaySign($params['nonce_str'], $prepay['prepay_id'], $time); return [ 'prepay_id' => $prepay['prepay_id'], 'nonceStr' => $nonceStr, 'timeStamp' => (string)$time, 'paySign' => $paySign ]; }
↓
模板消息在支付完成后将 prepay_id 请求模板发送
↓
模板消息见:
原创文章,转载请标明出处!