• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

微信小程序调用微信支付

武飞扬头像
辉_哥
帮助1

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

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

直接上代码。

框架是springboot maven

在pom.xml中添加依赖

  1.  
    <!--微信支付-->
  2.  
    <dependency>
  3.  
    <groupId>com.github.binarywang</groupId>
  4.  
    <artifactId>weixin-java-pay</artifactId>
  5.  
    <version>3.5.0</version>
  6.  
    </dependency>

yml配置文件

  1.  
     
  2.  
    # 小程序
  3.  
    #appid: wxdc441d07e8130fa9
  4.  
    # secret: 4bcd53d721cd6f133d2471aa0fd33ee1
  5.  
    miniporgram:
  6.  
    appid: wx17f07c0f59e3d719e #需要换成自己的
  7.  
    secret: 51806f5515ea9619604daff93eb02bb3b #需要换成自己的
  8.  
    login-url: https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code
  9.  
    getUnlimited-url: https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=%s
  10.  
    access-token-url: https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s
  11.  
     
  12.  
    wx:
  13.  
    pay:
  14.  
    appId: wx17f07c0f59e3d719e #微信公众号或者小程序等的appid #需要换成自己的
  15.  
    secret: 51806f5515ea9619604daff93eb02bb3b #需要换成自己的
  16.  
    mchId: 1150801291151 #微信支付商户号 #需要换成自己的
  17.  
    mchKey: fa2182b3cee6ac930f493af9b6a8abd7f #微信支付商户密钥
  18.  
    # subAppId: #服务商模式下的子商户公众账号ID
  19.  
    # subMchId: #服务商模式下的子商户号
  20.  
    keyPath: classpath:/cert/apiclient_cert.p12 # p12证书的位置,可以指定绝对路径,也可以指定类路径(以classpath:开头)
  21.  
    notifyUrl: https://1579lw7417.goho.co/wx/wxPay/payNotify #微信支付结果通知,微信支付回调地
学新通

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

学新通

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

添加一个支付按钮

<button class="weui-btn btn-radius" bindtap="confirm">支付</button>

js

  1.  
    //支付
  2.  
    confirm:function(){
  3.  
    console.log('支付')
  4.  
    wx.login({
  5.  
    success: res => {
  6.  
    request.creatOrdel({ code:res.code,money:'1'}).then(r => {
  7.  
    console.log(r)
  8.  
    wx.requestPayment({
  9.  
    timeStamp: r.data.timeStamp,
  10.  
    nonceStr: r.data.nonceStr,
  11.  
    package: r.data.package,
  12.  
    signType: r.data.signType,
  13.  
    paySign: r.data.paySign,
  14.  
    success (res) { },
  15.  
    fail (res) { }
  16.  
    })
  17.  
    })
  18.  
    }
  19.  
    })
  20.  
    }
学新通

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

学新通

后端代码:

