简单概括:
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 请求模板发送
↓

模板消息见:
原创文章,转载请标明出处!