vue+laravel使用微信Natvite支付

Native支付是指商户系统按微信支付协议生成支付二维码,用户再用微信“扫一扫”完成支付的模式。适用于PC网站、实体店单品或订单、媒体广告支付等场景
1.先阅读微信支付接入前的准备文档 文档连接:Native支付接入前准备
2.php下载插件 composer require wechatpay/wechatpay
3.需要把证书文件下载下来用于签名验证。下载的签名文件有例如

4.需要用到的参数配置到env环境变量中 如下

5.代码实现

获取支付二维码链接
/**
 * 微信二维码预支付
 * @param string $total 价格
 * @param string $outTradeNo 商户订单号
 * @param int $duration 二维码有效时长 单位:秒
 * @return array 返回二维码链接
 */
 public static function wxNativePrePay(string $total, string $outTradeNo, $duration = 180)
 {
 try {
 $config = Common::get_platform_payInfo();
 $time = \time();
 $time_expire = $time + $duration;
 $rfc3339_time = date(DATE_RFC3339, $time_expire);
 $total = intval(bcmul($total, 100));
 $payInfo = [
 'out_trade_no' => $outTradeNo,
 'appid' => $config['appId'],
 'description' => '支付维修费用',
 'total' => $total,
 'time_expire' => (string)$rfc3339_time,
 ];
 $instance = Common::wxPayObj();
 $resp = $instance
 ->chain('v3/pay/transactions/native')
 ->post(['json' => [
 'mchid' => $config['merchantId'],
 'out_trade_no' => $payInfo['out_trade_no'],
 'time_expire' => $payInfo['time_expire'],
 'appid' => $config['appId'],
 'description' => $payInfo['description'],
 'notify_url' => $config['notify_url'],
 'amount' => [
 'total' => $payInfo['total'],
 'currency' => 'CNY'
 ],
 ]]);
 $data = [];
 $data['code'] = (int)$resp->getStatusCode();
 $data['body'] = $resp->getBody();
 return $data;
 } catch (\Exception $exception) {
 if ($exception instanceof RequestException && $exception->hasResponse()) {
 $message = "错误回复:" + $exception->getResponse() + "错误码:" + $exception->getResponse()->getStatusCode();
 +"错误原因" + $exception->getResponse()->getReasonPhrase();
 Log::info($message);
 }
 return [];
 }
 }
common只使用的方法
public static function get_platform_payInfo() {
 $data['merchantPrivateKeyFilePath'] = env('MERCHANT_FILE_PATH');
 $data['platformCertificateFilePath'] = env('PLATFORM_FILE_PATH');
 $data['merchantId'] = env('WX_MERCHANT_ID');
 $data['merchantCertificateSerial'] = env('CERTIFICATE_SERIAL');
 $data['appId'] = env('WX_APP_ID');
 $data['appSecret'] = env('WX_APP_SECRET');
 $data['notify_url'] = env('WX_NOTIFY_URL');
 $data['api_key'] = env('WX_API_KEY');
 return $data;
 }
 public static function wxPayObj()
 {
 try {
 $payInfo = self::get_platform_payInfo();
 // 从本地文件中加载「商户API私钥」,「商户API私钥」会用来生成请求的签名
 $merchantPrivateKeyInstance = Rsa::from($payInfo['merchantPrivateKeyFilePath'], Rsa::KEY_TYPE_PRIVATE);
 // 从本地文件中加载「微信支付平台证书」,用来验证微信支付应答的签名
 $platformPublicKeyInstance = Rsa::from($payInfo['platformCertificateFilePath'], Rsa::KEY_TYPE_PUBLIC);
 // 从「微信支付平台证书」中获取「证书序列号」
 $platformCertificateSerial = PemUtil::parseCertificateSerialNo($payInfo['platformCertificateFilePath']);
 // 构造一个 APIv3 客户端实例
 $instance = Builder::factory([
 'mchid' => $payInfo['merchantId'],
 'serial' => $payInfo['merchantCertificateSerial'],
 'privateKey' => $merchantPrivateKeyInstance,
 'certs' => [
 $platformCertificateSerial => $platformPublicKeyInstance,
 ],
 ]);
 return $instance;
 } catch (\Exception $e) {
 Log::info("返回微信支付对象失败", $e);
 return false;
 }
 }

前端vue DEMO

需要用的的插件 qrcode

点击查看代码
<template>
 <div class="center">
 <el-button type="primary" @click="toWxPrePay">支付</el-button>
 <el-dialog title="支付" :visible.sync="payVisible" width="30%">
 <div class="qrcode_box">
 <canvas id="canvas" ref="qrcodeCanvas" class="qrcode"></canvas>
 <div style="color: #409EFF">请使用微信支付</div>
 </div>
 </el-dialog>
 </div>
</template>
<script>
import {wxPayInfo} from "@/api/teacher";
import QRCode from "qrcode";
import {wxTransactions} from "@/api/wxAccounts";
export default {
 name: "add",
 data() {
 return {
 payVisible: false,
 codeUrl: '',
 outTradeNo: '',
 intervalId: null,
 }
 },
 destroyed() {
 this.stopPolling()
 },
 methods: {
 toWxPrePay() {
 let total = "0.01" //这里是要付的价格
 wxPayInfo({
 userId: localStorage.getItem("ID"),
 teacherId: 1,
 total: total
 }).then(res => {
 this.codeUrl = res.data['code_url']
 this.outTradeNo = res.data['out_trade_no']
 this.payVisible = true
 this.$nextTick(() => {
 const canvas = document.getElementById('canvas')
 console.log("这是收到的coderUrl", this.codeUrl)
 var text = this.codeUrl
 const ctx = canvas.getContext('2d')
 QRCode.toCanvas(canvas, text, error => {
 if (error) console.log(error)
 })
 this.startPolling()
 })
 })
 },
 startPolling() {
 this.intervalId = setInterval(this.interPaymentWx, 2000); //每两秒更新一次
 },
 stopPolling() {
 if (this.intervalId) clearInterval(this.intervalId)
 },
 //查询订单状态
 interPaymentWx() {
 wxTransactions({
 out_trade_no: this.outTradeNo
 }).then(res => {
 let trade_state = res.data['trade_state']
 if (trade_state === 'SUCCESS') {
 this.$message({
 message: '支付成功',
 type: 'success'
 })
 this.payVisible = false
 this.stopPolling()
 }
 })
 },
 }
}
</script>
<style scoped lang="scss">
.qrcode_box {
 display: flex;
 flex-direction: column;
 justify-content: space-between;
 align-items: center;
 width: 100%;
 .qrcode {
 width: 270px !important;
 height: 270px !important;
 }
}
</style>
作者:hasse原文地址:https://www.cnblogs.com/spinachead/p/18568273

%s 个评论

要回复文章请先登录注册