小程序实战教程之问答红包(二)微信支付

本文详细介绍了小程序微信支付的具体流程,包括从前端用户点击支付按钮到后端处理预支付信息的全过程,并提供了PHP后端实现的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上一次教程我们解决了用户登录问题,今天解决微信支付问题。
微信支付的文档第一次接触特别头晕,看的云里雾里的,好在还是解决了,今天就分享下微信支付的解决方法

这里写图片描述

小程序微信支付流程为:

1、用户点击支付按钮
2、小程序向我的服务器发送用户openid、支付金额,因为之前已经获取过用户openid,所以这里可以直接发送
3、我的服务器接收到这些信息后将这些信息和其它一些信息(具体发送字段参考这里)一起发送到接口https://api.mch.weixin.qq.com/pay/unifiedorder 换取prepay_id,这里的复杂之处在于有一个签名字段sign需要我们生成,具体方法见下文
4、经过第三步我的服务器就可以得到prepay_id,可微信觉得还不够安全,因此又要求我对这个信息签名确保安全性,没办法,我的服务器只好将prepay_id和appId等一起做一次加密,然后将加密信息连同其它一些信息发送给小程序端
5、小程序端接收到需要的信息后,就可以调用wx.requestPayment来调起用户的支付窗口请求用户支付
6、用户输入密码支付成功后微信会将结果发送到我的服务器,这时我会验证这个结果(支付金额等)正确不正确,如果正确整个流程就结束了

小程序端代码:

 wx.request({
      url: 'https://mydomain/mycontroller/pay',
      data:{
        openid:openid,
        userid:userid,
        hongbao:that.data.hongbao,
      },
      success:function(res){
        console.log(res)
        wx.requestPayment({
          'timeStamp': res.data.timeStamp,
          'nonceStr': res.data.nonceStr,
          'package': res.data.package,
          'signType': 'MD5',
          'paySign': res.data.paySign,
          'success': function (res) {
            console.log(res)
          },
          'fail': function (res) {
            console.log(res)
          }
        })
      }
    })

后端php处理我封装了一个类

<?php
$config = [
    'appid' => APPID, //小程序APPID
    'mch_id' => MCHID,       //商户号
    'api_key' => APISECRET //商户api secret
];

class Wxpay{ 
    //统一支付接口
    public static function uniorder($openid,$fee,$ip){
        $nonceStr = self::getNonceStr();
        $unidorder = array(
            'appid'         => $config['appid'],
            'mch_id'        => $config['mch_id'],
            'nonce_str'     => $nonceStr,
            'body'          => "问答-红包",//商品名称
            'device_info'   => "WEB",
            'out_trade_no'  => self::getTradeNum(),
            'total_fee'     => $fee* 100,
            'spbill_create_ip'  => $ip,
            'notify_url'    => 'https://mydomain/mycontroller/notify',
            'trade_type'    => 'JSAPI',
            'openid'        => $openid          
        );
        $sign = self::getSign($unidorder);
        $unidorder['sign'] = $sign;
        $url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        $xmldata = self::array2xml($unidorder);
        $res = self::curl_post($url,$xmldata);
        if(!$res){
            return "api post error";
        }
        $result = self::xml2array($res);
        if($result['result_code']=='FAIL'){
            return $result['result_msg'];
        }
        $prepay_id = $result['prepay_id'];
        //二次签名
        $time = time();
        $arr_sign2 = array( 
            'appId'   => $config['appid'],
            'nonceStr' => $nonceStr,
            'package' => "prepay_id=$prepay_id",
            'signType' => 'MD5',
            'timeStamp' => $time
        );
        $paySign = self::getSign($arr_sign2);
        return json_encode([
            'timeStamp' => strval($time),
            'nonceStr'  => $nonceStr,
            'package'   => "prepay_id=$prepay_id",
            'paySign'   => $paySign
        ]);
    }

    public static function curl_post($url,$data){
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);        
        $output = curl_exec($ch);
        curl_close($ch);
        return $output;
    }
    //获取16为随机字符串
    public static function getNonceStr(){
        $charts = "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz0123456789";
        $max = strlen($charts);
        $noncestr = "";
        for($i = 0; $i < 16; $i++)
        {
            $noncestr .= $charts[mt_rand(0, $max-1)];
        }
        return $noncestr;        
    }
    //获取签名
    public static function getSign($arr){
        //排序处理,微信文档要求必须参数名ASCII码从小到大排序
        ksort($arr);
        $stringA = "";
        foreach($arr as $key => $val){
            $stringA .= "$key=$val&";
        }
        $stringSignTemp = $stringA."key=$config['api_key']";
        $sign = strtoupper(md5($stringSignTemp));
        return $sign;        
    }
    //生成交易订单号 时间+随机六位数,例20180801121212097654
    public static function getTradeNum(){
        $num = "0123456789";
        $left_num = "";
        for($i=0;$i<6;$i++){
            $left_num .= $num[mt_rand(0,9)];
        }
        return date("YmdHis",time()).$left_num;
    } 

    //array2xml
    public static function array2xml($arr){
        if(!is_array($arr) || count($arr) <= 0){
            return false;
        }
        $xml = "<xml>";
        foreach ($arr as $key=>$val){
            if (is_numeric($val)){
                $xml.="<".$key.">".$val."</".$key.">";
            }else{
                $xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
            }
        }
        $xml.="</xml>";
        return $xml; 
    } 
    //xml2array
    public static function xml2array($xml){
        libxml_disable_entity_loader(true);                
        $xmlstring = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);                
        $val = json_decode(json_encode($xmlstring), true);                
        return $val;
    }
}

在控制器里调用这个类就可以实现支付了

//支付处理
    public function actionPay(){
        $get = Yii::$app->request->get();
        $openid = $get['openid'];
        $fee = $get['hongbao'];
        $ip = Yii::$app->request->userIP;
        $res = W下pay::uniorder($openid, $fee, $ip);
        return $res;
    }

以上就是今天的主要内容了,支付类如有问题可以和我联系。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值