微信小程序支付后端逻辑

2023-11-06

/* 小程序报名,生成订单 */
    public function make_order(){
        if(IS_POST){
            $data['openid'] = I('POST.openid');
            $data_total = I('POST.data_total');
            $data['crsNo'] = 'W'.date('YmdHis',time()).'-'.randomkeys(2);
            $insertId = M('home_order','xxf_witkey_')->add($data);
            if($insertId){
                $this->insertID = $insertId;
                $this->data_total = $data_total*100;    //订单总金额,单位分
                /* 调用微信【统一下单】 */
                $this->pay($data_total*100,$data['openid'],$data['crsNo']);
            }else{
                echo $insertId;
            }
            //echo json_encode($re);
        }
    }
    




/* 首先在服务器端调用微信【统一下单】接口,返回prepay_id和sign签名等信息给前端,前端调用微信支付接口 */
    private function Pay($total_fee,$openid,$order_id){
        if(empty($total_fee)){
            echo json_encode(array('state'=>0,'Msg'=>'金额有误'));exit;
        }
        if(empty($openid)){
            echo json_encode(array('state'=>0,'Msg'=>'登录失效,请重新登录(openid参数有误)'));exit;
        }
        if(empty($order_id)){
            echo json_encode(array('state'=>0,'Msg'=>'自定义订单有误'));exit;
        }
        $appid =        '小程序appid';//如果是公众号 就是公众号的appid;小程序就是小程序的appid
        $body =         '自己填';
        $mch_id =       '商户账号';
        $KEY = '你申请微信支付的key';
        $nonce_str =    randomkeys(32);//随机字符串
        $notify_url =   'https://m.******.com/index.php/Home/Xiaoxxf/xiao_notify_url';  //支付完成回调地址url,不能带参数
        $out_trade_no = $order_id;//商户订单号
        $spbill_create_ip = $_SERVER['SERVER_ADDR'];
        $trade_type = 'JSAPI';//交易类型 默认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'] = intval($total_fee);        //总金额 最低为一分钱 必须是整数
        $post['trade_type'] = $trade_type;
        $sign = $this->MakeSign($post,$KEY);              //签名
        $this->sign = $sign;
    
        $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);     //POST方式请求http
        $array = $this->xml2array($xml);               //将【统一下单】api返回xml数据转换成数组,全要大写
        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'] = 1;
            $data['timeStamp'] = "$time";           //时间戳
            $data['nonceStr'] = $nonce_str;         //随机字符串
            $data['signType'] = 'MD5';              //签名算法,暂支持 MD5
            $data['package'] = 'prepay_id='.$array['PREPAY_ID'];   //统一下单接口返回的 prepay_id 参数值,提交格式如:prepay_id=*
            $data['paySign'] = $this->MakeSign($tmp,$KEY);       //签名,具体签名方案参见微信公众号支付帮助文档;
            $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);
    }
    
    /**
     * 生成签名, $KEY就是支付key
     * @return 签名
     */
    public function MakeSign( $params,$KEY){
        //签名步骤一:按字典序排序数组参数
        ksort($params);
        $string = $this->ToUrlParams($params);  //参数进行拼接key=value&k=v
        //签名步骤二:在string后加入KEY
        $string = $string . "&key=".$KEY;
        //签名步骤三:MD5加密
        $string = md5($string);
        //签名步骤四:所有字符转为大写
        $result = strtoupper($string);
        return $result;
    }
    /**
     * 将参数拼接为url: key=value&key=value
     * @param $params
     * @return string
     */
    public function ToUrlParams( $params ){
        $string = '';
        if( !empty($params) ){
            $array = array();
            foreach( $params as $key => $value ){
                $array[] = $key.'='.$value;
            }
            $string = implode("&",$array);
        }
        return $string;
    }
    /**
     * 调用接口, $data是数组参数
     * @return 签名
     */
    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里面数据,转换成array
    private function xml2array($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;
    }
    






