php 微信小程序支付

直接贴代码:

前端测试按钮wxml:

<view class="container">
  <text class="name">当前选择:《参加活动》 ¥0.01</text>
  <view class="pay"   bindtap="onTap">确认支付</view>
</view>

wxss:

.container {
  padding: 50rpx;
}

.pay {
  margin-top: 30rpx;
  color: #fff;
  background-color: #1fb922;
}

js:

Page({

    /**
     * 页面的初始数据
     */
    onTap () {
      console.log(‘6666‘);
        let _self = this;
        _self._togglePay();
        //发起网络请求
        wx.request({
            url: ‘付款url‘,
            method: "POST",
            data: {
                openid: ‘‘,
                money:0.01
            },
            header: {
                "content-type": "application/x-www-form-urlencoded"
            },
            success(res) {
                var params = res.data.data;
                wx.requestPayment({
                    ‘timeStamp‘: String(params[‘timeStamp‘]),
                    ‘nonceStr‘: params[‘nonceStr‘],
                    ‘package‘: params[‘package‘],
                    ‘signType‘: params[‘signType‘],
                    ‘paySign‘: params[‘paySign‘],
                    ‘success‘: function (res) {
                        wx.showToast({
                            title: ‘支付成功‘,
                            icon: ‘success‘,
                            duration: 2000
                        })
                        _self._togglePay();
                    },
                    ‘fail‘: function (res) {
                        wx.showToast({
                            title: ‘支付失败‘,
                            icon: ‘none‘,
                            duration: 2000
                        })
                        _self._togglePay();
                    },
                })
            }
        })

    },

    _togglePay() {
        this.setData({
            pay: !this.data.pay
        });
    }

})

后端PHP代码:

首先是公共函数,处理数据用的:

  // curl请求方法封装
    private 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); //严格校验
        //设置header
        curl_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 Exception("curl出错,错误码:$error");
        }
    }

    //数组转换成xml
    private function arrayToXml($arr) {
        $xml = "<xml>";
        foreach ($arr as $key => $val) {
            if (is_array($val)) {
                $xml .= "<" . $key . ">" . $this->arrayToXml($val) . "</" . $key . ">";
            } else {
                $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
            }
        }
        $xml .= "</xml>";
        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;
    }

    //作用:产生随机字符串,不长于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;
    }

    /*生成订单号*/
    private function out_trade_no(){
        //return date(‘YmdHis‘).md5($openid.time().rand(10,99));//32位
        return date(‘YmdHis‘,time()).time().rand(10,99);
    }

业务代码:

//统一下单
    private function unifiedorder($body,$openid,$pay) {
        $url = ‘https://api.mch.weixin.qq.com/pay/unifiedorder‘;
        // 这里的参数顺序一定要按下面的,不然可能就一直报商户号此功能未授权等错误
        $parameters = array(
            ‘appid‘ => $this->appid,                              // 小程序ID
            ‘body‘ => $body,                                         //支付标题
            ‘mch_id‘ => $this->mch_id,                          // 商户号
            ‘nonce_str‘ => $this->createNoncestr(),             // 随机字符串
            ‘notify_url‘ => $this->notify_url,                  //‘https://shop.gdpress.cn/syw_jingzhun/index.php/Api/xiaochengxu/notify_url_api‘, // 通知地址 确保外网能正常访问
            ‘openid‘ => $openid,                                // 用户id
            ‘out_trade_no‘=> $this->out_trade_no(),               // 商户订单号
            ‘spbill_create_ip‘ => Yii::$app->request->userIP,   // 终端IP ,这是YII2框架的写法
            ‘total_fee‘ => floatval($pay * 100),           //支付金额 单位 分
            ‘trade_type‘ => ‘JSAPI‘                             // 交易类型
        );

        //统一下单签名
        $parameters[‘sign‘] = $this->getSign($parameters);
        $xmlData =  $this->arrayToXml($parameters);
        $return  =  $this->xmlToArray($this->postXmlCurl($xmlData, $url, 60));
        return $return;
    }

    //微信小程序支付接口  调用
    public function actionWxpay() {

        $body=‘小程序支付测试‘;
        $openid=‘‘;//付款者openid
        $pay=‘0.01‘;//支付金额
        //统一下单接口
        $unifiedorder = $this->unifiedorder($body,$openid,$pay);
        // 统一下单出错,参数出错等原因
        if($unifiedorder[‘return_code‘] == ‘FAIL‘) {
            return Json::encode([‘code‘=>400,‘msg‘=>‘支付失败‘,‘data‘=>$unifiedorder[‘return_msg‘]]);
        }

        // 对统一下单返回得参数进行处理
        $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 Json::encode([‘code‘=>200,‘msg‘=>‘支付成功‘,‘data‘=>$parameters]);
    }

