微信小程序调用微信支付

最近开发到小程序调用微信支付功能,看了下微信支付商户官网API文档再结合项目本身情况因是本人第一次接触走了很多弯路所以记录下开发的过程。

本次微信支付用的是老版本XML格式的,所有的支付功能直接复制就可以用了。无需大量改动把相应的商户appid 和商户支付秘钥修改

直接上代码。

框架是springboot maven

在pom.xml中添加依赖

        
        
            com.github.binarywang
            weixin-java-pay
            3.5.0
        

yml配置文件


# 小程序
#appid: wxdc441d07e8130fa9
  #  secret: 4bcd53d721cd6f133d2471aa0fd33ee1
miniporgram:
  appid: wx17f07c0f59e3d719e                  #需要换成自己的
  secret: 51806f5515ea9619604daff93eb02bb3b   #需要换成自己的
  login-url: https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code
  getUnlimited-url: https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=%s
  access-token-url: https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s

wx:
  pay:
    appId: wx17f07c0f59e3d719e #微信公众号或者小程序等的appid    #需要换成自己的
    secret: 51806f5515ea9619604daff93eb02bb3b                   #需要换成自己的
    mchId: 1150801291151 #微信支付商户号                          #需要换成自己的
    mchKey: fa2182b3cee6ac930f493af9b6a8abd7f #微信支付商户密钥
    #    subAppId: #服务商模式下的子商户公众账号ID
    #    subMchId: #服务商模式下的子商户号
    keyPath: classpath:/cert/apiclient_cert.p12 # p12证书的位置,可以指定绝对路径,也可以指定类路径(以classpath:开头)
    notifyUrl: https://1579lw7417.goho.co/wx/wxPay/payNotify #微信支付结果通知,微信支付回调地

微信公众号商户添加支付回调地址,支付成功后就会把信息推过来

微信小程序调用微信支付_第1张图片

 配置已经完了现在看小程序支付页面源码:

添加一个支付按钮

js

//支付
 confirm:function(){
  console.log('支付') 
  wx.login({
    success: res => {
      request.creatOrdel({ code:res.code,money:'1'}).then(r => { 
        console.log(r)
        wx.requestPayment({   
          timeStamp: r.data.timeStamp, 
          nonceStr: r.data.nonceStr,
          package: r.data.package,
          signType: r.data.signType,
          paySign: r.data.paySign,
          success (res) { },
          fail (res) { }
        })
      })
    }
  })
 } 

支付的时候把code传到后台,还有金额,生成预支付流水成功后前端 wx.requestPayment 就唤起了微信支付界面,在小程序开发这个工具中可能看到的是二维码不过不要紧,在手机端就是这个正常界面

 

微信小程序调用微信支付_第2张图片

后端代码:

controller

package cn.umidata.nucleic.api.controller;


import cn.hutool.json.JSONObject;
import cn.umidata.nucleic.api.utils.Httprequests;
import cn.umidata.nucleic.wechat.domain.WechatPaymentRecord;
import cn.umidata.nucleic.wechat.domain.WxOrderParams;
import cn.umidata.nucleic.wechat.service.WxPlayService;
import com.ijpay.core.kit.HttpKit;
import com.ijpay.core.kit.WxPayKit;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import cn.umidata.nucleic.common.core.domain.AjaxResult;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

/**
 * @BelongsProject: nucleic
 * @BelongsPackage: cn.umidata.nucleic.api.controller
 * @Author: zhanghui
 * @CreateTime: 2022-09-13  19:05
 * @Description: 订单支付
 * @Version: 1.0
 */
@Api(tags = "订单支付")
@RestController
@RequestMapping(value = "wxPay")
public class wxOrderController {
    @Value("${miniporgram.appid}")
    private String appid;
    @Value("${miniporgram.secret}")
    private String secret;
    @Value("${wx.pay.mchId}")
    private String mchid;

    @Value("${wx.pay.notifyUrl}")
    private String notifyUrl;
    @Value("${wx.pay.mchKey}")
    private String mchKey;