controller

  1.  
    package cn.umidata.nucleic.api.controller;
  2.  
     
  3.  
     
  4.  
    import cn.hutool.json.JSONObject;
  5.  
    import cn.umidata.nucleic.api.utils.Httprequests;
  6.  
    import cn.umidata.nucleic.wechat.domain.WechatPaymentRecord;
  7.  
    import cn.umidata.nucleic.wechat.domain.WxOrderParams;
  8.  
    import cn.umidata.nucleic.wechat.service.WxPlayService;
  9.  
    import com.ijpay.core.kit.HttpKit;
  10.  
    import com.ijpay.core.kit.WxPayKit;
  11.  
    import io.swagger.annotations.Api;
  12.  
    import io.swagger.annotations.ApiOperation;
  13.  
    import org.slf4j.Logger;
  14.  
    import org.slf4j.LoggerFactory;
  15.  
    import org.springframework.beans.factory.annotation.Autowired;
  16.  
    import org.springframework.beans.factory.annotation.Value;
  17.  
    import org.springframework.web.bind.annotation.PostMapping;
  18.  
    import org.springframework.web.bind.annotation.RequestMapping;
  19.  
    import org.springframework.web.bind.annotation.RestController;
  20.  
    import cn.umidata.nucleic.common.core.domain.AjaxResult;
  21.  
     
  22.  
    import javax.servlet.http.HttpServletRequest;
  23.  
    import java.math.BigDecimal;
  24.  
    import java.util.HashMap;
  25.  
    import java.util.Map;
  26.  
     
  27.  
    /**
  28.  
    * @BelongsProject: nucleic
  29.  
    * @BelongsPackage: cn.umidata.nucleic.api.controller
  30.  
    * @Author: zhanghui
  31.  
    * @CreateTime: 2022-09-13 19:05
  32.  
    * @Description: 订单支付
  33.  
    * @Version: 1.0
  34.  
    */
  35.  
    @Api(tags = "订单支付")
  36.  
    @RestController
  37.  
    @RequestMapping(value = "wxPay")
  38.  
    public class wxOrderController {
  39.  
    @Value("${miniporgram.appid}")
  40.  
    private String appid;
  41.  
    @Value("${miniporgram.secret}")
  42.  
    private String secret;
  43.  
    @Value("${wx.pay.mchId}")
  44.  
    private String mchid;
  45.  
     
  46.  
    @Value("${wx.pay.notifyUrl}")
  47.  
    private String notifyUrl;
  48.  
    @Value("${wx.pay.mchKey}")
  49.  
    private String mchKey;
  50.  
     
  51.  
    @Autowired
  52.  
    private WxPlayService wxPlayService;
  53.  
    private final Logger log = LoggerFactory.getLogger(this.getClass());
  54.  
    /**
  55.  
    * 微信小程序支付
  56.  
    *oderBathNum 订单批号,在申领果树中/wx/ReceiveFruiter/getBathNum接口中获取
  57.  
    */
  58.  
    @ApiOperation(value = "微信小程序支付",notes = "微信小程序支付")
  59.  
    @PostMapping("/placeOrder")
  60.  
    public AjaxResult miniAppPay(String openid,String money,String oderBathNum) {
  61.  
    /* String param = "appid=" appid "&secret=" secret "&js_code=" code "&grant_type=authorization_code";
  62.  
    String sendGet = Httprequests.sendGet("https://api.weixin.qq.com/sns/jscode2session", param); //发起请求拿到key和openid
  63.  
    JSONObject json = new JSONObject(sendGet);
  64.  
    String openid=json.get("openid").toString(); //用户唯一标识*/
  65.  
    WxOrderParams params = new WxOrderParams();
  66.  
    params.setAttach("预约");
  67.  
    params.setBody("预约单支付");
  68.  
    params.setDetail("");
  69.  
    params.setOpenid(openid);
  70.  
    params.setOrderType("1");
  71.  
    params.setOutTradeNo("FSA" String.valueOf(System.currentTimeMillis()));
  72.  
    params.setTotalFee(new BigDecimal(money));
  73.  
    params.setAppid(appid);
  74.  
    params.setMchid(mchid);
  75.  
    params.setNotifyUrl(notifyUrl);
  76.  
    params.setMchKey(mchKey);
  77.  
    params.setOderBathNum(oderBathNum);
  78.  
    Map<String, String> stringStringMap = wxPlayService.placeOrder(params);
  79.  
    return AjaxResult.success(stringStringMap);
  80.  
    }
  81.  
    /**
  82.  
    * 支付回调异步通知
  83.  
    */
  84.  
    @ApiOperation(value = "支付回调异步通知",notes = "支付回调异步通知")
  85.  
    @RequestMapping(value = "/payNotify")
  86.  
    public String payNotify(HttpServletRequest request) {
  87.  
    execPayNotify(request);
  88.  
    Map<String, String> xml = new HashMap<String, String>(2);
  89.  
    xml.put("return_code", "SUCCESS");
  90.  
    xml.put("return_msg", "OK");
  91.  
    return WxPayKit.toXml(xml);
  92.  
    }
  93.  
     
  94.  
    /**
  95.  
    * 支付回调异步通知
  96.  
    */
  97.  
    public synchronized void execPayNotify(HttpServletRequest request) {
  98.  
    String xmlMsg = HttpKit.readData(request);
  99.  
    log.info("支付通知:" xmlMsg);
  100.  
    Map<String, String> params = WxPayKit.xmlToMap(xmlMsg);
  101.  
    WechatPaymentRecord record = wxPlayService.payNotify(params,mchKey);
  102.  
    System.out.println("微信支付通知:" record);
  103.  
     
  104.  
    }
  105.  
    }
