thinkphp微信浏览器内拉起微信支付
vendor/wxpay/pay.php
<?php
/*
+-----------------------------------+
| 微信支付类 |
+-----------------------------------+
*/
require_once 'config.php'; class pay{ public $params = array();
private $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
private $prepay_id; //统一下单号 /**
*
* 获取jsapi支付的参数
* @param array $UnifiedOrderResult 统一支付接口返回的数据
* @throws WxPayException
* @return json数据,可直接填入js函数作为参数
*/
public function GetJsApiParameters()
{
$this->doneOrder();
$timeStamp = time();
$this->params = array(
'appId' => Config::APPID,
'timeStamp'=> "$timeStamp",
'nonceStr' => $this->getNonceStr(),
'package' => 'prepay_id=' . $this->prepay_id,
'signType' => 'MD5'
);
$this->params['paySign'] = $this->MakeSign();
} /**
* 统一下单
* @return array
*/
public function doneOrder(){
$this->params['mch_id'] = Config::MCHID;
$this->params['appid'] = Config::APPID;
$this->params['sign'] = $this->MakeSign($this->params);
$response = $this->FromXml($this->postXmlCurl($this->ToXml(), $this->url, false));
$this->prepay_id = $response['prepay_id']; } /**
* 验证
* @return array 返回数组格式的notify数据
*/
public function notify(){
//获取xml
$xml = file_get_contents('php://input');
//转成php数组
$this->params = $this->FromXml($xml);
//保存原sign
$data_sign = $this->params['sign'];
//sign不参与签名
unset($this->params['sign']);
$sign = $this->makeSign();
//判断签名是否正确 判断支付状态
if ($sign===$data_sign && $this->params['return_code']=='SUCCESS' && $this->params['result_code']=='SUCCESS') {
$result = $this->params;
$str = '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
}else{
$result = false;
$str = '<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[签名失败]]></return_msg></xml>';
}
echo $str;
return $result;
} /**
* 生成签名
* @return 签名,本函数不覆盖sign成员变量,如要设置签名需要调用SetSign方法赋值
*/
public function MakeSign()
{
//签名步骤一:按字典序排序参数
ksort($this->params);
$string = $this->ToUrlParams();
//签名步骤二:在string后加入KEY
$string = $string . '&key=' . Config::KEY;
//签名步骤三:MD5加密
$string = md5($string);
//签名步骤四:所有字符转为大写
$result = strtoupper($string);
return $result;
} /**
* 格式化参数格式化成url参数
*/
public function ToUrlParams()
{
$buff = '';
foreach($this->params as $k => $v)
{
if($k!='sign' && $v!='' && !is_array($v)){
$buff .= $k . '=' . $v . '&';
}
}
$buff = trim($buff, '&');
return $buff;
} /**
* 以post方式提交xml到对应的接口url
* @param string $xml 需要post的xml数据
* @param string $url url
* @param bool $useCert 是否需要证书,默认不需要
* @param int $second url执行超时时间,默认30s
* @throws WxPayException
*/
private static function postXmlCurl($xml, $url, $useCert = false, $second = 30)
{
$ch = curl_init();
//设置超时
curl_setopt($ch, CURLOPT_TIMEOUT, $second);
//如果有配置代理这里就设置代理
if(Config::CURL_PROXY_HOST != "0.0.0.0" && Config::CURL_PROXY_PORT != 0){
curl_setopt($ch,CURLOPT_PROXY, Config::CURL_PROXY_HOST);
curl_setopt($ch,CURLOPT_PROXYPORT, Config::CURL_PROXY_PORT);
}
curl_setopt($ch,CURLOPT_URL, $url);
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE);//严格校验
//设置header
curl_setopt($ch, CURLOPT_HEADER, FALSE);
//要求结果为字符串且输出到屏幕上
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
if($useCert == true){
//设置证书
//使用证书:cert 与 key 分别属于两个.pem文件
curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
curl_setopt($ch,CURLOPT_SSLCERT, Config::SSLCERT_PATH);
curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
curl_setopt($ch,CURLOPT_SSLKEY, Config::SSLKEY_PATH);
}
//post提交方式
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
//运行curl
$data = curl_exec($ch);
//返回结果
if($data){
curl_close($ch);
return $data;
} else {
$error = curl_errno($ch);
curl_close($ch);
throw new Exception("curl出错,错误码:$error");
}
} /**
* 输出xml字符
* @throws WxPayException
**/
public function ToXml()
{
if(!is_array($this->params) || count($this->params) <= 0)
{
throw new Exception('数组数据异常!');
}
$xml = '<xml>';
foreach($this->params as $key=>$val)
{
if(is_numeric($val)){
$xml .= '<'.$key.'>'.$val.'</'.$key.'>';
}else{
$xml .= '<'.$key.'><![CDATA['.$val.']]></'.$key.'>';
}
}
$xml .= '</xml>';
return $xml;
} /**
* 将xml转为array
* @param string $xml
* @throws WxPayException
*/
public function FromXml($xml)
{
if(!$xml){
throw new Exception('xml数据异常!');
}
//将XML转为array
//禁止引用外部xml实体
libxml_disable_entity_loader(true);
$this->params = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
return $this->params;
} /**
*
* 产生随机字符串,不长于32位
* @param int $length
* @return 产生的随机字符串
*/
public function getNonceStr($length = 32)
{
$chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
$str = '';
for($i = 0; $i<$length; $i++){
$str .= substr($chars, mt_rand(0, strlen($chars)-1), 1);
}
return $str;
}
}
?>
vendor/wxpay/config.php
<?php
/**
* 配置账号信息
*/ class Config
{
//=======【基本信息设置】=====================================
//
/**
* 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 = 'wx000000000000';
const MCHID = 'xxxxxxx';
const KEY = 'xxxxxxxxxxxxxxxxxxxxxxxxxxx';
const APPSECRET = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'; //=======【证书路径设置】=====================================
/**
* TODO:设置商户证书路径
* 证书路径,注意应该填写绝对路径(仅退款、撤销订单时需要,可登录商户平台下载,
* API证书下载地址:https://pay.weixin.qq.com/index.php/account/api_cert,下载之前需要安装商户操作证书)
* @var path
*/
const SSLCERT_PATH = 'cert/apiclient_cert.pem';
const SSLKEY_PATH = 'cert/apiclient_key.pem'; //=======【curl代理设置】===================================
/**
* TODO:这里设置代理机器,只有需要代理的时候才设置,不需要代理,请设置为0.0.0.0和0
* 本例程通过curl使用HTTP POST方法,此处可修改代理服务器,
* 默认CURL_PROXY_HOST=0.0.0.0和CURL_PROXY_PORT=0,此时不开启代理(如有需要才设置)
* @var unknown_type
*/
const CURL_PROXY_HOST = "0.0.0.0";//"10.152.18.220";
const CURL_PROXY_PORT = 0;//8080; //=======【上报信息配置】===================================
/**
* TODO:接口调用上报等级,默认紧错误上报(注意:上报超时间为【1s】,上报无论成败【永不抛出异常】,
* 不会影响接口调用流程),开启上报之后,方便微信监控请求调用的质量,建议至少
* 开启错误上报。
* 上报等级,0.关闭上报; 1.仅错误出错上报; 2.全量上报
* @var int
*/
const REPORT_LEVENL = 0;
}
vendor/cert/apiclient_cert.pem vendor/cert/apiclient_key.pem 控制器Controller
Vendor('wechat.pay'); class Wechat extends Base
{
public function wxPay(){
$payobj = new \pay();
$openid = input('post.openid/s');
$needMoney = input('post.money/s');
if (!empty($openid)) {
//统一下单
$orderid = $this->build_order_no();
$notify_url = 'http://xxxxxx/Wechat/notify'; $payobj->params = [
'openid' => $openid,
'body' => 'body',
'out_trade_no' => $orderid,
'total_fee' => $needMoney * 100,
'nonce_str' => $this->getNonceStr(),
'spbill_create_ip' => getIp(),
'notify_url' => $notify_url,
'trade_type' => 'JSAPI'
]; $payobj->GetJsApiParameters();
$data = [
'order_num' => $orderid,
'user_open_id' => $openid,
'pay_money' => $needMoney,
];
$oid = Db::name('order_pay')->insert($data);
if($oid){
return ['status'=>'0','info'=>'ok','data'=>json_encode($payobj->params)];
}
return ['status'=>'-1','info'=>'下单失败,请重试']; }
} //微信支付回调
public function notify(){
$payobj = new \pay();
$result = $payobj->notify();
if($result){
//成功后回调
$where['order_num'] = $result['out_trade_no'];
//根据需求处理逻辑 }
} /**
* 生成订单号码
* @return string
*/
public function build_order_no() {
return date('Ymd') . substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 6), 1))), 0, 8) . mt_rand(100,999);
} /**
* 产生随机字符串,不长于32位
* @param int $length
* @return 产生的随机字符串
*/
public function getNonceStr($length = 32) {
$chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
$str = '';
for($i = 0; $i<$length; $i++){
$str .= substr($chars, mt_rand(0, strlen($chars)-1), 1);
}
return $str;
} }
页面上View 引用jquery; 引用layui.js 引用jweixin-1.1..js
<script type="text/javascript"> $.ajax({
url:"http://xxxxxx/Wechat/wxPay",
type:'post',
data:{'money':money,'openid':openid},
async : false,
dataType: "JSON",
success:function(data){
if(data.status === '0'){
var params = $.parseJSON(data.data);
// alert(data.url);
WeixinJSBridge.invoke('getBrandWCPayRequest', params, function(res){
if(res.err_msg == 'get_brand_wcpay_request:cancel'){
layer.open({
content: '您消了此次支付'
,skin: 'msg'
,time: 5 //2秒后自动关闭
});
}else if(res.err_msg == 'get_brand_wcpay_request:fail'){
layer.open({
content: '支付失败,请重新支付'
,skin: 'msg'
,time: 5 //2秒后自动关闭
});
}else if(res.err_msg == 'get_brand_wcpay_request:ok'){
layer.open({
content: '支付成功'
,skin: 'msg'
,time: 5 //2秒后自动关闭
});
setTimeout(function(){
window.location.href = 'index.html';
},2000);
}else{
layer.open({
content: "未知错误"+res.error_msg
,skin: 'msg'
,time: 5 //2秒后自动关闭
});
}
});
}else{
layer.open({
content: data.info
,skin: 'msg'
,time: 5 //2秒后自动关闭
});
return false;
}
}
}); </script>
thinkphp微信浏览器内拉起微信支付的更多相关文章
- H5 网站支付宝支付(前端部分)包含微信浏览器中的处理方法。
手机网站唤起支付宝支付: H5 网站实现支付宝支付是一个很常见的需求: 实现方式主要是在后台配置和预支付, 前端需要做的就是唤起 支付宝App 然后就可以输入密码支付. 这个其实难度很低, 主要就是在 ...
- 微信网页授权-公众号支付(获取openid、用户信息等)
名词解释: openid 用户唯一标识,请注意,在未关注公众号时,用户访问公众号的网页,也会产生一个用户和公众号唯一的OpenID 业务功能描述:实现H5页面可以在微信浏览器里面进行微信支付,所以需要 ...
- js判断移动端浏览器类型,微信浏览器、支付宝小程序、微信小程序等
起因 现在市场上各种跨平台开发方案百家争鸣各有千秋,个人认为最成熟的还是hybird方案,简单的说就是写H5各种嵌入,当然作为前端工程师最希望的也就是公司采用hybird方案当作技术路线. 所谓的hy ...
- JS 判断PC、android、ios、微信浏览器
1.通过js userAgent来判断 <h1>判断访问此链接的操作系统</h1> <script> var Agents = new Array("An ...
- es6 Object.assign ECMAScript 6 笔记(六) ECMAScript 6 笔记(一) react入门——慕课网笔记 jquery中动态新增的元素节点无法触发事件解决办法 响应式图像 弹窗细节 微信浏览器——返回操作 Float 的那些事 Flex布局 HTML5 data-* 自定义属性 参数传递的四种形式
es6 Object.assign 目录 一.基本用法 二.用途 1. 为对象添加属性 2. 为对象添加方法 3. 克隆对象 4. 合并多个对象 5. 为属性指定默认值 三.浏览器支持 ES6 O ...
- PHP和js判断访问设备是否是微信浏览器实例
PHP和js判断访问设备是否是微信浏览器实例,代码非常精简,适合新手学习. js判断是否是微信浏览器: 1 function is_weixin() { 2 var ua = window.navig ...
- 黄聪:微信h5支付demo微信H5支付demo非微信浏览器支付demo微信wap支付
一.首先先确定H5支付权限已经申请! 二.开发流程 1.用户在商户侧完成下单,使用微信支付进行支付 2.由商户后台向微信支付发起下单请求(调用统一下单接口)注:交易类型trade_type=MWEB ...
- JAVA开发微信支付-公众号支付/微信浏览器支付(JSAPI)
写这篇文章的目的有2个,一是自己的项目刚开发完微信支付功能,趁热回个炉温习一下,二也是帮助像我这样对微信支付不熟悉,反复看了多天文档还是一知半解,原理都没摸清,更不要说实现了.本以为网上的微信开发教程 ...
- H5版如何在微信外(非微信浏览器)进行微信支付技术方案
官方是支持在非微信内置浏览器中调起微信支付的!H5支付是基于公众号基础开发的一种非微信内浏览器支付方式(需要单独申请支付权限),可以满足在微信外的手机H5页面进行微信支付的需求.同时,由于H5链接传播 ...
随机推荐
- 作业二:分布式版本控制系统Git的安装与使用
作业要求来自于:https://edu.cnblogs.com/campus/gzcc/GZCC-16SE2/homework/2097 1.下载安装配置用户名和邮箱. (1)下载安装Github配置 ...
- CSS3基础入门01
CSS3 基础入门 01 前言 相对于css2来说,css3更新了很多的内容,其中包括选择器.颜色.阴影.背景.文本.边框.新的布局方案.2d.3d.动画等等. 而如果想要学习css3的诸多部分,不妨 ...
- 中国剩余定理 CRT
中国剩余定理 CRT 正常版本CRT 要解的是一个很容易的东西 \[ \begin{aligned} x\equiv a_1(mod\ m_1)\\ x\equiv a_2(mod\ m_2)\\ . ...
- python xpath学习
一.选取节点: 二.谓词: 注意:在scrapy中用xpath进行搜索时,如果使用相对路径,要加上.,如,不然搜索的是整个文档.
- 随手记一个漂亮的code
代码 从前有个代码长这样 if (a) { if (b) { c } } else { if (d) { c } } 后来长这样 if (a && b || !a && ...
- Nginx反向代理、负载均衡、动静分离、缓存、压缩、防盗链、跨域访问
一.反向代理 1.在192.168.189.130机器启动tomcat服务,http://192.168.189.130:8080/ 访问服务正常 2.在192.168.189.131机器配置ngin ...
- 金融量化分析【day111】:Pandas-时间序列处理
一.时间对象处理 1.start 开始时间 df["2018-12-01":"2018-12-30"] 2.end 结束时间 df['2018'] ...... ...
- swiper常见问题
swiper是一个比较不错的一个轮播插件,但是呢,有时候在使用的时候也会出现很多的问题,我将我遇到的一些问题解决办法写在下面. 第一个问题:swiper分页器不显示 一般swiper使用分页器都是这样 ...
- NOI-OJ 2.2 ID:8758 2的幂次方表示
思路 可以把任意一个数转化为2^a+2^b+2^c+...+2^n 例如137的二进制为10001001,这就等效于2^7+2^3+2^0 以上结果如何通过程序循环处理呢?需要把数字n分解为上述公式, ...
- sql注入学习 sqlliab教程 lesson1 (sqlliab搭建教程)
靶场搭建 小白建议直接用集成环境.推荐laragon (由于这套靶场较早,需要使用php7.0以下环境,安装完php laragon需要在安装php低版本,默认laragon只集成了一个7.0的php ...