java+uniapp对接app微信支付

java+uniapp对接app微信支付

1.准备工作

注册app

APP接入微信支付,需要先将商户APP在微信开放平台进行注册,登记APP开发参数以生成APPID。具体操作步骤如下:

一、登录微信开放平台,进入【管理中心 → 移动应用 → 创建移动应用】;

java+uniapp对接app微信支付_第1张图片

二、完成基本信息的录入,商户需要在本步骤提交APP对应的下载地址,应用官网,应用水印,icon等业务信息;

java+uniapp对接app微信支付_第2张图片

三、完成平台信息的录入,商户需要在本步骤提交APP在Android及iOS端对应的开发参数,包括Android端应用的包名,应用签名,iOS端应用的bundle ID, universal link等;

java+uniapp对接app微信支付_第3张图片

注意:

  • Android应用包名和签名的相关说明,参考“Andriod开发要点说明”。

四、以上信息全部提交完成后,即完成APP的注册,商户可在【管理中心 → 移动应用】中,选择具体的应用查看其APPID及已获得的接口能力;

java+uniapp对接app微信支付_第4张图片

五、获取到APP的APPID后,需要将该APPID与商户的收款mch_id进行绑定,商户可登录商户平台后前往【产品中心 -> AppID账号管理】界面中进行AppID的绑定及管理,界面如图所示:

java+uniapp对接app微信支付_第5张图片

2.业务流程

java+uniapp对接app微信支付_第6张图片

重点步骤说明:

步骤3:用户下单发起支付,商户可通过微信支付APP下单API创建支付订单。

商户调用APP下单API后,分正常返回和异常返回情况:

  • 正常返回:返回prepay_id,商户可根据返回的prepay_id来生成调用OpenSDK的签名以执行下一步。
  • 异常返回:返回http code或错误码,商户可根据http code列表 或错误码说明来排查原因并执行下一步操作

步骤8: 商户通过APP调起支付OpenSDK调起微信支付,发起支付请求,有关OpenSDK调起支付的详细说明,请参考2.2.2部分的说明

步骤15-19: 用户支付成功后,商户可通过以下两种方式获取订单状态

我们通过以下接口将用户确认订单信息回调通知给商户系统:

*方法一:*支付结果通知。用户支付成功后,微信支付会将支付成功的结果以回调通知的形式同步给商户,商户的回调地址需要在调用APP下单API时传入notify_url参数。

*方法二:*当因网络抖动或本身notify_url存在问题等原因,导致无法接收到回调通知时,商户也可主动调用查询订单API 查询订单API来获取订单状态

3.工具类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PrePayVo {
    private String appid;
    private String partnerid;
    private String prepayid;
//    private String package;
    private String noncestr;
    private long timestamp;
    private String sign;

}

签名工具类

package com.jdzh.enterprise.admin.controller.pay;

/**
 * @author Heb
 * @version 1.0
 * @description: TODO
 * @date 2023/2/21 14:33
 */
import java.security.MessageDigest;
import java.util.*;

public class WechatPaySignUtil {

    /**
     * 对参数进行签名
     * @param params 待签名的参数
     * @param key API密钥
     * @return 签名结果
     */
    public static String sign(Map<String, String> params, String key) {
        // 按照参数名ASCII码从小到大排序
        List<String> keys = new ArrayList<String>(params.keySet());
        Collections.sort(keys);

        // 拼接参数名和参数值
        StringBuilder sb = new StringBuilder();
        for (String k : keys) {
            String v = params.get(k);
            if (v != null && !"".equals(v.trim())) {
                sb.append(k).append("=").append(v.trim()).append("&");
            }
        }
        sb.append("key=").append(key);

        // 对字符串进行MD5加密
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] bytes = md.digest(sb.toString().getBytes("UTF-8"));
            String sign = bytesToHexString(bytes).toUpperCase();
            return sign;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 将字节数组转换为十六进制字符串
     * @param bytes 字节数组
     * @return 十六进制字符串
     */
    private static String bytesToHexString(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            String hex = Integer.toHexString(b & 0xFF);
            if (hex.length() == 1) {
                sb.append("0");
            }
            sb.append(hex);
        }
        return sb.toString();
    }

    public static void main(String[] args) {
       Map<String, String> params = new HashMap<String, String>();
        params.put("appid", "");
        String key = "";//api2秘钥
        /**
         * 一次签名
         * ------------------------------
         */
//        params.put("nonce_str", "");
//        params.put("attach","");
//        params.put("body", "");
//        params.put("mch_id", "");
//        params.put("notify_url", "");
//        params.put("out_trade_no", "");
//        params.put("total_fee", "");
//        params.put("spbill_create_ip", "");
//        params.put("trade_type", "");

///**
// * 二次签名
// * ------------------------------
// */
        params.put("partnerid","");
        params.put("prepayid","");
        params.put("package","Sign=WXPay");
        params.put("noncestr", "FOBvoTUvG8sM5lMvYrYofUdhmYUSDGRw");
        params.put("timestamp","1677135129641");


        String sign = WechatPaySignUtil.sign(params, key);
        System.out.println("sign = " + sign);
        params.put("sign", sign);
    }

}
package com.jdzh.enterprise.admin.controller.pay;

