Integração de Pagamentos JSAPI em Contas Oficiais do WeChat

O pagamento via Contas Oficiais (JSAPI) é uma das formas mais comuns de transação no ecossistema WeChat. Ele permite que usuários realizem compras diretamente através de links em menus ou mensagens dentro do aplicativo. Neste guia, abordaremos a implementação técnica dessa funcionalidade utilizando .NET MVC e JavaScript.

1. Configurações Preliminares

Antes de iniciar a codificação, é necessário garantir que o ambiente no Portal do Merchant do WeChat Pay e na Plataforma de Desenvolvedor esteja configurado:

  • Diretório de Pagamento: Defina a URL exata onde o pagamento será processado.
  • Domínio de Autenticação OAuth2: Configure o domínio para obtenção do OpenID do usuário.
  • Whitelist de IPs: Registre o IP do servidor que fará as chamadas de API.

2. Fluxo de Autenticação e Obtenção de OpenID

Para processar um pagamento JSAPI, o sistema precisa do openid do usuário. Isso é feito através do fluxo de redirecionamento OAuth2 do WeChat.


// Controller: Gerenciamento de Autenticação
public class CheckoutController : Controller
{
   public ActionResult Index()
   {
       if (Session["UserOpenId"] == null)
       {
           PrepareAuthentication();
       }
       return View();
   }

   private void PrepareAuthentication()
   {
       string currentUrl = Request.Url.AbsoluteUri;
       if (Session["AuthCode"] == null)
       {
           // Construção da URL de autorização do WeChat
           var authUrl = string.Format(
               "https://open.weixin.qq.com/connect/oauth2/authorize?appid={0}&redirect_uri={1}&response_type=code&scope=snsapi_base#wechat_redirect",
               WechatConfig.AppId,
               HttpUtility.UrlEncode(currentUrl)
           );
           Session["RedirectUrl"] = authUrl;
       }
   }

   [HttpPost]
   public JsonResult RequestAuthUrl()
   {
       return Json(new { url = Session["RedirectUrl"]?.ToString() });
   }
}
   

3. Implementação do Frontend (JavaScript)

O frontend é responsável por capturar o código de autorização na URL, obter os parâmetros de pagamento do servidor e invocar a ponte de comunicação do WeChat (WeixinJSBridge).


$(function() {
   const urlParams = new URLSearchParams(window.location.search);
   const authCode = urlParams.get('code');

   if (authCode) {
       // Envia o código para o servidor para obter o OpenID
       $.post('/Checkout/InitializeSession', { code: authCode });
   } else {
       // Busca URL de redirecionamento se não houver código
       $.post('/Checkout/RequestAuthUrl', function(response) {
           if (response.url) window.location.href = response.url;
       });
   }
});

function initWechatPayment() {
   const amount = $('#paymentAmount').val();
   
   if (!amount || amount <= 0) {
       alert('Insira um valor válido');
       return;
   }

   $.ajax({
       url: '/Checkout/CreatePaymentOrder',
       type: 'POST',
       data: { total: amount },
       success: function(config) {
           invokeWechatPay(config);
       },
       error: function() {
           alert('Erro ao processar transação.');
       }
   });
}

function invokeWechatPay(config) {
   if (typeof WeixinJSBridge == "undefined") {
       document.addEventListener('WeixinJSBridgeReady', () => onBridgeReady(config), false);
   } else {
       onBridgeReady(config);
   }
}

function onBridgeReady(config) {
   WeixinJSBridge.invoke(
       'getBrandWCPayRequest', {
           "appId": config.appId,
           "timeStamp": config.timeStamp,
           "nonceStr": config.nonceStr,
           "package": config.packageValue,
           "signType": "MD5",
           "paySign": config.paySign
       },
       function(res) {
           if (res.err_msg == "get_brand_wcpay_request:ok") {
               window.location.href = "/Checkout/Success";
           }
       }
   );
}
   

4. Processamento da Ordem Unificada no Backend

O servidor deve realizar a chamada de "Unified Order" para o WeChat Pay e retornar os parâmetros assinados para o frontend.


[HttpPost]
public JsonResult CreatePaymentOrder(decimal total)
{
   try
   {
       // Converte valor para centavos (requisito do WeChat Pay)
       int amountInCents = (int)(total * 100);
       string openId = Session["UserOpenId"].ToString();

       // Parâmetros para a Unified Order
       JsapiPayHandler handler = new JsapiPayHandler();
       var unifiedResult = handler.GenerateUnifiedOrder(amountInCents, openId);
       
       // Gera os parâmetros para o JSAPI (appId, timeStamp, nonceStr, package, paySign)
       var jsParams = handler.GetJsApiParameters(unifiedResult);

       return Json(new {
           appId = jsParams.Get("appId"),
           timeStamp = jsParams.Get("timeStamp"),
           nonceStr = jsParams.Get("nonceStr"),
           packageValue = jsParams.Get("package"),
           paySign = jsParams.Get("paySign"),
           status = "success"
       });
   }
   catch (Exception ex)
   {
       return Json(new { status = "error", message = ex.Message });
   }
}
   

5. Requisitos de Segurança

Para evitar alertas de segurança do navegaodr dentro do WeChat ("Não insira senhas nesta página"), é imprescindível configurar o Domínio de Negócios Confiável nas configurações da Conta Oficial. Isso remove tarjas de aviso e melhora a taxa de conversão.

Além disso, certifique-se de validar as notificações de pagamento (Webhooks) no backend para confirmar se a transação foi realmente concluída com sucesso antes de liberar o produto ou serviço ao cliente.

Tags: WeChat Pay JSAPI .NET MVC C# desenvolvimento web

Publicado em 9-10 01:54