h5端实现调起微信app支付

在H5端实现调起微信APP支付需要通过一系列步骤,包括配置微信支付、前端调用微信支付接口、生成支付订单、调用支付接口等。下面是详细的步骤和代码示例:

1. 配置微信支付

首先需要在微信支付商户平台上进行配置,获取商户号(MchID)和API密钥(API Key),并且确保已开通支付功能。

2. 前端代码示例

前端代码主要是生成支付订单并调用微信支付接口。这里假设你使用的是Vue.js框架,其他框架类似。

HTML和JavaScript代码:
<!DOCTYPE html>
<html>
<head>
  <title>微信支付</title>
  <script src="https://res2.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
</head>
<body>
  <button id="payBtn">微信支付</button>

  <script>
    // 微信配置
    wx.config({
      debug: false,
      appId: 'yourAppId', // 必填,公众号的唯一标识
      timestamp: 0, // 必填,生成签名的时间戳
      nonceStr: '', // 必填,生成签名的随机串
      signature: '', // 必填,签名
      jsApiList: ['chooseWXPay'] // 必填,需要使用的JS接口列表
    });

    // 获取支付订单参数
    function getPaymentParams() {
      return fetch('https://your-backend-api.com/getPaymentParams', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          orderId: 'yourOrderId'
        })
      })
      .then(response => response.json());
    }

    // 调用微信支付
    function invokeWeChatPay(params) {
      wx.chooseWXPay({
        timestamp: params.timestamp, // 支付签名时间戳
        nonceStr: params.nonceStr, // 支付签名随机串,不长于 32 位
        package: params.package, // 统一下单接口返回的 prepay_id 参数值,提交格式如:prepay_id=***
        signType: params.signType, // 签名类型,默认为'SHA1',使用新版支付需传入'MD5'
        paySign: params.paySign, // 支付签名
        success: function (res) {
          // 支付成功后的回调函数
          alert('支付成功');
        },
        fail: function (res) {
          // 支付失败后的回调函数
          alert('支付失败');
        }
      });
    }

    document.getElementById('payBtn').addEventListener('click', function() {
      getPaymentParams().then(params => {
        invokeWeChatPay(params);
      });
    });
  </script>
</body>
</html>
代码说明:
  1. 微信配置:使用wx.config方法配置微信JS SDK,包括appIdtimestampnonceStrsignature等。
  2. 获取支付订单参数:通过调用后台接口获取支付订单参数,包括timestampnonceStrpackagesignTypepaySign
  3. 调用微信支付:使用wx.chooseWXPay方法调起微信支付,传入支付订单参数。

3. 后端代码示例

后端代码负责生成支付订单并返回给前端。以下是Node.js的示例代码。

Node.js代码:
const express = require('express');
const bodyParser = require('body-parser');
const request = require('request');
const crypto = require('crypto');

const app = express();
app.use(bodyParser.json());

const appId = 'yourAppId';
const mchId = 'yourMchId';
const apiKey = 'yourApiKey';

// 生成支付订单参数
app.post('/getPaymentParams', (req, res) => {
  const orderId = req.body.orderId;
  
  // 统一下单接口
  const unifiedOrderUrl = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
  
  const nonceStr = crypto.randomBytes(16).toString('hex');
  const timestamp = Math.floor(Date.now() / 1000).toString();
  const body = '商品描述';
  const outTradeNo = orderId;
  const totalFee = 1; // 订单金额,单位为分
  const spbillCreateIp = req.ip;
  const notifyUrl = 'https://your-notify-url.com/pay/notify';
  const tradeType = 'JSAPI';
  const openId = 'yourOpenId'; // 用户的OpenID

  // 签名
  const params = {
    appid: appId,
    mch_id: mchId,
    nonce_str: nonceStr,
    body,
    out_trade_no: outTradeNo,
    total_fee: totalFee,
    spbill_create_ip: spbillCreateIp,
    notify_url: notifyUrl,
    trade_type: tradeType,
    openid: openId
  };
  
  const stringA = Object.keys(params).sort().map(key => `${key}=${params[key]}`).join('&');
  const stringSignTemp = `${stringA}&key=${apiKey}`;
  const sign = crypto.createHash('md5').update(stringSignTemp).digest('hex').toUpperCase();
  
  const formData = `<xml>
    <appid>${appId}</appid>
    <mch_id>${mchId}</mch_id>
    <nonce_str>${nonceStr}</nonce_str>
    <sign>${sign}</sign>
    <body>${body}</body>
    <out_trade_no>${outTradeNo}</out_trade_no>
    <total_fee>${totalFee}</total_fee>
    <spbill_create_ip>${spbillCreateIp}</spbill_create_ip>
    <notify_url>${notifyUrl}</notify_url>
    <trade_type>${tradeType}</trade_type>
    <openid>${openId}</openid>
  </xml>`;

  request({
    url: unifiedOrderUrl,
    method: 'POST',
    body: formData
  }, (err, response, body) => {
    if (err) {
      res.status(500).send(err);
    } else {
      // 解析微信返回的XML数据
      const prepayId = /<prepay_id><!\[CDATA\[(.*)\]\]><\/prepay_id>/.exec(body)[1];
      const paySign = crypto.createHash('md5').update(`appId=${appId}&nonceStr=${nonceStr}&package=prepay_id=${prepayId}&signType=MD5&timeStamp=${timestamp}&key=${apiKey}`).digest('hex').toUpperCase();

      res.json({
        timestamp,
        nonceStr,
        package: `prepay_id=${prepayId}`,
        signType: 'MD5',
        paySign
      });
    }
  });
});

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});
代码说明:
  1. 生成支付订单参数:接收前端传来的订单ID,生成支付订单参数,包括nonceStrtimestampoutTradeNototalFeespbillCreateIpnotifyUrltradeTypeopenId
  2. 签名:对支付参数进行签名,生成sign
  3. 调用统一下单接口:向微信支付的统一下单接口发送请求,获取prepayId
  4. 返回支付参数:将prepayIdtimestampnonceStrpackagesignTypepaySign返回给前端。

4. 回调处理

支付成功后,微信会回调商户服务器的通知URL。商户服务器需要对通知进行处理,并更新订单状态。

Node.js回调处理示例:
const xmlParser = require('express-xml-bodyparser');

// 微信支付回调通知
app.post('/pay/notify', xmlParser({trim: false, explicitArray: false}), (req, res) => {
  const xml = req.body.xml;
  
  const params = {
    appid: xml.appid,
    mch_id: xml.mch_id,
    nonce_str: xml.nonce_str,
    result_code: xml.result_code,
    openid: xml.openid,
    total_fee: xml.total_fee,
    out_trade_no: xml.out_trade_no
  };
  
  const stringA = Object.keys(params).sort().map(key => `${key}=${params[key]}`).join('&');
  const stringSignTemp = `${stringA}&key=${apiKey}`;
  const sign = crypto.createHash('md5').update(stringSignTemp).digest('hex').toUpperCase();
  
  if (sign === xml.sign) {
    // 验签成功,处理业务逻辑
    if (xml.result_code === 'SUCCESS') {
      // 支付成功,更新订单状态
      // TODO: 更新数据库订单状态
      res.send('<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>');
    } else {
      res.send('<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[支付失败]]></return_msg></xml>');
   

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值