import org.springframework.stereotype.Component;

/**
 * @author Heb
 * @version 1.0
 * @description: TODO
 * @date 2023/2/23 9:25
 */
@Component
public class WxPayConfig {
    /**
     * 统一下单地址
     */
    public static final String API_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder";
    /**
     * appid
     */
    public static String APP_ID = "";
    /**
     * 商户id
     */
    public static String MCH_ID = "";
    /**
     * 附加数据
     */
    public static String ATTCH="";
    /**
     * 发起请求的服务器ip
     */
    public static String SPBILL_CREATE_IP="";
    /**
     *     apiv2key
     */
    public static String MCH_KEY = "";
//    public static String APP_SECRET = "xxxxxx";
    /**
     * 通知回调地址
     */
    public static String NOTIFY_URL = "http://example.com/wechatpay/notify";
    public static String TRADE_TYPE = "APP";

    /**
     *    生成随机字符串
     * @return
     */
    public static String getNonceStr() {
        String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 32; i++) {
            sb.append(str.charAt((int) (Math.random() * str.length())));
        }
        return sb.toString();
    }

    /**
     *  生成商户订单号
     * @return
     */
    public static String getOutTradeNo() {
        return MCH_ID + System.currentTimeMillis();
    }
}

4.后端代码
package com.jdzh.enterprise.admin.controller.pay;

import com.jdzh.enterprise.framework.entity.*;
import com.jdzh.enterprise.framework.entity.vo.PrePayVo;
import com.jdzh.enterprise.framework.service.*;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.*;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Heb
 * @version 1.0
 * @description: TODO
 * @date 2023/2/23 9:03
 */
@RestController
@RequestMapping("/wxPay")
public class WxPayController {

    @Autowired
    IQbbcommodityService iQbbcommodityService;
    @Autowired
    IUserService iUserService;
    @Autowired
    IEnterpriseService iEnterpriseService;
    @Autowired
    IBusinessService iBusinessService;
    @Autowired
    IIndividualService iIndividualService;
    /**
     *
     *  total_fee 下单金额:单位(分)
     *  body  商品描述
     *  
     * @return
     */
    @PostMapping("/pay")
    public RespBean Pay(String total_fee, String body) throws IOException {
        //生成随机字符串
        String nonce_str= WxPayConfig.getNonceStr();
        //生成订单号
        String out_trade_no=WxPayConfig.getOutTradeNo();
        //获取当前系统时间戳
        Timestamp sysTime = new Timestamp(System.currentTimeMillis());
        long timestamp = sysTime.getTime();

        //调用微信统一下单接口
        String prePayMsg=this.prePay(total_fee,body,nonce_str,out_trade_no);

        //获得prePayId
        String prePayId= null;
        try {
            prePayId = prePayMsg.substring(prePayMsg.indexOf(")+20,prePayMsg.indexOf("]]>"));
        } catch (Exception exception) {
            return RespBean.error("生成预订单失败");
        }
        //对数据进行二次签名
        PrePayVo prePayVo = this.SecondsSign(prePayId, nonce_str, timestamp);
        return RespBean.ok("请求成功",prePayVo);
    }

