PS:本篇文章是PHP对小程序进行微信支付v3版本的实现,仅用于对支付流程的了解,具体使用方面需要大家自行调整
小程序端JS代码:
getPrepayID(){
var that = this
wx.getStorage({
key:'openid',
success(res){
that.setData({
'openid':res.data
})
}
})
wx.getStorage({
key:'username',
success(res){
that.setData({
'username':res.data
})
}
})
//console.log(that.data.openid)
wx.request({
url: 'http://127.0.0.1:2908/wxPayV3/v3GetPrepayId.php', //此处填写你的PHP文件url地址
method:'POST',
header:{
'content-type':'application/x-www-form-urlencoded'
},
data:{ //发送的数据,大家根据需要自行调整
'description':'0.38mm.pen', //商品描述,自行调整
'openid':that.data.openid, //用户openid,此处是从缓存中获取到的
'total':1, //订单总金额,单位为分,实际使用请乘100改为以元为单位
'username':that.data.username, //用户的昵称,此处从缓存中获取,用于后续存放于数据库中
'goods_id':1 //商品编号,数据库使用
},
success(res){
//console.log(res)
// that.setData({
// 'nonceStr':res.data.nonceStr,
// 'package':res.data.package,
// 'paySign':res.data.paySign,
// 'timeStamp':res.data.timeStamp,
// 'signType':res.data.signType
// })
console.log(res.data)
wx.requestPayment({
nonceStr: res.data.nonceStr,
package: res.data.package,
paySign: res.data.paySign,
timeStamp: res.data.timeStamp,
signType: 'RSA',
success(res){
//自行书写成功调用的逻辑,本篇仅为了实现成功支付
}
})
}
})
},
PHP类的相关代码:
<?php
require_once('../config/appConfig.php'); //读取相关配置,主要是appid,mch_id,serial_no,APIv3
class API_v3Connect
{
/**
* 获取相关配置
*/
public function __construct()
{
$appid = appid;
$mch_id = mchID;
$serial_no = serial_no;
$APIv3 = APIv3;
$this->appid = $appid;
$this->mch_id = $mch_id;
$this->serial_no = $serial_no;
$this->APIv3 = $APIv3;
}
/**
* 用于生成请求报文的主体,最终返回json格式数据
* @param $description :商品描述
* @param $out_trade_no :商户订单号
* @param $total :订单总金额
* @param $openid :小程序微信用户身份唯一标识符
* @return false|string
*/
public function requestBody($description, $out_trade_no, $total, $openid)
{
$data = array(
'appid' => $this->appid,
'mchid' => $this->mch_id,
'description' => $description,
'out_trade_no' => $out_trade_no,
'notify_url' => 'http://001.chutest.xyz/v3Result.php',
'amount' => [
'total' => $total,
],
'payer' => [
'openid' => $openid
]
);
return json_encode($data);
}
/**
* 用于生成签名数据主体
* @param $disposeUrl :此处的url是接口地址去除域名后的url
* @param $nonce_str :32位随机字符串
* @param $requestBody :请求报文的主体
* @return string
*/
public function signBody($disposeUrl, $time, $nonce_str, $requestBody)
{
$data = array(
'POST', $disposeUrl, $time, $nonce_str, $requestBody, ''
);
return join("\n", $data);
}
/**
* 用于生成签名值
* @param $data :用于签名的数据
* @return string
*/
public function getSignature($data)
{
$private = file_get_contents('./certificate/apiclient_key.pem');
$key = openssl_pkey_get_private($private);
openssl_sign($data, $signature, $key, 'sha256WithRSAEncryption');
return base64_encode($signature);
}
/**
* @param $nonce_str :32位随机字符串,与上方的随机字符串保持一致
* @param $signature :上方生成的签名值
* @return string[]
*/
public function getHeader($nonce_str, $signature)
{
$token = sprintf('mchid="%s",serial_no="%s",nonce_str="%s",timestamp="%s",signature="%s"', $this->mch_id, $this->serial_no, $nonce_str, time(), $signature);
$data = array(
'Accept: application/json',
'Content-Type: application/json',
'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.134 Safari/537.36 Edg/103.0.1264.71',
"Authorization: WECHATPAY2-SHA256-RSA2048 $token",
);
return $data;
}
/**
* 使用curl完成对接口的请求
* @param $url :接口的url地址
* @param string $type :传输类型,若为POST需要提供$data与$header
* @param string $data :当type = POST时需要提供,为请求主体数据
* @param array $header :当type = POST时需要提供,为请求头
* @return bool|string
*/
public function curlRequest($url, string $type = '', string $data = '', array $header = [])
{
$action = curl_init();
curl_setopt($action, CURLOPT_URL, $url);
curl_setopt($action, CURLOPT_CONNECTTIMEOUT, 60);
curl_setopt($action, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($action, CURLOPT_HEADER, 0);
curl_setopt($action, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($action, CURLOPT_SSL_VERIFYHOST, 0);
if ($type == 'POST') {
curl_setopt($action, CURLOPT_POST, 1);
curl_setopt($action, CURLOPT_POSTFIELDS, $data);
curl_setopt($action, CURLOPT_HTTPHEADER, $header);
}
$result = curl_exec($action);
curl_close($action);
return $result;
}
/**
* 构造对prepay_id再次签名的签名数据主体
* @param $time :时间戳
* @param $nonceStr :32位随机字符串
* @param $prepay_id :预支付参数
* @return string
*/
public function paySignBody($time, $nonceStr, $prepay_id)
{
$data = array(
$this->appid, $time, $nonceStr, "prepay_id=$prepay_id", ''
);
return join("\n", $data);
}
/**
* 构造返回给小程序段的数据,json数据
* @param $nonce_str :32位随机字符串
* @param $prepay_id :预支付参数
* @param $paySign :签名值
* @param $time :时间戳
* @param $out_trade_no :商户订单号
* @return false|string
*/
public function requestPayData($nonce_str, $prepay_id, $paySign, $time, $out_trade_no)
{
$data = array(
'nonceStr' => $nonce_str,
'package' => 'prepay_id=' . $prepay_id,
'paySign' => $paySign,
'timeStamp' => $time,
'signType' => 'RSA',
'out_trade_no' => $out_trade_no
);
return json_encode($data);
}
}
PHP调用方法的代码:
<?php
require_once('./API_v3Connect.php');
require_once('../wxPayV2/API_Connect.php'); //此处调用v2是为了省去再次写一遍获取随机字符串与商户订单号的麻烦
require_once('../database/getDatabase.php'); //此处调用数据库,将该订单的相关信息加入数据库中
$description = $_POST['description']; //接收商品描述
$openid = $_POST['openid']; //接收用户的openid
$total = $_POST['total']; //接收订单总金额
$total = (int)$total; //将订单总金额转化为int类型,此处接收到的数据默认是string类型
$time = time();
$getPartData = new v2Connect;
$nonce_str = $getPartData->nonce_str(); //获取32位随机字符串
$out_trade_no = $getPartData->out_trade_no(); //获取商户订单号
$getData = new API_v3Connect;
$requestBody = $getData->requestBody($description, $out_trade_no, $total, $openid); //获取请求主体的json数据
$disposeUrl = '/v3/pay/transactions/jsapi'; //处理过后的url地址 注:去掉前方的域名即可
$signBody = $getData->signBody($disposeUrl, $time, $nonce_str, $requestBody); //获取参与签名的主体数据
$signature = $getData->getSignature($signBody); //获取签名值
$header = $getData->getHeader($nonce_str, $signature); //获取请求头
$url = 'https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi'; //接口的url地址
$prepay_id = $getData->curlRequest($url, 'POST', $requestBody, $header); //获取预支付参数
$disposePrepayId = json_decode($prepay_id, true); //将返回的数据转化为数组
$prepay_id = $disposePrepayId['prepay_id']; //从转化的数组中获取prepay_id
$paySignBody = $getData->paySignBody($time, $nonce_str, $prepay_id); //构造生成支付签名的签名主体数据
$paySign = $getData->getSignature($paySignBody); //对构造好的签名数据主体进行签名
$time = (string)$time; //将时间戳由int转化为string类型
$getPayData = $getData->requestPayData($nonce_str, $prepay_id, $paySign, $time, $out_trade_no); //获取返回给小程序段的数据
echo $getPayData;
支付成功后微信回调发送的数据:
{
"id": "2dd87d80-2478-5ab0-852c-6d20084f8175",
"create_time": "2022-07-26T17:07:28+08:00",
"resource_type": "encrypt-resource",
"event_type": "TRANSACTION.SUCCESS",
"summary": "支付成功",
"resource": {
"original_type": "transaction",
"algorithm": "AEAD_AES_256_GCM",
"ciphertext": "此处显示密文,需要经过解密显示",
"associated_data": "transaction",
"nonce": "8oAAd7fCPvpO"
}
}
PS:微信会掉返回的内容中部分数据是进过加密的,需要进过解密之后才会显示
本文由优快云用户: 缱绻淡蓝海 原创,代码具有时效性,作者会不定时对发布过的文章进行更新