    @Autowired
    private WxPlayService wxPlayService;
    private final Logger log = LoggerFactory.getLogger(this.getClass());
    /**
     * 微信小程序支付
     *oderBathNum 订单批号,在申领果树中/wx/ReceiveFruiter/getBathNum接口中获取
     */
    @ApiOperation(value = "微信小程序支付",notes = "微信小程序支付")
    @PostMapping("/placeOrder")
    public AjaxResult miniAppPay(String openid,String money,String oderBathNum) {
      /*  String param = "appid=" + appid + "&secret=" + secret + "&js_code=" + code + "&grant_type=authorization_code";
        String sendGet = Httprequests.sendGet("https://api.weixin.qq.com/sns/jscode2session", param); //发起请求拿到key和openid
        JSONObject json = new JSONObject(sendGet);
        String openid=json.get("openid").toString(); //用户唯一标识*/
        WxOrderParams params = new WxOrderParams();
        params.setAttach("预约");
        params.setBody("预约单支付");
        params.setDetail("");
        params.setOpenid(openid);
        params.setOrderType("1");
        params.setOutTradeNo("FSA"+String.valueOf(System.currentTimeMillis()));
        params.setTotalFee(new BigDecimal(money));
        params.setAppid(appid);
        params.setMchid(mchid);
        params.setNotifyUrl(notifyUrl);
        params.setMchKey(mchKey);
        params.setOderBathNum(oderBathNum);
        Map stringStringMap = wxPlayService.placeOrder(params);
        return AjaxResult.success(stringStringMap);
    }
    /**
     * 支付回调异步通知
     */
    @ApiOperation(value = "支付回调异步通知",notes = "支付回调异步通知")
    @RequestMapping(value = "/payNotify")
    public String payNotify(HttpServletRequest request) {
        execPayNotify(request);
        Map xml = new HashMap(2);
        xml.put("return_code", "SUCCESS");
        xml.put("return_msg", "OK");
        return WxPayKit.toXml(xml);
    }

    /**
     * 支付回调异步通知
     */
    public synchronized  void execPayNotify(HttpServletRequest request) {
        String xmlMsg = HttpKit.readData(request);
        log.info("支付通知:"+xmlMsg);
        Map params = WxPayKit.xmlToMap(xmlMsg);
        WechatPaymentRecord record = wxPlayService.payNotify(params,mchKey);
        System.out.println("微信支付通知:"+record);

    }
}
WxPlayService:
package cn.umidata.nucleic.wechat.service;

import cn.umidata.nucleic.wechat.domain.RefundParams;
import cn.umidata.nucleic.wechat.domain.WechatPaymentRecord;
import cn.umidata.nucleic.wechat.domain.WxOrderParams;

import java.util.Map;

public interface WxPlayService {

    /**
     * 下单:
     * @param params
     * @return 微信调用微信支付的所需要的参数
     */
    public Map placeOrder(WxOrderParams params);


    /**
     * 微信支付通知
     * @param params 微信通知xml转map的参数
     */
    public WechatPaymentRecord payNotify(Map params,String mchKey );



    /**
     * 退款
     * @param refundParams
     */
    public String refund(RefundParams refundParams);


    /**
     * 退款通知
     * @param params 微信通知xml转map的参数
     */
    public void refundNotify(Map params);
}
WxPlayServiceImpl:
package cn.umidata.nucleic.wechat.service.impl;

import cn.umidata.nucleic.common.utils.DateUtils;
import cn.umidata.nucleic.common.utils.ip.IpUtils;
import cn.umidata.nucleic.wechat.domain.RefundParams;
import cn.umidata.nucleic.wechat.domain.WechatPaymentRecord;
import cn.umidata.nucleic.wechat.domain.WxOrderParams;
import cn.umidata.nucleic.wechat.enums.WxPlayStatus;
import cn.umidata.nucleic.wechat.service.IWechatPaymentRecordService;
import cn.umidata.nucleic.wechat.service.WxPlayService;
import com.ijpay.core.enums.SignType;
import com.ijpay.core.enums.TradeType;
import com.ijpay.core.kit.WxPayKit;
import com.ijpay.wxpay.WxPayApi;
import com.ijpay.wxpay.WxPayApiConfigKit;
import com.ijpay.wxpay.enums.WxDomain;
import com.ijpay.wxpay.model.UnifiedOrderModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ijpay.wxpay.WxPayApiConfig;

import java.util.Date;
import java.util.Map;