    /**
     * 预下单获取prepayiD,第一次签名
     */
    public String  prePay(Integer total_fee,String body,String nonce_str,String out_trade_no) throws IOException {

        WxPayConfig wxPayConfig = new WxPayConfig();
        Map<String, String> params = new HashMap<String, String>();
        params.put("appid", wxPayConfig.APP_ID);
        params.put("nonce_str", nonce_str);
        params.put("attach",wxPayConfig.ATTCH);
        params.put("body", body);
        params.put("mch_id", wxPayConfig.MCH_ID);
        params.put("notify_url", wxPayConfig.NOTIFY_URL);
        params.put("out_trade_no", out_trade_no);
        params.put("total_fee", String.valueOf(total_fee));
        //发起请求的服务器ip
        params.put("spbill_create_ip", wxPayConfig.SPBILL_CREATE_IP);
        params.put("trade_type", wxPayConfig.TRADE_TYPE);
        //生成签名
        String key = wxPayConfig.MCH_KEY;//api2秘钥
        String sign = WechatPaySignUtil.sign(params, key);
       //存入签名
        params.put("sign", sign);
        // //封装请求参数
                String xml = "" +
                                "" + wxPayConfig.APP_ID + "" +
                                 "" + wxPayConfig.ATTCH + "" +
                                "" + body + "" +
                                "" + wxPayConfig.MCH_ID + "" +
                                "" + nonce_str + "" +
                                 "" + wxPayConfig.NOTIFY_URL + "" +
                                "" +out_trade_no + "" +
                                "" + wxPayConfig.SPBILL_CREATE_IP + "" +
                                 "" + total_fee + "" +
                                "" + wxPayConfig.TRADE_TYPE + "" +
                                "" + sign + "" +
                            "";
        //发送请求到微信统一下单接口,获取prepayId

        // 发送HTTP POST请求
        HttpClient httpClient = new DefaultHttpClient();
        HttpPost httpPost = new HttpPost(wxPayConfig.API_URL);
        httpPost.setHeader("Content-Type", "application/xml;charset=UTF-8");
        httpPost.setEntity(new StringEntity(xml.toString(), "UTF-8"));
        HttpResponse httpResponse = httpClient.execute(httpPost);
        HttpEntity httpEntity = httpResponse.getEntity();
        String result = "";
        if (httpEntity != null) {
            result = EntityUtils.toString(httpEntity, "UTF-8");
        }
        return result;
    }
    /**
     * 通过prePayId.进行二次签名
     */
    public PrePayVo SecondsSign(String prePayId,String nonce_str,long  timestamp){
        WxPayConfig wxPayConfig = new WxPayConfig();
        Map<String, String> params = new HashMap<String, String>();
        params.put("appid", wxPayConfig.APP_ID);
        params.put("partnerid",wxPayConfig.MCH_ID);
        params.put("prepayid",prePayId);
        params.put("package","Sign=WXPay");
        params.put("noncestr", nonce_str);
        params.put("timestamp", String.valueOf(timestamp));
        //生成签名
        String key = wxPayConfig.MCH_KEY;//api2秘钥
        String sign = WechatPaySignUtil.sign(params, key);
//        params.put("sign", sign);
        //封装参数
        PrePayVo prePayVo = new PrePayVo();
        prePayVo.setAppid(wxPayConfig.APP_ID);
        prePayVo.setPartnerid( wxPayConfig.MCH_ID);
        prePayVo.setPrepayid(prePayId);
        prePayVo.setNoncestr(nonce_str);
        prePayVo.setTimestamp(timestamp);
        prePayVo.setSign(sign);
        return prePayVo;
    }

}

5.前端代码
<template>
	<view class="content">
		
		<view class="text-area">
			<button @click="wxPay">微信支付</button>
		</view>
	</view>
</template>

<script>
	export default {
		
		data() {
			return {
				title: 'Hello',
			}
			
		},
		onLoad() {

		},
		methods: {
			wxPay(){
				uni.request({
						    url: 'http://192.168.1.9:8085/wxPay/pay?total_fee=1&body=测试', //仅为示例,并非真实接口地址。
							method:'post',
						    data: {
						  
						    },
							 success: (res) => {
							  //       console.log(res.data);
							  //       this.text = 'request success';
							  var msg=res.data.data;
							   console.log(res.data);
							    console.log("appid="+msg.appid);
							  uni.requestPayment({
							      "provider": "wxpay", 
							      "orderInfo": {
							       "appid": msg.appid,  // 应用ID(AppID)
									 "partnerid": msg.partnerid,      // 商户号(PartnerID)
									 "prepayid": msg.prepayid, // 预支付交易会话ID
									 "package": "Sign=WXPay",        // 固定值
									 "noncestr": msg.noncestr, // 随机字符串
									 "timestamp": msg.timestamp,        // 时间戳(单位:秒)
									 "sign": msg.sign // 签名,这里用的 MD5 签名
							      },
							     success: function (res) {
							         var rawdata = JSON.parse(res.rawdata);
									//在这里可以根据自己的需求将支付信息存到数据库中,我这里就不演示了
									
							         console.log("支付成功");
							     },
							     fail: function (e) {
									//支付失败也可以根据自己的需求将支付信息存到数据库中,我这里也就不演示了
							         console.log('支付失败:' + JSON.stringify(e));
							     }
							  })
							    }
						    
						});
		
			
			},
			
		}
	}
</script>

<style>
</style>

6.将项目打包

点击发行-app原生打包
java+uniapp对接app微信支付_第7张图片

包名要和微信开放平台的一致,,证书别名,秘钥,证书,就是我们在微信开放平台设置的,填进去就行

然后真机运行,就可以支付了

你可能感兴趣的:(微信,java,uni-app)