上一篇咱们讲了在微信浏览器内实现微信支付的功能,它特别适合于一些基于微信公众号的h5站点等,支付流程也至关流畅,可是...php
还有一种状况,好比如今北哥兄弟连PC版,是生成了一个二维码,这个二维码是专属的,扫描后直接就蹦出了支付页面。如今告诉你它如何实现的~html
本文相关框架前端
Yii2数据库
EasyWechatjson
上节课咱们讲了一个很重要的概念,那就是预支付交易回话标识 “咱们先调用接口在微信支付服务后台生成预支付交易单,返回正确的预支付交易回话标识后再按扫码、JSAPI、APP等不一样场景生成交易串调起支付。”segmentfault
换句话说,获取预支付交易回话标识 这步基本都是一致的,不一样就在于场景不一样,你们必定要触类旁通。api
那么你还记得上篇咱们获取 预支付交易回话标识 的代码实现么?数组
忘记了?那你先穿越下:开启穿越门浏览器
核心就是这段代码安全
我先来模拟一个场景,假设咱们如今有一个action(index.php?r=charge/qrcode)负责生成上篇文章充值花费的微信二维码,但愿结果是微信扫码后,不进入任何页面,直接蹦出输入支付密码的地方,而后就支付了。
// ChargeController use EasyWeChat\Foundation\Application; use EasyWeChat\Payment\Order; ... /** * 生成支付二维码 **/ public function actionQrcode(){ $charge = new Charge(); // 刷刷刷一堆代码,就生成了未付款订单。 // 经过EasyWechat来调用 $config = Yii::$app->params['WECHAT']; $wxApp = new Application($config); $payment = $wxApp->payment; $notifyUrl = Yii::$app->request->getHostInfo() . Url::to(['/wechat/charge/notify-qrcode']); $attributes = [ 'trade_type'=>Order::NATIVE,//不一样点 'body'=>"商品描述", 'detail'=>"商品简介", 'out_trade_no'=>$charge->number, 'total_fee'=>$charge->money*100, 'notify_url'=>$notifyUrl ]; $o = new Order($attributes); $result = $payment->prepare($o); if ($result->return_code == 'SUCCESS' && $result->result_code == 'SUCCESS'){ $prepayId = $result->prepay_id; $codeUrl = $result->code_url; } } ...
上面的codeUrl就是支付二维码内容,从这里你看到了,其实流程仍是同样的,先得到一个prepayId(Native类型),而后得到一个codeUrl,固然,在视图里面你须要用一个库将这个codeUrl生成一个二维码(可使用Yii的yii2-qrcode-helper库或js库都成)。
要注意:这个过程是原生的微信支付,和公众号没有半毛钱关系,所以在$attributes 里你看到了,没有 openid 这个必填项了已经,这点要尤为注意
而后浏览器就会出现一个二维码,以下图。
你真的用微信扫了?好纯真的少年呀,这是北哥小报的公众号二维码呀。好了,反正你将codeUrl的内容生成了一个二维码,客户微信扫描后。
而后客户进行支付,钱就刷刷刷的进入到微信支付平台帐号啦。
哦,还有一点,就是咱们如何知道微信支付成功了那,对于原生扫码支付,咱们也须要给微信提供一个异步通知的地址,对,就是那个$notifyUrl,看来你认真看了上一篇。
在上面设置生成二维码代码里咱们定义了一个url
$notifyUrl = Yii::$app->request->getHostInfo() . Url::to(['/wechat/charge/notify-qrcode']);
如今咱们就用它来接收微信给咱们的反馈
public function actionNotifyQrcode(){ $config = Yii::$app->params['WECHAT']; $wxApp = new Application($config); $payment = $wxApp->payment; $response = $payment->handleNotify(function ($notify, $successful){ if ($successful) { $order_arr = json_decode($notify, true); $transactionId = $order_arr['transaction_id']; // $order_arr就是微信异步通知给服务器的信息 //todo 咱们的逻辑,将charge变为已支付 } }); $response->send(); }
很奇怪是么,它和接收公众号支付类的notify是同样的,并且EasyWeChat封装的就几行代码,非常简单。
要注意:这也是一个POST请求,请关闭该方法的csrf验证,不然Yii会将其拒之门外。
这就完了么?是的。
二维码支付其实比公众号设置的更简单,你也看到了,生成二维码,而后扫描接收支付通知,处理本地逻辑。
关于APP的的微信支付要日后放一放,这个还要涉及对于APP SDK的配置等。
接下来咱们还会将微信企业支付接口和微信发红包接口这两个微信支付。
(完)
转自:https://segmentfault.com/a/1190000009826689
框架下载:https://www.easywechat.com/
前期准备:
申请微信支付后, 会收到2个参数, 商户id,和商户key.
注意,这2个参数,不要和微信的参数混淆.
微信参数: appid, appkey, token
支付参数: merchant_id(商户号), key(支付密钥)
支付密钥怎么获得?
到 https://pay.weixin.qq.com -->帐户中心-->API安全-->设置API密钥
自行设置一个32位的密钥
微信支付流程:
一、composer安装EasyWechat包
环境要求:
安装:
composer require overtrue/wechat:~3.1 -vvv
二、公众号配置
2.一、配置支付目录及受权域名
2.二、配置网页受权
三、初始化SDK,建立一个 EasyWeChat\Foundation\Application
实例
<?php use EasyWeChat\Foundation\Application; protected $app=null; public function construct(){ $options = [ /** * Debug 模式,bool 值:true/false * * 当值为 false 时,全部的日志都不会记录 */ 'debug' => true, /** * 帐号基本信息,请从微信公众平台/开放平台获取 */ 'app_id' => 'your-app-id', // AppID 'secret' => 'your-app-secret', // AppSecret 'token' => 'your-token', // Token 'aes_key' => '', // EncodingAESKey,安全模式下请必定要填写!!! /** * 日志配置 * * level: 日志级别, 可选为: * debug/info/notice/warning/error/critical/alert/emergency * permission:日志文件权限(可选),默认为null(若为null值,monolog会取0644) * file:日志文件位置(绝对路径!!!),要求可写权限 */ 'log' => [ 'level' => 'debug', 'permission' => 0777, 'file' => '/tmp/easywechat.log', ], /** * OAuth 配置 * * scopes:公众平台(snsapi_userinfo / snsapi_base),开放平台:snsapi_login * callback:OAuth受权完成后的回调页地址 */ 'oauth' => [ 'scopes' => ['snsapi_userinfo'], 'callback' => '/examples/oauth_callback.php', ], /** * 微信支付 */ 'payment' => [ 'merchant_id' => 'your-mch-id', 'key' => 'key-for-signature', 'cert_path' => 'path/to/your/cert.pem', // XXX: 绝对路径!!!! 'key_path' => 'path/to/your/key', // XXX: 绝对路径!!!! 'notify_url' => '默认的订单回调地址', // 你也能够在下单时单独设置来想覆盖它 // 'device_info' => '013467007045764', // 'sub_app_id' => '', // 'sub_merchant_id' => '', // ... ], ]; $this->$app = new Application($options); }
4. 获得支付对象payment
$payment =$this->$app->payment;
五、把订单对象order(订单号,金额,openid)以参数传入
<?php use EasyWeChat\Foundation\Application; use EasyWeChat\Payment\Order; $attributes = [ 'trade_type' => 'JSAPI', // JSAPI,NATIVE,APP... 'body' => 'iPad mini 16G 白色', 'detail' => 'iPad mini 16G 白色', 'out_trade_no' => '1217752501201407033233368018',//订单号 'total_fee' => 5388, // 单位:分 'notify_url' => 'http://xxx.com/order-notify', // 支付结果通知网址,若是不设置则会使用配置里的默认地址 'openid' => '当前用户的 openid', // trade_type=JSAPI,此参数必传,用户在商户appid下的惟一标识, // ... ]; $order = new Order($attributes);
6.、预处理,获得一个预处理id, payment->prepare(order);
$result = $payment->prepare($order); if ($result->return_code == 'SUCCESS' && $result->result_code == 'SUCCESS'){ $prepayId = $result->prepay_id; }
七、生成支付JS配置
$json = $payment->configForPayment($prepayId); // 返回 json 字符串,若是想返回数组,传第二个参数 false
八、将把订单号和json写入用户确认支付的模板中,触发js,调起支付
return view('done',['order'=>$ordersn,'json'=>$json]);
<script> $('form').submit (function() { WeixinJSBridge.invoke( 'getBrandWCPayRequest', {!!$json!!}, function(res){ if(res.err_msg == "get_brand_wcpay_request:ok" ) { // 使用以上方式判断前端返回,微信团队郑重提示: // res.err_msg将在用户支付成功后返回 // ok,但并不保证它绝对可靠。 } } ); return false; }); </script>
九、成功回调
在用户成功支付后,微信服务器会向该 订单中设置的回调URL 发起一个 POST 请求,请求的内容为一个 XML。
先在中间件VerifyCsrfToken中配置paid方法无需走CSRF验证
public function paid(){ $response =$this->$app->payment->handleNotify(function($notify, $successful){ // 使用通知里的 "微信支付订单号" 或者 "商户订单号" 去本身的数据库找到订单 $order = 查询订单($notify->out_trade_no); if (!$order) { // 若是订单不存在 return 'Order not exist.'; // 告诉微信,我已经处理完了,订单没找到,别再通知我了 } // 若是订单存在 // 检查订单是否已经更新过支付状态 if ($order->paid_at) { // 假设订单字段“支付时间”不为空表明已经支付 return true; // 已经支付成功了就再也不更新了 } // 用户是否支付成功 if ($successful) { // 不是已经支付状态则修改成已经支付状态 $order->paid_at = time(); // 更新支付时间为当前时间 $order->status = 'paid'; } else { // 用户支付失败 $order->status = 'paid_fail'; } $order->save(); // 保存订单 return true; // 返回处理完成 }); return $response; }
至此微信支付就完成了,如有其余问题,请参考EasyWeChat文档
转自:
https://www.cnblogs.com/lamp01/p/7420944.html