文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

PHP接入微信官方支付(native·APIv3)

2023-09-02 09:37

关注

一、项目介绍

两个文件实现微信官方支付(native·APIv3)的发起支付和回调应答功能

二、准备资料

  1. 商户号:需要使用到营业执照注册商户
  2. appid:小程序或者订阅号的appid
  3. APIv3秘钥:32位秘钥,APIv2秘钥为16位,不要混淆
  4. 证书序号:apiclient_key.pem文件中的秘钥,需要将该文件改为txt后缀,然后获取其中的秘钥

三、支付代码

1.index.php文件

setTotalFee($payAmount);$wxPay->setOutTradeNo($outTradeNo);$wxPay->setOrderName($orderName);$wxPay->setNotifyUrl($notifyUrl);$result = $wxPay->doPay();$url = 'https://wenhairu.com/static/api/qr/?size=300&text=' . $result['code_url'];echo "
";echo '二维码内容:' . $result['code_url'];//IndexService类class IndexService{ protected $mchid; protected $appid; protected $apiKey; protected $privateKey; protected $serialNumber; protected $totalFee; protected $outTradeNo; protected $orderName; protected $notifyUrl; protected $auth; protected $gateWay='https://api.mch.weixin.qq.com/v3'; public function __construct($mchid, $appid, $apikey, $privateKey, $serialNumber) { $this->mchid = $mchid; $this->appid = $appid; $this->apiKey = $apikey; $this->privateKey = $privateKey; $this->serialNumber = $serialNumber; } public function setTotalFee($totalFee) { $this->totalFee = floatval($totalFee); } public function setOutTradeNo($outTradeNo) { $this->outTradeNo = $outTradeNo; } public function setOrderName($orderName) { $this->orderName = $orderName; } public function setNotifyUrl($notifyUrl) { $this->notifyUrl = $notifyUrl; } public function doPay() { $reqParams = array( 'appid' => $this->appid, //公众号或移动应用appid 'mchid' => $this->mchid, //商户号 'description' => $this->orderName, //商品描述 'attach' => 'pay', //附加数据,在查询API和支付通知中原样返回,可作为自定义参数使用 'notify_url' => $this->notifyUrl, //通知URL必须为直接可访问的URL,不允许携带查询串。 'out_trade_no' => $this->outTradeNo, //商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一,详见【商户订单号】。特殊规则:最小字符长度为6 'amount'=>array( 'total'=> floatval($this->totalFee) * 100, //订单总金额,单位为分 'currency'=> 'CNY', //CNY:人民币,境内商户号仅支持人民币 ), 'scene_info'=>array( //支付场景描述 'payer_client_ip'=>'127.0.0.1' //调用微信支付API的机器IP ) ); $reqUrl = $this->gateWay.'/pay/transactions/native'; $this->getAuthStr($reqUrl,$reqParams); $response = $this->curlPost($reqUrl,$reqParams); return json_decode($response,true); } public function curlPost($url = '', $postData = array(), $options = array()) { if (is_array($postData)) { $postData = json_encode($postData); } $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'Authorization:'.$this->auth, 'Content-Type:application/json', 'Accept:application/json', 'User-Agent:'.$_SERVER['HTTP_USER_AGENT'] )); curl_setopt($ch, CURLOPT_TIMEOUT, 30); //设置cURL允许执行的最长秒数 if (!empty($options)) { curl_setopt_array($ch, $options); } //https请求 不验证证书和host curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); $data = curl_exec($ch); curl_close($ch); return $data; } private function getSchema(): string { return 'WECHATPAY2-SHA256-RSA2048'; } public function getAuthStr($requestUrl,$reqParams=array()): string { $schema = $this->getSchema(); $token = $this->getToken($requestUrl,$reqParams); $this->auth = $schema.' '.$token; return $this->auth; } private function getNonce() { static $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; $charactersLength = strlen($characters); $randomString = ''; for ($i = 0; $i < 32; $i++) { $randomString .= $characters[rand(0, $charactersLength - 1)]; } return $randomString; } public function getToken($requestUrl,$reqParams=array()): string { $body = $reqParams ? json_encode($reqParams) : ''; $nonce = $this->getNonce(); $timestamp = time(); $message = $this->buildMessage($nonce, $timestamp, $requestUrl,$body); $sign = $this->sign($message); $serialNo = $this->serialNumber; return sprintf('mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"', $this->mchid, $nonce, $timestamp, $serialNo, $sign ); } private function buildMessage($nonce, $timestamp, $requestUrl, $body = ''): string { $method = 'POST'; $urlParts = parse_url($requestUrl); $canonicalUrl = ($urlParts['path'] . (!empty($urlParts['query']) ? "?{$urlParts['query']}" : "")); return strtoupper($method) . "\n" . $canonicalUrl . "\n" . $timestamp . "\n" . $nonce . "\n" . $body . "\n"; } private function sign($message): string { if (!in_array('sha256WithRSAEncryption', openssl_get_md_methods(true))) { throw new \RuntimeException("当前PHP环境不支持SHA256withRSA"); } $res = $this->privateKey; if (!openssl_sign($message, $sign, $res, 'sha256WithRSAEncryption')) { throw new \UnexpectedValueException("签名验证过程发生了错误"); } return base64_encode($sign); }}

说明:

  1. 该微信支付属于native的APIv3版本,需要用到商户证书的相关内内容,不要和微信的其他支付方式或者APIv2相混淆
  2. index.php中的支付成功通知地址需要用https协议,该文件内容,下面会给出
  3. 仅需要填写IndexService类上边的配置即可,IndexService类的内容不需要修改

 2.notify.php

decryptToString($associatedData, $nonceStr, $ciphertext);//解密结果,为关联数组格式$resultArray = json_decode($resultJson, true);//交易成功if ($resultArray['trade_state'] === 'SUCCESS') {  //这里填写交易成功的相关业务,如更新账单状态,其中可能需要用到的参数如下    //$resultArray['out_trade_no']       商户订单号  //$resultArray['transaction_id']     订单号  //$resultArray['amount']['total']    订单金额}//NotifyService类class NotifyService{    protected $apiKey;    const AUTH_TAG_LENGTH_BYTE = 16;    public function __construct($apiKey)    {        $this->apiKey = $apiKey;    }        public function decryptToString(string $associatedData, string $nonceStr, string $ciphertext)    {        $ciphertext = \base64_decode($ciphertext);        if (strlen($ciphertext) <= self::AUTH_TAG_LENGTH_BYTE) {            return false;        }        $ctext = substr($ciphertext, 0, -self::AUTH_TAG_LENGTH_BYTE);        $authTag = substr($ciphertext, -self::AUTH_TAG_LENGTH_BYTE);        return \openssl_decrypt($ctext, 'aes-256-gcm', $this->apiKey, \OPENSSL_RAW_DATA, $nonceStr,            $authTag, $associatedData);    }} 

注意:

  1. notify.php中需要再次填写你的APIv3秘钥
  2. 在交易成功的if语句中,填写最终支付成功的相关业务逻辑

四、项目总结

  1. 如果有相关问题,可以在下面评论区评论

来源地址:https://blog.csdn.net/qq_63573498/article/details/129997511

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