微信支付生成平台证书

    public function test1(){
        $wx_config  = [
            // 前面的appid什么的也得保留哦
            'app_id'             => '',   // appid
            'mch_id'             => '', // 商户号
            'key'                => '', // apiV3 秘钥
            'cert_path'          =>  public_path().'/wxpay/apiclient_cert04.pem', // 绝对路径!!!!
            'key_path'           => public_path().'/wxpay/apiclient_key04.pem',      // 绝对路径!!!!

        ];
        //获取证书
        $url2 = '/v3/certificates';
        $token2 = self::token1($url2,'GET','',$wx_config);
        $url3 = 'https://api.mch.weixin.qq.com/v3/certificates';
        $serial1 = self::https_request($url3,'',$token2);

        $arr = json_decode($serial1,true);
        $serial = $arr['data'][0]['serial_no'];

        // 这里是获取 平台证书的地方 解密之后 需要自行保存
        $associated_data = $arr['data'][0]['encrypt_certificate']['associated_data'];
        $ciphertext = $arr['data'][0]['encrypt_certificate']['ciphertext'];
        $nonce = $arr['data'][0]['encrypt_certificate']['nonce'];

        $aesUtil=new AesUtil($wx_config['key']);
        $jiemi=$aesUtil->decryptToString($associated_data,$nonce,$ciphertext);
        print_r($jiemi);
        $print_r($serial);

    }

    public static function https_request($url,$data,$token)
    {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, (string)$url);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
        if (!empty($data)){
            curl_setopt($curl, CURLOPT_POST, 1);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        }
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        //添加请求头
        $headers = [
            'Authorization:'.$token,
            'Accept: application/json',
            'Content-Type: application/json; charset=utf-8',
            'User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36',
        ];
        if(!empty($headers)){
            curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
        }
        $output = curl_exec($curl);
        curl_close($curl);
        return $output;
    }


    /**
     * @notes 获取签名
     */
    public static function token1($url,$http_method,$data,$config)
    {
        $timestamp   = time();//请求时间戳
        $url_parts   = parse_url($url);//获取请求的绝对URL
        $nonce       = $timestamp.rand('10000','99999');//请求随机串
        $body        = empty($data) ? '' : json_encode((object)$data);//请求报文主体
        $stream_opts = [
            "ssl" => [
                "verify_peer"=>false,
                "verify_peer_name"=>false,
            ]
        ];

        $apiclient_cert_arr = openssl_x509_parse(file_get_contents($config['cert_path'],false, stream_context_create($stream_opts)));
        $serial_no          = '684245A4B04BB2B9D1538999BEF59A0340DA251E';//证书序列号
        $mch_private_key    = file_get_contents($config['key_path'],false, stream_context_create($stream_opts));//密钥
        $merchant_id = $config['mch_id'];//商户id
        $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, $mch_private_key, '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);//微信返回token
        return $schema.' '.$token;
    }

因通过     composer require wechatpay/wechatpay 和下面命令无法生成平台证书(命令只能在linux下生成,无法在windows使用)

php ./bin/CertificateDownloader.php -k ${apiV3key} -m ${mchId} -f ${mchPrivateKeyFilePath} -s ${mchSerialNo} -o ${outputFilePath}

apiV3key : 微信支付商户平台设置

mchId:微信支付商户号

mchPrivateKeyFilePath:微信工具生成的证书私钥

mchSerialNo:证书序列号,在微信支付商户平台可以查看,注意不是平台证书序列号

outputFilePath:输入路径,生成的平台证书到这

所以写了通过接口获取平台证书内容 和zheng

方法:访问test1接口,打印$jiemi为平台证书内容 ,$serial为平台证书序列号,需要用到一个AesUtil解密类,内容如下:

<?php

namespace App\Http\Controllers\Tools;

class AesUtil {
 /**
  * AES key
  *
  * @var string
  */
 private $aesKey;

 const KEY_LENGTH_BYTE = 32;
 const AUTH_TAG_LENGTH_BYTE = 16;

