Navite支付介紹
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>