业务流程时序图
php
业务流程说明:
(1)商户后台系统根据微信支付规定格式生成二维码(规则见下文),展现给用户扫码。html
(2)用户打开微信“扫一扫”扫描二维码,微信客户端将扫码内容发送到微信支付系统。数据库
(3)微信支付系统收到客户端请求,发起对商户后台系统支付回调URL的调用。调用请求将带productid和用户的openid等参数,并要求商户系统返回交数据包,详细请见"本节3.1回调数据输入参数"json
(4)商户后台系统收到微信支付系统的回调请求,根据productid生成商户系统的订单。api
(5)商户系统调用微信支付【统一下单API】请求下单,获取交易会话标识(prepay_id)安全
(6)微信支付系统根据商户系统的请求生成预支付交易,并返回交易会话标识(prepay_id)。服务器
(7)商户后台系统获得交易会话标识prepay_id(2小时内有效)。微信
(8)商户后台系统将prepay_id返回给微信支付系统。返回数据见"本节3.2回调数据输出参数"app
(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
<?php
ini_set('date.timezone','Asia/Shanghai');
//error_reporting(E_ERROR);
//这地方注意require_once的设置,base_path是获取到项目的根目录,后面路径的设置根据我的项目结构改变
require_once base_path()."/app/Wxpay/lib/WxPay.Api.php";
require_once base_path()."/app/Wxpay/example/WxPay.NativePay.php";
require_once base_path().'/app/Wxpay/example/log.php';
//模式一
/**
?>
{{ 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; }