这个是我,2021年写的代码了,最近参加比赛,涉及到支付,于是又拿来用,幸好代码健全,但是去微信平台看,已经出v3支付了,再次,这个教程以及代码部分,仅仅用于V2版本,请勿踩空!

文章目录

  • 前言
  • 一、开始
  • 别急,我已经为各位踩坑了,一定讲解清楚!
  • 二、详细教程
    • 1.后端Payfee.php代码
    • 2.WeixinPay.php封装代码
    • 3.后端支付成功后微信发送的通知接收
    • 4.小程序前端wxml
    • 5.小程序主要js
    • 6.小程序支付拉起截图
  • 总结

前言

文章用于记录我的开发经历,以及记录代码,亲测可用,时间: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 = $_POST['out_trade_no'];
$out_trade_no = $mch_id. time();//商户号
//业务构造 由前端提交 这里注释
$total_fee = $_GET['money'];
//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, //小程序ID'mch_id' => $this->mch_id, //商户号'nonce_str' => $this->createNoncestr(), //随机字符串
//            'body' => 'test', //商品描述'body' => $this->body,'attach' =>$this->attach,
//            'out_trade_no' => '2015450806125348', //商户订单号'out_trade_no'=> $this->out_trade_no,
//            'total_fee' => floatval(0.01 * 100), //总金额 单位 分'total_fee' => $this->total_fee,
//            'spbill_create_ip' => $_SERVER['REMOTE_ADDR'], //终端IP'spbill_create_ip' => '192.168.0.161', //终端IP'notify_url' => '回调地址', //通知地址  确保外网能正常访问'openid' => $this->openid, //用户id'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); //严格校验//设置headercurl_setopt($ch, CURLOPT_HEADER, FALSE);//要求结果为字符串且输出到屏幕上curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);//post提交方式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);//运行curl$data = curl_exec($ch);//返回结果if ($data) {curl_close($ch);return $data;} else {$error = curl_errno($ch);curl_close($ch);throw new WxPayException("curl出错,错误码:$error");}}//数组转换成xmlprivate 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;}//xml转换成数组private function xmlToArray($xml) {//禁止引用外部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();
//        print_r($unifiedorder);$parameters = array('appId' => $this->appid, //小程序ID'timeStamp' => '' . time() . '', //时间戳'nonceStr' => $this->createNoncestr(), //随机串'package' => 'prepay_id=' . $unifiedorder['prepay_id'], //数据包'signType' => 'MD5'//签名方式);//签名$parameters['paySign'] = $this->getSign($parameters);return $parameters;}//作用:产生随机字符串,不长于32位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后加入KEY$String = $String . "&key=" . $this->key;//签名步骤三:MD5加密$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;
}//将xml格式转换成数组
function xmlToArray($xml) {//禁止引用外部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'];//用户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';// $page="pages/myqj/myqj";//点击小程序订阅消息跳转的页
moban($touser,$ACCESS_TOKEN,"7IG9zV_nPkwrJTiTDI7fUkVOSwgl8h60axbdXoE6h0Q",$out_trade_no,$nnew_shopname,$nnew_shopmoney,$nnew_shoptime);
//调用方法 格式(openid,ACCESS_TOKEN,模板id,数据1,数据2,数据3,数据4,数据5);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',//发起人openidattach:'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连

基于原生PHP完成小程序支付对接踩坑(V2版本)相关推荐

  1. 微信小程序uni.getImageInfo踩坑大计划

    B站https://www.bilibili.com/read/cv6317437 如果你在使用getImageInfo的时候真机调试没问题,上传生成体验版的时候或者是线上版本没反应,主要原因是网络图 ...

  2. 基于weixin-java-tools集成微信小程序支付功能

    目前,公司正在把业务从公众号向小程序迁移,本人负责订单功能的开发,现在把微信小程序接入微信支付这块的知识分享给大家,可能有部分人对微信支付不太了解,可以参考下面的微信支付流程图. 微信支付流程图 我是 ...

  3. 小程序统一服务消息_[miniblog]小程序订阅消息踩坑记

    有阵子没有更新我的mini-blog了,这次把推送消息那块做了些改动,小程序的模板消息即将废弃,订阅消息终于来了. 关于订阅消息 订阅消息分为一次性订阅和长期订阅,长期订阅就不说啦,不是个人号可以染指 ...

  4. 微信小程序Megalo开发踩坑计-普通二维码绑定

    原文首发于http://blog.yumengtao.top 首先简单说一下普通二维码绑定功能作用: 兼容线下已有的二维码 能同时支持微信.支付宝小程序 小程序启动传参 微信小程序普通二维码资料 支付 ...

  5. 小程序组件onload_微信小程序自定义组件踩坑教程

    微信小程序不支持自定义组件,只提供了一个非常受限制的模板功能,尤其缺乏了开发产品中最重要的几个功能:模板内的数据只能由当前页面传递,无法预先设置一些初始化数据以达到复用的目的: 模板内的数据变化无法通 ...

  6. WeChat小程序授权机制踩坑请求头中设置cookie保持session

    思路 存储token在redis中,但是现在没有redis,使用session进行存储 ,key为token   value为用户信息 session机制使用的文件缓存 token机制使用的redis ...

  7. 小程序二级页面tabbar_小程序页面推广踩坑记

    前几天,团队里有个小伙伴遇到一个问题,卡壳了大半天.我觉得这个例子值得拿出来分享给大家.希望大家以后遇到类似的问题能顺利绕过这种坑. 业务场景很常见,就是为了配合小程序中特定页面的推广,区分推广渠道和 ...

  8. 小程序获取openid保存缓存吗_小程序获取openid踩坑

    在app.js添加此函数,使用promise获取 getOpenid: function () { var that = this; return new Promise(function (reso ...

  9. php silk v3 decoder,微信小程序语音搜索踩坑:silk文件格式转换,在PHP中使用

    直接调用微信小程序录音接口,然后上传到服务器,百度语音的接口是识别不了这种格式的文件,那么问题来了 一.如何转码?ffmpeg? 二.如何在PHP中使用? 本文将要解决这两个问题. 用到的第三方工具: ...

最新文章

  1. 详解/etc/profile、/etc/bash.bahsrc、~/.profile、~/.bashrc的用途
  2. 【CAD制图视频】AutoCAD 2014 高手之道
  3. 070901css基础知识
  4. Linux系统磁状态检测,检测Linux硬件状态
  5. DOS常用网络相关命令
  6. String.prototype.substr()
  7. 阿里云openapi接口使用,PHP,视频直播
  8. C++学习笔记—srand()和rand()
  9. Ubuntu技巧之xxx is not in the sudoers file解决方法
  10. 2016年CIO的五个优先级
  11. 谈一下ACM的入门书籍及方法
  12. Ckeditor 的加载顺序
  13. Redis如何实现故障自动恢复?
  14. 微信小程序云开发教程-云函数操作数据库-增、查
  15. 2015QS世界大学排名-[转]
  16. linux下制作mac os x,桌面应用|Ubuntu 14.04 下的MAC OS X 主题安装
  17. python爬取链家二手房信息并存储到数据库
  18. 还原html默认打开方式,Win7旗舰版64位系统下如何还原文件默认打开方式
  19. 利用BaiduPCS-Go批量秒传与备份
  20. 第11期 Jenkins 社区 2020年 GSoC Phase1 分享

热门文章

  1. 深圳软件测试培训:Jmeter目录构成
  2. FreeChinaNet登陆器
  3. Windows10安装MG2580打印机
  4. c语言窗口插件,C语言使用ActiveX控件
  5. 雨滴特效源码html,js雨滴特效
  6. 6.又双叒叕背包模拟
  7. android代码里切换横竖屏,Android横竖屏切换
  8. element table里的嵌入的input框设置只能输入英文和数字
  9. bpl文件java_BPL_Motor Control Virtual Commissioning
  10. Oracle ORA-12899错误的解决方法