PHP 接入微信支付分

2023-10-16 19:19:41 浏览数 (2)

♦ 背景

  • 最近项目中需要接入【微信支付分】的服务, 本文以 【免确认订单模式】:即先享模式(评估不通过不可使用服务)的使用 在此做一下实现步骤,希望能对小伙伴有所帮助,欢迎指摘 … 实现语言:PHP

官方文档,请参考:【>>> 微信支付分产品介绍】


☞ 前期准备

可直接参考指导文档 【>>>接入前准备】

    1. 首先商户向 weixinpay_scoreBD@tencent.com 发送邮件接入申请 一般都由 产品负责人员进行申请, 作为开发人员,重点在于阅读开发文档,编写测试用例
    1. 接口调用权限说明 此处引用官方解释如下:
代码语言:javascript复制
【免确认订单模式】是高级接口权限,需特殊申请才能使用。
 使用支付分的行业/场景,目前只能调用【需确认订单模式】接口。
 
 接口调用权限与服务id相关,在申请服务id时,只有上述场景下的服务 id,才有权限调用【免确认订单模式】接口。
 即只有在上述场景下,创建支付分订单 api 接口中 need_user_confirm 字段才能传。
 false:免确认订单。

以【免确认订单模式】为例,用户使用流程如下:

代码语言:javascript复制
首次使用,用户先从商户端(小程序/app/H5),跳入微信支付分页面,进行商户服务的授权
授权成功后,商户即可通过后台接口,进行支付分订单的创建和完结。用户无需再进入支付分授权页面进行授权。
    1. 测试号配置指引

一般正式开发前,需进行 【>>> 微信支付分测试号配置指引】


☛ 开发指引

再次提醒,以【免确认模式】开发操作为例

  • 流程分析
代码语言:javascript复制
1. 首先,用户在商户侧下单购买产品或服务,此时,我们需要先对用户的授权状态进行查询
2. 引导用户开启授权服务
	这一步需要根据实际场景,比如:APP场景调起支付分-授权服务、H5场景调起支付分-授权服务、小程序调起支付分-授权服务
3. 创建支付分订单
4. 商户为用户提供服务,待服务结束后,商户调用完结订单接口完结当前订单
5. 收到用户扣款成功通知,业务流程结束

▷ 第一步 引导用户开启授权服务

这一步需要前端的页面设计,主要在于引导开启授权服务

▷ 第二步 签名生成

服务端接口编写前,我们需要成功使用 微信官方要求的 >>>【签名规则】

  • 请求签名串的构造规则如下:
  • 通过参考文档,可以封装出一个方法,方便后期接口请求的使用 如下,即为鄙人整理的 HTTP Header 头 封装方法:
代码语言:javascript复制
	/**
     * @Notes:	签名封装方法
     * @param $url      请求接口链接地址
     * @param $type     请求方法 GET/POST
     * @param $bodys    请求主体 json_encode() 处理后的字符串
     * @return mixed
     * @User: zhanghj
     * @DateTime: 2023-08-31 18:18
     */
    public function getToken($url,$type,$bodys= ''){
        //请求头
        $arr_header[] = "Content-Type: application/json";
        $arr_header[] = "Accept: application/json";
        $arr_header[] = "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3100.0 Safari/537.36" ;
        //生成签名
        $http_method = $type;
        $timestamp = time();
        $nonce = $this->createNoncestr(32);
        $body = $bodys;
        $merchant_id = "XXXXXXXXXXXXXXXXX";  //商户号
        $serial_no = "NNNNNNNNNNNNNNNNNNNNNNNNNN"; //这个是证书号  这个必须使用新版证书
        $url_parts = parse_url($url);
        $canonical_url = ($url_parts['path'] . (!empty($url_parts['query']) ? "?${url_parts['query']}" : ""));
        $message = $http_method . "n" .
            $canonical_url . "n" .
            $timestamp . "n" .
            $nonce . "n" .
            $body . "n";
        openssl_sign($message, $raw_sign, PayConfig::PrivateKey, 'sha256WithRSAEncryption');
        $sign = base64_encode($raw_sign);
        $schema = 'WECHATPAY2-SHA256-RSA2048 ';
        $token = sprintf('mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"',
            $merchant_id, $nonce, $timestamp, $serial_no, $sign);
        $arr_header[] = "Authorization:" . $schema . $token;
        return $arr_header;
    }
    
    //作用:产生随机字符串,不长于 32 位
    public function createNoncestr($length = 32) {
        $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
        $str = "";
        for ($i = 0; $i < $length; $i  ) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        $result_ = strtoupper($str);
        return $result_;
    }

▷ 第三步 接口请求用例

以 “创建支付分订单” 为例,代码参考如下:

  • 基本的接口调用用例如下:
代码语言:javascript复制
		$url = 'https://api.mch.weixin.qq.com/v3/payscore/serviceorder';
		$data = array(
            'out_order_no'=>$orderSn,
            'appid' => PayConfig::AppId,//公众号
            'service_id' =>$wxPayConf['service_id'],//服务id
            'service_introduction'=>'智慧零售',
            'risk_fund'=>array(
                'name'=>'ESTIMATE_ORDER_COST',
                'amount'=>20000,
            ),
            'location'=>array(
                'start_location'=>'江苏省苏州市创意产业园15-303',
            ),
            'time_range'=>array(
                'start_time'=>'OnAccept',
            ),
            'need_user_confirm'=>false,
            'notify_url'=>'http://xxxxxxxxxxxxx/order/wx_pay_notify', //回调地址
        );
		$arr_header = $this->getToken($url,'POST',json_encode($data,JSON_UNESCAPED_UNICODE));
        $res = $this->posturl($url, json_encode($data,JSON_UNESCAPED_UNICODE), $arr_header);
        $res_arr = json_decode($res, true);

【提示】:可根据返回参数 "state",对支付分订单作符合业务的处理

  • 此处提供一个 CURL POST 请求处理方法
代码语言:javascript复制
 public function posturl($url, $data = null, $arr_header = []){
        $curl = curl_init();
        // curl 设置
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
        // 判断 $data get  or post
        if ( !empty($data) ) {
            curl_setopt($curl, CURLOPT_POST, 1);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        }

        if (!empty($arr_header)) {
            curl_setopt($curl, CURLOPT_HTTPHEADER, $arr_header);
        }

        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        // 执行
        $res = curl_exec($curl);
        curl_close($curl);
        return $res;
    }

▷ 第四步 支付成功回调通知 API

微信支付分通过支付成功通知接口将用户支付成功消息通知给商户

  • 【>>> 支付成功回调通知文档】 描述如下:
  • 【提示】 一般在此回调接口位置, 根据返回的订单号out_order_no,以及状态 state="DONE" 对商家应用的订单,处理最后的更新操作逻辑 同时,注意保存 微信服务端返回的支付信息,比如字段:transaction_id,方便后期的退款操作

▶ 附录

  • 简单场景中,常用的功能就是:
代码语言:javascript复制
  创建支付分订单
  取消支付分订单
  完结支付分订单
  支付成功回调通知
  申请退款、退款结果通知

0 人点赞