微信小程序获取手机号 前台+php后台
两个部分三个位置,前台加后台,前台分为js+wxml
前端
wxml
<button class='bottom' open-type="getPhoneNumber" bindgetphonenumber="getphonenumber" >
授权登录
</button>
js:需要修改两个请求连接
// pages/demo/demo.js
Page({
getphonenumber: function (e) {
if (e.detail.errMsg == 'getPhoneNumber:fail user deny') {
wx.showModal({
title: '提示',
showCancel: false,
content: '未授权',
success: function (res) {}
})
} else {
//调用接口获取登录凭证
wx.login({
success: function (res) {
//获取到的code
var code = res.code;
if (!code) {
console.log('获取用户登录态失败!' + res.errMsg)
}
//获取opendi、session_key
wx.request({
url: 'htt son/wei/v1/getopenid',
method: 'POST',
data: {
code: code,
},
header: {
'content-type': 'application/json'
},
success: function (res) {
wx.setStorageSync('openid', res.data.openid);
var encryptedData = e.detail.encryptedData
var iv = e.detail.iv
var se_key = res.data.session_key
console.log(res);
//换取手机号
wx.request({
url: 'https wp-json/wei/v1/getphone',
method: 'POST',
data: {
// 必须,获取手机号
encryptedData: encryptedData,
iv: iv,
session_key: se_key,
// 修改数据库所需
uid:3
},
header: {
'Content-Type': 'application/x-www-form-urlencoded'
},
method: 'POST',
success: function (res) {
console.log(res);
/*
每个人都不同
countryCode: "86"
phoneNumber: "123"
purePhoneNumber: "7823"
watermark: {timestamp: 16175702, appid: "wxa0fe31"}
*/
}
})
},
});
}
});
}
},
})
后台
封装了三个功能:
- 获取openid+session_key
- 获取用户手机号
- 支付
需要修改 __construct里的内容,支付需要所有信息获取完全
<?php
// include "PHP/wxBizDataCrypt.php";
class Wei_user_controller extends WP_REST_Controller
{
public function register_routes()
{
register_rest_route("wei/v1", '/' . "pay", array(
array(
'methods' => "post",
'callback' => array($this, 'pay_fn'),
)
));
register_rest_route("wei/v1", '/' . "getopenid", array(
array(
'methods' => "POST",
'callback' => array($this, 'getopenid_fn'),
)
));
register_rest_route("wei/v1", '/' . "getphone", array(
array(
'methods' => "POST",
'callback' => array($this, 'getphone_fn'),
)
));
}
// 小程序付款
public function pay_fn($request)
{
$params = $request->get_params();
$aaa = new Wx_app;
$res = $aaa->pay($params['code']);
return $res;
}
//换取手机号
public function getphone_fn($request)
{
$params = $request->get_params();
$aaa = new Wx_app;
$data = $aaa->get_phone($params['session_key'], $params['encryptedData'], $params['iv']);
if (isset($data->phoneNumber)) {
global $wpdb;
$phone = $data->phoneNumber;
$sql = "UPDATE wp_usermeta SET meta_value='{$phone}' WHERE user_id={$params['uid']} and meta_key='user_phone'";
$res2 = $wpdb->query($sql);
return $data;
}
}
//获取openid、session_key
public function getopenid_fn($request)
{
$params = $request->get_params();
$aaa = new Wx_app;
$res = $aaa->get_openid($params['code']);
return $res;
}
}
class Wx_app
{
public function __construct()
{
$this->mchid = '14 022'; //https://pay.weixin.qq.com 产品中心-开发配置-商户号
$this->apiKey = 'lnh asrvjw'; //https://pay.weixin.qq.com 帐户设置-安全设置-API安全-API密钥-设置API密钥
$this->appid = "w e31"; /* 小程序appid */
$this->appSecret = "d5 c";/* 小程序AppSecret */
// //回调的url【自己填写】, 付款
$this->notify_url = '回调/notify.php';
}
// 功能1 :获取openid、session_key
public function get_openid($code)
{
$code = $code;
$WX_APPID = $this->appid; //appid
$WX_SECRET = $this->appSecret; //AppSecret
$url = "https://api.weixin.qq.com/sns/jscode2session?appid=" . $WX_APPID . "&secret=" . $WX_SECRET . "&js_code=" . $code . "&grant_type=authorization_code";
$infos = json_decode(file_get_contents($url));
return $infos;
}
// 功能2,获取电话
public function get_phone($sessionKey, $encryptedData, $iv)
{
$appid = $this->appid;
$data = $this->decryptData($encryptedData, $iv, $sessionKey, $appid);
$res = json_decode($data);
return $res;
}
// 功能3,微信支付
public function pay($code)
{
$fee = 0.01; //举例支付0.01
$appid = $this->appid; //这里填写公众号appiid的话会显示 appid和openid不匹配 ,解决方法 添加特约商户号关联起来,在商户号后台关联小程序即可,调用时候使用小程序的appid
$body = '标题';
$mch_id = $this->mchid; //商户号
$nonce_str = $this->nonce_str(); //随机字符串
$notify_url = $this->notify_url;
$openid = $this->get_openid($code)->openid;
$out_trade_no = $this->order_number($openid); //商户订单号
$spbill_create_ip = '127.0.0.1'; //服务器的ip【自己填写】;
$total_fee = $fee * 100; // 微信支付单位是分,所以这里需要*100
$trade_type = 'JSAPI'; //交易类型 默认
//这里是按照顺序的 因为下面的签名是按照顺序 排序错误 肯定出错
$post['appid'] = $appid;
$post['body'] = $body;
$post['mch_id'] = $mch_id;
$post['nonce_str'] = $nonce_str; //随机字符串
$post['notify_url'] = $notify_url;
$post['openid'] = $openid;
$post['out_trade_no'] = $out_trade_no;
$post['spbill_create_ip'] = $spbill_create_ip; //终端的ip
$post['total_fee'] = $total_fee; //总金额
$post['trade_type'] = $trade_type;
// $sign1 = $this->sign($post); //签名
$sign = self::getSign($post, $this->apiKey);
$post_xml = '<xml>
<appid>' . $appid . '</appid>
<body>' . $body . '</body>
<mch_id>' . $mch_id . '</mch_id>
<nonce_str>' . $nonce_str . '</nonce_str>
<notify_url>' . $notify_url . '</notify_url>
<openid>' . $openid . '</openid>
<out_trade_no>' . $out_trade_no . '</out_trade_no>
<spbill_create_ip>' . $spbill_create_ip . '</spbill_create_ip>
<total_fee>' . $total_fee . '</total_fee>
<trade_type>' . $trade_type . '</trade_type>
<sign>' . $sign . '</sign>
</xml> ';
//统一接口prepay_id
$url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
$xml = $this->http_request($url, $post_xml); //发送请求
$array = $this->xml($xml); //全要大写
// print_r($array); // print_r($xml); die();
/* */
if ($array['RETURN_CODE'] == 'SUCCESS' && $array['RESULT_CODE'] == 'SUCCESS') {
$time = time();
$tmp = []; //临时数组用于签名
$tmp['appId'] = $appid;
$tmp['nonceStr'] = $nonce_str;
$tmp['package'] = 'prepay_id=' . $array['PREPAY_ID'];
$tmp['signType'] = 'MD5';
$tmp['timeStamp'] = "$time";
$data['state'] = 200;
$data['timeStamp'] = "$time"; //时间戳
$data['nonceStr'] = $nonce_str; //随机字符串
$data['signType'] = 'MD5'; //签名算法,暂支持 MD5
$data['package'] = 'prepay_id=' . $array['PREPAY_ID']; //统一下单接口返回的 prepay_id 参数值,提交格式如:prepay_id=*
$data['paySign'] = self::getSign($tmp, $this->apiKey); //签名,具体签名方案参见微信公众号支付帮助文档;
$data['out_trade_no'] = $out_trade_no;
} else {
$data['state'] = 0;
$data['text'] = "错误";
$data['RETURN_CODE'] = $array['RETURN_CODE'];
$data['RETURN_MSG'] = $array['RETURN_MSG'];
}
echo json_encode($data);
}
//授权
public function decryptData($encryptedData, $iv, $sessionKey, $appid)
{
if (strlen($sessionKey) != 24) {
return 41001;
}
$aesKey = base64_decode($sessionKey);
if (strlen($iv) != 24) {
return 41002;
}
$aesIV = base64_decode($iv);
$aesCipher = base64_decode($encryptedData);
$result = openssl_decrypt($aesCipher, "AES-128-CBC", $aesKey, 1, $aesIV);
$dataObj = json_decode($result);
if ($dataObj == NULL) {
return 41003;
}
if ($dataObj->watermark->appid != $appid) {
return 41004;
}
$data = $result;
return $data;
}
//随机32位字符串
private function nonce_str()
{
$result = '';
$str = 'QWERTYUIOPASDFGHJKLZXVBNMqwertyuioplkjhgfdsamnbvcxz';
for ($i = 0; $i < 32; $i++) {
$result .= $str[rand(0, 48)];
}
return $result;
}
//生成订单号
private function order_number($openid)
{
//date('Ymd',time()).time().rand(10,99);//18位
return md5($openid . time() . rand(10, 99)); //32位
}
//签名 $data要先排好顺序
private function sign($data)
{
$stringA = '';
foreach ($data as $key => $value) {
if (!$value) continue;
if ($stringA) $stringA .= '&' . $key . "=" . $value;
else $stringA = $key . "=" . $value;
}
$wx_key = ''; //申请支付后有给予一个商户账号和密码,登陆后自己设置的key
$stringSignTemp = $stringA . '&key=' . $wx_key;
return strtoupper(md5($stringSignTemp));
}
// 获取签名
public static function getSign($params, $key)
{
ksort($params, SORT_STRING);
$unSignParaString = self::formatQueryParaMap($params, false);
$signStr = strtoupper(md5($unSignParaString . "&key=" . $key));
return $signStr;
}
protected static function formatQueryParaMap($paraMap, $urlEncode = false)
{
$buff = "";
ksort($paraMap);
foreach ($paraMap as $k => $v) {
if (null != $v && "null" != $v) {
if ($urlEncode) {
$v = urlencode($v);
}
$buff .= $k . "=" . $v . "&";
}
}
$reqPar = '';
if (strlen($buff) > 0) {
$reqPar = substr($buff, 0, strlen($buff) - 1);
}
return $reqPar;
}
//curl请求
public function http_request($url, $data = null, $headers = array())
{
$curl = curl_init();
if (count($headers) >= 1) {
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
}
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
if (!empty($data)) {
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
}
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($curl);
curl_close($curl);
return $output;
}
//获取xml
private function xml($xml)
{
$p = xml_parser_create();
xml_parse_into_struct($p, $xml, $vals, $index);
xml_parser_free($p);
$data = [];
foreach ($index as $key => $value) {
if ($key == 'xml' || $key == 'XML') continue;
$tag = $vals[$value[0]]['tag'];
$value = $vals[$value[0]]['value'];
$data[$tag] = $value;
}
return $data;
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效