/**
     * 将xml转为array
     * @param string $xml
     * return array
     */
    public function xml_to_array($xml){
        if(!$xml){
            return false;
        }
        //将XML转为array
        //禁止引用外部xml实体
        libxml_disable_entity_loader(true);
        $data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        return $data;
    }


//还有就是,微信要求支付后处理微信发送的回调内容,就是告诉商户,订单交易成功了,你要发送‘我知道了’给微信。
//还有一点就是:这里就是回调url,你预支付填写的notify_url地址。废话不多说,看下面
 


    /* 微信支付完成,回调地址url方法  xiao_notify_url() */
    public function xiao_notify_url(){
        $post = post_data();    //接受POST数据XML个数
/*


function post_data(){
    $receipt = $_REQUEST;
    if($receipt==null){
        $receipt = file_get_contents("php://input");
        if($receipt == null){
            $receipt = $GLOBALS['HTTP_RAW_POST_DATA'];
        }
    }
    return $receipt;
}
*/


        $post_data = $this->xml_to_array($post);   //微信支付成功,返回回调地址url的数据:XML转数组Array
        $postSign = $post_data['sign'];
        unset($post_data['sign']);
        
        /* 微信官方提醒:
         *  商户系统对于支付结果通知的内容一定要做【签名验证】,
         *  并校验返回的【订单金额是否与商户侧的订单金额】一致,
         *  防止数据泄漏导致出现“假通知”,造成资金损失。
         */
        ksort($post_data);// 对数据进行排序
        $str = $this->ToUrlParams($post_data);//对数组数据拼接成key=value字符串
        $user_sign = strtoupper(md5($post_data));   //再次生成签名,与$postSign比较
        
        $where['crsNo'] = $post_data['out_trade_no'];
        $order_status = M('home_order','xxf_witkey_')->where($where)->find();
        
        if($post_data['return_code']=='SUCCESS'&&$postSign){
            /*
            * 首先判断,订单是否已经更新为ok,因为微信会总共发送8次回调确认
            * 其次,订单已经为ok的,直接返回SUCCESS
            * 最后,订单没有为ok的,更新状态为ok,返回SUCCESS
            */
            if($order_status['order_status']=='ok'){
                $this->return_success();
            }else{
                $updata['order_status'] = 'ok';
                if(M('home_order','xxf_witkey_')->where($where)->save($updata)){
                    $this->return_success();
                }
            }
        }else{
            echo '微信支付失败';
        }
    }
    
    /*
     * 给微信发送确认订单金额和签名正确,SUCCESS信息 -xzz0521
     */
    private function return_success(){
        $return['return_code'] = 'SUCCESS';
        $return['return_msg'] = 'OK';
        $xml_post = '<xml>
                    <return_code>'.$return['return_code'].'</return_code>
                    <return_msg>'.$return['return_msg'].'</return_msg>
                    </xml>';
        echo $xml_post;exit;
    }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