支付成功回调:

*微信支付的 异步通知 *回调地址*/
    public function actionNoticefy() {
        $xml = file_get_contents("php://input");
        //将服务器返回的XML数据转化为数组
        $data = $this->xmlToArray($xml);
        // 判断签名是否正确  判断支付状态
        if (($data[‘return_code‘] == ‘SUCCESS‘)) {//支付成功
            $result = $data;
            //获取服务器返回的数据
            $out_trade_no = $data[‘out_trade_no‘];      // 订单单号
            $openid = $data[‘openid‘];                  // 付款人openID
            $total_fee = floatval(($data[‘total_fee‘])/100);      // 付款金额
            $transaction_id = $data[‘transaction_id‘];  // 微信支付流水号
            $time_end = $data[‘time_end‘];  // 处理时间

            //查找订单
            $order=ActivityOrder::find()->where([‘out_trade_no‘=>$out_trade_no])->one();
            if ($order) {// 订单存在
                $result=true;
            }else{// 订单不存在,则创建订单
                $activityOrder=new ActivityOrder();
                $activityOrder->out_trade_no=$out_trade_no;
                $activityOrder->openid=$openid;
                $activityOrder->activity_id=48;
                $activityOrder->status=1;
                $activityOrder->total_fee=$total_fee;
                $activityOrder->transaction_id=$transaction_id;
                $activityOrder->time_end=$time_end;
                $activityOrder->userIP=Yii::$app->request->userIP;
                $activityOrder->create_time=time();
                 if ($activityOrder->save()){
                     $result=true;
                 }else{
                     $result = false;
                 }
            }
        }else {//支付失败
            $result = false;
        }
        // 返回状态给微信服务器
        if ($result) {
            $str=‘<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>‘;
        }else{
            $str=‘<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[签名失败]]></return_msg></xml>‘;
        }

        return $str;
    }

注:本支付基于Yii2框架编写,若用其他框架,请自行改掉名称等Yii2专有函数。

原文地址:https://www.cnblogs.com/jackzhuo/p/11698291.html

时间: 2024-10-29 05:07:04

php 微信小程序支付的相关文章

微信小程序支付及退款流程详解

微信小程序的支付和退款流程 近期在做微信小程序时,涉及到了小程序的支付和退款流程,所以也大概的将这方面的东西看了一个遍,就在这篇博客里总结一下. 首先说明一下,微信小程序支付的主要逻辑集中在后端,前端只需携带支付所需的数据请求后端接口然后根据返回结果做相应成功失败处理即可.我在后端使用的是php,当然在这篇博客里我不打算贴一堆代码来说明支付的具体实现,而主要会侧重于整个支付的流程和一些细节方面的东西.所以使用其他后端语言的朋友有需要也是可以看一下的.很多时候开发的需求和相应问题的解决真的要跳出语

php对接微信小程序支付

前言:这里我就假装你已经注册了微信小程序,并且基本的配置都已经好了.注: 个人注册小程序不支持微信支付,所以我还是假装你是企业或者个体工商户的微信小程序,其他的商户号注册,二者绑定,授权,支付开通,就阅读文档吧,这里我先负责实战. 微信小程序支付开发文档: https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_3&index=1 基本流程: 1. 申请商户平台账号 https://pay.weixin.qq.com/in