学新通
WxPlayService:
  1.  
    package cn.umidata.nucleic.wechat.service;
  2.  
     
  3.  
    import cn.umidata.nucleic.wechat.domain.RefundParams;
  4.  
    import cn.umidata.nucleic.wechat.domain.WechatPaymentRecord;
  5.  
    import cn.umidata.nucleic.wechat.domain.WxOrderParams;
  6.  
     
  7.  
    import java.util.Map;
  8.  
     
  9.  
    public interface WxPlayService {
  10.  
     
  11.  
    /**
  12.  
    * 下单:
  13.  
    * @param params
  14.  
    * @return 微信调用微信支付的所需要的参数
  15.  
    */
  16.  
    public Map<String, String> placeOrder(WxOrderParams params);
  17.  
     
  18.  
     
  19.  
    /**
  20.  
    * 微信支付通知
  21.  
    * @param params 微信通知xml转map的参数
  22.  
    */
  23.  
    public WechatPaymentRecord payNotify(Map<String, String> params,String mchKey );
  24.  
     
  25.  
     
  26.  
     
  27.  
    /**
  28.  
    * 退款
  29.  
    * @param refundParams
  30.  
    */
  31.  
    public String refund(RefundParams refundParams);
  32.  
     
  33.  
     
  34.  
    /**
  35.  
    * 退款通知
  36.  
    * @param params 微信通知xml转map的参数
  37.  
    */
  38.  
    public void refundNotify(Map<String, String> params);
  39.  
    }
