当前位置: 首页 > news >正文

Laravel7 + easyWeChat 实现微信公众号支付功能

注册服务号,需进行微信认证,此时需缴费 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 OrderControllerphp 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 步:JSSDKif ($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、请求微信成功会返回支付所需要的参数,appidtimestamp 等。返回前端 js 调起支付。

5、支付后微信会将支付结果通过回调返回,可根据返回信息修改订单状态。

参考文献:https://learnku.com/articles/37459

相关文章:

Laravel7 + easyWeChat 实现微信公众号支付功能

注册服务号&#xff0c;需进行微信认证&#xff0c;此时需缴费 300 元/年&#xff0c;必须是认证成功的服务号才能开通微信支付。 注册微信支付商户号 1、登录 https://pay.weixin.qq.com/index.php/core/home/login?return_urlhttps%3A%2F%2Fpay.weixin.qq.com%2Findex.php%…...

Linux环境下,针对QT软件工程搭建C++Test单元测试环境的操作指南

文章目录 前言一、安装QT二、安装CTest三、使用QT生成.bdf文件四、创建CTest工程注意事项 前言 CTest是Parasoft公司出品的一款可以针对C/C源代码进行静态分析、单元测试、集成测试的测试工具。本文主要讲解如何在Linux环境下&#xff0c;搭建QT插件版的CTest测试环境。 一、…...

16k+ start 一个开源的的监控系统部署教程

安装条件 Linux或macOS系统 4GB内存 开放 33014、33174、3183端口 1.安装 1、下载源码 首先使用 git 克隆源码到本地 git clone -b main https://github.com/SigNoz/signoz.git && cd signoz/deploy/ 方式1&#xff1a;运行 install.sh 脚本一键安装 ./install.s…...

Mermaid使用教程(绘制各种图)

Mermaid使用教程&#xff08;绘制各种图&#xff09; 文章目录 Mermaid使用教程&#xff08;绘制各种图&#xff09;简介饼状图简单的例子应用案例 序列图简单案例应用案例另一个应用案例 甘特图简单案例应用案例一个更为复杂的应用案例 Git图简单案例 总结 简介 本文将主要介…...

OpenAI/ChatGPT Plus 支持的虚拟卡有哪些

最近&#xff0c;有关 OpenAI/ChatGPT Plus 需要信用卡的讨论越来越多。在这篇文章中&#xff0c;我将分享一些我在绑定信用卡过程中得到的经验和教训&#xff0c;以及 OpenAI/ChatGPT Plus 支持的卡类型。 不支持的卡 根据 OpenAI 的地区限制&#xff0c;国内和香港的卡都不…...

ARM多核调度器DSU

1. 背景 从A75开始&#xff0c;ARM提出了一个新的多核心管理系统单元&#xff0c;叫做DSU(DynamIQ Shared Unit)。DSU的核心功能是控制CPU内核&#xff0c;使其成簇Cluster使用&#xff0c;簇内每一个核心可以单独开关、调整频率/电压&#xff0c;能效表现更佳&#xff0c;甚至…...

vue解决部署文件缓存方式

问题&#xff1a;系统上线后&#xff0c;除了bug。紧急修复后&#xff0c;发现安卓正常&#xff0c;ios上海市有问题。通过debug后发现&#xff0c;ios上缓存严重。于是想到了打包文件加时间戳的方式来去除缓存。 vue2 配置打包输出文件名方式&#xff1a; const baseUrl &qu…...

游戏开发中的噪声算法

一、噪声 噪声是游戏编程的常见技术&#xff0c;广泛应用于地形生成&#xff0c;图形学等多方面。 那么为什么要引入噪声这个概念呢&#xff1f;在程序中&#xff0c;我们经常使用直接使用最简单的rand()生成随机值&#xff0c;但它的问题在于生成的随机值太“随机”了&#xf…...

CodeReview 小工具

大家开发中有没有遇到一个版本开发的非常杂&#xff0c;开发很多个项目&#xff0c;改动几周后甚至已经忘了自己改了些什么&#xff0c;领导要对代码review的时候&#xff0c;理不清楚自己改过的代码&#xff0c;只能将主要改动的大功能过一遍。这样就很容易造成review遗漏&…...

UE5 C++ Slate独立程序的打包方法

在源码版安装目录内找到已编译通过的xxx.exe&#xff0c;&#xff08;\Engine\Binaries\Win64\xxx.exe)&#xff0c;在需要的位置新建文件夹&#xff0c;拷贝源码版Engine内的Binaries、Content、Shaders文件夹到目标文件夹内&#xff0c;将xxx.exe放入对应位置&#xff0c;删除…...

探索设计模式的魅力:一篇文章让你彻底搞懂建造者模式

建造者模式&#xff08;Builder Pattern&#xff09;是一种创建型设计模式&#xff0c;旨在将一个复杂对象的创建过程与其表示分离&#xff0c;使得同样的构建过程可以创建不同的表示形式。 主要角色&#xff1a; 产品&#xff08;Product&#xff09;&#xff1a;表示正在构建…...

Facebook广告投放指南,如何运营多个Facebook广告账户不被封?

许多卖家做广告投放会选择 Facebook 作为主要的业务和产品推广平台。然而&#xff0c;要在这个竞争激烈的平台上脱颖而出并成功拓宽广告覆盖面并不容易&#xff0c;通常情况下大家会运营多个Facebook广告账号&#xff0c;但是很多人因此遭遇Facebook账号被封的情况&#xff0c;…...

音乐人声分离工具:极简的人声和背景音乐分离工具

项目地址&#xff1a;jianchang512/vocal-separate: an extremely simple tool for separating vocals and background music, completely localized for web operation, using 2stems/4stems/5stems models 这是一个极简的人声和背景音乐分离工具&#xff0c;本地化网页操作&a…...

Go语言基础快速上手

1、Go语言关键字 2、Go数据类型 3、特殊的操作 3.1、iota关键字 Go中没有明确意思上的enum&#xff08;枚举&#xff09;定义&#xff0c;不过可以借用iota标识符实现一组自增常亮值来实现枚举类型。 const (a iota // 0b // 1c 100 // 100d // 100 (与上一…...

Excel 根据日期按月汇总公式

Excel 根据日期按月汇总公式 数据透视表日期那一列右击&#xff0c;选择“组合”&#xff0c;步长选择“月” 参考 Excel 根据日期按月汇总公式Excel如何按着日期来做每月求和...

使用 crypto-js 进行 AES 加解密操作

在前端开发中&#xff0c;数据的加密和解密是为了保障用户隐私和数据的安全性而常见的任务。AES&#xff08;Advanced Encryption Standard&#xff09;是一种对称密钥加密算法&#xff0c;被广泛用于保护敏感信息的传输和存储。本文将介绍 AES 加解密的基本原理&#xff0c;并…...

Vue-30、Vue非单文件组件。

非单文件组件&#xff1a; 一个组件包含n个组件 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>非单文件组件</title><script type"text/javascript" src"https://cdn.jsde…...

7-6 实验2_1_判断两数的大小

7-6 实验2_1_判断两数的大小 分数 100 全屏浏览题目 切换布局 作者 scs 单位 北京邮电大学 已知有两个整数&#xff0c;请使用if-else选择结构将它们中的较大数选择出来&#xff0c;存到max变量中&#xff1b;将较小数选择出来&#xff0c;存到min变量中&#xff0c;并将选…...

POKT Network (POKT) :进军百亿美元市场规模的人工智能推理市场

POKT Network&#xff08;又称 Pocket Network&#xff09;是一个去中心化的物理基础设施网络&#xff08;DePIN&#xff09;&#xff0c;它能够协调并激励对任何开放数据源的访问&#xff0c;最初专注于向应用程序和服务提供商提供区块链数据。 自 2020 年主网上线以来&#x…...

【STM32】STM32学习笔记-I2C通信外设(34)

00. 目录 文章目录 00. 目录01. I2C简介02. I2C外设简介03. I2C框图04. I2C基本结构05. 主机发送06. 主机接收07. 软件/硬件波形对比08. 预留09. 附录 01. I2C简介 I2C(Inter&#xff0d;Integrated Circuit)总线是一种由NXP&#xff08;原PHILIPS&#xff09;公司开发的两线式…...

从数据角度分析年龄与NBA球员赛场表现的关系【数据分析项目分享】

好久不见朋友们&#xff0c;今天给大家分享一个我自己很感兴趣的话题分析——NBA球员表现跟年龄关系到底大不大&#xff1f;数据来源于Kaggle&#xff0c;感兴趣的朋友可以点赞评论留言&#xff0c;我会将数据同代码一起发送给你。 目录 NBA球员表现的探索性数据分析导入Python…...

深入浅出Spring AOP

第1章&#xff1a;引言 大家好&#xff0c;我是小黑&#xff0c;咱们今天要聊的是Java中Spring框架的AOP&#xff08;面向切面编程&#xff09;。对于程序员来说&#xff0c;理解AOP对于掌握Spring框架来说是超级关键的。它像是魔法一样&#xff0c;能让咱们在不改变原有代码的…...

火速收藏!2024 新年微信红包封面领取全攻略

2024“龙”重登场&#xff01;今年有哪些令人期待的红包封面&#xff1f; 前方大批精美红包封面来袭&#xff0c;全新品牌氛围红包封面上线&#xff0c;支持品牌定制特色氛围元素&#xff0c;沉浸感受浓浓年味儿&#xff0c;收获满满惊喜&#xff01; 新年开好运&#xff0c;微…...

【RabbitMQ】RabbitMQ安装与使用详解以及Spring集成

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是Java方文山&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的专栏《RabbitMQ实战》。&#x1f3af;&#x1f3af; &am…...

企业多云组网怎么办?

在当今数字化时代&#xff0c;企业普遍采用多云策略&#xff0c;同时利用不同云平台的优势以实现成本优化和整体性能提升。根据Futuriom于2022年发布的“安全多云网络调查”报告&#xff0c;80%的受访者表示他们使用来自两个或更多公共云提供商的PaaS或IaaS产品。 多云策略的迅…...

背包问题(贪心) 二维01背包问题 Java

背包问题&#xff08;贪心&#xff09; 最优装载问题 题目描述 有n件物品和一个最大承重为w 的背包。第i件物品的重量是weight[i]&#xff0c;每件只能用一次&#xff0c;求装入背包的最多物品数量。 题目分析 因为我们只要求装入物品的数量&#xff0c;所以装重的显然没有…...

2019年认证杯SPSSPRO杯数学建模D题(第二阶段)5G时代引发的道路规划革命全过程文档及程序

2019年认证杯SPSSPRO杯数学建模 D题 5G时代引发的道路规划革命 原题再现&#xff1a; 忙着回家或上班的司机们都知道交通堵塞既浪费时间又浪费燃料&#xff0c;甚至有的时候会带来情绪上的巨大影响&#xff0c;引发一系列的交通问题。据报道&#xff0c;每年交通拥堵使得美国…...

可视化k8s页面(Kubepi)

Kubepi是一个简单高效的k8s集群图形化管理工具&#xff0c;方便日常管理K8S集群&#xff0c;高效快速的查询日志定位问题的工具 随便在哪个节点部署&#xff0c;我这里在主节点部署 docker pull kubeoperator/kubepi-server docker run --privileged -itd --restartunless-st…...

1434. 数池塘(四方向)-深度优先搜索-DFS

代码&#xff1a; #include<iostream> using namespace std; char a[200][200]; int fx[4]{0,1,0,-1}; int fy[4]{1,0,-1,0}; int k0; int n,m; void dfs(int x,int y){a[x][y].;int tx,ty;for(int i0;i<4;i){txxfx[i];tyyfy[i];if(tx>1&&tx<n&&am…...

Mysql:重点且常用的操作和理论知识整理 ^_^

目录 1 基础的命令操作 2 DDL 数据库定义语言 2.1 数据库操作 2.2 数据表操作 2.2.1 创建数据表 2.2.2 修改和删除数据表 2.2.3 添加外键 3 DML 数据库操作语言 3.1 插入语句(INSERT) 3.2 修改语句(UPDATE) 3.3 删除语句 3.3.1 DELETE命令 3.3.2 TRUNCATE命令 4 …...