Laravel 5.3 + 微信支付SDK v3.0.1 + 微信扫码支付

业务流程时序图

业务流程说明:
(1)商户后台系统根据微信支付规定格式生成二维码(规则见下文),展示给用户扫码。

(2)用户打开微信“扫一扫”扫描二维码,微信客户端将扫码内容发送到微信支付系统。

(3)微信支付系统收到客户端请求,发起对商户后台系统支付回调URL的调用。调用请求将带productid和用户的openid等参数,并要求商户系统返回交数据包,详细请见"本节3.1回调数据输入参数"

(4)商户后台系统收到微信支付系统的回调请求,根据productid生成商户系统的订单。

(5)商户系统调用微信支付【统一下单API】请求下单,获取交易会话标识(prepay_id)

(6)微信支付系统根据商户系统的请求生成预支付交易,并返回交易会话标识(prepay_id)。

(7)商户后台系统得到交易会话标识prepay_id(2小时内有效)。

(8)商户后台系统将prepay_id返回给微信支付系统。返回数据见"本节3.2回调数据输出参数"

(9)微信支付系统根据交易会话标识,发起用户端授权支付流程。

(10)用户在微信客户端输入密码,确认支付后,微信客户端提交支付授权。

(11)微信支付系统验证后扣款,完成支付交易。

(12)微信支付系统完成支付交易后给微信客户端返回交易结果,并将交易结果通过短信、微信消息提示用户。微信客户端展示支付交易结果页面。

(13)微信支付系统通过发送异步消息通知商户后台系统支付结果。商户后台系统需回复接收情况,通知微信后台系统不再发送该单的支付通知。

(14)未收到支付通知的情况,商户后台系统调用【查询订单API】。

(15)商户确认订单已支付后给用户发货。

微信基本参数配置:
1. 修改 \Desktop\WxpayAPI_php_v3.0.1\lib\WxPay.Config.php中的参数配置
//=【基本信息设置】===============================
//
/**
* TODO: 修改这里配置为您自己申请的商户信息
* 微信公众号信息配置
*
* APPID:绑定支付的APPID(必须配置,开户邮件中可查看)
*
* MCHID:商户号(必须配置,开户邮件中可查看)
*
* KEY:商户支付密钥,参考开户邮件设置(必须配置,登录商户平台自行设置)
* 设置地址:https://pay.weixin.qq.com/index.php/account/api_cert
*
* APPSECRET:公众帐号secert(仅JSAPI支付的时候需要配置, 登录公众平台,进入开发者中心可设置),
* 获取地址:https://mp.weixin.qq.com/advanced/advanced?action=dev&t=advanced/dev&token=2005451881&lang=zh_CN
* @var string
*/
const APPID = 'wx426b3015555a46be';
const MCHID = '1900009851';
const KEY = '8934e7d15453e97507ef794cf7b0519d';
const APPSECRET = '7813490da6f1265e4901ffb80afaa36f';
将上述几个参数修改为你的微信公众的相关信息
2.证书的更换,将Desktop\WxpayAPI_php_v3.0.1\cert\文件夹下的参数更换成相应公众号的证书具体下载地址:商虎平台 》 账户中心 》API安全 》API证书下载

3.授权域名的设置;在微信公众号中设置网页授权域名,JS接口安全域名,具体设置地址:公众平台》设置》公众号设置》功能设置》JS接口安全域名设置,网页授权域名:

TIP:设置域名的时候需要将一个验证文件拷贝到域名访问的根目录,否则授权无法通过:

4.在商户平台设置扫描回调URL, JSAPI支付授权目录:具体如下

TIP:设置JSAPI支付授权目录的时候需要注意,URL最后一个参数是可以变化的,如 JSAPI支付授权目录是 http://www.demo.com/wxpay/ ,那么你可以发起支付的路由是http://www.demo.com/wxpay/productID, productID可以变化,但是如果发起支付路由是是http://www.demo.com/wxpay/productID/deeper,则微信可能会报错“没有授权的....."

项目目录结构说明:

1.Controllers 文件夹中放置控制器
2.routes.php 设置路由信息
3.Wxpay 是 微信SDK
4.views 文件夹中放置显示文件

功能实现:
1.显示二维码:
1.1控制器,WeiXinController.php
//获取二维码
public function qrcode(){
//简单的页面跳转
return view('wexinPay.native');

}

1.2 Route路由
Route::get('qrcode','WeiXinController@qrcode');
1.3 View页面的设置,native.blade.php来自微信SDK 》 example > native.php

GetPrePayUrl("123456789"); ?>

{{ json_encode($result) }}

自助售花系统
扫描支付模式一

模式一扫码支付


TIP: $notify->GetPrePayUrl( ProductID );方法的具体实现参考微信SDK中的源码

2.扫码下单。
扫描支付二维码,触发扫码回调URL , 该URL中使用统一接口下单:
2.1 Controller
public function qrcodeNotify(){

    Log::info("qrcode notify.");

    $notify = new NativeNotifyCallBack();
    $notify->Handle(true);

    Log::info(json_encode($notify));

}

2.2 Route
Route::any('qrcodeNotify','WeiXinController@qrcodeNotify');
2.3回调函数的实现:
回调的实现 WxpayAPI_php_v3.0.1\example\native_notify.php

class NativeNotifyCallBack extends WxPayNotify
{
public function unifiedorder($openId, $product_id)
{
//统一下单
$input = new WxPayUnifiedOrder();
$input->SetBody("蓝色妖姬");
$input->SetAttach("测试数据");
$input->SetOut_trade_no(WxPayConfig::MCHID.date("YmdHis"));
$input->SetTotal_fee("1");
$input->SetTime_start(date("YmdHis"));
$input->SetTime_expire(date("YmdHis", time() + 600));
$input->SetGoods_tag("test");
$input->SetNotify_url(url('notify')); //这个URL是支付回调URL
$input->SetTrade_type("NATIVE");
$input->SetOpenid($openId);
$input->SetProduct_id($product_id);
$result = WxPayApi::unifiedOrder($input);
Log::DEBUG("unifiedorder:" . json_encode($result));
return $result;
}

3.支付回调的实现:
3.1 Controller

public function notify(){

    Log::info("pay notify.");

    $notify = new PayNotifyCallBack();
    $notify->Handle(false);

    Log::info(json_encode($notify));

}

3.2 ROUTE
Route::any('notify','WeiXinController@notify');
3.3 在回调函数中做相关处理

class PayNotifyCallBack extends WxPayNotify
{
//查询订单
public function Queryorder($transaction_id)
{
$input = new WxPayOrderQuery();
$input->SetTransaction_id($transaction_id);
$result = WxPayApi::orderQuery($input);

	\Illuminate\Support\Facades\Log::info("paynotify.query:" . json_encode($result));

	if(array_key_exists("return_code", $result)
		&& array_key_exists("result_code", $result)
		&& $result["return_code"] == "SUCCESS"
		&& $result["result_code"] == "SUCCESS")
	{
		// TODO
                    // 相关操作,保存相关数据,数据库操作 .......
                    
		return true;
	}
	return false;
}
posted @ 2017-11-30 15:41  mzxl1987  阅读(2068)  评论(0编辑  收藏  举报