注意事项

1,请求接口签名方式——RSA,用到了API证书序列号,后缀为key.pem的密钥文件,cert文件要用java自己生成,具体参考:https://developers.weixin.qq.com/community/develop/doc/000e4a0d5dc1486acc19c6fd15bc00?_at=1569021781371

2,返给小程序或者H5的支付参数签名也要RSA加密,而且仅支持RSA加密。

3,支付成功回调的数据要解密,根据php版本有的需要安装libsodium-php扩展:http://pecl.php.net/package/libsodium  我公司的服务器是php7.0的

wget http://pecl.php.net/get/libsodium-2.0.10.tgz
pecl install libsodium-2.0.10.tgz

php.ini 文件添加扩展,重启php就可以了

extension=sodium.so

安装官方sdk

composer require wechatpay/wechatpay-guzzle-middleware

代码

<?phpnamespace app\store\controller\api;use GuzzleHttp\Exception\RequestException;
use WechatPay\GuzzleMiddleware\WechatPayMiddleware;
use WechatPay\GuzzleMiddleware\Util\PemUtil;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Client;/**** Class PayV3* @package app\store\controller\api*/
class PayV3
{// 商户相关配置public $spAppId;public $subAppId;public $merchantId; // 商户号public $merchantSerialNumber = ''; // 商户API证书序列号public $merchantPrivateKey ; // 商户证书私钥public $wechatpayCertificateV3; // 微信支付平台证书public $key ;public $keyV3 ;public $out_trade_no;public function __construct(){//服务商appid$this->spAppId = 'wxxxxxxxxxxxxxxxxx';//特约商户appid$this->subAppId = 'wxxxxxxxxxxxxxxxxx';//服务商商户号$this->merchantId = '160xxxxxxx';//特约商户商户号(测试用项目里做成变量)$this->subMerchantId = '160xxxxxxx';$this->key = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';//apiV3 key$this->keyV3 = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';//微信商户号查看$this->merchantSerialNumber = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';//微信商户号下载$this->merchantPrivateKey = PemUtil::loadPrivateKey('config/01jh_cert/apiclient_key.pem');//此文件是java环境生成的不是商户号下载的,具体自作参考:https://developers.weixin.qq.com/community/develop/doc/000e4a0d5dc1486acc19c6fd15bc00?_at=1569021781371//注意java版本 我之前的是1.8.0_131 不好使跟新为 1.8.0_291 生成成功了$this->wechatpayCertificateV3 = PemUtil::loadCertificate('config/01jh_cert/v3_cert.pem');}private function client() {$wechatpayMiddleware = WechatPayMiddleware::builder()->withMerchant($this->merchantId, $this->merchantSerialNumber, $this->merchantPrivateKey) // 传入商户相关配置->withWechatPay([ $this->wechatpayCertificateV3 ]) // 可传入多个微信支付平台证书,参数类型为array->build();// 将WechatPayMiddleware添加到Guzzle的HandlerStack中$stack = HandlerStack::create();$stack->push($wechatpayMiddleware, 'wechatpay');// 创建Guzzle HTTP Client时,将HandlerStack传入return new Client(['handler' => $stack]);}private function request($url,$data,$method='POST') {$client = $this->client();// 接下来,正常使用Guzzle发起API请求,WechatPayMiddleware会自动地处理签名和验签try {$resp = $client->request($method, $url, ['headers' => ['Accept' => 'application/json', 'Content-Type' => 'application/json'],'json' => $data,]);//echo $resp->getStatusCode().' '.$resp->getReasonPhrase()."\n";//echo $resp->getBody()."\n";if($resp->getReasonPhrase() == 'OK') {return $resp->getBody();}return false;} catch (RequestException $e) {// 进行错误处理echo $e->getMessage();
//            echo $e->getMessage()."\n";
//            if ($e->hasResponse()) {
//                echo $e->getResponse()->getStatusCode().' '.$e->getResponse()->getReasonPhrase()."\n";
//                echo $e->getResponse()->getBody();
//            }}}//小程序获取支付参数(使用时直接调取这个方法就ok了)public function jsapiParams($data) {$this->out_trade_no = $data['out_trade_no'];//这可以设置默认的参数,也可以不设置$d = ['sp_appid'            => $this->spAppId ,'sp_mchid'            => $this->merchantId,'sub_appid'           => $this->subAppId,//支付到特约商户上'sub_mchid'           => $this->subMerchantId,'description'         =>'自定义商品描述','out_trade_no'        => $this->out_trade_no,'notify_url'          => 'https://xxxxx.xxxxx.com/ygyAdmin/public/store/api.v3pay/notify','amount'              => ['total' => 1000],//'payer'               => ['sp_openid' => 'o8MCu5UvKGRs8gJsP_VNFLvZj_fM'],'payer'               => ['sub_openid' => 'ogD1q5Hz0bNdoPac0DYfV6jLcR0s'],//是否分账//'settle_info'         =>['profit_sharing' => true]];foreach ($data as $k=>$v) $d[$k] = $v;$body = $this->request('https://api.mch.weixin.qq.com/v3/pay/partner/transactions/jsapi',$d);if($body === false) return false;$nonce_str = $this->getNoncestr();$prepay_id = json_decode($body,true)['prepay_id'];$time = time();//在哪个小程序下//$tmp['appId'] = $this->appid;$tmp['appId'] = $this->subAppId;$tmp['timeStamp'] = $time;$tmp['nonceStr'] = $nonce_str;$tmp['package'] = 'prepay_id='.$prepay_id;$data = array();$data['state'] = 200;$data['timeStamp'] = "$time";$data['nonceStr'] = $nonce_str;$data['package'] = 'prepay_id='.$prepay_id;//统一下单接口返回的 prepay_id 参数值,提交格式如:prepay_id=*$data['paySign'] = $this->sign($tmp);$data['out_trade_no'] = $this->out_trade_no;return $data;}//签名 $data要先排好顺序private function sign($data){$string = '';foreach ($data as $key=>$value){if(!$value) continue;$string .= $value."\n";}$private_key = $this->merchantPrivateKey;openssl_sign($string, $raw_sign, $private_key, 'sha256WithRSAEncryption');$sign = base64_encode($raw_sign);return $sign;}/*** 获取随机数*/public function getNoncestr($length = 32){$chars = "abcdefghijklmnopqrstuvwxyz0123456789";$str = "";for ($i = 0; $i < $length; $i++) {$str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);}return $str;}/*** 支付回调数据解密* @param string    $associatedData     AES GCM additional authentication data* @param string    $nonceStr           AES GCM nonce* @param string    $ciphertext         AES GCM cipher text* @return string|bool      Decrypted string on success or FALSE on failure*/public function decryptToString($associatedData, $nonceStr, $ciphertext){$ciphertext = \base64_decode($ciphertext);if (strlen($ciphertext) <= self::AUTH_TAG_LENGTH_BYTE) {return false;}// ext-sodium (default installed on >= PHP 7.2)if (function_exists('\sodium_crypto_aead_aes256gcm_is_available') &&\sodium_crypto_aead_aes256gcm_is_available()) {return \sodium_crypto_aead_aes256gcm_decrypt($ciphertext, $associatedData, $nonceStr, $this->aesKeyV3);}// ext-libsodium (need install libsodium-php 1.x via pecl)if (function_exists('\Sodium\crypto_aead_aes256gcm_is_available') &&\Sodium\crypto_aead_aes256gcm_is_available()) {return \Sodium\crypto_aead_aes256gcm_decrypt($ciphertext, $associatedData, $nonceStr, $this->aesKeyV3);}// openssl (PHP >= 7.1 support AEAD)if (PHP_VERSION_ID >= 70100 && in_array('aes-256-gcm', \openssl_get_cipher_methods())) {$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->aesKeyV3, \OPENSSL_RAW_DATA, $nonceStr,$authTag, $associatedData);}throw new \RuntimeException('AEAD_AES_256_GCM需要PHP 7.1以上或者安装libsodium-php');}
}

