php微信H5支付V3版

16 篇文章 0 订阅
3 篇文章 0 订阅
php微信H5支付V3版
    /**
     * todo 微信支付下单
     * @param Request $request
     */
    public function unifiedOrder(Request $request)
    {
        $body = [
            'appid' => config('xingji_wechatpay_v3.appid'),
            'mchid' => config('xingji_wechatpay_v3.mch_id'),
            'description' => '描述',
            'out_trade_no' => $phone . '_' . time(),
            'notify_url' => $this->notify_url,
            'amount' => [
                'total' => $money,
                'currency' => 'CNY'
            ],
            'scene_info' => [
                'payer_client_ip' => $request->ip(),
                'h5_info' => [
                    'type' => 'Wap',
                ],
            ],
        ];
        $server = $request->server();
        $headers = self::sign('POST', 'https://api.mch.weixin.qq.com/v3/pay/transactions/h5', json_encode($body));
        $http = new Client([
            'headers' => $headers
        ]);
        $response = $http->post('https://api.mch.weixin.qq.com/v3/pay/transactions/h5', [
            'json' => $body
        ]);
        $result = json_decode($response->getBody()->getContents(), true);

        $returnUrl = "支付完成跳转地址";
        $headers = [
            'REFERER' => $returnUrl,
            'USER-AGENT' => $server["HTTP_USER_AGENT"],
        ];
        $url = $result['h5_url'] . "&redirect_url=" . urlencode($returnUrl);
        $client = new Client();
        $response = $client->post($url, [
            'headers' => $headers,
            'verify' => false,
        ]);
        $body = $response->getBody()->getContents();
        echo $body;
        exit;
    }
 /**
     * 签名
     * @param string $http_method 请求方式GET|POST
     * @param string $url url
     * @param string $body 报文主体
     * @return array
     */
    public static function sign($http_method = 'POST', $url = '', $body = '')
    {
        $mch_private_key = self::getMchKey();//私钥
        $timestamp = time();//时间戳
        $nonce = self::getRandomStr(32);//随机串
        $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, $mch_private_key, 'sha256WithRSAEncryption');
        $sign = base64_encode($raw_sign);
        //设置HTTP头
        $token = sprintf('WECHATPAY2-SHA256-RSA2048 mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"',
            config('xingji_wechatpay_v3.mch_id'), $nonce, $timestamp, config('xingji_wechatpay_v3.serial_no'), $sign);
        return [
            'Accept' => 'application/json',
            'User-Agent' => '*/*',
            'Content-Type' => 'application/json; charset=utf-8',
            'Authorization' => $token
        ];
    }

    //读取私钥
    public static function getMchKey()
    {
        return openssl_get_privatekey(file_get_contents('apiclient_key.pem'));
    }

    /**
     * 获得随机字符串
     * @param $len      integer       需要的长度
     * @param $special  bool      是否需要特殊符号
     * @return string       返回随机字符串
     */
    public static function getRandomStr($len, $special = false)
    {
        $chars = [
            "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k",
            "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v",
            "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G",
            "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R",
            "S", "T", "U", "V", "W", "X", "Y", "Z", "0", "1", "2",
            "3", "4", "5", "6", "7", "8", "9"
        ];
        if ($special) {
            $chars = array_merge($chars, [
                "!", "@", "#", "$", "?", "|", "{", "/", ":", ";",
                "%", "^", "&", "*", "(", ")", "-", "_", "[", "]",
                "}", "<", ">", "~", "+", "=", ",", "."
            ]);
        }
        $charsLen = count($chars) - 1;
        shuffle($chars);
        $str = '';
        for ($i = 0; $i < $len; $i++) {
            $str .= $chars[mt_rand(0, $charsLen)];
        }
        return $str;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个 Java 本的微信 H5 支付 V3 API 异步通知的示例代码: ```java import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.Base64; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; public class WeChatH5NotifyHandler { private static final String WECHAT_API_CERT_SERIAL_NUMBER = "YOUR_WECHAT_API_CERT_SERIAL_NUMBER"; private static final String WECHAT_API_CERTIFICATE = "YOUR_WECHAT_API_CERTIFICATE"; private static final String WECHAT_API_CERTIFICATE_PRIVATE_KEY = "YOUR_WECHAT_API_CERTIFICATE_PRIVATE_KEY"; public static void handleNotify(HttpServletRequest request, HttpServletResponse response) throws IOException { try { InputStream inputStream = request.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); StringBuilder requestBody = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { requestBody.append(line); } // 验证通知的签名 String wechatSerialNumber = request.getHeader("Wechatpay-Serial"); String wechatSignature = request.getHeader("Wechatpay-Signature"); String wechatTimestamp = request.getHeader("Wechatpay-Timestamp"); String wechatNonce = request.getHeader("Wechatpay-Nonce"); if (verifySignature(wechatSerialNumber, wechatSignature, wechatTimestamp, wechatNonce, requestBody.toString())) { // 验证签名成功 // 处理支付成功的逻辑 // ... // 返回成功响应给微信服务器 response.setStatus(HttpServletResponse.SC_OK); response.getWriter().write("OK"); } else { // 验证签名失败,返回失败响应给微信服务器 response.setStatus(HttpServletResponse.SC_BAD_REQUEST); response.getWriter().write("Signature verification failed."); } } catch (Exception e) { e.printStackTrace(); // 返回失败响应给微信服务器 response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); response.getWriter().write("Internal Server Error"); } } private static boolean verifySignature(String wechatSerialNumber, String wechatSignature, String wechatTimestamp, String wechatNonce, String requestBody) throws Exception { String message = wechatTimestamp + "\n" + wechatNonce + "\n" + requestBody + "\n"; String signature = "SHA256withRSA"; X509Certificate certificate = getCertificate(); certificate.checkValidity(); certificate.verify(certificate.getPublicKey()); return true; // 假设签名验证成功 } private static X509Certificate getCertificate() throws CertificateException { byte[] certBytes = Base64.getDecoder().decode(WECHAT_API_CERTIFICATE.getBytes(StandardCharsets.UTF_8)); CertificateFactory certificateFactory = CertificateFactory.getInstance("X509"); InputStream inputStream = new ByteArrayInputStream(certBytes); return (X509Certificate) certificateFactory.generateCertificate(inputStream); } } ``` 在上述代码中,我们创建了一个名为 `WeChatH5NotifyHandler` 的类,其中的 `handleNotify` 方法用于处理微信 H5 支付 V3 API 的异步通知。该方法接收 `HttpServletRequest` 和 `HttpServletResponse` 对象作为参数,从请求中获取异步通知的数据,并进行相应的处理逻辑。 在 `handleNotify` 方法中,我们首先获取请求中的数据,并从请求头中获取签名相关信息(`Wechatpay-Serial`、`Wechatpay-Signature`、`Wechatpay-Timestamp`、`Wechatpay-Nonce`)。然后,我们使用 `verifySignature` 方法验证通知的签名是否正确。在示例代码中,我们假设签名验证成功。 如果签名验证成功,则表示支付成功,可以进行相应的处理逻辑,并返回成功响应给微信服务器。如果签名验证失败,则返回失败响应给微信服务器。 请注意,真实的微信 H5 支付 V3 API 的异步通知处理可能涉及到与微信服务器的交互、密钥管理、验签等复杂操作,需要仔细阅读微信支付文档,并使用微信提供的 SDK 或工具类来简化开发。以上示例代码仅供参考,需要根据实际情况进行修改和完善。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值