网站应用实现微信扫码支付功能

前言:

上篇文章讲了怎么利用微信开放平台实现微信扫描登录功能(网站应用微信扫码登录

此篇将为大家讲解怎么利用微信开放平台在网站应用PC端实现微信扫码支付功能

一、准备工作

首先还是登录 微信开放平台

然后在应用详情里边会看到有一个“微信支付”的功能,此时我们点击“申请开通”;跟随着引导会让我们登录 微信支付平台 进行appId绑定

但是绑定网站应用appId的时候会提示下图信息

下边描述也没有说支持网站应用绑定,这个时候不要慌,我们根据指引去联系腾讯客服,给客服说明我们想要在微信支付平台绑定网站应用。接着客服会让我们填写一下信息

(Tips:腾讯客服很难联系到人工客服,一旦联系成功尽量一次性把信息提供完整,不然再次联系又要等很久了)

把腾讯客服需要的信息提供之后我们能做的就是漫长的等待了,说的是审核预计1-3天,大概等了一天半,然后登录微信开放平台和微信支付平台就可以看到已经绑定成功了,由于是微信后台操作,我们不需要手动再去绑定,现在就可以进行代码开发工作了

二、代码开发

代码部分跟之前的小程序微信支付代码几乎一样,可以看一下之前的文章(微信小程序支付流程及代码实现java+uniapp

唯一不同的是支付类型不一样,之前的小程序支付使用的是JSAPI方式,在网站PC端也是可以使用这种方式,但是前端需要去引入对应的微信SDK再开发,为了减少前端工作量,这里我们就更换另外一种方式,使用NATIVE方式,使用这种方式,创建统一支付订单之后,会返回一个code_url字段,把这个字段的字符串信息生成二维码,使用微信扫一扫即可完成支付,非常方便

代码修改部分(参考之前文章的代码)

    /**
     * 创建统一支付订单
     * @param payParameterVO 商品信息
     * @return 返回结果
     */
    @Override
    @Transactional
    public HashMap<String, String> insertPayRecord(PayParameterVO payParameterVO) {
            String title = payParameterVO.getGoodsTitle();
            //金额 * 100 以分为单位
            BigDecimal fee = BigDecimal.valueOf(1);
            BigDecimal RMB = new BigDecimal(payParameterVO.getPrice());
            BigDecimal totalFee = fee.multiply(RMB);
 
            try {
                WeChatPay weChatPay = new WeChatPay();
                weChatPay.setAppid(payProperties.getAppId());
                weChatPay.setMch_id(payProperties.getMchId());
                weChatPay.setNonce_str(getRandomStringByLength(32));
                weChatPay.setBody(title);
                weChatPay.setOut_trade_no(getRandomStringByLength(32));
                weChatPay.setTotal_fee(df.format(Double.parseDouble(String.valueOf(totalFee))));
                weChatPay.setSpbill_create_ip(IpUtils.getHostIp());
                weChatPay.setNotify_url(payProperties.getNotifyUrl());
                weChatPay.setTrade_type("NATIVE");//JSAPI
                //这里直接使用当前用户的openid
                weChatPay.setOpenid(payParameterVO.getWxOpenId());
                weChatPay.setSign_type("MD5");
                //生成签名
                String sign = SignUtils.getSign(weChatPay);
                weChatPay.setSign(sign);

                log.info("订单号:" + weChatPay.getOut_trade_no());
                //向微信发送下单请求
                String result = HttpRequest.sendPost(WeChatPayUrlConstants.Uifiedorder, weChatPay);
 
                //将返回结果从xml格式转换为map格式
                Map<String, String> wxResultMap = WXPayUtil.xmlToMap(result);
                System.out.println(wxResultMap);
                if (StringUtils.isNotEmpty(wxResultMap.get("return_code")) && wxResultMap.get("return_code").equals("SUCCESS")){
                    if (wxResultMap.get("result_code").equals("FAIL")){
                        log.error("微信统一下单失败![{}]", wxResultMap.get("err_code_des"));
                        return null;
                    }
                }
                OrderReturnInfo returnInfo = MapToObject.convertMapToObject(wxResultMap, OrderReturnInfo.class);

                // 二次签名
                if ("SUCCESS".equals(returnInfo.getReturn_code()) && returnInfo.getReturn_code().equals(returnInfo.getResult_code())) {
                    SignInfo signInfo = new SignInfo();
                    signInfo.setAppId(payProperties.getAppId());
                    long time = System.currentTimeMillis() / 1000;
                    signInfo.setTimeStamp(String.valueOf(time));
                    signInfo.setNonceStr(WXPayUtil.generateNonceStr());
                    signInfo.setRepay_id("prepay_id=" + returnInfo.getPrepay_id());
                    signInfo.setSignType("MD5");
                    //生成签名
                    String sign1 = SignUtils.getSign(signInfo);
                    HashMap<String, String> payInfo = new HashMap<>();
                    payInfo.put("placeOrderJsonMsg", JSON.toJSONString(weChatPay));
                    payInfo.put("orderNum", weChatPay.getOut_trade_no());

                    PaySignInfo paySignInfo = new PaySignInfo();
                    paySignInfo.setAppId(signInfo.getAppId());
                    paySignInfo.setTimeStamp(signInfo.getTimeStamp());
                    paySignInfo.setNonceStr(signInfo.getNonceStr());
                    paySignInfo.setRepay_id(signInfo.getRepay_id());
                    paySignInfo.setSignType(signInfo.getSignType());
                    paySignInfo.setPaySign(sign1);
                    payInfo.put("paySignInfo",JSON.toJSONString(paySignInfo));
                    payInfo.put("payQrcodeUrl", wxResultMap.get("code_url"));
 
                    // 业务逻辑结束 回传给小程序端唤起支付
                    return payInfo;
                }
                return null;
            } catch (Exception e) {
                log.error(e.getMessage());
            }
        return null;
    }

就修改两处,一个是trade_type字段改为NATIVE

另外就是返回的时候把code_url也传给前端

另外在实体类中需要加上code_url字段,不然 MapToObject.convertMapToObject 方法会因为字段不匹配而报错

/**
 * 预下单成功之后返回结果对象
 * @author kun
 * {@code @date} 2024/1/30
 */
@Data
public class OrderReturnInfo {

    /** 返回状态码 */
    private String return_code;

    /** 返回信息 */
    private String return_msg;

    /** 业务结果 */
    private String result_code;

    /** 小程序appID */
    private String appid;

    /** 商户号 */
    private String mch_id;

    /** 随机字符串 */
    private String nonce_str;

    /** 签名 */
    private String sign;

    /**  预支付交易会话标识。用于后续接口调用中使用,该值有效期为2小时 */
    private String prepay_id;

    /** 交易类型 */
    private String trade_type;

    /** 支付二维码 */
    private String code_url;

 
}

然后前端随便用个二维码生成工具把这个链接生成为二维码就行了,或者后端生成二维码把图片给前端也是可以的。然后扫码付钱即可

支付成功演示:

总结:

网站应用接入微信支付流程也还是比较简单,主要难点是在权限申请那里,很多小伙伴以为绑定不了appId就无法接入使用了,但很多时候只是官方自己没有完善到位,遇到这种情况可以联系一下人工客服再次确认。有的小伙伴可能会说在网站应用使用公众号的appId也可以做微信支付;但这是有一个前提的,就是登录也同样需要使用公众号授权登录,我们上篇文章讲了使用微信开放平台的登录功能,所以要支付的话也同样需要使用微信开放平台的支付功能。因为在创建统一支付订单的时候,是需要校验用户的OpenId、应用的appId、商户号这几个信息的,如果拿着开放平台的用户授权信息又去使用公众号的微信支付,那必然是会提示信息不匹配的。

以下是一个简单的Python代码示例,用于实现微信扫码支付: ```python import requests # 微信扫码支付接口地址 wechat_api_url = 'https://api.mch.weixin.qq.com/pay/unifiedorder' # 商户号 mch_id = 'your_mch_id' # 应用ID appid = 'your_appid' # 商户密钥 mch_key = 'your_mch_key' # 生成签名函数 def generate_sign(params): # 按照参数名的ASCII码从小到大排序 sorted_params = sorted(params.items(), key=lambda x:x[0], reverse=False) # 拼接参数名与参数值 sign_str = '&'.join([f'{key}={value}' for key, value in sorted_params]) # 拼接商户密钥 sign_str += f'&key={mch_key}' # 计算签名(使用MD5加密) import hashlib m = hashlib.md5() m.update(sign_str.encode('utf-8')) return m.hexdigest().upper() # 构建请求参数 params = { 'appid': appid, 'mch_id': mch_id, 'nonce_str': 'your_nonce_str', # 随机字符串 'body': 'your_order_description', # 订单描述 'out_trade_no': 'your_out_trade_no', # 商户订单号 'total_fee': 'your_total_fee', # 订单总金额(单位:分) 'spbill_create_ip': 'your_spbill_create_ip', # 终端IP 'notify_url': 'your_notify_url', # 接收微信支付异步通知回调地址 'trade_type': 'NATIVE', # 交易类型为扫码支付 } # 生成签名 params['sign'] = generate_sign(params) # 发起请求 response = requests.post(wechat_api_url, data=params) # 解析响应结果 import xml.etree.ElementTree as ET root = ET.fromstring(response.content) return_code = root.find('return_code').text result_code = root.find('result_code').text if return_code == 'SUCCESS' and result_code == 'SUCCESS': # 获取二维码链接 code_url = root.find('code_url').text print(f'请使用微信扫描以下二维码进行支付:{code_url}') else: # 支付失败处理逻辑 err_code = root.find('err_code').text err_msg = root.find('err_code_des').text print(f'支付失败,错误代码:{err_code},错误信息:{err_msg}') ``` 请注意,上述代码仅为示例,实际应用中需要根据自己的业务需求进行适当的修改和完善。 另外,该示例代码中使用了第三方库`requests`和`xml.etree.ElementTree`,请确保这两个库已经安装在你的Python环境中。你可以使用`pip install requests`和`pip install xml.etree.ElementTree`命令进行安装。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值