TPshop学习(8)微信支付
http://blog.csdn.net/phper8/article/details/76383415
学习内容:
https://www.kancloud.cn/tpshop/thinkphp5/305718
这节课讲微信扫码支付。
初步简单的理解微信支付对接流程:
流程图:
* 什么是二维码?
打开下面url,将看到一个二维码。
demo5.tp-shop.cn/index.php?m=Home&c=index&a=qr_code&data=http%3A%2F%2Fwww.tp-shop.cn
查看项目中代码,qr_code方法:
// 二维码
public function qr_code(){
// 导入Vendor类库包 Library/Vendor/Zend/Server.class.php
//http://www.tp-shop.cn/Home/Index/erweima/data/www.99soubao.com
//require_once 'vendor/phpqrcode/phpqrcode.php';
vendor('phpqrcode.phpqrcode');
//import('Vendor.phpqrcode.phpqrcode');
error_reporting(E_ERROR);
$url = urldecode($_GET["data"]);
\QRcode::png($url);
exit;
}
附:
二维码解码器 在线识别系统
jiema.wwei.cn
== 下面开始讲 微信支付 ==
1.先申请微信支付商户号。。
2.后台填写,配置。
3.测试一条商品支付。
4.支付完成。
顺着支付订单的页面,看代码:
/application/home/controller/Cart.php
/*
* 订单支付页面
*/
public function cart4(){ $order_id = I('order_id/d');
$order = M('Order')->where("order_id", $order_id)->find(); // 如果已经支付过的订单直接到订单详情页面. 不再进入支付页面
if($order['pay_status'] == 1){
$order_detail_url = U("Home/User/order_detail",array('id'=>$order_id));
header("Location: $order_detail_url");
exit;
}
//如果是预售订单,支付尾款
if($order['pay_status'] == 2 && $order['order_prom_type'] == 4){
$pre_sell_info = M('goods_activity')->where(array('act_id'=>$order['order_prom_id']))->find();
$pre_sell_info = array_merge($pre_sell_info,unserialize($pre_sell_info['ext_info']));
if($pre_sell_info['retainage_start'] > time()){
$this->error('还未到支付尾款时间'.date('Y-m-d H:i:s',$pre_sell_info['retainage_start']));
}
if($pre_sell_info['retainage_end'] < time()){
$this->error('对不起,该预售商品已过尾款支付时间'.date('Y-m-d H:i:s',$pre_sell_info['retainage_start']));
}
}
if($order['order_prom_type'] != 4){
$userlogic = new UsersLogic();
$res = $userlogic->abolishOrder($order['user_id'],$order['order_id'],$order['add_time']); //检测是否超时没支付
if($res['status']==1)
$this->error('订单超时未支付已自动取消',U("Home/User/order_detail",array('id'=>$order_id)));
} $payment_where = array(
'type'=>'payment',
'status'=>1,
'scene'=>array('in',array(0,2))
);
//预售和抢购暂不支持货到付款
$orderGoodsPromType = M('order_goods')->where(['order_id'=>$order['order_id']])->getField('prom_type',true);
if($order['order_prom_type'] == 4 || in_array(1,$orderGoodsPromType)){
$payment_where['code'] = array('neq','cod');
}
$paymentList = M('Plugin')->where($payment_where)->select();
$paymentList = convert_arr_key($paymentList, 'code'); foreach($paymentList as $key => $val)
{
$val['config_value'] = unserialize($val['config_value']);
if($val['config_value']['is_bank'] == 2)
{
$bankCodeList[$val['code']] = unserialize($val['bank_code']);
}
} $bank_img = include APP_PATH.'home/bank.php'; // 银行对应图片
$this->assign('paymentList',$paymentList);
$this->assign('bank_img',$bank_img);
$this->assign('order',$order);
$this->assign('bankCodeList',$bankCodeList);
$this->assign('pay_date',date('Y-m-d', strtotime("+1 day"))); return $this->fetch();
}
然后进入
/template/pc/cart/cart4.html
<form action="{:U('Home/Payment/getCode')}" method="post" name="cart4_form" id="cart4_form">
</form>
再看:Home/Payment/getCode
- 1
其中:this−>payment−>getcode(order,$config_value);
这就要看__construct(),可知,指的是,plugins/payment/weixin/weixin.class.php
代码如下(代码中是以alipay举例)
class Payment extends Base { public $payment; // 具体的支付类
public $pay_code; // 具体的支付code /**
* 析构流函数
*/
public function __construct() {
parent::__construct(); // tpshop 订单支付提交
$pay_radio = $_REQUEST['pay_radio'];
if(!empty($pay_radio))
{
$pay_radio = parse_url_param($pay_radio);
$this->pay_code = $pay_radio['pay_code']; // 支付 code
}
else // 第三方 支付商返回
{
//file_put_contents('./a.html',$_GET,FILE_APPEND);
$this->pay_code = I('get.pay_code');
unset($_GET['pay_code']); // 用完之后删除, 以免进入签名判断里面去 导致错误
}
//获取通知的数据
$xml = $GLOBALS['HTTP_RAW_POST_DATA']; if(empty($this->pay_code))
exit('pay_code 不能为空');
// 导入具体的支付类文件
include_once "plugins/payment/{$this->pay_code}/{$this->pay_code}.class.php"; // D:\wamp\www\svn_tpshop\www\plugins\payment\alipay\alipayPayment.class.php
$code = '\\'.$this->pay_code; // \alipay
$this->payment = new $code();
}
...略
/**
* tpshop 提交支付方式
*/
public function getCode(){
//C('TOKEN_ON',false); // 关闭 TOKEN_ON
header("Content-type:text/html;charset=utf-8");
$order_id = I('order_id/d'); // 订单id
session('order_id',$order_id); // 最近支付的一笔订单 id
// 修改订单的支付方式
$payment_arr = M('Plugin')->where("`type` = 'payment'")->getField("code,name");
M('order')->where("order_id",$order_id)->save(array('pay_code'=>$this->pay_code,'pay_name'=>$payment_arr[$this->pay_code])); $order = M('order')->where("order_id", $order_id)->find();
if($order['pay_status'] == 1){
$this->error('此订单,已完成支付!');
}
// tpshop 订单支付提交
$pay_radio = $_REQUEST['pay_radio'];
$config_value = parse_url_param($pay_radio); // 类似于 pay_code=alipay&bank_code=CCB-DEBIT 参数 //微信JS支付
if($this->pay_code == 'weixin' && $_SESSION['openid'] && strstr($_SERVER['HTTP_USER_AGENT'],'MicroMessenger')){
$code_str = $this->payment->getJSAPI($order,$config_value);
exit($code_str);
}else{
$code_str = $this->payment->get_code($order,$config_value);
}
$this->assign('code_str', $code_str);
$this->assign('order_id', $order_id);
return $this->fetch('payment'); // 分跳转 和不 跳转
}
...略
}
注意:this−>payment−>getcode(order,$config_value);
是weixin.class.php中的get_code
/**
* 生成支付代码
* @param array $order 订单信息
* @param array $config_value 支付方式信息
*/
function get_code($order, $config_value)
{
$notify_url = SITE_URL.'/index.php/Home/Payment/notifyUrl/pay_code/weixin'; // 接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数。
//$notify_url = C('site_url').U('Home/Payment/notifyUrl',array('pay_code'=>'weixin')); // 接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数。
//$notify_url = C('site_url')."/index.php?m=Home&c=Payment&a=notifyUrl&pay_code=weixin";
$input = new WxPayUnifiedOrder();
$input->SetBody("TPshop商品"); // 商品描述
$input->SetAttach("weixin"); // 附加数据,在查询API和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据
$input->SetOut_trade_no($order['order_sn'].time()); // 商户系统内部的订单号,32个字符内、可包含字母, 其他说明见商户订单号
$input->SetTotal_fee($order['order_amount']*100); // 订单总金额,单位为分,详见支付金额
$input->SetNotify_url($notify_url); // 接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数。
$input->SetTrade_type("NATIVE"); // 交易类型 取值如下:JSAPI,NATIVE,APP,详细说明见参数规定 NATIVE--原生扫码支付
$input->SetProduct_id("123456789"); // 商品ID trade_type=NATIVE,此参数必传。此id为二维码中包含的商品ID,商户自行定义。
$notify = new NativePay();
$result = $notify->GetPayUrl($input); // 获取生成二维码的地址
$url2 = $result["code_url"];
return '<img alt="模式二扫码支付" src="/index.php?m=Home&c=Index&a=qr_code&data='.urlencode($url2).'" style="width:110px;height:110px;"/>';
}
这里就出来了,二维码的图片。主要就是这个get_code。
这里成功后,用户扫码。扫码成功后,返回到$notify_url的地址。
$notify_url = SITE_URL.'/index.php/Home/Payment/notifyUrl/pay_code/weixin'; 1 /application/home/controller/Payment.php 看notifyUrl() // 服务器点对点 // http://www.tp-shop.cn/index.php/Home/Payment/notifyUrl
public function notifyUrl(){
$this->payment->response();
exit();
}
再看weixin.class.php中的response()
/**
* 服务器点对点响应操作给支付接口方调用
*
*/
function response()
{
require_once("example/notify.php");
$notify = new PayNotifyCallBack();
$notify->Handle(false);
}
主要是:plugins/payment/weixin/example/notify.php
//重写回调处理函数
public function NotifyProcess($data, &$msg)
{
Log::DEBUG("call back:" . json_encode($data));
$notfiyOutput = array(); if(!array_key_exists("transaction_id", $data)){
$msg = "输入参数不正确";
return false;
}
//查询订单,判断订单真实性
if(!$this->Queryorder($data["transaction_id"])){
$msg = "订单查询失败";
return false;
}
$appid = $data['appid']; //公众账号ID
$order_sn = $out_trade_no = $data['out_trade_no']; //商户系统的订单号,与请求一致。
$attach = $data['attach']; //商家数据包,原样返回
//file_put_contents('/web/tpshop2/c.html',print_r($data,true),FILE_APPEND);
//20160316 JSAPI支付情况 去掉订单号后面的十位时间戳
if(strlen($order_sn) > 18){
$order_sn = substr($order_sn,0,18);
}
update_pay_status($order_sn); // 修改订单支付状态 return true;
}
update_pay_status($order_sn); // 修改订单支付状态
- 1
这个方法在common.php
/**
* 支付完成修改订单
* @param $order_sn 订单号
* @param array $ext 额外参数
* @return bool|void
*/
function update_pay_status($order_sn,$ext=array())
{
if(stripos($order_sn,'recharge') !== false){
//用户在线充值
$count = M('recharge')->where(['order_sn'=>$order_sn,'pay_status'=>0])->count(); // 看看有没已经处理过这笔订单 支付宝返回不重复处理操作
if($count == 0) return false;
$order = M('recharge')->where("order_sn", $order_sn)->find();
M('recharge')->where("order_sn",$order_sn)->save(array('pay_status'=>1,'pay_time'=>time()));
accountLog($order['user_id'],$order['account'],0,'会员在线充值');
}else{
// 如果这笔订单已经处理过了
$count = M('order')->master()->where("order_sn = :order_sn and pay_status = 0 OR pay_status = 2")->bind(['order_sn'=>$order_sn])->count(); // 看看有没已经处理过这笔订单 支付宝返回不重复处理操作
if($count == 0) return false;
// 找出对应的订单
$order = M('order')->master()->where("order_sn",$order_sn)->find();
//预售订单
if ($order['order_prom_type'] == 4) {
$orderGoodsArr = M('OrderGoods')->where(array('order_id'=>$order['order_id']))->find();
// 预付款支付 有订金支付 修改支付状态 部分支付
if($order['total_amount'] != $order['order_amount'] && $order['pay_status'] == 0){
//支付订金
M('order')->where("order_sn", $order_sn)->save(array('order_sn'=> date('YmdHis').mt_rand(1000,9999) ,'pay_status' => 2, 'pay_time' => time(),'paid_money'=>$order['order_amount']));
M('goods_activity')->where(array('act_id'=>$order['order_prom_id']))->setInc('act_count',$orderGoodsArr['goods_num']);
}else{
//全额支付 无订金支付 支付尾款
M('order')->where("order_sn", $order_sn)->save(array('pay_status' => 1, 'pay_time' => time()));
$pre_sell = M('goods_activity')->where(array('act_id'=>$order['order_prom_id']))->find();
$ext_info = unserialize($pre_sell['ext_info']);
//全额支付 活动人数加一
if(empty($ext_info['deposit'])){
M('goods_activity')->where(array('act_id'=>$order['order_prom_id']))->setInc('act_count',$orderGoodsArr['goods_num']);
}
}
} else {
// 修改支付状态 已支付
M('order')->where("order_sn", $order_sn)->save(array('pay_status'=>1,'pay_time'=>time()));
}
// 减少对应商品的库存
minus_stock($order['order_id']);
// 给他升级, 根据order表查看消费记录 给他会员等级升级 修改他的折扣 和 总金额
update_user_level($order['user_id']);
// 记录订单操作日志
if(array_key_exists('admin_id',$ext)){
logOrder($order['order_id'],$ext['note'],'付款成功',$ext['admin_id']);
}else{
logOrder($order['order_id'],'订单付款成功','付款成功',$order['user_id']);
}
//分销设置
M('rebate_log')->where("order_id" ,$order['order_id'])->save(array('status'=>1));
// 成为分销商条件
$distribut_condition = tpCache('distribut.condition');
if($distribut_condition == 1) // 购买商品付款才可以成为分销商
M('users')->where("user_id", $order['user_id'])->save(array('is_distribut'=>1)); //用户支付, 发送短信给商家
$res = checkEnableSendSms("4");
if(!$res || $res['status'] !=1) return ; $sender = tpCache("shop_info.mobile");
if(empty($sender))return;
$params = array('order_sn'=>$order_sn);
sendSms("4", $sender, $params);
} }
Tpshop的微信支付就简单介绍到此,
需要我们再多研究,不是一下子就能理解和掌握。
加油!
学习改变命运,技术成就梦想!
坚持不懈的努力,其结果一定是成功!
回调业务处理逻辑:
TPshop学习(8)微信支付的更多相关文章
- 微信小程序------微信支付模块
最近项目涉及到小程序开发:需要进行微信支付模块,接下来通过叙述,记录一下微信小程序中微信支付模块的开发,以便日后翻阅和使用. 学习指南----------微信支付开发文档:https://pay.we ...
- 华水开学第一课&微信支付
由于疫情的延续,导致我们不能及时开学.只能在网上观看华水开学第一课,但是好像正常开学也没有这个哈哈(不记得了) 昨天没有玩到很晚,12点就睡下.大约半个小时睡着了.定了8点的闹钟.起来的时候那是真的困 ...
- [转帖]"微信支付"勒索病毒制造者被锁定 传播、危害和疫情终极解密 --- 可以学习下一年火绒团队的分析原理的精神.
"微信支付"勒索病毒制造者被锁定 传播.危害和疫情终极解密 https://www.cnbeta.com/articles/tech/794851.htm 12月1日,首个要求&q ...
- python开发微信支付学习记录(转)
前言 微信支付是由微信及财付通联合推出的移动支付创新产品.如今,随着微信支付的全面开放,相关需求也越来越多,很多开发人员进行微信支付开发及商家申请微信支付时,面临着诸多疑惑. 要想开发顺利进行,首先要 ...
- 【原创分享·微信支付】 C# MVC 微信支付教程系列之扫码支付
微信支付教程系列之扫码支付 今天,我们来一起探讨一下这个微信扫码支付.何为扫码支付呢?这里面,扫的码就是二维码了,就是我们经常扫一扫的那种二维码图片,例如,我们自己添 ...
- 基于H5的微信支付开发详解
这次总结一下用户在微信内打开网页时,可以调用微信支付完成下单功能的模块开发,也就是在微信内的H5页面通过jsApi接口实现支付功能.当然了,微信官网上的微信支付开发文档也讲解的很详细,并且有实现代码可 ...
- iOS之微信支付
前言:下面介绍微信支付的开发流程的细节,图文并茂,你可以按照我的随笔流程过一遍代码.包你也学会了微信支付.而且支付也是面试常问的内容. 正文: 1.首先在开始使用微信支付之前,有一些东西是开发者必须要 ...
- IOS开发--微信支付
前言:下面介绍微信支付的开发流程的细节,图文并茂,你可以按照我的随笔流程过一遍代码.包你也学会了微信支付.而且支付也是面试常问的内容. 正文: 1.首先在开始使用微信支付之前,有一些东西是开发者必须要 ...
- PHP微信支付开发实例
这篇文章主要为大家详细介绍了PHP微信支付开发过程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 PHP微信支付开发过程,分享给大家,供大家参考,具体内容如下 1.开发环境 Thinkphp 3. ...
随机推荐
- gitlab 远程 定时备份
=============================================== 2017/11/1_第2次修改 ccb_warlock 更新 ...
- 通过 kms 激活 office 2016
1.管理员模式打开cmd,并切换到office的安装路径 注:office2016默认安装在C:\Program Files\Microsoft Office\Office16,激活其他office自 ...
- Webpack 2 视频教程 009 - 配置 ESLint 实现代码规范自动测试 (上)
原文发表于我的技术博客 这是我免费发布的高质量超清「Webpack 2 视频教程」. Webpack 作为目前前端开发必备的框架,Webpack 发布了 2.0 版本,此视频就是基于 2.0 的版本讲 ...
- KVO键值观察的具体实现
1.KVO简介 KVO是Objective-C对观察者设计模式的一种实现,它提供一种机制,指定一个被观察对象(如A类),当对象中的某个属性发生变化的时候,对象就会接收到通知,并作出相应的处理.在MVC ...
- k8s 核心功能 - 每天5分钟玩转 Docker 容器技术(116)
本节带领大家快速体验 k8s 的核心功能:应用部署.访问.Scale Up/Down 以及滚动更新. 部署应用 执行命令: kubectl run kubernetes-bootcamp \ --im ...
- Jenkins 学习笔记(三):我们的JAVA 项目是这么发布的
发布拓扑 1. 拓扑图 2. 流程说明: Git 插件从 Git Server 上面拉取源代码. Maven 插件将源代码安装我们设定的指令进行编译打包,存放于项目的 WorkSpace. Publi ...
- zabbix-server端与zabbix-agent端部署与监控
环境: [root@redis ~]# uname -a Linux redis -.el6.x86_64 # SMP Tue Mar :: UTC x86_64 x86_64 x86_64 GNU/ ...
- 使用阿里云镜像maven管理配置开发环境
修改方法:在~/.m2目录下的settings.xml文件中,(如果该文件不存在,则需要从maven/conf目录下拷贝一份),找到<mirrors>标签,添加如下子标签: <mir ...
- 设备树的interrupt
http://www.cnblogs.com/targethero/p/5080499.html https://www.cnblogs.com/xiaojiang1025/p/6131381.htm ...
- 高通secury boot过程
整理内容网盘地址: 链接:https://share.weiyun.com/79c3920b4f2097d93b719b3149a7f3f9 (密码:4jm9cx) 相关内容网站: http://bl ...