这个是我,2021年写的代码了,最近参加比赛,涉及到支付,于是又拿来用,幸好代码健全,但是去微信平台看,已经出v3支付了,再次,这个教程以及代码部分,仅仅用于V2版本,请勿踩空!
前言
文章用于记录我的开发经历,以及记录代码,亲测可用,时间:2022/03/07 原生PHP开发,简单的说一下微信的支付流程,以及回调方法,大家可以先看完正文,再找代码
提示:以下是本篇文章正文内容,下面案例可供参考
一、开始
这里对微信支付每个方法做一下说明,
wx.requestPluginPayment
基础库 2.22.1 开始支持,低版本需做兼容处理。 以 Promise 风格 调用:不支持 小程序插件:支持,需要小程序基础库版本不低于 2.22.1 插件中发起支付。
wx.requestPayment
以 Promise 风格 调用:支持 小程序插件:不支持 微信 Windows 版:支持 微信 Mac 版:支持 发起微信支付。调用前需在小程序微信公众平台 -功能-微信支付入口申请接入微信支付。了解更多信息,可以参考 微信支付开发文档:
开发指引 下单接口 支付接口 旧版本 (v2) 开发指引 支付接口
wx.requestOrderPayment
基础库 2.16.0 开始支持,低版本需做兼容处理。 以 Promise 风格 调用:支持 小程序插件:不支持 创建自定义版交易组件订单,并发起支付。 仅接入了自定义版交易组件的小程序需要使用,普通小程序可直接使用 wx.requestPayment。
这里我们使用第二个,wx.requestPayment方法,看一下该方法具体使用需要些什么参数:
wx.requestPayment({
nonceStr: 'nonceStr',
package: 'package',
paySign: 'paySign',
signType: '',
timeStamp: 'timeStamp',
})
完整拉起小程序支付需要5个参数,看一下官方给的说明: signType中官方给出了: 这里本教程用的是MD5
wx.requestPayment({
timeStamp: '',
nonceStr: '',
package: '',
signType: 'MD5',
paySign: '',
success (res) { },
fail (res) { }
})
接下来我们就要完成统一下单操作,小程序绑定微信商户,拿到商户号,在微信支付网页找到:
我的账户->API审核->V2密钥->生成随机32位密钥输入即可(自己做个备份,不需要用什么工具,自己打随意乱输入包含大写即可!)
接下来拿到商户号(mch_id)、V2密钥(key)
那!!wx.requestPayment中的各个参数怎么获得?
别急,我已经为各位踩坑了,一定讲解清楚!
首先把整个流程说明白,我们把获得的商户号、v2密钥、小程序appid及其他参数 通过统一下单 获得prepay_id 详细可以看下统一下单文档,已经写明了: 会返回 预支付交易会话标识,那这个是干嘛的呢?
它是用于获得签名paySign的
到此我们已经获取到了,商户号、密钥、签名、package接下来开始本篇的详细教程!
二、详细教程
1.后端Payfee.php代码
<?php
include 'WeixinPay.php';
$appid='appid';
$openid= $_GET['openid'];
$mch_id='商户号';
$key='商户密钥32位';
$out_trade_no = $mch_id. time();
$total_fee = $_GET['money'];
$attach = $_GET['attach'];
if(empty($total_fee))
{
$body = "支付";
$total_fee = floatval(99*100);
}
else {
$body = "支付";
$total_fee = floatval($total_fee*100);
}
$weixinpay = new WeixinPay($appid,$openid,$mch_id,$key,$out_trade_no,$body,$attach,$total_fee);
$return=$weixinpay->pay();
echo json_encode($return);
2.WeixinPay.php封装代码
记得改一下里面的回调通知
<?php
class WeixinPay {
protected $appid;
protected $mch_id;
protected $key;
protected $openid;
protected $out_trade_no;
protected $body;
protected $attach;
protected $total_fee;
function __construct($appid, $openid, $mch_id, $key,$out_trade_no,$body,$attach,$total_fee) {
$this->appid = $appid;
$this->openid = $openid;
$this->mch_id = $mch_id;
$this->key = $key;
$this->out_trade_no = $out_trade_no;
$this->body = $body;
$this->attach = $attach;
$this->total_fee = $total_fee;
}
public function pay() {
$return = $this->weixinapp();
return $return;
}
private function unifiedorder() {
$url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
$parameters = array(
'appid' => $this->appid,
'mch_id' => $this->mch_id,
'nonce_str' => $this->createNoncestr(),
'body' => $this->body,
'attach' =>$this->attach,
'out_trade_no'=> $this->out_trade_no,
'total_fee' => $this->total_fee,
'spbill_create_ip' => '192.168.0.161',
'notify_url' => '回调地址',
'openid' => $this->openid,
'trade_type' => 'JSAPI'
);
$parameters['sign'] = $this->getSign($parameters);
$xmlData = $this->arrayToXml($parameters);
$return = $this->xmlToArray($this->postXmlCurl($xmlData, $url, 60));
return $return;
}
private static function postXmlCurl($xml, $url, $second = 30)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_TIMEOUT, $second);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_HEADER, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 20);
curl_setopt($ch, CURLOPT_TIMEOUT, 40);
set_time_limit(0);
$data = curl_exec($ch);
if ($data) {
curl_close($ch);
return $data;
} else {
$error = curl_errno($ch);
curl_close($ch);
throw new WxPayException("curl出错,错误码:$error");
}
}
private function arrayToXml($arr) {
$xml = "<root>";
foreach ($arr as $key => $val) {
if (is_array($val)) {
$xml .= "<" . $key . ">" . arrayToXml($val) . "</" . $key . ">";
} else {
$xml .= "<" . $key . ">" . $val . "</" . $key . ">";
}
}
$xml .= "</root>";
return $xml;
}
private function xmlToArray($xml) {
libxml_disable_entity_loader(true);
$xmlstring = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
$val = json_decode(json_encode($xmlstring), true);
return $val;
}
private function weixinapp() {
$unifiedorder = $this->unifiedorder();
$parameters = array(
'appId' => $this->appid,
'timeStamp' => '' . time() . '',
'nonceStr' => $this->createNoncestr(),
'package' => 'prepay_id=' . $unifiedorder['prepay_id'],
'signType' => 'MD5'
);
$parameters['paySign'] = $this->getSign($parameters);
return $parameters;
}
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;
}
private function getSign($Obj) {
foreach ($Obj as $k => $v) {
$Parameters[$k] = $v;
}
ksort($Parameters);
$String = $this->formatBizQueryParaMap($Parameters, false);
$String = $String . "&key=" . $this->key;
$String = md5($String);
$result_ = strtoupper($String);
return $result_;
}
private function formatBizQueryParaMap($paraMap, $urlencode) {
$buff = "";
ksort($paraMap);
foreach ($paraMap as $k => $v) {
if ($urlencode) {
$v = urlencode($v);
}
$buff .= $k . "=" . $v . "&";
}
$reqPar;
if (strlen($buff) > 0) {
$reqPar = substr($buff, 0, strlen($buff) - 1);
}
return $reqPar;
}
}
3.后端支付成功后微信发送的通知接收
自己改一下,对接自己的业务即可,至于最底部的
echo ‘<return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg>’;
上面是处理通知的,简单的来说,就是微信告诉你,对方支付结果,你要告诉对方,我已经正确的处理了这件事情,否则微信将会按一定的周期通知你,接收,随着时间的流逝,通知的频率也会越来越低,直到不通知为止,我建议做一下处理,避免业务多重写,对于微信返回的参数我们做业务处理即可,这里不必多说,自己看代码,不懂就评论问我
<?php
$postXml = file_get_contents("php://input");
if (empty($postXml)) {
return false;
}
function xmlToArray($xml) {
libxml_disable_entity_loader(true);
$xmlstring = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
$val = json_decode(json_encode($xmlstring), true);
return $val;
}
$attr = xmlToArray($postXml);
$total_fee = $attr['total_fee'];
$open_id = $attr['openid'];
$out_trade_no = $attr['out_trade_no'];
$time = $attr['time_end'];
$attach= $attr['attach'];
include '../conn.php';
include 'access_token.php';
$touser=$open_id;
$ACCESS_TOKEN=$access_token;
$sq="UPDATE `order_pay` SET `is_success` = '1',`order_number` = '$out_trade_no', `pay_time` = '$time' WHERE openid='$open_id' and md_order='$attach'";
$r=$conn->query($sq);
mysqli_free_result($r);
$cx_tuis_data="select * from order_pay WHERE openid='$open_id' and md_order='$attach'";
$jieguo_data=$conn->query($cx_tuis_data);
$new_data=$jieguo_data->fetch_assoc();
$nnew_shopname=$new_data['shop_name'];
$nnew_shopmoney=$new_data['money'];
$nnew_shoptime=$new_data['time'];
mysqli_free_result($jieguo_data);
include 'payment_success_notify.php';
moban($touser,$ACCESS_TOKEN,"7IG9zV_nPkwrJTiTDI7fUkVOSwgl8h60axbdXoE6h0Q",$out_trade_no,$nnew_shopname,$nnew_shopmoney,$nnew_shoptime);
echo '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
4.小程序前端wxml
<button bindtap="pay" type="primary">支付</button>
5.小程序主要js
pay:function(){
wx.request({
url: '你的域名/payfee.php',
data: {
money: '12.00',
openid: 'o7J2i5YNkHn0nELz87HFS6zKL9oQ',
attach:'12'
},
header: {
'content-type': 'application/json'
},
success (res) {
console.log(res.data)
wx.requestPayment({
'timeStamp': res.data.timeStamp,
'nonceStr': res.data.nonceStr,
'package': res.data.package,
'signType': 'MD5',
'paySign': res.data.paySign,
'success':function(res){
},
'fail':function(res){
}
})
}
})
},
6.小程序支付拉起截图
总结
提示:本文简单的讲了,关于小程序如何拉起支付踩坑经历,给大家附上了健全的代码,关于如何处理支付上述已经讲解完毕了,有问题或者能指教一二的,欢迎留言讨论,还是那句话:
关注、收藏、点赞3连😀!!! 关注、收藏、点赞3连😀!!!
以上!
|