php 微信支付V3接口相关推荐

  1. Node——微信支付 V3接口

    1. 新建v3PayApi.js const fs = require("fs") const request = require('request') const rsa = r ...

  2. java异步调用微信接口_微信支付V3 SDK(Java版,支持同步异步调用)

    我们在开发微信支付时,发现微信官方已经对SDK做了升级,V3版本的SDK从设计上符合RESTful规范. 我们再在开源库中寻找是否有现成de开箱即用.并且支持响应式编程的SDK版本.经过一凡寻找,令我 ...

  3. 微信公众平台开发(120) 微信支付报关接口

    关键字:微信支付 微信支付v3 报关接口  作者:方倍工作室 原文: http://www.cnblogs.com/txw1958/p/wxpay-declare.html 本文介绍微信支付下的报关接 ...

  4. 微信支付v3版本npm包

    wechatpay-node-v3 # 微信支付v3 支持在ts和js中使用 欢迎大家加入一起完善这个api 前言 微信官方在2020-12-25正式开放了v3版本的接口,相比较旧版本v2有了不少改变 ...

  5. 微信支付V3版 java

    微信支付V3版 1.引入依赖 2.创建时间工具类 DateTimeZoneUtil.class 3.解密工具类 AesUtil.class 4.对外暴露方法 公共参数 4-1.支付下单 V3PayGe ...

  6. springboot利用官方SDK(wechatpay-apache-httpclient)接入微信支付V3

    利用微信官方提供的SDK wechatpay-apache-httpclient 实现.以微信小程序支付为例,其他支付也是一样的,就是参数和接口地址不同. 微信支付V3文档 首先要在微信商户平台设置好 ...

  7. 微信支付V3版本的 签名生成,验签,解密,统一下单的简单封装

    微信支付 V3版本的 签名生成,验签,解密,统一下单的简单封装 V3Base 获取平台证书 回调报文解密 统一下单 暂时看了文档只完成了这部分,感觉封装的不是特别完美,希望有大佬指点一下,想着封装好一 ...

  8. java微信支付v3系列——6.微信支付查询订单API

    目录 java微信支付v3系列--1.微信支付准备工作 java微信支付v3系列--2.微信支付基本配置 java微信支付v3系列--3.订单创建准备操作 java微信支付v3系列--4.创建订单的封 ...

  9. SpringBoot集成微信支付V3

    河南循中网络科技有限公司 - 精心创作,详细分解,按照步骤,均可成功! 文章目录 吐槽! 此文章包含实现了哪些接口? 学习资料 集成微信支付V3 什么是"商户证书"?什么是&quo ...

  10. java微信支付v3系列——4.创建订单的封装及使用

    目录 java微信支付v3系列--1.微信支付准备工作 java微信支付v3系列--2.微信支付基本配置 java微信支付v3系列--3.订单创建准备操作 java微信支付v3系列--4.创建订单的封 ...