/**
 * @BelongsProject: nucleic
 * @BelongsPackage: cn.umidata.nucleic.wechat.service.impl
 * @Author: zhanghui
 * @CreateTime: 2022-09-15  15:59
 * @Description: TODO
 * @Version: 1.0
 */
@Service
public class WxPlayServiceImpl implements WxPlayService {
    private final Logger log = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private IWechatPaymentRecordService recordService;
    /*
     * @description:下单:
     * @author: zhanghui
     * @date: 2022/9/15 0015 下午 4:00
     * @param params
     * @return 微信调用微信支付的所需要的参数
     **/
    @Override
    public Map placeOrder(WxOrderParams params) {
        // 获取openId一般情况下用户登录的时候openId是和用户关联的 所以openId可以通过当前的userId去查询openId
        String ip = IpUtils.getHostIp();
        Map wxparams = UnifiedOrderModel.builder().appid(params.getAppid())
                .mch_id(params.getMchid()).nonce_str(WxPayKit.generateStr()).body(params.getBody()).attach(params.getAttach())
                .out_trade_no(params.getOutTradeNo())
                .mch_id(params.getMchid()).fee_type(params.getFeeType())
                // 注意 微信单位是分 我的数据库存的是元 需要转换
                .total_fee(String.valueOf(params.getTotalFee().intValue())).spbill_create_ip(ip)
                .notify_url(params.getNotifyUrl()).trade_type(TradeType.JSAPI.getTradeType()).openid(params.getOpenid()).build()
                .createSign(params.getMchKey(), SignType.MD5);
        String xmlResult = WxPayApi.pushOrder(false, WxDomain.CHINA, wxparams);
        Map result = WxPayKit.xmlToMap(xmlResult);
        String returnCode = result.get("return_code");
        String returnMsg = result.get("return_msg");
        if (!WxPayKit.codeIsOk(returnCode)) {
            throw new SecurityException(returnMsg);
        }
        String resultCode = result.get("result_code");
        if (!WxPayKit.codeIsOk(resultCode)) {
            throw new SecurityException(returnMsg);
        }
        //实例化
        installRecord(params);
        // 以下字段在 return_code 和 result_code 都为 SUCCESS 的时候有返回
        String prepayId = result.get("prepay_id");
        Map packageParams = WxPayKit.miniAppPrepayIdCreateSign(params.getAppid(), prepayId,
                params.getMchKey(), SignType.MD5);
        log.info("小程序支付统一下单返回参数:" + packageParams.toString());
        return packageParams;

    }

    /*
     * @description:微信支付记录流水
     * @author: zhanghui
     * @date: 2022/9/16 0016 下午 4:32
     **/
    private void  installRecord(WxOrderParams params){
        System.out.println("入库");
        WechatPaymentRecord record1 = recordService.selectByOutTradeNo(params.getOutTradeNo());
        if(null==record1){
            WechatPaymentRecord record = new WechatPaymentRecord();
            record.setId(WxPayKit.generateStr());
            record.setAttach(params.getAttach());
            record.setBody(params.getBody());
            record.setDetail(params.getDetail());
            record.setFeeType(params.getFeeType());
            record.setNickname(params.getNickname());
            record.setOpenid(params.getOpenid());
            record.setOrderType(params.getOrderType());
            record.setOutTradeNo(params.getOutTradeNo());
            record.setSpbillCreateIp(IpUtils.getHostIp());
            record.setStatus(WxPlayStatus.PLACED.getCode());
            record.setTradeType(TradeType.JSAPI.getTradeType());
            record.setCreateBy(params.getOpenid());
            record.setTotalFee(params.getTotalFee());
            record.setOderBathNum(params.getOderBathNum());
            record.setCreateTime(new Date());
            recordService.insertWechatPaymentRecord(record);
        }
    }

//    public WxPayApiConfig getApiConfig() {
//        WxPayApiConfig apiConfig;
//
//        try {
//            apiConfig = WxPayApiConfigKit.getApiConfig();
//        } catch (Exception e) {
//            apiConfig = WxPayApiConfig.builder().appId(systemParamsConfig.getSpappid()).mchId(systemParamsConfig.getMchid())
//                    .partnerKey(systemParamsConfig.getPartnerKey()).certPath(systemParamsConfig.getCertPath())
//                    .domain(systemParamsConfig.getDomain()).build();
//        }
//        notifyUrl = apiConfig.getDomain().concat("/wxPay/payNotify");
//        refundNotifyUrl = apiConfig.getDomain().concat("/wxPay/refundNotify");
//        return apiConfig;
//    }

