欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

php 对接微信小程序支付完整代码

程序员文章站 2022-07-13 17:08:45
...

一、准备工作

  1. 小程序注册,要以公司的以身份去注册一个小程序,才有微信支付权限;
  2. 绑定商户号。
  3. 在小程序填写合法域

二、完成以上条件,你可以得到

  1. 小程序appid 小程序秘钥 这两个用于获取用户openid;
  2. 商户号id ,商户号秘钥 支付接口必须的;

三、开始开发

<?php
/**
 * 生成微信签名
 * Date: 2020-09-21
 * Time: 10:41
 */
namespace app\model;

class Dev
{
    //作用:生成签名
    public static function get_sign($params, $secret) {
        foreach ($params as $k => $v) {
            $Parameters[$k] = $v;
        }
        //签名步骤一:按字典序排序参数
        ksort($Parameters);
        $String = self::formatBizQueryParaMap($Parameters, false);
        //签名步骤二:在string后加入KEY
        $String = $String . "&key=" . $secret;
        //签名步骤三:MD5加密
        $String = md5($String);
        //签名步骤四:所有字符转为大写
        $result_ = strtoupper($String);
        return $result_;
    }


    ///作用:格式化参数,签名过程需要使用
    public static 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;
    }

}
在这里插入代码片
<?php
/**
 * 微信支付
 * Date: 2020-09-21
 * Time: 10:41
 */

namespace app\model;

use think\Db;
use app\model\Dev;
use think\Cache;

class Wxpay
{


    /**
     * 微信支付
     * @param string $order_sn 订单号
     * @param string $fee 金额 如 0.01
     * @param $openid       openid
     * @param string $body 标题
     * @param string $notify_url 成功回掉路径
     */
    public static function pay($order_sn = '', $fee = '', $code, $body = '', $notify_url = '')
    {
        $ip               = $_SERVER['SERVER_ADDR'];
        $appid            = config('wx_payment.appid');//appid.如果是公众号 就是公众号的appid
        $mch_id           = config('wx_payment.wx_mch_id');  //商户号
        $nonce_str        = nonce_str();//随机字符串
        $out_trade_no     = $order_sn;//订单号
        $spbill_create_ip = $ip;//服务器的ip【自己填写】;
        $total_fee        = $fee * 100;// 微信支付单位是分,所以这里需要*100
        $trade_type       = 'JSAPI';//交易类型 默认

        $get_code = Cache::get($code);
        if ($get_code) {
            $openid = $get_code;
        } else {
            $WX_SECRET = config('wx_payment.appsecret');//AppSecret
            $url       = "https://api.weixin.qq.com/sns/jscode2session?appid=" . $appid . "&secret=" . $WX_SECRET . "&js_code=" . $code . "&grant_type=authorization_code";
            $infos     = json_decode(file_get_contents($url));
            $openid    = $infos->openid ?? '';
            if (empty($openid)) {
                $data['state']       = 0;
                $data['text']        = "支付失败";
                $data['RETURN_CODE'] = "";
                $data['RETURN_MSG']  = "";
                return json_encode($data);
            }
            $set_code = Cache::set($code, $openid);
        }
        //这里是按照顺序的 因为下面的签名是按照顺序 排序错误 肯定出错
        $post['appid']            = trim($appid);
        $post['mch_id']           = trim($mch_id);//商户号
        $post['nonce_str']        = trim($nonce_str);//随机字符串
        $post['notify_url']       = trim($notify_url);
        $post['body']             = $body;
        $post['openid']           = trim($openid);
        $post['out_trade_no']     = trim($out_trade_no);
        $post['spbill_create_ip'] = $spbill_create_ip;//终端的ip
        $post['total_fee']        = intval($total_fee); //总金额 最低为一分钱 必须是整数
        $post['trade_type']       = $trade_type;
        $sign                     = Dev::get_sign($post, config('wx_payment.wx_key'));
        $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> ';;
//        $post_xml                 = self::arrayToXml($post);

        //统一接口prepay_id
        $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
        $xml = http_request($url, $post_xml);

        write_log('Res:xml' . $xml, 'pay');
        $array = self::xml($xml);//全要大写
        write_log('Res:xml 转大写' . json_encode($array, JSON_UNESCAPED_UNICODE), 'pay');

        if ($array['RETURN_CODE'] == 'SUCCESS' && $array['RESULT_CODE'] == 'SUCCESS') {
            write_log('Res:状态成功', 'pay');

            $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']        = 200;
            $data['timeStamp']    = "$time";//时间戳
            $data['nonceStr']     = $nonce_str;//随机字符串
            $data['signType']     = 'MD5';//签名算法,暂支持 MD5
            $data['package']      = 'prepay_id=' . $array['PREPAY_ID'];//统一下单接口返回的 prepay_id 参数值,提交格式如:prepay_id=*
            $data['paySign']      = Dev::get_sign($tmp, config('wx_payment.wx_key'));
            $data['out_trade_no'] = $out_trade_no;


        } else {
            write_log('Res:失败', 'pay');
            $data['state']       = 0;
            $data['text']        = "支付失败";
            $data['RETURN_CODE'] = $array['RETURN_CODE'];
            $data['RETURN_MSG']  = $array['RETURN_MSG'];
        }
        return json_encode($data);
    }


    //获取xml
    private static function xml($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;
    }


}
在这里插入代码片
<?php
/**
 * 微信支付配置文件
 * Date: 2020-09-21
 * Time: 16:40
 */

// 微信支付
return [
    'appid' => '',    //小程序appid,如果是公众号 就是公众号的appid
    'appsecret' => '',    //小程序appid
    'wx_mch_id' => '',// 商户号
    'wx_key' => '',// 商户支付**
];
在这里插入代码片

最后调用 微信获取 code 获取openid

  $cash       = 0.01;
        $body       = "礼包支付";
        $host       = $this->request->domain();
        $notify_url = $host . '/order/notify/opay_notify';
        $res        = Wxpay::pay($order_sn, $cash, $code, $body, $notify_url);
        if (empty($res)) {
            return json(['code' => '2002', 'msg' => '请求支付失败', 'data' => []]);
        }
        $send_res = json_decode($res, true);

        if (!is_array($send_res) || empty($send_res)) {
            return json(['code' => '2002', 'msg' => '请求支付失败', 'data' => []]);
        }
        if ($send_res['state'] != '200') {
            return json(['code' => '2002', 'msg' => '请求支付失败', 'data' => []]);
        }
        return json(['code' => '0000', 'msg' => '支付成功', 'data' => []]);

有问题留言,随时查看

相关标签: php php