微信小程序支付后端逻辑 的相关文章

  • Android中必须学习的八大开源项目

    欢迎Follow我的GitHub 关注我的CSDN 其余参考Android目录 转载请注明出处 http blog csdn net xiaole0313 article details 52562041 1 Ghost 微影 一款纯粹的在
  • 伺服速度控制模式接线图_PLC采用转矩、位置、速度模式控制伺服电机的方法

    原标题 PLC采用转矩 位置 速度模式控制伺服电机的方法 今天为大家讲解的是关于PLC控制伺服电机三种方式 一 转矩控制 二 位置控制 三 速度模式 一 转矩控制 转矩控制方式是通过外部模拟量的输入或直接的地址的赋值来设定电机轴对外的输出转
  • top-K 算法总结

    问题描述 有 N N gt 1000000 个数 求出其中的前K个最小的数 又被称作topK问题 1 最基本思路 将N个数进行完全排序 从中选出排在前K的元素即为所求 有了这个思路 我们可以选择相应的排序算法进行处理 目前来看快速排序 堆排
  • 【APT检测——论文精读】SLEUTH: Real-time Attack Scenario Reconstruction from COTS Audit Data

    2017 USENIX Security 顶会 Abstract 提出了一种实时重建企业主机攻击场景的方法和系统 为了满足问题的可扩展性和实时性需求 我们开发了一个平台中立的 基于主存的 并使用依赖图来抽象审计数据 然后 我们提出了有效的
  • redux成员、store成员、redux的数据流转、redux如何配合react-redux使用?react-redux的常用API、react-redux、redux和vuex的区别是什么?

    文章目录 前言 一 redux 1 redux三大原则 2 redux的安装 3 redux成员 4 store成员 5 数据流动 6 redux操作流程 7 action里处理异步 8 combineReducers提取reducer 二
  • java实验:电商购物平台(demo)

    课程融合之电商购物平台 将之前所学的知识都融合起来运用 是我目前做过最复杂的项目 不出意外会长期更新 文章目录 前言 实验内容 根据电商购物平台项目需求说明书的要求 抽象出电商购物平台中商品类目类和商品类 并用数组模拟商品数据库 完成商品信
  • vue el-table动态表格表头+对应数据

    vue el table动态表格创建 动态渲染表头 动态匹配表头对应数据 在这里插入代码片
  • SQLmap常用命令/使用教程

    SQLmap是一款自动化SQL注入神器 用于SQL注入漏洞的检测和利用 支持多种数据库 检测位置 u 指定url GET请求 p 指定参数 url包含多个参数时 指定参数 data 指定POST请求参数 cookie 指定cookie参数
  • 线性代数06 矩阵的逆以及求法

    我们已经了解了对于方程组来说 如何根据他的系数矩阵的变化 来实现高斯 诺尔当消元算法 并可以快速的判断方程组的解的情况 这样看上去非常的完美 但是我们在线性代数中 还有一个非常重要的部分就是矩阵的运算 似乎除了初等变换以外 现在目前还对任何
  • 可以这样学习linux命令

    通过综合练习 可以强化linux命令的学习 带着问题学习linux命令及其相关知识 是十分有效的方法 我们通过查询当前目录下的子目录这个问题 学习与训练linux 中一些重要命令 综合练习强于单个命令的分散学习 知识的串联 可以打通知识结点
  • python数组(矩阵)乘法(点乘、叉乘)

    转载 https blog csdn net haiziccc article details 101361583 总结 1 tf matmul A C np dot A C A C都属于叉乘 而tf multiply A C A C A
  • STM32的IAP在线升级

    IAP简介 简介部分copy自正点原子 IAP In Application Programming 即在应用编程 IAP 是用户自己的程序在运行过程中对User Flash 的部分区域进行烧写 目的是为了在产品发布后可以方便地通过预留的通
  • redhat 6.4安装oracle11g RAC (三)

    为数据和快速恢复去创建ASM磁盘组 只在节点rac1执行即可 进入grid用户下 grid rac1 grid srvctl status asm a ASM is running on rac2 rac1 ASM is enabled g
  • 快速浮点开方运算

    二分法 浮点开方也就是给定一个浮点数x 求根号x 这个简单的问题有很多解 我们从最简单最容易想到的二分开始讲起 利用二分进行开平方的思想很简单 就是假定中值为最终解 假定下限为0 上限为x 然后求中值 然后比较中值的平方和x的大小 并根据大
  • FISCO BCOS(二十)——— FISCO BCOS多群组搭建

    1 创建文件夹 创建目录 root wyg virtual machine mkdir fisco 2 创建配置文件 root wyg virtual machine fisco vim ipconf 3 建链 root wyg virtu
  • 【C++】封装的详细介绍

    目录 1 封装的意义 2 struct和class的区别 3 成员属性设置为私有 1 封装的意义 封装是C 面向对象的三大特性之一 封装的意义 1 将属性和行为作为一个整体 表现生活中的事物 2 将属性和行为加以权限控制 public公共权
  • CTFshow-pwn入门-栈溢出pwn49(静态链接pwn-mprotect函数的应用)

    pwn49 首先我们先将pwn文件下载下来 然后赋上可执行权限 再来查看pwn文件的保护信息 chomd x pwn checksec pwn file pwn 我们可以看到这是一个32位的pwn文件 并且保护信息开启了NX和canary
  • idea运行SSM项目及启动(tomcat),详细图解

    1 导入进项目 配置maven 2 配置本地的tomcat 3 选择本地的Tomcat Server 选择Local 点击create 4 tomcat路径配置 名称配置 端口及访问配置 5 项目war包配置生成 进入项目配置 1 进入Ar
  • Vuebnb:一个用vue.js和Laravel构建的全栈应用

    今年我一直在写一本新书叫全栈Vue网站开发 Vue js Vuex和Laravel 它会在Packt出版社在2018年初出版 这本书是围绕着一个案例研究项目 Vuebnb 简单克隆Airbnb 在这篇文章中 我会把它如何工作做一个高层次的概
  • 机器学习 day22(ReLU激活函数,激活函数的种类,如何选择激活函数)

    1 ReLU激活函数 当问题的结果是二元的 则a的范围是 0 1 激活函数g z 可以用sigmoid激活函数 如果问题的结果是无穷多个 如让a的范围取 0 激活函数g z 可以选用ReLU激活函数 他在z 0时取0 在z 0时取z 2 常