 /**
  * Constructor
  */
 public function __construct($aesKey) {
  if (strlen($aesKey) != self::KEY_LENGTH_BYTE) {
   throw new InvalidArgumentException('无效的ApiV3Key,长度应为32个字节');
  }
  $this -> aesKey = $aesKey;
 }

 /**
  * Decrypt AEAD_AES_256_GCM ciphertext
  *
  * @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-> aesKey);
  }

  // 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 -> aesKey);
  }

  // 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 -> aesKey, \OPENSSL_RAW_DATA, $nonceStr,
    $authTag, $associatedData);
  }

  throw new \RuntimeException('AEAD_AES_256_GCM需要PHP 7.1以上或者安装libsodium-php');
 }
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
生成微信支付二维码,可以使用微信支付官方提供的接口,以下是基于 Spring Boot 的简单实现步骤: 1. 引入相关依赖 ```xml <dependency> <groupId>com.github.wxpay</groupId> <artifactId>wxpay-sdk</artifactId> <version>3.0.9</version> </dependency> <dependency> <groupId>com.google.zxing</groupId> <artifactId>core</artifactId> <version>3.3.3</version> </dependency> <dependency> <groupId>com.google.zxing</groupId> <artifactId>javase</artifactId> <version>3.3.3</version> </dependency> ``` 2. 配置微信支付相关参数 ```java @Configuration public class WxPayConfig { // 微信支付分配的商户号 @Value("${wxpay.mchId}") private String mchId; // 微信支付分配的终端设备号 @Value("${wxpay.deviceInfo}") private String deviceInfo; // 微信支付分配的公众账号ID @Value("${wxpay.appId}") private String appId; // 微信支付分配的商户密钥 @Value("${wxpay.key}") private String key; // 微信支付异步通知地址 @Value("${wxpay.notifyUrl}") private String notifyUrl; // 微信支付统一下单接口地址 @Value("${wxpay.unifiedOrderUrl}") private String unifiedOrderUrl; // 微信支付查询订单接口地址 @Value("${wxpay.orderQueryUrl}") private String orderQueryUrl; // 微信支付关闭订单接口地址 @Value("${wxpay.closeOrderUrl}") private String closeOrderUrl; // 微信支付申请退款接口地址 @Value("${wxpay.refundUrl}") private String refundUrl; // 微信支付查询退款接口地址 @Value("${wxpay.refundQueryUrl}") private String refundQueryUrl; // 微信支付下载对账单接口地址 @Value("${wxpay.downloadBillUrl}") private String downloadBillUrl; // 微信支付交易保障接口地址 @Value("${wxpay.reportUrl}") private String reportUrl; // 签名类型 private final String SIGN_TYPE = "MD5"; // 连接超时时间 private final int CONNECT_TIMEOUT = 5000; // 读取超时时间 private final int READ_TIMEOUT = 10000; // 微信支付API证书路径 @Value("${wxpay.certPath}") private String certPath; // 微信支付API证书密码 @Value("${wxpay.certPassword}") private String certPassword; /** * 初始化微信支付配置 */ @Bean public WXPay wxPay() throws Exception { WXPayConfigImpl config = new WXPayConfigImpl(); config.setAppID(appId); config.setMchID(mchId); config.setKey(key); config.setDeviceInfo(deviceInfo); config.setSignType(SIGN_TYPE); config.setUnifiedOrderUrl(unifiedOrderUrl); config.setOrderQueryUrl(orderQueryUrl); config.setCloseOrderUrl(closeOrderUrl); config.setRefundUrl(refundUrl); config.setRefundQueryUrl(refundQueryUrl); config.setDownloadBillUrl(downloadBillUrl); config.setReportUrl(reportUrl); return new WXPay(config, notifyUrl, true, true); } /** * 微信支付配置类 */ class WXPayConfigImpl extends WXPayConfig { private String appId; private String mchId; private String key; private String deviceInfo; private String signType; private String unifiedOrderUrl; private String orderQueryUrl; private String closeOrderUrl; private String refundUrl; private String refundQueryUrl; private String downloadBillUrl; private String reportUrl; public void setAppID(String appId) { this.appId = appId; } public void setMchID(String mchId) { this.mchId = mchId; } public void setKey(String key) { this.key = key; } public void setDeviceInfo(String deviceInfo) { this.deviceInfo = deviceInfo; } public void setSignType(String signType) { this.signType = signType; } public void setUnifiedOrderUrl(String unifiedOrderUrl) { this.unifiedOrderUrl = unifiedOrderUrl; } public void setOrderQueryUrl(String orderQueryUrl) { this.orderQueryUrl = orderQueryUrl; } public void setCloseOrderUrl(String closeOrderUrl) { this.closeOrderUrl = closeOrderUrl; } public void setRefundUrl(String refundUrl) { this.refundUrl = refundUrl; } public void setRefundQueryUrl(String refundQueryUrl) { this.refundQueryUrl = refundQueryUrl; } public void setDownloadBillUrl(String downloadBillUrl) { this.downloadBillUrl = downloadBillUrl; } public void setReportUrl(String reportUrl) { this.reportUrl = reportUrl; } @Override public String getAppID() { return appId; } @Override public String getMchID() { return mchId; } @Override public String getKey() { return key; } @Override public InputStream getCertStream() { try { return new FileInputStream(new File(certPath)); } catch (FileNotFoundException e) { e.printStackTrace(); } return null; } @Override public int getHttpConnectTimeoutMs() { return CONNECT_TIMEOUT; } @Override public int getHttpReadTimeoutMs() { return READ_TIMEOUT; } @Override public String getDeviceInfo() { return deviceInfo; } @Override public String getSignType() { return signType; } @Override public String getUnifiedOrderUrl() { return unifiedOrderUrl; } @Override public String getOrderQueryUrl() { return orderQueryUrl; } @Override public String getCloseOrderUrl() { return closeOrderUrl; } @Override public String getRefundUrl() { return refundUrl; } @Override public String getRefundQueryUrl() { return refundQueryUrl; } @Override public String getDownloadBillUrl() { return downloadBillUrl; } @Override public String getReportUrl() { return reportUrl; } } } ``` 3. 调用微信支付统一下单接口,获取支付二维码 ```java @RestController @RequestMapping("/wxpay") public class WxPayController { @Autowired private WXPay wxPay; /** * 生成微信支付二维码 * * @param orderId 订单ID * @param amount 支付金额 * @return 二维码图片Base64编码字符串 */ @GetMapping("/qrcode") public String generateQrCode(@RequestParam("order_id") String orderId, @RequestParam("amount") int amount) { try { Map<String, String> data = new HashMap<>(); data.put("body", "xxxx"); // 商品描述 data.put("out_trade_no", orderId); // 订单号 data.put("total_fee", String.valueOf(amount)); // 支付金额,单位为分 data.put("spbill_create_ip", "127.0.0.1"); // 发起支付的客户端IP data.put("notify_url", "http://localhost/wxpay/notify"); // 支付成功的回调地址 data.put("trade_type", "NATIVE"); // 交易类型,JSAPI:公众号支付;NATIVE:扫码支付;APP:APP支付 data.put("product_id", orderId); // 商品ID,trade_type=NATIVE时必填 // 调用微信支付统一下单接口 Map<String, String> result = wxPay.unifiedOrder(data); String return_code = result.get("return_code"); String result_code = result.get("result_code"); if ("SUCCESS".equals(return_code) && "SUCCESS".equals(result_code)) { String codeUrl = result.get("code_url"); // 生成二维码 ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); BitMatrix bitMatrix = new MultiFormatWriter().encode(codeUrl, BarcodeFormat.QR_CODE, 300, 300); MatrixToImageWriter.writeToStream(bitMatrix, "png", outputStream); byte[] bytes = outputStream.toByteArray(); return Base64.getEncoder().encodeToString(bytes); } else { String err_code_des = result.get("err_code_des"); throw new RuntimeException(err_code_des); } } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e.getMessage()); } } } ``` 以上就是基于 Spring Boot 的微信支付二维码生成的简单实现了。需要注意的是,微信支付二维码的有效期为2小时,超过时间后需要重新生成
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值