    /*
     * @description:微信支付通知
     * @author: zhanghui
     * @date: 2022/9/15 0015 下午 4:00
     *
     * @param params 微信通知xml转map的参数
     **/
    @Override
    public WechatPaymentRecord payNotify(Map params,String mchKey) {
        // 支付回调的code
        String returnCode = params.get("return_code");
        WechatPaymentRecord record= null;
        if (WxPayKit.verifyNotify(params, mchKey, SignType.MD5)) {
            if (WxPayKit.codeIsOk(returnCode)) {
                String resultCode = params.get("result_code");
                if (WxPayKit.codeIsOk(resultCode)) {
                    String outTradeNo = params.get("out_trade_no");
                    String transactionId = params.get("transaction_id");

                    String bankType = params.get("bank_type");
                    // 支付时间
                    String payTime = params.get("time_end");
                    String isSubscribe = params.get("is_subscribe");
                    record = recordService.selectByOutTradeNo(outTradeNo);
                    if(record!=null && record.getStatus()==WxPlayStatus.PLACED.getCode()){//订单不为空并且订单状态为已下单
                        record.setTransactionId(transactionId);
                        record.setBankType(bankType);
                        record.setTimeEnd(DateUtils.dateTime("yyyyMMddHHmmss",payTime));
                        record.setIsSubscribe(isSubscribe);
                        record.setStatus(WxPlayStatus.PAID.getCode());
                        record.setUpdateBy(record.getCreateBy());
                        recordService.updateWechatPaymentRecord(record);
                    }
                }

            }
        }
        return record;
    }

    /*
     * @description:退款
     * @author: zhanghui
     * @date: 2022/9/15 0015 下午 4:01
     **/
    @Override
    public String refund(RefundParams refundParams) {
        return null;
    }

    /*
     * @description:退款通知
     * @author: zhanghui
     * @date: 2022/9/15 0015 下午 4:01
     **/
    @Override
    public void refundNotify(Map params) {

    }
}

数据库表:

CREATE TABLE `wechat_payment_record` (
  `id` varchar(32) NOT NULL,
  `transaction_id` varchar(50) DEFAULT NULL COMMENT '微信支付订单号',
  `body` varchar(100) DEFAULT NULL COMMENT '商品描述',
  `detail` varchar(100) DEFAULT NULL COMMENT '商品详情',
  `attach` varchar(50) DEFAULT NULL COMMENT '附加数据',
  `out_trade_no` varchar(20) DEFAULT NULL COMMENT '商户订单号',
  `fee_type` varchar(10) DEFAULT NULL COMMENT '标价币种',
  `total_fee` double DEFAULT NULL COMMENT '标价金额',
  `spbill_create_ip` varchar(32) DEFAULT NULL COMMENT '终端IP',
  `trade_type` varchar(10) DEFAULT NULL COMMENT '交易类型',
  `openid` varchar(50) DEFAULT NULL COMMENT '用户标识',
  `nickname` varchar(30) DEFAULT NULL COMMENT '微信昵称',
  `is_subscribe` varchar(32) DEFAULT NULL COMMENT '是否关注公众账号',
  `bank_type` varchar(32) DEFAULT NULL COMMENT '付款银行',
  `time_end` datetime DEFAULT NULL COMMENT '支付时间',
  `status` bigint(20) DEFAULT NULL COMMENT '1:已下单2:已关闭 3:已支付 4:退款中  5:已退款',
  `order_type` varchar(20) DEFAULT NULL COMMENT '订单类型',
  `refund_total_amount` varchar(20) DEFAULT NULL COMMENT '退款总金额',
  `create_by` varchar(50) DEFAULT NULL COMMENT '创建者',
  `create_time` datetime DEFAULT NULL,
  `update_by` varchar(50) DEFAULT NULL,
  `update_time` datetime DEFAULT NULL,
  `receive_fruiter_batch_num` bigint(32) DEFAULT NULL COMMENT '申领果树批次',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='微信支付记录流水对象';

就这些后面有时间了再更新

你可能感兴趣的:(微信小程序调用支付接口,微信小程序,微信,小程序)