关于使用微信公众号后端springboot项目对接微信支付v3 jsapi [后端代码支付篇]

前期

请参考上一篇 关于使用微信公众号后端springboot项目对接微信支付v3 jsapi [配置参数篇]

环境

最近在学习微信支付这方面的知识,经过重重试错,终于成功,现在分享出来让大家借鉴
ps:我开发的是微信公众号调用jsapi微信支付v3的业务逻辑
JSAPI支付产品介绍

开发环境

  1. jdk8
  2. springboot2
  3. 若依
  4. 微信支付版本
        <!--            微信支付的sdk-->
        <dependency>
            <groupId>com.github.wechatpay-apiv3</groupId>
            <artifactId>wechatpay-java</artifactId>
            <version>0.2.8</version>
        </dependency>
        <dependency>
            <groupId>com.github.wechatpay-apiv3</groupId>
            <artifactId>wechatpay-apache-httpclient</artifactId>
            <version>0.4.9</version>
        </dependency>

DTO 实体

这个是自己微信的openid ,一定要和调用者的微信id相同,不能会调支付失败

@Data
public class PayDTO {

    @NotBlank(message = "微信code不能为空")
    private String openId;
}

Service 层

这三个注入的类已经在上一篇配置好了

@Service
@Slf4j
public class WxPayService{

    @Autowired
    private WxPayConfig wxPayConfig;
    @Autowired
    private CloseableHttpClient httpClient;

    @Autowired
    private  PrivateKey privateKey;


    private PrivateKey  getPrivateKey(){
        try {

            PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(
                    new FileInputStream(wxPayConfig.getPrivateKeyPath()));
            return  merchantPrivateKey;
        } catch (FileNotFoundException e) {
            throw new RuntimeException("私钥文件不存在",e);
        }
    }


    @Override
    public Map<String, Objects> nativePay(String openId) throws IOException, GeneralSecurityException, HttpCodeException, NotFoundException {
        HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi");
		// jsapi 的接口


//        String reqdata = "{"
//                + "\"amount\": {"
//                + "\"total\": 1,"
//                + "\"currency\": \"CNY\""
//                + "},"
//                + "\"mchid\": \"1900006891\","
//                + "\"description\": \"Image形象店-深圳腾大-QQ公仔\","
//                + "\"notify_url\": \"https://www.weixin.qq.com/wxpay/pay.php\","
//                + "\"payer\": {"
//                + "\"openid\": \"o4GgauE1lgaPsLabrYvqhVg7O8yA\"" + "},"
//                + "\"out_trade_no\": \"1217752501201407033233388882\","
//                + "\"goods_tag\": \"WXG\","
//                + "\"appid\": \"wxdace645e0bc2c424\"" + "}";

        Map map = new HashMap();
        Map amountMap = new HashMap();

        amountMap.put("total",1);   //支付金额
        amountMap.put("currency","CNY"); //支付币种 默认人民币
        map.put("amount",amountMap);

        map.put("mchid",wxPayConfig.getMchId());
        map.put("description","测试1");  //支付描述
        map.put("notify_url",wxPayConfig.getNotifyDomain()); //支付成功回调api

        Map payerMap = new HashMap();
        payerMap.put("openid",openId); // 支付者的openid
        map.put("payer",payerMap);  
        map.put("out_trade_no", RandomUtil.randomNumbers(28));  //交易号 每个商户号不能有重复的交易号
        map.put("goods_tag","WXG");   
        map.put("appid",wxPayConfig.getAppid());  //微信公众号 appid


        Gson gson = new Gson();
        String jsonStr = gson.toJson(map);  
        StringEntity entity = new StringEntity(jsonStr,"utf-8"); //转化为requestbody
        entity.setContentType("application/json");  //使用json 
        httpPost.setEntity(entity);
        httpPost.setHeader("Accept", "application/json"); //协议切换

        //完成签名并执行请求


        CloseableHttpResponse response = httpClient.execute(httpPost); //执行发送
        try {
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == 200) {
            //这一部分 我建议是后台完成 ,因为根据文档,前端支付的时候需要
            //  公众号appid  ,时间戳,随机字符串和   后端发送请求微信返回的prepay_id和签名
            // 所以可以在这次调用时候,使用map 一起返回前端 ,让前端自己组装
                String responseStr = EntityUtils.toString(response.getEntity());
                System.out.println("success,return body = " + responseStr);  
                JSONObject jsonObject = JSONUtil.parseObj(responseStr);
                String prepay_id = jsonObject.getStr("prepay_id");
                // 获取时间戳
                long timeL = System.currentTimeMillis() / 1000;
                // 获取随机字符串
                String nonceStr = TokenTool.getToken();
                // 新建一个支付参数map
                Map req = new HashMap();
                req.put("appId", wxPayConfig.getAppid());
                req.put("timeStamp", timeL);
                req.put("nonceStr", nonceStr);
                req.put("package", "prepay_id=" + prepay_id);
                // 设置加密方式
                req.put("signType", "RSA");
                // 获取加密后的密文
                String paySign = RSAUtil.getToken(wxPayConfig.getAppid(), timeL, nonceStr,"prepay_id=" + prepay_id, privateKey);
                req.put("paySign", paySign);
                return req;
            } else if (statusCode == 204) {
                System.out.println("success");
                return null;
            } else {
                System.out.println("failed,resp code = " + statusCode+ ",return body = " + EntityUtils.toString(response.getEntity()));
                throw new IOException("request failed");
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            response.close();

        }

    }
 }

Controller层 编写

可以先做一个demo微信支付Controller,测试好再进行具体逻辑修改

ps :该支付接口一定不要有任何认证和拦截 ,不能微信服务器调用不起来

@R
estController
@RequestMapping("/test/wxpay")
@Api(tags = "[测试]微信支付功能相关接口")
@Slf4j
@CrossOrigin
public class TestControllerByWxPay {


    @Autowired
    private WxPayConfig wxPayConfig;


    @Autowired
    private WxPayService wxPayService;

    @GetMapping("/d1")
    @Anonymous
    @ApiOperation(value = "第一个测试[匿名]")
    public AjaxResult d1(){
        return  AjaxResult.success(wxPayConfig.getAppid());
    }





    @PostMapping("/navtivepay")
    @ApiOperation(value = "微信jsapi支付接口[匿名]")
    @Anonymous
    public AjaxResult nativePay(@Validated @RequestBody PayDTO payDTO){
        Map<String, Objects> map = null;
        log.info(payDTO.getOpenId());
        try {
            map = wxPayService.nativePay(payDTO.getOpenId());
        } catch (IOException e) {
            throw new RuntimeException("还是报错了",e);
        } catch (GeneralSecurityException e) {
            throw new RuntimeException(e);
        } catch (NotFoundException e) {
            throw new RuntimeException(e);
        } catch (HttpCodeException e) {
            throw new RuntimeException(e);
        }
        return  AjaxResult.success(map);

    }

}

结语

在下一篇 我会对前端demo代码测试微信支付,进行讲解

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

已久依依

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值