注册app
APP接入微信支付,需要先将商户APP在微信开放平台进行注册,登记APP开发参数以生成APPID。具体操作步骤如下:
一、登录微信开放平台,进入【管理中心 → 移动应用 → 创建移动应用】;
二、完成基本信息的录入,商户需要在本步骤提交APP对应的下载地址,应用官网,应用水印,icon等业务信息;
三、完成平台信息的录入,商户需要在本步骤提交APP在Android及iOS端对应的开发参数,包括Android端应用的包名,应用签名,iOS端应用的bundle ID, universal link等;
注意:
四、以上信息全部提交完成后,即完成APP的注册,商户可在【管理中心 → 移动应用】中,选择具体的应用查看其APPID及已获得的接口能力;
五、获取到APP的APPID后,需要将该APPID与商户的收款mch_id进行绑定,商户可登录商户平台后前往【产品中心 -> AppID账号管理】界面中进行AppID的绑定及管理,界面如图所示:
重点步骤说明:
步骤3:用户下单发起支付,商户可通过微信支付APP下单API创建支付订单。
商户调用APP下单API后,分正常返回和异常返回情况:
步骤8: 商户通过APP调起支付OpenSDK调起微信支付,发起支付请求,有关OpenSDK调起支付的详细说明,请参考2.2.2部分的说明
步骤15-19: 用户支付成功后,商户可通过以下两种方式获取订单状态
我们通过以下接口将用户确认订单信息回调通知给商户系统:
*方法一:*支付结果通知。用户支付成功后,微信支付会将支付成功的结果以回调通知的形式同步给商户,商户的回调地址需要在调用APP下单API时传入notify_url参数。
*方法二:*当因网络抖动或本身notify_url存在问题等原因,导致无法接收到回调通知时,商户也可主动调用查询订单API 查询订单API来获取订单状态
@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();
}
}
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;
}
}
<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>
包名要和微信开放平台的一致,,证书别名,秘钥,证书,就是我们在微信开放平台设置的,填进去就行
然后真机运行,就可以支付了