SpringBoot对接微信小程序支付功能开发(二,支付回调功能)

接着上一篇: SpringBoot对接微信小程序支付功能开发(一,下单功能)

在上一篇下单功能中我们有传支付结果回调地址。
在这里插入图片描述
下面是回调接口实现

package com.office.miniapp.controller;


import cn.hutool.core.date.DateTime;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.office.miniapp.constants.ProjectConstant;
import com.office.miniapp.entity.TdOrders;
import com.office.miniapp.entity.TdShops;
import com.office.miniapp.entity.TdWxPay;
import com.office.miniapp.service.TdOrdersService;
import com.office.miniapp.service.TdShopsService;
import com.office.miniapp.service.TdWxPayService;
import com.office.miniapp.utils.HttpClientUtil;
import com.office.miniapp.utils.WxPayUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

/**
 * <p>
 * 支付表 前端控制器
 * </p>
 *
 * @author XQD
 * @since 2022-08-13
 */
@Slf4j
@RestController
@RequestMapping("/wxPay")
public class TdWxPayController extends BaseController {

    @PostMapping("/callback")
    public Object callback(HttpServletRequest request) {
        log.info("【支付回调】");
        System.out.println("Wechatpay-Timestamp:" + request.getHeader("Wechatpay-Timestamp"));
        System.out.println("Wechatpay-Nonce:" + request.getHeader("Wechatpay-Nonce"));
        System.out.println("Wechatpay-Signature:" + request.getHeader("Wechatpay-Signature"));
        System.out.println("Wechatpay-Serial:" + request.getHeader("Wechatpay-Serial"));
        Map result = new HashMap();
        result.put("code", "FAIL");
        try {
            StringBuilder signStr = new StringBuilder();
            // 应答时间戳\n
            signStr.append(request.getHeaders("Wechatpay-Timestamp")).append("\n");
            // 应答随机串\n
            signStr.append(request.getHeaders("Wechatpay-Nonce")).append("\n");
            // 应答报文主体\n
            BufferedReader br = request.getReader();
            String str = null;
            StringBuilder builder = new StringBuilder();
            while ((str = br.readLine()) != null) {
                builder.append(str);
            }
            System.out.println("支付应答报文主体:" + builder);
            signStr.append(builder.toString()).append("\n");
            // 第一步:验证签名
            if (WxPayUtil.signVerify(request.getHeader("Wechatpay-Serial"), signStr.toString(), request.getHeader("Wechatpay-Signature"))) {
                result.put("message", "sign error");
                return result;
            }
            // 第二步:解密密文
            String decryptOrder = WxPayUtil.decryptOrder(builder.toString());
            System.out.println("解密后支付信息:" + decryptOrder);
            JSONObject jsonObject = JSON.parseObject(decryptOrder);
            //String transactionId = jsonObject.getString("transaction_id");
            //String appid= jsonObject.getString("appid");
            //String successTime = new DateTime(jsonObject.getString("success_time")).toString();
            //JSONObject jsonPayer = JSON.parseObject(jsonObject.getString("payer"));
            //String openid= jsonPayer.getString("openid");
            //解密后的支付信息存入数据库...
            //第三步:验证订单,解密后的订单信息和自己数据库中的订单信息进行比对
            //金额对比  orders.getAmount()为数据库中的订单金额
            if (orders.getAmount().equals(jsonAmout.getInteger("total"))) {
                if ("SUCCESS".equals(jsonObject.getString("trade_state"))) {
                     // 支付成功...
                     //根据支付信息查询已存的订单信息,进行状态改变等操作,根据业务操作
                    }
               }
            result.put("code", "SUCCESS");
            result.put("message", "成功");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }
}

根据官网给的参数进行业务处理

在这里插入图片描述

这就完成了,微信支付回调你的地址,并且把支付的信息传进来,剩下就要根据自己业务进行操作。
注意:
1,验证签名和解密的操作在上一篇下单功能的文章中的WxPayUtil 中
2,这个地址必须为线上地址,https前缀的域名+/wxPay/callback。

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要在 Java对接微信小程序支付,你需要完成以下步骤: 1. 获取微信支付的 API 密钥和商户号,以及小程序 appID 和 appSecret。 2. 在小程序开发者工具中创建支付统一下单接口,并记录好接口地址。 3. 在 Java 中编代码,向微信支付下单接口发送请求,并获取返回的 prepay_id。 4. 将 prepay_id 和其他参数按照微信支付要求的格式进行签名,并返回给前端。 5. 前端通过微信小程序支付 API 调起支付界面,用户完成支付后,微信服务器会向商户服务器发送支付结果通知。 6. 商户服务器接收到支付结果通知后,需要进行签名验证和订单处理。 以下是一份示例代码,可以帮助你完成微信小程序支付对接: ```java import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.HashMap; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; public class WechatPayment { private String appid; // 小程序 ID private String mch_id; // 商户号 private String key; // API 密钥 public WechatPayment(String appid, String mch_id, String key) { this.appid = appid; this.mch_id = mch_id; this.key = key; } public Map<String, String> unifiedorder(String body, String out_trade_no, int total_fee, String spbill_create_ip, String notify_url) throws Exception { SortedMap<String, String> params = new TreeMap<String, String>(); params.put("appid", appid); params.put("mch_id", mch_id); params.put("nonce_str", getRandomString(32)); params.put("body", body); params.put("out_trade_no", out_trade_no); params.put("total_fee", String.valueOf(total_fee)); params.put("spbill_create_ip", spbill_create_ip); params.put("notify_url", notify_url); params.put("trade_type", "JSAPI"); params.put("openid", "用户的 openid"); String sign = createSign(params); params.put("sign", sign); String xml = mapToXml(params); String responseXml = HttpUtils.post("https://api.mch.weixin.qq.com/pay/unifiedorder", xml); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document document = builder.parse(new ByteArrayInputStream(responseXml.getBytes())); Element rootElement = document.getDocumentElement(); String return_code = getElementValue(rootElement, "return_code"); String result_code = getElementValue(rootElement, "result_code"); String prepay_id = getElementValue(rootElement, "prepay_id"); if ("SUCCESS".equals(return_code) && "SUCCESS".equals(result_code) && prepay_id != null) { Map<String, String> result = new HashMap<String, String>(); result.put("prepay_id", prepay_id); String nonce_str = getRandomString(32); result.put("nonceStr", nonce_str); result.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000)); result.put("signType", "MD5"); result.put("package", "prepay_id=" + prepay_id); sign = createSign(result); result.put("paySign", sign); return result; } else { throw new Exception(getElementValue(rootElement, "return_msg")); } } private String createSign(Map<String, String> params) throws NoSuchAlgorithmException { StringBuilder sb = new StringBuilder(); for (Map.Entry<String, String> entry : params.entrySet()) { if (entry.getValue() != null && entry.getValue().length() > 0 && !"sign".equals(entry.getKey()) && !"key".equals(entry.getKey())) { sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&"); } } sb.append("key=").append(key); MessageDigest md = MessageDigest.getInstance("MD5"); md.update(sb.toString().getBytes()); byte[] digest = md.digest(); StringBuilder signBuilder = new StringBuilder(); for (byte b : digest) { String hex = Integer.toHexString(b & 0xff); if (hex.length() == 1) { signBuilder.append("0"); } signBuilder.append(hex); } return signBuilder.toString().toUpperCase(); } private String mapToXml(Map<String, String> params) { StringBuilder sb = new StringBuilder(); sb.append("<xml>"); for (Map.Entry<String, String> entry : params.entrySet()) { sb.append("<").append(entry.getKey()).append(">"); sb.append(entry.getValue()); sb.append("</").append(entry.getKey()).append(">"); } sb.append("</xml>"); return sb.toString(); } private String getElementValue(Element element, String tagName) { Element childElement = (Element) element.getElementsByTagName(tagName).item(0); if (childElement != null) { return childElement.getTextContent(); } return null; } private String getRandomString(int length) { String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; StringBuilder sb = new StringBuilder(); for (int i = 0; i < length; i++) { sb.append(str.charAt((int) (Math.random() * str.length()))); } return sb.toString(); } } ``` 其中,HttpUtils.post() 方法用于发送 HTTP POST 请求,你需要自己实现。在 unifiedorder() 方法中,我们按照微信支付要求的格式构造请求参数,并对参数进行签名。然后向微信支付下单接口发送请求,获取 prepay_id。最后,我们将 prepay_id 和其他参数按照微信支付要求的格式进行签名,并返回给前端。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值