easywechat laravel 公众号 微信支付
首先、申请微信商户平台,申请微信支付,公众号关联微信商户平台
公众号可以通过jsapi来实现公众号微信支付
一、业务页面
@extends('m.order')
@section('content')
<style type="text/css">
input, textarea {
border: 0;
-webkit-appearance: none;
}
</style>
<section class="container">
<div class="pay_main">
<div class="ay_ma1"><span>付款金额</span><em><i>¥</i>{{$total_price}}</em></div><!--ay_ma1-->
<div class="ay_ma2">订单编号:{{$order_no}}</div><!--ay_ma2-->
<div class="ay_ma2">付款方式</div><!--ay_ma2-->
<div class="ay_ma3"><span>微信支付</span><label></label></div>
{{--<div class="ay_ma3"><span>微信支付</span><label><input name="" type="radio" value="" checked></label></div>--}}
<div class="ay_ma4">
<ul>
<button type="button" onclick="wxPay()" id="pay_button">确认付款</button>
</ul>
</div><!--ay_ma4-->
</div><!--pay_main-->
<input type="hidden" id="order_no" value="{{$order_no}}">
<input type="hidden" id="code" value="">
</section>
@endsection
@section('js')
<script type="text/javascript" src="/static/new/m/js/jweixin-1.4.0.js"></script>
<script type="text/javascript" src="/static/new/m/js/pay.js"></script>
@endsection
二、前端pay.js逻辑
$(function () {
var layer;
layui.use(['layer'], function () {
layer = layui.layer;
});
$('#pay_button').hide();
wxConfig();
wx.ready(function(){
$('#pay_button').show();
});
});
function wxConfig() {
var order_no = $('#order_no').val();
$.ajax({
type:"GET",
url:"/wechat/pay",
data:{order_no:order_no},
success:function (config) {
// 微信配置
wx.config({
debug: false,
appId: config.appId,
timestamp: config.timeStamp,
nonceStr: config.nonceStr,
signature: config.signature,
jsApiList: ['chooseWXPay']
});
}
});
}
function wxPayAuth(orderPayNo) {
window.location.href = '/mp/oauth?targetUrl=/pay/request?orderPayNo=' + orderPayNo;
}
var jsApiConfig;
function wxPay() {
var order_no = $('#order_no').val();
$.ajax({
type:"GET",
url:"/wechat/pay",
data:{order_no:order_no},
success:function (config) {
jsApiConfig = config;//请求微信成功返回的支付参数
callpay();
}
})
}
//调用微信JS api 支付
function jsApiCall()
{
WeixinJSBridge.invoke(
'getBrandWCPayRequest',jsApiConfig,
function(res){
//WeixinJSBridge.log(res.err_msg);
//alert(res.err_code+res.err_desc+res.err_msg);
if(res.err_msg == "get_brand_wcpay_request:ok" ) {
layer.msg('支付成功', {time: 1000, end: function () {
location.href = '/inquiry/index';
}});
}else{
layer.msg('支付失败,请重试');
}
});
}
function callpay()
{
if (typeof WeixinJSBridge == "undefined"){
if( document.addEventListener ){
document.addEventListener('WeixinJSBridgeReady', jsApiCall, false);
}else if (document.attachEvent){
document.attachEvent('WeixinJSBridgeReady', jsApiCall);
document.attachEvent('onWeixinJSBridgeReady', jsApiCall);
}
}else{
jsApiCall();
}
}
三、服务端处理页面
<?php
namespace App\Http\Controllers\M;
use App\Library\Common;
use App\Library\Y;
use App\Models\Member\MemberConnect;
use App\Models\Prod\Order;
use App\Models\Prod\SaleOrder;
use App\Services\Wechat\MenuService;
use App\Services\Wechat\MessageService;
use App\Services\Wechat\UserService;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
class WeChatController extends Controller
{
//
/**
* 处理微信的请求消息
*
* @return string
*/
/* public function serve()
{
Log::info('request arrived.'); # 注意:Log 为 Laravel 组件,所以它记的日志去 Laravel 日志看,而不是 EasyWeChat 日志
$app = app('wechat.official_account');
$app->server->push(function($message){
return "欢迎关注 一览商城!";
});
return $app->server->serve();
}*/
public function serve(MessageService $messageService)
{
Log::info('request arrived.'); # 注意:Log 为 Laravel 组件,所以它记的日志去 Laravel 日志看,而不是 EasyWeChat 日志
$app = app('wechat.official_account');
$app->server->push(function($message) use($messageService){
return $messageService->index($message);
});
return $app->server->serve();
}
/**
* 登录时请求验证
* @return mixed
*/
public function login_oauth(){
Log::info('start', ['login_oauth']);
$member_id= isset(auth('member')->user()->id) ?auth('member')->user()->id : 0;
//判断是否存在 openid
if(!Common::getOpenid($member_id)){
$app = app('wechat.official_account');
return $response = $app->oauth->scopes(['snsapi_userinfo'])->redirect(route('m.login_callback'));
}
return redirect(route('m.member.index'));
}
/**
* 登录时请求回调
* @return mixed
*/
public function login_callback(){
Log::info('start', ['login_callback']);
$app = app('wechat.official_account');
// 获取 OAuth 授权结果用户信息
$user = $app->oauth->user();
if(!$user){
Log::info('oauth_callback_user_error', ['none user']);
}
$openid = $user->getId();
$UserService = new UserService();
$user_info =$UserService->getUserInfo($openid);
$member_id= isset(auth('member')->user()->id) ?auth('member')->user()->id : 0;
//查询openid 有没有绑定 member
$memberConnect = MemberConnect::where('openid', '=', $openid)->first();
if(!$memberConnect){
//没保存先保存memberConnect
Common::createMemberConnect($user_info, 3);
}
//绑定openid memberid
MemberConnect::where('openid', '=', $openid)->update(['member_id'=>$member_id]);
//如果登录,则保存微信用户信息进cache
if($member_id > 0){
Log::info('login_callback_cache', [$user_info]);
Cache::add("wx_user:".$member_id, $user_info);
}
return redirect(route('m.member.index'));
}
/**
* 发起授权
* @return mixed
*/
public function oauth(){
Log::info('start', ['oauth']);
$member_id= isset(auth('member')->user()->id) ?auth('member')->user()->id : 0;
//已登录状态
if($member_id > 0){
$memberConnect = MemberConnect::where('member_id', '=', $member_id)->first();
//如果会员已绑定,直接跳转会员主页
if($memberConnect) return redirect(route('m.member.index'));
//如果会员没绑定,查看openid是否绑定
$openid = Common::getOpenid($member_id);
if($openid){
$memberConnect = MemberConnect::where('openid', '=', $openid)->first();
//存在则更新
if($memberConnect){
MemberConnect::where('openid', '=', $openid)->update(['member_id'=>$member_id]);
return redirect(route('m.member.index'));
}
}
}
$app = app('wechat.official_account');
return $app->oauth->scopes(['snsapi_userinfo'])->redirect();
}
/**
* 授权回调
* @return mixed
*/
public function callback(){
Log::info('start', ['oauth_callback']);
// 获取 OAuth 授权结果用户信息
$app = app('wechat.official_account');
$user = $app->oauth->user();
if(!$user) Log::info('oauth_callback', ['none user']);
$openid = $user->getId();
$UserService = new UserService();
$user_info =$UserService->getUserInfo($openid);
//查询openid 有没有绑定 member
$memberConnect = MemberConnect::where('openid', '=', $openid)->first();
$member_id = 0;
if(!$memberConnect){
//没保存先保存memberConnect
Common::createMemberConnect($user_info, 3);
}else{
$member_id = $memberConnect->member_id;
}
if($member_id > 0){
//openid 已经跟会员member绑定,则默认登录
Auth::guard('member')->loginUsingId($member_id);
//加入openid缓存
Cache::add("wx_user:".$member_id, $user_info);
Log::info('wechat login email', [auth('member')->user()->email]);
return redirect(route('m.member.index'));
}
if($member_id ==0 ){
//openid还没跟会员member绑定,提醒用户去设置绑定
return redirect(route('m.bind_account', array('openid'=>$openid)));
}
}
public function wxMenu(Request $request,MenuService $menuService){
$buttons = [
[
"name" => "我要采购",
"sub_button" => [
[
"type" => "view",
"name" => "发布采购",
"url" => "http://m.bychem.com/inquiry/add"
],
[
"type" => "view",
"name" => "采购管理",
"url" => "http://m.bychem.com/inquiry/lists?type=quote"
],
[
"type" => "view",
"name" => "采购订单",
"url" => "http://m.bychem.com/order/lists?type=pay"
],
],
],
[
"name" => "我要销售",
"sub_button" => [
[
"type" => "view",
"name" => "发布产品",
"url" => "http://m.bychem.com/sale/goods_add"
],
[
"type" => "view",
"name" => "产品管理",
"url" => "http://m.bychem.com/sale/goods_list"
],
[
"type" => "view",
"name" => "询盘管理",
"url" => "http://m.bychem.com/sale/lists"
],
[
"type" => "view",
"name" => "销售订单",
"url" => "http://m.bychem.com/sale/order"
],
],
],
[
"name" => "会员中心",
"sub_button" => [
[
"type" => "view",
"name" => "注册/登录",
"url" => "http://m.bychem.com/users/sign_in"
],
[
"type" => "view",
"name" => "会员中心",
"url" => "http://m.bychem.com/member/index"
],
[
"type" => "click",
"name" => "联系客服",
"key" => "CONTACT_KEFU"
],
],
],
];
return $menuService->index($request,$buttons);
}
/**
* 公众号微信支付成功回调
* @param Request $request
* @return mixed
*/
public function wechat_notify(Request $request){
Log::info('start', ['wechat mp notify']);
$payment = app('wechat.payment');
$response = $payment->handlePaidNotify(function ($message, $fail) {
Log::info('wechat mp notify msg', [$message]);
if ($message['return_code'] === 'SUCCESS' && $message['result_code'] === 'SUCCESS') {
Order::where('id','=', $message['out_trade_no'])->update(['is_pay' => 1,'status' => 2,'trade_no'=>$message['transaction_id'],'pay_method'=>'微信']);//更改订单状态
//更新销售合同支付状态
SaleOrder::where('order_id','=',$message['out_trade_no'])->update(['is_pay'=>1]);
//支付后,微信会在此处返回支付状态,就是$message,回调里面打印不出来,可通过写入日志里面查看,支付成功后更改订单状态。当然你也可以进行其他操作。
return true;
} else {
return $fail('失败');
}
});
return $response;
}
/**
* 发起支付
* 组合微信支付需要参数
* @param Request $request
* @return mixed
*/
public function pay(Request $request){
Log::info('start',['wechat paying']);
$order_no = $request->get('order_no');
$member_id = isset(auth('member')->user()->id) ?auth('member')->user()->id : 0;
//判断是否有权限操作此订单
$order = Order::where('order_no', '=', $order_no)->first();
if($order->user_id != $member_id) return Y::error('没有权限操作!');
$total_price = $order->total_price;
$total_price = $total_price * 100;//微信支付以分为单位
$openid = Common::getOpenid($member_id);
if(!$openid) return Y::error('没有openid!请重新登录');
Log::info('wechat repay',[$order_no, $member_id,$total_price, $openid]);
$payment = app('wechat.payment');
//统一下单
$result = $payment->order->unify([
'body' => '微信支付',
'out_trade_no' => $order->id,
'total_fee' => $total_price,
//'notify_url' => 'http://m.bychem.com/wechat/payments/wechat-notify', //回调地址,用于接收微信支付结果
'notify_url' => route('m.wechat_notify'), //回调地址,用于接收微信支付结果
'trade_type' => 'JSAPI',
'openid' => $openid,
]);
Log::info('wechat payment result',[$result]);
if ($result['result_code'] == 'SUCCESS' && $result['return_code'] == 'SUCCESS') {
$prepayId = $result['prepay_id'];
$jssdk = $payment->jssdk;
$config = $jssdk->sdkConfig($prepayId);
$config['timestamp'] = strval(time());
$config['timeStamp'] = strval(time());
Log::info('wechat config',[$config]);
return $config;
} else {
Log::info('wechat config un_success',[$result]);
return $result;
}
}
}
四、csrf排除
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
class VerifyCsrfToken extends Middleware
{
/**
* Indicates whether the XSRF-TOKEN cookie should be set on the response.
*
* @var bool
*/
protected $addHttpCookie = true;
/**
* The URIs that should be excluded from CSRF verification.
*
* @var array
*/
protected $except = [
'wechat_notify',
'ali_notify',
'wechat',
'wechat/*',
'payments/*'
];
}