准备工作:
1:邮箱(自行注册)
2:联系方式
3:小程序管理者身份证电子版
4:营业执照电子版
5:对公银行账户信息(税号,开户名,开户行,账号)
6:认证费用300
7:小程序上线必须要域名(本地测试不需要,可在微信开发者工具中将不校验域名勾选)
实现效果:点击付款手机下方弹出一个支付密码,展示支付金额
(自行添加的一个支付按钮做测试使用,具体业务做调整,只有支付,没做退款回调等)
前端代码:
<template>
<view class="coll-list" v-for="item in collList">
<view class="title">
<text>商品名称:{{item.title}}</text>
<text>商品金额:{{item.count}}</text>
<text>商品描述:{{item.description}}</text>
<button size="mini" v-if="item.status=='0'" @click="onpay(item)">待付款</button>
<button size="mini" v-else-if="item.status=='1'">已付款</button>
</view>
</view>
</template>
<script>
export default {
data() {
return {
urlx: getApp().globalData.URLAl,
YYMMDD: YYMMDD,
collList: [{
id: '0',
title: "商品1",
date: '2023-11-11',
time: '17:55',
img: "../../static/api.png",
count: 1,
status: '0',
description: '这是一份'
},
{
id: '1',
title: "商品2",
date: '2023-11-11',
time: '17:55',
img: "../../static/api.png",
count: 1,
status: '1',
description: '这是一份111'
}
]
}
},
onLoad() {
},
methods: {
onpay(item) {
wx.login({
success(res) {
if (res.code) {
//发起网络请求
wx.request({
url: 'http://127.0.0.1:8085/weChatApp/appLogin',
method: 'post',
data: {
code: res.code
},
success(res2) {
let session_key = res2.data.data.session_key
let openid = res2.data.data.openid
// 发起支付
wx.request({
url: 'http://127.0.0.1:8085/appWeChatPay/paymentForGoods',
method: 'post',
data: {
openid: openid,
total: item.count, //金额必须是整数,以分为单位
description: item.description
},
success(res3) {
if (res3.data && res3.data.code == 200) {
wx.requestPayment({
"timeStamp": res3.data.timeStamp,
"nonceStr": res3.data.nonceStr,
"package": res3.data.package,
"signType": res3.data.signType,
"paySign": res3.data.paySign,
success(res4) {
console.log('用户支付扣款成功', res4)
},
fail(res4) {
console.log('用户支付扣款失败', res4)
}
})
}
}
})
}
})
} else {
console.log('登录失败!' + res.errMsg)
}
}
})
},
}
}
</script>
后端代码:
第一个接口:“/appLogin”
这个是获取当前用户的openid
@Override
public Result<Object> appLogin(WeChatVO weiXinVO) {
String code = weiXinVO.getCode();
Result<Object> res = new Result<>();
if (StringUtils.isNotEmpty(code)) {
HttpUtil instance = HttpUtil.getInstance();
String url = WeChatUrlConstants.CODE_SESSION_URL + "?appid=" + WxV3PayConfig.app_id +
"&secret=" + WxV3PayConfig.app_secret +
"&js_code=" + code +
"&grant_type=authorization_code";
String result = instance.sendHttpGet(url);
if (StringUtils.isNotEmpty(result)) {
HashMap map = JSON.parseObject(result, HashMap.class);
if (map.get("openid") != null) {
res.setMessage("查询成功");
res.setCode(200);
res.setData(map);
return res;
}else{
res.setMessage((String) map.get("errmsg"));
res.setCode((Integer) map.get("errcode"));
res.setData(null);
return res;
}
}
}else {
res.setMessage("入参code为空,请联系管理员!");
res.setCode(500);
res.setData(null);
}
return res;
}
第二个接口:“/paymentForGoods”
商户系统先调用该接口在微信支付服务后台生成预支付交易单
@Override
public Map<String, Object> weChatDoUnifiedOrder(WeChatPayVO weChatPayVO) throws IOException {
//请求URL
CloseableHttpClient httpClient = WXPaySignatureCertificateUtil.checkSign();
HttpPost httpPost = new HttpPost(WeChatUrlConstants.JS_API);
String outTradeNo = generateOrderId();
ObjectMapper objectMapper = new ObjectMapper();
ObjectNode rootNode = objectMapper.createObjectNode();
rootNode.put("mchid", WxV3PayConfig.mch_id)
.put("appid", WxV3PayConfig.app_id)
.put("description",weChatPayVO.getDescription())
.put("notify_url", WeChatUrlConstants.WECHAT_PAY_NOTIFY_URL)//回调
.put("out_trade_no", outTradeNo);
rootNode.putObject("amount")
.put("total",weChatPayVO.getTotal())
.put("currency","CNY");
rootNode.putObject("payer")
.put("openid",weChatPayVO.getOpenid());
// 请求body参数
StringEntity entity = new StringEntity(rootNode.toString(),"utf-8");
entity.setContentType("application/json");
httpPost.setEntity(entity);
httpPost.setHeader("Accept", "application/json");
//完成签名并执行请求
CloseableHttpResponse response = httpClient.execute(httpPost);
try {
HashMap<String, Object> map = new HashMap<>();
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == 200) {
JSONObject object = JSONObject.parseObject(EntityUtils.toString(response.getEntity()));
String prepayId = object.getString("prepay_id");
map.put("code",200);
map.put("message", "下单成功");
//获取预付单
map.put("prepay_id",prepayId);
System.out.println("success,return body = " + EntityUtils.toString(response.getEntity()));
//生成签名
Long timestamp = System.currentTimeMillis() / 1000;
map.put("timeStamp",String.valueOf(timestamp));
//随机字符串,长度为32个字符以下
String nonceStr = WXPayUtil.generateNonceStr();
map.put("nonceStr",nonceStr);
//统一下单接口返回的 prepay_id 参数值,提交格式如:prepay_id=***
map.put("package","prepay_id="+prepayId);
//签名算法,应与后台下单时的值一致
map.put("signType","RSA");
//生成带签名支付信息
String paySign = WXPaySignatureCertificateUtil.jsApiPaySign(String.valueOf(timestamp), nonceStr, prepayId);
map.put("paySign",paySign);
return map;
} else if (statusCode == 204) {
System.out.println("success");
} 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);
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
response.close();
}
return null;
}
WeChatUrlConstants:
package com.insigma.hzrb.common.constant;
/**
* 常量
*/
public class WeChatUrlConstants {
public static String CODE_SESSION_URL = "https://api.weixin.qq.com/sns/jscode2session";
public static String JS_API = "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi";
public static final String DOMAIN_API = "https://api.mch.weixin.qq.com/v3";
//微信支付回调
public static final String WECHAT_PAY_NOTIFY_URL = "";
//申请退款
public static final String REFUND_DOMESTIC_REFUNDS = "/refund/domestic/refunds";
//微信退款回调
public static final String WECHAT_REFUNDS_NOTIFY_URL = "https://xxx.xxxx.com/api/appPayment/weChatPayRefundsNotify";
//关闭订单
public static final String PAY_TRANSACTIONS_OUT_TRADE_NO = "/pay/transactions/out-trade-no/{}/close";
}
WxV3PayConfig:这些参数哪里找可以自行百度,相当好找
import lombok.Data;
@Data
public class WxV3PayConfig {
//支付通知地址
private String payNotifyUrl;
//平台证书序列号
public static final String mchserialno = "";
//appID
public static final String app_id = "";
// 小程序密钥
public static final String app_secret = "";
//商户id
public static final String mch_id = "";
// API V3密钥
public static final String apiV3Key = "";
// 商户API V3私钥
public static final String privateKey = "";
}
有问题可以联系,业务代码自己添加