PC网站微信登录:
流程:
2 第二步:通过code换取网页授权access_token
4 第四步:拉取用户信息(需scope为 snsapi_userinfo)
所需材料:
1、在开放平台申请开发者认证。
2、认证通过后创建网站应用
3、拿到所需APPID相关信息开发需要用到。
网址:https://open.weixin.qq.com/cgi-bin/index?t=home/index&lang=zh_CN
代码:
html代码:
<!-- KDT获取 -->
<meta name="Keywords" content="{$key}"/>
<meta name="Description" content="{$des}"/>
<title>登录</title>
<link rel="stylesheet" href="{:config('home_file')}css/simple.css">
<!-- 引入公共头部 -->
{include file="public:header" /}
<section class="login">
<div class="container">
<div class="con">
<div class="text"></div>
<div class="box">
<ul class="clearfix">
<li class="on" onclick="tab(1)"><i class="wx"></i>微信登录</li>
<li onclick="tab(2)"><i class="ph"></i>手机登录</li>
</ul>
<div class="wx-con">
<div id="Wechat_img"></div>
</div>
<div class="ph-con">
<form action="__URL__/sign_handle" method="post" name="login">
<div class="list">
<input type="text" placeholder="手机号:" name="mobile" class="mobile" required="required"/>
</div>
<div class="list clearfix">
<input type="text" placeholder="图形验证码:" name="capimg" class="capimg" required="required" />
<img src="__URL__/show_captcha" id="capimg"/>
</div>
<div class="list clearfix">
<input type="text" placeholder="短信验证码:" name="sms" class="sms" required="required" pattern='^\w{4,6}$'/>
<button type="button" class="getsms" data-action="login">获取</button>
</div>
<div class="list">
<input type="submit" value="登录" onclick="return checkform()"/>
</div>
</form>
</div>
</div>
</div>
</div>
</section>
<script type="text/javascript" src="{:config('home_file')}js/simple.js"></script>
<script type="text/javascript" src="https://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js"></script>
<script>
var obj = new WxLogin({
self_redirect:false,
id:"Wechat_img",
appid: "{$appid}",
scope: "snsapi_login",
redirect_uri: "{$redirect_uri}",
state: "",
style: "",
href: "https://www.yx685.com/public/static/home/css/wx_login.css"
});
$(".moveup").on('click',function(){
$('html,body').animate({scrollTop: '0px'}, 300);
});
</script>
PHP代码:
public function login()
{
if(input('?get.url')){
session('login_return_url',input('get.url'));
}
$wechat = new Wechat();
$this->assign('appid',$wechat->appid);
$this->assign('redirect_uri',urlencode('http://www.yx685.com/home/simple/code_redirect_uri'));
if(input('?get.type') && input('get.type') == 'code'){
$wechat = new Wechat();
$get_code = $wechat->get_code();
header('location:'.$get_code);exit;
}
return $this->fetch();
}
public function code_redirect_uri(){
$wechat = new Wechat();
$code = input('get.code');
$access_res = $wechat->get_access_token($code);
$access_arr = array();
$access_arr = json_decode($access_res,true);
if(isset($access_arr['errcode'])){
$this->error('获取凭证失败,请返回上级页面重新登录');
}
//检测access_token
$check_res = $wechat->check_access($access_arr['access_token'],$access_arr['openid']);
$check_arr = json_decode($check_res,true);
if($check_arr['errcode'] != 0){
//刷新凭证
$access_res = $wechat->refresh_token($access_arr['refresh_token']);
//销毁上一个access_token重新声明
$access_arr = array();
$access_arr = json_decode($access_res,true);
}
//获取用户信息
$user_info_res = $wechat->get_user_info($access_arr['access_token'],$access_arr['openid']);
$user_info_arr = json_decode($user_info_res,true);
if(isset($user_info_arr['errcode'])){
$this->error('获取用户信息失败,请返回上级页面重新登录');
}else{
$user = db('member')->field('id,phone')->where('unionid',$user_info_arr['unionid'])->find();
if($user['id']){
session('user_id',$user['id']);
session('user_name',$username);
//pc端openid不存在就更新
if(!db('member')->where('id',$user['id'])->value('open_id')){
$update_res = db('member')->where('id',$user['id'])->update(['open_id' => $user_info_arr['openid']]);
}
if(!empty($user['phone'])){
login_log($user['id'],1);//PC微信登录
$url = session('login_return_url') ? session('login_return_url') : '/member/ucenter/index';
$this->success('微信登录成功',$url);
}else{
$this->redirect('/home/simple/bind');
}
}else{
$password = md5('000000');
$data = array();
$data['open_id'] = $user_info_arr['openid'];
$data['user_name'] = $user_info_arr['nickname'];
$data['user_pass'] = $password;
//$data['phone'] = $username;
$data['add_time'] = time();
$data['user_type'] = 1;
$data['head_ico'] = $user_info_arr['headimgurl'];
$data['unionid'] = $user_info_arr['unionid'];
$data['login_type'] = 1;
$user_id = db('member')->insertGetId($data);
if($user_id){
session('user_id',$user_id);
session('user_name',$data['user_name']);
if(!empty($user['phone'])){
login_log($user_id,1);//PC微信登录
$url = session('login_return_url') ? session('login_return_url') : '/member/ucenter/index';
$this->success('微信登录成功',$url);
}else{
$this->redirect('/home/simple/bind');
}
}else{
$this->error('数据异常,微信登录失败');
}
}
}
}
//显示验证码
public function show_captcha(){
$captcha = new \think\captcha\Captcha();
$captcha->expire = 180;//有效期
$captcha->length = 3;//验证码位数
$captcha->useZh = true;//使用中文验证码
return $captcha->entry();
}
所需SDK:
--------------------------------------------------------------------------------------------------
PC网站微信支付
参考文档:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_1
流程:
1、申请公众号必须是服务号,服务号登录地址(https://pay.weixin.qq.com/index.php/core/info)
2、拿到APPID相关信息写入到开发配置中。
3、下载微信官方微信支付SDK(网址:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=11_1)
4、将微信支付SDK引入到自己项目中,我用的thinkphp5,所用到的文件如下图:
5、thinkphp5导入方式(import('WxPay.WxPayApi');)
6、thinkphp5调用方式($input = new \WxPayUnifiedOrder();),注意前面\反斜杠必需。
7、注意交易类型是NATICE
代码:
html:
<!-- KDT获取 -->
<meta name="Keywords" content="{$key}"/>
<meta name="Description" content="{$des}"/>
<title>在线充值</title>
<link rel="stylesheet" href="{:config('home_file')}css/ucenter.css">
<!-- 引入公共头部 -->
{include file="public:header" /}
<!--定位-->
<div class="ulocat">
<span>当前位置:</span><a href="/home/index/index">首页</a><a href="/member/ucenter/index">个人中心</a><a href="/member/ucenter/recharge">在线充值</a>
</div>
<!--主体部分-->
<section class="main">
<div class="container clearfix">
<!--左侧-->
<div class="left">
<dl>
<!--引入左侧-->
{include file="public:left" /}
</dl>
</div>
<!--右侧-->
<div class="right">
<div class="box">
<h4 class="tit">在线充值</h4>
<div class="rec clearfix">
{volist name="$list" id="vo"}
<dl class="">
<dt>
<img src="{$vo.img_url}" alt="{$vo.describe}"/>
<span class="bor" data-id="{$vo.id}"></span>
</dt>
<dd><p class="des">{$vo.describe}</p><p class="pri">{$vo.price}元</p></dd>
</dl>
{/volist}
</div>
<div class="rectice">在您支付前,请确保查看过<a href="/member/ucenter/retxt">《厚昌学院充值说明》</a></div>
</div>
<div class="box log">
<h4 class="tit">充值记录</h4>
<table class="tabg">
<colgroup>
<col width="580px" />
<col width="150px" />
<col width="208px" />
</colgroup>
<thead><tr><th>类型</th><th>金额</th><th>充值状态</th><th width="231">日期</th></tr></thead>
<tbody>
{volist name="charge_list" id="vo"}
<tr><td>{$charge_type[$vo[type]]}</td>
<td><span class="add">{$vo.money}</span></td>
<td><span class="{$vo.status ? 'add' : 'cud'}">{$vo.status ? '充值成功' : '充值失败'}</span></td>
<td>{$vo.add_time|date="Y-m-d H:i:s",###}</td></tr>
{/volist}
</tbody>
</table>
</div>
</div>
</div>
</section>
<script>
var ifid = 1;
var timer;
$(function(){
$(".main .right .rec dl").each(function(i){
var t = $(this);
t.on('click',function(){
t.addClass('on').siblings().removeClass('on');
var obj = $(".main .right .rec dl.on .bor");
if(obj.attr('data-id')){
var url = "__URL__/wechat_pay?id="+obj.attr('data-id');
layer.open({
title: '微信支付',
content: [url, 'no'],
type: 2,
area: ['500px', '400px'],
offset: '250px',
closeBtn: 2,
shadeClose: true,
cancel: function(index, layero){
ifid++;
clearInterval(timer);
return true;
}
});
timer = setInterval(function(){SelectOut()},2000);
}else{
layer.msg('您还没有选中任何商品呢', {icon: 2,offset: '250px'});
}
})
});
})
function SelectOut() {
var obj = "#layui-layer-iframe"+ifid+"";
var out_trade_no = $(obj).contents().find("#out_trade_no").val();
$.get("__URL__/SelectOut?out_trade_no="+out_trade_no,function(d){
if(d == 1){
clearInterval(timer);
window.location.href='/member/ucenter/recharge';
}
});
}
</script>
<!--引入公共底部-->
{include file="public:footer"/}
PHP:
/*
* 微信支付-生成二维码链接
* @author 董强
*/
public function wechat_pay(){
if(empty($_GET)) $this->error('数据异常');
//$money = input('get.money/d') <= 0 || empty(input('get.money/d')) || input('?get.money/d') ? $this->error('充值金额异常') : input('get.money/d');
$id = input('get.id/d') <= 0 ? $this->error('充值ID异常') : input('get.id/d');
$money = db('goods')
->field('price,describe,type_id')
->where('id',$id)
->find();
//导入微信支付类库
import('WxPay.WxPayApi');
$wechat = new \WxPayApi();//API类库
$send_data = new \WxPayUnifiedOrder();
$notify = new \NativePay();
$send_data->SetBody($money['describe']);
$send_data->SetAttach($money['describe']);
$out_trade_no = \WxPayConfig::MCHID.date("YmdHis");
$send_data->SetOut_trade_no($out_trade_no);
$send_data->SetTotal_fee(intval($money['price']*100));
$send_data->SetTime_start(date("YmdHis"));
$send_data->SetTime_expire(date("YmdHis", time() + 600));
$send_data->SetNotify_url("https://www.***.com/home/Wxnotify/notify");
$send_data->SetTrade_type("NATIVE");
$send_data->SetProduct_id($id);
$result = $notify->GetPayUrl($send_data);
$type = $money['type_id'] == 2 || $money['type_id'] == 3 ? 2 : 1;
//判断是否成功,本地增加充值记录
if($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS' && $result['return_msg'] == 'OK'){
$db_res = db('wx_recharge')
->insert([
'uid' => $this->user_id,
'money' => $money['price'],
'out_trade_no' => $out_trade_no,
'add_time' => time(),
'goods_id' => $id,
'type' => $type
]);
if(!$db_res) $this->error('本地数据异常');
}else{
$this->error('充值异常');
}
$url = $result["code_url"];
$this->assign('url',urlencode($url));
$this->assign('out_trade_no',urlencode($out_trade_no));
return $this->fetch();
}
/*
* 微信支付-生成支付二维码
* @author 董强
* @info 二维码是直接输出所以必须是一个方法
*/
public function qrcode(){
import('WxPay.WxPayApi');
$url = urldecode(input('get.url'));
\QRcode::png($url);
}
/*
* Ajax轮训查订单状态
* @author 董强
*/
public function SelectOut(){
$out_trade_no = input('get.out_trade_no');
$result = db('wx_recharge')
->where('out_trade_no',$out_trade_no)
->value('status');
return json($result);
}
--------------------------------------------------------------------------------------------------
小程序微信登录
参考文档:https://developers.weixin.qq.com/miniprogram/dev/api/api-login.html
流程:
1、申请小程序APPID,网址(https://mp.weixin.qq.com/)
2、获取APPID相关信息配置到项目中
3、调用小程序接口wx.login或者code传给服务端
4、服务端返回用户信息,将uid存入到本地缓存,作为用户登录状态的判断。
代码:
html:
<view class='container'>
<view class='box'>
<!-- tab头部 -->
<view class='navtop'>
<view class='tab {{nav == 0 ? "on" : ""}}' data-nav="0" bindtap='changetab'>
<image src='../../images/logwx-on.png' class='wx' wx:if="{{nav == 0}}"></image>
<image src='../../images/logwx.png' class='wx' wx:else></image>
<text>微信登录</text>
</view>
<view class='tab {{nav == 0 ? "" : "on"}}' data-nav="1" bindtap='changetab'>
<image src='../../images/logph-on.png' class='ph' wx:if="{{nav == 1}}"></image>
<image src='../../images/logph.png' class='ph' wx:else></image>
<text>手机登录</text>
</view>
</view>
<!-- tab主体 -->
<swiper bindchange='swiperchange' class='cont' current='{{nav}}'>
<swiper-item>
<button open-type="getUserInfo" bindgetuserinfo="wxlogin" class='logbtn mt210'>一键登录</button>
</swiper-item>
<swiper-item>
<view class='list'>
<input placeholder='手机号:' placeholder-class='place' value='{{phone}}' class='phone' bindinput='changetext' data-name='phone'></input>
</view>
<view class='list'>
<input placeholder='短信验证码:' placeholder-class='place' value='{{sms}}' class='sms' bindinput='changetext' data-name='sms'></input>
<button class='getsms' bindtap='getSms' disabled='{{disabled}}'>{{getsms}}</button>
</view>
<view class='logbtn mt68' bindtap='phlogin'>登录</view>
</swiper-item>
</swiper>
</view>
</view>
JS:
// pages/member/index.js
const Util = require('../../utils/util.js')
const Api = require('../../utils/api.js')
const app = getApp()
Page({
data: {
uid: '',
nav: 0,
phone: '',
sms: '',
time: 60,
getsms: '获取',
disabled: false
},
onLoad: function (options) {},
onShow: function () {},
// tab改变
changetab: function(e){
this.setData({
nav: e.currentTarget.dataset.nav
});
},
//tab底部切换效果
swiperchange: function (e) {
this.setData({
nav: e.detail.current
});
},
// 微信一键登录
wxlogin: function (e) {
if (e.detail.userInfo) {
wx.login({
success: res => {
if (res.code) {
wx.request({
url: Api.wxlogin(),
method: "POST",
header: {
"Content-Type": "application/x-www-form-urlencoded"
},
data: Api.json2Form({
code: res.code,
iv: e.detail.iv,
encryptedData: e.detail.encryptedData,
}),
success: res => {
if (res.data.status) {
//本地存储user_id和创建user_id时间戳
wx.setStorageSync('user_id', res.data.data.user_id);
wx.setStorageSync('user_time', new Date().getTime());
wx.showToast({
title: '登录成功',
icon: 'none',
duration: 2000
});
setTimeout(function () {
wx.reLaunch({ url: 'index', });
}, 2000);
} else {
wx.showToast({
title: res.data.info,
icon: 'none',
duration: 2000
})
}
},
fail: res => {
console.log('微信登录发生错误', res);
},
complete: res => {
console.log('微信登录状态反馈', res);
}
})
}
}
});
} else {
console.log("用户拒绝授权");
}
},
// 输入框改变
changetext: function(e){
var that = this;
var k = e.target.dataset.name;
var v = e.detail.value;
switch (k){
case 'phone':
that.setData({ phone: v });
break;
case 'sms':
that.setData({ sms: v });
break;
default:
break;
}
},
// 获取手机验证码操作
getSms: function(){
var that = this;
var phone = that.data.phone;
if (!phone.match(/^(1(([3578][0-9])|(47)|[8][01236789]))\d{8}$/)){
wx.showToast({
title: '手机号格式不正确',
icon: 'none',
duration: 2000
})
}else{
wx.request({
url: Api.sendsms(),
method: "POST",
header: {
"Content-Type": "application/x-www-form-urlencoded"
},
data: Api.json2Form({
phone: that.data.phone
}),
success: res => {
wx.showToast({
title: res.data.info,
icon: 'none',
duration: 2000
});
if (res.data.status) {
//倒计时操作
that.setTime();
}
},
fail: res => {
console.log('发生错误', res);
},
complete: res => {
console.log('获取手机验证码状态反馈', res);
}
})
}
},
// 倒计时操作
setTime: function(){
var that = this;
if(that.data.time == 0){
that.setData({
time: 60,
disabled: false,
getsms: '获取'
});
}else{
that.setData({
getsms: that.data.time + 'S',
disabled: true,
time: that.data.time -1
});
setTimeout(function(){
that.setTime();
},1000);
}
},
//登录操作
phlogin: function(){
var that = this;
if (!that.data.phone.match(/^(1(([3578][0-9])|(47)|[8][01236789]))\d{8}$/)) {
wx.showToast({
title: '手机号格式不正确',
icon: 'none',
duration: 2000
})
}else if(that.data.sms.length != 4){
wx.showToast({
title: '短信验证码格式不正确',
icon: 'none',
duration: 2000
});
}else{
wx.request({
url: Api.PhoneLogin(),
method: "POST",
header: {
"Content-Type": "application/x-www-form-urlencoded"
},
data: Api.json2Form({
mobile: that.data.phone,
sms: that.data.sms,
}),
success: res => {
if (res.data.status) {
wx.setStorageSync('user_id', res.data.data.user_id);
wx.setStorageSync('user_time', new Date().getTime());
wx.showToast({
title: '登录成功',
icon: 'none',
duration: 2000
});
setTimeout(function () {
wx.reLaunch({ url: 'index', });
}, 2000);
}else{
wx.showToast({
title: res.data.info,
icon: 'none',
duration: 2000
})
}
},
fail: res => {
console.log('发生错误', res);
},
complete: res => {
console.log('状态反馈', res);
}
})
}
}
})
服务端:
//微信登录 董强
public function wxLogin(){
$code = input('param.code');//获取code
$iv = input('param.iv');//获取IV用于解密
$encryptedData = input('param.encryptedData');//用户加密信息
//通过code获取openid、session_key
$url = 'https://api.weixin.qq.com/sns/jscode2session?appid='.$this->appid.'&secret='.$this->serect.'&js_code='.$code.'&grant_type=authorization_code';
$res = file_get_contents($url);
$jscode_res = json_decode($res,true);
//解密用户信息并获取open_id、unionID、用户信息
$wechat = new WxBizDataCrypt($this->appid,$jscode_res['session_key']);
$errCode = $wechat->decryptData($encryptedData,$iv,$data);
$heavy_data = $data;//引用值赋值给变量
$en_res = json_decode($heavy_data,true);
$user_id = db('member')->where('unionid',$en_res['unionId'])->value('id');
if(!empty($user_id)){//判断该用户是否存在
if(empty(db('member')->where('id',$user_id)->value('small_open_id'))){//判断该用户小程序openid不存在就写入
if(!db('member')->where('unionid',$en_res['unionId'])->update(['small_open_id' => $en_res['openId']])) return $this->ReturnStatus(false,'小程序openid更新异常');
}
return $this->ReturnStatus(true,'正常',array('user_id' => $user_id));
}else{
$data = array(
'small_open_id' => $en_res['openId'],
'user_name' => $en_res['nickName'],
'user_pass' => md5('000000'),
'add_time' => time(),
'user_type' => 1,
'head_ico' => $en_res['avatarUrl'],
'unionid' => $en_res['unionId'],
'login_type' => 2,
);
$user_id = db('member')->insertGetId($data);
login_log($user,3);//小程序微信一键登录
if($user_id){
return $this->ReturnStatus(true,'新增用户正常',array('user_id' => $user_id));
}else{
return $this->ReturnStatus(false,'新增用户异常',null);
}
}
}
--------------------------------------------------------------------------------------------------
小程序微信支付
参考文档:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_1
流程:
1、申请小程序微信支付APPID,跟小程序微信登录是通用
2、把产品ID用户ID传给服务端
3、服务端处理产品信息并调用微信支付统一下单接口,预处理后判断返回状态是否成功,成功则本地存入预处理订单,但支付状态为未支付,注意交易类型参数必须是JSAPI,openid必传。
4、调用统一下单接口预处理之后拼接签名,下面代码会贴出签名方式代码,返回小程序所需参数。
5、小程序调用微信支付接口wx.requestPayment,官方文档里有案例
公众号微信登录,SDK和所需文件跟上面的PC微信支付大致一样,就不在细写了。
代码:
html:
<view class='tit'><view></view><text>当前积分</text></view>
<view class='inte'>
<image src='../../images/integral_2.png'></image>
<text>{{inte}}</text>
</view>
<view class='tit'><view></view><text>积分充值</text></view>
<view class='box'>
<view class='list {{product_id == item.id ? "on" : ""}}' wx:for="{{intelist}}" wx:key='key' data-id="{{item.id}}" bindtap='select'>
<view class='t1'>{{item.integral}}积分</view>
<view class='t2'>{{item.price}}元</view>
</view>
</view>
<view class='tit'><view></view><text>会员充值</text></view>
<view class='box'>
<view class='list {{product_id == item.id ? "on" : ""}}' wx:for="{{utplist}}" wx:key='key' data-id="{{item.id}}" bindtap='select'>
<view class='t1'>{{item.integral}}天</view>
<view class='t2'>{{item.price}}元</view>
</view>
</view>
<view class='submit' bindtap='submitdata'>确认支付</view>
JS:
const Util = require('../../utils/util.js')
const Api = require('../../utils/api.js')
const app = getApp()
Page({
data: {
uid: '',
inte: '',
product_id:'',
intelist: [],
utplist: [],
},
onLoad: function (options) {
var that = this;
// 获取本地存储用户ID
var uid = wx.getStorageSync('user_id');
if (uid) {
// 存在且为真 存储本页面user_id
that.setData({ uid: uid });
}
},
onShow: function () {
this.rechargeInfo();
},
// 获取充值信息
rechargeInfo: function(){
var that = this;
wx.request({
url: Api.goodsinfo(),
method: 'GET',
header: {
'content-type': 'application/json'
},
data: {
uid: that.data.uid
},
success: res => {
if (res.data.status) {
that.setData({
inte: res.data.data.inte,
intelist: res.data.data.intelist,
utplist: res.data.data.utplist
});
}
},
fail: res => {
console.log('错误信息', res);
},
complete: res => {
console.log('请求状态反馈', res);
}
});
},
/**
* 点击商品赋值商品ID
* @author Dongqiang
*/
select:function(e){
var that = this;
that.setData({
product_id: e.currentTarget.dataset.id,
});
},
/**
* 提交支付
* @author Dongqiang
*/
submitdata:function(){
var that = this;
if (that.data.product_id != ''){
wx.request({
url: Api.wxpay(),
method: 'GET',
header: {
'content-type': 'application/json'
},
data: {
uid: that.data.uid,//用户ID
product_id: that.data.uid//商品ID
},
success: res => {
if (res.data.status) {
var send_data = res.data.data;
//获取服务端统一下单返回数据包拉起支付
wx.requestPayment({
'timeStamp': send_data.time,//当前时间戳
'nonceStr': send_data.nonceStr,//随机字符串
'package': send_data.prepay_id,//统一下单返回数据包
'signType': 'MD5',//签名方式
'paySign': send_data.sign,//签名
'success': function (res) {
console.log(res);
},
'fail': function (res) {
},
'complete': function (res) {
console.log('支付请求反馈',res);
}
})
}
},
fail: res => {
console.log('错误信息', res);
},
complete: res => {
console.log('请求状态反馈', res);
}
});
}else{
wx.showToast({
title: '未获取有效支付信息',
icon: 'none',
duration: 2000
})
}
}
})
服务端:
//微信支付 DongQiang
public function WxPay(){
$id = input('get.product_id/d') <= 0 ? $this->ReturnStatus(false,'充值ID异常') : input('get.product_id/d');
$uid = empty(input('get.uid')) ? $this->ReturnStatus(false,'UID异常') : input('get.uid/d');
$money = db('goods')
->field('price,describe,type_id')
->where('id',$id)
->find();
//导入微信支付类库
import('SmallWxPay.WxPayApi');
//调用统一下单接口
$input = new \WxPayUnifiedOrder();
$input->SetBody($money['describe']);//商品描述
$input->SetAttach($money['describe']);//商品附加描述
$out_trade_no = \WxPayConfig::MCHID.date("YmdHis");
$input->SetOut_trade_no($out_trade_no);//唯一订单号
$input->SetTotal_fee(intval($money['price']));//金额
$input->SetTime_start(date("YmdHis"));//开始时间
$input->SetTime_expire(date("YmdHis", time() + 600));//结束时间
$input->SetNotify_url("https://www.***.com/home/Wxnotify/notify");//异步回调地址
$input->SetTrade_type("JSAPI");//交易类型:小程序填JSAPI
$openId = db('member')
->where('id',$uid)
->value('small_open_id');
$input->SetOpenid($openId);//用户Openid
$result = \WxPayApi::unifiedOrder($input);//调用微信API提交数据并取得返回
$type = $money['type_id'] == 2 || $money['type_id'] == 3 ? 2 : 1;//充值类型
$res = array();
//判断预支付是否成功
if($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS'){
//增加本地数据
$db_res = db('wx_recharge')
->insert([
'uid' => $uid,
'money' => $money['price'],
'out_trade_no' => $out_trade_no,
'add_time' => time(),
'goods_id' => $id,
'type' => $type
]);
if(!$db_res) return $this->ReturnStatus(false,'本地数据异常');
//生成签名
$nonceStr = $this->createNoncestr();//随机字符串
//生成签名所需参数
$sign_arr = array(
'appId' => $result['appid'],//小程序Appid
'timeStamp' => strval(time()),//当前时间戳
'nonceStr' => $nonceStr,//随机字符串32位
'package' => 'prepay_id='.$result['prepay_id'],//统计下单返回
'signType' => 'MD5',//加密类型
);
ksort($sign_arr);//根据键,以升序对关联数组进行排序
$sign = "";
//拼接签名
foreach ($sign_arr as $k => $v)
{
if($k != "sign"){
$sign .= $k . "=" . $v . "&";
}
}
$sign = trim($sign, "&");
$sign = $sign.'&key='.\WxPayConfig::KEY;//KEY拼接到最后
$sign_md = md5($sign);//md5加密
$sign_res = strtoupper($sign_md);//转为大写
$res = array(
'sign' => $sign_res,//签名
'time' => $sign_arr['timeStamp'],//当前时间戳
'nonceStr' => $sign_arr['nonceStr'],//随机字符串32位
'prepay_id' => 'prepay_id='.$result['prepay_id'],//统一下单返回数据包
);
}else{
$this->ReturnStatus(false,'充值异常');
}
return $result['return_code'] == 'SUCCESS' ? $this->ReturnStatus(true,'成功',$res) : $this->ReturnStatus(false,'失败',$result);
}
--------------------------------------------------------------------------------------------------
公众号微信登录:
参考文档:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842
流程:
2 第二步:通过code换取网页授权access_token
4 第四步:拉取用户信息(需scope为 snsapi_userinfo)
所需材料:
1、微信公众服务号APPID,地址(https://mp.weixin.qq.com/wiki)
代码:
html:
我没写,就写了按钮,哈哈哈哈哈哈哈哈
服务端:
//获取code DongQiang
public function get_code(){
$appid = $this->appid;//公众号的唯一标识
$appsecret = $this->appsecret;//公众号的appsecret
$redirect_uri = urlencode('https://www.yx685.com/mobile/Simple/redirect_uri');//授权后重定向的回调链接地址, 请使用 urlEncode 对链接进行处理
$response_type = 'code';//返回类型,请填写code
$scope = 'snsapi_userinfo';//应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且, 即使在未关注的情况下,只要用户授权,也能获取其信息 )
$state = 'STATE';//重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节
//请求微信链接,参数拼接
$url = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid='.$appid.'&redirect_uri='.$redirect_uri.'&response_type='.$response_type.'&scope='.$scope.'&state=STATE#wechat_redirect';
//打开该链接
$this->redirect($url);
}
//微信登录回调地址 DongQiang
public function redirect_uri(){
$code = input('get.code');//微信返回的code
//获取access_token
$aurl = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid='.$this->appid.'&secret='.$this->appsecret.'&code='.$code.'&grant_type=authorization_code';
$aurl_res = json_decode(file_get_contents($aurl),true);
//+-----------------------------------------+
//+ 检测access_token 暂时先不用了 +
//+ 预留出个地方,后期可能会用到检测并刷新 +
//+-----------------------------------------+
//拉取用户信息(需scope为 snsapi_userinfo)
$url = 'https://api.weixin.qq.com/sns/userinfo?access_token='.$aurl_res['access_token'].'&openid='.$aurl_res['openid'].'&lang=zh_CN';
$user_info_arr = json_decode(file_get_contents($url),true);
if(isset($user_info_arr['errcode'])){
$this->error('获取用户信息失败,请返回上级页面重新登录');
}else{
$user = db('member')->field('id,phone')->where('unionid',$user_info_arr['unionid'])->find();//通过unionid判断该用户是否存在
if($user['id']){
session('user_id',$user['id']);
session('user_name',$username);
//微信端public_open_id不存在就更新
if(!db('member')->where('id',$user['id'])->value('public_open_id')){
$update_res = db('member')->where('id',$user['id'])->update(['public_open_id' => $user_info_arr['openid']]);
}
if(!empty($user['phone'])){
login_log($user['id'],1);//PC微信登录
$url = session('login_return_url') ? session('login_return_url') : '/member/ucenter/index';
$this->success('微信登录成功',$url);
}else{
$this->redirect('/home/simple/bind');
}
}else{
$password = md5('000000');
$data = array();
$data['public_open_id'] = $user_info_arr['openid'];
$data['user_name'] = $user_info_arr['nickname'];
$data['user_pass'] = $password;
//$data['phone'] = $username;
$data['add_time'] = time();
$data['user_type'] = 1;
$data['head_ico'] = $user_info_arr['headimgurl'];
$data['unionid'] = $user_info_arr['unionid'];
$data['login_type'] = 1;
$user_id = db('member')->insertGetId($data);
if($user_id){
session('user_id',$user_id);
session('user_name',$data['user_name']);
if(!empty($user['phone'])){
login_log($user_id,1);//PC微信登录
$url = session('login_return_url') ? session('login_return_url') : '/member/ucenter/index';
$this->success('微信登录成功',$url);
}else{
$this->redirect('/home/simple/bind');
}
}else{
$this->error('数据异常,微信登录失败');
}
}
}
halt($res);
}
--------------------------------------------------------------------------------------------------
公众号微信支付
参考文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
流程:
1、使用公众服务号的APPID配置到项目中
2、把产品和用户ID传参给服务端。
3、服务端处理产品信息并调用统一下单接口,注意这里的交易类型是JSAPI,openid必传,跟小程序的一样。
4、调用统一下单预处理后判断返回状态是否成功,成功则本地存入预处理订单,但支付状态为未支付。
5、拼接签名,返回前端JS所需参数。
6、调用微信浏览器自由接口WeixinJSBridge.invoke拉起支付请求,SDK和所需文件跟上面的PC微信支付大致一样,就不在细写了。
代码:
html:
<!-- KDT获取 -->
<meta name="Keywords" content="{$key}"/>
<meta name="Description" content="{$des}"/>
<title>用户中心</title>
<!-- 引入公共头部 -->
{include file="public:header" /}
<button onclick="SendWxPay()">点击支付</button>
{include file="public:footer" /}
<script>
function SendWxPay(){
$.post("__URL__/wxpay",{},function(d){
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {
"appId":d.appId, //公众号名称,由商户传入
"timeStamp":d.timeStamp, //时间戳,自1970年以来的秒数
"nonceStr":d.nonceStr, //随机串
"package":d.package,
"signType":d.signType, //微信签名方式:
"paySign":d.paySign //微信签名
},
function(res){
if(res.err_msg == "get_brand_wcpay_request:ok" ){
alert('支付成功');
return false;
}
}
);
/*if (typeof WeixinJSBridge == "undefined"){
if( document.addEventListener ){
document.addEventListener('WeixinJSBridgeReady', SendWxPay, false);
}else if (document.attachEvent){
document.attachEvent('WeixinJSBridgeReady', SendWxPay);
document.attachEvent('onWeixinJSBridgeReady', SendWxPay);
}
}else{
SendWxPay();
}*/
},'json');
}
</script>
服务端:
//公众号微信支付 DongQiang
public function wxpay(){
//$id = input('get.product_id/d') <= 0 ? $this->error('充值ID异常') : input('get.product_id/d');
//$uid = empty(input('get.uid')) ? $this->error('UID异常') : input('get.uid/d');
$id = 6;
$uid = 1;
$money = db('goods')
->field('price,describe,type_id')
->where('id',$id)
->find();
//导入微信支付类库
import('WxPay.WxPayApi');
//调用统一下单接口
$input = new \WxPayUnifiedOrder();
$input->SetBody($money['describe']);//商品描述
$input->SetAttach($money['describe']);//商品附加描述
$out_trade_no = \WxPayConfig::MCHID.date("YmdHis");
$input->SetOut_trade_no($out_trade_no);//唯一订单号
$input->SetTotal_fee(intval($money['price']));//金额
$input->SetTime_start(date("YmdHis"));//开始时间
$input->SetTime_expire(date("YmdHis", time() + 600));//结束时间
$input->SetNotify_url("https://www.***.com/home/Wxnotify/notify");//异步回调地址
$input->SetTrade_type("JSAPI");//交易类型:小程序填JSAPI
$openId = db('member')
->where('id',$uid)
->value('public_open_id');
$input->SetOpenid($openId);//用户Openid
$result = \WxPayApi::unifiedOrder($input);//调用微信API提交数据并取得返回
$type = $money['type_id'] == 2 || $money['type_id'] == 3 ? 2 : 1;//充值类型
$res = array();
//判断预支付是否成功
if($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS'){
//增加本地数据
$db_res = db('wx_recharge')
->insert([
'uid' => $uid,
'money' => $money['price'],
'out_trade_no' => $out_trade_no,
'add_time' => time(),
'goods_id' => $id,
'type' => $type
]);
if(!$db_res) return json('本地数据异常');
//生成签名
$nonceStr = $this->createNoncestr();//随机字符串
//生成签名所需参数
$sign_arr = array(
'appId' => $result['appid'],//公众号Appid
'timeStamp' => strval(time()),//当前时间戳
'nonceStr' => $nonceStr,//随机字符串32位
'package' => 'prepay_id='.$result['prepay_id'],//统计下单返回
'signType' => 'MD5',//加密类型
);
ksort($sign_arr);//根据键,以升序对关联数组进行排序
$sign = "";
//拼接签名
foreach ($sign_arr as $k => $v)
{
if($k != "sign"){
$sign .= $k . "=" . $v . "&";
}
}
$sign = trim($sign, "&");
$sign = $sign.'&key='.\WxPayConfig::KEY;//KEY拼接到最后
$sign_md = md5($sign);//md5加密
$sign_res = strtoupper($sign_md);//转为大写
$res = array(
'appId' => $result['appid'],
'paySign' => $sign_res,//签名
'timeStamp' => $sign_arr['timeStamp'],//当前时间戳
'nonceStr' => $sign_arr['nonceStr'],//随机字符串32位
'package' => 'prepay_id='.$result['prepay_id'],//统一下单返回数据包
'signType' => 'MD5'
);
return json($res);
}else{
return json('充值异常');
}
}
/*
* 生成随机字符串
* @author DongQiang
*/
private function createNoncestr($length = 32) {
$chars = "abcdefghijklmnopqrstuvwxyz0123456789";
$str = "";
for ($i = 0; $i < $length; $i++) {
$str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
}
return $str;
}