学新通
WxPlayServiceImpl:
  1.  
    package cn.umidata.nucleic.wechat.service.impl;
  2.  
     
  3.  
    import cn.umidata.nucleic.common.utils.DateUtils;
  4.  
    import cn.umidata.nucleic.common.utils.ip.IpUtils;
  5.  
    import cn.umidata.nucleic.wechat.domain.RefundParams;
  6.  
    import cn.umidata.nucleic.wechat.domain.WechatPaymentRecord;
  7.  
    import cn.umidata.nucleic.wechat.domain.WxOrderParams;
  8.  
    import cn.umidata.nucleic.wechat.enums.WxPlayStatus;
  9.  
    import cn.umidata.nucleic.wechat.service.IWechatPaymentRecordService;
  10.  
    import cn.umidata.nucleic.wechat.service.WxPlayService;
  11.  
    import com.ijpay.core.enums.SignType;
  12.  
    import com.ijpay.core.enums.TradeType;
  13.  
    import com.ijpay.core.kit.WxPayKit;
  14.  
    import com.ijpay.wxpay.WxPayApi;
  15.  
    import com.ijpay.wxpay.WxPayApiConfigKit;
  16.  
    import com.ijpay.wxpay.enums.WxDomain;
  17.  
    import com.ijpay.wxpay.model.UnifiedOrderModel;
  18.  
    import org.slf4j.Logger;
  19.  
    import org.slf4j.LoggerFactory;
  20.  
    import org.springframework.beans.factory.annotation.Autowired;
  21.  
    import org.springframework.stereotype.Service;
  22.  
    import com.ijpay.wxpay.WxPayApiConfig;
  23.  
     
  24.  
    import java.util.Date;
  25.  
    import java.util.Map;
  26.  
     
  27.  
    /**
  28.  
    * @BelongsProject: nucleic
  29.  
    * @BelongsPackage: cn.umidata.nucleic.wechat.service.impl
  30.  
    * @Author: zhanghui
  31.  
    * @CreateTime: 2022-09-15 15:59
  32.  
    * @Description: TODO
  33.  
    * @Version: 1.0
  34.  
    */
  35.  
    @Service
  36.  
    public class WxPlayServiceImpl implements WxPlayService {
  37.  
    private final Logger log = LoggerFactory.getLogger(this.getClass());
  38.  
    @Autowired
  39.  
    private IWechatPaymentRecordService recordService;
  40.  
    /*
  41.  
    * @description:下单:
  42.  
    * @author: zhanghui
  43.  
    * @date: 2022/9/15 0015 下午 4:00
  44.  
    * @param params
  45.  
    * @return 微信调用微信支付的所需要的参数
  46.  
    **/
  47.  
    @Override
  48.  
    public Map<String, String> placeOrder(WxOrderParams params) {
  49.  
    // 获取openId一般情况下用户登录的时候openId是和用户关联的 所以openId可以通过当前的userId去查询openId
  50.  
    String ip = IpUtils.getHostIp();
  51.  
    Map<String, String> wxparams = UnifiedOrderModel.builder().appid(params.getAppid())
  52.  
    .mch_id(params.getMchid()).nonce_str(WxPayKit.generateStr()).body(params.getBody()).attach(params.getAttach())
  53.  
    .out_trade_no(params.getOutTradeNo())
  54.  
    .mch_id(params.getMchid()).fee_type(params.getFeeType())
  55.  
    // 注意 微信单位是分 我的数据库存的是元 需要转换
  56.  
    .total_fee(String.valueOf(params.getTotalFee().intValue())).spbill_create_ip(ip)
  57.  
    .notify_url(params.getNotifyUrl()).trade_type(TradeType.JSAPI.getTradeType()).openid(params.getOpenid()).build()
  58.  
    .createSign(params.getMchKey(), SignType.MD5);
  59.  
    String xmlResult = WxPayApi.pushOrder(false, WxDomain.CHINA, wxparams);
  60.  
    Map<String, String> result = WxPayKit.xmlToMap(xmlResult);
  61.  
    String returnCode = result.get("return_code");
  62.  
    String returnMsg = result.get("return_msg");
  63.  
    if (!WxPayKit.codeIsOk(returnCode)) {
  64.  
    throw new SecurityException(returnMsg);
  65.  
    }
  66.  
    String resultCode = result.get("result_code");
  67.  
    if (!WxPayKit.codeIsOk(resultCode)) {
  68.  
    throw new SecurityException(returnMsg);
  69.  
    }
  70.  
    //实例化
  71.  
    installRecord(params);
  72.  
    // 以下字段在 return_code 和 result_code 都为 SUCCESS 的时候有返回
  73.  
    String prepayId = result.get("prepay_id");
  74.  
    Map<String, String> packageParams = WxPayKit.miniAppPrepayIdCreateSign(params.getAppid(), prepayId,
  75.  
    params.getMchKey(), SignType.MD5);
  76.  
    log.info("小程序支付统一下单返回参数:" packageParams.toString());
  77.  
    return packageParams;
  78.  
     
  79.  
    }
  80.  
     
  81.  
    /*
  82.  
    * @description:微信支付记录流水
  83.  
    * @author: zhanghui
  84.  
    * @date: 2022/9/16 0016 下午 4:32
  85.  
    **/
  86.  
    private void installRecord(WxOrderParams params){
  87.  
    System.out.println("入库");
  88.  
    WechatPaymentRecord record1 = recordService.selectByOutTradeNo(params.getOutTradeNo());
  89.  
    if(null==record1){
  90.  
    WechatPaymentRecord record = new WechatPaymentRecord();
  91.  
    record.setId(WxPayKit.generateStr());
  92.  
    record.setAttach(params.getAttach());
  93.  
    record.setBody(params.getBody());
  94.  
    record.setDetail(params.getDetail());
  95.  
    record.setFeeType(params.getFeeType());
  96.  
    record.setNickname(params.getNickname());
  97.  
    record.setOpenid(params.getOpenid());
  98.  
    record.setOrderType(params.getOrderType());
  99.  
    record.setOutTradeNo(params.getOutTradeNo());
  100.  
    record.setSpbillCreateIp(IpUtils.getHostIp());
  101.  
    record.setStatus(WxPlayStatus.PLACED.getCode());
  102.  
    record.setTradeType(TradeType.JSAPI.getTradeType());
  103.  
    record.setCreateBy(params.getOpenid());
  104.  
    record.setTotalFee(params.getTotalFee());
  105.  
    record.setOderBathNum(params.getOderBathNum());
  106.  
    record.setCreateTime(new Date());
  107.  
    recordService.insertWechatPaymentRecord(record);
  108.  
    }
  109.  
    }
  110.  
     
  111.  
    // public WxPayApiConfig getApiConfig() {
  112.  
    // WxPayApiConfig apiConfig;
  113.  
    //
  114.  
    // try {
  115.  
    // apiConfig = WxPayApiConfigKit.getApiConfig();
  116.  
    // } catch (Exception e) {
  117.  
    // apiConfig = WxPayApiConfig.builder().appId(systemParamsConfig.getSpappid()).mchId(systemParamsConfig.getMchid())
  118.  
    // .partnerKey(systemParamsConfig.getPartnerKey()).certPath(systemParamsConfig.getCertPath())
  119.  
    // .domain(systemParamsConfig.getDomain()).build();
  120.  
    // }
  121.  
    // notifyUrl = apiConfig.getDomain().concat("/wxPay/payNotify");
  122.  
    // refundNotifyUrl = apiConfig.getDomain().concat("/wxPay/refundNotify");
  123.  
    // return apiConfig;
  124.  
    // }
  125.  
     
  126.  
    /*
  127.  
    * @description:微信支付通知
  128.  
    * @author: zhanghui
  129.  
    * @date: 2022/9/15 0015 下午 4:00
  130.  
    *
  131.  
    * @param params 微信通知xml转map的参数
  132.  
    **/
  133.  
    @Override
  134.  
    public WechatPaymentRecord payNotify(Map<String, String> params,String mchKey) {
  135.  
    // 支付回调的code
  136.  
    String returnCode = params.get("return_code");
  137.  
    WechatPaymentRecord record= null;
  138.  
    if (WxPayKit.verifyNotify(params, mchKey, SignType.MD5)) {
  139.  
    if (WxPayKit.codeIsOk(returnCode)) {
  140.  
    String resultCode = params.get("result_code");
  141.  
    if (WxPayKit.codeIsOk(resultCode)) {
  142.  
    String outTradeNo = params.get("out_trade_no");
  143.  
    String transactionId = params.get("transaction_id");
  144.  
     
  145.  
    String bankType = params.get("bank_type");
  146.  
    // 支付时间
  147.  
    String payTime = params.get("time_end");
  148.  
    String isSubscribe = params.get("is_subscribe");
  149.  
    record = recordService.selectByOutTradeNo(outTradeNo);
  150.  
    if(record!=null && record.getStatus()==WxPlayStatus.PLACED.getCode()){//订单不为空并且订单状态为已下单
  151.  
    record.setTransactionId(transactionId);
  152.  
    record.setBankType(bankType);
  153.  
    record.setTimeEnd(DateUtils.dateTime("yyyyMMddHHmmss",payTime));
  154.  
    record.setIsSubscribe(isSubscribe);
  155.  
    record.setStatus(WxPlayStatus.PAID.getCode());
  156.  
    record.setUpdateBy(record.getCreateBy());
  157.  
    recordService.updateWechatPaymentRecord(record);
  158.  
    }
  159.  
    }
  160.  
     
  161.  
    }
  162.  
    }
  163.  
    return record;
  164.  
    }
  165.  
     
  166.  
    /*
  167.  
    * @description:退款
  168.  
    * @author: zhanghui
  169.  
    * @date: 2022/9/15 0015 下午 4:01
  170.  
    **/
  171.  
    @Override
  172.  
    public String refund(RefundParams refundParams) {
  173.  
    return null;
  174.  
    }
  175.  
     
  176.  
    /*
  177.  
    * @description:退款通知
  178.  
    * @author: zhanghui
  179.  
    * @date: 2022/9/15 0015 下午 4:01
  180.  
    **/
  181.  
    @Override
  182.  
    public void refundNotify(Map<String, String> params) {
  183.  
     
  184.  
    }
  185.  
    }
学新通

数据库表:

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

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

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgbjfba
系列文章
更多 icon
同类精品
更多 icon
继续加载