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

  • 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' => []]);

有问题留言,随时查看

猜你喜欢