asp写的微信小程序支付demo-服务器端是asp+mdb的

这个微信小程序支付demo代码是我用asp写的,微信小程序端加上服务器端用的asp和mdb数据库,下面是代码分享: <view class="container"> <view class='view'>订单说明:{{paydata.title}}</view> <view class='view inputview'> 支付金额:<input bindinput="bindKeyInput" type=&quo

微信小程序支付代码asp源码下载

昨天晚上给朋友写了一个asp的微信小程序支付接口,我这朋友的小程序服务器端用的asp做的,以前没有支付,非让我给写一个支付,因为必须是asp来写,他不会,所以我就帮他写了,顺便还写了一个asp获取用户资料头像和微信名入库的代码,也是asp源码,数据库用的是mdb的格式,还可以比较好用,微信小程序用asp做服务器端估计很少,应该有朋友需要,下载这个代码:ly.ftphn.com/wxpay.rar ============================================= 互相学习

微信小程序支付

关于微信小程序支付功能,他的官方文档真的写的很清楚了!但是整理吸收一下还是不错的 官网呈上:https://developers.weixin.qq.com/miniprogram/dev/api/wx.requestPayment.html 核心流程:下面的图和交互流程描述写的真是不能再清晰了 商户系统和微信支付系统主要交互: 1.小程序内调用登录接口,获取到用户的openid,api参见公共api[小程序登录API] 2.商户server调用支付统一下单,api参见公共api[统一下单API

微信小程序支付最容易犯的坑notify_url(支付回调)

最近做了微信小程序支付,支付成功之后发现notify_url回调地址竟然没有访问. 检查了无数次代码,下单结果里面的回调地址看了又看,都没有错啊. 把回调地址复制出来到浏览器上面,外网也是可以访问的啊. 然后我再分析,为什么以前公众号支付都没有出现这种类型的错误,偏偏小程序就出现了呢. 然后对比了一下发现应对小程序需求,我把域名换成了https的. 然后去把IIS的http访问也加上了,再把回调地址改成了http.试了一下果然有效. 最终总结:微信支付异步回调通知只能支持外网能够访问的80端口的

PHP实现微信小程序支付

本文仅记录了微信小程序支付开发的基本流程和代码,具体业务需自行修改.tp5框架下演示: 参考: 微信小程序支付:业务流程 SDK与DEMO:  下载页 PHPPayDemo: demo 小程序端: goPay(e){ var that = this; //发起预支付,获取所需参数 wx.request({ url: app.globalData.host + '/api/wx_pay/createOrder', //请求地址 data: { openid: wx.getStorageSync('

微信小程序支付功能 C# .NET开发

微信小程序支付功能的开发的时候坑比较多,不过对于钱的事谨慎也是好事.网上关于小程序支付的实例很多,但是大多多少有些问题,C#开发的更少.此篇文档的目的是讲开发过程中遇到的问题做一个备注,也方便其他开发的同学作为参考! 1.首先建议把官方文档支付部分看上三遍,每个细节都不要放过,因为任何一个点和微信要求不符都会导致支付不成功.https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=3_1 2.经过验证的微信支付功能,会需要一些商

Asp.net Core 微信小程序支付

最近要做一个微信小程序支付的功能 在网上找了一下 .net Core做微信支付的博客 和 demo 几乎没有 自己研究了好几天 参考了 很多 大牛的博客 勉强做出来了  因为参数都没有 比如 opid 小程序域名 所以只是简单的测了一下 模拟了微信支付的回调请求 后续等项目上线 会回来填坑的 第一次看小程序支付的api文档 看得我一脸懵逼 现在简单说一下吧 先上一个官方图 小程序支付的流程是这样的 首先 用户下单 然后后台生成订单 调用统一支付api(注意这并不是支付 只是算一个预下单 通知下微