随机推荐

  • CDN服务技术架构图

    为什么80 的码农都做不了架构师 gt gt gt 前言 在博文中 解读大型网站的演变过程 浅谈 举家搬迁静态文件到CDN 博文中都有涉及CDN 这次我们来详细讲解下CDN的架构 简介 CDN是构建在网络之上的内容分发网络 依靠部署在各地的
  • linux搭建ftp修改域名访问,linux下构建建设完美FTP服务器

    关键字 ubuntu linux Apache2 PHP5 Pure FTPD pureftpd MySQL5 linux下构建建设完美FTP服务器 可管理 WEB管理 管理界面 一 安装Ubuntu5 Desktop版 来源博客 url
  • 对遗留系统组织重构项目

    很多IT组织都面临一个难题 老系统的维护 升级越来越难做 特别是那些价值高 生命周期长 规模大的核心业务系统 越到后来 要修复一个缺陷或者新增一个功能就需要越大的工作量 这是为什么呢 软 件的质量体现在两方面 商业方面的质量 以及技术方面的
  • 线性链表和顺序表的基本操作

    线性链表和顺序表的基本操作 一 实验目的 线掌握线性表的逻辑特性以及在计算机内的两种存储结构 线性链表和顺序表存储结构下基本操作的实现 会灵活应用线性表结构解决某些实际问题 二 实验内容 1 线性表顺序存储结下的基本操作的实现 初始化 赋值
  • 【2022年研究生科研素养提升系列公益讲座】课程笔记2——一些有用的数据库和科研工具

  • mobx基本使用

    mobx是一个简单可扩展的状态管理库 基本概念 state 状态 状态是驱动应用的数据 像有数据的excel表格 2 derivations 衍生 任何源自状态并且不会再进一步相互作用的东西 比如用户界面 待办事件的数量 把变化发送到服务端
  • c语言利用公式sin x=,用泰勒公式求sin(x)的近似值

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 include include define PI 3 1415927 double FACT double x double fact int n int main int n i k fla
  • java小笔记,List实体类对象的去重

    java小笔记 List实体类对象的去重 去除重复的数据 ArrayList lt 实体类 gt collect orderPOList stream collect Collectors collectingAndThen Collect
  • MySQL中的DDL操作,MySQL中DML操作,MySQL查询数据,SQL函数,MySQL中的索引,MySQL事务,MySQL的用户管理,MySQL分页查询

    目录 MySQL中的DDL操作 一 创建表与删除表 1 创建表 2 查看已创建的表 3 删除表 二 修改表 1 修改表名 2 修改列名 3 修改列类型 4 添加新列 5 删除指定列 三 MySQL的约束 1 修改表添加主键约束 2 删除主键
  • 记录电脑弹垃圾广告的处理方案

    今天电脑突然弹出了垃圾广告 作为一个看不得广告弹窗的人 务必把他扼杀了 他要获取广告信息可能会用到网络 这是一种思路 不同程序运行方式不一样 弹出广告后 打开任务管理器 资源监视器 可以看到有一个可以程序 通过 Wox 查找定位到程序存储路
  • Python 基于pickle的 保存和加载训练后的模型

    pickle允许我们将Python保存为硬盘驱动器上的二进制文件 在pickle我们的对象后 可以结束我们的Python 对话 并在之后将对象在加载到Python中 pickle文件可以备份到云盘或者移动盘里或者拿来想给谁给谁 警告 不要加
  • linux内核的编译和安装

    linux内核的编译和安装 文章目录 linux内核的编译和安装 1 获取内核源码 2 编译源码 3 安装内核 4 reboot 系统加载新的内核 1 获取内核源码 登录Linux内核官方网站 可以获取源代码 使用git获取最新提交到Lin
  • flask虚拟环境搭建及flask基础

    常用端口号 http 80 https 443 ssh 22 远程访问 ftp 21 文件传输mysql 3306 redis 6379 smtp 25 邮件发送服务 pop3 110 邮件接收服务 虚拟环境 pip是python的包管理工
  • BSN-DDC 基础网络关键知识点(一)DDC背景介绍

    id BSN 2021 公众号 BSN研习社 2022年1月25日 区块链服务网络发展联盟 简称 BSN联盟 上线推出了 BSN DDC基础网络 并进入试商用阶段 同时 BSN DDC官网门户 ddc bsnbase com 上线发布 供D
  • Python——人工智能时代的通用语言

    Python对于从事数据分析的专业人士来说 并不陌生 而我正在熟悉Python的道路上 先易后难 快速驶过高速公路后 目前正在泥泞山路上挣扎 期待雨过天晴 顺利跨过瓶颈期 学习Python就像学一门外语 需要了解它的语法 按照既定的规则组词
  • TypeScript语法

    TypeScript基础语法 1 1 js与ts的区别 最大区别 js不会在赋值时检查是否与类型匹配 而ts会检查所赋的值是否与类型匹配 若不匹配则会进行报错提示 1 2 js的数据类型 两大类 1 2 1 原始数据类型 5种 原始数据类型
  • 【NOI2018模拟3.26】Cti

    Description 有一个 n m 的地图 地图上的每一个位置可以是空地 炮塔或是敌人 你需要操纵炮塔消灭敌人 对于每个炮塔都有一个它可以瞄准的方向 你需要在它的瞄准方向上确定一个它的攻击位置 当然也可以不进行攻击 一旦一个位置被攻击
  • SpringBoot集成手机验证码业务(榛子云短信服务)

    一 手机验证码的作用 举个例子 如果你开发了一个系统 那这个系统肯定会有登录功能对吧 那如果说你的密码忘记了呢 这个时候我们的解决方式是 1 联系管理员 2 再注册一个 emmm 那我以前的资料就没了呀 3 对于管理员自己而言 手动修改数据
  • 简单的介绍一下:柔性数组

    对于柔性数组 其实这个是在如今的大学生书本上是很难能找到的 原因在于 笔者现在就是大学生一枚 但是在C语言的书本上没有涉及到柔性数组的部分 经查略资料 我们可以找到 在如今的C语言中 C99规定 结构体中允许最后一个元素是未知大小的数组 这
  • 微信小程序支付后端逻辑

    小程序报名 生成订单 public function make order if IS POST data openid I POST openid data total I POST data total data crsNo W dat