注册服务号,需进行微信认证,此时需缴费 300 元/年,必须是认证成功的服务号才能开通微信支付。
1、登录 https://pay.weixin.qq.com/index.php/core/home/login?return_url=https%3A%2F%2Fpay.weixin.qq.com%2Findex.php%2Fextend%2Fpay_setting%2Fma
,
点击 接入微信
,点击 注册微信支付商户号
,按步骤 创建申请单
–填写商户资料
–确认提交
即可。 <按提示进行操作即可,步骤无比繁琐>
2、管理员微信号关注 微信支付商家助手
,以上操作步骤完成并通过后,商家助手会收到 入驻申请进展通知---待签约
,用管理员手机点进去,扫脸确认签约即可,完成后商家助手会收到 入驻成功
信息。
3、接下来完成 APPID授权管理
,登录到微信服务号首页,找到 设置与开发---接口权限
,在右边找到 微信支付接口---未获得
,点击 申请
。在 待关联商户号
一栏中,点击 确认
,同意授权即可。
此时在 已关联商户号
一栏中显示对应内容,返回 接口权限
页面,查看右边的 微信支付接口
显示 已获得
。
1、微信商户平台(pay.weixin.qq.com)–>账户中心–>账户设置–>API安全–>设置API密钥,密钥需下载下来放到项目的根目录。接下来设置 APIv2
秘钥、设置 APIv3
秘钥。
2、产品中心–>开发配置–>支付配置,在此添加 JSAPI支付授权目录
,如下图所示:
3、关联服务号,如下图:
4、登录微信公众服务号后台,对公众号进行功能设置,如下图:
1、打开 easyWeChat
官网,找到 Laravel 5 拓展包,按步骤安装 laravel-wechat
。
// 安装easyWeChat包
composer require "overtrue/laravel-wechat:~5.1"
// 创建配置文件
php artisan vendor:publish --provider="Overtrue\LaravelWeChat\ServiceProvider"
在
composer.json
中显示的laravel-wechat
版本号为"overtrue/laravel-wechat": "^5.1",
。
在项目的
config
文件夹中自动生成wechat.php
文件。
2、在 config/wechat.php
中打开微信支付的配置,然后在 .env
文件中做如下配置:
WECHAT_DEBUG=true
# 此配置是实现微信公众号登录认证的配置
WECHAT_OFFICIAL_ACCOUNT_APPID='微信公众号的APPID'
WECHAT_OFFICIAL_ACCOUNT_SECRET='微信公众号的开发者密码(AppSecret)'
WECHAT_OFFICIAL_ACCOUNT_TOKEN='随意字符串'
WECHAT_PAYMENT_APPID='微信公众号APPID'
WECHAT_PAYMENT_MCH_ID='微信支付商户号'
WECHAT_PAYMENT_KEY='Hubei***********8'
3、添加下单和支付路由:
Route::prefix('order')->group(function () {
// 下单
Route::post('/', 'OrderController@store');
// 支付
Route::get('/pay/{id}', 'OrderController@pay');
});
4、创建订单的控制器方法和模型以及数据表 orders
php artisan make:controller OrderController
php artisan make:model Models/Order
// 模型里面添加黑名单
protected $guarded = [];
// orders 表的字段,以下只是范例,可根据需求自行添加
id、customer_id、out_trade_no、status、total_price、created_at、pay_time、updated_at
我的表结构如下:
5、在 Order
控制器里面的 store
方法,代码如下:
use App\Models\Shop\Address;
use App\Models\Shop\Cart;
use App\Models\Shop\Order;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
// 下单
function store(Request $request)
{
$carts = Cart::with('product')->where('customer_id', session('wechat.customer.id'))->get();
// 防止用户使用微信的后退按钮,重新提交订单,导致出现没有数据的订单
if ($carts->isEmpty()) {
return ['status' => 0, 'info' => ''];
}
$count = Cart::count_cart();
$total_price = $count['total_price'];
DB::beginTransaction();
try {
//生成订单
$order = Order::create([
'out_trade_no'=> Order::make_orderNo(),
'customer_id' => session('wechat.customer.id'),
'total_price' => $total_price,
'status' => 1
]);
//订单地址
$address = Address::find($request->address_id);
$order->address()->create([
'province' => $address['province'],
'city' => $address['city'],
'area' => $address['area'],
'detail' => $address['detail'],
'name' => $address['name'],
'tel' => $address['tel'],
]);
$carts = Cart::with('product')->where('customer_id', session('wechat.customer.id'))->get();
foreach ($carts as $cart) {
//判断库存是否足够
if ($cart->product->stock != '-1' and $cart->product->stock - $cart->num < 0) {
throw new \Exception('商品' . $cart->product->name . ", 目前仅剩下" . $cart->product->stock . " 件. \n请返回购物车, 修改订单后再下单!");
}
//削减库存数量
if ($cart->product->stock != '-1') {
$cart->product->decrement('stock', $cart->num);
}
//插入订单商品表
$order->order_products()->create([
'product_id' => $cart->product_id,
'num' => $cart->num
]);
}
//清空购物车
Cart::where('customer_id', session('wechat.customer.id'))->delete();
} catch (\Exception $e) {
//echo $e->getMessage();
DB::rollback();
return ['status' => 0, 'info' => $e->getMessage()];
}
DB::commit();
return ['status' => 1, 'order_id' => $order->id];
}
6、在 Order
控制器里面的 pay
方法,代码如下:
use App\Models\Shop\Order;
use EasyWeChat;
// 微信支付
function pay($id)
{
$payment = EasyWeChat::payment();
// 第 1 步:查询订单并计算金额
$order = Order::with('address')->find($id);
// 第 2 步:统一下单
$result = $payment->order->unify([
'body' => '测试支付',
'out_trade_no' => $order->out_trade_no,
'total_fee' => $order->total_price * 100,
'notify_url' => 'https://shop.***.com/order/notify', // 支付结果通知网址
'trade_type' => 'JSAPI',
'openid' => session('wechat.customer.openid'),
]);
// return $result; // 打印$result看是否有结果
// 第 3 步:JSSDK
if ($result['result_code'] == 'SUCCESS' && $result['return_code'] == 'SUCCESS') {
$prepayId = $result['prepay_id'];
$jssdk = $payment->jssdk;
$json = $jssdk->sdkConfig($prepayId);
// return $json; // 打印$json看是否有结果
return view('wechat.order.show_pay', compact('order', 'json'));
} else {
return $result;
}
}
接下来,我们来测试一下上述代码,打印 return $result;
。打开 微信开发者工具
,进入商城首页,依次添加商品到购物车、选择地址、下单,会得到如下图结果:
继续测试,打印 return $json;
。就在上图结果中刷新地址,你会得到如下结果:
7、在前端页面底部增加 js
调用代码如下:
<script>
$(function () {
$("#pay").click(function () {
if (typeof WeixinJSBridge === 'undefined') {
alert('请在微信在打开页面!');
return false;
}
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {!! json_encode($json) !!}, function (res) {
switch (res.err_msg) {
case 'get_brand_wcpay_request:cancel':
alert('您取消了支付!');
break;
case 'get_brand_wcpay_request:fail':
alert('支付失败!(' + res.err_desc + ')');
break;
case 'get_brand_wcpay_request:ok':
alert('支付成功!');
location.href = '/order';
break;
default:
alert(JSON.stringify(res));
break;
}
});
})
})
</script>
接下来测试是否能唤起微信支付密码窗口,输入密码后显示支付成功。
注:如有出现错误
调用支付 JSAPI 缺少参数 timeStamp
,解决办法:在你项目的vendor/overtrue/wechat/src/Payment/Jssdk/Client.php
中屏蔽两行代码就行。
public function sdkConfig(string $prepayId): array
{
$config = $this->bridgeConfig($prepayId, false);
// 屏蔽这两行代码
// $config['timestamp'] = $config['timeStamp'];
// unset($config['timeStamp']);
return $config;
}
如有其他错误,可以在评论区交流。
1、首先增加支付回调路由,注意此路由应放在 middleware
中间件路由外面,回调路由请求必须是 post
//支付成功回调
Route::namespace('Wechat')->group(function () {
Route::post('/order/notify', 'OrderController@notify');
});
2、laravel
框架必须取消回调路由的 csrf
防护。在你项目的 app/Http/Middleware/VerifyCsrfToken.php
中加入如下代码:
protected $except = [
'order/notify', // 回调路由取消csrf防护
];
3、回调代码如下:
/**
* 微信支付回调方法,修改订单状态
* @return mixed
*/
function notify()
{
$payment = EasyWeChat::payment();
$response = $payment->handlePaidNotify(function ($message, $fail) {
if ($message['return_code'] === 'SUCCESS' && $message['result_code'] === 'SUCCESS') {
// \Log::debug($message);
Order::where('out_trade_no', $message['out_trade_no'])->update(['status' => 2, 'pay_time' => Carbon\Carbon::now()]);//更改订单状态
//支付后,微信会在此处返回支付状态,就是$message,回调里面打印不出来,可通过写入日志里面查看,支付成功后更改订单状态。当然你也可以进行其他操作。
return true;
} else {
// \Log::debug('我不买了');
return $fail('失败');
}
});
return $response;
}
4、最后测试如下:
1、点击支付按钮,js
提交相应参数到后台支付方法。
2、后台接收请求,往你的订单表里插入一条订单数据,状态为 1
,也就是未支付状态。
3、带上这条订单的订单号、价格,请求微信换取 prepay_id
。
4、请求微信成功会返回支付所需要的参数,appid
,timestamp
等。返回前端 js
调起支付。
5、支付后微信会将支付结果通过回调返回,可根据返回信息修改订单状态。
参考文献:https://learnku.com/articles/37459