最新文章

  1. android test.apk,app-debug.apk和app-debug-androidTest.apk在安装macaca-android模块的时候build失败...
  2. mysql五补充部分:SQL逻辑查询语句执行顺序
  3. 企业人员管理项目咨询_祝贺直线管理咨询与振野智能营销咨询项目启动
  4. thinkphp3.23开发的“二当家的”官网
  5. 阿里巴巴、支付宝员工都在用的知识管理工具,究竟有何特别?
  6. mysql drop 权限_MySQL procedure drop权限问题
  7. Tensorflow中的name_scope和variable_scope
  8. C语言中二级指针的作用
  9. isjavaidentifierpart和isjavaidentifierstart有区别么?
  10. atitit 2017年学业计划 v5 r818.xlsx
  11. xshell5 的账号密码搬家
  12. 目标检测:SSD目标检测中PriorBox代码解读
  13. printf() 输出数据格式汇总
  14. Oracle:ORA-00054 资源正忙 -- 锁表的解决方法
  15. Multipath TCP(MPTCP) Congestion Control抛砖引玉
  16. 关于急救和医学常识,告诉我们你想知道什么?
  17. 《区块链DAPP开发入门、代码实现、场景应用》笔记1——天外飞仙DAPP
  18. 腾讯区块链强势出击,公链的机会在哪里?
  19. 【学习笔记】arduino mega2560 和 ESP8266WIFI模块 联合调试 ①
  20. 2022年国内私网IP地址

热门文章

  1. 2G维码器-以及4G维码器--基于合宙air202 air720sl luat
  2. python列表排序sorted_python列表使用sorted排序的方法
  3. android小米手机拍照功能,小米手机 调用相机拍照后无法返回问题
  4. 超声波传感器测距原理与模块使用
  5. H264的码率控制方法(CBR, VBR, CVBR,ABR)
  6. 室内定位——卡尔曼滤波原理、Matlab与javascript实现
  7. Visio 2013—安装步骤说明
  8. html5 ios 音乐加载失败,Cocos2d-JS HTML5的cc.audioEngine音乐音效在iOS设备上不响应静音键的问题...
  9. python小明爬楼梯_Python3爬楼梯算法示例
  10. 正态分布假设检验相关知识